summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2006-02-20 08:01:00 -0800
committerAlan Mishchenko <alanmi@berkeley.edu>2006-02-20 08:01:00 -0800
commit8eef7f8326e715ea4e9e84f46487cf4657601c25 (patch)
tree03a394e5a245bd3c0ed0b6397275c5b029adfb41 /src
parent77d7377442c28fd5c65144d7ea23938600967b2b (diff)
downloadabc-8eef7f8326e715ea4e9e84f46487cf4657601c25.tar.gz
abc-8eef7f8326e715ea4e9e84f46487cf4657601c25.tar.bz2
abc-8eef7f8326e715ea4e9e84f46487cf4657601c25.zip
Version abc60220
Diffstat (limited to 'src')
-rw-r--r--src/base/abc/abc.h21
-rw-r--r--src/base/abc/abcAig.c223
-rw-r--r--src/base/abc/abcNames.c4
-rw-r--r--src/base/abc/abcNtk.c114
-rw-r--r--src/base/abc/abcRefs.c314
-rw-r--r--src/base/abc/abcUtil.c31
-rw-r--r--src/base/abci/abc.c1045
-rw-r--r--src/base/abci/abcBalance.c117
-rw-r--r--src/base/abci/abcClpBdd.c (renamed from src/base/abci/abcCollapse.c)0
-rw-r--r--src/base/abci/abcClpSop.c53
-rw-r--r--src/base/abci/abcCut.c55
-rw-r--r--src/base/abci/abcDsd.c2
-rw-r--r--src/base/abci/abcEspresso.c244
-rw-r--r--src/base/abci/abcFraig.c2
-rw-r--r--src/base/abci/abcMap.c2
-rw-r--r--src/base/abci/abcMiter.c18
-rw-r--r--src/base/abci/abcNewAig.c13
-rw-r--r--src/base/abci/abcNtbdd.c2
-rw-r--r--src/base/abci/abcProve.c232
-rw-r--r--src/base/abci/abcRenode.c2
-rw-r--r--src/base/abci/abcRestruct.c1026
-rw-r--r--src/base/abci/abcRewrite.c8
-rw-r--r--src/base/abci/abcSat.c294
-rw-r--r--src/base/abci/abcUnreach.c2
-rw-r--r--src/base/abci/abcVanEijk.c8
-rw-r--r--src/base/abci/abcVanImp.c2
-rw-r--r--src/base/abci/abcVerify.c8
-rw-r--r--src/base/abci/module.make5
-rw-r--r--src/base/cmd/cmd.c104
-rw-r--r--src/base/cmd/cmdAlias.c4
-rw-r--r--src/base/cmd/cmdApi.c4
-rw-r--r--src/base/cmd/cmdFlag.c7
-rw-r--r--src/base/cmd/cmdHist.c2
-rw-r--r--src/base/cmd/cmdUtils.c26
-rw-r--r--src/base/io/io.c161
-rw-r--r--src/base/io/ioReadBaf.c4
-rw-r--r--src/base/io/ioReadBlif.c12
-rw-r--r--src/base/io/ioReadEdif.c2
-rw-r--r--src/base/io/ioReadEqn.c2
-rw-r--r--src/base/io/ioReadVerilog.c6
-rw-r--r--src/base/io/ioUtil.c2
-rw-r--r--src/base/io/ioWriteCnf.c8
-rw-r--r--src/base/main/main.c57
-rw-r--r--src/base/main/main.h9
-rw-r--r--src/base/main/mainFrame.c19
-rw-r--r--src/base/main/mainUtils.c4
-rw-r--r--src/base/seq/seqAigCore.c4
-rw-r--r--src/base/seq/seqCreate.c4
-rw-r--r--src/base/seq/seqRetCore.c4
-rw-r--r--src/bdd/cudd/cuddAPI.c2
-rw-r--r--src/bdd/cudd/cuddAddAbs.c2
-rw-r--r--src/bdd/cudd/cuddAddApply.c2
-rw-r--r--src/bdd/cudd/cuddAddFind.c2
-rw-r--r--src/bdd/cudd/cuddAddInv.c2
-rw-r--r--src/bdd/cudd/cuddAddIte.c2
-rw-r--r--src/bdd/cudd/cuddAddNeg.c2
-rw-r--r--src/bdd/cudd/cuddAddWalsh.c2
-rw-r--r--src/bdd/cudd/cuddAndAbs.c2
-rw-r--r--src/bdd/cudd/cuddAnneal.c2
-rw-r--r--src/bdd/cudd/cuddApa.c2
-rw-r--r--src/bdd/cudd/cuddApprox.c2
-rw-r--r--src/bdd/cudd/cuddBddAbs.c2
-rw-r--r--src/bdd/cudd/cuddBddCorr.c2
-rw-r--r--src/bdd/cudd/cuddBddIte.c2
-rw-r--r--src/bdd/cudd/cuddBridge.c2
-rw-r--r--src/bdd/cudd/cuddCache.c2
-rw-r--r--src/bdd/cudd/cuddCheck.c2
-rw-r--r--src/bdd/cudd/cuddClip.c2
-rw-r--r--src/bdd/cudd/cuddCof.c2
-rw-r--r--src/bdd/cudd/cuddCompose.c2
-rw-r--r--src/bdd/cudd/cuddDecomp.c2
-rw-r--r--src/bdd/cudd/cuddEssent.c2
-rw-r--r--src/bdd/cudd/cuddExact.c2
-rw-r--r--src/bdd/cudd/cuddExport.c2
-rw-r--r--src/bdd/cudd/cuddGenCof.c2
-rw-r--r--src/bdd/cudd/cuddGenetic.c2
-rw-r--r--src/bdd/cudd/cuddGroup.c2
-rw-r--r--src/bdd/cudd/cuddHarwell.c2
-rw-r--r--src/bdd/cudd/cuddInit.c2
-rw-r--r--src/bdd/cudd/cuddInteract.c2
-rw-r--r--src/bdd/cudd/cuddLCache.c2
-rw-r--r--src/bdd/cudd/cuddLevelQ.c2
-rw-r--r--src/bdd/cudd/cuddLinear.c2
-rw-r--r--src/bdd/cudd/cuddLiteral.c2
-rw-r--r--src/bdd/cudd/cuddMatMult.c2
-rw-r--r--src/bdd/cudd/cuddPriority.c2
-rw-r--r--src/bdd/cudd/cuddRead.c2
-rw-r--r--src/bdd/cudd/cuddRef.c2
-rw-r--r--src/bdd/cudd/cuddReorder.c2
-rw-r--r--src/bdd/cudd/cuddSat.c2
-rw-r--r--src/bdd/cudd/cuddSign.c2
-rw-r--r--src/bdd/cudd/cuddSolve.c2
-rw-r--r--src/bdd/cudd/cuddSplit.c2
-rw-r--r--src/bdd/cudd/cuddSubsetHB.c2
-rw-r--r--src/bdd/cudd/cuddSubsetSP.c2
-rw-r--r--src/bdd/cudd/cuddSymmetry.c2
-rw-r--r--src/bdd/cudd/cuddTable.c2
-rw-r--r--src/bdd/cudd/cuddUtil.c2
-rw-r--r--src/bdd/cudd/cuddWindow.c2
-rw-r--r--src/bdd/cudd/cuddZddCount.c2
-rw-r--r--src/bdd/cudd/cuddZddFuncs.c2
-rw-r--r--src/bdd/cudd/cuddZddGroup.c2
-rw-r--r--src/bdd/cudd/cuddZddIsop.c2
-rw-r--r--src/bdd/cudd/cuddZddLin.c2
-rw-r--r--src/bdd/cudd/cuddZddMisc.c2
-rw-r--r--src/bdd/cudd/cuddZddPort.c2
-rw-r--r--src/bdd/cudd/cuddZddReord.c2
-rw-r--r--src/bdd/cudd/cuddZddSetop.c2
-rw-r--r--src/bdd/cudd/cuddZddSymm.c2
-rw-r--r--src/bdd/cudd/cuddZddUtil.c2
-rw-r--r--src/bdd/cudd/testcudd.c2
-rw-r--r--src/bdd/dsd/dsd.h2
-rw-r--r--src/bdd/dsd/dsdTree.c295
-rw-r--r--src/bdd/epd/epd.c2
-rw-r--r--src/bdd/mtr/mtrBasic.c2
-rw-r--r--src/bdd/mtr/mtrGroup.c2
-rw-r--r--src/map/fpga/fpga.c14
-rw-r--r--src/map/fpga/fpgaLib.c4
-rw-r--r--src/map/mapper/mapper.c12
-rw-r--r--src/map/mio/mio.c14
-rw-r--r--src/map/mio/mioFunc.c2
-rw-r--r--src/map/mio/mioRead.c10
-rw-r--r--src/map/mio/mioUtils.c2
-rw-r--r--src/map/pga/pgaMatch.c2
-rw-r--r--src/map/super/super.c44
-rw-r--r--src/misc/espresso/cofactor.c382
-rw-r--r--src/misc/espresso/cols.c314
-rw-r--r--src/misc/espresso/compl.c680
-rw-r--r--src/misc/espresso/contain.c441
-rw-r--r--src/misc/espresso/cubehack.c138
-rw-r--r--src/misc/espresso/cubestr.c152
-rw-r--r--src/misc/espresso/cvrin.c810
-rw-r--r--src/misc/espresso/cvrm.c539
-rw-r--r--src/misc/espresso/cvrmisc.c142
-rw-r--r--src/misc/espresso/cvrout.c609
-rw-r--r--src/misc/espresso/dominate.c98
-rw-r--r--src/misc/espresso/equiv.c94
-rw-r--r--src/misc/espresso/espresso.c139
-rw-r--r--src/misc/espresso/espresso.h782
-rw-r--r--src/misc/espresso/essen.c179
-rw-r--r--src/misc/espresso/exact.c181
-rw-r--r--src/misc/espresso/expand.c693
-rw-r--r--src/misc/espresso/gasp.c228
-rw-r--r--src/misc/espresso/gimpel.c106
-rw-r--r--src/misc/espresso/globals.c76
-rw-r--r--src/misc/espresso/hack.c641
-rw-r--r--src/misc/espresso/indep.c134
-rw-r--r--src/misc/espresso/irred.c440
-rw-r--r--src/misc/espresso/main.c746
-rw-r--r--src/misc/espresso/main.h122
-rw-r--r--src/misc/espresso/map.c115
-rw-r--r--src/misc/espresso/matrix.c574
-rw-r--r--src/misc/espresso/mincov.c378
-rw-r--r--src/misc/espresso/mincov.h11
-rw-r--r--src/misc/espresso/mincov_int.h55
-rw-r--r--src/misc/espresso/module.make39
-rw-r--r--src/misc/espresso/opo.c624
-rw-r--r--src/misc/espresso/pair.c675
-rw-r--r--src/misc/espresso/part.c122
-rw-r--r--src/misc/espresso/primes.c170
-rw-r--r--src/misc/espresso/reduce.c258
-rw-r--r--src/misc/espresso/rows.c314
-rw-r--r--src/misc/espresso/set.c820
-rw-r--r--src/misc/espresso/setc.c483
-rw-r--r--src/misc/espresso/sharp.c247
-rw-r--r--src/misc/espresso/sminterf.c44
-rw-r--r--src/misc/espresso/solution.c114
-rw-r--r--src/misc/espresso/sparse.c146
-rw-r--r--src/misc/espresso/sparse.h135
-rw-r--r--src/misc/espresso/sparse_int.h121
-rw-r--r--src/misc/espresso/unate.c441
-rw-r--r--src/misc/espresso/util_old.h301
-rw-r--r--src/misc/espresso/verify.c193
-rw-r--r--src/misc/extra/extra.h26
-rw-r--r--src/misc/extra/extraBddMisc.c23
-rw-r--r--src/misc/extra/extraUtil.h60
-rw-r--r--src/misc/extra/extraUtilFile.c4
-rw-r--r--src/misc/extra/extraUtilUtil.c330
-rw-r--r--src/misc/extra/module.make4
-rw-r--r--src/misc/mvc/mvc.h3
-rw-r--r--src/misc/st/st.c98
-rw-r--r--src/misc/st/st.h44
-rw-r--r--src/misc/st/stmm.c98
-rw-r--r--src/misc/st/stmm.h2
-rw-r--r--src/misc/util/cpu_stats.c122
-rw-r--r--src/misc/util/cpu_time.c128
-rw-r--r--src/misc/util/datalimit.c95
-rw-r--r--src/misc/util/getopt.c84
-rw-r--r--src/misc/util/leaks.h8
-rw-r--r--src/misc/util/module.make9
-rw-r--r--src/misc/util/pathsearch.c131
-rw-r--r--src/misc/util/safe_mem.c104
-rw-r--r--src/misc/util/strsav.c157
-rw-r--r--src/misc/util/texpand.c66
-rw-r--r--src/misc/util/util.h331
-rw-r--r--src/misc/util/util_hack.h87
-rw-r--r--src/misc/vec/vecInt.h3
-rw-r--r--src/opt/cut/cut.h5
-rw-r--r--src/opt/cut/cutInt.h2
-rw-r--r--src/opt/cut/cutMan.c9
-rw-r--r--src/opt/cut/cutNode.c23
-rw-r--r--src/opt/dec/dec.h82
-rw-r--r--src/opt/dec/decAbc.c5
-rw-r--r--src/opt/fxu/fxuInt.h1
-rw-r--r--src/opt/rwr/rwrDec.c2
-rw-r--r--src/opt/rwr/rwrEva.c5
-rw-r--r--src/sat/aig/aig.h3
-rw-r--r--src/sat/aig/aigNode.c23
-rw-r--r--src/sat/aig/fraigCore.c2
-rw-r--r--src/sat/aig/rwrMffc.c303
-rw-r--r--src/sat/aig/rwrTruth.c2
-rw-r--r--src/sat/aig/rwr_.c48
-rw-r--r--src/sat/asat/asatmem.c527
-rw-r--r--src/sat/asat/asatmem.h76
-rw-r--r--src/sat/asat/module.make1
-rw-r--r--src/sat/asat/solver.c65
-rw-r--r--src/sat/asat/solver.h9
-rw-r--r--src/sat/csat/csat_apis.c356
-rw-r--r--src/sat/csat/csat_apis.h99
-rw-r--r--src/sat/fraig/fraig.h2
-rw-r--r--src/sat/fraig/fraigCanon.c2
221 files changed, 20678 insertions, 3060 deletions
diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h
index 7ace4880..e36f133e 100644
--- a/src/base/abc/abc.h
+++ b/src/base/abc/abc.h
@@ -410,6 +410,8 @@ extern bool Abc_AigCheck( Abc_Aig_t * pMan );
extern int Abc_AigGetLevelNum( Abc_Ntk_t * pNtk );
extern Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
extern Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
+extern Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType );
+extern Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType );
extern Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
extern Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
extern Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs );
@@ -425,7 +427,7 @@ extern void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk );
/*=== abcAttach.c ==========================================================*/
extern int Abc_NtkAttach( Abc_Ntk_t * pNtk );
/*=== abcBalance.c ==========================================================*/
-extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective );
+extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel );
/*=== abcCheck.c ==========================================================*/
extern bool Abc_NtkCheck( Abc_Ntk_t * pNtk );
extern bool Abc_NtkCheckRead( Abc_Ntk_t * pNtk );
@@ -435,7 +437,7 @@ extern bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t *
/*=== abcCollapse.c ==========================================================*/
extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fVerbose );
/*=== abcCut.c ==========================================================*/
-extern void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj );
+extern void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fMulti );
extern void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fMulti );
extern void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fFirst );
extern void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj );
@@ -559,8 +561,9 @@ extern void Abc_NtkFinalizeLatches( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkStartRead( char * pName );
extern void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk );
-extern Abc_Ntk_t * Abc_NtkCreateOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAllCis );
-extern Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues );
+extern Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis );
+extern Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName );
+extern Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues );
extern Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode );
extern Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop );
extern void Abc_NtkDelete( Abc_Ntk_t * pNtk );
@@ -575,6 +578,8 @@ extern void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, in
extern void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames );
extern void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes );
extern void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode );
+/*=== abcProve.c ==========================================================*/
+extern int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, int nConfLimit, int nImpLimit, int fUseRewrite, int fUseFraig, int fVerbose );
/*=== abcReconv.c ==========================================================*/
extern Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop );
extern void Abc_NtkManCutStop( Abc_ManCut_t * p );
@@ -590,13 +595,14 @@ extern int Abc_NodeMffcSize( Abc_Obj_t * pNode );
extern int Abc_NodeMffcSizeSupp( Abc_Obj_t * pNode );
extern int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode );
extern int Abc_NodeMffcLabel( Abc_Obj_t * pNode );
-extern int Abc_NodeMffcLabelFast( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
-extern Vec_Ptr_t * Abc_NodeMffcCollect( Abc_Obj_t * pNode );
+extern void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp );
+extern int Abc_NodeDeref_rec( Abc_Obj_t * pNode );
+extern int Abc_NodeRef_rec( Abc_Obj_t * pNode );
/*=== abcRenode.c ==========================================================*/
extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple );
extern DdNode * Abc_NtkRenodeDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld );
/*=== abcSat.c ==========================================================*/
-extern int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nSeconds, int fVerbose );
+extern int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nConfLimit, int nImpLimit, int fVerbose );
extern solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk );
/*=== abcSop.c ==========================================================*/
extern char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName );
@@ -681,6 +687,7 @@ extern int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDup
extern void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode );
extern bool Abc_NodeIsExorType( Abc_Obj_t * pNode );
extern bool Abc_NodeIsMuxType( Abc_Obj_t * pNode );
+extern bool Abc_NodeIsMuxControlType( Abc_Obj_t * pNode );
extern Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE );
extern int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2 );
extern void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
diff --git a/src/base/abc/abcAig.c b/src/base/abc/abcAig.c
index 167e7552..e5f39127 100644
--- a/src/base/abc/abcAig.c
+++ b/src/base/abc/abcAig.c
@@ -54,7 +54,6 @@ struct Abc_Aig_t_
int nBins; // the size of the table
int nEntries; // the total number of entries in the table
Vec_Ptr_t * vNodes; // the temporary array of nodes
- Vec_Ptr_t * vStackDelete; // the nodes to be deleted
Vec_Ptr_t * vStackReplaceOld; // the nodes to be replaced
Vec_Ptr_t * vStackReplaceNew; // the nodes to be used for replacement
Vec_Vec_t * vLevels; // the nodes to be updated
@@ -83,8 +82,7 @@ static Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_O
static void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis );
static void Abc_AigResize( Abc_Aig_t * pMan );
// incremental AIG procedures
-static void Abc_AigReplace_int( Abc_Aig_t * pMan, int fUpdateLevel );
-static void Abc_AigDelete_int( Abc_Aig_t * pMan );
+static void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel );
static void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan );
static void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan );
static void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode );
@@ -116,7 +114,6 @@ Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig )
pMan->pBins = ALLOC( Abc_Obj_t *, pMan->nBins );
memset( pMan->pBins, 0, sizeof(Abc_Obj_t *) * pMan->nBins );
pMan->vNodes = Vec_PtrAlloc( 100 );
- pMan->vStackDelete = Vec_PtrAlloc( 100 );
pMan->vStackReplaceOld = Vec_PtrAlloc( 100 );
pMan->vStackReplaceNew = Vec_PtrAlloc( 100 );
pMan->vLevels = Vec_VecAlloc( 100 );
@@ -139,13 +136,11 @@ Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig )
***********************************************************************/
void Abc_AigFree( Abc_Aig_t * pMan )
{
- assert( Vec_PtrSize( pMan->vStackDelete ) == 0 );
assert( Vec_PtrSize( pMan->vStackReplaceOld ) == 0 );
assert( Vec_PtrSize( pMan->vStackReplaceNew ) == 0 );
// free the table
Vec_VecFree( pMan->vLevels );
Vec_VecFree( pMan->vLevelsR );
- Vec_PtrFree( pMan->vStackDelete );
Vec_PtrFree( pMan->vStackReplaceOld );
Vec_PtrFree( pMan->vStackReplaceNew );
Vec_PtrFree( pMan->vNodes );
@@ -166,18 +161,21 @@ void Abc_AigFree( Abc_Aig_t * pMan )
***********************************************************************/
int Abc_AigCleanup( Abc_Aig_t * pMan )
{
+ Vec_Ptr_t * vDangles;
Abc_Obj_t * pAnd;
- int i, Counter;
+ int i, nNodesOld;
+ nNodesOld = pMan->nEntries;
// collect the AND nodes that do not fanout
- assert( Vec_PtrSize( pMan->vStackDelete ) == 0 );
+ vDangles = Vec_PtrAlloc( 100 );
for ( i = 0; i < pMan->nBins; i++ )
Abc_AigBinForEachEntry( pMan->pBins[i], pAnd )
if ( Abc_ObjFanoutNum(pAnd) == 0 )
- Vec_PtrPush( pMan->vStackDelete, pAnd );
+ Vec_PtrPush( vDangles, pAnd );
// process the dangling nodes and their MFFCs
- for ( Counter = 0; Vec_PtrSize(pMan->vStackDelete) > 0; Counter++ )
- Abc_AigDelete_int( pMan );
- return Counter;
+ Vec_PtrForEachEntry( vDangles, pAnd, i )
+ Abc_AigDeleteNode( pMan, pAnd );
+ Vec_PtrFree( vDangles );
+ return nNodesOld - pMan->nEntries;
}
/**Function*************************************************************
@@ -383,6 +381,74 @@ Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
/**Function*************************************************************
+ Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.]
+
+ Description [The argument nodes can be complemented.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType )
+{
+ Abc_Obj_t * pNode1, * pNode2, * pNode;
+ // set the flag to zero
+ if ( pType ) *pType = 0;
+ // check the case of XOR(a,b) = OR(ab, a'b')'
+ if ( (pNode1 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), Abc_ObjNot(p1))) &&
+ (pNode2 = Abc_AigAndLookup(pMan, p0, p1)) )
+ {
+ pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ if ( pNode && pType ) *pType = 1;
+ return pNode;
+ }
+ // check the case of XOR(a,b) = OR(a'b, ab')
+ if ( (pNode1 = Abc_AigAndLookup(pMan, p0, Abc_ObjNot(p1))) &&
+ (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), p1)) )
+ {
+ pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ return pNode? Abc_ObjNot(pNode) : NULL;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.]
+
+ Description [The argument nodes can be complemented.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType )
+{
+ Abc_Obj_t * pNode1, * pNode2, * pNode;
+ // set the flag to zero
+ if ( pType ) *pType = 0;
+ // check the case of MUX(c,t,e) = OR(ct', c'e')'
+ if ( (pNode1 = Abc_AigAndLookup(pMan, pC, Abc_ObjNot(pT))) &&
+ (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), Abc_ObjNot(pE))) )
+ {
+ pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ if ( pNode && pType ) *pType = 1;
+ return pNode;
+ }
+ // check the case of MUX(c,t,e) = OR(ct, c'e)
+ if ( (pNode1 = Abc_AigAndLookup(pMan, pC, pT)) &&
+ (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), pE)) )
+ {
+ pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ return pNode? Abc_ObjNot(pNode) : NULL;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
Synopsis [Deletes an AIG node from the hash table.]
Description []
@@ -662,11 +728,16 @@ void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool
{
assert( Vec_PtrSize(pMan->vStackReplaceOld) == 0 );
assert( Vec_PtrSize(pMan->vStackReplaceNew) == 0 );
- assert( Vec_PtrSize(pMan->vStackDelete) == 0 );
Vec_PtrPush( pMan->vStackReplaceOld, pOld );
Vec_PtrPush( pMan->vStackReplaceNew, pNew );
+ assert( !Abc_ObjIsComplement(pOld) );
+ // process the replacements
while ( Vec_PtrSize(pMan->vStackReplaceOld) )
- Abc_AigReplace_int( pMan, fUpdateLevel );
+ {
+ pOld = Vec_PtrPop( pMan->vStackReplaceOld );
+ pNew = Vec_PtrPop( pMan->vStackReplaceNew );
+ Abc_AigReplace_int( pMan, pOld, pNew, fUpdateLevel );
+ }
if ( fUpdateLevel )
{
Abc_AigUpdateLevel_int( pMan );
@@ -685,14 +756,10 @@ void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool
SeeAlso []
***********************************************************************/
-void Abc_AigReplace_int( Abc_Aig_t * pMan, int fUpdateLevel )
+void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel )
{
- Abc_Obj_t * pOld, * pNew, * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout;
- int k, v, iFanin;
- // get the pair of nodes to replace
- assert( Vec_PtrSize(pMan->vStackReplaceOld) > 0 );
- pOld = Vec_PtrPop( pMan->vStackReplaceOld );
- pNew = Vec_PtrPop( pMan->vStackReplaceNew );
+ Abc_Obj_t * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout;
+ int k, v, iFanin;
// make sure the old node is regular and has fanouts
// (the new node can be complemented and can have fanouts)
assert( !Abc_ObjIsComplement(pOld) );
@@ -775,88 +842,58 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan, int fUpdateLevel )
SeeAlso []
***********************************************************************/
-void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld )
-{
- assert( Vec_PtrSize(pMan->vStackDelete) == 0 );
- Vec_PtrPush( pMan->vStackDelete, pOld );
- while ( Vec_PtrSize(pMan->vStackDelete) )
- Abc_AigDelete_int( pMan );
-}
-
-/**Function*************************************************************
-
- Synopsis [Performs internal deletion step.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Abc_AigDelete_int( Abc_Aig_t * pMan )
+void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
{
- Vec_Ptr_t * vNodes;
- Abc_Obj_t * pRoot, * pObj;
- int k;
- // get the node to delete
- assert( Vec_PtrSize(pMan->vStackDelete) > 0 );
- pRoot = Vec_PtrPop( pMan->vStackDelete );
+ Abc_Obj_t * pNode0, * pNode1, * pTemp;
+ int i, k;
// make sure the node is regular and dangling
- assert( !Abc_ObjIsComplement(pRoot) );
- assert( Abc_ObjIsNode(pRoot) );
- assert( Abc_ObjFaninNum(pRoot) == 2 );
- assert( Abc_ObjFanoutNum(pRoot) == 0 );
-
- // collect the MFFC
- vNodes = Abc_NodeMffcCollect( pRoot );
-
- // if reverse levels are specified, schedule fanins of MFFC for updating
- // currently, we do not do it because we do not know the correct level of the fanins
- // also, it is unlikely that this will make a difference since we are
- // processing the network forward while at this point fanins are left behind...
-/*
- if ( pObj->pNtk->vLevelsR )
- Vec_PtrForEachEntry( vNodes, pObj, k )
+ assert( !Abc_ObjIsComplement(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
+ assert( Abc_ObjFaninNum(pNode) == 2 );
+ assert( Abc_ObjFanoutNum(pNode) == 0 );
+
+ // when deleting an old node that is scheduled for replacement, remove it from the replacement queue
+ Vec_PtrForEachEntry( pMan->vStackReplaceOld, pTemp, i )
+ if ( pNode == pTemp )
{
- Abc_Obj_t * pFanin;
- if ( Abc_ObjIsCi(pObj) )
- continue;
- pFanin = Abc_ObjFanin0(pObj);
- if ( pFanin->fMarkB == 0 )
- {
- pFanin->fMarkB = 1;
- Vec_VecPush( pMan->vLevelsR, Abc_NodeReadReverseLevel(pFanin), pFanin );
- }
- pFanin = Abc_ObjFanin1(pObj);
- if ( pFanin->fMarkB == 0 )
+ // remove the entry from the replacement array
+ for ( k = i; k < pMan->vStackReplaceOld->nSize - 1; k++ )
{
- pFanin->fMarkB = 1;
- Vec_VecPush( pMan->vLevelsR, Abc_NodeReadReverseLevel(pFanin), pFanin );
+ pMan->vStackReplaceOld->pArray[k] = pMan->vStackReplaceOld->pArray[k+1];
+ pMan->vStackReplaceNew->pArray[k] = pMan->vStackReplaceNew->pArray[k+1];
}
+ pMan->vStackReplaceOld->nSize--;
+ pMan->vStackReplaceNew->nSize--;
}
-*/
- // delete the nodes in MFFC
- Vec_PtrForEachEntry( vNodes, pObj, k )
- {
- if ( Abc_ObjIsCi(pObj) )
- continue;
- assert( Abc_ObjFanoutNum(pObj) == 0 );
- // remove the node from the table
- Abc_AigAndDelete( pMan, pObj );
- // if the node is in the level structure, remove it
- if ( pObj->fMarkA )
- Abc_AigRemoveFromLevelStructure( pMan->vLevels, pObj );
- if ( pObj->fMarkB )
- Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pObj );
- // remove the node from the network
- Abc_NtkDeleteObj( pObj );
- }
- Vec_PtrFree( vNodes );
+ // when deleting a new node that should replace another node, do not delete
+ Vec_PtrForEachEntry( pMan->vStackReplaceNew, pTemp, i )
+ if ( pNode == Abc_ObjRegular(pTemp) )
+ return;
+
+ // remember the node's fanins
+ pNode0 = Abc_ObjFanin0( pNode );
+ pNode1 = Abc_ObjFanin1( pNode );
+
+ // remove the node from the table
+ Abc_AigAndDelete( pMan, pNode );
+ // if the node is in the level structure, remove it
+ if ( pNode->fMarkA )
+ Abc_AigRemoveFromLevelStructure( pMan->vLevels, pNode );
+ if ( pNode->fMarkB )
+ Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pNode );
+ // remove the node from the network
+ Abc_NtkDeleteObj( pNode );
+
+ // call recursively for the fanins
+ if ( Abc_ObjIsNode(pNode0) && pNode0->vFanouts.nSize == 0 )
+ Abc_AigDeleteNode( pMan, pNode0 );
+ if ( Abc_ObjIsNode(pNode1) && pNode1->vFanouts.nSize == 0 )
+ Abc_AigDeleteNode( pMan, pNode1 );
}
+
/**Function*************************************************************
Synopsis [Updates the level of the node after it has changed.]
diff --git a/src/base/abc/abcNames.c b/src/base/abc/abcNames.c
index b366890f..ccbd2c85 100644
--- a/src/base/abc/abcNames.c
+++ b/src/base/abc/abcNames.c
@@ -306,7 +306,7 @@ Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode )
int i;
vNodes = Vec_PtrAlloc( 100 );
Abc_ObjForEachFanin( pNode, pFanin, i )
- Vec_PtrPush( vNodes, util_strsav(Abc_ObjName(pFanin)) );
+ Vec_PtrPush( vNodes, Extra_UtilStrsav(Abc_ObjName(pFanin)) );
return vNodes;
}
@@ -341,7 +341,7 @@ Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames )
Buffer[1] = '0' + i/26;
Buffer[2] = 0;
}
- Vec_PtrPush( vNames, util_strsav(Buffer) );
+ Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) );
}
return vNames;
}
diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c
index 82367c09..31b4c5f4 100644
--- a/src/base/abc/abcNtk.c
+++ b/src/base/abc/abcNtk.c
@@ -117,8 +117,8 @@ Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_
// start the network
pNtkNew = Abc_NtkAlloc( Type, Func );
// duplicate the name and the spec
- pNtkNew->pName = util_strsav(pNtk->pName);
- pNtkNew->pSpec = util_strsav(pNtk->pSpec);
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+ pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
// clean the node copy fields
Abc_NtkForEachNode( pNtk, pObj, i )
pObj->pCopy = NULL;
@@ -235,8 +235,8 @@ Abc_Ntk_t * Abc_NtkStartRead( char * pName )
// allocate the empty network
pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP );
// set the specs
- pNtkNew->pName = util_strsav( Extra_FileNameGeneric(pName) );
- pNtkNew->pSpec = util_strsav( pName );
+ pNtkNew->pName = Extra_FileNameGeneric(pName);
+ pNtkNew->pSpec = Extra_UtilStrsav(pName);
return pNtkNew;
}
@@ -359,7 +359,7 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk )
/**Function*************************************************************
- Synopsis [Creates the network composed of one output.]
+ Synopsis [Creates the network composed of one logic cone.]
Description []
@@ -368,22 +368,22 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkCreateOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAllCis )
+Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis )
{
- Vec_Ptr_t * vNodes;
Abc_Ntk_t * pNtkNew;
- Abc_Obj_t * pObj, * pFanin;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pFanin, * pNodeCoNew;
char Buffer[1000];
int i, k;
assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
- assert( Abc_ObjIsCo(pNode) );
+ assert( Abc_ObjIsNode(pNode) );
// start the network
pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc );
// set the name
- sprintf( Buffer, "%s_%s", pNtk->pName, Abc_ObjName(pNode) );
- pNtkNew->pName = util_strsav(Buffer);
+ sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName );
+ pNtkNew->pName = Extra_UtilStrsav(Buffer);
// establish connection between the constant nodes
Abc_NtkConst1(pNtk)->pCopy = Abc_NtkConst1(pNtkNew);
@@ -399,7 +399,9 @@ Abc_Ntk_t * Abc_NtkCreateOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAl
Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) );
}
}
-
+ // add the PO corresponding to this output
+ pNodeCoNew = Abc_NtkCreatePo( pNtkNew );
+ Abc_NtkLogicStoreName( pNodeCoNew, pNodeName );
// copy the nodes
Vec_PtrForEachEntry( vNodes, pObj, i )
{
@@ -415,15 +417,83 @@ Abc_Ntk_t * Abc_NtkCreateOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAl
Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
}
}
+ // connect the internal nodes to the new CO
+ Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy );
Vec_PtrFree( vNodes );
- // add the PO corresponding to this output
- pNode->pCopy = Abc_NtkCreatePo( pNtkNew );
- Abc_ObjAddFanin( pNode->pCopy, Abc_ObjFanin0(pNode)->pCopy );
- Abc_NtkLogicStoreName( pNode->pCopy, Abc_ObjName(pNode) );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the network composed of MFFC of one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pFanin, * pNodeCoNew;
+ Vec_Ptr_t * vCone, * vSupp;
+ char Buffer[1000];
+ int i, k;
+
+ assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
+
+ // start the network
+ pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc );
+ // set the name
+ sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName );
+ pNtkNew->pName = Extra_UtilStrsav(Buffer);
+
+ // establish connection between the constant nodes
+ Abc_NtkConst1(pNtk)->pCopy = Abc_NtkConst1(pNtkNew);
+
+ // collect the nodes in MFFC
+ vCone = Vec_PtrAlloc( 100 );
+ vSupp = Vec_PtrAlloc( 100 );
+ Abc_NodeDeref_rec( pNode );
+ Abc_NodeMffsConeSupp( pNode, vCone, vSupp );
+ Abc_NodeRef_rec( pNode );
+ // create the PIs
+ Vec_PtrForEachEntry( vSupp, pObj, i )
+ {
+ pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+ Abc_NtkLogicStoreName( pObj->pCopy, Abc_ObjName(pObj) );
+ }
+ // create the PO
+ pNodeCoNew = Abc_NtkCreatePo( pNtkNew );
+ Abc_NtkLogicStoreName( pNodeCoNew, pNodeName );
+ // copy the nodes
+ Vec_PtrForEachEntry( vCone, pObj, i )
+ {
+ // if it is an AIG, add to the hash table
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
+ }
+ else
+ {
+ Abc_NtkDupObj( pNtkNew, pObj );
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+ }
+ }
+ // connect the topmost node
+ Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy );
+ Vec_PtrFree( vCone );
+ Vec_PtrFree( vSupp );
if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkCreateOutput(): Network check has failed.\n" );
+ fprintf( stdout, "Abc_NtkCreateMffc(): Network check has failed.\n" );
return pNtkNew;
}
@@ -438,7 +508,7 @@ Abc_Ntk_t * Abc_NtkCreateOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int fUseAl
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues )
+Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues )
{
Vec_Ptr_t * vNodes;
Abc_Ntk_t * pNtkNew;
@@ -450,7 +520,7 @@ Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t *
// start the network
Abc_NtkCleanCopy( pNtk );
pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG );
- pNtkNew->pName = util_strsav(pNtk->pName);
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
// collect the nodes in the TFI of the output
vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)vRoots->pArray, vRoots->nSize );
@@ -483,7 +553,7 @@ Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t *
Abc_ObjAddFanin( pNodePo, pFinal );
Abc_NtkLogicStoreName( pNodePo, "miter" );
if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+ fprintf( stdout, "Abc_NtkCreateTarget(): Network check has failed.\n" );
return pNtkNew;
}
@@ -505,7 +575,7 @@ Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode )
int i;
// start the network
pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc );
- pNtkNew->pName = util_strsav(Abc_ObjName(pNode));
+ pNtkNew->pName = Extra_UtilStrsav(Abc_ObjName(pNode));
// add the PIs corresponding to the fanins of the node
Abc_ObjForEachFanin( pNode, pFanin, i )
{
@@ -544,7 +614,7 @@ Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop )
int i, nVars;
// start the network
pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP );
- pNtkNew->pName = util_strsav("ex");
+ pNtkNew->pName = Extra_UtilStrsav("ex");
// create PIs
Vec_PtrPush( pNtkNew->vObjs, NULL );
nVars = Abc_SopGetVarNum( pSop );
diff --git a/src/base/abc/abcRefs.c b/src/base/abc/abcRefs.c
index 5d0c68d1..808bfae8 100644
--- a/src/base/abc/abcRefs.c
+++ b/src/base/abc/abcRefs.c
@@ -24,10 +24,8 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t * vNodes );
-static int Abc_NodeMffcCountSupp( Vec_Ptr_t * vNodes );
+static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel );
static int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference );
-static int Abc_NodeDeref( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
@@ -52,8 +50,8 @@ int Abc_NodeMffcSize( Abc_Obj_t * pNode )
assert( Abc_ObjIsNode( pNode ) );
if ( Abc_ObjFaninNum(pNode) == 0 )
return 0;
- nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0, NULL ); // dereference
- nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference
+ nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference
+ nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference
assert( nConeSize1 == nConeSize2 );
assert( nConeSize1 > 0 );
return nConeSize1;
@@ -61,36 +59,6 @@ int Abc_NodeMffcSize( Abc_Obj_t * pNode )
/**Function*************************************************************
- Synopsis [Returns the MFFC size.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_NodeMffcSizeSupp( Abc_Obj_t * pNode )
-{
- Vec_Ptr_t * vNodes;
- int nSuppSize, nConeSize1, nConeSize2;
- assert( Abc_NtkIsStrash(pNode->pNtk) );
- assert( !Abc_ObjIsComplement( pNode ) );
- assert( Abc_ObjIsNode( pNode ) );
- if ( Abc_ObjFaninNum(pNode) == 0 )
- return 0;
- vNodes = Vec_PtrAlloc( 10 );
- nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0, vNodes ); // dereference
- nSuppSize = Abc_NodeMffcCountSupp(vNodes);
- nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference
- assert( nConeSize1 == nConeSize2 );
- assert( nConeSize1 > 0 );
- Vec_PtrFree(vNodes);
- return nSuppSize;
-}
-
-/**Function*************************************************************
-
Synopsis [Returns the MFFC size while stopping at the complemented edges.]
Description []
@@ -129,12 +97,13 @@ int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode )
int Abc_NodeMffcLabel( Abc_Obj_t * pNode )
{
int nConeSize1, nConeSize2;
+ assert( Abc_NtkIsStrash(pNode->pNtk) );
assert( !Abc_ObjIsComplement( pNode ) );
assert( Abc_ObjIsNode( pNode ) );
if ( Abc_ObjFaninNum(pNode) == 0 )
return 0;
- nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1, NULL ); // dereference
- nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference
+ nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1 ); // dereference
+ nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference
assert( nConeSize1 == nConeSize2 );
assert( nConeSize1 > 0 );
return nConeSize1;
@@ -142,88 +111,64 @@ int Abc_NodeMffcLabel( Abc_Obj_t * pNode )
/**Function*************************************************************
- Synopsis [Returns the MFFC size.]
+ Synopsis [References/references the node and returns MFFC size.]
- Description [Profiling shows that this procedure runs the same as
- the above one, not faster.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NodeMffcLabelFast( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel )
{
- Abc_Obj_t * pTemp;
- int nConeSize, i;
-
- assert( !Abc_ObjIsComplement( pNode ) );
- assert( Abc_ObjIsNode( pNode ) );
- if ( Abc_ObjFaninNum(pNode) == 0 )
+ Abc_Obj_t * pNode0, * pNode1;
+ int Counter;
+ // label visited nodes
+ if ( fLabel )
+ Abc_NodeSetTravIdCurrent( pNode );
+ // skip the CI
+ if ( Abc_ObjIsCi(pNode) )
return 0;
-
- Vec_PtrClear( vNodes );
- nConeSize = Abc_NodeDeref( pNode, vNodes );
- // label the nodes with the current ID and ref their children
- Vec_PtrForEachEntry( vNodes, pTemp, i )
+ // process the internal node
+ pNode0 = Abc_ObjFanin0(pNode);
+ pNode1 = Abc_ObjFanin1(pNode);
+ Counter = 1;
+ if ( fReference )
+ {
+ if ( pNode0->vFanouts.nSize++ == 0 )
+ Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel );
+ if ( pNode1->vFanouts.nSize++ == 0 )
+ Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel );
+ }
+ else
{
- Abc_NodeSetTravIdCurrent( pTemp );
- if ( Abc_ObjIsCi(pTemp) )
- continue;
- Abc_ObjFanin0(pTemp)->vFanouts.nSize++;
- Abc_ObjFanin1(pTemp)->vFanouts.nSize++;
+ assert( pNode0->vFanouts.nSize > 0 );
+ assert( pNode1->vFanouts.nSize > 0 );
+ if ( --pNode0->vFanouts.nSize == 0 )
+ Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel );
+ if ( --pNode1->vFanouts.nSize == 0 )
+ Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel );
}
- return nConeSize;
+ return Counter;
}
-/**Function*************************************************************
-
- Synopsis [Collects the nodes in MFFC in the topological order.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Vec_Ptr_t * Abc_NodeMffcCollect( Abc_Obj_t * pNode )
-{
- Vec_Ptr_t * vNodes;
- int nConeSize1, nConeSize2;
- assert( !Abc_ObjIsComplement( pNode ) );
- assert( Abc_ObjIsNode( pNode ) );
- vNodes = Vec_PtrAlloc( 8 );
- if ( Abc_ObjFaninNum(pNode) == 0 )
- return vNodes;
- nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0, vNodes ); // dereference
- nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference
- assert( nConeSize1 == nConeSize2 );
- assert( nConeSize1 > 0 );
- return vNodes;
-}
/**Function*************************************************************
Synopsis [References/references the node and returns MFFC size.]
- Description []
+ Description [Stops at the complemented edges.]
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t * vNodes )
+int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference )
{
Abc_Obj_t * pNode0, * pNode1;
int Counter;
- // label visited nodes
- if ( fLabel )
- Abc_NodeSetTravIdCurrent( pNode );
- // collect visited nodes
- if ( vNodes )
- Vec_PtrPush( vNodes, pNode );
// skip the CI
if ( Abc_ObjIsCi(pNode) )
return 0;
@@ -233,26 +178,29 @@ int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t
Counter = 1;
if ( fReference )
{
- if ( pNode0->vFanouts.nSize++ == 0 )
- Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel, vNodes );
- if ( pNode1->vFanouts.nSize++ == 0 )
- Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel, vNodes );
+ if ( pNode0->vFanouts.nSize++ == 0 && !Abc_ObjFaninC0(pNode) )
+ Counter += Abc_NodeRefDerefStop( pNode0, fReference );
+ if ( pNode1->vFanouts.nSize++ == 0 && !Abc_ObjFaninC1(pNode) )
+ Counter += Abc_NodeRefDerefStop( pNode1, fReference );
}
else
{
assert( pNode0->vFanouts.nSize > 0 );
assert( pNode1->vFanouts.nSize > 0 );
- if ( --pNode0->vFanouts.nSize == 0 )
- Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel, vNodes );
- if ( --pNode1->vFanouts.nSize == 0 )
- Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel, vNodes );
+ if ( --pNode0->vFanouts.nSize == 0 && !Abc_ObjFaninC0(pNode) )
+ Counter += Abc_NodeRefDerefStop( pNode0, fReference );
+ if ( --pNode1->vFanouts.nSize == 0 && !Abc_ObjFaninC1(pNode) )
+ Counter += Abc_NodeRefDerefStop( pNode1, fReference );
}
return Counter;
}
+
+
+
/**Function*************************************************************
- Synopsis [References/references the node and returns MFFC supp size.]
+ Synopsis [Dereferences the node's MFFC.]
Description []
@@ -261,53 +209,24 @@ int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t
SeeAlso []
***********************************************************************/
-int Abc_NodeMffcCountSupp( Vec_Ptr_t * vNodes )
+int Abc_NodeDeref_rec( Abc_Obj_t * pNode )
{
- Abc_Obj_t * pNode, * pNode0, * pNode1;
- int i, Counter = 0;
- Vec_PtrForEachEntry( vNodes, pNode, i )
- {
- if ( Abc_ObjIsCi(pNode) )
- {
- if ( pNode->fMarkB == 0 )
- {
- pNode->fMarkB = 1;
- Counter++;
- }
- continue;
- }
- pNode0 = Abc_ObjFanin0(pNode);
- if ( pNode0->vFanouts.nSize > 0 && pNode0->fMarkB == 0 )
- {
- pNode0->fMarkB = 1;
- Counter++;
- }
- pNode1 = Abc_ObjFanin1(pNode);
- if ( pNode1->vFanouts.nSize > 0 && pNode1->fMarkB == 0 )
- {
- pNode1->fMarkB = 1;
- Counter++;
- }
- }
- Vec_PtrForEachEntry( vNodes, pNode, i )
+ Abc_Obj_t * pFanin;
+ int i, Counter = 1;
+ if ( Abc_ObjIsCi(pNode) )
+ return 0;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
{
- if ( Abc_ObjIsCi(pNode) )
- {
- pNode->fMarkB = 0;
- continue;
- }
- pNode0 = Abc_ObjFanin0(pNode);
- pNode0->fMarkB = 0;
- pNode1 = Abc_ObjFanin1(pNode);
- pNode1->fMarkB = 0;
+ assert( pFanin->vFanouts.nSize > 0 );
+ if ( --pFanin->vFanouts.nSize == 0 )
+ Counter += Abc_NodeDeref_rec( pFanin );
}
return Counter;
-
}
/**Function*************************************************************
- Synopsis [References/references the node and returns MFFC size.]
+ Synopsis [References the node's MFFC.]
Description []
@@ -316,69 +235,98 @@ int Abc_NodeMffcCountSupp( Vec_Ptr_t * vNodes )
SeeAlso []
***********************************************************************/
-int Abc_NodeDeref( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
+int Abc_NodeRef_rec( Abc_Obj_t * pNode )
{
- Abc_Obj_t * pNode0, * pNode1;
- int Counter;
- // collect visited nodes
- Vec_PtrPush( vNodes, pNode );
- // skip the CI
+ Abc_Obj_t * pFanin;
+ int i, Counter = 1;
if ( Abc_ObjIsCi(pNode) )
return 0;
- // process the internal node
- pNode0 = Abc_ObjFanin0(pNode);
- pNode1 = Abc_ObjFanin1(pNode);
- assert( pNode0->vFanouts.nSize > 0 );
- assert( pNode1->vFanouts.nSize > 0 );
- Counter = 1;
- if ( --pNode0->vFanouts.nSize == 0 )
- Counter += Abc_NodeDeref( pNode0, vNodes );
- if ( --pNode1->vFanouts.nSize == 0 )
- Counter += Abc_NodeDeref( pNode1, vNodes );
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( pFanin->vFanouts.nSize++ == 0 )
+ Counter += Abc_NodeRef_rec( pFanin );
+ }
return Counter;
}
/**Function*************************************************************
- Synopsis [References/references the node and returns MFFC size.]
+ Synopsis [Collects the internal and boundary nodes in the derefed MFFC.]
- Description [Stops at the complemented edges.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference )
+void Abc_NodeMffsConeSupp_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost )
{
- Abc_Obj_t * pNode0, * pNode1;
- int Counter;
- // skip the CI
- if ( Abc_ObjIsCi(pNode) )
- return 0;
- // process the internal node
- pNode0 = Abc_ObjFanin0(pNode);
- pNode1 = Abc_ObjFanin1(pNode);
- Counter = 1;
- if ( fReference )
- {
- if ( pNode0->vFanouts.nSize++ == 0 && !Abc_ObjFaninC0(pNode) )
- Counter += Abc_NodeRefDerefStop( pNode0, fReference );
- if ( pNode1->vFanouts.nSize++ == 0 && !Abc_ObjFaninC1(pNode) )
- Counter += Abc_NodeRefDerefStop( pNode1, fReference );
- }
- else
+ Abc_Obj_t * pFanin;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return;
+ Abc_NodeSetTravIdCurrent(pNode);
+ // add to the new support nodes
+ if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) )
{
- assert( pNode0->vFanouts.nSize > 0 );
- assert( pNode1->vFanouts.nSize > 0 );
- if ( --pNode0->vFanouts.nSize == 0 && !Abc_ObjFaninC0(pNode) )
- Counter += Abc_NodeRefDerefStop( pNode0, fReference );
- if ( --pNode1->vFanouts.nSize == 0 && !Abc_ObjFaninC1(pNode) )
- Counter += Abc_NodeRefDerefStop( pNode1, fReference );
+ Vec_PtrPush( vSupp, pNode );
+ return;
}
- return Counter;
+ // recur on the children
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ Abc_NodeMffsConeSupp_rec( pFanin, vCone, vSupp, 0 );
+ // collect the internal node
+ Vec_PtrPush( vCone, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the support of the derefed MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp )
+{
+ assert( Abc_ObjIsNode(pNode) );
+ assert( !Abc_ObjIsComplement(pNode) );
+ Vec_PtrClear( vCone );
+ Vec_PtrClear( vSupp );
+ Abc_NtkIncrementTravId( pNode->pNtk );
+ Abc_NodeMffsConeSupp_rec( pNode, vCone, vSupp, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the support of the derefed MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode )
+{
+ Vec_Ptr_t * vCone, * vSupp;
+ vCone = Vec_PtrAlloc( 100 );
+ vSupp = Vec_PtrAlloc( 100 );
+ Abc_NodeDeref_rec( pNode );
+ Abc_NodeMffsConeSupp( pNode, vCone, vSupp );
+ Abc_NodeRef_rec( pNode );
+ printf( "Cone = %6d. Supp = %6d. \n", Vec_PtrSize(vCone), Vec_PtrSize(vSupp) );
+ Vec_PtrFree( vCone );
+ Vec_PtrFree( vSupp );
}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c
index 1e52e4a6..122cf589 100644
--- a/src/base/abc/abcUtil.c
+++ b/src/base/abc/abcUtil.c
@@ -28,8 +28,6 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fFanouts, bool fReference );
-
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -605,6 +603,35 @@ bool Abc_NodeIsMuxType( Abc_Obj_t * pNode )
/**Function*************************************************************
+ Synopsis [Returns 1 if the node is the control type of the MUX.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NodeIsMuxControlType( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pNode0, * pNode1;
+ // check that the node is regular
+ assert( !Abc_ObjIsComplement(pNode) );
+ // skip the node that do not have two fanouts
+ if ( Abc_ObjFanoutNum(pNode) != 2 )
+ return 0;
+ // get the fanouts
+ pNode0 = Abc_ObjFanout( pNode, 0 );
+ pNode1 = Abc_ObjFanout( pNode, 1 );
+ // if they have more than one fanout, we are not interested
+ if ( Abc_ObjFanoutNum(pNode0) != 1 || Abc_ObjFanoutNum(pNode1) != 1 )
+ return 0;
+ // if the fanouts have the same fanout, this is MUX or EXOR (or a redundant gate (CA)(CB))
+ return Abc_ObjFanout0(pNode0) == Abc_ObjFanout0(pNode1);
+}
+
+/**Function*************************************************************
+
Synopsis [Recognizes what nodes are control and data inputs of a MUX.]
Description [If the node is a MUX, returns the control variable C.
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index 119f8cdf..d2422b64 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -62,6 +62,7 @@ static int Abc_CommandDisjoint ( Abc_Frame_t * pAbc, int argc, char ** argv
static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRestructure ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -80,6 +81,7 @@ static int Abc_CommandExdcGet ( Abc_Frame_t * pAbc, int argc, char ** argv
static int Abc_CommandExdcSet ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandXyz ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandEspresso ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -110,6 +112,7 @@ static int Abc_CommandSeqCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv
static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandProve ( Abc_Frame_t * pAbc, int argc, char ** argv );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
@@ -161,6 +164,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "restructure", Abc_CommandRestructure, 1 );
// Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 );
Cmd_CommandAdd( pAbc, "Various", "miter", Abc_CommandMiter, 1 );
@@ -171,14 +175,15 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Various", "muxes", Abc_CommandMuxes, 1 );
Cmd_CommandAdd( pAbc, "Various", "sat", Abc_CommandSat, 0 );
Cmd_CommandAdd( pAbc, "Various", "ext_seq_dcs", Abc_CommandExtSeqDcs, 0 );
- Cmd_CommandAdd( pAbc, "Various", "one_output", Abc_CommandOneOutput, 1 );
- Cmd_CommandAdd( pAbc, "Various", "one_node", Abc_CommandOneNode, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "cone", Abc_CommandOneOutput, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "node", Abc_CommandOneNode, 1 );
Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 0 );
Cmd_CommandAdd( pAbc, "Various", "exdc_free", Abc_CommandExdcFree, 1 );
Cmd_CommandAdd( pAbc, "Various", "exdc_get", Abc_CommandExdcGet, 1 );
Cmd_CommandAdd( pAbc, "Various", "exdc_set", Abc_CommandExdcSet, 1 );
Cmd_CommandAdd( pAbc, "Various", "cut", Abc_CommandCut, 0 );
Cmd_CommandAdd( pAbc, "Various", "xyz", Abc_CommandXyz, 1 );
+ Cmd_CommandAdd( pAbc, "Various", "espresso", Abc_CommandEspresso, 1 );
Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 );
@@ -209,6 +214,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 );
Cmd_CommandAdd( pAbc, "Verification", "sec", Abc_CommandSec, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "prove", Abc_CommandProve, 1 );
// Rwt_Man4ExploreStart();
// Map_Var3Print();
@@ -258,8 +264,8 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
// set the defaults
fShort = 1;
fFactor = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "sfh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "sfh" ) ) != EOF )
{
switch ( c )
{
@@ -321,8 +327,8 @@ int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv )
// set the defaults
fShort = 1;
fPrintDc = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "sdh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "sdh" ) ) != EOF )
{
switch ( c )
{
@@ -407,8 +413,8 @@ int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -425,18 +431,18 @@ int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind + 1 )
+ if ( argc == globalUtilOptind + 1 )
{
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
Abc_NodePrintFanio( pOut, pNode );
@@ -476,8 +482,8 @@ int Abc_CommandPrintLatch( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -526,8 +532,8 @@ int Abc_CommandPrintFanio( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -580,8 +586,8 @@ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fUseRealNames = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "nh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
{
switch ( c )
{
@@ -607,18 +613,18 @@ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind + 1 )
+ if ( argc == globalUtilOptind + 1 )
{
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
Abc_NodePrintFactor( pOut, pNode, fUseRealNames );
@@ -664,8 +670,8 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fListNodes = 0;
fProfile = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "nph" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nph" ) ) != EOF )
{
switch ( c )
{
@@ -694,18 +700,18 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind + 1 )
+ if ( argc == globalUtilOptind + 1 )
{
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
Abc_NodePrintLevel( pOut, pNode );
@@ -752,8 +758,8 @@ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
@@ -829,8 +835,8 @@ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv )
fUseBdds = 0;
fNaive = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "bnvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "bnvh" ) ) != EOF )
{
switch ( c )
{
@@ -906,8 +912,8 @@ int Abc_CommandPrintUnate( Abc_Frame_t * pAbc, int argc, char ** argv )
fUseBdds = 1;
fUseNaive = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "bnvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "bnvh" ) ) != EOF )
{
switch ( c )
{
@@ -978,19 +984,19 @@ int Abc_CommandPrintAuto( Abc_Frame_t * pAbc, int argc, char ** argv )
Output = -1;
fNaive = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Onvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Onvh" ) ) != EOF )
{
switch ( c )
{
case 'O':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" );
goto usage;
}
- Output = atoi(argv[util_optind]);
- util_optind++;
+ Output = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( Output < 0 )
goto usage;
break;
@@ -1058,8 +1064,8 @@ int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fUseRealNames = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "nh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
{
switch ( c )
{
@@ -1084,12 +1090,12 @@ int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Visualizing Karnaugh map works for BDD logic networks (run \"bdd\").\n" );
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind )
+ if ( argc == globalUtilOptind )
{
pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) );
if ( !Abc_ObjIsNode(pNode) )
@@ -1100,10 +1106,10 @@ int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv )
}
else
{
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
}
@@ -1145,8 +1151,8 @@ int Abc_CommandPrintGates( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fUseLibrary = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
{
switch ( c )
{
@@ -1208,8 +1214,8 @@ int Abc_CommandPrintSharing( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fUseLibrary = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
{
switch ( c )
{
@@ -1269,8 +1275,8 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1293,12 +1299,12 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind )
+ if ( argc == globalUtilOptind )
{
pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) );
if ( !Abc_ObjIsNode(pNode) )
@@ -1309,10 +1315,10 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
}
else
{
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
}
@@ -1359,30 +1365,30 @@ int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
nNodeSizeMax = 10;
nConeSizeMax = ABC_INFINITY;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "NCh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NCh" ) ) != EOF )
{
switch ( c )
{
case 'N':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
goto usage;
}
- nNodeSizeMax = atoi(argv[util_optind]);
- util_optind++;
+ nNodeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nNodeSizeMax < 0 )
goto usage;
break;
case 'C':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
goto usage;
}
- nConeSizeMax = atoi(argv[util_optind]);
- util_optind++;
+ nConeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nConeSizeMax < 0 )
goto usage;
break;
@@ -1404,16 +1410,16 @@ int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Visualizing cuts only works for AIGs (run \"strash\").\n" );
return 1;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax );
@@ -1459,8 +1465,8 @@ int Abc_CommandShowAig( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fMulti = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "mh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF )
{
switch ( c )
{
@@ -1533,8 +1539,8 @@ int Abc_CommandShowNtk( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fGateNames = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "gh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "gh" ) ) != EOF )
{
switch ( c )
{
@@ -1595,8 +1601,8 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1671,8 +1677,8 @@ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fAllNodes = 0;
fCleanup = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ach" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ach" ) ) != EOF )
{
switch ( c )
{
@@ -1733,19 +1739,24 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
bool fDuplicate;
bool fSelective;
+ bool fUpdateLevel;
pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fDuplicate = 0;
- fSelective = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dsh" ) ) != EOF )
+ fDuplicate = 0;
+ fSelective = 0;
+ fUpdateLevel = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ldsh" ) ) != EOF )
{
switch ( c )
{
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
case 'd':
fDuplicate ^= 1;
break;
@@ -1773,7 +1784,7 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv )
// get the new network
if ( Abc_NtkIsStrash(pNtk) )
{
- pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective );
+ pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective, fUpdateLevel );
}
else
{
@@ -1783,7 +1794,7 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Strashing before balancing has failed.\n" );
return 1;
}
- pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective );
+ pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective, fUpdateLevel );
Abc_NtkDelete( pNtkTemp );
}
@@ -1798,8 +1809,9 @@ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: balance [-dsh]\n" );
+ fprintf( pErr, "usage: balance [-ldsh]\n" );
fprintf( pErr, "\t transforms the current network into a well-balanced AIG\n" );
+ fprintf( pErr, "\t-l : toggle minimizing the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" );
fprintf( pErr, "\t-s : toggle duplication on the critical paths [default = %s]\n", fSelective? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
@@ -1836,30 +1848,30 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
fCnf = 0;
fMulti = 0;
fSimple = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "TFmcsh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "TFmcsh" ) ) != EOF )
{
switch ( c )
{
case 'T':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
goto usage;
}
- nThresh = atoi(argv[util_optind]);
- util_optind++;
+ nThresh = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nThresh < 0 )
goto usage;
break;
case 'F':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
goto usage;
}
- nFaninMax = atoi(argv[util_optind]);
- util_optind++;
+ nFaninMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFaninMax < 0 )
goto usage;
break;
@@ -1938,8 +1950,8 @@ int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1993,8 +2005,8 @@ int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2062,30 +2074,30 @@ int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv )
p->fUse0 = 0;
p->fUseCompl = 1;
p->fVerbose = 0;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "LNsdzcvh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "LNsdzcvh")) != EOF )
{
switch (c)
{
case 'L':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" );
goto usage;
}
- p->nPairsMax = atoi(argv[util_optind]);
- util_optind++;
+ p->nPairsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( p->nPairsMax < 0 )
goto usage;
break;
case 'N':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
goto usage;
}
- p->nNodesExt = atoi(argv[util_optind]);
- util_optind++;
+ p->nNodesExt = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( p->nNodesExt < 0 )
goto usage;
break;
@@ -2184,8 +2196,8 @@ int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv )
fVerbose = 0;
fPrint = 0;
fShort = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "grvpsh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "grvpsh" ) ) != EOF )
{
switch ( c )
{
@@ -2309,8 +2321,8 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
fPrecompute = 0;
fUseZeros = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "lxzvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvh" ) ) != EOF )
{
switch ( c )
{
@@ -2371,7 +2383,7 @@ usage:
fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
-}
+}
/**Function*************************************************************
@@ -2404,34 +2416,34 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
nNodeSizeMax = 10;
nConeSizeMax = 16;
- fUpdateLevel = 0;
+ fUpdateLevel = 1;
fUseZeros = 0;
fUseDcs = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "NClzdvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NClzdvh" ) ) != EOF )
{
switch ( c )
{
case 'N':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
goto usage;
}
- nNodeSizeMax = atoi(argv[util_optind]);
- util_optind++;
+ nNodeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nNodeSizeMax < 0 )
goto usage;
break;
case 'C':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
goto usage;
}
- nConeSizeMax = atoi(argv[util_optind]);
- util_optind++;
+ nConeSizeMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nConeSizeMax < 0 )
goto usage;
break;
@@ -2497,6 +2509,109 @@ usage:
return 1;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int nCutMax;
+ bool fUpdateLevel;
+ bool fUseZeros;
+ bool fVerbose;
+ extern int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nCutMax = 5;
+ fUpdateLevel = 0;
+ fUseZeros = 0;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Klzvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'K':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nCutMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nCutMax < 0 )
+ goto usage;
+ break;
+ case 'l':
+ fUpdateLevel ^= 1;
+ break;
+ case 'z':
+ fUseZeros ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( nCutMax < 4 || nCutMax > CUT_SIZE_MAX )
+ {
+ fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", 4, CUT_SIZE_MAX );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" );
+ return 1;
+ }
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
+ return 1;
+ }
+
+ // modify the current network
+ if ( !Abc_NtkRestructure( pNtk, nCutMax, fUpdateLevel, fUseZeros, fVerbose ) )
+ {
+ fprintf( pErr, "Refactoring has failed.\n" );
+ return 1;
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: restructure [-K num] [-lzvh]\n" );
+ fprintf( pErr, "\t performs technology-independent restructuring of the AIG\n" );
+ fprintf( pErr, "\t-K num : the max cut size (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, nCutMax );
+ fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
/**Function*************************************************************
@@ -2520,8 +2635,8 @@ int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2591,8 +2706,8 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fComb = 1;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -2604,8 +2719,8 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- pArgvNew = argv + util_optind;
- nArgcNew = argc - util_optind;
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
return 1;
@@ -2662,19 +2777,19 @@ int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fInitial = 0;
nFrames = 5;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Fih" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Fih" ) ) != EOF )
{
switch ( c )
{
case 'F':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
goto usage;
}
- nFrames = atoi(argv[util_optind]);
- util_optind++;
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFrames <= 0 )
goto usage;
break;
@@ -2744,8 +2859,8 @@ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2804,8 +2919,8 @@ int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2866,8 +2981,8 @@ int Abc_CommandReorder( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
@@ -2926,8 +3041,8 @@ int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -2987,29 +3102,43 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int RetValue;
int fVerbose;
- int nSeconds;
+ int nConfLimit;
+ int nImpLimit;
+ int clk;
pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- fVerbose = 0;
- nSeconds = 20;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Tvh" ) ) != EOF )
+ fVerbose = 0;
+ nConfLimit = 100000;
+ nImpLimit = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF )
{
switch ( c )
{
- case 'T':
- if ( util_optind >= argc )
+ case 'C':
+ if ( globalUtilOptind >= argc )
{
- fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
goto usage;
}
- nSeconds = atoi(argv[util_optind]);
- util_optind++;
- if ( nSeconds < 0 )
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nImpLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nImpLimit < 0 )
goto usage;
break;
case 'v':
@@ -3038,46 +3167,42 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
}
-/*
- if ( !Abc_NtkIsLogic(pNtk) )
- {
- fprintf( stdout, "This command can only be applied to logic network (run \"renode -c\").\n" );
- return 0;
- }
- if ( Abc_NtkIsMappedLogic(pNtk) )
- Abc_NtkUnmap(pNtk);
- if ( Abc_NtkIsSopLogic(pNtk) )
- Abc_NtkSopToBdd(pNtk);
-*/
if ( Abc_NtkIsStrash(pNtk) )
{
- RetValue = Abc_NtkMiterSat( pNtk, nSeconds, fVerbose );
+ clk = clock();
+ RetValue = Abc_NtkMiterSat( pNtk, nConfLimit, nImpLimit, fVerbose );
if ( RetValue == -1 )
- printf( "The miter is UNDECIDED (SAT solver timed out).\n" );
+ printf( "UNDECIDED " );
else if ( RetValue == 0 )
- printf( "The miter is SATISFIABLE.\n" );
+ printf( "SATISFIABLE " );
else
- printf( "The miter is UNSATISFIABLE.\n" );
+ printf( "UNSATISFIABLE " );
+ //printf( "\n" );
+ PRT( "Time", clock() - clk );
}
else
{
Abc_Ntk_t * pTemp;
pTemp = Abc_NtkStrash( pNtk, 0, 0 );
- RetValue = Abc_NtkMiterSat( pTemp, nSeconds, fVerbose );
+ clk = clock();
+ RetValue = Abc_NtkMiterSat( pTemp, nConfLimit, nImpLimit, fVerbose );
if ( RetValue == -1 )
- printf( "The miter is UNDECIDED (SAT solver timed out).\n" );
+ printf( "UNDECIDED " );
else if ( RetValue == 0 )
- printf( "The miter is SATISFIABLE.\n" );
+ printf( "SATISFIABLE " );
else
- printf( "The miter is UNSATISFIABLE.\n" );
+ printf( "UNSATISFIABLE " );
+ //printf( "\n" );
+ PRT( "Time", clock() - clk );
Abc_NtkDelete( pTemp );
}
return 0;
usage:
- fprintf( pErr, "usage: sat [-T num] [-vh]\n" );
+ fprintf( pErr, "usage: sat [-C num] [-I num] [-vh]\n" );
fprintf( pErr, "\t solves the combinational miter\n" );
- fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of implications [default = %d]\n", nImpLimit );
fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
@@ -3109,8 +3234,8 @@ int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
@@ -3169,9 +3294,10 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
- Abc_Obj_t * pNode;
+ Abc_Obj_t * pNode, * pNodeCo;
int c;
int fUseAllCis;
+ int fUseMffc;
int Output;
pNtk = Abc_FrameReadNtk(pAbc);
@@ -3180,23 +3306,26 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fUseAllCis = 0;
+ fUseMffc = 0;
Output = -1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Oah" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Omah" ) ) != EOF )
{
switch ( c )
{
case 'O':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" );
goto usage;
}
- Output = atoi(argv[util_optind]);
- util_optind++;
+ Output = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( Output < 0 )
goto usage;
break;
+ case 'm':
+ fUseMffc ^= 1;
case 'a':
fUseAllCis ^= 1;
break;
@@ -3219,27 +3348,31 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc > util_optind + 1 )
+ if ( argc > globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- if ( argc == util_optind + 1 )
+ if ( argc == globalUtilOptind + 1 )
{
- pNode = Abc_NtkFindCo( pNtk, argv[util_optind] );
+ pNodeCo = Abc_NtkFindCo( pNtk, argv[globalUtilOptind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find CO node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
- pNtkRes = Abc_NtkCreateOutput( pNtk, pNode, fUseAllCis );
+ if ( fUseMffc )
+ pNtkRes = Abc_NtkCreateMffc( pNtk, pNode, argv[globalUtilOptind] );
+ else
+ pNtkRes = Abc_NtkCreateCone( pNtk, pNode, argv[globalUtilOptind], fUseAllCis );
}
else
{
if ( Output == -1 )
{
- fprintf( pErr, "The output is not specified.\n" );
+ fprintf( pErr, "The node is not specified.\n" );
return 1;
}
if ( Output >= Abc_NtkCoNum(pNtk) )
@@ -3247,11 +3380,17 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "The 0-based output number (%d) is larger than the number of outputs (%d).\n", Output, Abc_NtkCoNum(pNtk) );
return 1;
}
- pNtkRes = Abc_NtkCreateOutput( pNtk, Abc_NtkCo(pNtk,Output), fUseAllCis );
+ pNodeCo = Abc_NtkCo( pNtk, Output );
+ if ( fUseMffc )
+ pNtkRes = Abc_NtkCreateMffc( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo) );
+ else
+ pNtkRes = Abc_NtkCreateCone( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo), fUseAllCis );
}
+ if ( pNodeCo && Abc_ObjFaninC0(pNodeCo) )
+ printf( "The extracted cone represents the complement function of the CO.\n" );
if ( pNtkRes == NULL )
{
- fprintf( pErr, "Splitting one output has failed.\n" );
+ fprintf( pErr, "Writing the logic cone of one node has failed.\n" );
return 1;
}
// replace the current network
@@ -3259,12 +3398,13 @@ int Abc_CommandOneOutput( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: one_output [-O num] [-ah] <name>\n" );
- fprintf( pErr, "\t replaces the current network by the logic cone of one output\n" );
+ fprintf( pErr, "usage: cone [-O num] [-amh] <name>\n" );
+ fprintf( pErr, "\t replaces the current network by one logic cone\n" );
fprintf( pErr, "\t-a : toggle writing all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" );
+ fprintf( pErr, "\t-m : toggle writing only MFFC or complete TFI cone [default = %s]\n", fUseMffc? "MFFC": "TFI cone" );
fprintf( pErr, "\t-h : print the command usage\n");
- fprintf( pErr, "\t-O num : (optional) the 0-based number of the output\n");
- fprintf( pErr, "\tname : (optional) the name of the output\n");
+ fprintf( pErr, "\t-O num : (optional) the 0-based number of the CO to extract\n");
+ fprintf( pErr, "\tname : (optional) the name of the node to extract\n");
return 1;
}
@@ -3291,8 +3431,8 @@ int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -3315,16 +3455,16 @@ int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
fprintf( pErr, "Wrong number of auguments.\n" );
goto usage;
}
- pNode = Abc_NtkFindNode( pNtk, argv[util_optind] );
+ pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] );
if ( pNode == NULL )
{
- fprintf( pErr, "Cannot find node \"%s\".\n", argv[util_optind] );
+ fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] );
return 1;
}
@@ -3340,7 +3480,7 @@ int Abc_CommandOneNode( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: one_node [-h] <name>\n" );
+ fprintf( pErr, "usage: node [-h] <name>\n" );
fprintf( pErr, "\t replaces the current network by the network composed of one node\n" );
fprintf( pErr, "\t-h : print the command usage\n");
fprintf( pErr, "\tname : the node name\n");
@@ -3371,8 +3511,8 @@ int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -3420,8 +3560,8 @@ int Abc_CommandExdcFree( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -3480,8 +3620,8 @@ int Abc_CommandExdcGet( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -3538,8 +3678,8 @@ int Abc_CommandExdcSet( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -3556,13 +3696,13 @@ int Abc_CommandExdcSet( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
@@ -3639,30 +3779,30 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv )
pParams->fDrop = 0; // drop cuts on the fly
pParams->fMulti = 0; // use multi-input AND-gates
pParams->fVerbose = 0; // the verbosiness flag
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "KMtfdmvoh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdmvoh" ) ) != EOF )
{
switch ( c )
{
case 'K':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nVarsMax = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nVarsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nVarsMax < 0 )
goto usage;
break;
case 'M':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nKeepMax = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nKeepMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nKeepMax < 0 )
goto usage;
break;
@@ -3729,7 +3869,7 @@ usage:
fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" );
fprintf( pErr, "\t-f : toggle filtering of duplicated/dominated [default = %s]\n", pParams->fFilter? "yes": "no" );
fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" );
- fprintf( pErr, "\t-m : toggle using multi-input AND-gates [default = %s]\n", pParams->fMulti? "yes": "no" );
+ fprintf( pErr, "\t-m : toggle computing only factor-cuts [default = %s]\n", pParams->fMulti? "yes": "no" );
fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
@@ -3767,30 +3907,30 @@ int Abc_CommandScut( Abc_Frame_t * pAbc, int argc, char ** argv )
pParams->fFilter = 1; // filter dominated cuts
pParams->fSeq = 1; // compute sequential cuts
pParams->fVerbose = 0; // the verbosiness flag
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "KMtvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KMtvh" ) ) != EOF )
{
switch ( c )
{
case 'K':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nVarsMax = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nVarsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nVarsMax < 0 )
goto usage;
break;
case 'M':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nKeepMax = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nKeepMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nKeepMax < 0 )
goto usage;
break;
@@ -3868,19 +4008,19 @@ int Abc_CommandXyz( Abc_Frame_t * pAbc, int argc, char ** argv )
fVerbose = 0;
fUseInvs = 1;
nFaninMax = 128;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Nivh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Nivh" ) ) != EOF )
{
switch ( c )
{
case 'N':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
goto usage;
}
- nFaninMax = atoi(argv[util_optind]);
- util_optind++;
+ nFaninMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFaninMax < 0 )
goto usage;
break;
@@ -3931,6 +4071,66 @@ usage:
return 1;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandEspresso( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk;
+ int c;
+ int fVerbose;
+ extern void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsLogic(pNtk) )
+ {
+ fprintf( pErr, "SOP minimization is possible for logic networks (run \"renode\").\n" );
+ return 1;
+ }
+ Abc_NtkEspresso( pNtk, fVerbose );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: espresso [-vh]\n" );
+ fprintf( pErr, "\t minimizes SOPs of the local functions using Espresso\n" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
/**Function*************************************************************
@@ -3948,15 +4148,15 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
int c;
-// extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk );
+ extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk );
pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -3984,8 +4184,8 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
// run the command
// pNtkRes = Abc_NtkMiterForCofactors( pNtk, 0, 0, -1 );
-// pNtkRes = Abc_NtkNewAig( pNtk );
- pNtkRes = NULL;
+ pNtkRes = Abc_NtkNewAig( pNtk );
+// pNtkRes = NULL;
if ( pNtkRes == NULL )
{
fprintf( pErr, "Command has failed.\n" );
@@ -4044,41 +4244,41 @@ int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv )
pParams->fTryProve = 0; // tries to solve the final miter
pParams->fVerbose = 0; // the verbosiness flag
pParams->fVerboseP = 0; // the verbosiness flag
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "RDBrscpvaeh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "RDBrscpvaeh" ) ) != EOF )
{
switch ( c )
{
case 'R':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nPatsRand = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nPatsRand = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nPatsRand < 0 )
goto usage;
break;
case 'D':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nPatsDyna = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nPatsDyna = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nPatsDyna < 0 )
goto usage;
break;
case 'B':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" );
goto usage;
}
- pParams->nBTLimit = atoi(argv[util_optind]);
- util_optind++;
+ pParams->nBTLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( pParams->nBTLimit < 0 )
goto usage;
break;
@@ -4189,8 +4389,8 @@ int Abc_CommandFraigTrust( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
@@ -4253,8 +4453,8 @@ int Abc_CommandFraigStore( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
@@ -4314,8 +4514,8 @@ int Abc_CommandFraigRestore( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
@@ -4378,8 +4578,8 @@ int Abc_CommandFraigClean( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fDuplicate = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "dh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
@@ -4432,8 +4632,8 @@ int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
fUseInv = 1;
fExdc = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ievh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ievh" ) ) != EOF )
{
switch ( c )
{
@@ -4521,19 +4721,19 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
fSweep = 1;
fSwitching = 0;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Daspvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Daspvh" ) ) != EOF )
{
switch ( c )
{
case 'D':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" );
goto usage;
}
- DelayTarget = (float)atof(argv[util_optind]);
- util_optind++;
+ DelayTarget = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( DelayTarget <= 0.0 )
goto usage;
break;
@@ -4576,7 +4776,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Strashing before mapping has failed.\n" );
return 1;
}
- pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0 );
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
Abc_NtkDelete( pNtkRes );
if ( pNtk == NULL )
{
@@ -4652,8 +4852,8 @@ int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -4713,8 +4913,8 @@ int Abc_CommandAttach( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -4776,8 +4976,8 @@ int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -4853,8 +5053,8 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
fSwitching = 0;
fVerbose = 0;
DelayTarget =-1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "apvhD" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "apvhD" ) ) != EOF )
{
switch ( c )
{
@@ -4870,13 +5070,13 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'h':
goto usage;
case 'D':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" );
goto usage;
}
- DelayTarget = (float)atof(argv[util_optind]);
- util_optind++;
+ DelayTarget = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( DelayTarget <= 0.0 )
goto usage;
break;
@@ -4906,7 +5106,7 @@ int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Strashing before FPGA mapping has failed.\n" );
return 1;
}
- pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0 );
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
Abc_NtkDelete( pNtkRes );
if ( pNtk == NULL )
{
@@ -4985,8 +5185,8 @@ int Abc_CommandPga( Abc_Frame_t * pAbc, int argc, char ** argv )
pParams->fSwitching = 0;
pParams->fDropCuts = 0;
pParams->fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "fapdvh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "fapdvh" ) ) != EOF )
{
switch ( c )
{
@@ -5029,7 +5229,7 @@ int Abc_CommandPga( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Strashing before FPGA mapping has failed.\n" );
return 1;
}
- pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0 );
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
Abc_NtkDelete( pNtkRes );
if ( pNtk == NULL )
{
@@ -5106,8 +5306,8 @@ int Abc_CommandInit( Abc_Frame_t * pAbc, int argc, char ** argv )
fOnes = 0;
fRandom = 0;
fDontCare = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "zordh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "zordh" ) ) != EOF )
{
switch ( c )
{
@@ -5211,19 +5411,19 @@ int Abc_CommandPipe( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
nLatches = 5;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Lh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Lh" ) ) != EOF )
{
switch ( c )
{
case 'L':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-L\" should be followed by a positive integer.\n" );
goto usage;
}
- nLatches = atoi(argv[util_optind]);
- util_optind++;
+ nLatches = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nLatches < 0 )
goto usage;
break;
@@ -5286,8 +5486,8 @@ int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -5364,8 +5564,8 @@ int Abc_CommandUnseq( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fShare = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "sh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF )
{
switch ( c )
{
@@ -5445,19 +5645,19 @@ int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
fInitial = 1;
fVerbose = 0;
nMaxIters = 15;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Ifbivh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Ifbivh" ) ) != EOF )
{
switch ( c )
{
case 'I':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" );
goto usage;
}
- nMaxIters = atoi(argv[util_optind]);
- util_optind++;
+ nMaxIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nMaxIters < 0 )
goto usage;
break;
@@ -5568,19 +5768,19 @@ int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
nMaxIters = 15;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Ivh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF )
{
switch ( c )
{
case 'I':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" );
goto usage;
}
- nMaxIters = atoi(argv[util_optind]);
- util_optind++;
+ nMaxIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nMaxIters < 0 )
goto usage;
break;
@@ -5625,7 +5825,7 @@ int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0 );
+ pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 );
Abc_NtkDelete( pNtkRes );
if ( pNtkNew == NULL )
{
@@ -5692,19 +5892,19 @@ int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
nMaxIters = 15;
fVerbose = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Ivh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF )
{
switch ( c )
{
case 'I':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" );
goto usage;
}
- nMaxIters = atoi(argv[util_optind]);
- util_optind++;
+ nMaxIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nMaxIters < 0 )
goto usage;
break;
@@ -5749,7 +5949,7 @@ int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
- pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0 );
+ pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 );
Abc_NtkDelete( pNtkRes );
if ( pNtkNew == NULL )
{
@@ -5824,19 +6024,19 @@ int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv )
fExdc = 1;
fImp = 0;
fVerbose = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Feivh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Feivh" ) ) != EOF )
{
switch ( c )
{
case 'F':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
goto usage;
}
- nFrames = atoi(argv[util_optind]);
- util_optind++;
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFrames <= 0 )
goto usage;
break;
@@ -5927,8 +6127,8 @@ int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -5983,8 +6183,10 @@ int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
int fSat;
int fVerbose;
int nSeconds;
+ int nConfLimit;
+ int nImpLimit;
- extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds );
+ extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nImpLimit );
extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose );
@@ -5996,22 +6198,46 @@ int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
fSat = 0;
fVerbose = 0;
nSeconds = 20;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "Tsvh" ) ) != EOF )
+ nConfLimit = 10000;
+ nImpLimit = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "TCIsvh" ) ) != EOF )
{
switch ( c )
{
case 'T':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
goto usage;
}
- nSeconds = atoi(argv[util_optind]);
- util_optind++;
+ nSeconds = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nSeconds < 0 )
goto usage;
break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nImpLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nImpLimit < 0 )
+ goto usage;
+ break;
case 's':
fSat ^= 1;
break;
@@ -6023,14 +6249,14 @@ int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- pArgvNew = argv + util_optind;
- nArgcNew = argc - util_optind;
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
return 1;
// perform equivalence checking
if ( fSat )
- Abc_NtkCecSat( pNtk1, pNtk2, nSeconds );
+ Abc_NtkCecSat( pNtk1, pNtk2, nConfLimit, nImpLimit );
else
Abc_NtkCecFraig( pNtk1, pNtk2, nSeconds, fVerbose );
@@ -6039,9 +6265,11 @@ int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: cec [-T num] [-svh] <file1> <file2>\n" );
+ fprintf( pErr, "usage: cec [-T num] [-C num] [-I num] [-svh] <file1> <file2>\n" );
fprintf( pErr, "\t performs combinational equivalence checking\n" );
fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of implications [default = %d]\n", nImpLimit );
fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
@@ -6075,8 +6303,10 @@ int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv )
int fVerbose;
int nFrames;
int nSeconds;
+ int nConfLimit;
+ int nImpLimit;
- extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames );
+ extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nImpLimit, int nFrames );
extern void Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose );
@@ -6089,33 +6319,57 @@ int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv )
fVerbose = 0;
nFrames = 3;
nSeconds = 20;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "FTsvh" ) ) != EOF )
+ nConfLimit = 10000;
+ nImpLimit = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FTCIsvh" ) ) != EOF )
{
switch ( c )
{
case 'F':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
goto usage;
}
- nFrames = atoi(argv[util_optind]);
- util_optind++;
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nFrames <= 0 )
goto usage;
break;
case 'T':
- if ( util_optind >= argc )
+ if ( globalUtilOptind >= argc )
{
fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
goto usage;
}
- nSeconds = atoi(argv[util_optind]);
- util_optind++;
+ nSeconds = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nSeconds < 0 )
goto usage;
break;
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nImpLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nImpLimit < 0 )
+ goto usage;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -6127,14 +6381,14 @@ int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- pArgvNew = argv + util_optind;
- nArgcNew = argc - util_optind;
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
return 1;
// perform equivalence checking
if ( fSat )
- Abc_NtkSecSat( pNtk1, pNtk2, nSeconds, nFrames );
+ Abc_NtkSecSat( pNtk1, pNtk2, nConfLimit, nImpLimit, nFrames );
else
Abc_NtkSecFraig( pNtk1, pNtk2, nSeconds, nFrames, fVerbose );
@@ -6143,13 +6397,15 @@ int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: sec [-F num] [-T num] [-svh] <file1> <file2>\n" );
+ fprintf( pErr, "usage: sec [-F num] [-T num] [-C num] [-I num] [-svh] <file1> <file2>\n" );
fprintf( pErr, "\t performs bounded sequential equivalence checking\n" );
fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" );
fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
fprintf( pErr, "\t-F num : the number of time frames to use [default = %d]\n", nFrames );
fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of implications [default = %d]\n", nImpLimit );
fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
fprintf( pErr, "\t if no files are given, uses the current network and its spec\n");
@@ -6157,6 +6413,137 @@ usage:
return 1;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+ int c;
+ int RetValue;
+ int fVerbose;
+ int fRewrite;
+ int fFraig;
+ int nConfLimit;
+ int nImpLimit;
+ int clk;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fVerbose = 0;
+ fRewrite = 1;
+ fFraig = 1;
+ nConfLimit = 300000;
+ nImpLimit = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "CIrfvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'C':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nConfLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nConfLimit < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nImpLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nImpLimit < 0 )
+ goto usage;
+ break;
+ case 'r':
+ fRewrite ^= 1;
+ break;
+ case 'f':
+ fFraig ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkLatchNum(pNtk) > 0 )
+ {
+ fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" );
+ return 0;
+ }
+ if ( Abc_NtkCoNum(pNtk) != 1 )
+ {
+ fprintf( stdout, "Currently can only solve the miter with one output.\n" );
+ return 0;
+ }
+ if ( Abc_NtkIsSeq(pNtk) )
+ {
+ fprintf( stdout, "This command cannot be applied to the sequential AIG.\n" );
+ return 0;
+ }
+
+ clk = clock();
+
+ if ( Abc_NtkIsStrash(pNtk) )
+ pNtkTemp = Abc_NtkDup( pNtk );
+ else
+ pNtkTemp = Abc_NtkStrash( pNtk, 0, 0 );
+
+ RetValue = Abc_NtkMiterProve( &pNtkTemp, nConfLimit, nImpLimit, fRewrite, fFraig, fVerbose );
+ if ( RetValue == -1 )
+ printf( "UNDECIDED " );
+ else if ( RetValue == 0 )
+ printf( "SATISFIABLE " );
+ else
+ printf( "UNSATISFIABLE " );
+ //printf( "\n" );
+
+ PRT( "Time", clock() - clk );
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: prove [-C num] [-I num] [-rfvh]\n" );
+ fprintf( pErr, "\t solves combinational miter by rewriting, FRAIGing, and SAT\n" );
+ fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit );
+ fprintf( pErr, "\t-I num : limit on the number of implications [default = %d]\n", nImpLimit );
+ fprintf( pErr, "\t-r : toggle the use of rewriting [default = %s]\n", fRewrite? "yes": "no" );
+ fprintf( pErr, "\t-f : toggle the use of FRAIGing [default = %s]\n", fFraig? "yes": "no" );
+ fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/base/abci/abcBalance.c b/src/base/abci/abcBalance.c
index effae853..919ea3b2 100644
--- a/src/base/abci/abcBalance.c
+++ b/src/base/abci/abcBalance.c
@@ -24,8 +24,8 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective );
-static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective );
+static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel );
+static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel );
static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int Level, int fDuplicate, bool fSelective );
static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective );
static void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk );
@@ -45,7 +45,7 @@ static void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk );
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective )
+Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel )
{
Abc_Ntk_t * pNtkAig;
assert( Abc_NtkIsStrash(pNtk) );
@@ -57,7 +57,7 @@ Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective )
}
// perform balancing
pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
- Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate, fSelective );
+ Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate, fSelective, fUpdateLevel );
Abc_NtkFinalize( pNtk, pNtkAig );
// undo the required times
if ( fSelective )
@@ -88,7 +88,7 @@ Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective )
SeeAlso []
***********************************************************************/
-void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective )
+void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel )
{
int fCheck = 1;
ProgressBar * pProgress;
@@ -107,7 +107,7 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica
Extra_ProgressBarUpdate( pProgress, i, NULL );
// strash the driver node
pDriver = Abc_ObjFanin0(pNode);
- Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, 0, fDuplicate, fSelective );
+ Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, 0, fDuplicate, fSelective, fUpdateLevel );
}
Extra_ProgressBarStop( pProgress );
Vec_VecFree( vStorage );
@@ -115,38 +115,93 @@ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplica
/**Function*************************************************************
- Synopsis [Randomizes the node positions.]
+ Synopsis [Finds the left bound on the next candidate to be paired.]
- Description []
+ Description [The nodes in the array are in the decreasing order of levels.
+ The last node in the array has the smallest level. By default it would be paired
+ with the next node on the left. However, it may be possible to pair it with some
+ other node on the left, in such a way that the new node is shared. This procedure
+ finds the index of the left-most node, which can be paired with the last node.]
SideEffects []
SeeAlso []
***********************************************************************/
-void Abc_NodeBalanceRandomize( Vec_Ptr_t * vSuper )
+int Abc_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
{
- Abc_Obj_t * pNode1, * pNode2;
- int i, Signature;
+ Abc_Obj_t * pNodeRight, * pNodeLeft;
+ int Current;
+ // if two or less nodes, pair with the first
if ( Vec_PtrSize(vSuper) < 3 )
+ return 0;
+ // set the pointer to the one before the last
+ Current = Vec_PtrSize(vSuper) - 2;
+ pNodeRight = Vec_PtrEntry( vSuper, Current );
+ // go through the nodes to the left of this one
+ for ( Current--; Current >= 0; Current-- )
+ {
+ // get the next node on the left
+ pNodeLeft = Vec_PtrEntry( vSuper, Current );
+ // if the level of this node is different, quit the loop
+ if ( Abc_ObjRegular(pNodeLeft)->Level != Abc_ObjRegular(pNodeRight)->Level )
+ break;
+ }
+ Current++;
+ // get the node, for which the equality holds
+ pNodeLeft = Vec_PtrEntry( vSuper, Current );
+ assert( Abc_ObjRegular(pNodeLeft)->Level == Abc_ObjRegular(pNodeRight)->Level );
+ return Current;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Moves closer to the end the node that is best for sharing.]
+
+ Description [If there is no node with sharing, randomly chooses one of
+ the legal nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeBalancePermute( Abc_Ntk_t * pNtkNew, Vec_Ptr_t * vSuper, int LeftBound )
+{
+ Abc_Obj_t * pNode1, * pNode2, * pNode3;
+ int RightBound, i;
+ // get the right bound
+ RightBound = Vec_PtrSize(vSuper) - 2;
+ assert( LeftBound <= RightBound );
+ if ( LeftBound == RightBound )
return;
- pNode1 = Vec_PtrEntry( vSuper, Vec_PtrSize(vSuper)-2 );
- pNode2 = Vec_PtrEntry( vSuper, Vec_PtrSize(vSuper)-3 );
- if ( Abc_ObjRegular(pNode1)->Level != Abc_ObjRegular(pNode2)->Level )
- return;
- // some reordering will be performed
- Signature = rand();
- for ( i = Vec_PtrSize(vSuper)-2; i > 0; i-- )
+ // get the two last nodes
+ pNode1 = Vec_PtrEntry( vSuper, RightBound + 1 );
+ pNode2 = Vec_PtrEntry( vSuper, RightBound );
+ // find the first node that can be shared
+ for ( i = RightBound; i >= LeftBound; i-- )
+ {
+ pNode3 = Vec_PtrEntry( vSuper, i );
+ if ( Abc_AigAndLookup( pNtkNew->pManFunc, pNode1, pNode3 ) )
+ {
+ if ( pNode3 == pNode2 )
+ return;
+ Vec_PtrWriteEntry( vSuper, i, pNode2 );
+ Vec_PtrWriteEntry( vSuper, RightBound, pNode3 );
+ return;
+ }
+ }
+/*
+ // we did not find the node to share, randomize choice
{
- pNode1 = Vec_PtrEntry( vSuper, i );
- pNode2 = Vec_PtrEntry( vSuper, i-1 );
- if ( Abc_ObjRegular(pNode1)->Level != Abc_ObjRegular(pNode2)->Level )
+ int Choice = rand() % (RightBound - LeftBound + 1);
+ pNode3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
+ if ( pNode3 == pNode2 )
return;
- if ( Signature & (1 << (i % 10)) )
- continue;
- Vec_PtrWriteEntry( vSuper, i, pNode2 );
- Vec_PtrWriteEntry( vSuper, i-1, pNode1 );
+ Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pNode2 );
+ Vec_PtrWriteEntry( vSuper, RightBound, pNode3 );
}
+*/
}
/**Function*************************************************************
@@ -160,12 +215,12 @@ void Abc_NodeBalanceRandomize( Vec_Ptr_t * vSuper )
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective )
+Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel )
{
Abc_Aig_t * pMan = pNtkNew->pManFunc;
Abc_Obj_t * pNodeNew, * pNode1, * pNode2;
Vec_Ptr_t * vSuper;
- int i;
+ int i, LeftBound;
assert( !Abc_ObjIsComplement(pNodeOld) );
// return if the result if known
if ( pNodeOld->pCopy )
@@ -181,7 +236,7 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_
// for each old node, derive the new well-balanced node
for ( i = 0; i < vSuper->nSize; i++ )
{
- pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), vStorage, Level + 1, fDuplicate, fSelective );
+ pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), vStorage, Level + 1, fDuplicate, fSelective, fUpdateLevel );
vSuper->pArray[i] = Abc_ObjNotCond( pNodeNew, Abc_ObjIsComplement(vSuper->pArray[i]) );
}
if ( vSuper->nSize < 2 )
@@ -192,8 +247,10 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_
assert( vSuper->nSize > 1 );
while ( vSuper->nSize > 1 )
{
- // randomize the node positions
-// Abc_NodeBalanceRandomize( vSuper );
+ // find the left bound on the node to be paired
+ LeftBound = (!fUpdateLevel)? 0 : Abc_NodeBalanceFindLeft( vSuper );
+ // find the node that can be shared (if no such node, randomize choice)
+ Abc_NodeBalancePermute( pNtkNew, vSuper, LeftBound );
// pull out the last two nodes
pNode1 = Vec_PtrPop(vSuper);
pNode2 = Vec_PtrPop(vSuper);
diff --git a/src/base/abci/abcCollapse.c b/src/base/abci/abcClpBdd.c
index 59c76e09..59c76e09 100644
--- a/src/base/abci/abcCollapse.c
+++ b/src/base/abci/abcClpBdd.c
diff --git a/src/base/abci/abcClpSop.c b/src/base/abci/abcClpSop.c
new file mode 100644
index 00000000..de92243f
--- /dev/null
+++ b/src/base/abci/abcClpSop.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+ FileName [abcCollapse.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Collapsing the network into two-levels.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Collapses the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkCollapseSop( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Ntk_t * pNtkNew;
+ pNtkNew = NULL;
+ return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c
index 3e34602d..1ee9a712 100644
--- a/src/base/abci/abcCut.c
+++ b/src/base/abci/abcCut.c
@@ -57,10 +57,41 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk );
assert( Abc_NtkIsStrash(pNtk) );
-
+/*
if ( pParams->fMulti )
- Abc_NtkBalanceAttach(pNtk);
-
+ {
+ Abc_Obj_t * pNode, * pNodeA, * pNodeB, * pNodeC;
+ int nFactors;
+ // lebel the nodes, which will be the roots of factor-cuts
+ // mark the multiple-fanout nodes
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ if ( pNode->vFanouts.nSize > 1 )
+ pNode->fMarkB = 1;
+ // unmark the control inputs of MUXes and inputs of EXOR gates
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ {
+ if ( !Abc_NodeIsMuxType(pNode) )
+ continue;
+
+ pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeA, &pNodeB );
+ // if real children are used, skip
+ if ( Abc_ObjFanin0(pNode)->vFanouts.nSize > 1 || Abc_ObjFanin1(pNode)->vFanouts.nSize > 1 )
+ continue;
+
+ if ( pNodeC->vFanouts.nSize == 2 )
+ pNodeC->fMarkB = 0;
+ if ( Abc_ObjRegular(pNodeA) == Abc_ObjRegular(pNodeB) && Abc_ObjRegular(pNodeA)->vFanouts.nSize == 2 )
+ Abc_ObjRegular(pNodeA)->fMarkB = 0;
+ }
+ // mark the PO drivers
+// Abc_NtkForEachCo( pNtk, pNode, i )
+// Abc_ObjFanin0(pNode)->fMarkB = 1;
+ nFactors = 0;
+ Abc_AigForEachAnd( pNtk, pNode, i )
+ nFactors += pNode->fMarkB;
+ printf( "Total nodes = %6d. Total factors = %6d.\n", Abc_NtkNodeNum(pNtk), nFactors );
+ }
+*/
// start the manager
pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
p = Cut_ManStart( pParams );
@@ -104,8 +135,13 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
}
Vec_PtrFree( vNodes );
Vec_IntFree( vChoices );
+/*
if ( pParams->fMulti )
- Abc_NtkBalanceDetach(pNtk);
+ {
+ Abc_NtkForEachObj( pNtk, pNode, i )
+ pNode->fMarkB = 0;
+ }
+*/
PRT( "Total", clock() - clk );
//Abc_NtkPrintCuts_( p, pNtk, 0 );
// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk );
@@ -282,14 +318,14 @@ printf( "Converged after %d iterations.\n", nIters );
SeeAlso []
***********************************************************************/
-void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj )
+void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fMulti )
{
void * pList;
if ( pList = Abc_NodeReadCuts( p, pObj ) )
return pList;
- Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj) );
- Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj) );
- return Abc_NodeGetCuts( p, pObj, 0 );
+ Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fMulti );
+ Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fMulti );
+ return Abc_NodeGetCuts( p, pObj, fMulti );
}
/**Function*************************************************************
@@ -305,7 +341,8 @@ void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj )
***********************************************************************/
void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fMulti )
{
- int fTriv = (!fMulti) || (pObj->pCopy != NULL);
+// int fTriv = (!fMulti) || pObj->fMarkB;
+ int fTriv = (!fMulti) || (pObj->vFanouts.nSize > 1 && !Abc_NodeIsMuxControlType(pObj));
assert( Abc_NtkIsStrash(pObj->pNtk) );
assert( Abc_ObjFaninNum(pObj) == 2 );
return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
diff --git a/src/base/abci/abcDsd.c b/src/base/abci/abcDsd.c
index a73ab2b5..9dd5ea3a 100644
--- a/src/base/abci/abcDsd.c
+++ b/src/base/abci/abcDsd.c
@@ -446,7 +446,7 @@ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager
/**Function*************************************************************
- Synopsis [Performs decomposition of one node.]
+ Synopsis [Checks if the node should be decomposed by DSD.]
Description []
diff --git a/src/base/abci/abcEspresso.c b/src/base/abci/abcEspresso.c
new file mode 100644
index 00000000..ee6598c9
--- /dev/null
+++ b/src/base/abci/abcEspresso.c
@@ -0,0 +1,244 @@
+/**CFile****************************************************************
+
+ FileName [abcEspresso.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Procedures to minimize SOPs using Espresso.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcEspresso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "espresso.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NodeEspresso( Abc_Obj_t * pNode );
+static pset_family Abc_SopToEspresso( char * pSop );
+static char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover );
+static pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes SOP representations using Espresso.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ assert( Abc_NtkIsLogic(pNtk) );
+ // convert the network to have SOPs
+ if ( Abc_NtkHasMapping(pNtk) )
+ Abc_NtkUnmap(pNtk);
+ else if ( Abc_NtkHasBdd(pNtk) )
+ Abc_NtkBddToSop(pNtk);
+ // minimize SOPs of all nodes
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( i ) Abc_NodeEspresso( pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes SOP representation of one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeEspresso( Abc_Obj_t * pNode )
+{
+ extern void define_cube_size( int n );
+ pset_family Cover;
+ int fCompl;
+
+ assert( Abc_ObjIsNode(pNode) );
+ // define the cube for this node
+ define_cube_size( Abc_ObjFaninNum(pNode) );
+ // create the Espresso cover
+ fCompl = Abc_SopIsComplement( pNode->pData );
+ Cover = Abc_SopToEspresso( pNode->pData );
+ // perform minimization
+ Cover = Abc_EspressoMinimize( Cover, NULL ); // deletes also cover
+ // convert back onto the node's SOP representation
+ pNode->pData = Abc_SopFromEspresso( pNode->pNtk->pManFunc, Cover );
+ if ( fCompl ) Abc_SopComplement( pNode->pData );
+ sf_free(Cover);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts SOP in ABC into SOP representation in Espresso.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+pset_family Abc_SopToEspresso( char * pSop )
+{
+ char * pCube;
+ pset_family Cover;
+ pset set;
+ int nCubes, nVars, Value, v;
+
+ if ( pSop == NULL )
+ return NULL;
+
+ nVars = Abc_SopGetVarNum(pSop);
+ nCubes = Abc_SopGetCubeNum(pSop);
+ assert( cube.size == 2 * nVars );
+
+ if ( Abc_SopIsConst0(pSop) )
+ {
+ Cover = sf_new(0, cube.size);
+ return Cover;
+ }
+ if ( Abc_SopIsConst1(pSop) )
+ {
+ Cover = sf_new(1, cube.size);
+ set = GETSET(Cover, Cover->count++);
+ set_copy( set, cube.fullset );
+ return Cover;
+ }
+
+ // create the cover
+ Cover = sf_new(nCubes, cube.size);
+ // fill in the cubes
+ Abc_SopForEachCube( pSop, nVars, pCube )
+ {
+ set = GETSET(Cover, Cover->count++);
+ set_copy( set, cube.fullset );
+ Abc_CubeForEachVar( pCube, Value, v )
+ {
+ if ( Value == '0' )
+ set_remove(set, 2*v+1);
+ else if ( Value == '1' )
+ set_remove(set, 2*v);
+ }
+ }
+ return Cover;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts SOP representation in Espresso into SOP in ABC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover )
+{
+ pset set;
+ char * pSop, * pCube;
+ int Lit, nVars, nCubes, i, k;
+
+ nVars = Cover->sf_size/2;
+ nCubes = Cover->count;
+
+ pSop = Abc_SopStart( pMan, nCubes, nVars );
+
+ // go through the cubes
+ i = 0;
+ Abc_SopForEachCube( pSop, nVars, pCube )
+ {
+ set = GETSET(Cover, i++);
+ for ( k = 0; k < nVars; k++ )
+ {
+ Lit = GETINPUT(set, k);
+ if ( Lit == ZERO )
+ pCube[k] = '0';
+ else if ( Lit == ONE )
+ pCube[k] = '1';
+ }
+ }
+ return pSop;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes the cover using Espresso.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset )
+{
+ pset_family pOffset;
+ int fNewDcset, i;
+ int fSimple = 0;
+ int fSparse = 0;
+
+ if ( fSimple )
+ {
+ for ( i = 0; i < cube.num_vars; i++ )
+ pOnset = d1merge( pOnset, i );
+ pOnset = sf_contain( pOnset );
+ return pOnset;
+ }
+
+ // create the dcset
+ fNewDcset = (pDcset == NULL);
+ if ( pDcset == NULL )
+ pDcset = sf_new( 1, cube.size );
+ pDcset->wsize = pOnset->wsize;
+ pDcset->sf_size = pOnset->sf_size;
+
+ // derive the offset
+ if ( pDcset->sf_size == 0 || pDcset->count == 0 )
+ pOffset = complement(cube1list(pOnset));
+ else
+ pOffset = complement(cube2list(pOnset, pDcset));
+
+ // perform minimization
+ skip_make_sparse = !fSparse;
+ pOnset = espresso( pOnset, pDcset, pOffset );
+
+ // free covers
+ sf_free( pOffset );
+ if ( fNewDcset )
+ sf_free( pDcset );
+ return pOnset;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcFraig.c b/src/base/abci/abcFraig.c
index d59f21a0..4aae6ba5 100644
--- a/src/base/abci/abcFraig.c
+++ b/src/base/abci/abcFraig.c
@@ -26,7 +26,7 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
static Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
static Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig );
static void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs );
diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c
index 128e054a..39bf15aa 100644
--- a/src/base/abci/abcMap.c
+++ b/src/base/abci/abcMap.c
@@ -105,7 +105,7 @@ clk = clock();
Map_ManFree( pMan );
return NULL;
}
- Map_ManPrintStatsToFile( pNtk->pSpec, Map_ManReadAreaFinal(pMan), Map_ManReadRequiredGlo(pMan), clock()-clk );
+// Map_ManPrintStatsToFile( pNtk->pSpec, Map_ManReadAreaFinal(pMan), Map_ManReadRequiredGlo(pMan), clock()-clk );
// reconstruct the network after mapping
pNtkNew = Abc_NtkFromMap( pMan, pNtk );
diff --git a/src/base/abci/abcMiter.c b/src/base/abci/abcMiter.c
index 44130a20..30fc3a79 100644
--- a/src/base/abci/abcMiter.c
+++ b/src/base/abci/abcMiter.c
@@ -90,7 +90,7 @@ Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
// start the new network
pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG );
sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName );
- pNtkMiter->pName = util_strsav(Buffer);
+ pNtkMiter->pName = Extra_UtilStrsav(Buffer);
// perform strashing
Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb );
@@ -308,7 +308,7 @@ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In
// start the new network
pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG );
sprintf( Buffer, "%s_miter", Abc_ObjName(Abc_NtkCo(pNtk, Out)) );
- pNtkMiter->pName = util_strsav(Buffer);
+ pNtkMiter->pName = Extra_UtilStrsav(Buffer);
// get the root output
pRoot = Abc_NtkCo( pNtk, Out );
@@ -372,7 +372,7 @@ Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist )
// start the new network
pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG );
- pNtkMiter->pName = util_strsav( Abc_ObjName(Abc_NtkCo(pNtk, 0)) );
+ pNtkMiter->pName = Extra_UtilStrsav( Abc_ObjName(Abc_NtkCo(pNtk, 0)) );
// get the root output
pRoot = Abc_NtkCo( pNtk, 0 );
@@ -384,14 +384,16 @@ Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist )
// add the first cofactor
Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
// save the output
- pOutput1 = Abc_ObjFanin0(pRoot)->pCopy;
+// pOutput1 = Abc_ObjFanin0(pRoot)->pCopy;
+ pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) );
// set the second cofactor
Abc_NtkCi(pNtk, In)->pCopy = Abc_NtkConst1( pNtkMiter );
// add the second cofactor
Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot );
// save the output
- pOutput2 = Abc_ObjFanin0(pRoot)->pCopy;
+// pOutput2 = Abc_ObjFanin0(pRoot)->pCopy;
+ pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) );
// create the miter of the two outputs
if ( fExist )
@@ -461,7 +463,7 @@ int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter )
assert( Abc_NtkIsStrash(pMiter) );
Abc_NtkForEachPo( pMiter, pNodePo, i )
{
- pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) );
+ pChild = Abc_ObjChild0( pNodePo );
if ( Abc_ObjIsNode(Abc_ObjRegular(pChild)) && Abc_NodeIsConst(pChild) )
{
assert( Abc_ObjRegular(pChild) == Abc_NtkConst1(pMiter) );
@@ -552,7 +554,7 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial )
// start the new network
pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG );
sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames );
- pNtkFrames->pName = util_strsav(Buffer);
+ pNtkFrames->pName = Extra_UtilStrsav(Buffer);
// create new latches (or their initial values) and remember them in the new latches
if ( !fInitial )
{
@@ -682,7 +684,7 @@ Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFram
// start the new network
pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG );
sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames );
- pNtkFrames->pName = util_strsav(Buffer);
+ pNtkFrames->pName = Extra_UtilStrsav(Buffer);
// create new latches (or their initial values) and remember them in the new latches
if ( !fInitial )
{
diff --git a/src/base/abci/abcNewAig.c b/src/base/abci/abcNewAig.c
index 33f58135..ce76195a 100644
--- a/src/base/abci/abcNewAig.c
+++ b/src/base/abci/abcNewAig.c
@@ -56,9 +56,11 @@ Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk )
{
Aig_Man_t * pMan;
Abc_Ntk_t * pNtkAig;
- Aig_ProofType_t RetValue;
+// Aig_ProofType_t RetValue;
int fCleanup = 1;
int nNodes;
+ extern void Aig_MffcTest( Aig_Man_t * pMan );
+
assert( !Abc_NtkIsNetlist(pNtk) );
assert( !Abc_NtkIsSeq(pNtk) );
@@ -70,6 +72,10 @@ Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk )
// convert to the AIG manager
pMan = Abc_NtkToAig( pNtk );
+
+ Aig_MffcTest( pMan );
+
+/*
// execute a command in the AIG manager
RetValue = Aig_FraigProve( pMan );
if ( RetValue == AIG_PROOF_SAT )
@@ -80,6 +86,7 @@ Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk )
printf( "Undecided.\n" );
else
assert( 0 );
+*/
// convert from the AIG manager
pNtkAig = Abc_NtkFromAig( pNtk, pMan );
@@ -173,6 +180,8 @@ Aig_Man_t * Abc_NtkToAig( Abc_Ntk_t * pNtkOld )
Abc_NtkConst1(pNtkOld)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan);
Abc_NtkForEachCi( pNtkOld, pObj, i )
pObj->pCopy = (Abc_Obj_t *)Aig_NodeCreatePi(pMan);
+ Abc_NtkForEachCo( pNtkOld, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)Aig_NodeCreatePo(pMan);
// perform the conversion of the internal nodes
Abc_NtkStrashPerformAig( pNtkOld, pMan );
// create the POs
@@ -180,7 +189,7 @@ Aig_Man_t * Abc_NtkToAig( Abc_Ntk_t * pNtkOld )
{
pFanin = (Aig_Node_t *)Abc_ObjFanin0(pObj)->pCopy;
pFanin = Aig_NotCond( pFanin, Abc_ObjFaninC0(pObj) );
- pObj->pCopy = (Abc_Obj_t *)Aig_NodeCreatePo( pMan, pFanin );
+ Aig_NodeConnectPo( pMan, (Aig_Node_t *)pObj->pCopy, pFanin );
}
return pMan;
}
diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c
index 6257bd08..b961ec15 100644
--- a/src/base/abci/abcNtbdd.c
+++ b/src/base/abci/abcNtbdd.c
@@ -79,7 +79,7 @@ Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo
// start the network
pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD );
- pNtk->pName = util_strsav(pNamePo);
+ pNtk->pName = Extra_UtilStrsav(pNamePo);
// make sure the new manager has enough inputs
Cudd_bddIthVar( pNtk->pManFunc, Vec_PtrSize(vNamesPi) );
// add the PIs corresponding to the names
diff --git a/src/base/abci/abcProve.c b/src/base/abci/abcProve.c
new file mode 100644
index 00000000..18ee9a3f
--- /dev/null
+++ b/src/base/abci/abcProve.c
@@ -0,0 +1,232 @@
+/**CFile****************************************************************
+
+ FileName [abcProve.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Proves the miter using AIG rewriting, FRAIGing, and SAT solving.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcProve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "fraig.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose );
+extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose );
+extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk );
+
+static Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, int * pRetValue );
+static void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Attempts to solve the miter using a number of tricks.]
+
+ Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT. Returns
+ a simplified version of the original network (or a constant 0 network).
+ In case the network is not a constant zero and a SAT assignment is found,
+ pNtk->pModel contains a satisfying assignment.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, int nConfLimit, int nImpLimit, int fUseRewrite, int fUseFraig, int fVerbose )
+{
+ Abc_Ntk_t * pNtk, * pNtkTemp;
+ int nConfsStart = 1000, nImpsStart = 0, nBTLimitStart = 2;
+ int nConfs, nImps, nBTLimit, RetValue;
+ int nIter = 0, clk, timeStart = clock();
+
+ // get the starting network
+ pNtk = *ppNtk;
+ assert( Abc_NtkIsStrash(pNtk) );
+ assert( Abc_NtkPoNum(pNtk) == 1 );
+
+ // set the initial limits
+ nConfs = !nConfLimit? nConfsStart : ABC_MIN( nConfsStart, nConfLimit );
+ nImps = !nImpLimit ? nImpsStart : ABC_MIN( nImpsStart , nImpLimit );
+ nBTLimit = nBTLimitStart;
+
+ if ( fVerbose )
+ printf( "Global resource limits: ConfsLim = %6d. ImpsLim = %d.\n", nConfLimit, nImpLimit );
+
+ // if SAT only, solve without iteration
+ if ( !fUseRewrite && !fUseFraig )
+ {
+ clk = clock();
+ RetValue = Abc_NtkMiterSat( pNtk, nConfLimit, nImpLimit, 0 );
+ Abc_NtkMiterPrint( pNtk, "SAT solving", clk, fVerbose );
+ *ppNtk = pNtk;
+ return RetValue;
+ }
+
+ // check the current resource limits
+ do {
+ nIter++;
+
+ if ( fVerbose )
+ printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter, nConfs, nBTLimit );
+
+ // try brute-force SAT
+ clk = clock();
+ RetValue = Abc_NtkMiterSat( pNtk, nConfs, nImps, 0 );
+ Abc_NtkMiterPrint( pNtk, "SAT solving", clk, fVerbose );
+ if ( RetValue >= 0 )
+ break;
+
+ if ( fUseRewrite )
+ {
+ clk = clock();
+
+ // try rewriting
+ Abc_NtkRewrite( pNtk, 0, 0, 0 );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+ Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+ pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp );
+ if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 )
+ break;
+
+ Abc_NtkMiterPrint( pNtk, "Rewriting ", clk, fVerbose );
+ }
+
+ if ( fUseFraig )
+ {
+ // try FRAIGing
+ clk = clock();
+ pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, nBTLimit, &RetValue ); Abc_NtkDelete( pNtkTemp );
+ Abc_NtkMiterPrint( pNtk, "FRAIGing ", clk, fVerbose );
+ if ( RetValue >= 0 )
+ break;
+ }
+
+ // increase resource limits
+ nConfs = ABC_MIN( nConfs * 3 / 2, 1000000000 );
+ nImps = ABC_MIN( nImps * 3 / 2, 1000000000 );
+ nBTLimit = ABC_MIN( nBTLimit * 8, 1000000000 );
+
+ // timeout at 5 minutes
+ if ( clock() - timeStart >= 300 * CLOCKS_PER_SEC )
+ break;
+ if ( nIter == 4 )
+ break;
+ }
+ while ( (nConfLimit == 0 || nConfs <= nConfLimit) &&
+ (nImpLimit == 0 || nImps <= nImpLimit ) );
+
+ // try to prove it using brute force SAT
+ if ( RetValue < 0 )
+ {
+ clk = clock();
+ RetValue = Abc_NtkMiterSat( pNtk, nConfLimit, nImpLimit, 0 );
+ Abc_NtkMiterPrint( pNtk, "SAT solving", clk, fVerbose );
+ }
+
+ *ppNtk = pNtk;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attempts to solve the miter using a number of tricks.]
+
+ Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, int * pRetValue )
+{
+ Abc_Ntk_t * pNtkNew;
+ Fraig_Params_t Params, * pParams = &Params;
+ Fraig_Man_t * pMan;
+ int nWords1, nWords2, nWordsMin, RetValue;
+ int * pModel;
+
+ // to determine the number of simulation patterns
+ // use the following strategy
+ // at least 64 words (32 words random and 32 words dynamic)
+ // no more than 256M for one circuit (128M + 128M)
+ nWords1 = 32;
+ nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk));
+ nWordsMin = ABC_MIN( nWords1, nWords2 );
+
+ // set the FRAIGing parameters
+ Fraig_ParamsSetDefault( pParams );
+ pParams->nPatsRand = nWordsMin * 32; // the number of words of random simulation info
+ pParams->nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info
+ pParams->nBTLimit = nBTLimit; // the max number of backtracks
+ pParams->nSeconds = -1; // the runtime limit
+ pParams->fTryProve = 0; // do not try to prove the final miter
+ pParams->fDoSparse = 1; // try proving sparse functions
+ pParams->fVerbose = 0;
+
+ // transform the target into a fraig
+ pMan = Abc_NtkToFraig( pNtk, pParams, 0, 0 );
+ Fraig_ManProveMiter( pMan );
+ RetValue = Fraig_ManCheckMiter( pMan );
+
+ // save model
+ if ( RetValue == 0 )
+ {
+ pModel = Fraig_ManReadModel( pMan );
+ FREE( pNtk->pModel );
+ pNtk->pModel = ALLOC( int, Abc_NtkCiNum(pNtk) );
+ memcpy( pNtk->pModel, pModel, sizeof(int) * Abc_NtkCiNum(pNtk) );
+ }
+ // create the network
+ pNtkNew = Abc_NtkFromFraig( pMan, pNtk );
+ // delete the fraig manager
+ Fraig_ManFree( pMan );
+ *pRetValue = RetValue;
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Attempts to solve the miter using a number of tricks.]
+
+ Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose )
+{
+ if ( !fVerbose )
+ return;
+ printf( "Nodes = %7d. Levels = %4d. ", Abc_NtkNodeNum(pNtk), Abc_AigGetLevelNum(pNtk) );
+ PRT( pString, clock() - clk );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcRenode.c b/src/base/abci/abcRenode.c
index ea2f808c..cfb05aee 100644
--- a/src/base/abci/abcRenode.c
+++ b/src/base/abci/abcRenode.c
@@ -407,7 +407,7 @@ void Abc_NtkRenodeSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax )
continue;
if ( pNode->fMarkA == 0 )
continue;
- // continue cutting branches ntil it meets the fanin limit
+ // continue cutting branches until it meets the fanin limit
while ( Abc_NtkRenodeLimit(pNode, vCone, nFaninMax) );
assert( vCone->nSize <= nFaninMax );
}
diff --git a/src/base/abci/abcRestruct.c b/src/base/abci/abcRestruct.c
new file mode 100644
index 00000000..0b4c80c8
--- /dev/null
+++ b/src/base/abci/abcRestruct.c
@@ -0,0 +1,1026 @@
+/**CFile****************************************************************
+
+ FileName [abcRestruct.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcRestruct.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "dec.h"
+#include "dsd.h"
+#include "cut.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Abc_ManRst_t_ Abc_ManRst_t;
+struct Abc_ManRst_t_
+{
+ // the network
+ Abc_Ntk_t * pNtk; // the network for restructuring
+ // user specified parameters
+ int nCutMax; // the limit on the size of the supernode
+ int fUpdateLevel; // turns on watching the number of levels
+ int fUseZeros; // turns on zero-cost replacements
+ int fVerbose; // the verbosity flag
+ // internal data structures
+ DdManager * dd; // the BDD manager
+ Dsd_Manager_t * pManDsd; // the DSD manager
+ Vec_Ptr_t * vVisited; // temporary
+ Vec_Ptr_t * vLeaves; // temporary
+ Vec_Ptr_t * vDecs; // temporary
+ // node statistics
+ int nLastGain;
+ int nCutsConsidered;
+ int nCutsExplored;
+ int nNodesConsidered;
+ int nNodesRestructured;
+ int nNodesGained;
+ // runtime statistics
+ int timeCut;
+ int timeBdd;
+ int timeDsd;
+ int timeEval;
+ int timeRes;
+ int timeNtk;
+ int timeTotal;
+};
+
+static Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList );
+static Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCut );
+static Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded );
+
+static Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fMulti );
+static Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose );
+static void Abc_NtkManRstStop( Abc_ManRst_t * p );
+static void Abc_NtkManRstPrintStats( Abc_ManRst_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Implements AIG restructuring.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose )
+{
+ ProgressBar * pProgress;
+ Abc_ManRst_t * pManRst;
+ Cut_Man_t * pManCut;
+ Cut_Cut_t * pCutList;
+ Dec_Graph_t * pGraph;
+ Abc_Obj_t * pNode;
+ int clk, clkStart = clock();
+ int fMulti = 1;
+ int i, nNodes;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // cleanup the AIG
+ Abc_AigCleanup(pNtk->pManFunc);
+ Abc_NtkCleanCopy(pNtk);
+
+ // compute the reverse levels if level update is requested
+ if ( fUpdateLevel )
+ Abc_NtkStartReverseLevels( pNtk );
+
+ // start the restructuring manager
+ pManRst = Abc_NtkManRstStart( nCutMax, fUpdateLevel, fUseZeros, fVerbose );
+ pManRst->pNtk = pNtk;
+ // start the cut manager
+clk = clock();
+ pManCut = Abc_NtkStartCutManForRestruct( pNtk, nCutMax, fMulti );
+pManRst->timeCut += clock() - clk;
+// pNtk->pManCut = pManCut;
+
+ // resynthesize each node once
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // skip the constant node
+ if ( Abc_NodeIsConst(pNode) )
+ continue;
+ // skip the node if it is inside the tree
+// if ( Abc_ObjFanoutNum(pNode) < 2 )
+// continue;
+ // skip the nodes with too many fanouts
+ if ( Abc_ObjFanoutNum(pNode) > 1000 )
+ continue;
+ // stop if all nodes have been tried once
+ if ( i >= nNodes )
+ break;
+ // get the cuts for the given node
+clk = clock();
+ pCutList = Abc_NodeGetCutsRecursive( pManCut, pNode, fMulti );
+pManRst->timeCut += clock() - clk;
+ // evaluate these cuts
+clk = clock();
+ pGraph = Abc_NodeRestructure( pManRst, pNode, pCutList );
+pManRst->timeRes += clock() - clk;
+ if ( pGraph == NULL )
+ continue;
+ // acceptable replacement found, update the graph
+clk = clock();
+ Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, pManRst->nLastGain );
+pManRst->timeNtk += clock() - clk;
+ Dec_GraphFree( pGraph );
+ }
+ Extra_ProgressBarStop( pProgress );
+pManRst->timeTotal = clock() - clkStart;
+
+ // print statistics of the manager
+// if ( fVerbose )
+ Abc_NtkManRstPrintStats( pManRst );
+ // delete the managers
+ Cut_ManStop( pManCut );
+ Abc_NtkManRstStop( pManRst );
+ // put the nodes into the DFS order and reassign their IDs
+ Abc_NtkReassignIds( pNtk );
+// Abc_AigCheckFaninOrder( pNtk->pManFunc );
+ // fix the levels
+ if ( fUpdateLevel )
+ Abc_NtkStopReverseLevels( pNtk );
+ else
+ Abc_NtkGetLevelNum( pNtk );
+ // check
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Abc_NtkRefactor: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_RestructNodeDivisors( Abc_ManRst_t * p, Abc_Obj_t * pRoot )
+{
+ Abc_Obj_t * pNode, * pFanin, * pFanout;
+ int i, k;
+ // start with the leaves
+ Vec_PtrClear( p->vDecs );
+ Vec_PtrForEachEntry( p->vLeaves, pNode, i )
+ {
+ Vec_PtrPush( p->vDecs, pNode );
+ assert( pNode->fMarkC == 0 );
+ pNode->fMarkC = 1;
+ }
+ // explore the fanouts
+ Vec_PtrForEachEntry( p->vDecs, pNode, i )
+ {
+ // if the fanout has both fanins in the set, add it
+ Abc_ObjForEachFanout( pNode, pFanout, k )
+ {
+ if ( pFanout->fMarkC || Abc_ObjIsPo(pFanout) )
+ continue;
+ if ( Abc_ObjFanin0(pFanout)->fMarkC && Abc_ObjFanin1(pFanout)->fMarkC )
+ {
+ Vec_PtrPush( p->vDecs, pFanout );
+ pFanout->fMarkC = 1;
+ }
+ }
+ }
+ // unmark the nodes
+ Vec_PtrForEachEntry( p->vDecs, pNode, i )
+ pNode->fMarkC = 0;
+ // print the nodes
+ Vec_PtrForEachEntryStart( p->vDecs, pNode, i, Vec_PtrSize(p->vLeaves) )
+ {
+ printf( "%2d %s = ", i, Abc_NodeIsTravIdCurrent(pNode)? "*" : " " );
+ // find the first fanin
+ Vec_PtrForEachEntry( p->vDecs, pFanin, k )
+ if ( Abc_ObjFanin0(pNode) == pFanin )
+ break;
+ if ( k < Vec_PtrSize(p->vLeaves) )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" );
+ // find the second fanin
+ Vec_PtrForEachEntry( p->vDecs, pFanin, k )
+ if ( Abc_ObjFanin1(pNode) == pFanin )
+ break;
+ if ( k < Vec_PtrSize(p->vLeaves) )
+ printf( "%c", 'a' + k );
+ else
+ printf( "%d", k );
+ printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" );
+ printf( "\n" );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut manager for rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList )
+{
+ Dec_Graph_t * pGraph;
+ Cut_Cut_t * pCut;
+ int nCuts;
+ p->nNodesConsidered++;
+
+ // count the number of cuts with four inputs or more
+ nCuts = 0;
+ for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+ nCuts += (int)(pCut->nLeaves > 3);
+ printf( "-----------------------------------\n" );
+ printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts );
+
+ // go through the interesting cuts
+ for ( pCut = pCutList; pCut; pCut = pCut->pNext )
+ {
+ if ( pCut->nLeaves < 4 )
+ continue;
+ if ( pGraph = Abc_NodeRestructureCut( p, pNode, pCut ) )
+ return pGraph;
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut manager for rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut )
+{
+ Dec_Graph_t * pGraph;
+ Dsd_Node_t * pNodeDsd;
+ Abc_Obj_t * pLeaf;
+ DdNode * bFunc;
+ int nNodesSaved, nNodesAdded;
+ int Required, nMaxSize, clk, i;
+ int fVeryVerbose = 0;
+
+ p->nCutsConsidered++;
+
+ // get the required time for the node
+ Required = p->fUpdateLevel? Abc_NodeReadRequiredLevel(pRoot) : ABC_INFINITY;
+
+ // collect the leaves of the cut
+ Vec_PtrClear( p->vLeaves );
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ pLeaf = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]);
+ if ( pLeaf == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes
+ return NULL;
+ Vec_PtrPush( p->vLeaves, pLeaf );
+ }
+clk = clock();
+ // collect the internal nodes of the cut
+ Abc_NodeConeCollect( &pRoot, 1, p->vLeaves, p->vVisited, 0 );
+ // derive the BDD of the cut
+ bFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pRoot, p->vLeaves, p->vVisited ); Cudd_Ref( bFunc );
+p->timeBdd += clock() - clk;
+
+ // consider the special case, when the function is a constant
+ if ( Cudd_IsConstant(bFunc) )
+ {
+ p->nLastGain = Abc_NodeMffcSize( pRoot );
+ p->nNodesGained += p->nLastGain;
+ p->nNodesRestructured++;
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ if ( Cudd_IsComplement(bFunc) )
+ return Dec_GraphCreateConst0();
+ return Dec_GraphCreateConst1();
+ }
+
+clk = clock();
+ // try disjoint support decomposition
+ pNodeDsd = Dsd_DecomposeOne( p->pManDsd, bFunc );
+p->timeDsd += clock() - clk;
+
+
+ // skip nodes with non-decomposable blocks
+ Dsd_TreeNodeGetInfoOne( pNodeDsd, NULL, &nMaxSize );
+ if ( nMaxSize > 3 )
+ {
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ return NULL;
+ }
+/*
+ // skip nodes that cannot be improved
+ if ( Vec_PtrSize(p->vVisited) <= Dsd_TreeGetAigCost(pNodeDsd) )
+ {
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ return NULL;
+ }
+*/
+
+ p->nCutsExplored++;
+
+ // mark the fanin boundary
+ // (can mark only essential fanins, belonging to bNodeFunc!)
+ Vec_PtrForEachEntry( p->vLeaves, pLeaf, i )
+ pLeaf->vFanouts.nSize++;
+ // label MFFC with current traversal ID
+ Abc_NtkIncrementTravId( pRoot->pNtk );
+ nNodesSaved = Abc_NodeMffcLabel( pRoot );
+ // unmark the fanin boundary and set the fanins as leaves in the form
+ Vec_PtrForEachEntry( p->vLeaves, pLeaf, i )
+ pLeaf->vFanouts.nSize--;
+
+
+ printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d.\n",
+ pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd),
+ nNodesSaved );
+ Dsd_NodePrint( stdout, pNodeDsd );
+
+ Abc_RestructNodeDivisors( p, pRoot );
+
+ if ( pRoot->Id == 433 )
+ {
+ int x = 0;
+ }
+
+ // detect how many new nodes will be added (while taking into account reused nodes)
+clk = clock();
+ pGraph = Abc_NodeEvaluateDsd( p, pNodeDsd, pRoot, Required, nNodesSaved, &nNodesAdded );
+// pGraph = NULL;
+p->timeEval += clock() - clk;
+
+ // quit if there is no improvement
+ if ( nNodesAdded == -1 || nNodesAdded == nNodesSaved && !p->fUseZeros )
+ {
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ if ( pGraph ) Dec_GraphFree( pGraph );
+ return NULL;
+ }
+
+
+ // print stats
+ printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d. New MFFC = %2d. Gain = %d.\n",
+ pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd),
+ nNodesSaved, nNodesAdded, (nNodesAdded == -1)? 0 : nNodesSaved-nNodesAdded );
+// Dsd_NodePrint( stdout, pNodeDsd );
+// Dec_GraphPrint( stdout, pGraph, NULL, NULL );
+
+
+ // compute the total gain in the number of nodes
+ p->nLastGain = nNodesSaved - nNodesAdded;
+ p->nNodesGained += p->nLastGain;
+ p->nNodesRestructured++;
+
+ // report the progress
+ if ( fVeryVerbose )
+ {
+ printf( "Node %6s : ", Abc_ObjName(pRoot) );
+ printf( "Cone = %2d. ", p->vLeaves->nSize );
+ printf( "BDD = %2d. ", Cudd_DagSize(bFunc) );
+ printf( "FF = %2d. ", 1 + Dec_GraphNodeNum(pGraph) );
+ printf( "MFFC = %2d. ", nNodesSaved );
+ printf( "Add = %2d. ", nNodesAdded );
+ printf( "GAIN = %2d. ", p->nLastGain );
+ printf( "\n" );
+ }
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ return pGraph;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Moves closer to the end the node that is best for sharing.]
+
+ Description [If the flag is set, tries to find an EXOR, otherwise, tries
+ to find an OR.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeEdgeDsdPermute( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Vec_Int_t * vEdges, int fExor )
+{
+ Dec_Edge_t eNode1, eNode2, eNode3;
+ Abc_Obj_t * pNode1, * pNode2, * pNode3, * pTemp;
+ int LeftBound = 0, RightBound, i;
+ // get the right bound
+ RightBound = Vec_IntSize(vEdges) - 2;
+ assert( LeftBound <= RightBound );
+ if ( LeftBound == RightBound )
+ return;
+ // get the two last nodes
+ eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound + 1) );
+ eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound ) );
+ pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+ pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+ pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+ pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+ // quit if the last node does not exist
+ if ( pNode1 == NULL )
+ return;
+ // find the first node that can be shared
+ for ( i = RightBound; i >= LeftBound; i-- )
+ {
+ // get the third node
+ eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, i) );
+ pNode3 = Dec_GraphNode( pGraph, eNode3.Node )->pFunc;
+ pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl );
+ if ( pNode3 == NULL )
+ continue;
+ // check if the node exists
+ if ( fExor )
+ {
+ if ( pNode1 && pNode3 )
+ {
+ pTemp = Abc_AigXorLookup( pManRst->pNtk->pManFunc, pNode1, pNode3, NULL );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ continue;
+
+ if ( pNode3 == pNode2 )
+ return;
+ Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) );
+ Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) );
+ return;
+ }
+ }
+ else
+ {
+ if ( pNode1 && pNode3 )
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ continue;
+
+ if ( eNode3.Node == eNode2.Node )
+ return;
+ Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) );
+ Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) );
+ return;
+ }
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the new edge in the given order.]
+
+ Description [Similar to Vec_IntPushOrder, except in decreasing order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeEdgeDsdPushOrdered( Dec_Graph_t * pGraph, Vec_Int_t * vEdges, int Edge )
+{
+ int i, NodeOld, NodeNew;
+ vEdges->nSize++;
+ for ( i = vEdges->nSize-2; i >= 0; i-- )
+ {
+ NodeOld = Dec_IntToEdge(vEdges->pArray[i]).Node;
+ NodeNew = Dec_IntToEdge(Edge).Node;
+ // use <= because we are trying to push the new (non-existent) nodes as far as possible
+ if ( Dec_GraphNode(pGraph, NodeOld)->Level <= Dec_GraphNode(pGraph, NodeNew)->Level )
+ vEdges->pArray[i+1] = vEdges->pArray[i];
+ else
+ break;
+ }
+ vEdges->pArray[i+1] = Edge;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluation one DSD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Edge_t Abc_NodeEvaluateDsd_rec( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, int Required, int nNodesSaved, int * pnNodesAdded )
+{
+ Dec_Edge_t eNode1, eNode2, eNode3, eResult, eQuit = { 0, 2006 };
+ Abc_Obj_t * pNode1, * pNode2, * pNode3, * pNode4, * pTemp;
+ Dsd_Node_t * pChildDsd;
+ Dsd_Type_t DecType;
+ Vec_Int_t * vEdges;
+ int Level1, Level2, Level3, Level4;
+ int i, Index, fCompl, Type;
+
+ // remove the complemented attribute
+ fCompl = Dsd_IsComplement( pNodeDsd );
+ pNodeDsd = Dsd_Regular( pNodeDsd );
+
+ // consider the trivial case
+ DecType = Dsd_NodeReadType( pNodeDsd );
+ if ( DecType == DSD_NODE_BUF )
+ {
+ Index = Dsd_NodeReadFunc(pNodeDsd)->index;
+ assert( Index < Dec_GraphLeaveNum(pGraph) );
+ eResult = Dec_EdgeCreate( Index, fCompl );
+ return eResult;
+ }
+ assert( DecType == DSD_NODE_OR || DecType == DSD_NODE_EXOR || DecType == DSD_NODE_PRIME );
+
+ // solve the problem for the children
+ vEdges = Vec_IntAlloc( Dsd_NodeReadDecsNum(pNodeDsd) );
+ Dsd_NodeForEachChild( pNodeDsd, i, pChildDsd )
+ {
+ eResult = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pChildDsd, Required, nNodesSaved, pnNodesAdded );
+ if ( eResult.Node == eQuit.Node ) // infeasible
+ {
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ // order the inputs only if this is OR or EXOR
+ if ( DecType == DSD_NODE_PRIME )
+ Vec_IntPush( vEdges, Dec_EdgeToInt(eResult) );
+ else
+ Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eResult) );
+ }
+ // the edges are sorted by the level of their nodes in decreasing order
+
+
+ // consider special cases
+ if ( DecType == DSD_NODE_OR )
+ {
+ // try to balance the nodes by delay
+ assert( Vec_IntSize(vEdges) > 1 );
+ while ( Vec_IntSize(vEdges) > 1 )
+ {
+ // permute the last two entries
+ if ( Vec_IntSize(vEdges) > 2 )
+ Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 0 );
+ // get the two last nodes
+ eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+ pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+ pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+ pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+ // check if the new node exists
+ pNode3 = NULL;
+ if ( pNode1 && pNode2 )
+ {
+ pNode3 = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ pNode3 = !pNode3? NULL : Abc_ObjNot(pNode3);
+ }
+ // create the new node
+ eNode3 = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 );
+ // set level
+ Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level;
+ Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level;
+ Dec_GraphNode( pGraph, eNode3.Node )->Level = 1 + ABC_MAX(Level1, Level2);
+ // get the new node if possible
+ if ( pNode3 )
+ {
+ Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl);
+ Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level;
+ assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level );
+ }
+ if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) )
+ {
+ (*pnNodesAdded)++;
+ if ( *pnNodesAdded > nNodesSaved )
+ {
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ }
+ // add the resulting node to the form
+ Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) );
+ }
+ // get the last node
+ eResult = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ Vec_IntFree( vEdges );
+ // complement the graph if the node was complemented
+ eResult.fCompl ^= fCompl;
+ return eResult;
+ }
+ if ( DecType == DSD_NODE_EXOR )
+ {
+ // try to balance the nodes by delay
+ assert( Vec_IntSize(vEdges) > 1 );
+ while ( Vec_IntSize(vEdges) > 1 )
+ {
+ // permute the last two entries
+ if ( Vec_IntSize(vEdges) > 2 )
+ Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 1 );
+ // get the two last nodes
+ eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+ pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+ pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+ pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+ // check if the new node exists
+ Type = 0;
+ pNode3 = NULL;
+ if ( pNode1 && pNode2 )
+ pNode3 = Abc_AigXorLookup( pManRst->pNtk->pManFunc, pNode1, pNode2, &Type );
+ // create the new node
+ eNode3 = Dec_GraphAddNodeXor( pGraph, eNode1, eNode2, Type ); // should have the same structure as in AIG
+ // set level
+ Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level;
+ Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level;
+ Dec_GraphNode( pGraph, eNode3.Node )->Level = 2 + ABC_MAX(Level1, Level2);
+ // get the new node if possible
+ if ( pNode3 )
+ {
+ Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl);
+ Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level;
+ assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level );
+ }
+ if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) )
+ {
+ (*pnNodesAdded)++;
+ if ( !pNode1 || !pNode2 )
+ (*pnNodesAdded) += 2;
+ else if ( Type == 0 )
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode2 );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, pNode2 );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ if ( *pnNodesAdded > nNodesSaved )
+ {
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ }
+ // add the resulting node to the form
+ Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) );
+ }
+ // get the last node
+ eResult = Dec_IntToEdge( Vec_IntPop(vEdges) );
+ Vec_IntFree( vEdges );
+ // complement the graph if the node is complemented
+ eResult.fCompl ^= fCompl;
+ return eResult;
+ }
+ if ( DecType == DSD_NODE_PRIME )
+ {
+ DdNode * bLocal, * bVar, * bCofT, * bCofE;
+ bLocal = Dsd_TreeGetPrimeFunction( pManRst->dd, pNodeDsd ); Cudd_Ref( bLocal );
+//Extra_bddPrint( pManRst->dd, bLocal );
+
+ bVar = pManRst->dd->vars[0];
+ bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE );
+ bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT );
+ if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) )
+ {
+ Cudd_RecursiveDeref( pManRst->dd, bCofE );
+ Cudd_RecursiveDeref( pManRst->dd, bCofT );
+ bVar = pManRst->dd->vars[1];
+ bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE );
+ bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT );
+ if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) )
+ {
+ Cudd_RecursiveDeref( pManRst->dd, bCofE );
+ Cudd_RecursiveDeref( pManRst->dd, bCofT );
+ bVar = pManRst->dd->vars[2];
+ bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE );
+ bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT );
+ if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) )
+ {
+ Cudd_RecursiveDeref( pManRst->dd, bCofE );
+ Cudd_RecursiveDeref( pManRst->dd, bCofT );
+ Cudd_RecursiveDeref( pManRst->dd, bLocal );
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ }
+ }
+ Cudd_RecursiveDeref( pManRst->dd, bLocal );
+ // we found the control variable (bVar) and the var-cofactors (bCofT, bCofE)
+
+ // find the graph nodes
+ eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, bVar->index) );
+ eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofT)->index) );
+ eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofE)->index) );
+ // add the complements to the graph nodes
+ eNode2.fCompl ^= Cudd_IsComplement(bCofT);
+ eNode3.fCompl ^= Cudd_IsComplement(bCofE);
+
+ // because the cofactors are vars, we can just as well deref them here
+ Cudd_RecursiveDeref( pManRst->dd, bCofE );
+ Cudd_RecursiveDeref( pManRst->dd, bCofT );
+
+ // find the ABC nodes
+ pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc;
+ pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc;
+ pNode3 = Dec_GraphNode( pGraph, eNode3.Node )->pFunc;
+ pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl );
+ pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl );
+ pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl );
+
+ // check if the new node exists
+ Type = 0;
+ pNode4 = NULL;
+ if ( pNode1 && pNode2 && pNode3 )
+ pNode4 = Abc_AigMuxLookup( pManRst->pNtk->pManFunc, pNode1, pNode2, pNode3, &Type );
+
+ // create the new node
+ eResult = Dec_GraphAddNodeMux( pGraph, eNode1, eNode2, eNode3, Type ); // should have the same structure as AIG
+
+ // set level
+ Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level;
+ Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level;
+ Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level;
+ Dec_GraphNode( pGraph, eResult.Node )->Level = 2 + ABC_MAX( ABC_MAX(Level1, Level2), Level3 );
+ // get the new node if possible
+ if ( pNode4 )
+ {
+ Dec_GraphNode( pGraph, eResult.Node )->pFunc = Abc_ObjNotCond(pNode4, eResult.fCompl);
+ Level4 = Dec_GraphNode( pGraph, eResult.Node )->Level;
+ assert( Required == ABC_INFINITY || Level4 == (int)Abc_ObjRegular(pNode4)->Level );
+ }
+ if ( !pNode4 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode4)) )
+ {
+ (*pnNodesAdded)++;
+ if ( Type == 0 )
+ {
+ if ( !pNode1 || !pNode2 )
+ (*pnNodesAdded)++;
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, pNode2 );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ if ( !pNode1 || !pNode3 )
+ (*pnNodesAdded)++;
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode3 );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ }
+ else
+ {
+ if ( !pNode1 || !pNode2 )
+ (*pnNodesAdded)++;
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ if ( !pNode1 || !pNode3 )
+ (*pnNodesAdded)++;
+ else
+ {
+ pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) );
+ if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) )
+ (*pnNodesAdded)++;
+ }
+ }
+ if ( *pnNodesAdded > nNodesSaved )
+ {
+ Vec_IntFree( vEdges );
+ return eQuit;
+ }
+ }
+
+ Vec_IntFree( vEdges );
+ // complement the graph if the node was complemented
+ eResult.fCompl ^= fCompl;
+ return eResult;
+ }
+ Vec_IntFree( vEdges );
+ return eQuit;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluation one DSD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t gEdge;
+ Abc_Obj_t * pLeaf;
+ Dec_Node_t * pNode;
+ int i;
+
+ // create the graph and set the leaves
+ pGraph = Dec_GraphCreate( Vec_PtrSize(pManRst->vLeaves) );
+ Dec_GraphForEachLeaf( pGraph, pNode, i )
+ {
+ pLeaf = Vec_PtrEntry( pManRst->vLeaves, i );
+ pNode->pFunc = pLeaf;
+ pNode->Level = pLeaf->Level;
+ }
+
+ // create the decomposition structure from the DSD
+ *pnNodesAdded = 0;
+ gEdge = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pNodeDsd, Required, nNodesSaved, pnNodesAdded );
+ if ( gEdge.Node > 1000 ) // infeasible
+ {
+ *pnNodesAdded = -1;
+ Dec_GraphFree( pGraph );
+ return NULL;
+ }
+
+ // quit if the root node is the same
+ pLeaf = Dec_GraphNode( pGraph, gEdge.Node )->pFunc;
+ if ( Abc_ObjRegular(pLeaf) == pRoot )
+ {
+ *pnNodesAdded = -1;
+ Dec_GraphFree( pGraph );
+ return NULL;
+ }
+
+ Dec_GraphSetRoot( pGraph, gEdge );
+ return pGraph;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut manager for rewriting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fMulti )
+{
+ static Cut_Params_t Params, * pParams = &Params;
+ Cut_Man_t * pManCut;
+ Abc_Obj_t * pObj;
+ int i;
+ // start the cut manager
+ memset( pParams, 0, sizeof(Cut_Params_t) );
+ pParams->nVarsMax = nCutMax; // the max cut size ("k" of the k-feasible cuts)
+ pParams->nKeepMax = 250; // the max number of cuts kept at a node
+ pParams->fTruth = 0; // compute truth tables
+ pParams->fFilter = 1; // filter dominated cuts
+ pParams->fSeq = 0; // compute sequential cuts
+ pParams->fDrop = 0; // drop cuts on the fly
+ pParams->fMulti = fMulti; // compute factor-cuts
+ pParams->fVerbose = 0; // the verbosiness flag
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ pManCut = Cut_ManStart( pParams );
+ if ( pParams->fDrop )
+ Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) );
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( pManCut, pObj->Id );
+ return pManCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose )
+{
+ Abc_ManRst_t * p;
+ p = ALLOC( Abc_ManRst_t, 1 );
+ memset( p, 0, sizeof(Abc_ManRst_t) );
+ // set the parameters
+ p->nCutMax = nCutMax;
+ p->fUpdateLevel = fUpdateLevel;
+ p->fUseZeros = fUseZeros;
+ p->fVerbose = fVerbose;
+ // start the BDD manager
+ p->dd = Cudd_Init( p->nCutMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_zddVarsFromBddVars( p->dd, 2 );
+ // start the DSD manager
+ p->pManDsd = Dsd_ManagerStart( p->dd, p->dd->size, 0 );
+ // other temp datastructures
+ p->vVisited = Vec_PtrAlloc( 100 );
+ p->vLeaves = Vec_PtrAlloc( 100 );
+ p->vDecs = Vec_PtrAlloc( 100 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkManRstStop( Abc_ManRst_t * p )
+{
+ Dsd_ManagerStop( p->pManDsd );
+ Extra_StopManager( p->dd );
+ Vec_PtrFree( p->vDecs );
+ Vec_PtrFree( p->vLeaves );
+ Vec_PtrFree( p->vVisited );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkManRstPrintStats( Abc_ManRst_t * p )
+{
+ printf( "Refactoring statistics:\n" );
+ printf( "Nodes considered = %8d.\n", p->nNodesConsidered );
+ printf( "Cuts considered = %8d.\n", p->nCutsConsidered );
+ printf( "Cuts explored = %8d.\n", p->nCutsExplored );
+ printf( "Nodes restructured = %8d.\n", p->nNodesRestructured );
+ printf( "Calculated gain = %8d.\n", p->nNodesGained );
+ PRT( "Cuts ", p->timeCut );
+ PRT( "Resynthesis", p->timeRes );
+ PRT( " BDD ", p->timeBdd );
+ PRT( " DSD ", p->timeDsd );
+ PRT( " Eval ", p->timeEval );
+ PRT( "AIG update ", p->timeNtk );
+ PRT( "TOTAL ", p->timeTotal );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcRewrite.c b/src/base/abci/abcRewrite.c
index b3b30d9a..f3360421 100644
--- a/src/base/abci/abcRewrite.c
+++ b/src/base/abci/abcRewrite.c
@@ -96,6 +96,14 @@ Rwr_ManAddTimeCuts( pManRwr, clock() - clk );
{
Dec_Graph_t * pGraph = Rwr_ManReadDecs(pManRwr);
int fCompl = Rwr_ManReadCompl(pManRwr);
+/*
+ if ( nGain > 0 )
+ { // print stats on the MFFC
+ extern void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode );
+ printf( "Node %6d : Gain = %4d ", pNode->Id, nGain );
+ Abc_NodeMffsConeSuppPrint( pNode );
+ }
+*/
// complement the FF if needed
if ( fCompl ) Dec_GraphComplement( pGraph );
clk = clock();
diff --git a/src/base/abci/abcSat.c b/src/base/abci/abcSat.c
index 9c650aa9..5376444b 100644
--- a/src/base/abci/abcSat.c
+++ b/src/base/abci/abcSat.c
@@ -24,13 +24,7 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static int Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars );
-static int Abc_NodeAddClausesTop( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars );
-
-static solver * Abc_NtkMiterSatCreate2( Abc_Ntk_t * pNtk );
-
static Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk );
-
static nMuxes;
////////////////////////////////////////////////////////////////////////
@@ -48,13 +42,13 @@ static nMuxes;
SeeAlso []
***********************************************************************/
-int Abc_NtkMiterSat_OldAndRusty( Abc_Ntk_t * pNtk, int nSeconds, int fVerbose )
+int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nConfLimit, int nImpLimit, int fVerbose )
{
solver * pSat;
lbool status;
int RetValue, clk;
- assert( Abc_NtkIsBddLogic(pNtk) );
+ assert( Abc_NtkIsStrash(pNtk) );
assert( Abc_NtkLatchNum(pNtk) == 0 );
if ( Abc_NtkPoNum(pNtk) > 1 )
@@ -84,7 +78,7 @@ int Abc_NtkMiterSat_OldAndRusty( Abc_Ntk_t * pNtk, int nSeconds, int fVerbose )
clk = clock();
if ( fVerbose )
pSat->verbosity = 1;
- status = solver_solve( pSat, NULL, NULL, nSeconds );
+ status = solver_solve( pSat, NULL, NULL, nConfLimit, nImpLimit );
if ( status == l_Undef )
{
// printf( "The problem timed out.\n" );
@@ -107,277 +101,6 @@ int Abc_NtkMiterSat_OldAndRusty( Abc_Ntk_t * pNtk, int nSeconds, int fVerbose )
// if the problem is SAT, get the counterexample
if ( status == l_True )
{
- Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk );
- pNtk->pModel = solver_get_model( pSat, vCiIds->pArray, vCiIds->nSize );
- Vec_IntFree( vCiIds );
- }
- // free the solver
- solver_delete( pSat );
- return RetValue;
-}
-
-/**Function*************************************************************
-
- Synopsis [Sets up the SAT solver.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk )
-{
- solver * pSat;
- Extra_MmFlex_t * pMmFlex;
- Abc_Obj_t * pNode;
- Vec_Str_t * vCube;
- Vec_Int_t * vVars;
- char * pSop0, * pSop1;
- int i, clk = clock();
-
- assert( Abc_NtkIsBddLogic(pNtk) );
-
- // start the data structures
- pSat = solver_new();
- pMmFlex = Extra_MmFlexStart();
- vCube = Vec_StrAlloc( 100 );
- vVars = Vec_IntAlloc( 100 );
-
- // add clauses for each internal nodes
- Abc_NtkForEachNode( pNtk, pNode, i )
- {
- // derive SOPs for both phases of the node
- Abc_NodeBddToCnf( pNode, pMmFlex, vCube, &pSop0, &pSop1 );
- // add the clauses to the solver
- if ( !Abc_NodeAddClauses( pSat, pSop0, pSop1, pNode, vVars ) )
- {
- solver_delete( pSat );
- return NULL;
- }
- }
- // add clauses for the POs
- if ( !Abc_NodeAddClausesTop( pSat, Abc_NtkPo(pNtk, Abc_NtkPoNum(pNtk)-1), vVars ) )
- {
- solver_delete( pSat );
- return NULL;
- }
-// Asat_SolverWriteDimacs( pSat, "test.cnf", NULL, NULL, 0 );
-
- PRT( "Creating solver", clock() - clk );
-
- // delete
- Vec_StrFree( vCube );
- Vec_IntFree( vVars );
- Extra_MmFlexStop( pMmFlex, 0 );
- return pSat;
-}
-
-/**Function*************************************************************
-
- Synopsis [Adds clauses for the internal node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_NodeAddClauses( solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars )
-{
- Abc_Obj_t * pFanin;
- int i, c, nFanins;
- char * pCube;
-
- nFanins = Abc_ObjFaninNum( pNode );
- assert( nFanins == Abc_SopGetVarNum( pSop0 ) );
-
- if ( nFanins == 0 )
- {
- vVars->nSize = 0;
- if ( Abc_SopIsConst1(pSop1) )
- Vec_IntPush( vVars, toLit(pNode->Id) );
- else
- Vec_IntPush( vVars, neg(toLit(pNode->Id)) );
- return solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
- }
-
- // add clauses for the negative phase
- for ( c = 0; ; c++ )
- {
- // get the cube
- pCube = pSop0 + c * (nFanins + 3);
- if ( *pCube == 0 )
- break;
- // add the clause
- vVars->nSize = 0;
- Abc_ObjForEachFanin( pNode, pFanin, i )
- {
- if ( pCube[i] == '0' )
- Vec_IntPush( vVars, toLit(pFanin->Id) );
- else if ( pCube[i] == '1' )
- Vec_IntPush( vVars, neg(toLit(pFanin->Id)) );
- }
- Vec_IntPush( vVars, neg(toLit(pNode->Id)) );
- if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
- return 0;
- }
-
- // add clauses for the positive phase
- for ( c = 0; ; c++ )
- {
- // get the cube
- pCube = pSop1 + c * (nFanins + 3);
- if ( *pCube == 0 )
- break;
- // add the clause
- vVars->nSize = 0;
- Abc_ObjForEachFanin( pNode, pFanin, i )
- {
- if ( pCube[i] == '0' )
- Vec_IntPush( vVars, toLit(pFanin->Id) );
- else if ( pCube[i] == '1' )
- Vec_IntPush( vVars, neg(toLit(pFanin->Id)) );
- }
- Vec_IntPush( vVars, toLit(pNode->Id) );
- if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
- return 0;
- }
- return 1;
-}
-
-/**Function*************************************************************
-
- Synopsis [Adds clauses for the PO node.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_NodeAddClausesTop( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars )
-{
- Abc_Obj_t * pFanin;
-
- pFanin = Abc_ObjFanin0(pNode);
- if ( Abc_ObjFaninC0(pNode) )
- {
- vVars->nSize = 0;
- Vec_IntPush( vVars, toLit(pFanin->Id) );
- Vec_IntPush( vVars, toLit(pNode->Id) );
- if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
- return 0;
-
- vVars->nSize = 0;
- Vec_IntPush( vVars, neg(toLit(pFanin->Id)) );
- Vec_IntPush( vVars, neg(toLit(pNode->Id)) );
- if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
- return 0;
- }
- else
- {
- vVars->nSize = 0;
- Vec_IntPush( vVars, neg(toLit(pFanin->Id)) );
- Vec_IntPush( vVars, toLit(pNode->Id) );
- if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
- return 0;
-
- vVars->nSize = 0;
- Vec_IntPush( vVars, toLit(pFanin->Id) );
- Vec_IntPush( vVars, neg(toLit(pNode->Id)) );
- if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
- return 0;
- }
-
- vVars->nSize = 0;
- Vec_IntPush( vVars, toLit(pNode->Id) );
- return solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
-}
-
-
-
-
-
-
-
-
-
-
-
-/**Function*************************************************************
-
- Synopsis [Attempts to solve the miter using an internal SAT solver.]
-
- Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nSeconds, int fVerbose )
-{
- solver * pSat;
- lbool status;
- int RetValue, clk;
-
- assert( Abc_NtkIsStrash(pNtk) );
- assert( Abc_NtkLatchNum(pNtk) == 0 );
-
- if ( Abc_NtkPoNum(pNtk) > 1 )
- fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) );
-
- // load clauses into the solver
- clk = clock();
- pSat = Abc_NtkMiterSatCreate2( pNtk );
- if ( pSat == NULL )
- return 1;
-// printf( "Created SAT problem with %d variable and %d clauses. ", solver_nvars(pSat), solver_nclauses(pSat) );
-// PRT( "Time", clock() - clk );
-
- // simplify the problem
- clk = clock();
- status = solver_simplify(pSat);
-// printf( "Simplified the problem to %d variables and %d clauses. ", solver_nvars(pSat), solver_nclauses(pSat) );
-// PRT( "Time", clock() - clk );
- if ( status == 0 )
- {
- solver_delete( pSat );
-// printf( "The problem is UNSATISFIABLE after simplification.\n" );
- return 1;
- }
-
- // solve the miter
- clk = clock();
- if ( fVerbose )
- pSat->verbosity = 1;
- status = solver_solve( pSat, NULL, NULL, nSeconds );
- if ( status == l_Undef )
- {
-// printf( "The problem timed out.\n" );
- RetValue = -1;
- }
- else if ( status == l_True )
- {
-// printf( "The problem is SATISFIABLE.\n" );
- RetValue = 0;
- }
- else if ( status == l_False )
- {
-// printf( "The problem is UNSATISFIABLE.\n" );
- RetValue = 1;
- }
- else
- assert( 0 );
- PRT( "SAT solver time", clock() - clk );
-
- // if the problem is SAT, get the counterexample
- if ( status == l_True )
- {
// Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk );
Vec_Int_t * vCiIds = Abc_NtkGetCiSatVarNums( pNtk );
pNtk->pModel = solver_get_model( pSat, vCiIds->pArray, vCiIds->nSize );
@@ -411,7 +134,6 @@ Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk )
}
-
/**Function*************************************************************
@@ -669,7 +391,7 @@ void Abc_NtkCollectSupergate( Abc_Obj_t * pNode, int fStopAtMux, Vec_Ptr_t * vNo
SeeAlso []
***********************************************************************/
-int Abc_NtkMiterSatCreate2Int( solver * pSat, Abc_Ntk_t * pNtk )
+int Abc_NtkMiterSatCreateInt( solver * pSat, Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE;
Vec_Ptr_t * vNodes, * vSuper;
@@ -787,7 +509,7 @@ int Abc_NtkMiterSatCreate2Int( solver * pSat, Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-solver * Abc_NtkMiterSatCreate2( Abc_Ntk_t * pNtk )
+solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk )
{
solver * pSat;
Abc_Obj_t * pNode;
@@ -796,7 +518,7 @@ solver * Abc_NtkMiterSatCreate2( Abc_Ntk_t * pNtk )
nMuxes = 0;
pSat = solver_new();
- RetValue = Abc_NtkMiterSatCreate2Int( pSat, pNtk );
+ RetValue = Abc_NtkMiterSatCreateInt( pSat, pNtk );
Abc_NtkForEachObj( pNtk, pNode, i )
pNode->fMarkA = 0;
// Asat_SolverWriteDimacs( pSat, "temp_sat.cnf", NULL, NULL, 1 );
@@ -805,8 +527,8 @@ solver * Abc_NtkMiterSatCreate2( Abc_Ntk_t * pNtk )
solver_delete(pSat);
return NULL;
}
- printf( "The number of MUXes detected = %d (%5.2f %% of logic). ", nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) );
- PRT( "Creating solver", clock() - clk );
+// printf( "Ands = %6d. Muxes = %6d (%5.2f %%). ", Abc_NtkNodeNum(pNtk), nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) );
+// PRT( "Creating solver", clock() - clk );
return pSat;
}
diff --git a/src/base/abci/abcUnreach.c b/src/base/abci/abcUnreach.c
index 00370002..34757145 100644
--- a/src/base/abci/abcUnreach.c
+++ b/src/base/abci/abcUnreach.c
@@ -285,7 +285,7 @@ Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUn
// start the new network
pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD );
- pNtkNew->pName = util_strsav( "exdc" );
+ pNtkNew->pName = Extra_UtilStrsav( "exdc" );
pNtkNew->pSpec = NULL;
// create PIs corresponding to LOs
diff --git a/src/base/abci/abcVanEijk.c b/src/base/abci/abcVanEijk.c
index f8d659a0..d719df4f 100644
--- a/src/base/abci/abcVanEijk.c
+++ b/src/base/abci/abcVanEijk.c
@@ -517,13 +517,13 @@ Abc_Ntk_t * Abc_NtkVanEijkFrames( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCorresp, int nF
pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG );
if ( fShortNames )
{
- pNtkFrames->pName = util_strsav(pNtk->pName);
- pNtkFrames->pSpec = util_strsav(pNtk->pSpec);
+ pNtkFrames->pName = Extra_UtilStrsav(pNtk->pName);
+ pNtkFrames->pSpec = Extra_UtilStrsav(pNtk->pSpec);
}
else
{
sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames + fAddLast );
- pNtkFrames->pName = util_strsav(Buffer);
+ pNtkFrames->pName = Extra_UtilStrsav(Buffer);
}
// map the constant nodes
Abc_NtkConst1(pNtk)->pCopy = Abc_NtkConst1(pNtkFrames);
@@ -722,7 +722,7 @@ Abc_Ntk_t * Abc_NtkVanEijkDeriveExdc( Abc_Ntk_t * pNtk, Vec_Ptr_t * vClasses )
// start the network
pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc );
- pNtkNew->pName = util_strsav("exdc");
+ pNtkNew->pName = Extra_UtilStrsav("exdc");
pNtkNew->pSpec = NULL;
// map the constant nodes
diff --git a/src/base/abci/abcVanImp.c b/src/base/abci/abcVanImp.c
index 693d0af7..1805378c 100644
--- a/src/base/abci/abcVanImp.c
+++ b/src/base/abci/abcVanImp.c
@@ -878,7 +878,7 @@ Abc_Ntk_t * Abc_NtkVanImpDeriveExdc( Abc_Ntk_t * pNtk, Vec_Ptr_t * vZeros, Vec_I
// start the network
pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc );
- pNtkNew->pName = util_strsav( "exdc" );
+ pNtkNew->pName = Extra_UtilStrsav( "exdc" );
pNtkNew->pSpec = NULL;
// map the constant nodes
diff --git a/src/base/abci/abcVerify.c b/src/base/abci/abcVerify.c
index 99392e48..5c7b525e 100644
--- a/src/base/abci/abcVerify.c
+++ b/src/base/abci/abcVerify.c
@@ -46,7 +46,7 @@ static void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2,
SeeAlso []
***********************************************************************/
-void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds )
+void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nImpLimit )
{
Abc_Ntk_t * pMiter;
Abc_Ntk_t * pCnf;
@@ -87,7 +87,7 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds )
}
// solve the CNF using the SAT solver
- RetValue = Abc_NtkMiterSat( pCnf, nSeconds, 0 );
+ RetValue = Abc_NtkMiterSat( pCnf, nConfLimit, nImpLimit, 0 );
if ( RetValue == -1 )
printf( "Networks are undecided (SAT solver timed out).\n" );
else if ( RetValue == 0 )
@@ -184,7 +184,7 @@ void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fV
SeeAlso []
***********************************************************************/
-void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames )
+void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nImpLimit, int nFrames )
{
Abc_Ntk_t * pMiter;
Abc_Ntk_t * pFrames;
@@ -244,7 +244,7 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFra
}
// solve the CNF using the SAT solver
- RetValue = Abc_NtkMiterSat( pCnf, nSeconds, 0 );
+ RetValue = Abc_NtkMiterSat( pCnf, nConfLimit, nImpLimit, 0 );
if ( RetValue == -1 )
printf( "Networks are undecided (SAT solver timed out).\n" );
else if ( RetValue == 0 )
diff --git a/src/base/abci/module.make b/src/base/abci/module.make
index 5b15641b..3ca188b7 100644
--- a/src/base/abci/module.make
+++ b/src/base/abci/module.make
@@ -2,9 +2,11 @@ SRC += src/base/abci/abc.c \
src/base/abci/abcAttach.c \
src/base/abci/abcAuto.c \
src/base/abci/abcBalance.c \
- src/base/abci/abcCollapse.c \
+ src/base/abci/abcClpBdd.c \
+ src/base/abci/abcClpSop.c \
src/base/abci/abcCut.c \
src/base/abci/abcDsd.c \
+ src/base/abci/abcEspresso.c \
src/base/abci/abcFpga.c \
src/base/abci/abcFraig.c \
src/base/abci/abcFxu.c \
@@ -13,6 +15,7 @@ SRC += src/base/abci/abc.c \
src/base/abci/abcNtbdd.c \
src/base/abci/abcPga.c \
src/base/abci/abcPrint.c \
+ src/base/abci/abcProve.c \
src/base/abci/abcReconv.c \
src/base/abci/abcRefactor.c \
src/base/abci/abcRenode.c \
diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c
index b2a90806..21dba247 100644
--- a/src/base/cmd/cmd.c
+++ b/src/base/cmd/cmd.c
@@ -142,8 +142,8 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv )
{
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -154,7 +154,7 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv )
}
}
- if ( argc != util_optind )
+ if ( argc != globalUtilOptind )
{
goto usage;
}
@@ -188,8 +188,8 @@ int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv )
int c;
int n = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "hn" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "hn" ) ) != EOF )
{
switch ( c )
{
@@ -204,7 +204,7 @@ int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv )
}
}
- for ( i = util_optind; i < argc; i++ )
+ for ( i = globalUtilOptind; i < argc; i++ )
fprintf( pAbc->Out, "%s ", argv[i] );
if ( n )
fprintf( pAbc->Out, "\n" );
@@ -234,8 +234,8 @@ int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv )
{
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "hs" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "hs" ) ) != EOF )
{
switch ( c )
{
@@ -250,7 +250,7 @@ int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv )
}
}
- if ( argc != util_optind )
+ if ( argc != globalUtilOptind )
goto usage;
return -1;
@@ -294,8 +294,8 @@ int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv )
int i, c, num, size;
num = 20;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -309,8 +309,8 @@ int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv )
goto usage;
// get the number of commands to print
- if ( argc == util_optind + 1 )
- num = atoi(argv[util_optind]);
+ if ( argc == globalUtilOptind + 1 )
+ num = atoi(argv[globalUtilOptind]);
// print the commands
size = pAbc->aHistory->nSize;
num = ( num < size ) ? num : size;
@@ -342,8 +342,8 @@ int CmdCommandAlias( Abc_Frame_t * pAbc, int argc, char **argv )
char *key, *value;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -399,8 +399,8 @@ int CmdCommandUnalias( Abc_Frame_t * pAbc, int argc, char **argv )
char *key, *value;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -450,8 +450,8 @@ int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv )
int c;
fPrintAll = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ah" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF )
{
switch ( c )
{
@@ -468,7 +468,7 @@ int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv )
}
}
- if ( argc != util_optind )
+ if ( argc != globalUtilOptind )
goto usage;
CmdCommandPrint( pAbc, fPrintAll );
@@ -503,8 +503,8 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv )
interactive = silent = prompt = echo = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "hipsx" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "hipsx" ) ) != EOF )
{
switch ( c )
{
@@ -529,12 +529,12 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv )
}
/* added to avoid core-dumping when no script file is specified */
- if ( argc == util_optind )
+ if ( argc == globalUtilOptind )
{
goto usage;
}
- lp_file_index = util_optind;
+ lp_file_index = globalUtilOptind;
lp_count = 0;
/*
@@ -568,7 +568,7 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv )
}
else
{
- prompt_string = NIL( char );
+ prompt_string = NULL;
}
/* clear errors -- e.g., EOF reached from stdin */
@@ -602,7 +602,7 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv )
fprintf( pAbc->Out, "abc - > %s", line );
}
command = CmdHistorySubstitution( pAbc, line, &did_subst );
- if ( command == NIL( char ) )
+ if ( command == NULL )
{
status = 1;
break;
@@ -620,8 +620,8 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv )
}
if ( interactive && *line != '\0' )
{
- Cmd_HistoryAddCommand( pAbc, util_strsav(line) );
- if ( pAbc->Hst != NIL( FILE ) )
+ Cmd_HistoryAddCommand( pAbc, Extra_UtilStrsav(line) );
+ if ( pAbc->Hst != NULL )
{
fprintf( pAbc->Hst, "%s\n", line );
( void ) fflush( pAbc->Hst );
@@ -674,8 +674,8 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
char *flag_value, *key, *value;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -703,9 +703,9 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
FREE( value );
}
- flag_value = argc == 2 ? util_strsav( "" ) : util_strsav( argv[2] );
-// flag_value = argc == 2 ? NULL : util_strsav(argv[2]);
- st_insert( pAbc->tFlags, util_strsav(argv[1]), flag_value );
+ flag_value = argc == 2 ? Extra_UtilStrsav( "" ) : Extra_UtilStrsav( argv[2] );
+// flag_value = argc == 2 ? NULL : Extra_UtilStrsav(argv[2]);
+ st_insert( pAbc->tFlags, Extra_UtilStrsav(argv[1]), flag_value );
if ( strcmp( argv[1], "abcout" ) == 0 )
{
@@ -713,7 +713,7 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
fclose( pAbc->Out );
if ( strcmp( flag_value, "" ) == 0 )
flag_value = "-";
- pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NIL( char * ), 0 );
+ pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 );
if ( pAbc->Out == NULL )
pAbc->Out = stdout;
#if HAVE_SETVBUF
@@ -726,7 +726,7 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
fclose( pAbc->Err );
if ( strcmp( flag_value, "" ) == 0 )
flag_value = "-";
- pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NIL( char * ), 0 );
+ pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 );
if ( pAbc->Err == NULL )
pAbc->Err = stderr;
#if HAVE_SETVBUF
@@ -735,15 +735,15 @@ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
}
if ( strcmp( argv[1], "history" ) == 0 )
{
- if ( pAbc->Hst != NIL( FILE ) )
+ if ( pAbc->Hst != NULL )
fclose( pAbc->Hst );
if ( strcmp( flag_value, "" ) == 0 )
- pAbc->Hst = NIL( FILE );
+ pAbc->Hst = NULL;
else
{
- pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NIL( char * ), 0 );
+ pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 );
if ( pAbc->Hst == NULL )
- pAbc->Hst = NIL( FILE );
+ pAbc->Hst = NULL;
}
}
return 0;
@@ -774,8 +774,8 @@ int CmdCommandUnsetVariable( Abc_Frame_t * pAbc, int argc, char **argv )
char *key, *value;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -867,8 +867,8 @@ int CmdCommandRecall( Abc_Frame_t * pAbc, int argc, char **argv )
}
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -979,8 +979,8 @@ int CmdCommandEmpty( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
}
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1021,7 +1021,7 @@ int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv )
Abc_Ntk_t * pNtkTemp;
int id, c;
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1032,12 +1032,12 @@ int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv )
goto usage;
}
}
- if (util_optind <= argc) {
+ if (globalUtilOptind <= argc) {
pNtkTemp = pAbc->pNtk;
pAbc->pNtk = pAbc->pNtkSaved;
pAbc->pNtkSaved = pNtkTemp;
}
- id = atoi(argv[util_optind]);
+ id = atoi(argv[globalUtilOptind]);
pNtkTemp = Cmd_HistoryGetSnapshot(pAbc, id);
if (!pNtkTemp)
fprintf( pAbc->Err, "Snapshot %d does not exist\n", id);
@@ -1095,8 +1095,8 @@ int CmdCommandLs( Abc_Frame_t * pAbc, int argc, char **argv )
int fPrintedNewLine;
char c;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "lb") ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "lb") ) != EOF )
{
switch (c)
{
@@ -1294,7 +1294,7 @@ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv )
if ( pNtk->pSpec )
{
FREE( pNtkNew->pSpec );
- pNtkNew->pSpec = util_strsav( pNtk->pSpec );
+ pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec );
}
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew );
@@ -1430,7 +1430,7 @@ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv )
if ( pNtk->pSpec )
{
FREE( pNtkNew->pSpec );
- pNtkNew->pSpec = util_strsav( pNtk->pSpec );
+ pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec );
}
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew );
diff --git a/src/base/cmd/cmdAlias.c b/src/base/cmd/cmdAlias.c
index beb7a566..0ec3feea 100644
--- a/src/base/cmd/cmdAlias.c
+++ b/src/base/cmd/cmdAlias.c
@@ -45,11 +45,11 @@ void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** arg
int fStatus, i;
pAlias = ALLOC(Abc_Alias, 1);
- pAlias->sName = util_strsav(sName);
+ pAlias->sName = Extra_UtilStrsav(sName);
pAlias->argc = argc;
pAlias->argv = ALLOC(char *, pAlias->argc);
for(i = 0; i < argc; i++)
- pAlias->argv[i] = util_strsav(argv[i]);
+ pAlias->argv[i] = Extra_UtilStrsav(argv[i]);
fStatus = st_insert( pAbc->tAliases, pAlias->sName, (char *) pAlias );
assert(!fStatus);
}
diff --git a/src/base/cmd/cmdApi.c b/src/base/cmd/cmdApi.c
index cc3d5806..7167e22b 100644
--- a/src/base/cmd/cmdApi.c
+++ b/src/base/cmd/cmdApi.c
@@ -57,8 +57,8 @@ void Cmd_CommandAdd( Abc_Frame_t * pAbc, char * sGroup, char * sName, void * pFu
// create the new command
pCommand = ALLOC( Abc_Command, 1 );
- pCommand->sName = util_strsav( sName );
- pCommand->sGroup = util_strsav( sGroup );
+ pCommand->sName = Extra_UtilStrsav( sName );
+ pCommand->sGroup = Extra_UtilStrsav( sGroup );
pCommand->pFunc = pFunc;
pCommand->fChange = fChanges;
fStatus = st_insert( pAbc->tCommands, sName, (char *)pCommand );
diff --git a/src/base/cmd/cmdFlag.c b/src/base/cmd/cmdFlag.c
index 267f8e06..993f2a49 100644
--- a/src/base/cmd/cmdFlag.c
+++ b/src/base/cmd/cmdFlag.c
@@ -35,8 +35,7 @@
Description [The command parser maintains a table of named values. These
are manipulated using the 'set' and 'unset' commands. The value of the
- named flag is returned, or NIL(char) is returned if the flag has not been
- set.]
+ named flag is returned, or NULL is returned if the flag has not been set.]
SideEffects []
@@ -65,9 +64,9 @@ void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, char * key, char * value )
if ( !key )
return;
if ( value )
- newValue = util_strsav(value);
+ newValue = Extra_UtilStrsav(value);
else
- newValue = util_strsav("");
+ newValue = Extra_UtilStrsav("");
// newValue = NULL;
if ( st_delete(pAbc->tFlags, &key, &oldValue) )
FREE(oldValue);
diff --git a/src/base/cmd/cmdHist.c b/src/base/cmd/cmdHist.c
index dae293d7..12750d16 100644
--- a/src/base/cmd/cmdHist.c
+++ b/src/base/cmd/cmdHist.c
@@ -47,7 +47,7 @@ void Cmd_HistoryAddCommand( Abc_Frame_t * p, char * command )
strcpy( Buffer, command );
if ( command[strlen(command)-1] != '\n' )
strcat( Buffer, "\n" );
- Vec_PtrPush( p->aHistory, util_strsav(Buffer) );
+ Vec_PtrPush( p->aHistory, Extra_UtilStrsav(Buffer) );
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/cmd/cmdUtils.c b/src/base/cmd/cmdUtils.c
index 9b7fb49f..47e54bb3 100644
--- a/src/base/cmd/cmdUtils.c
+++ b/src/base/cmd/cmdUtils.c
@@ -121,10 +121,10 @@ int CmdCommandDispatch( Abc_Frame_t * pAbc, int argc, char **argv )
}
// execute the command
- clk = util_cpu_time();
+ clk = Extra_CpuTime();
pFunc = (int (*)(Abc_Frame_t *, int, char **))pCommand->pFunc;
fError = (*pFunc)( pAbc, argc, argv );
- pAbc->TimeCommand += (util_cpu_time() - clk);
+ pAbc->TimeCommand += (Extra_CpuTime() - clk);
// automatic execution of arbitrary command after each command
// usually this is a passive command ...
@@ -270,7 +270,7 @@ int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop )
}
for ( i = 1; i <= added; i++ )
{
- argv[i] = NIL( char );
+ argv[i] = NULL;
}
argc += added;
}
@@ -278,7 +278,7 @@ int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop )
for ( i = 0, offset = 0; i < alias->argc; i++, offset++ )
{
arg = CmdHistorySubstitution( pAbc, alias->argv[i], &did_subst );
- if ( arg == NIL( char ) )
+ if ( arg == NULL )
{
*argcp = argc;
*argvp = argv;
@@ -383,11 +383,11 @@ FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFi
if (strcmp(sFileName, "-") == 0) {
if (strcmp(sMode, "w") == 0) {
- sRealName = util_strsav( "stdout" );
+ sRealName = Extra_UtilStrsav( "stdout" );
pFile = stdout;
}
else {
- sRealName = util_strsav( "stdin" );
+ sRealName = Extra_UtilStrsav( "stdin" );
pFile = stdin;
}
}
@@ -403,24 +403,24 @@ FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFi
sPathAll = NULL;
}
else if ( sPathUsr == NULL ) {
- sPathAll = util_strsav( sPathLib );
+ sPathAll = Extra_UtilStrsav( sPathLib );
}
else if ( sPathLib == NULL ) {
- sPathAll = util_strsav( sPathUsr );
+ sPathAll = Extra_UtilStrsav( sPathUsr );
}
else {
sPathAll = ALLOC( char, strlen(sPathLib)+strlen(sPathUsr)+5 );
sprintf( sPathAll, "%s:%s",sPathUsr, sPathLib );
}
- if ( sPathAll != NIL(char) ) {
- sRealName = util_file_search(sFileName, sPathAll, "r");
+ if ( sPathAll != NULL ) {
+ sRealName = Extra_UtilFileSearch(sFileName, sPathAll, "r");
FREE( sPathAll );
}
}
- if (sRealName == NIL(char)) {
- sRealName = util_tilde_expand(sFileName);
+ if (sRealName == NULL) {
+ sRealName = Extra_UtilTildeExpand(sFileName);
}
- if ((pFile = fopen(sRealName, sMode)) == NIL(FILE)) {
+ if ((pFile = fopen(sRealName, sMode)) == NULL) {
if (! silent) {
perror(sRealName);
}
diff --git a/src/base/io/io.c b/src/base/io/io.c
index 69b60000..2725eb8a 100644
--- a/src/base/io/io.c
+++ b/src/base/io/io.c
@@ -120,8 +120,8 @@ int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -135,13 +135,13 @@ int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
@@ -192,8 +192,8 @@ int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -207,13 +207,13 @@ int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
@@ -265,8 +265,8 @@ int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -280,13 +280,13 @@ int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
@@ -346,8 +346,8 @@ int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -361,13 +361,13 @@ int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
@@ -426,8 +426,8 @@ int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -441,13 +441,13 @@ int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
@@ -506,8 +506,8 @@ int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -521,13 +521,13 @@ int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
@@ -586,8 +586,8 @@ int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -601,13 +601,13 @@ int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
@@ -666,8 +666,8 @@ int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
fCheck = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "ch" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF )
{
switch ( c )
{
@@ -681,13 +681,13 @@ int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName );
@@ -745,8 +745,8 @@ int IoCommandReadTruth( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
fHex = 0;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "xh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "xh" ) ) != EOF )
{
switch ( c )
{
@@ -760,16 +760,16 @@ int IoCommandReadTruth( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// convert truth table to SOP
if ( fHex )
- pSopCover = Abc_SopFromTruthHex(argv[util_optind]);
+ pSopCover = Abc_SopFromTruthHex(argv[globalUtilOptind]);
else
- pSopCover = Abc_SopFromTruthBin(argv[util_optind]);
+ pSopCover = Abc_SopFromTruthBin(argv[globalUtilOptind]);
if ( pSopCover == NULL )
{
fprintf( pAbc->Err, "Reading truth table has failed.\n" );
@@ -814,8 +814,8 @@ int IoCommandWriteBaf( Abc_Frame_t * pAbc, int argc, char **argv )
char * FileName;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
{
switch ( c )
{
@@ -833,11 +833,11 @@ int IoCommandWriteBaf( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
// check the network type
if ( !Abc_NtkIsStrash(pNtk) )
@@ -875,8 +875,8 @@ int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv )
int c;
fWriteLatches = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
{
switch ( c )
{
@@ -897,11 +897,11 @@ int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
// check the network type
if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSeq(pNtk) )
@@ -941,8 +941,8 @@ int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv )
int c;
fWriteLatches = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "lh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF )
{
switch ( c )
{
@@ -963,12 +963,12 @@ int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( !Abc_NtkIsStrash(pNtk) )
{
@@ -1012,8 +1012,8 @@ int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv )
char * FileName;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1026,17 +1026,22 @@ int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv )
if ( pAbc->pNtkCur == NULL )
{
- fprintf( pAbc->Out, "Empty network.\n" );
+ printf( "Empty network.\n" );
return 0;
}
+ if ( !Abc_NtkIsStrash(pAbc->pNtkCur) )
+ {
+ printf( "This command can only be applied to an AIG (run \"strash\").\n" );
+ return 1;
+ }
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
// write the file
if ( !Io_WriteCnf( pAbc->pNtkCur, FileName ) )
{
@@ -1070,8 +1075,8 @@ int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv )
Vec_Ptr_t * vNodes;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1094,13 +1099,13 @@ int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
// write the file
vNodes = Abc_NtkCollectObjects( pAbc->pNtkCur );
Io_WriteDotAig( pAbc->pNtkCur, vNodes, NULL, FileName, 0 );
@@ -1132,8 +1137,8 @@ int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv )
char * FileName;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1151,7 +1156,7 @@ int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
@@ -1163,7 +1168,7 @@ int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv )
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
// write the file
// get rid of complemented covers if present
if ( Abc_NtkIsSopLogic(pNtk) )
@@ -1203,8 +1208,8 @@ int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv )
char * FileName;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1227,13 +1232,13 @@ int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
// write the file
Io_WriteGml( pAbc->pNtkCur, FileName );
return 0;
@@ -1264,8 +1269,8 @@ int IoCommandWriteList( Abc_Frame_t * pAbc, int argc, char **argv )
int c;
fUseHost = 1;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "nh" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF )
{
switch ( c )
{
@@ -1291,13 +1296,13 @@ int IoCommandWriteList( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
// write the file
Io_WriteList( pAbc->pNtkCur, FileName, fUseHost );
return 0;
@@ -1328,8 +1333,8 @@ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv )
char * FileName;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1359,12 +1364,12 @@ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
// derive the netlist
pNtkTemp = Abc_NtkLogicToNetlist(pNtk);
@@ -1402,8 +1407,8 @@ int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv )
char * FileName;
int c;
- util_getopt_reset();
- while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
@@ -1421,12 +1426,12 @@ int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv )
return 0;
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
// derive the netlist
pNtkTemp = Abc_NtkLogicToNetlist(pNtk);
diff --git a/src/base/io/ioReadBaf.c b/src/base/io/ioReadBaf.c
index 2d6c3ca6..e2aa2109 100644
--- a/src/base/io/ioReadBaf.c
+++ b/src/base/io/ioReadBaf.c
@@ -74,8 +74,8 @@ Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck )
// allocate the empty AIG
pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG );
- pNtkNew->pName = util_strsav( pName );
- pNtkNew->pSpec = util_strsav( pFileName );
+ pNtkNew->pName = Extra_UtilStrsav( pName );
+ pNtkNew->pSpec = Extra_UtilStrsav( pFileName );
// prepare the array of nodes
vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds );
diff --git a/src/base/io/ioReadBlif.c b/src/base/io/ioReadBlif.c
index c05f444e..39b85a10 100644
--- a/src/base/io/ioReadBlif.c
+++ b/src/base/io/ioReadBlif.c
@@ -230,7 +230,7 @@ Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p )
vTokens->nSize--;
// load them into the new array
for ( i = 0; i < vTokens->nSize; i++ )
- Vec_PtrPush( p->vNewTokens, util_strsav(vTokens->pArray[i]) );
+ Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) );
// load as long as there is the line break
while ( 1 )
@@ -249,12 +249,12 @@ Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p )
vTokens->nSize--;
// load them into the new array
for ( i = 0; i < vTokens->nSize; i++ )
- Vec_PtrPush( p->vNewTokens, util_strsav(vTokens->pArray[i]) );
+ Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) );
continue;
}
// otherwise, load them and break
for ( i = 0; i < vTokens->nSize; i++ )
- Vec_PtrPush( p->vNewTokens, util_strsav(vTokens->pArray[i]) );
+ Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) );
break;
}
return p->vNewTokens;
@@ -294,8 +294,8 @@ Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p )
pModelName = vTokens->pArray[1];
// allocate the empty network
p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP );
- p->pNtk->pName = util_strsav( pModelName );
- p->pNtk->pSpec = util_strsav( p->pFileName );
+ p->pNtk->pName = Extra_UtilStrsav( pModelName );
+ p->pNtk->pSpec = Extra_UtilStrsav( p->pFileName );
}
else
p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP );
@@ -681,7 +681,7 @@ int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens )
return 1;
}
// set the arrival time
- Abc_NtkTimeSetArrival( p->pNtk, pNet->Id, (float)TimeRise, (float)TimeFall );
+ Abc_NtkTimeSetArrival( p->pNtk, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall );
return 0;
}
diff --git a/src/base/io/ioReadEdif.c b/src/base/io/ioReadEdif.c
index f100a45f..3bdf2567 100644
--- a/src/base/io/ioReadEdif.c
+++ b/src/base/io/ioReadEdif.c
@@ -181,7 +181,7 @@ Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p )
else if ( strcmp( vTokens->pArray[0], "design" ) == 0 )
{
free( pNtk->pName );
- pNtk->pName = util_strsav( vTokens->pArray[3] );
+ pNtk->pName = Extra_UtilStrsav( vTokens->pArray[3] );
break;
}
}
diff --git a/src/base/io/ioReadEqn.c b/src/base/io/ioReadEqn.c
index a5a46f40..4fb313f4 100644
--- a/src/base/io/ioReadEqn.c
+++ b/src/base/io/ioReadEqn.c
@@ -145,7 +145,7 @@ Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p )
continue;
}
// determine unique variables
- pCubesCopy = util_strsav( pCubesCopy );
+ pCubesCopy = Extra_UtilStrsav( pCubesCopy );
// find the names of the fanins of this node
Io_ReadEqnStrCutAt( pCubesCopy, "!*+", 1, vVars );
// create the node
diff --git a/src/base/io/ioReadVerilog.c b/src/base/io/ioReadVerilog.c
index 58071e39..a4610cac 100644
--- a/src/base/io/ioReadVerilog.c
+++ b/src/base/io/ioReadVerilog.c
@@ -272,8 +272,8 @@ Abc_Ntk_t * Io_ReadVerNetwork( Io_ReadVer_t * p )
// allocate the empty network
pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP );
- pNtk->pName = util_strsav( pModelName );
- pNtk->pSpec = util_strsav( p->pFileName );
+ pNtk->pName = Extra_UtilStrsav( pModelName );
+ pNtk->pSpec = Extra_UtilStrsav( p->pFileName );
// create constant nodes and nets
Abc_NtkFindOrCreateNet( pNtk, "1'b0" );
@@ -334,7 +334,7 @@ Abc_Ntk_t * Io_ReadVerNetwork( Io_ReadVer_t * p )
}
// add the tri-state element to the skipped ones
sprintf( Buffer, "%s %s", vTokens->pArray[0], vTokens->pArray[1] );
- Vec_PtrPush( p->vSkipped, util_strsav(Buffer) );
+ Vec_PtrPush( p->vSkipped, Extra_UtilStrsav(Buffer) );
}
Extra_ProgressBarStop( pProgress );
diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c
index e817bee8..fc37bc3f 100644
--- a/src/base/io/ioUtil.c
+++ b/src/base/io/ioUtil.c
@@ -223,7 +223,7 @@ FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mo
{
char ActualFileName[4096];
FILE * fp = 0;
- t = util_strsav( c );
+ t = Extra_UtilStrsav( c );
for (i = strtok( t, ":" ); i != 0; i = strtok( 0, ":") )
{
#ifdef WIN32
diff --git a/src/base/io/ioWriteCnf.c b/src/base/io/ioWriteCnf.c
index f2131257..9e5ceb9f 100644
--- a/src/base/io/ioWriteCnf.c
+++ b/src/base/io/ioWriteCnf.c
@@ -42,19 +42,19 @@
int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName )
{
solver * pSat;
- if ( !Abc_NtkIsBddLogic(pNtk) )
+ if ( !Abc_NtkIsStrash(pNtk) )
{
- fprintf( stdout, "Io_WriteCnf(): Currently can only process logic networks with BDDs.\n" );
+ fprintf( stdout, "Io_WriteCnf(): Currently can only process AIGs.\n" );
return 0;
}
if ( Abc_NtkPoNum(pNtk) != 1 )
{
- fprintf( stdout, "Io_WriteCnf(): Currently can only solve the miter (the network with one PO).\n" );
+ fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter (the network with one PO).\n" );
return 0;
}
if ( Abc_NtkLatchNum(pNtk) != 0 )
{
- fprintf( stdout, "Io_WriteCnf(): Currently can only solve the miter for combinational circuits.\n" );
+ fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter for combinational circuits.\n" );
return 0;
}
// create solver with clauses
diff --git a/src/base/main/main.c b/src/base/main/main.c
index a9f27bf8..1c6cbcb0 100644
--- a/src/base/main/main.c
+++ b/src/base/main/main.c
@@ -75,21 +75,21 @@ int main( int argc, char * argv[] )
sprintf( sReadCmd, "read" );
sprintf( sWriteCmd, "write" );
- util_getopt_reset();
- while ((c = util_getopt(argc, argv, "c:hf:F:o:st:T:x")) != EOF) {
+ Extra_UtilGetoptReset();
+ while ((c = Extra_UtilGetopt(argc, argv, "c:hf:F:o:st:T:x")) != EOF) {
switch(c) {
case 'c':
- strcpy( sCommandUsr, util_optarg );
+ strcpy( sCommandUsr, globalUtilOptarg );
fBatch = 1;
break;
case 'f':
- sprintf(sCommandUsr, "source %s", util_optarg);
+ sprintf(sCommandUsr, "source %s", globalUtilOptarg);
fBatch = 1;
break;
case 'F':
- sprintf(sCommandUsr, "source -x %s", util_optarg);
+ sprintf(sCommandUsr, "source -x %s", globalUtilOptarg);
fBatch = 1;
break;
@@ -98,7 +98,7 @@ int main( int argc, char * argv[] )
break;
case 'o':
- sOutFile = util_optarg;
+ sOutFile = globalUtilOptarg;
fFinalWrite = 1;
break;
@@ -107,12 +107,12 @@ int main( int argc, char * argv[] )
break;
case 't':
- if ( TypeCheck( pAbc, util_optarg ) )
+ if ( TypeCheck( pAbc, globalUtilOptarg ) )
{
- if ( !strcmp(util_optarg, "none") == 0 )
+ if ( !strcmp(globalUtilOptarg, "none") == 0 )
{
fInitRead = 1;
- sprintf( sReadCmd, "read_%s", util_optarg );
+ sprintf( sReadCmd, "read_%s", globalUtilOptarg );
}
}
else {
@@ -122,12 +122,12 @@ int main( int argc, char * argv[] )
break;
case 'T':
- if ( TypeCheck( pAbc, util_optarg ) )
+ if ( TypeCheck( pAbc, globalUtilOptarg ) )
{
- if (!strcmp(util_optarg, "none") == 0)
+ if (!strcmp(globalUtilOptarg, "none") == 0)
{
fFinalWrite = 1;
- sprintf( sWriteCmd, "write_%s", util_optarg);
+ sprintf( sWriteCmd, "write_%s", globalUtilOptarg);
}
}
else {
@@ -151,14 +151,14 @@ int main( int argc, char * argv[] )
{
pAbc->fBatchMode = 1;
- if (argc - util_optind == 0)
+ if (argc - globalUtilOptind == 0)
{
sInFile = NULL;
}
- else if (argc - util_optind == 1)
+ else if (argc - globalUtilOptind == 1)
{
fInitRead = 1;
- sInFile = argv[util_optind];
+ sInFile = argv[globalUtilOptind];
}
else
{
@@ -221,10 +221,7 @@ int main( int argc, char * argv[] )
// if the memory should be freed, quit packages
if ( fStatus < 0 )
{
- // perform uninitializations
- Abc_FrameEnd( pAbc );
- // stop the framework
- Abc_FrameDeallocate( pAbc );
+ Abc_Stop();
}
return 0;
@@ -250,16 +247,12 @@ usage:
void Abc_Start()
{
Abc_Frame_t * pAbc;
-
// added to detect memory leaks:
#ifdef _DEBUG
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
-
- // get global frame (singleton pattern)
- // will be initialized on first call
+ // start the glocal frame
pAbc = Abc_FrameGetGlobalFrame();
-
// source the resource file
// Abc_UtilsSource( pAbc );
}
@@ -278,17 +271,11 @@ void Abc_Start()
void Abc_Stop()
{
Abc_Frame_t * pAbc;
- int fStatus = 0;
-
- // if the memory should be freed, quit packages
- if ( fStatus == -2 )
- {
- pAbc = Abc_FrameGetGlobalFrame();
- // perform uninitializations
- Abc_FrameEnd( pAbc );
- // stop the framework
- Abc_FrameDeallocate( pAbc );
- }
+ pAbc = Abc_FrameGetGlobalFrame();
+ // perform uninitializations
+ Abc_FrameEnd( pAbc );
+ // stop the framework
+ Abc_FrameDeallocate( pAbc );
}
/**Function********************************************************************
diff --git a/src/base/main/main.h b/src/base/main/main.h
index c5f311aa..d5a463f5 100644
--- a/src/base/main/main.h
+++ b/src/base/main/main.h
@@ -40,17 +40,10 @@ typedef struct Abc_Frame_t_ Abc_Frame_t;
// it is used to catch memory leaks on Windows
#include "leaks.h"
-// standard includes
-#include <stdio.h>
-#include <string.h>
-
-// includes from GLU
-#include "util.h"
-#include "st.h"
-
// data structure packages
#include "extra.h"
#include "vec.h"
+#include "st.h"
// core packages
#include "abc.h"
diff --git a/src/base/main/mainFrame.c b/src/base/main/mainFrame.c
index e9e243af..b3208740 100644
--- a/src/base/main/mainFrame.c
+++ b/src/base/main/mainFrame.c
@@ -48,8 +48,8 @@ int Abc_FrameReadNtkStoreSize() { return s_GlobalFrame->nSt
void * Abc_FrameReadLibLut() { return s_GlobalFrame->pLibLut; }
void * Abc_FrameReadLibGen() { return s_GlobalFrame->pLibGen; }
void * Abc_FrameReadLibSuper() { return s_GlobalFrame->pLibSuper; }
-void * Abc_FrameReadManDd() { return s_GlobalFrame->dd; }
-void * Abc_FrameReadManDec() { return s_GlobalFrame->pManDec; }
+void * Abc_FrameReadManDd() { if ( s_GlobalFrame->dd == NULL ) s_GlobalFrame->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); return s_GlobalFrame->dd; }
+void * Abc_FrameReadManDec() { if ( s_GlobalFrame->pManDec == NULL ) s_GlobalFrame->pManDec = Dec_ManStart(); return s_GlobalFrame->pManDec; }
char * Abc_FrameReadFlag( char * pFlag ) { return Cmd_FlagReadByName( s_GlobalFrame, pFlag ); }
void Abc_FrameSetNtkStore( Abc_Ntk_t * pNtk ) { s_GlobalFrame->pStored = pNtk; }
@@ -97,7 +97,8 @@ bool Abc_FrameIsFlagEnabled( char * pFlag )
Abc_Frame_t * Abc_FrameAllocate()
{
Abc_Frame_t * p;
-
+ extern void define_cube_size( int n );
+ extern void set_espresso_flags();
// allocate and clean
p = ALLOC( Abc_Frame_t, 1 );
memset( p, 0, sizeof(Abc_Frame_t) );
@@ -111,8 +112,8 @@ Abc_Frame_t * Abc_FrameAllocate()
p->nSteps = 1;
p->fBatchMode = 0;
// initialize decomposition manager
- p->pManDec = Dec_ManStart();
- p->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ define_cube_size(20);
+ set_espresso_flags();
return p;
}
@@ -130,11 +131,13 @@ Abc_Frame_t * Abc_FrameAllocate()
***********************************************************************/
void Abc_FrameDeallocate( Abc_Frame_t * p )
{
- Dec_ManStop( p->pManDec );
- Extra_StopManager( p->dd );
+ extern void undefine_cube_size();
+ undefine_cube_size();
+ if ( p->pManDec ) Dec_ManStop( p->pManDec );
+ if ( p->dd ) Extra_StopManager( p->dd );
Abc_FrameDeleteAllNetworks( p );
free( p );
- p = NULL;
+ s_GlobalFrame = NULL;
}
/**Function*************************************************************
diff --git a/src/base/main/mainUtils.c b/src/base/main/mainUtils.c
index aa8b63d0..3d0bdc33 100644
--- a/src/base/main/mainUtils.c
+++ b/src/base/main/mainUtils.c
@@ -139,8 +139,8 @@ void Abc_UtilsSource( Abc_Frame_t * pAbc )
// If .rc is present in both the home and current directories, then read
// it from the home directory. Otherwise, read it from wherever it's located.
- sPath1 = util_file_search(".rc", "~/", "r");
- sPath2 = util_file_search(".rc", ".", "r");
+ sPath1 = Extra_UtilFileSearch(".rc", "~/", "r");
+ sPath2 = Extra_UtilFileSearch(".rc", ".", "r");
if ( sPath1 && sPath2 ) {
/* ~/.rc == .rc : Source the file only once */
diff --git a/src/base/seq/seqAigCore.c b/src/base/seq/seqAigCore.c
index ed2a33fc..e74f3fa7 100644
--- a/src/base/seq/seqAigCore.c
+++ b/src/base/seq/seqAigCore.c
@@ -343,7 +343,7 @@ int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int
}
// get the miter cone
- pNtkMiter = Abc_NtkCreateCone( pNtkProb, pNtkProb->vCos, vValues );
+ pNtkMiter = Abc_NtkCreateTarget( pNtkProb, pNtkProb->vCos, vValues );
Abc_NtkDelete( pNtkProb );
Vec_IntFree( vValues );
@@ -358,7 +358,7 @@ int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int
// solve the miter
clk = clock();
// RetValue = Abc_NtkMiterSat_OldAndRusty( pNtkCnf, 30, 0 );
- RetValue = Abc_NtkMiterSat( pNtkCnf, 30, 0 );
+ RetValue = Abc_NtkMiterSat( pNtkCnf, 500000, 50000000, 0 );
if ( fVerbose )
if ( clock() - clk > 100 )
{
diff --git a/src/base/seq/seqCreate.c b/src/base/seq/seqCreate.c
index d94e8e82..b0c2e084 100644
--- a/src/base/seq/seqCreate.c
+++ b/src/base/seq/seqCreate.c
@@ -88,8 +88,8 @@ Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk )
// start the network
pNtkNew = Abc_NtkAlloc( ABC_NTK_SEQ, ABC_FUNC_AIG );
// duplicate the name and the spec
- pNtkNew->pName = util_strsav(pNtk->pName);
- pNtkNew->pSpec = util_strsav(pNtk->pSpec);
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+ pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
// map the constant nodes
Abc_NtkCleanCopy( pNtk );
diff --git a/src/base/seq/seqRetCore.c b/src/base/seq/seqRetCore.c
index b4795039..4aba069d 100644
--- a/src/base/seq/seqRetCore.c
+++ b/src/base/seq/seqRetCore.c
@@ -112,8 +112,8 @@ Abc_Ntk_t * Seq_NtkRetimeDerive( Abc_Ntk_t * pNtk, int fVerbose )
// start the network
pNtkNew = Abc_NtkAlloc( ABC_NTK_SEQ, ABC_FUNC_AIG );
// duplicate the name and the spec
- pNtkNew->pName = util_strsav(pNtk->pName);
- pNtkNew->pSpec = util_strsav(pNtk->pSpec);
+ pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
+ pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
// map the constant nodes
Abc_NtkCleanCopy( pNtk );
diff --git a/src/bdd/cudd/cuddAPI.c b/src/bdd/cudd/cuddAPI.c
index 2acde7cd..a16b82cf 100644
--- a/src/bdd/cudd/cuddAPI.c
+++ b/src/bdd/cudd/cuddAPI.c
@@ -164,7 +164,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddAddAbs.c b/src/bdd/cudd/cuddAddAbs.c
index 27039908..b256ad0f 100644
--- a/src/bdd/cudd/cuddAddAbs.c
+++ b/src/bdd/cudd/cuddAddAbs.c
@@ -32,7 +32,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddAddApply.c b/src/bdd/cudd/cuddAddApply.c
index 67649913..60c06de6 100644
--- a/src/bdd/cudd/cuddAddApply.c
+++ b/src/bdd/cudd/cuddAddApply.c
@@ -42,7 +42,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddAddFind.c b/src/bdd/cudd/cuddAddFind.c
index 3399527a..0469b014 100644
--- a/src/bdd/cudd/cuddAddFind.c
+++ b/src/bdd/cudd/cuddAddFind.c
@@ -27,7 +27,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddAddInv.c b/src/bdd/cudd/cuddAddInv.c
index cb6dbfbe..fc4a340b 100644
--- a/src/bdd/cudd/cuddAddInv.c
+++ b/src/bdd/cudd/cuddAddInv.c
@@ -24,7 +24,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddAddIte.c b/src/bdd/cudd/cuddAddIte.c
index 77c4d18a..71f8070f 100644
--- a/src/bdd/cudd/cuddAddIte.c
+++ b/src/bdd/cudd/cuddAddIte.c
@@ -33,7 +33,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddAddNeg.c b/src/bdd/cudd/cuddAddNeg.c
index 2420df64..bdb08ddc 100644
--- a/src/bdd/cudd/cuddAddNeg.c
+++ b/src/bdd/cudd/cuddAddNeg.c
@@ -26,7 +26,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddAddWalsh.c b/src/bdd/cudd/cuddAddWalsh.c
index 980ee215..c6a67e34 100644
--- a/src/bdd/cudd/cuddAddWalsh.c
+++ b/src/bdd/cudd/cuddAddWalsh.c
@@ -26,7 +26,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddAndAbs.c b/src/bdd/cudd/cuddAndAbs.c
index 3a6ce85f..5ec47beb 100644
--- a/src/bdd/cudd/cuddAndAbs.c
+++ b/src/bdd/cudd/cuddAndAbs.c
@@ -24,7 +24,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddAnneal.c b/src/bdd/cudd/cuddAnneal.c
index dfc81e86..3d8b56b9 100644
--- a/src/bdd/cudd/cuddAnneal.c
+++ b/src/bdd/cudd/cuddAnneal.c
@@ -35,7 +35,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddApa.c b/src/bdd/cudd/cuddApa.c
index 805a4dde..47ab51e8 100644
--- a/src/bdd/cudd/cuddApa.c
+++ b/src/bdd/cudd/cuddApa.c
@@ -28,7 +28,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddApprox.c b/src/bdd/cudd/cuddApprox.c
index eb6813ff..debcf48b 100644
--- a/src/bdd/cudd/cuddApprox.c
+++ b/src/bdd/cudd/cuddApprox.c
@@ -51,7 +51,7 @@
#else
#define DBL_MAX_EXP 1024
#endif
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddBddAbs.c b/src/bdd/cudd/cuddBddAbs.c
index 20a8f15a..9552464e 100644
--- a/src/bdd/cudd/cuddBddAbs.c
+++ b/src/bdd/cudd/cuddBddAbs.c
@@ -35,7 +35,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddBddCorr.c b/src/bdd/cudd/cuddBddCorr.c
index 47395ec7..c99324a8 100644
--- a/src/bdd/cudd/cuddBddCorr.c
+++ b/src/bdd/cudd/cuddBddCorr.c
@@ -30,7 +30,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddBddIte.c b/src/bdd/cudd/cuddBddIte.c
index fe0c6500..b44e40de 100644
--- a/src/bdd/cudd/cuddBddIte.c
+++ b/src/bdd/cudd/cuddBddIte.c
@@ -44,7 +44,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddBridge.c b/src/bdd/cudd/cuddBridge.c
index e7e5c89f..ccc0893f 100644
--- a/src/bdd/cudd/cuddBridge.c
+++ b/src/bdd/cudd/cuddBridge.c
@@ -44,7 +44,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddCache.c b/src/bdd/cudd/cuddCache.c
index 6598948a..d9e40921 100644
--- a/src/bdd/cudd/cuddCache.c
+++ b/src/bdd/cudd/cuddCache.c
@@ -36,7 +36,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddCheck.c b/src/bdd/cudd/cuddCheck.c
index 3db08dd6..aec8246d 100644
--- a/src/bdd/cudd/cuddCheck.c
+++ b/src/bdd/cudd/cuddCheck.c
@@ -34,7 +34,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddClip.c b/src/bdd/cudd/cuddClip.c
index 3c728a56..4da296ef 100644
--- a/src/bdd/cudd/cuddClip.c
+++ b/src/bdd/cudd/cuddClip.c
@@ -33,7 +33,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddCof.c b/src/bdd/cudd/cuddCof.c
index 0dfeff6c..f79e3f91 100644
--- a/src/bdd/cudd/cuddCof.c
+++ b/src/bdd/cudd/cuddCof.c
@@ -29,7 +29,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddCompose.c b/src/bdd/cudd/cuddCompose.c
index 11c6cb7b..8c858051 100644
--- a/src/bdd/cudd/cuddCompose.c
+++ b/src/bdd/cudd/cuddCompose.c
@@ -55,7 +55,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddDecomp.c b/src/bdd/cudd/cuddDecomp.c
index d9c28482..4fde7392 100644
--- a/src/bdd/cudd/cuddDecomp.c
+++ b/src/bdd/cudd/cuddDecomp.c
@@ -34,7 +34,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddEssent.c b/src/bdd/cudd/cuddEssent.c
index 7bd48c5a..db4b8b49 100644
--- a/src/bdd/cudd/cuddEssent.c
+++ b/src/bdd/cudd/cuddEssent.c
@@ -25,7 +25,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddExact.c b/src/bdd/cudd/cuddExact.c
index 6a81406b..6852be68 100644
--- a/src/bdd/cudd/cuddExact.c
+++ b/src/bdd/cudd/cuddExact.c
@@ -40,7 +40,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddExport.c b/src/bdd/cudd/cuddExport.c
index d7b9645b..d148be42 100644
--- a/src/bdd/cudd/cuddExport.c
+++ b/src/bdd/cudd/cuddExport.c
@@ -35,7 +35,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddGenCof.c b/src/bdd/cudd/cuddGenCof.c
index 59ae55d7..142ee27e 100644
--- a/src/bdd/cudd/cuddGenCof.c
+++ b/src/bdd/cudd/cuddGenCof.c
@@ -46,7 +46,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddGenetic.c b/src/bdd/cudd/cuddGenetic.c
index 8341dcbd..9fe03dad 100644
--- a/src/bdd/cudd/cuddGenetic.c
+++ b/src/bdd/cudd/cuddGenetic.c
@@ -53,7 +53,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddGroup.c b/src/bdd/cudd/cuddGroup.c
index f84f7881..81c05d2c 100644
--- a/src/bdd/cudd/cuddGroup.c
+++ b/src/bdd/cudd/cuddGroup.c
@@ -49,7 +49,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddHarwell.c b/src/bdd/cudd/cuddHarwell.c
index 10746186..063f1922 100644
--- a/src/bdd/cudd/cuddHarwell.c
+++ b/src/bdd/cudd/cuddHarwell.c
@@ -21,7 +21,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddInit.c b/src/bdd/cudd/cuddInit.c
index aec8d286..8e06a425 100644
--- a/src/bdd/cudd/cuddInit.c
+++ b/src/bdd/cudd/cuddInit.c
@@ -29,7 +29,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#define CUDD_MAIN
#include "cuddInt.h"
#undef CUDD_MAIN
diff --git a/src/bdd/cudd/cuddInteract.c b/src/bdd/cudd/cuddInteract.c
index 5a4ec79a..96613639 100644
--- a/src/bdd/cudd/cuddInteract.c
+++ b/src/bdd/cudd/cuddInteract.c
@@ -47,7 +47,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddLCache.c b/src/bdd/cudd/cuddLCache.c
index 72fbd48a..8bd37ba0 100644
--- a/src/bdd/cudd/cuddLCache.c
+++ b/src/bdd/cudd/cuddLCache.c
@@ -45,7 +45,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddLevelQ.c b/src/bdd/cudd/cuddLevelQ.c
index c4c621e7..3cc8e8d8 100644
--- a/src/bdd/cudd/cuddLevelQ.c
+++ b/src/bdd/cudd/cuddLevelQ.c
@@ -50,7 +50,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddLinear.c b/src/bdd/cudd/cuddLinear.c
index cec7c255..7f6b3678 100644
--- a/src/bdd/cudd/cuddLinear.c
+++ b/src/bdd/cudd/cuddLinear.c
@@ -34,7 +34,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddLiteral.c b/src/bdd/cudd/cuddLiteral.c
index 69594486..43740690 100644
--- a/src/bdd/cudd/cuddLiteral.c
+++ b/src/bdd/cudd/cuddLiteral.c
@@ -25,7 +25,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddMatMult.c b/src/bdd/cudd/cuddMatMult.c
index b10975ec..345e7921 100644
--- a/src/bdd/cudd/cuddMatMult.c
+++ b/src/bdd/cudd/cuddMatMult.c
@@ -29,7 +29,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddPriority.c b/src/bdd/cudd/cuddPriority.c
index bb0b83d3..788fc712 100644
--- a/src/bdd/cudd/cuddPriority.c
+++ b/src/bdd/cudd/cuddPriority.c
@@ -43,7 +43,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddRead.c b/src/bdd/cudd/cuddRead.c
index eea4c7f3..2c4a86d8 100644
--- a/src/bdd/cudd/cuddRead.c
+++ b/src/bdd/cudd/cuddRead.c
@@ -23,7 +23,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddRef.c b/src/bdd/cudd/cuddRef.c
index af08d048..a9241f3d 100644
--- a/src/bdd/cudd/cuddRef.c
+++ b/src/bdd/cudd/cuddRef.c
@@ -38,7 +38,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddReorder.c b/src/bdd/cudd/cuddReorder.c
index e2b3470b..1387196f 100644
--- a/src/bdd/cudd/cuddReorder.c
+++ b/src/bdd/cudd/cuddReorder.c
@@ -45,7 +45,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddSat.c b/src/bdd/cudd/cuddSat.c
index dde33a5b..1755a1c1 100644
--- a/src/bdd/cudd/cuddSat.c
+++ b/src/bdd/cudd/cuddSat.c
@@ -42,7 +42,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddSign.c b/src/bdd/cudd/cuddSign.c
index 62477e7f..fcaa65c4 100644
--- a/src/bdd/cudd/cuddSign.c
+++ b/src/bdd/cudd/cuddSign.c
@@ -25,7 +25,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/cudd/cuddSolve.c b/src/bdd/cudd/cuddSolve.c
index 058e0c08..d9c4a2e7 100644
--- a/src/bdd/cudd/cuddSolve.c
+++ b/src/bdd/cudd/cuddSolve.c
@@ -28,7 +28,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddSplit.c b/src/bdd/cudd/cuddSplit.c
index af7d6372..e21ea7cb 100644
--- a/src/bdd/cudd/cuddSplit.c
+++ b/src/bdd/cudd/cuddSplit.c
@@ -32,7 +32,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddSubsetHB.c b/src/bdd/cudd/cuddSubsetHB.c
index 43aaf744..24d41ce5 100644
--- a/src/bdd/cudd/cuddSubsetHB.c
+++ b/src/bdd/cudd/cuddSubsetHB.c
@@ -46,7 +46,7 @@
#else
#define DBL_MAX_EXP 1024
#endif
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddSubsetSP.c b/src/bdd/cudd/cuddSubsetSP.c
index 0f7209dd..55ee3470 100644
--- a/src/bdd/cudd/cuddSubsetSP.c
+++ b/src/bdd/cudd/cuddSubsetSP.c
@@ -41,7 +41,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddSymmetry.c b/src/bdd/cudd/cuddSymmetry.c
index 7b2013e4..e5488b17 100644
--- a/src/bdd/cudd/cuddSymmetry.c
+++ b/src/bdd/cudd/cuddSymmetry.c
@@ -38,7 +38,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddTable.c b/src/bdd/cudd/cuddTable.c
index b118b76a..7f14aed1 100644
--- a/src/bdd/cudd/cuddTable.c
+++ b/src/bdd/cudd/cuddTable.c
@@ -54,7 +54,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddUtil.c b/src/bdd/cudd/cuddUtil.c
index c366d534..d5fa18e2 100644
--- a/src/bdd/cudd/cuddUtil.c
+++ b/src/bdd/cudd/cuddUtil.c
@@ -76,7 +76,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddWindow.c b/src/bdd/cudd/cuddWindow.c
index 3e6d5686..9ceb79b2 100644
--- a/src/bdd/cudd/cuddWindow.c
+++ b/src/bdd/cudd/cuddWindow.c
@@ -31,7 +31,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddCount.c b/src/bdd/cudd/cuddZddCount.c
index 29cf0c14..6c6ec1df 100644
--- a/src/bdd/cudd/cuddZddCount.c
+++ b/src/bdd/cudd/cuddZddCount.c
@@ -34,7 +34,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddFuncs.c b/src/bdd/cudd/cuddZddFuncs.c
index f938e1de..9dc27a95 100644
--- a/src/bdd/cudd/cuddZddFuncs.c
+++ b/src/bdd/cudd/cuddZddFuncs.c
@@ -48,7 +48,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddGroup.c b/src/bdd/cudd/cuddZddGroup.c
index 35f28881..621fa43f 100644
--- a/src/bdd/cudd/cuddZddGroup.c
+++ b/src/bdd/cudd/cuddZddGroup.c
@@ -40,7 +40,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddIsop.c b/src/bdd/cudd/cuddZddIsop.c
index 0918461c..f4b057ea 100644
--- a/src/bdd/cudd/cuddZddIsop.c
+++ b/src/bdd/cudd/cuddZddIsop.c
@@ -34,7 +34,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddLin.c b/src/bdd/cudd/cuddZddLin.c
index 9369bb05..ef2cd298 100644
--- a/src/bdd/cudd/cuddZddLin.c
+++ b/src/bdd/cudd/cuddZddLin.c
@@ -32,7 +32,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddMisc.c b/src/bdd/cudd/cuddZddMisc.c
index d55bb768..6a4ddd09 100644
--- a/src/bdd/cudd/cuddZddMisc.c
+++ b/src/bdd/cudd/cuddZddMisc.c
@@ -33,7 +33,7 @@
******************************************************************************/
#include <math.h>
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddPort.c b/src/bdd/cudd/cuddZddPort.c
index 1700ab2b..6d4a3236 100644
--- a/src/bdd/cudd/cuddZddPort.c
+++ b/src/bdd/cudd/cuddZddPort.c
@@ -32,7 +32,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddReord.c b/src/bdd/cudd/cuddZddReord.c
index e14ae2ad..e2da37f2 100644
--- a/src/bdd/cudd/cuddZddReord.c
+++ b/src/bdd/cudd/cuddZddReord.c
@@ -46,7 +46,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddSetop.c b/src/bdd/cudd/cuddZddSetop.c
index cf05210f..f1bd72f3 100644
--- a/src/bdd/cudd/cuddZddSetop.c
+++ b/src/bdd/cudd/cuddZddSetop.c
@@ -46,7 +46,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddSymm.c b/src/bdd/cudd/cuddZddSymm.c
index c9ffaab4..54019892 100644
--- a/src/bdd/cudd/cuddZddSymm.c
+++ b/src/bdd/cudd/cuddZddSymm.c
@@ -40,7 +40,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddZddUtil.c b/src/bdd/cudd/cuddZddUtil.c
index 0795f123..616d16d4 100644
--- a/src/bdd/cudd/cuddZddUtil.c
+++ b/src/bdd/cudd/cuddZddUtil.c
@@ -35,7 +35,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/testcudd.c b/src/bdd/cudd/testcudd.c
index 451bb190..d8affadc 100644
--- a/src/bdd/cudd/testcudd.c
+++ b/src/bdd/cudd/testcudd.c
@@ -23,7 +23,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "cuddInt.h"
diff --git a/src/bdd/dsd/dsd.h b/src/bdd/dsd/dsd.h
index 3fd365d7..04385933 100644
--- a/src/bdd/dsd/dsd.h
+++ b/src/bdd/dsd/dsd.h
@@ -101,6 +101,7 @@ extern Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc
/*=== dsdTree.c =======================================================*/
extern void Dsd_TreeNodeGetInfo( Dsd_Manager_t * dMan, int * DepthMax, int * GateSizeMax );
extern void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax );
+extern int Dsd_TreeGetAigCost( Dsd_Node_t * pNode );
extern int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * dMan );
extern int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot );
extern int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan );
@@ -109,6 +110,7 @@ extern int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * dMan, in
extern Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * dMan, int * pnNodes );
extern Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes );
extern void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * dMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output );
+extern void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode );
/*=== dsdLocal.c =======================================================*/
extern DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode );
diff --git a/src/bdd/dsd/dsdTree.c b/src/bdd/dsd/dsdTree.c
index 7905cbdd..2f83ddd5 100644
--- a/src/bdd/dsd/dsdTree.c
+++ b/src/bdd/dsd/dsdTree.c
@@ -29,7 +29,7 @@ static int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode );
static int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars );
static void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes );
static void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fCcmp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames );
-
+static void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter );
////////////////////////////////////////////////////////////////////////
/// STATIC VARIABLES ///
@@ -243,6 +243,58 @@ void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur )
/**Function*************************************************************
+ Synopsis [Counts AIG nodes needed to implement this node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dsd_TreeGetAigCost_rec( Dsd_Node_t * pNode )
+{
+ int i, Counter = 0;
+
+ assert( pNode );
+ assert( !Dsd_IsComplement( pNode ) );
+ assert( pNode->nVisits >= 0 );
+
+ if ( pNode->nDecs < 2 )
+ return 0;
+
+ // we don't want the two-input gates to count for non-decomposable blocks
+ if ( pNode->Type == DSD_NODE_OR )
+ Counter += pNode->nDecs - 1;
+ else if ( pNode->Type == DSD_NODE_EXOR )
+ Counter += 3*(pNode->nDecs - 1);
+ else if ( pNode->Type == DSD_NODE_PRIME && pNode->nDecs == 3 )
+ Counter += 3;
+
+ // call recursively
+ for ( i = 0; i < pNode->nDecs; i++ )
+ Counter += Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode->pDecs[i]) );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts AIG nodes needed to implement this node.]
+
+ Description [Assumes that the only primes of the DSD tree are MUXes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dsd_TreeGetAigCost( Dsd_Node_t * pNode )
+{
+ return Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode) );
+}
+
+/**Function*************************************************************
+
Synopsis [Counts non-terminal nodes of the DSD tree.]
Description [Nonterminal nodes include all the nodes with the
@@ -631,27 +683,21 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp
pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR );
Extra_PrintSymbols( pFile, ' ', nOffset, 0 );
- fprintf( pFile, "%s: ", pOutputName );
+ if ( !fComp )
+ fprintf( pFile, "%s = ", pOutputName );
+ else
+ fprintf( pFile, "NOT(%s) = ", pOutputName );
pInputNums = ALLOC( int, pNode->nDecs );
if ( pNode->Type == DSD_NODE_CONST1 )
{
- if ( fComp )
- fprintf( pFile, " Constant 0.\n" );
- else
- fprintf( pFile, " Constant 1.\n" );
+ fprintf( pFile, " Constant 1.\n" );
}
else if ( pNode->Type == DSD_NODE_BUF )
{
- if ( fComp )
- fprintf( pFile, " NOT(" );
- else
- fprintf( pFile, " " );
if ( fShortNames )
- fprintf( pFile, "%d", pNode->S->index );
+ fprintf( pFile, "%d", 'a' + pNode->S->index );
else
fprintf( pFile, "%s", pInputNames[pNode->S->index] );
- if ( fComp )
- fprintf( pFile, ")" );
fprintf( pFile, "\n" );
}
else if ( pNode->Type == DSD_NODE_PRIME )
@@ -664,25 +710,25 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp
fCompNew = (int)( pInput != pNode->pDecs[i] );
if ( i )
fprintf( pFile, "," );
+ if ( fCompNew )
+ fprintf( pFile, " NOT(" );
+ else
+ fprintf( pFile, " " );
if ( pInput->Type == DSD_NODE_BUF )
{
pInputNums[i] = 0;
- if ( fCompNew )
- fprintf( pFile, " NOT(" );
- else
- fprintf( pFile, " " );
if ( fShortNames )
fprintf( pFile, "%d", pInput->S->index );
else
fprintf( pFile, "%s", pInputNames[pInput->S->index] );
- if ( fCompNew )
- fprintf( pFile, ")" );
}
else
{
pInputNums[i] = (*pSigCounter)++;
- fprintf( pFile, " <%d>", pInputNums[i] );
+ fprintf( pFile, "<%d>", pInputNums[i] );
}
+ if ( fCompNew )
+ fprintf( pFile, ")" );
}
fprintf( pFile, " )\n" );
// call recursively for the following blocks
@@ -690,43 +736,39 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp
if ( pInputNums[i] )
{
pInput = Dsd_Regular( pNode->pDecs[i] );
- fCompNew = (int)( pInput != pNode->pDecs[i] );
sprintf( Buffer, "<%d>", pInputNums[i] );
- Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), fCompNew, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
+ Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
}
}
else if ( pNode->Type == DSD_NODE_OR )
{
// print the line
- if ( fComp )
- fprintf( pFile, "AND(" );
- else
- fprintf( pFile, "OR(" );
+ fprintf( pFile, "OR(" );
for ( i = 0; i < pNode->nDecs; i++ )
{
pInput = Dsd_Regular( pNode->pDecs[i] );
fCompNew = (int)( pInput != pNode->pDecs[i] );
if ( i )
fprintf( pFile, "," );
+ if ( fCompNew )
+ fprintf( pFile, " NOT(" );
+ else
+ fprintf( pFile, " " );
if ( pInput->Type == DSD_NODE_BUF )
{
pInputNums[i] = 0;
- if ( fCompNew )
- fprintf( pFile, " NOT(" );
- else
- fprintf( pFile, " " );
if ( fShortNames )
- fprintf( pFile, "%d", pInput->S->index );
+ fprintf( pFile, "%c", 'a' + pInput->S->index );
else
fprintf( pFile, "%s", pInputNames[pInput->S->index] );
- if ( fCompNew )
- fprintf( pFile, ")" );
}
else
{
pInputNums[i] = (*pSigCounter)++;
- fprintf( pFile, " <%d>", pInputNums[i] );
+ fprintf( pFile, "<%d>", pInputNums[i] );
}
+ if ( fCompNew )
+ fprintf( pFile, ")" );
}
fprintf( pFile, " )\n" );
// call recursively for the following blocks
@@ -734,43 +776,199 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp
if ( pInputNums[i] )
{
pInput = Dsd_Regular( pNode->pDecs[i] );
- fCompNew = (int)( pInput != pNode->pDecs[i] );
sprintf( Buffer, "<%d>", pInputNums[i] );
- Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), fComp ^ fCompNew, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
+ Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
}
}
else if ( pNode->Type == DSD_NODE_EXOR )
{
// print the line
- if ( fComp )
- fprintf( pFile, "NEXOR(" );
- else
- fprintf( pFile, "EXOR(" );
+ fprintf( pFile, "EXOR(" );
for ( i = 0; i < pNode->nDecs; i++ )
{
pInput = Dsd_Regular( pNode->pDecs[i] );
fCompNew = (int)( pInput != pNode->pDecs[i] );
if ( i )
fprintf( pFile, "," );
+ if ( fCompNew )
+ fprintf( pFile, " NOT(" );
+ else
+ fprintf( pFile, " " );
if ( pInput->Type == DSD_NODE_BUF )
{
pInputNums[i] = 0;
- if ( fCompNew )
- fprintf( pFile, " NOT(" );
- else
- fprintf( pFile, " " );
if ( fShortNames )
- fprintf( pFile, "%d", pInput->S->index );
+ fprintf( pFile, "%c", 'a' + pInput->S->index );
else
fprintf( pFile, "%s", pInputNames[pInput->S->index] );
- if ( fCompNew )
- fprintf( pFile, ")" );
+ }
+ else
+ {
+ pInputNums[i] = (*pSigCounter)++;
+ fprintf( pFile, "<%d>", pInputNums[i] );
+ }
+ if ( fCompNew )
+ fprintf( pFile, ")" );
+ }
+ fprintf( pFile, " )\n" );
+ // call recursively for the following blocks
+ for ( i = 0; i < pNode->nDecs; i++ )
+ if ( pInputNums[i] )
+ {
+ pInput = Dsd_Regular( pNode->pDecs[i] );
+ sprintf( Buffer, "<%d>", pInputNums[i] );
+ Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
+ }
+ }
+ free( pInputNums );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the decompostion tree into file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode )
+{
+ Dsd_Node_t * pNodeR;
+ int SigCounter = 1;
+ pNodeR = Dsd_Regular(pNode);
+ Dsd_NodePrint_rec( pFile, pNodeR, pNodeR != pNode, "F", 0, &SigCounter );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints one node of the decomposition tree.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter )
+{
+ char Buffer[100];
+ Dsd_Node_t * pInput;
+ int * pInputNums;
+ int fCompNew, i;
+
+ assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 ||
+ pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR );
+
+ Extra_PrintSymbols( pFile, ' ', nOffset, 0 );
+ if ( !fComp )
+ fprintf( pFile, "%s = ", pOutputName );
+ else
+ fprintf( pFile, "NOT(%s) = ", pOutputName );
+ pInputNums = ALLOC( int, pNode->nDecs );
+ if ( pNode->Type == DSD_NODE_CONST1 )
+ {
+ fprintf( pFile, " Constant 1.\n" );
+ }
+ else if ( pNode->Type == DSD_NODE_BUF )
+ {
+ fprintf( pFile, " " );
+ fprintf( pFile, "%c", 'a' + pNode->S->index );
+ fprintf( pFile, "\n" );
+ }
+ else if ( pNode->Type == DSD_NODE_PRIME )
+ {
+ // print the line
+ fprintf( pFile, "PRIME(" );
+ for ( i = 0; i < pNode->nDecs; i++ )
+ {
+ pInput = Dsd_Regular( pNode->pDecs[i] );
+ fCompNew = (int)( pInput != pNode->pDecs[i] );
+ assert( fCompNew == 0 );
+ if ( i )
+ fprintf( pFile, "," );
+ if ( pInput->Type == DSD_NODE_BUF )
+ {
+ pInputNums[i] = 0;
+ fprintf( pFile, " %c", 'a' + pInput->S->index );
+ }
+ else
+ {
+ pInputNums[i] = (*pSigCounter)++;
+ fprintf( pFile, " <%d>", pInputNums[i] );
+ }
+ if ( fCompNew )
+ fprintf( pFile, "\'" );
+ }
+ fprintf( pFile, " )\n" );
+ // call recursively for the following blocks
+ for ( i = 0; i < pNode->nDecs; i++ )
+ if ( pInputNums[i] )
+ {
+ pInput = Dsd_Regular( pNode->pDecs[i] );
+ sprintf( Buffer, "<%d>", pInputNums[i] );
+ Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter );
+ }
+ }
+ else if ( pNode->Type == DSD_NODE_OR )
+ {
+ // print the line
+ fprintf( pFile, "OR(" );
+ for ( i = 0; i < pNode->nDecs; i++ )
+ {
+ pInput = Dsd_Regular( pNode->pDecs[i] );
+ fCompNew = (int)( pInput != pNode->pDecs[i] );
+ if ( i )
+ fprintf( pFile, "," );
+ if ( pInput->Type == DSD_NODE_BUF )
+ {
+ pInputNums[i] = 0;
+ fprintf( pFile, " %c", 'a' + pInput->S->index );
+ }
+ else
+ {
+ pInputNums[i] = (*pSigCounter)++;
+ fprintf( pFile, " <%d>", pInputNums[i] );
+ }
+ if ( fCompNew )
+ fprintf( pFile, "\'" );
+ }
+ fprintf( pFile, " )\n" );
+ // call recursively for the following blocks
+ for ( i = 0; i < pNode->nDecs; i++ )
+ if ( pInputNums[i] )
+ {
+ pInput = Dsd_Regular( pNode->pDecs[i] );
+ sprintf( Buffer, "<%d>", pInputNums[i] );
+ Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter );
+ }
+ }
+ else if ( pNode->Type == DSD_NODE_EXOR )
+ {
+ // print the line
+ fprintf( pFile, "EXOR(" );
+ for ( i = 0; i < pNode->nDecs; i++ )
+ {
+ pInput = Dsd_Regular( pNode->pDecs[i] );
+ fCompNew = (int)( pInput != pNode->pDecs[i] );
+ assert( fCompNew == 0 );
+ if ( i )
+ fprintf( pFile, "," );
+ if ( pInput->Type == DSD_NODE_BUF )
+ {
+ pInputNums[i] = 0;
+ fprintf( pFile, " %c", 'a' + pInput->S->index );
}
else
{
pInputNums[i] = (*pSigCounter)++;
fprintf( pFile, " <%d>", pInputNums[i] );
}
+ if ( fCompNew )
+ fprintf( pFile, "\'" );
}
fprintf( pFile, " )\n" );
// call recursively for the following blocks
@@ -778,9 +976,8 @@ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInp
if ( pInputNums[i] )
{
pInput = Dsd_Regular( pNode->pDecs[i] );
- fCompNew = (int)( pInput != pNode->pDecs[i] );
sprintf( Buffer, "<%d>", pInputNums[i] );
- Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), fCompNew, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames );
+ Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter );
}
}
free( pInputNums );
diff --git a/src/bdd/epd/epd.c b/src/bdd/epd/epd.c
index a843b986..a80240bc 100644
--- a/src/bdd/epd/epd.c
+++ b/src/bdd/epd/epd.c
@@ -25,7 +25,7 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
-#include "util.h"
+#include "util_hack.h"
#include "epd.h"
diff --git a/src/bdd/mtr/mtrBasic.c b/src/bdd/mtr/mtrBasic.c
index 2aec8d6b..94105282 100644
--- a/src/bdd/mtr/mtrBasic.c
+++ b/src/bdd/mtr/mtrBasic.c
@@ -33,7 +33,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "mtrInt.h"
diff --git a/src/bdd/mtr/mtrGroup.c b/src/bdd/mtr/mtrGroup.c
index ae9c5c2f..363b776b 100644
--- a/src/bdd/mtr/mtrGroup.c
+++ b/src/bdd/mtr/mtrGroup.c
@@ -33,7 +33,7 @@
******************************************************************************/
-#include "util.h"
+#include "util_hack.h"
#include "mtrInt.h"
/*---------------------------------------------------------------------------*/
diff --git a/src/map/fpga/fpga.c b/src/map/fpga/fpga.c
index 31894590..c663aa74 100644
--- a/src/map/fpga/fpga.c
+++ b/src/map/fpga/fpga.c
@@ -111,8 +111,8 @@ int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
// set the defaults
fVerbose = 1;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "vh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF )
{
switch (c)
{
@@ -128,13 +128,13 @@ int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = fopen( FileName, "r" )) == NULL )
{
fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
@@ -201,8 +201,8 @@ int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
// set the defaults
fVerbose = 1;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "vh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF )
{
switch (c)
{
@@ -218,7 +218,7 @@ int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
}
- if ( argc != util_optind )
+ if ( argc != globalUtilOptind )
{
goto usage;
}
diff --git a/src/map/fpga/fpgaLib.c b/src/map/fpga/fpgaLib.c
index bf27397a..00832bce 100644
--- a/src/map/fpga/fpgaLib.c
+++ b/src/map/fpga/fpgaLib.c
@@ -70,7 +70,7 @@ Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose )
p = ALLOC( Fpga_LutLib_t, 1 );
memset( p, 0, sizeof(Fpga_LutLib_t) );
- p->pName = util_strsav( FileName );
+ p->pName = Extra_UtilStrsav( FileName );
i = 1;
while ( fgets( pBuffer, 1000, pFile ) != NULL )
@@ -125,7 +125,7 @@ Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p )
Fpga_LutLib_t * pNew;
pNew = ALLOC( Fpga_LutLib_t, 1 );
*pNew = *p;
- pNew->pName = util_strsav( pNew->pName );
+ pNew->pName = Extra_UtilStrsav( pNew->pName );
return pNew;
}
diff --git a/src/map/mapper/mapper.c b/src/map/mapper/mapper.c
index 4d77df8f..b18b68c0 100644
--- a/src/map/mapper/mapper.c
+++ b/src/map/mapper/mapper.c
@@ -95,16 +95,16 @@ int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
fVerbose = 1;
fAlgorithm = 1;
ExcludeFile = 0;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "eovh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "eovh")) != EOF )
{
switch (c)
{
case 'e':
- ExcludeFile = argv[util_optind];
+ ExcludeFile = argv[globalUtilOptind];
if ( ExcludeFile == 0 )
goto usage;
- util_optind++;
+ globalUtilOptind++;
break;
case 'o':
fAlgorithm ^= 1;
@@ -121,13 +121,13 @@ int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL )
// if ( (pFile = fopen( FileName, "r" )) == NULL )
{
diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c
index a5dd8f95..10a5af9d 100644
--- a/src/map/mio/mio.c
+++ b/src/map/mio/mio.c
@@ -139,8 +139,8 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
// set the defaults
fVerbose = 1;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "vh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF )
{
switch (c)
{
@@ -156,13 +156,13 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
goto usage;
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL )
{
fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
@@ -229,8 +229,8 @@ int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
// set the defaults
fVerbose = 1;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "vh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF )
{
switch (c)
{
@@ -246,7 +246,7 @@ int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
}
- if ( argc != util_optind )
+ if ( argc != globalUtilOptind )
{
goto usage;
}
diff --git a/src/map/mio/mioFunc.c b/src/map/mio/mioFunc.c
index b63cadda..78c98fbe 100644
--- a/src/map/mio/mioFunc.c
+++ b/src/map/mio/mioFunc.c
@@ -253,7 +253,7 @@ int Mio_GateCollectNames( char * pFormula, char * pPinNames[] )
break;
if ( i == nPins )
{ // cannot find this name; save it
- pPinNames[nPins++] = util_strsav(pTemp);
+ pPinNames[nPins++] = Extra_UtilStrsav(pTemp);
}
// get the next name
pTemp = strtok( NULL, " " );
diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c
index 0c2000a3..847acc27 100644
--- a/src/map/mio/mioRead.c
+++ b/src/map/mio/mioRead.c
@@ -99,7 +99,7 @@ Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fE
// allocate the genlib structure
pLib = ALLOC( Mio_Library_t, 1 );
memset( pLib, 0, sizeof(Mio_Library_t) );
- pLib->pName = util_strsav( FileName );
+ pLib->pName = Extra_UtilStrsav( FileName );
pLib->tName2Gate = st_init_table(strcmp, st_strhash);
pLib->pMmFlex = Extra_MmFlexStart();
pLib->vCube = Vec_StrAlloc( 100 );
@@ -251,7 +251,7 @@ Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat )
// read the name
pToken = strtok( NULL, " \t\r\n" );
- pGate->pName = util_strsav( pToken );
+ pGate->pName = Extra_UtilStrsav( pToken );
// read the area
pToken = strtok( NULL, " \t\r\n" );
@@ -265,7 +265,7 @@ Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat )
// then rest of the expression
pToken = strtok( NULL, ";" );
- pGate->pForm = util_strsav( pToken );
+ pGate->pForm = Extra_UtilStrsav( pToken );
// read the pin info
// start the linked list of pins
@@ -319,7 +319,7 @@ Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, bool fExtendedFormat )
// read the name
pToken = strtok( NULL, " \t\r\n" );
- pPin->pName = util_strsav( pToken );
+ pPin->pName = Extra_UtilStrsav( pToken );
// read the pin phase
pToken = strtok( NULL, " \t\r\n" );
@@ -507,7 +507,7 @@ int Mio_LibraryReadExclude( Abc_Frame_t * pAbc, char * ExcludeFile, st_table * t
while (1 == fscanf( pEx, "%127s", buffer ))
{
//printf ("Read: '%s'\n", buffer );
- st_insert( tExcludeGate, util_strsav( buffer ), (char *)0 );
+ st_insert( tExcludeGate, Extra_UtilStrsav( buffer ), (char *)0 );
nDel++;
}
diff --git a/src/map/mio/mioUtils.c b/src/map/mio/mioUtils.c
index b051584e..05cf59ad 100644
--- a/src/map/mio/mioUtils.c
+++ b/src/map/mio/mioUtils.c
@@ -120,7 +120,7 @@ Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin )
pPinNew = ALLOC( Mio_Pin_t, 1 );
*pPinNew = *pPin;
- pPinNew->pName = (pPinNew->pName ? util_strsav(pPinNew->pName) : NULL);
+ pPinNew->pName = (pPinNew->pName ? Extra_UtilStrsav(pPinNew->pName) : NULL);
pPinNew->pNext = NULL;
return pPinNew;
diff --git a/src/map/pga/pgaMatch.c b/src/map/pga/pgaMatch.c
index 77d82b86..a4c57089 100644
--- a/src/map/pga/pgaMatch.c
+++ b/src/map/pga/pgaMatch.c
@@ -73,7 +73,7 @@ void Pga_MappingMatches( Pga_Man_t * p, int Mode )
continue;
// get the cuts
clk = clock();
- pList = Abc_NodeGetCutsRecursive( p->pManCut, pObj );
+ pList = Abc_NodeGetCutsRecursive( p->pManCut, pObj, 0 );
p->timeCuts += clock() - clk;
// match the node
Pga_MappingMatchNode( p, pObj->Id, pList, Mode );
diff --git a/src/map/super/super.c b/src/map/super/super.c
index 4b4968dd..97420c5c 100644
--- a/src/map/super/super.c
+++ b/src/map/super/super.c
@@ -90,20 +90,20 @@ int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv )
nVarsMax = 4;
nLevels = 3;
fVerbose = 0;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "ilvh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "ilvh")) != EOF )
{
switch (c)
{
case 'i':
- nVarsMax = atoi(argv[util_optind]);
- util_optind++;
+ nVarsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nVarsMax < 0 )
goto usage;
break;
case 'l':
- nLevels = atoi(argv[util_optind]);
- util_optind++;
+ nLevels = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nLevels < 0 )
goto usage;
break;
@@ -172,44 +172,44 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv )
fWriteOldFormat = 0;
ExcludeFile = 0;
- util_getopt_reset();
- while ( (c = util_getopt(argc, argv, "eiltdasovh")) != EOF )
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "eiltdasovh")) != EOF )
{
switch (c)
{
case 'e':
- ExcludeFile = argv[util_optind];
+ ExcludeFile = argv[globalUtilOptind];
if ( ExcludeFile == 0 )
goto usage;
- util_optind++;
+ globalUtilOptind++;
break;
case 'i':
- nVarsMax = atoi(argv[util_optind]);
- util_optind++;
+ nVarsMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nVarsMax < 0 )
goto usage;
break;
case 'l':
- nLevels = atoi(argv[util_optind]);
- util_optind++;
+ nLevels = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( nLevels < 0 )
goto usage;
break;
case 't':
- TimeLimit = atoi(argv[util_optind]);
- util_optind++;
+ TimeLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( TimeLimit < 0 )
goto usage;
break;
case 'd':
- DelayLimit = (float)atof(argv[util_optind]);
- util_optind++;
+ DelayLimit = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( DelayLimit <= 0.0 )
goto usage;
break;
case 'a':
- AreaLimit = (float)atof(argv[util_optind]);
- util_optind++;
+ AreaLimit = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
if ( AreaLimit <= 0.0 )
goto usage;
break;
@@ -231,7 +231,7 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv )
}
- if ( argc != util_optind + 1 )
+ if ( argc != globalUtilOptind + 1 )
{
fprintf( pErr, "The GENLIB library file should be given on the command line.\n" );
goto usage;
@@ -244,7 +244,7 @@ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv )
}
// get the input file name
- FileName = argv[util_optind];
+ FileName = argv[globalUtilOptind];
if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL )
// if ( (pFile = fopen( FileName, "r" )) == NULL )
{
diff --git a/src/misc/espresso/cofactor.c b/src/misc/espresso/cofactor.c
new file mode 100644
index 00000000..b851a639
--- /dev/null
+++ b/src/misc/espresso/cofactor.c
@@ -0,0 +1,382 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+/*
+ The cofactor of a cover against a cube "c" is a cover formed by the
+ cofactor of each cube in the cover against c. The cofactor of two
+ cubes is null if they are distance 1 or more apart. If they are
+ distance zero apart, the cofactor is the restriction of the cube
+ to the minterms of c.
+
+ The cube list contains the following information:
+
+ T[0] = pointer to a cube identifying the variables that have
+ been cofactored against
+ T[1] = pointer to just beyond the sentinel (i.e., T[n] in this case)
+ T[2]
+ .
+ . = pointers to cubes
+ .
+ T[n-2]
+ T[n-1] = NULL pointer (sentinel)
+
+
+ Cofactoring involves repeated application of "cdist0" to check if a
+ cube of the cover intersects the cofactored cube. This can be
+ slow, especially for the recursive descent of the espresso
+ routines. Therefore, a special cofactor routine "scofactor" is
+ provided which assumes the cofactor is only in a single variable.
+*/
+
+
+/* cofactor -- compute the cofactor of a cover with respect to a cube */
+pcube *cofactor(T, c)
+IN pcube *T;
+IN register pcube c;
+{
+ pcube temp = cube.temp[0], *Tc_save, *Tc, *T1;
+ register pcube p;
+ int listlen;
+
+ listlen = CUBELISTSIZE(T) + 5;
+
+ /* Allocate a new list of cube pointers (max size is previous size) */
+ Tc_save = Tc = ALLOC(pcube, listlen);
+
+ /* pass on which variables have been cofactored against */
+ *Tc++ = set_or(new_cube(), T[0], set_diff(temp, cube.fullset, c));
+ Tc++;
+
+ /* Loop for each cube in the list, determine suitability, and save */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (p != c) {
+
+#ifdef NO_INLINE
+ if (! cdist0(p, c)) goto false;
+#else
+ {register int w,last;register unsigned int x;if((last=cube.inword)!=-1)
+ {x=p[last]&c[last];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w<last;w++)
+ {x=p[w]&c[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,last;
+ register pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){
+ mask=cube.var_mask[var];last=cube.last_word[var];for(w=cube.first_word[var
+ ];w<=last;w++)if(p[w]&c[w]&mask[w])goto nextvar;goto false;nextvar:;}}
+#endif
+
+ *Tc++ = p;
+ false: ;
+ }
+ }
+
+ *Tc++ = (pcube) NULL; /* sentinel */
+ Tc_save[1] = (pcube) Tc; /* save pointer to last */
+ return Tc_save;
+}
+
+/*
+ scofactor -- compute the cofactor of a cover with respect to a cube,
+ where the cube is "active" in only a single variable.
+
+ This routine has been optimized for speed.
+*/
+
+pcube *scofactor(T, c, var)
+IN pcube *T, c;
+IN int var;
+{
+ pcube *Tc, *Tc_save;
+ register pcube p, mask = cube.temp[1], *T1;
+ register int first = cube.first_word[var], last = cube.last_word[var];
+ int listlen;
+
+ listlen = CUBELISTSIZE(T) + 5;
+
+ /* Allocate a new list of cube pointers (max size is previous size) */
+ Tc_save = Tc = ALLOC(pcube, listlen);
+
+ /* pass on which variables have been cofactored against */
+ *Tc++ = set_or(new_cube(), T[0], set_diff(mask, cube.fullset, c));
+ Tc++;
+
+ /* Setup for the quick distance check */
+ (void) set_and(mask, cube.var_mask[var], c);
+
+ /* Loop for each cube in the list, determine suitability, and save */
+ for(T1 = T+2; (p = *T1++) != NULL; )
+ if (p != c) {
+ register int i = first;
+ do
+ if (p[i] & mask[i]) {
+ *Tc++ = p;
+ break;
+ }
+ while (++i <= last);
+ }
+
+ *Tc++ = (pcube) NULL; /* sentinel */
+ Tc_save[1] = (pcube) Tc; /* save pointer to last */
+ return Tc_save;
+}
+
+void massive_count(T)
+IN pcube *T;
+{
+ int *count = cdata.part_zeros;
+ pcube *T1;
+
+ /* Clear the column counts (count of # zeros in each column) */
+ { register int i;
+ for(i = cube.size - 1; i >= 0; i--)
+ count[i] = 0;
+ }
+
+ /* Count the number of zeros in each column */
+ { register int i, *cnt;
+ register unsigned int val;
+ register pcube p, cof = T[0], full = cube.fullset;
+ for(T1 = T+2; (p = *T1++) != NULL; )
+ for(i = LOOP(p); i > 0; i--)
+ if (val = full[i] & ~ (p[i] | cof[i])) {
+ cnt = count + ((i-1) << LOGBPI);
+#if BPI == 32
+ if (val & 0xFF000000) {
+ if (val & 0x80000000) cnt[31]++;
+ if (val & 0x40000000) cnt[30]++;
+ if (val & 0x20000000) cnt[29]++;
+ if (val & 0x10000000) cnt[28]++;
+ if (val & 0x08000000) cnt[27]++;
+ if (val & 0x04000000) cnt[26]++;
+ if (val & 0x02000000) cnt[25]++;
+ if (val & 0x01000000) cnt[24]++;
+ }
+ if (val & 0x00FF0000) {
+ if (val & 0x00800000) cnt[23]++;
+ if (val & 0x00400000) cnt[22]++;
+ if (val & 0x00200000) cnt[21]++;
+ if (val & 0x00100000) cnt[20]++;
+ if (val & 0x00080000) cnt[19]++;
+ if (val & 0x00040000) cnt[18]++;
+ if (val & 0x00020000) cnt[17]++;
+ if (val & 0x00010000) cnt[16]++;
+ }
+#endif
+ if (val & 0xFF00) {
+ if (val & 0x8000) cnt[15]++;
+ if (val & 0x4000) cnt[14]++;
+ if (val & 0x2000) cnt[13]++;
+ if (val & 0x1000) cnt[12]++;
+ if (val & 0x0800) cnt[11]++;
+ if (val & 0x0400) cnt[10]++;
+ if (val & 0x0200) cnt[ 9]++;
+ if (val & 0x0100) cnt[ 8]++;
+ }
+ if (val & 0x00FF) {
+ if (val & 0x0080) cnt[ 7]++;
+ if (val & 0x0040) cnt[ 6]++;
+ if (val & 0x0020) cnt[ 5]++;
+ if (val & 0x0010) cnt[ 4]++;
+ if (val & 0x0008) cnt[ 3]++;
+ if (val & 0x0004) cnt[ 2]++;
+ if (val & 0x0002) cnt[ 1]++;
+ if (val & 0x0001) cnt[ 0]++;
+ }
+ }
+ }
+
+ /*
+ * Perform counts for each variable:
+ * cdata.var_zeros[var] = number of zeros in the variable
+ * cdata.parts_active[var] = number of active parts for each variable
+ * cdata.vars_active = number of variables which are active
+ * cdata.vars_unate = number of variables which are active and unate
+ *
+ * best -- the variable which is best for splitting based on:
+ * mostactive -- most # active parts in any variable
+ * mostzero -- most # zeros in any variable
+ * mostbalanced -- minimum over the maximum # zeros / part / variable
+ */
+
+ { register int var, i, lastbit, active, maxactive;
+ int best = -1, mostactive = 0, mostzero = 0, mostbalanced = 32000;
+ cdata.vars_unate = cdata.vars_active = 0;
+
+ for(var = 0; var < cube.num_vars; var++) {
+ if (var < cube.num_binary_vars) { /* special hack for binary vars */
+ i = count[var*2];
+ lastbit = count[var*2 + 1];
+ active = (i > 0) + (lastbit > 0);
+ cdata.var_zeros[var] = i + lastbit;
+ maxactive = MAX(i, lastbit);
+ } else {
+ maxactive = active = cdata.var_zeros[var] = 0;
+ lastbit = cube.last_part[var];
+ for(i = cube.first_part[var]; i <= lastbit; i++) {
+ cdata.var_zeros[var] += count[i];
+ active += (count[i] > 0);
+ if (active > maxactive) maxactive = active;
+ }
+ }
+
+ /* first priority is to maximize the number of active parts */
+ /* for binary case, this will usually select the output first */
+ if (active > mostactive)
+ best = var, mostactive = active, mostzero = cdata.var_zeros[best],
+ mostbalanced = maxactive;
+ else if (active == mostactive)
+ /* secondary condition is to maximize the number zeros */
+ /* for binary variables, this is the same as minimum # of 2's */
+ if (cdata.var_zeros[var] > mostzero)
+ best = var, mostzero = cdata.var_zeros[best],
+ mostbalanced = maxactive;
+ else if (cdata.var_zeros[var] == mostzero)
+ /* third condition is to pick a balanced variable */
+ /* for binary vars, this means roughly equal # 0's and 1's */
+ if (maxactive < mostbalanced)
+ best = var, mostbalanced = maxactive;
+
+ cdata.parts_active[var] = active;
+ cdata.is_unate[var] = (active == 1);
+ cdata.vars_active += (active > 0);
+ cdata.vars_unate += (active == 1);
+ }
+ cdata.best = best;
+ }
+}
+
+int binate_split_select(T, cleft, cright, debug_flag)
+IN pcube *T;
+IN register pcube cleft, cright;
+IN int debug_flag;
+{
+ int best = cdata.best;
+ register int i, lastbit = cube.last_part[best], halfbit = 0;
+ register pcube cof=T[0];
+
+ /* Create the cubes to cofactor against */
+ (void) set_diff(cleft, cube.fullset, cube.var_mask[best]);
+ (void) set_diff(cright, cube.fullset, cube.var_mask[best]);
+ for(i = cube.first_part[best]; i <= lastbit; i++)
+ if (! is_in_set(cof,i))
+ halfbit++;
+ for(i = cube.first_part[best], halfbit = halfbit/2; halfbit > 0; i++)
+ if (! is_in_set(cof,i))
+ halfbit--, set_insert(cleft, i);
+ for(; i <= lastbit; i++)
+ if (! is_in_set(cof,i))
+ set_insert(cright, i);
+
+ if (debug & debug_flag) {
+ (void) printf("BINATE_SPLIT_SELECT: split against %d\n", best);
+ if (verbose_debug)
+ (void) printf("cl=%s\ncr=%s\n", pc1(cleft), pc2(cright));
+ }
+ return best;
+}
+
+
+pcube *cube1list(A)
+pcover A;
+{
+ register pcube last, p, *plist, *list;
+
+ list = plist = ALLOC(pcube, A->count + 3);
+ *plist++ = new_cube();
+ plist++;
+ foreach_set(A, last, p) {
+ *plist++ = p;
+ }
+ *plist++ = NULL; /* sentinel */
+ list[1] = (pcube) plist;
+ return list;
+}
+
+
+pcube *cube2list(A, B)
+pcover A, B;
+{
+ register pcube last, p, *plist, *list;
+
+ list = plist = ALLOC(pcube, A->count + B->count + 3);
+ *plist++ = new_cube();
+ plist++;
+ foreach_set(A, last, p) {
+ *plist++ = p;
+ }
+ foreach_set(B, last, p) {
+ *plist++ = p;
+ }
+ *plist++ = NULL;
+ list[1] = (pcube) plist;
+ return list;
+}
+
+
+pcube *cube3list(A, B, C)
+pcover A, B, C;
+{
+ register pcube last, p, *plist, *list;
+
+ plist = ALLOC(pcube, A->count + B->count + C->count + 3);
+ list = plist;
+ *plist++ = new_cube();
+ plist++;
+ foreach_set(A, last, p) {
+ *plist++ = p;
+ }
+ foreach_set(B, last, p) {
+ *plist++ = p;
+ }
+ foreach_set(C, last, p) {
+ *plist++ = p;
+ }
+ *plist++ = NULL;
+ list[1] = (pcube) plist;
+ return list;
+}
+
+
+pcover cubeunlist(A1)
+pcube *A1;
+{
+ register int i;
+ register pcube p, pdest, cof = A1[0];
+ register pcover A;
+
+ A = new_cover(CUBELISTSIZE(A1));
+ for(i = 2; (p = A1[i]) != NULL; i++) {
+ pdest = GETSET(A, i-2);
+ INLINEset_or(pdest, p, cof);
+ }
+ A->count = CUBELISTSIZE(A1);
+ return A;
+}
+
+simplify_cubelist(T)
+pcube *T;
+{
+ register pcube *Tdest;
+ register int i, ncubes;
+
+ (void) set_copy(cube.temp[0], T[0]); /* retrieve cofactor */
+
+ ncubes = CUBELISTSIZE(T);
+ qsort((char *) (T+2), ncubes, sizeof(pset), (int (*)()) d1_order);
+
+ Tdest = T+2;
+ /* *Tdest++ = T[2]; */
+ for(i = 3; i < ncubes; i++) {
+ if (d1_order(&T[i-1], &T[i]) != 0) {
+ *Tdest++ = T[i];
+ }
+ }
+
+ *Tdest++ = NULL; /* sentinel */
+ Tdest[1] = (pcube) Tdest; /* save pointer to last */
+}
diff --git a/src/misc/espresso/cols.c b/src/misc/espresso/cols.c
new file mode 100644
index 00000000..ec3797e6
--- /dev/null
+++ b/src/misc/espresso/cols.c
@@ -0,0 +1,314 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+#include "sparse_int.h"
+
+
+/*
+ * allocate a new col vector
+ */
+sm_col *
+sm_col_alloc()
+{
+ register sm_col *pcol;
+
+#ifdef FAST_AND_LOOSE
+ if (sm_col_freelist == NIL(sm_col)) {
+ pcol = ALLOC(sm_col, 1);
+ } else {
+ pcol = sm_col_freelist;
+ sm_col_freelist = pcol->next_col;
+ }
+#else
+ pcol = ALLOC(sm_col, 1);
+#endif
+
+ pcol->col_num = 0;
+ pcol->length = 0;
+ pcol->first_row = pcol->last_row = NIL(sm_element);
+ pcol->next_col = pcol->prev_col = NIL(sm_col);
+ pcol->flag = 0;
+ pcol->user_word = NIL(char); /* for our user ... */
+ return pcol;
+}
+
+
+/*
+ * free a col vector -- for FAST_AND_LOOSE, this is real cheap for cols;
+ * however, freeing a rowumn must still walk down the rowumn discarding
+ * the elements one-by-one; that is the only use for the extra '-DCOLS'
+ * compile flag ...
+ */
+void
+sm_col_free(pcol)
+register sm_col *pcol;
+{
+#if defined(FAST_AND_LOOSE) && ! defined(COLS)
+ if (pcol->first_row != NIL(sm_element)) {
+ /* Add the linked list of col items to the free list */
+ pcol->last_row->next_row = sm_element_freelist;
+ sm_element_freelist = pcol->first_row;
+ }
+
+ /* Add the col to the free list of cols */
+ pcol->next_col = sm_col_freelist;
+ sm_col_freelist = pcol;
+#else
+ register sm_element *p, *pnext;
+
+ for(p = pcol->first_row; p != 0; p = pnext) {
+ pnext = p->next_row;
+ sm_element_free(p);
+ }
+ FREE(pcol);
+#endif
+}
+
+
+/*
+ * duplicate an existing col
+ */
+sm_col *
+sm_col_dup(pcol)
+register sm_col *pcol;
+{
+ register sm_col *pnew;
+ register sm_element *p;
+
+ pnew = sm_col_alloc();
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ (void) sm_col_insert(pnew, p->row_num);
+ }
+ return pnew;
+}
+
+
+/*
+ * insert an element into a col vector
+ */
+sm_element *
+sm_col_insert(pcol, row)
+register sm_col *pcol;
+register int row;
+{
+ register sm_element *test, *element;
+
+ /* get a new item, save its address */
+ sm_element_alloc(element);
+ test = element;
+ sorted_insert(sm_element, pcol->first_row, pcol->last_row, pcol->length,
+ next_row, prev_row, row_num, row, test);
+
+ /* if item was not used, free it */
+ if (element != test) {
+ sm_element_free(element);
+ }
+
+ /* either way, return the current new value */
+ return test;
+}
+
+
+/*
+ * remove an element from a col vector
+ */
+void
+sm_col_remove(pcol, row)
+register sm_col *pcol;
+register int row;
+{
+ register sm_element *p;
+
+ for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row)
+ ;
+ if (p != 0 && p->row_num == row) {
+ dll_unlink(p, pcol->first_row, pcol->last_row,
+ next_row, prev_row, pcol->length);
+ sm_element_free(p);
+ }
+}
+
+
+/*
+ * find an element (if it is in the col vector)
+ */
+sm_element *
+sm_col_find(pcol, row)
+sm_col *pcol;
+int row;
+{
+ register sm_element *p;
+
+ for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row)
+ ;
+ if (p != 0 && p->row_num == row) {
+ return p;
+ } else {
+ return NIL(sm_element);
+ }
+}
+
+/*
+ * return 1 if col p2 contains col p1; 0 otherwise
+ */
+int
+sm_col_contains(p1, p2)
+sm_col *p1, *p2;
+{
+ register sm_element *q1, *q2;
+
+ q1 = p1->first_row;
+ q2 = p2->first_row;
+ while (q1 != 0) {
+ if (q2 == 0 || q1->row_num < q2->row_num) {
+ return 0;
+ } else if (q1->row_num == q2->row_num) {
+ q1 = q1->next_row;
+ q2 = q2->next_row;
+ } else {
+ q2 = q2->next_row;
+ }
+ }
+ return 1;
+}
+
+
+/*
+ * return 1 if col p1 and col p2 share an element in common
+ */
+int
+sm_col_intersects(p1, p2)
+sm_col *p1, *p2;
+{
+ register sm_element *q1, *q2;
+
+ q1 = p1->first_row;
+ q2 = p2->first_row;
+ if (q1 == 0 || q2 == 0) return 0;
+ for(;;) {
+ if (q1->row_num < q2->row_num) {
+ if ((q1 = q1->next_row) == 0) {
+ return 0;
+ }
+ } else if (q1->row_num > q2->row_num) {
+ if ((q2 = q2->next_row) == 0) {
+ return 0;
+ }
+ } else {
+ return 1;
+ }
+ }
+}
+
+
+/*
+ * compare two cols, lexical ordering
+ */
+int
+sm_col_compare(p1, p2)
+sm_col *p1, *p2;
+{
+ register sm_element *q1, *q2;
+
+ q1 = p1->first_row;
+ q2 = p2->first_row;
+ while(q1 != 0 && q2 != 0) {
+ if (q1->row_num != q2->row_num) {
+ return q1->row_num - q2->row_num;
+ }
+ q1 = q1->next_row;
+ q2 = q2->next_row;
+ }
+
+ if (q1 != 0) {
+ return 1;
+ } else if (q2 != 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+/*
+ * return the intersection
+ */
+sm_col *
+sm_col_and(p1, p2)
+sm_col *p1, *p2;
+{
+ register sm_element *q1, *q2;
+ register sm_col *result;
+
+ result = sm_col_alloc();
+ q1 = p1->first_row;
+ q2 = p2->first_row;
+ if (q1 == 0 || q2 == 0) return result;
+ for(;;) {
+ if (q1->row_num < q2->row_num) {
+ if ((q1 = q1->next_row) == 0) {
+ return result;
+ }
+ } else if (q1->row_num > q2->row_num) {
+ if ((q2 = q2->next_row) == 0) {
+ return result;
+ }
+ } else {
+ (void) sm_col_insert(result, q1->row_num);
+ if ((q1 = q1->next_row) == 0) {
+ return result;
+ }
+ if ((q2 = q2->next_row) == 0) {
+ return result;
+ }
+ }
+ }
+}
+
+int
+sm_col_hash(pcol, modulus)
+sm_col *pcol;
+int modulus;
+{
+ register int sum;
+ register sm_element *p;
+
+ sum = 0;
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ sum = (sum*17 + p->row_num) % modulus;
+ }
+ return sum;
+}
+
+/*
+ * remove an element from a col vector (given a pointer to the element)
+ */
+void
+sm_col_remove_element(pcol, p)
+register sm_col *pcol;
+register sm_element *p;
+{
+ dll_unlink(p, pcol->first_row, pcol->last_row,
+ next_row, prev_row, pcol->length);
+ sm_element_free(p);
+}
+
+
+void
+sm_col_print(fp, pcol)
+FILE *fp;
+sm_col *pcol;
+{
+ sm_element *p;
+
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ (void) fprintf(fp, " %d", p->row_num);
+ }
+}
diff --git a/src/misc/espresso/compl.c b/src/misc/espresso/compl.c
new file mode 100644
index 00000000..8f1c6606
--- /dev/null
+++ b/src/misc/espresso/compl.c
@@ -0,0 +1,680 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * module: compl.c
+ * purpose: compute the complement of a multiple-valued function
+ *
+ * The "unate recursive paradigm" is used. After a set of special
+ * cases are examined, the function is split on the "most active
+ * variable". These two halves are complemented recursively, and then
+ * the results are merged.
+ *
+ * Changes (from Version 2.1 to Version 2.2)
+ * 1. Minor bug in compl_lifting -- cubes in the left half were
+ * not marked as active, so that when merging a leaf from the left
+ * hand side, the active flags were essentially random. This led
+ * to minor impredictability problem, but never affected the
+ * accuracy of the results.
+ */
+
+#include "espresso.h"
+
+#define USE_COMPL_LIFT 0
+#define USE_COMPL_LIFT_ONSET 1
+#define USE_COMPL_LIFT_ONSET_COMPLEX 2
+#define NO_LIFTING 3
+
+static bool compl_special_cases();
+static pcover compl_merge();
+static void compl_d1merge();
+static pcover compl_cube();
+static void compl_lift();
+static void compl_lift_onset();
+static void compl_lift_onset_complex();
+static bool simp_comp_special_cases();
+static bool simplify_special_cases();
+
+
+/* complement -- compute the complement of T */
+pcover complement(T)
+pcube *T; /* T will be disposed of */
+{
+ register pcube cl, cr;
+ register int best;
+ pcover Tbar, Tl, Tr;
+ int lifting;
+ static int compl_level = 0;
+
+ if (debug & COMPL)
+ debug_print(T, "COMPLEMENT", compl_level++);
+
+ if (compl_special_cases(T, &Tbar) == MAYBE) {
+
+ /* Allocate space for the partition cubes */
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, COMPL);
+
+ /* Complement the left and right halves */
+ Tl = complement(scofactor(T, cl, best));
+ Tr = complement(scofactor(T, cr, best));
+
+ if (Tr->count*Tl->count > (Tr->count+Tl->count)*CUBELISTSIZE(T)) {
+ lifting = USE_COMPL_LIFT_ONSET;
+ } else {
+ lifting = USE_COMPL_LIFT;
+ }
+ Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+
+ free_cube(cl);
+ free_cube(cr);
+ free_cubelist(T);
+ }
+
+ if (debug & COMPL)
+ debug1_print(Tbar, "exit COMPLEMENT", --compl_level);
+ return Tbar;
+}
+
+static bool compl_special_cases(T, Tbar)
+pcube *T; /* will be disposed if answer is determined */
+pcover *Tbar; /* returned only if answer determined */
+{
+ register pcube *T1, p, ceil, cof=T[0];
+ pcover A, ceil_compl;
+
+ /* Check for no cubes in the cover */
+ if (T[2] == NULL) {
+ *Tbar = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for only a single cube in the cover */
+ if (T[3] == NULL) {
+ *Tbar = compl_cube(set_or(cof, cof, T[2]));
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for a row of all 1's (implies complement is null) */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *Tbar = new_cover(0);
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which can be factored out */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ ceil_compl = compl_cube(ceil);
+ (void) set_or(cof, cof, set_diff(ceil, cube.fullset, ceil));
+ set_free(ceil);
+ *Tbar = sf_append(complement(T), ceil_compl);
+ return TRUE;
+ }
+ set_free(ceil);
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If single active variable not factored out above, then tautology ! */
+ if (cdata.vars_active == 1) {
+ *Tbar = new_cover(0);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate cover */
+ } else if (cdata.vars_unate == cdata.vars_active) {
+ A = map_cover_to_unate(T);
+ free_cubelist(T);
+ A = unate_compl(A);
+ *Tbar = map_unate_to_cover(A);
+ sf_free(A);
+ return TRUE;
+
+ /* Not much we can do about it */
+ } else {
+ return MAYBE;
+ }
+}
+
+/*
+ * compl_merge -- merge the two cofactors around the splitting
+ * variable
+ *
+ * The merge operation involves intersecting each cube of the left
+ * cofactor with cl, and intersecting each cube of the right cofactor
+ * with cr. The union of these two covers is the merged result.
+ *
+ * In order to reduce the number of cubes, a distance-1 merge is
+ * performed (note that two cubes can only combine distance-1 in the
+ * splitting variable). Also, a simple expand is performed in the
+ * splitting variable (simple implies the covering check for the
+ * expansion is not full containment, but single-cube containment).
+ */
+
+static pcover compl_merge(T1, L, R, cl, cr, var, lifting)
+pcube *T1; /* Original ON-set */
+pcover L, R; /* Complement from each recursion branch */
+register pcube cl, cr; /* cubes used for cofactoring */
+int var; /* splitting variable */
+int lifting; /* whether to perform lifting or not */
+{
+ register pcube p, last, pt;
+ pcover T, Tbar;
+ pcube *L1, *R1;
+
+ if (debug & COMPL) {
+ (void) printf("compl_merge: left %d, right %d\n", L->count, R->count);
+ (void) printf("%s (cl)\n%s (cr)\nLeft is\n", pc1(cl), pc2(cr));
+ cprint(L);
+ (void) printf("Right is\n");
+ cprint(R);
+ }
+
+ /* Intersect each cube with the cofactored cube */
+ foreach_set(L, last, p) {
+ INLINEset_and(p, p, cl);
+ SET(p, ACTIVE);
+ }
+ foreach_set(R, last, p) {
+ INLINEset_and(p, p, cr);
+ SET(p, ACTIVE);
+ }
+
+ /* Sort the arrays for a distance-1 merge */
+ (void) set_copy(cube.temp[0], cube.var_mask[var]);
+ qsort((char *) (L1 = sf_list(L)), L->count, sizeof(pset), (int (*)()) d1_order);
+ qsort((char *) (R1 = sf_list(R)), R->count, sizeof(pset), (int (*)()) d1_order);
+
+ /* Perform distance-1 merge */
+ compl_d1merge(L1, R1);
+
+ /* Perform lifting */
+ switch(lifting) {
+ case USE_COMPL_LIFT_ONSET:
+ T = cubeunlist(T1);
+ compl_lift_onset(L1, T, cr, var);
+ compl_lift_onset(R1, T, cl, var);
+ free_cover(T);
+ break;
+ case USE_COMPL_LIFT_ONSET_COMPLEX:
+ T = cubeunlist(T1);
+ compl_lift_onset_complex(L1, T, var);
+ compl_lift_onset_complex(R1, T, var);
+ free_cover(T);
+ break;
+ case USE_COMPL_LIFT:
+ compl_lift(L1, R1, cr, var);
+ compl_lift(R1, L1, cl, var);
+ break;
+ case NO_LIFTING:
+ break;
+ default:
+ ;
+ }
+ FREE(L1);
+ FREE(R1);
+
+ /* Re-create the merged cover */
+ Tbar = new_cover(L->count + R->count);
+ pt = Tbar->data;
+ foreach_set(L, last, p) {
+ INLINEset_copy(pt, p);
+ Tbar->count++;
+ pt += Tbar->wsize;
+ }
+ foreach_active_set(R, last, p) {
+ INLINEset_copy(pt, p);
+ Tbar->count++;
+ pt += Tbar->wsize;
+ }
+
+ if (debug & COMPL) {
+ (void) printf("Result %d\n", Tbar->count);
+ if (verbose_debug)
+ cprint(Tbar);
+ }
+
+ free_cover(L);
+ free_cover(R);
+ return Tbar;
+}
+
+/*
+ * compl_lift_simple -- expand in the splitting variable using single
+ * cube containment against the other recursion branch to check
+ * validity of the expansion, and expanding all (or none) of the
+ * splitting variable.
+ */
+static void compl_lift(A1, B1, bcube, var)
+pcube *A1, *B1, bcube;
+int var;
+{
+ register pcube a, b, *B2, lift=cube.temp[4], liftor=cube.temp[5];
+ pcube mask = cube.var_mask[var];
+
+ (void) set_and(liftor, bcube, mask);
+
+ /* for each cube in the first array ... */
+ for(; (a = *A1++) != NULL; ) {
+ if (TESTP(a, ACTIVE)) {
+
+ /* create a lift of this cube in the merging coord */
+ (void) set_merge(lift, bcube, a, mask);
+
+ /* for each cube in the second array */
+ for(B2 = B1; (b = *B2++) != NULL; ) {
+ INLINEsetp_implies(lift, b, /* when_false => */ continue);
+ /* when_true => fall through to next statement */
+
+ /* cube of A1 was contained by some cube of B1, so raise */
+ INLINEset_or(a, a, liftor);
+ break;
+ }
+ }
+ }
+}
+
+
+
+/*
+ * compl_lift_onset -- expand in the splitting variable using a
+ * distance-1 check against the original on-set; expand all (or
+ * none) of the splitting variable. Each cube of A1 is expanded
+ * against the original on-set T.
+ */
+static void compl_lift_onset(A1, T, bcube, var)
+pcube *A1;
+pcover T;
+pcube bcube;
+int var;
+{
+ register pcube a, last, p, lift=cube.temp[4], mask=cube.var_mask[var];
+
+ /* for each active cube from one branch of the complement */
+ for(; (a = *A1++) != NULL; ) {
+ if (TESTP(a, ACTIVE)) {
+
+ /* create a lift of this cube in the merging coord */
+ INLINEset_and(lift, bcube, mask); /* isolate parts to raise */
+ INLINEset_or(lift, a, lift); /* raise these parts in a */
+
+ /* for each cube in the ON-set, check for intersection */
+ foreach_set(T, last, p) {
+ if (cdist0(p, lift)) {
+ goto nolift;
+ }
+ }
+ INLINEset_copy(a, lift); /* save the raising */
+ SET(a, ACTIVE);
+nolift : ;
+ }
+ }
+}
+
+/*
+ * compl_lift_complex -- expand in the splitting variable, but expand all
+ * parts which can possibly expand.
+ * T is the original ON-set
+ * A1 is either the left or right cofactor
+ */
+static void compl_lift_onset_complex(A1, T, var)
+pcube *A1; /* array of pointers to new result */
+pcover T; /* original ON-set */
+int var; /* which variable we split on */
+{
+ register int dist;
+ register pcube last, p, a, xlower;
+
+ /* for each cube in the complement */
+ xlower = new_cube();
+ for(; (a = *A1++) != NULL; ) {
+
+ if (TESTP(a, ACTIVE)) {
+
+ /* Find which parts of the splitting variable are forced low */
+ INLINEset_clear(xlower, cube.size);
+ foreach_set(T, last, p) {
+ if ((dist = cdist01(p, a)) < 2) {
+ if (dist == 0) {
+ fatal("compl: ON-set and OFF-set are not orthogonal");
+ } else {
+ (void) force_lower(xlower, p, a);
+ }
+ }
+ }
+
+ (void) set_diff(xlower, cube.var_mask[var], xlower);
+ (void) set_or(a, a, xlower);
+ free_cube(xlower);
+ }
+ }
+}
+
+
+
+/*
+ * compl_d1merge -- distance-1 merge in the splitting variable
+ */
+static void compl_d1merge(L1, R1)
+register pcube *L1, *R1;
+{
+ register pcube pl, pr;
+
+ /* Find equal cubes between the two cofactors */
+ for(pl = *L1, pr = *R1; (pl != NULL) && (pr != NULL); )
+ switch (d1_order(L1, R1)) {
+ case 1:
+ pr = *(++R1); break; /* advance right pointer */
+ case -1:
+ pl = *(++L1); break; /* advance left pointer */
+ case 0:
+ RESET(pr, ACTIVE);
+ INLINEset_or(pl, pl, pr);
+ pr = *(++R1);
+ default:
+ ;
+ }
+}
+
+
+
+/* compl_cube -- return the complement of a single cube (De Morgan's law) */
+static pcover compl_cube(p)
+register pcube p;
+{
+ register pcube diff=cube.temp[7], pdest, mask, full=cube.fullset;
+ int var;
+ pcover R;
+
+ /* Allocate worst-case size cover (to avoid checking overflow) */
+ R = new_cover(cube.num_vars);
+
+ /* Compute bit-wise complement of the cube */
+ INLINEset_diff(diff, full, p);
+
+ for(var = 0; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var];
+ /* If the bit-wise complement is not empty in var ... */
+ if (! setp_disjoint(diff, mask)) {
+ pdest = GETSET(R, R->count++);
+ INLINEset_merge(pdest, diff, full, mask);
+ }
+ }
+ return R;
+}
+
+/* simp_comp -- quick simplification of T */
+void simp_comp(T, Tnew, Tbar)
+pcube *T; /* T will be disposed of */
+pcover *Tnew;
+pcover *Tbar;
+{
+ register pcube cl, cr;
+ register int best;
+ pcover Tl, Tr, Tlbar, Trbar;
+ int lifting;
+ static int simplify_level = 0;
+
+ if (debug & COMPL)
+ debug_print(T, "SIMPCOMP", simplify_level++);
+
+ if (simp_comp_special_cases(T, Tnew, Tbar) == MAYBE) {
+
+ /* Allocate space for the partition cubes */
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, COMPL);
+
+ /* Complement the left and right halves */
+ simp_comp(scofactor(T, cl, best), &Tl, &Tlbar);
+ simp_comp(scofactor(T, cr, best), &Tr, &Trbar);
+
+ lifting = USE_COMPL_LIFT;
+ *Tnew = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+
+ lifting = USE_COMPL_LIFT;
+ *Tbar = compl_merge(T, Tlbar, Trbar, cl, cr, best, lifting);
+
+ /* All of this work for nothing ? Let's hope not ... */
+ if ((*Tnew)->count > CUBELISTSIZE(T)) {
+ sf_free(*Tnew);
+ *Tnew = cubeunlist(T);
+ }
+
+ free_cube(cl);
+ free_cube(cr);
+ free_cubelist(T);
+ }
+
+ if (debug & COMPL) {
+ debug1_print(*Tnew, "exit SIMPCOMP (new)", simplify_level);
+ debug1_print(*Tbar, "exit SIMPCOMP (compl)", simplify_level);
+ simplify_level--;
+ }
+}
+
+static bool simp_comp_special_cases(T, Tnew, Tbar)
+pcube *T; /* will be disposed if answer is determined */
+pcover *Tnew; /* returned only if answer determined */
+pcover *Tbar; /* returned only if answer determined */
+{
+ register pcube *T1, p, ceil, cof=T[0];
+ pcube last;
+ pcover A;
+
+ /* Check for no cubes in the cover (function is empty) */
+ if (T[2] == NULL) {
+ *Tnew = new_cover(1);
+ *Tbar = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for only a single cube in the cover */
+ if (T[3] == NULL) {
+ (void) set_or(cof, cof, T[2]);
+ *Tnew = sf_addset(new_cover(1), cof);
+ *Tbar = compl_cube(cof);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for a row of all 1's (function is a tautology) */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ *Tbar = new_cover(1);
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which can be factored out */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ p = new_cube();
+ (void) set_diff(p, cube.fullset, ceil);
+ (void) set_or(cof, cof, p);
+ set_free(p);
+ simp_comp(T, Tnew, Tbar);
+
+ /* Adjust the ON-set */
+ A = *Tnew;
+ foreach_set(A, last, p) {
+ INLINEset_and(p, p, ceil);
+ }
+
+ /* Compute the new complement */
+ *Tbar = sf_append(*Tbar, compl_cube(ceil));
+ set_free(ceil);
+ return TRUE;
+ }
+ set_free(ceil);
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If single active variable not factored out above, then tautology ! */
+ if (cdata.vars_active == 1) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ *Tbar = new_cover(1);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate cover */
+ } else if (cdata.vars_unate == cdata.vars_active) {
+ /* Make the cover minimum by single-cube containment */
+ A = cubeunlist(T);
+ *Tnew = sf_contain(A);
+
+ /* Now form a minimum representation of the complement */
+ A = map_cover_to_unate(T);
+ A = unate_compl(A);
+ *Tbar = map_unate_to_cover(A);
+ sf_free(A);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Not much we can do about it */
+ } else {
+ return MAYBE;
+ }
+}
+
+/* simplify -- quick simplification of T */
+pcover simplify(T)
+pcube *T; /* T will be disposed of */
+{
+ register pcube cl, cr;
+ register int best;
+ pcover Tbar, Tl, Tr;
+ int lifting;
+ static int simplify_level = 0;
+
+ if (debug & COMPL) {
+ debug_print(T, "SIMPLIFY", simplify_level++);
+ }
+
+ if (simplify_special_cases(T, &Tbar) == MAYBE) {
+
+ /* Allocate space for the partition cubes */
+ cl = new_cube();
+ cr = new_cube();
+
+ best = binate_split_select(T, cl, cr, COMPL);
+
+ /* Complement the left and right halves */
+ Tl = simplify(scofactor(T, cl, best));
+ Tr = simplify(scofactor(T, cr, best));
+
+ lifting = USE_COMPL_LIFT;
+ Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+
+ /* All of this work for nothing ? Let's hope not ... */
+ if (Tbar->count > CUBELISTSIZE(T)) {
+ sf_free(Tbar);
+ Tbar = cubeunlist(T);
+ }
+
+ free_cube(cl);
+ free_cube(cr);
+ free_cubelist(T);
+ }
+
+ if (debug & COMPL) {
+ debug1_print(Tbar, "exit SIMPLIFY", --simplify_level);
+ }
+ return Tbar;
+}
+
+static bool simplify_special_cases(T, Tnew)
+pcube *T; /* will be disposed if answer is determined */
+pcover *Tnew; /* returned only if answer determined */
+{
+ register pcube *T1, p, ceil, cof=T[0];
+ pcube last;
+ pcover A;
+
+ /* Check for no cubes in the cover */
+ if (T[2] == NULL) {
+ *Tnew = new_cover(0);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for only a single cube in the cover */
+ if (T[3] == NULL) {
+ *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2]));
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for a row of all 1's (implies function is a tautology) */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which can be factored out */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ p = new_cube();
+ (void) set_diff(p, cube.fullset, ceil);
+ (void) set_or(cof, cof, p);
+ free_cube(p);
+
+ A = simplify(T);
+ foreach_set(A, last, p) {
+ INLINEset_and(p, p, ceil);
+ }
+ *Tnew = A;
+ set_free(ceil);
+ return TRUE;
+ }
+ set_free(ceil);
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If single active variable not factored out above, then tautology ! */
+ if (cdata.vars_active == 1) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate cover */
+ } else if (cdata.vars_unate == cdata.vars_active) {
+ A = cubeunlist(T);
+ *Tnew = sf_contain(A);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Not much we can do about it */
+ } else {
+ return MAYBE;
+ }
+}
diff --git a/src/misc/espresso/contain.c b/src/misc/espresso/contain.c
new file mode 100644
index 00000000..180dceb6
--- /dev/null
+++ b/src/misc/espresso/contain.c
@@ -0,0 +1,441 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ contain.c -- set containment routines
+
+ These are complex routines for performing containment over a
+ family of sets, but they have the advantage of being much faster
+ than a straightforward n*n routine.
+
+ First the cubes are sorted by size, and as a secondary key they are
+ sorted so that if two cubes are equal they end up adjacent. We can
+ than quickly remove equal cubes from further consideration by
+ comparing each cube to its neighbor. Finally, because the cubes
+ are sorted by size, we need only check cubes which are larger (or
+ smaller) than a given cube for containment.
+*/
+
+#include "espresso.h"
+
+
+/*
+ sf_contain -- perform containment on a set family (delete sets which
+ are contained by some larger set in the family). No assumptions are
+ made about A, and the result will be returned in decreasing order of
+ set size.
+*/
+pset_family sf_contain(A)
+INOUT pset_family A; /* disposes of A */
+{
+ int cnt;
+ pset *A1;
+ pset_family R;
+
+ A1 = sf_sort(A, descend); /* sort into descending order */
+ cnt = rm_equal(A1, descend); /* remove duplicates */
+ cnt = rm_contain(A1); /* remove contained sets */
+ R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+ sf_free(A);
+ return R;
+}
+
+
+/*
+ sf_rev_contain -- perform containment on a set family (delete sets which
+ contain some smaller set in the family). No assumptions are made about
+ A, and the result will be returned in increasing order of set size
+*/
+pset_family sf_rev_contain(A)
+INOUT pset_family A; /* disposes of A */
+{
+ int cnt;
+ pset *A1;
+ pset_family R;
+
+ A1 = sf_sort(A, ascend); /* sort into ascending order */
+ cnt = rm_equal(A1, ascend); /* remove duplicates */
+ cnt = rm_rev_contain(A1); /* remove containing sets */
+ R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+ sf_free(A);
+ return R;
+}
+
+
+/*
+ sf_ind_contain -- perform containment on a set family (delete sets which
+ are contained by some larger set in the family). No assumptions are
+ made about A, and the result will be returned in decreasing order of
+ set size. Also maintains a set of row_indices to track which rows
+ disappear and how the rows end up permuted.
+*/
+pset_family sf_ind_contain(A, row_indices)
+INOUT pset_family A; /* disposes of A */
+INOUT int *row_indices; /* updated with the new values */
+{
+ int cnt;
+ pset *A1;
+ pset_family R;
+
+ A1 = sf_sort(A, descend); /* sort into descending order */
+ cnt = rm_equal(A1, descend); /* remove duplicates */
+ cnt = rm_contain(A1); /* remove contained sets */
+ R = sf_ind_unlist(A1, cnt, A->sf_size, row_indices, A->data);
+ sf_free(A);
+ return R;
+}
+
+
+/* sf_dupl -- delete duplicate sets in a set family */
+pset_family sf_dupl(A)
+INOUT pset_family A; /* disposes of A */
+{
+ register int cnt;
+ register pset *A1;
+ pset_family R;
+
+ A1 = sf_sort(A, descend); /* sort the set family */
+ cnt = rm_equal(A1, descend); /* remove duplicates */
+ R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+ sf_free(A);
+ return R;
+}
+
+
+/*
+ sf_union -- form the contained union of two set families (delete
+ sets which are contained by some larger set in the family). A and
+ B are assumed already sorted in decreasing order of set size (and
+ the SIZE field is assumed to contain the set size), and the result
+ will be returned sorted likewise.
+*/
+pset_family sf_union(A, B)
+INOUT pset_family A, B; /* disposes of A and B */
+{
+ int cnt;
+ pset_family R;
+ pset *A1 = sf_list(A), *B1 = sf_list(B), *E1;
+
+ E1 = ALLOC(pset, MAX(A->count, B->count) + 1);
+ cnt = rm2_equal(A1, B1, E1, descend);
+ cnt += rm2_contain(A1, B1) + rm2_contain(B1, A1);
+ R = sf_merge(A1, B1, E1, cnt, A->sf_size);
+ sf_free(A); sf_free(B);
+ return R;
+}
+
+
+/*
+ dist_merge -- consider all sets to be "or"-ed with "mask" and then
+ delete duplicates from the set family.
+*/
+pset_family dist_merge(A, mask)
+INOUT pset_family A; /* disposes of A */
+IN pset mask; /* defines variables to mask out */
+{
+ pset *A1;
+ int cnt;
+ pset_family R;
+
+ (void) set_copy(cube.temp[0], mask);
+ A1 = sf_sort(A, d1_order);
+ cnt = d1_rm_equal(A1, d1_order);
+ R = sf_unlist(A1, cnt, A->sf_size);
+ sf_free(A);
+ return R;
+}
+
+
+/*
+ d1merge -- perform an efficient distance-1 merge of cubes of A
+*/
+pset_family d1merge(A, var)
+INOUT pset_family A; /* disposes of A */
+IN int var;
+{
+ return dist_merge(A, cube.var_mask[var]);
+}
+
+
+
+/* d1_rm_equal -- distance-1 merge (merge cubes which are equal under a mask) */
+int d1_rm_equal(A1, compare)
+register pset *A1; /* array of set pointers */
+int (*compare)(); /* comparison function */
+{
+ register int i, j, dest;
+
+ dest = 0;
+ if (A1[0] != (pcube) NULL) {
+ for(i = 0, j = 1; A1[j] != (pcube) NULL; j++)
+ if ( (*compare)(&A1[i], &A1[j]) == 0) {
+ /* if sets are equal (under the mask) merge them */
+ (void) set_or(A1[i], A1[i], A1[j]);
+ } else {
+ /* sets are unequal, so save the set i */
+ A1[dest++] = A1[i];
+ i = j;
+ }
+ A1[dest++] = A1[i];
+ }
+ A1[dest] = (pcube) NULL;
+ return dest;
+}
+
+
+/* rm_equal -- scan a sorted array of set pointers for duplicate sets */
+int rm_equal(A1, compare)
+INOUT pset *A1; /* updated in place */
+IN int (*compare)();
+{
+ register pset *p, *pdest = A1;
+
+ if (*A1 != NULL) { /* If more than one set */
+ for(p = A1+1; *p != NULL; p++)
+ if ((*compare)(p, p-1) != 0)
+ *pdest++ = *(p-1);
+ *pdest++ = *(p-1);
+ *pdest = NULL;
+ }
+ return pdest - A1;
+}
+
+
+/* rm_contain -- perform containment over a sorted array of set pointers */
+int rm_contain(A1)
+INOUT pset *A1; /* updated in place */
+{
+ register pset *pa, *pb, *pcheck, a, b;
+ pset *pdest = A1;
+ int last_size = -1;
+
+ /* Loop for all cubes of A1 */
+ for(pa = A1; (a = *pa++) != NULL; ) {
+ /* Update the check pointer if the size has changed */
+ if (SIZE(a) != last_size)
+ last_size = SIZE(a), pcheck = pdest;
+ for(pb = A1; pb != pcheck; ) {
+ b = *pb++;
+ INLINEsetp_implies(a, b, /* when_false => */ continue);
+ goto lnext1;
+ }
+ /* set a was not contained by some larger set, so save it */
+ *pdest++ = a;
+ lnext1: ;
+ }
+
+ *pdest = NULL;
+ return pdest - A1;
+}
+
+
+/* rm_rev_contain -- perform rcontainment over a sorted array of set pointers */
+int rm_rev_contain(A1)
+INOUT pset *A1; /* updated in place */
+{
+ register pset *pa, *pb, *pcheck, a, b;
+ pset *pdest = A1;
+ int last_size = -1;
+
+ /* Loop for all cubes of A1 */
+ for(pa = A1; (a = *pa++) != NULL; ) {
+ /* Update the check pointer if the size has changed */
+ if (SIZE(a) != last_size)
+ last_size = SIZE(a), pcheck = pdest;
+ for(pb = A1; pb != pcheck; ) {
+ b = *pb++;
+ INLINEsetp_implies(b, a, /* when_false => */ continue);
+ goto lnext1;
+ }
+ /* the set a did not contain some smaller set, so save it */
+ *pdest++ = a;
+ lnext1: ;
+ }
+
+ *pdest = NULL;
+ return pdest - A1;
+}
+
+
+/* rm2_equal -- check two sorted arrays of set pointers for equal cubes */
+int rm2_equal(A1, B1, E1, compare)
+INOUT register pset *A1, *B1; /* updated in place */
+OUT pset *E1;
+IN int (*compare)();
+{
+ register pset *pda = A1, *pdb = B1, *pde = E1;
+
+ /* Walk through the arrays advancing pointer to larger cube */
+ for(; *A1 != NULL && *B1 != NULL; )
+ switch((*compare)(A1, B1)) {
+ case -1: /* "a" comes before "b" */
+ *pda++ = *A1++; break;
+ case 0: /* equal cubes */
+ *pde++ = *A1++; B1++; break;
+ case 1: /* "a" is to follow "b" */
+ *pdb++ = *B1++; break;
+ }
+
+ /* Finish moving down the pointers of A and B */
+ while (*A1 != NULL)
+ *pda++ = *A1++;
+ while (*B1 != NULL)
+ *pdb++ = *B1++;
+ *pda = *pdb = *pde = NULL;
+
+ return pde - E1;
+}
+
+
+/* rm2_contain -- perform containment between two arrays of set pointers */
+int rm2_contain(A1, B1)
+INOUT pset *A1; /* updated in place */
+IN pset *B1; /* unchanged */
+{
+ register pset *pa, *pb, a, b, *pdest = A1;
+
+ /* for each set in the first array ... */
+ for(pa = A1; (a = *pa++) != NULL; ) {
+ /* for each set in the second array which is larger ... */
+ for(pb = B1; (b = *pb++) != NULL && SIZE(b) > SIZE(a); ) {
+ INLINEsetp_implies(a, b, /* when_false => */ continue);
+ /* set was contained in some set of B, so don't save pointer */
+ goto lnext1;
+ }
+ /* set wasn't contained in any set of B, so save the pointer */
+ *pdest++ = a;
+ lnext1: ;
+ }
+
+ *pdest = NULL; /* sentinel */
+ return pdest - A1; /* # elements in A1 */
+}
+
+
+
+/* sf_sort -- sort the sets of A */
+pset *sf_sort(A, compare)
+IN pset_family A;
+IN int (*compare)();
+{
+ register pset p, last, *pdest, *A1;
+
+ /* Create a single array pointing to each cube of A */
+ pdest = A1 = ALLOC(pset, A->count + 1);
+ foreach_set(A, last, p) {
+ PUTSIZE(p, set_ord(p)); /* compute the set size */
+ *pdest++ = p; /* save the pointer */
+ }
+ *pdest = NULL; /* Sentinel -- never seen by sort */
+
+ /* Sort cubes by size */
+ qsort((char *) A1, A->count, sizeof(pset), compare);
+ return A1;
+}
+
+
+/* sf_list -- make a list of pointers to the sets in a set family */
+pset *sf_list(A)
+IN register pset_family A;
+{
+ register pset p, last, *pdest, *A1;
+
+ /* Create a single array pointing to each cube of A */
+ pdest = A1 = ALLOC(pset, A->count + 1);
+ foreach_set(A, last, p)
+ *pdest++ = p; /* save the pointer */
+ *pdest = NULL; /* Sentinel */
+ return A1;
+}
+
+
+/* sf_unlist -- make a set family out of a list of pointers to sets */
+pset_family sf_unlist(A1, totcnt, size)
+IN pset *A1;
+IN int totcnt, size;
+{
+ register pset pr, p, *pa;
+ pset_family R = sf_new(totcnt, size);
+
+ R->count = totcnt;
+ for(pr = R->data, pa = A1; (p = *pa++) != NULL; pr += R->wsize)
+ INLINEset_copy(pr, p);
+ FREE(A1);
+ return R;
+}
+
+
+/* sf_ind_unlist -- make a set family out of a list of pointers to sets */
+pset_family sf_ind_unlist(A1, totcnt, size, row_indices, pfirst)
+IN pset *A1;
+IN int totcnt, size;
+INOUT int *row_indices;
+IN register pset pfirst;
+{
+ register pset pr, p, *pa;
+ register int i, *new_row_indices;
+ pset_family R = sf_new(totcnt, size);
+
+ R->count = totcnt;
+ new_row_indices = ALLOC(int, totcnt);
+ for(pr = R->data, pa = A1, i=0; (p = *pa++) != NULL; pr += R->wsize, i++) {
+ INLINEset_copy(pr, p);
+ new_row_indices[i] = row_indices[(p - pfirst)/R->wsize];
+ }
+ for(i = 0; i < totcnt; i++)
+ row_indices[i] = new_row_indices[i];
+ FREE(new_row_indices);
+ FREE(A1);
+ return R;
+}
+
+
+/* sf_merge -- merge three sorted lists of set pointers */
+pset_family sf_merge(A1, B1, E1, totcnt, size)
+INOUT pset *A1, *B1, *E1; /* will be disposed of */
+IN int totcnt, size;
+{
+ register pset pr, ps, *pmin, *pmid, *pmax;
+ pset_family R;
+ pset *temp[3], *swap;
+ int i, j, n;
+
+ /* Allocate the result set_family */
+ R = sf_new(totcnt, size);
+ R->count = totcnt;
+ pr = R->data;
+
+ /* Quick bubble sort to order the top member of the three arrays */
+ n = 3; temp[0] = A1; temp[1] = B1; temp[2] = E1;
+ for(i = 0; i < n-1; i++)
+ for(j = i+1; j < n; j++)
+ if (desc1(*temp[i], *temp[j]) > 0) {
+ swap = temp[j];
+ temp[j] = temp[i];
+ temp[i] = swap;
+ }
+ pmin = temp[0]; pmid = temp[1]; pmax = temp[2];
+
+ /* Save the minimum element, then update pmin, pmid, pmax */
+ while (*pmin != (pset) NULL) {
+ ps = *pmin++;
+ INLINEset_copy(pr, ps);
+ pr += R->wsize;
+ if (desc1(*pmin, *pmax) > 0) {
+ swap = pmax; pmax = pmin; pmin = pmid; pmid = swap;
+ } else if (desc1(*pmin, *pmid) > 0) {
+ swap = pmin; pmin = pmid; pmid = swap;
+ }
+ }
+
+ FREE(A1);
+ FREE(B1);
+ FREE(E1);
+ return R;
+}
diff --git a/src/misc/espresso/cubehack.c b/src/misc/espresso/cubehack.c
new file mode 100644
index 00000000..8e1724fc
--- /dev/null
+++ b/src/misc/espresso/cubehack.c
@@ -0,0 +1,138 @@
+/*
+ * Revision Control Information
+ *
+ * $Source: /vol/opua/opua2/sis/sis-1.1/common/src/sis/node/RCS/cubehack.c,v $
+ * $Author: sis $
+ * $Revision: 1.2 $
+ * $Date: 1992/05/06 18:57:41 $
+ *
+ */
+/*
+#include "sis.h"
+#include "node_int.h"
+
+#ifdef lint
+struct cube_struct cube;
+bool summary;
+bool trace;
+bool remove_essential;
+bool force_irredundant;
+bool unwrap_onset;
+bool single_expand;
+bool pos;
+bool recompute_onset;
+bool use_super_gasp;
+bool use_random_order;
+#endif
+*/
+#include "espresso.h"
+
+
+void
+cautious_define_cube_size(n)
+int n;
+{
+ if (cube.fullset != 0 && cube.num_binary_vars == n)
+ return;
+ if (cube.fullset != 0) {
+ setdown_cube();
+ FREE(cube.part_size);
+ }
+ cube.num_binary_vars = cube.num_vars = n;
+ cube.part_size = ALLOC(int, n);
+ cube_setup();
+}
+
+
+void
+define_cube_size(n)
+int n;
+{
+ register int q, i;
+ static int called_before = 0;
+
+ /* check if the cube is already just the right size */
+ if (cube.fullset != 0 && cube.num_binary_vars == n && cube.num_vars == n)
+ return;
+
+ /* We can't handle more than 100 inputs */
+ if (n > 100) {
+ cautious_define_cube_size(n);
+ called_before = 0;
+ return;
+ }
+
+ if (cube.fullset == 0 || ! called_before) {
+ cautious_define_cube_size(100);
+ called_before = 1;
+ }
+
+ cube.num_vars = n;
+ cube.num_binary_vars = n;
+ cube.num_mv_vars = 0;
+ cube.output = -1;
+ cube.size = n * 2;
+
+ /* first_part, last_part, first_word, last_word, part_size OKAY */
+ /* cube.sparse is OKAY */
+
+ /* need to completely re-make cube.fullset and cube.binary_mask */
+ (void) set_fill(cube.fullset, n*2);
+ (void) set_fill(cube.binary_mask, n*2);
+
+ /* need to resize each set in cube.var_mask and cube.temp */
+ q = cube.fullset[0];
+ for(i = 0; i < cube.num_vars; i++)
+ cube.var_mask[i][0] = q;
+ for(i = 0; i < CUBE_TEMP; i++)
+ cube.temp[i][0] = q;
+
+ /* need to resize cube.emptyset and cube.mv_mask */
+ cube.emptyset[0] = q;
+ cube.mv_mask[0] = q;
+
+ /* need to reset the inword and inmask */
+ if (cube.num_binary_vars != 0) {
+ cube.inword = cube.last_word[cube.num_binary_vars - 1];
+ cube.inmask = cube.binary_mask[cube.inword] & DISJOINT;
+ } else {
+ cube.inword = -1;
+ cube.inmask = 0;
+ }
+
+ /* cdata (entire structure) is OKAY */
+}
+
+
+void
+undefine_cube_size()
+{
+ if (cube.num_binary_vars > 100) {
+ if (cube.fullset != 0) {
+ setdown_cube();
+ FREE(cube.part_size);
+ }
+ } else {
+ cube.num_vars = cube.num_binary_vars = 100;
+ if (cube.fullset != 0) {
+ setdown_cube();
+ FREE(cube.part_size);
+ }
+ }
+}
+
+
+void
+set_espresso_flags()
+{
+ summary = FALSE;
+ trace = FALSE;
+ remove_essential = TRUE;
+ force_irredundant = TRUE;
+ unwrap_onset = TRUE;
+ single_expand = FALSE;
+ pos = FALSE;
+ recompute_onset = FALSE;
+ use_super_gasp = FALSE;
+ use_random_order = FALSE;
+}
diff --git a/src/misc/espresso/cubestr.c b/src/misc/espresso/cubestr.c
new file mode 100644
index 00000000..77389e73
--- /dev/null
+++ b/src/misc/espresso/cubestr.c
@@ -0,0 +1,152 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ Module: cubestr.c -- routines for managing the global cube structure
+*/
+
+#include "espresso.h"
+
+/*
+ cube_setup -- assume that the fields "num_vars", "num_binary_vars", and
+ part_size[num_binary_vars .. num_vars-1] are setup, and initialize the
+ rest of cube and cdata.
+
+ If a part_size is < 0, then the field size is abs(part_size) and the
+ field read from the input is symbolic.
+*/
+void cube_setup()
+{
+ register int i, var;
+ register pcube p;
+
+ if (cube.num_binary_vars < 0 || cube.num_vars < cube.num_binary_vars)
+ fatal("cube size is silly, error in .i/.o or .mv");
+
+ cube.num_mv_vars = cube.num_vars - cube.num_binary_vars;
+ cube.output = cube.num_mv_vars > 0 ? cube.num_vars - 1 : -1;
+
+ cube.size = 0;
+ cube.first_part = ALLOC(int, cube.num_vars);
+ cube.last_part = ALLOC(int, cube.num_vars);
+ cube.first_word = ALLOC(int, cube.num_vars);
+ cube.last_word = ALLOC(int, cube.num_vars);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (var < cube.num_binary_vars)
+ cube.part_size[var] = 2;
+ cube.first_part[var] = cube.size;
+ cube.first_word[var] = WHICH_WORD(cube.size);
+ cube.size += ABS(cube.part_size[var]);
+ cube.last_part[var] = cube.size - 1;
+ cube.last_word[var] = WHICH_WORD(cube.size - 1);
+ }
+
+ cube.var_mask = ALLOC(pset, cube.num_vars);
+ cube.sparse = ALLOC(int, cube.num_vars);
+ cube.binary_mask = new_cube();
+ cube.mv_mask = new_cube();
+ for(var = 0; var < cube.num_vars; var++) {
+ p = cube.var_mask[var] = new_cube();
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+ set_insert(p, i);
+ if (var < cube.num_binary_vars) {
+ INLINEset_or(cube.binary_mask, cube.binary_mask, p);
+ cube.sparse[var] = 0;
+ } else {
+ INLINEset_or(cube.mv_mask, cube.mv_mask, p);
+ cube.sparse[var] = 1;
+ }
+ }
+ if (cube.num_binary_vars == 0)
+ cube.inword = -1;
+ else {
+ cube.inword = cube.last_word[cube.num_binary_vars - 1];
+ cube.inmask = cube.binary_mask[cube.inword] & DISJOINT;
+ }
+
+ cube.temp = ALLOC(pset, CUBE_TEMP);
+ for(i = 0; i < CUBE_TEMP; i++)
+ cube.temp[i] = new_cube();
+ cube.fullset = set_fill(new_cube(), cube.size);
+ cube.emptyset = new_cube();
+
+ cdata.part_zeros = ALLOC(int, cube.size);
+ cdata.var_zeros = ALLOC(int, cube.num_vars);
+ cdata.parts_active = ALLOC(int, cube.num_vars);
+ cdata.is_unate = ALLOC(int, cube.num_vars);
+}
+
+/*
+ setdown_cube -- free memory allocated for the cube/cdata structs
+ (free's all but the part_size array)
+
+ (I wanted to call this cube_setdown, but that violates the 8-character
+ external routine limit on the IBM !)
+*/
+void setdown_cube()
+{
+ register int i, var;
+
+ FREE(cube.first_part);
+ FREE(cube.last_part);
+ FREE(cube.first_word);
+ FREE(cube.last_word);
+ FREE(cube.sparse);
+
+ free_cube(cube.binary_mask);
+ free_cube(cube.mv_mask);
+ free_cube(cube.fullset);
+ free_cube(cube.emptyset);
+ for(var = 0; var < cube.num_vars; var++)
+ free_cube(cube.var_mask[var]);
+ FREE(cube.var_mask);
+
+ for(i = 0; i < CUBE_TEMP; i++)
+ free_cube(cube.temp[i]);
+ FREE(cube.temp);
+
+ FREE(cdata.part_zeros);
+ FREE(cdata.var_zeros);
+ FREE(cdata.parts_active);
+ FREE(cdata.is_unate);
+
+ cube.first_part = cube.last_part = (int *) NULL;
+ cube.first_word = cube.last_word = (int *) NULL;
+ cube.sparse = (int *) NULL;
+ cube.binary_mask = cube.mv_mask = (pcube) NULL;
+ cube.fullset = cube.emptyset = (pcube) NULL;
+ cube.var_mask = cube.temp = (pcube *) NULL;
+
+ cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL;
+ cdata.is_unate = (bool *) NULL;
+}
+
+
+void save_cube_struct()
+{
+ temp_cube_save = cube; /* structure copy ! */
+ temp_cdata_save = cdata; /* "" */
+
+ cube.first_part = cube.last_part = (int *) NULL;
+ cube.first_word = cube.last_word = (int *) NULL;
+ cube.part_size = (int *) NULL;
+ cube.binary_mask = cube.mv_mask = (pcube) NULL;
+ cube.fullset = cube.emptyset = (pcube) NULL;
+ cube.var_mask = cube.temp = (pcube *) NULL;
+
+ cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL;
+ cdata.is_unate = (bool *) NULL;
+}
+
+
+void restore_cube_struct()
+{
+ cube = temp_cube_save; /* structure copy ! */
+ cdata = temp_cdata_save; /* "" */
+}
diff --git a/src/misc/espresso/cvrin.c b/src/misc/espresso/cvrin.c
new file mode 100644
index 00000000..7790b38b
--- /dev/null
+++ b/src/misc/espresso/cvrin.c
@@ -0,0 +1,810 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: cvrin.c
+ purpose: cube and cover input routines
+*/
+
+#include "espresso.h"
+
+static bool line_length_error;
+static int lineno;
+
+void skip_line(fpin, fpout, echo)
+register FILE *fpin, *fpout;
+register bool echo;
+{
+ register int ch;
+ while ((ch=getc(fpin)) != EOF && ch != '\n')
+ if (echo)
+ putc(ch, fpout);
+ if (echo)
+ putc('\n', fpout);
+ lineno++;
+}
+
+char *get_word(fp, word)
+register FILE *fp;
+register char *word;
+{
+ register int ch, i = 0;
+ while ((ch = getc(fp)) != EOF && isspace(ch))
+ ;
+ word[i++] = ch;
+ while ((ch = getc(fp)) != EOF && ! isspace(ch))
+ word[i++] = ch;
+ word[i++] = '\0';
+ return word;
+}
+
+/*
+ * Yes, I know this routine is a mess
+ */
+void read_cube(fp, PLA)
+register FILE *fp;
+pPLA PLA;
+{
+ register int var, i;
+ pcube cf = cube.temp[0], cr = cube.temp[1], cd = cube.temp[2];
+ bool savef = FALSE, saved = FALSE, saver = FALSE;
+ char token[256]; /* for kiss read hack */
+ int varx, first, last, offset; /* for kiss read hack */
+
+ set_clear(cf, cube.size);
+
+ /* Loop and read binary variables */
+ for(var = 0; var < cube.num_binary_vars; var++)
+ switch(getc(fp)) {
+ case EOF:
+ goto bad_char;
+ case '\n':
+ if (! line_length_error)
+ (void) fprintf(stderr, "product term(s) %s\n",
+ "span more than one line (warning only)");
+ line_length_error = TRUE;
+ lineno++;
+ var--;
+ break;
+ case ' ': case '|': case '\t':
+ var--;
+ break;
+ case '2': case '-':
+ set_insert(cf, var*2+1);
+ case '0':
+ set_insert(cf, var*2);
+ break;
+ case '1':
+ set_insert(cf, var*2+1);
+ break;
+ case '?':
+ break;
+ default:
+ goto bad_char;
+ }
+
+
+ /* Loop for the all but one of the multiple-valued variables */
+ for(var = cube.num_binary_vars; var < cube.num_vars-1; var++)
+
+ /* Read a symbolic multiple-valued variable */
+ if (cube.part_size[var] < 0) {
+ (void) fscanf(fp, "%s", token);
+ if (equal(token, "-") || equal(token, "ANY")) {
+ if (kiss && var == cube.num_vars - 2) {
+ /* leave it empty */
+ } else {
+ /* make it full */
+ set_or(cf, cf, cube.var_mask[var]);
+ }
+ } else if (equal(token, "~")) {
+ ;
+ /* leave it empty ... (?) */
+ } else {
+ if (kiss && var == cube.num_vars - 2)
+ varx = var - 1, offset = ABS(cube.part_size[var-1]);
+ else
+ varx = var, offset = 0;
+ /* Find the symbolic label in the label table */
+ first = cube.first_part[varx];
+ last = cube.last_part[varx];
+ for(i = first; i <= last; i++)
+ if (PLA->label[i] == (char *) NULL) {
+ PLA->label[i] = util_strsav(token); /* add new label */
+ set_insert(cf, i+offset);
+ break;
+ } else if (equal(PLA->label[i], token)) {
+ set_insert(cf, i+offset); /* use column i */
+ break;
+ }
+ if (i > last) {
+ (void) fprintf(stderr,
+"declared size of variable %d (counting from variable 0) is too small\n", var);
+ exit(-1);
+ }
+ }
+
+ } else for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+ switch (getc(fp)) {
+ case EOF:
+ goto bad_char;
+ case '\n':
+ if (! line_length_error)
+ (void) fprintf(stderr, "product term(s) %s\n",
+ "span more than one line (warning only)");
+ line_length_error = TRUE;
+ lineno++;
+ i--;
+ break;
+ case ' ': case '|': case '\t':
+ i--;
+ break;
+ case '1':
+ set_insert(cf, i);
+ case '0':
+ break;
+ default:
+ goto bad_char;
+ }
+
+ /* Loop for last multiple-valued variable */
+ if (kiss) {
+ saver = savef = TRUE;
+ (void) set_xor(cr, cf, cube.var_mask[cube.num_vars - 2]);
+ } else
+ set_copy(cr, cf);
+ set_copy(cd, cf);
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+ switch (getc(fp)) {
+ case EOF:
+ goto bad_char;
+ case '\n':
+ if (! line_length_error)
+ (void) fprintf(stderr, "product term(s) %s\n",
+ "span more than one line (warning only)");
+ line_length_error = TRUE;
+ lineno++;
+ i--;
+ break;
+ case ' ': case '|': case '\t':
+ i--;
+ break;
+ case '4': case '1':
+ if (PLA->pla_type & F_type)
+ set_insert(cf, i), savef = TRUE;
+ break;
+ case '3': case '0':
+ if (PLA->pla_type & R_type)
+ set_insert(cr, i), saver = TRUE;
+ break;
+ case '2': case '-':
+ if (PLA->pla_type & D_type)
+ set_insert(cd, i), saved = TRUE;
+ case '~':
+ break;
+ default:
+ goto bad_char;
+ }
+ if (savef) PLA->F = sf_addset(PLA->F, cf);
+ if (saved) PLA->D = sf_addset(PLA->D, cd);
+ if (saver) PLA->R = sf_addset(PLA->R, cr);
+ return;
+
+bad_char:
+ (void) fprintf(stderr, "(warning): input line #%d ignored\n", lineno);
+ skip_line(fp, stdout, TRUE);
+ return;
+}
+void parse_pla(fp, PLA)
+IN FILE *fp;
+INOUT pPLA PLA;
+{
+ int i, var, ch, np, last;
+ char word[256];
+
+ lineno = 1;
+ line_length_error = FALSE;
+
+loop:
+ switch(ch = getc(fp)) {
+ case EOF:
+ return;
+
+ case '\n':
+ lineno++;
+
+ case ' ': case '\t': case '\f': case '\r':
+ break;
+
+ case '#':
+ (void) ungetc(ch, fp);
+ skip_line(fp, stdout, echo_comments);
+ break;
+
+ case '.':
+ /* .i gives the cube input size (binary-functions only) */
+ if (equal(get_word(fp, word), "i")) {
+ if (cube.fullset != NULL) {
+ (void) fprintf(stderr, "extra .i ignored\n");
+ skip_line(fp, stdout, /* echo */ FALSE);
+ } else {
+ if (fscanf(fp, "%d", &cube.num_binary_vars) != 1)
+ fatal("error reading .i");
+ cube.num_vars = cube.num_binary_vars + 1;
+ cube.part_size = ALLOC(int, cube.num_vars);
+ }
+
+ /* .o gives the cube output size (binary-functions only) */
+ } else if (equal(word, "o")) {
+ if (cube.fullset != NULL) {
+ (void) fprintf(stderr, "extra .o ignored\n");
+ skip_line(fp, stdout, /* echo */ FALSE);
+ } else {
+ if (cube.part_size == NULL)
+ fatal(".o cannot appear before .i");
+ if (fscanf(fp, "%d", &(cube.part_size[cube.num_vars-1]))!=1)
+ fatal("error reading .o");
+ cube_setup();
+ PLA_labels(PLA);
+ }
+
+ /* .mv gives the cube size for a multiple-valued function */
+ } else if (equal(word, "mv")) {
+ if (cube.fullset != NULL) {
+ (void) fprintf(stderr, "extra .mv ignored\n");
+ skip_line(fp, stdout, /* echo */ FALSE);
+ } else {
+ if (cube.part_size != NULL)
+ fatal("cannot mix .i and .mv");
+ if (fscanf(fp,"%d %d",
+ &cube.num_vars,&cube.num_binary_vars) != 2)
+ fatal("error reading .mv");
+ if (cube.num_binary_vars < 0)
+fatal("num_binary_vars (second field of .mv) cannot be negative");
+ if (cube.num_vars < cube.num_binary_vars)
+ fatal(
+"num_vars (1st field of .mv) must exceed num_binary_vars (2nd field of .mv)");
+ cube.part_size = ALLOC(int, cube.num_vars);
+ for(var=cube.num_binary_vars; var < cube.num_vars; var++)
+ if (fscanf(fp, "%d", &(cube.part_size[var])) != 1)
+ fatal("error reading .mv");
+ cube_setup();
+ PLA_labels(PLA);
+ }
+
+ /* .p gives the number of product terms -- we ignore it */
+ } else if (equal(word, "p"))
+ (void) fscanf(fp, "%d", &np);
+ /* .e and .end specify the end of the file */
+ else if (equal(word, "e") || equal(word,"end")) {
+ if (cube.fullset == NULL) {
+ /* fatal("unknown PLA size, need .i/.o or .mv");*/
+ } else if (PLA->F == NULL) {
+ PLA->F = new_cover(10);
+ PLA->D = new_cover(10);
+ PLA->R = new_cover(10);
+ }
+ return;
+ }
+ /* .kiss turns on the kiss-hack option */
+ else if (equal(word, "kiss"))
+ kiss = TRUE;
+
+ /* .type specifies a logical type for the PLA */
+ else if (equal(word, "type")) {
+ (void) get_word(fp, word);
+ for(i = 0; pla_types[i].key != 0; i++)
+ if (equal(pla_types[i].key + 1, word)) {
+ PLA->pla_type = pla_types[i].value;
+ break;
+ }
+ if (pla_types[i].key == 0)
+ fatal("unknown type in .type command");
+
+ /* parse the labels */
+ } else if (equal(word, "ilb")) {
+ if (cube.fullset == NULL)
+ fatal("PLA size must be declared before .ilb or .ob");
+ if (PLA->label == NULL)
+ PLA_labels(PLA);
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ (void) get_word(fp, word);
+ i = cube.first_part[var];
+ PLA->label[i+1] = util_strsav(word);
+ PLA->label[i] = ALLOC(char, strlen(word) + 6);
+ (void) sprintf(PLA->label[i], "%s.bar", word);
+ }
+ } else if (equal(word, "ob")) {
+ if (cube.fullset == NULL)
+ fatal("PLA size must be declared before .ilb or .ob");
+ if (PLA->label == NULL)
+ PLA_labels(PLA);
+ var = cube.num_vars - 1;
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ (void) get_word(fp, word);
+ PLA->label[i] = util_strsav(word);
+ }
+ /* .label assigns labels to multiple-valued variables */
+ } else if (equal(word, "label")) {
+ if (cube.fullset == NULL)
+ fatal("PLA size must be declared before .label");
+ if (PLA->label == NULL)
+ PLA_labels(PLA);
+ if (fscanf(fp, "var=%d", &var) != 1)
+ fatal("Error reading labels");
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ (void) get_word(fp, word);
+ PLA->label[i] = util_strsav(word);
+ }
+
+ } else if (equal(word, "symbolic")) {
+ symbolic_t *newlist, *p1;
+ if (read_symbolic(fp, PLA, word, &newlist)) {
+ if (PLA->symbolic == NIL(symbolic_t)) {
+ PLA->symbolic = newlist;
+ } else {
+ for(p1=PLA->symbolic;p1->next!=NIL(symbolic_t);
+ p1=p1->next){
+ }
+ p1->next = newlist;
+ }
+ } else {
+ fatal("error reading .symbolic");
+ }
+
+ } else if (equal(word, "symbolic-output")) {
+ symbolic_t *newlist, *p1;
+ if (read_symbolic(fp, PLA, word, &newlist)) {
+ if (PLA->symbolic_output == NIL(symbolic_t)) {
+ PLA->symbolic_output = newlist;
+ } else {
+ for(p1=PLA->symbolic_output;p1->next!=NIL(symbolic_t);
+ p1=p1->next){
+ }
+ p1->next = newlist;
+ }
+ } else {
+ fatal("error reading .symbolic-output");
+ }
+
+ /* .phase allows a choice of output phases */
+ } else if (equal(word, "phase")) {
+ if (cube.fullset == NULL)
+ fatal("PLA size must be declared before .phase");
+ if (PLA->phase != NULL) {
+ (void) fprintf(stderr, "extra .phase ignored\n");
+ skip_line(fp, stdout, /* echo */ FALSE);
+ } else {
+ do ch = getc(fp); while (ch == ' ' || ch == '\t');
+ (void) ungetc(ch, fp);
+ PLA->phase = set_save(cube.fullset);
+ last = cube.last_part[cube.num_vars - 1];
+ for(i=cube.first_part[cube.num_vars - 1]; i <= last; i++)
+ if ((ch = getc(fp)) == '0')
+ set_remove(PLA->phase, i);
+ else if (ch != '1')
+ fatal("only 0 or 1 allowed in phase description");
+ }
+
+ /* .pair allows for bit-pairing input variables */
+ } else if (equal(word, "pair")) {
+ int j;
+ if (PLA->pair != NULL) {
+ (void) fprintf(stderr, "extra .pair ignored\n");
+ } else {
+ ppair pair;
+ PLA->pair = pair = ALLOC(pair_t, 1);
+ if (fscanf(fp, "%d", &(pair->cnt)) != 1)
+ fatal("syntax error in .pair");
+ pair->var1 = ALLOC(int, pair->cnt);
+ pair->var2 = ALLOC(int, pair->cnt);
+ for(i = 0; i < pair->cnt; i++) {
+ (void) get_word(fp, word);
+ if (word[0] == '(') (void) strcpy(word, word+1);
+ if (label_index(PLA, word, &var, &j)) {
+ pair->var1[i] = var+1;
+ } else {
+ fatal("syntax error in .pair");
+ }
+
+ (void) get_word(fp, word);
+ if (word[strlen(word)-1] == ')') {
+ word[strlen(word)-1]='\0';
+ }
+ if (label_index(PLA, word, &var, &j)) {
+ pair->var2[i] = var+1;
+ } else {
+ fatal("syntax error in .pair");
+ }
+ }
+ }
+
+ } else {
+ if (echo_unknown_commands)
+ printf("%c%s ", ch, word);
+ skip_line(fp, stdout, echo_unknown_commands);
+ }
+ break;
+ default:
+ (void) ungetc(ch, fp);
+ if (cube.fullset == NULL) {
+/* fatal("unknown PLA size, need .i/.o or .mv");*/
+ if (echo_comments)
+ putchar('#');
+ skip_line(fp, stdout, echo_comments);
+ break;
+ }
+ if (PLA->F == NULL) {
+ PLA->F = new_cover(10);
+ PLA->D = new_cover(10);
+ PLA->R = new_cover(10);
+ }
+ read_cube(fp, PLA);
+ }
+ goto loop;
+}
+/*
+ read_pla -- read a PLA from a file
+
+ Input stops when ".e" is encountered in the input file, or upon reaching
+ end of file.
+
+ Returns the PLA in the variable PLA after massaging the "symbolic"
+ representation into a positional cube notation of the ON-set, OFF-set,
+ and the DC-set.
+
+ needs_dcset and needs_offset control the computation of the OFF-set
+ and DC-set (i.e., if either needs to be computed, then it will be
+ computed via complement only if the corresponding option is TRUE.)
+ pla_type specifies the interpretation to be used when reading the
+ PLA.
+
+ The phase of the output functions is adjusted according to the
+ global option "pos" or according to an imbedded .phase option in
+ the input file. Note that either phase option implies that the
+ OFF-set be computed regardless of whether the caller needs it
+ explicitly or not.
+
+ Bit pairing of the binary variables is performed according to an
+ imbedded .pair option in the input file.
+
+ The global cube structure also reflects the sizes of the PLA which
+ was just read. If these fields have already been set, then any
+ subsequent PLA must conform to these sizes.
+
+ The global flags trace and summary control the output produced
+ during the read.
+
+ Returns a status code as a result:
+ EOF (-1) : End of file reached before any data was read
+ > 0 : Operation successful
+*/
+
+int read_pla(fp, needs_dcset, needs_offset, pla_type, PLA_return)
+IN FILE *fp;
+IN bool needs_dcset, needs_offset;
+IN int pla_type;
+OUT pPLA *PLA_return;
+{
+ pPLA PLA;
+ int i, second, third;
+ long time;
+ cost_t cost;
+
+ /* Allocate and initialize the PLA structure */
+ PLA = *PLA_return = new_PLA();
+ PLA->pla_type = pla_type;
+
+ /* Read the pla */
+ time = ptime();
+ parse_pla(fp, PLA);
+
+ /* Check for nothing on the file -- implies reached EOF */
+ if (PLA->F == NULL) {
+ return EOF;
+ }
+
+ /* This hack merges the next-state field with the outputs */
+ for(i = 0; i < cube.num_vars; i++) {
+ cube.part_size[i] = ABS(cube.part_size[i]);
+ }
+ if (kiss) {
+ third = cube.num_vars - 3;
+ second = cube.num_vars - 2;
+ if (cube.part_size[third] != cube.part_size[second]) {
+ (void) fprintf(stderr," with .kiss option, third to last and second\n");
+ (void) fprintf(stderr, "to last variables must be the same size.\n");
+ return EOF;
+ }
+ for(i = 0; i < cube.part_size[second]; i++) {
+ PLA->label[i + cube.first_part[second]] =
+ util_strsav(PLA->label[i + cube.first_part[third]]);
+ }
+ cube.part_size[second] += cube.part_size[cube.num_vars-1];
+ cube.num_vars--;
+ setdown_cube();
+ cube_setup();
+ }
+
+ if (trace) {
+ totals(time, READ_TIME, PLA->F, &cost);
+ }
+
+ /* Decide how to break PLA into ON-set, OFF-set and DC-set */
+ time = ptime();
+ if (pos || PLA->phase != NULL || PLA->symbolic_output != NIL(symbolic_t)) {
+ needs_offset = TRUE;
+ }
+ if (needs_offset && (PLA->pla_type==F_type || PLA->pla_type==FD_type)) {
+ free_cover(PLA->R);
+ PLA->R = complement(cube2list(PLA->F, PLA->D));
+ } else if (needs_dcset && PLA->pla_type == FR_type) {
+ pcover X;
+ free_cover(PLA->D);
+ /* hack, why not? */
+ X = d1merge(sf_join(PLA->F, PLA->R), cube.num_vars - 1);
+ PLA->D = complement(cube1list(X));
+ free_cover(X);
+ } else if (PLA->pla_type == R_type || PLA->pla_type == DR_type) {
+ free_cover(PLA->F);
+ PLA->F = complement(cube2list(PLA->D, PLA->R));
+ }
+
+ if (trace) {
+ totals(time, COMPL_TIME, PLA->R, &cost);
+ }
+
+ /* Check for phase rearrangement of the functions */
+ if (pos) {
+ pcover onset = PLA->F;
+ PLA->F = PLA->R;
+ PLA->R = onset;
+ PLA->phase = new_cube();
+ set_diff(PLA->phase, cube.fullset, cube.var_mask[cube.num_vars-1]);
+ } else if (PLA->phase != NULL) {
+ (void) set_phase(PLA);
+ }
+
+ /* Setup minimization for two-bit decoders */
+ if (PLA->pair != (ppair) NULL) {
+ set_pair(PLA);
+ }
+
+ if (PLA->symbolic != NIL(symbolic_t)) {
+ EXEC(map_symbolic(PLA), "MAP-INPUT ", PLA->F);
+ }
+ if (PLA->symbolic_output != NIL(symbolic_t)) {
+ EXEC(map_output_symbolic(PLA), "MAP-OUTPUT ", PLA->F);
+ if (needs_offset) {
+ free_cover(PLA->R);
+EXECUTE(PLA->R=complement(cube2list(PLA->F,PLA->D)), COMPL_TIME, PLA->R, cost);
+ }
+ }
+
+ return 1;
+}
+
+void PLA_summary(PLA)
+pPLA PLA;
+{
+ int var, i;
+ symbolic_list_t *p2;
+ symbolic_t *p1;
+
+ printf("# PLA is %s", PLA->filename);
+ if (cube.num_binary_vars == cube.num_vars - 1)
+ printf(" with %d inputs and %d outputs\n",
+ cube.num_binary_vars, cube.part_size[cube.num_vars - 1]);
+ else {
+ printf(" with %d variables (%d binary, mv sizes",
+ cube.num_vars, cube.num_binary_vars);
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++)
+ printf(" %d", cube.part_size[var]);
+ printf(")\n");
+ }
+ printf("# ON-set cost is %s\n", print_cost(PLA->F));
+ printf("# OFF-set cost is %s\n", print_cost(PLA->R));
+ printf("# DC-set cost is %s\n", print_cost(PLA->D));
+ if (PLA->phase != NULL)
+ printf("# phase is %s\n", pc1(PLA->phase));
+ if (PLA->pair != NULL) {
+ printf("# two-bit decoders:");
+ for(i = 0; i < PLA->pair->cnt; i++)
+ printf(" (%d %d)", PLA->pair->var1[i], PLA->pair->var2[i]);
+ printf("\n");
+ }
+ if (PLA->symbolic != NIL(symbolic_t)) {
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ printf("# symbolic: ");
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ printf(" %d", p2->variable);
+ }
+ printf("\n");
+ }
+ }
+ if (PLA->symbolic_output != NIL(symbolic_t)) {
+ for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1->next) {
+ printf("# output symbolic: ");
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ printf(" %d", p2->pos);
+ }
+ printf("\n");
+ }
+ }
+ (void) fflush(stdout);
+}
+
+
+pPLA new_PLA()
+{
+ pPLA PLA;
+
+ PLA = ALLOC(PLA_t, 1);
+ PLA->F = PLA->D = PLA->R = (pcover) NULL;
+ PLA->phase = (pcube) NULL;
+ PLA->pair = (ppair) NULL;
+ PLA->label = (char **) NULL;
+ PLA->filename = (char *) NULL;
+ PLA->pla_type = 0;
+ PLA->symbolic = NIL(symbolic_t);
+ PLA->symbolic_output = NIL(symbolic_t);
+ return PLA;
+}
+
+
+PLA_labels(PLA)
+pPLA PLA;
+{
+ int i;
+
+ PLA->label = ALLOC(char *, cube.size);
+ for(i = 0; i < cube.size; i++)
+ PLA->label[i] = (char *) NULL;
+}
+
+
+void free_PLA(PLA)
+pPLA PLA;
+{
+ symbolic_list_t *p2, *p2next;
+ symbolic_t *p1, *p1next;
+ int i;
+
+ if (PLA->F != (pcover) NULL)
+ free_cover(PLA->F);
+ if (PLA->R != (pcover) NULL)
+ free_cover(PLA->R);
+ if (PLA->D != (pcover) NULL)
+ free_cover(PLA->D);
+ if (PLA->phase != (pcube) NULL)
+ free_cube(PLA->phase);
+ if (PLA->pair != (ppair) NULL) {
+ FREE(PLA->pair->var1);
+ FREE(PLA->pair->var2);
+ FREE(PLA->pair);
+ }
+ if (PLA->label != NULL) {
+ for(i = 0; i < cube.size; i++)
+ if (PLA->label[i] != NULL)
+ FREE(PLA->label[i]);
+ FREE(PLA->label);
+ }
+ if (PLA->filename != NULL) {
+ FREE(PLA->filename);
+ }
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1next) {
+ for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) {
+ p2next = p2->next;
+ FREE(p2);
+ }
+ p1next = p1->next;
+ FREE(p1);
+ }
+ PLA->symbolic = NIL(symbolic_t);
+ for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1next) {
+ for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) {
+ p2next = p2->next;
+ FREE(p2);
+ }
+ p1next = p1->next;
+ FREE(p1);
+ }
+ PLA->symbolic_output = NIL(symbolic_t);
+ FREE(PLA);
+}
+
+
+int read_symbolic(fp, PLA, word, retval)
+FILE *fp;
+pPLA PLA;
+char *word; /* scratch string for words */
+symbolic_t **retval;
+{
+ symbolic_list_t *listp, *prev_listp;
+ symbolic_label_t *labelp, *prev_labelp;
+ symbolic_t *newlist;
+ int i, var;
+
+ newlist = ALLOC(symbolic_t, 1);
+ newlist->next = NIL(symbolic_t);
+ newlist->symbolic_list = NIL(symbolic_list_t);
+ newlist->symbolic_list_length = 0;
+ newlist->symbolic_label = NIL(symbolic_label_t);
+ newlist->symbolic_label_length = 0;
+ prev_listp = NIL(symbolic_list_t);
+ prev_labelp = NIL(symbolic_label_t);
+
+ for(;;) {
+ (void) get_word(fp, word);
+ if (equal(word, ";"))
+ break;
+ if (label_index(PLA, word, &var, &i)) {
+ listp = ALLOC(symbolic_list_t, 1);
+ listp->variable = var;
+ listp->pos = i;
+ listp->next = NIL(symbolic_list_t);
+ if (prev_listp == NIL(symbolic_list_t)) {
+ newlist->symbolic_list = listp;
+ } else {
+ prev_listp->next = listp;
+ }
+ prev_listp = listp;
+ newlist->symbolic_list_length++;
+ } else {
+ return FALSE;
+ }
+ }
+
+ for(;;) {
+ (void) get_word(fp, word);
+ if (equal(word, ";"))
+ break;
+ labelp = ALLOC(symbolic_label_t, 1);
+ labelp->label = util_strsav(word);
+ labelp->next = NIL(symbolic_label_t);
+ if (prev_labelp == NIL(symbolic_label_t)) {
+ newlist->symbolic_label = labelp;
+ } else {
+ prev_labelp->next = labelp;
+ }
+ prev_labelp = labelp;
+ newlist->symbolic_label_length++;
+ }
+
+ *retval = newlist;
+ return TRUE;
+}
+
+
+int label_index(PLA, word, varp, ip)
+pPLA PLA;
+char *word;
+int *varp;
+int *ip;
+{
+ int var, i;
+
+ if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) {
+ if (sscanf(word, "%d", varp) == 1) {
+ *ip = *varp;
+ return TRUE;
+ }
+ } else {
+ for(var = 0; var < cube.num_vars; var++) {
+ for(i = 0; i < cube.part_size[var]; i++) {
+ if (equal(PLA->label[cube.first_part[var]+i], word)) {
+ *varp = var;
+ *ip = i;
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
diff --git a/src/misc/espresso/cvrm.c b/src/misc/espresso/cvrm.c
new file mode 100644
index 00000000..7d42d6e3
--- /dev/null
+++ b/src/misc/espresso/cvrm.c
@@ -0,0 +1,539 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: cvrm.c
+ Purpose: miscellaneous cover manipulation
+ a) verify two covers are equal, check consistency of a cover
+ b) unravel a multiple-valued cover into minterms
+ c) sort covers
+*/
+
+#include "espresso.h"
+
+
+static void cb_unravel(c, start, end, startbase, B1)
+IN register pcube c;
+IN int start, end;
+IN pcube startbase;
+INOUT pcover B1;
+{
+ pcube base = cube.temp[0], p, last;
+ int expansion, place, skip, var, size, offset;
+ register int i, j, k, n;
+
+ /* Determine how many cubes it will blow up into, and create a mask
+ for those parts that have only a single coordinate
+ */
+ expansion = 1;
+ (void) set_copy(base, startbase);
+ for(var = start; var <= end; var++) {
+ if ((size = set_dist(c, cube.var_mask[var])) < 2) {
+ (void) set_or(base, base, cube.var_mask[var]);
+ } else {
+ expansion *= size;
+ }
+ }
+ (void) set_and(base, c, base);
+
+ /* Add the unravelled sets starting at the last element of B1 */
+ offset = B1->count;
+ B1->count += expansion;
+ foreach_remaining_set(B1, last, GETSET(B1, offset-1), p) {
+ INLINEset_copy(p, base);
+ }
+
+ place = expansion;
+ for(var = start; var <= end; var++) {
+ if ((size = set_dist(c, cube.var_mask[var])) > 1) {
+ skip = place;
+ place = place / size;
+ n = 0;
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ if (is_in_set(c, i)) {
+ for(j = n; j < expansion; j += skip) {
+ for(k = 0; k < place; k++) {
+ p = GETSET(B1, j+k+offset);
+ (void) set_insert(p, i);
+ }
+ }
+ n += place;
+ }
+ }
+ }
+ }
+}
+
+
+pcover unravel_range(B, start, end)
+IN pcover B;
+IN int start, end;
+{
+ pcover B1;
+ int var, total_size, expansion, size;
+ register pcube p, last, startbase = cube.temp[1];
+
+ /* Create the starting base for those variables not being unravelled */
+ (void) set_copy(startbase, cube.emptyset);
+ for(var = 0; var < start; var++)
+ (void) set_or(startbase, startbase, cube.var_mask[var]);
+ for(var = end+1; var < cube.num_vars; var++)
+ (void) set_or(startbase, startbase, cube.var_mask[var]);
+
+ /* Determine how many cubes it will blow up into */
+ total_size = 0;
+ foreach_set(B, last, p) {
+ expansion = 1;
+ for(var = start; var <= end; var++)
+ if ((size = set_dist(p, cube.var_mask[var])) >= 2)
+ if ((expansion *= size) > 1000000)
+ fatal("unreasonable expansion in unravel");
+ total_size += expansion;
+ }
+
+ /* We can now allocate a cover of exactly the correct size */
+ B1 = new_cover(total_size);
+ foreach_set(B, last, p) {
+ cb_unravel(p, start, end, startbase, B1);
+ }
+ free_cover(B);
+ return B1;
+}
+
+
+pcover unravel(B, start)
+IN pcover B;
+IN int start;
+{
+ return unravel_range(B, start, cube.num_vars-1);
+}
+
+/* lex_sort -- sort cubes in a standard lexical fashion */
+pcover lex_sort(T)
+pcover T;
+{
+ pcover T1 = sf_unlist(sf_sort(T, lex_order), T->count, T->sf_size);
+ free_cover(T);
+ return T1;
+}
+
+
+/* size_sort -- sort cubes by their size */
+pcover size_sort(T)
+pcover T;
+{
+ pcover T1 = sf_unlist(sf_sort(T, descend), T->count, T->sf_size);
+ free_cover(T);
+ return T1;
+}
+
+
+/* mini_sort -- sort cubes according to the heuristics of mini */
+pcover mini_sort(F, compare)
+pcover F;
+int (*compare)();
+{
+ register int *count, cnt, n = cube.size, i;
+ register pcube p, last;
+ pcover F_sorted;
+ pcube *F1;
+
+ /* Perform a column sum over the set family */
+ count = sf_count(F);
+
+ /* weight is "inner product of the cube and the column sums" */
+ foreach_set(F, last, p) {
+ cnt = 0;
+ for(i = 0; i < n; i++)
+ if (is_in_set(p, i))
+ cnt += count[i];
+ PUTSIZE(p, cnt);
+ }
+ FREE(count);
+
+ /* use qsort to sort the array */
+ qsort((char *) (F1 = sf_list(F)), F->count, sizeof(pcube), compare);
+ F_sorted = sf_unlist(F1, F->count, F->sf_size);
+ free_cover(F);
+
+ return F_sorted;
+}
+
+
+/* sort_reduce -- Espresso strategy for ordering the cubes before reduction */
+pcover sort_reduce(T)
+IN pcover T;
+{
+ register pcube p, last, largest = NULL;
+ register int bestsize = -1, size, n = cube.num_vars;
+ pcover T_sorted;
+ pcube *T1;
+
+ if (T->count == 0)
+ return T;
+
+ /* find largest cube */
+ foreach_set(T, last, p)
+ if ((size = set_ord(p)) > bestsize)
+ largest = p, bestsize = size;
+
+ foreach_set(T, last, p)
+ PUTSIZE(p, ((n - cdist(largest,p)) << 7) + MIN(set_ord(p),127));
+
+ qsort((char *) (T1 = sf_list(T)), T->count, sizeof(pcube), (int (*)()) descend);
+ T_sorted = sf_unlist(T1, T->count, T->sf_size);
+ free_cover(T);
+
+ return T_sorted;
+}
+
+pcover random_order(F)
+register pcover F;
+{
+ pset temp;
+ register int i, k;
+#ifdef RANDOM
+ long random();
+#endif
+
+ temp = set_new(F->sf_size);
+ for(i = F->count - 1; i > 0; i--) {
+ /* Choose a random number between 0 and i */
+#ifdef RANDOM
+ k = random() % i;
+#else
+ /* this is not meant to be really used; just provides an easy
+ "out" if random() and srandom() aren't around
+ */
+ k = (i*23 + 997) % i;
+#endif
+ /* swap sets i and k */
+ (void) set_copy(temp, GETSET(F, k));
+ (void) set_copy(GETSET(F, k), GETSET(F, i));
+ (void) set_copy(GETSET(F, i), temp);
+ }
+ set_free(temp);
+ return F;
+}
+
+/*
+ * cubelist_partition -- take a cubelist T and see if it has any components;
+ * if so, return cubelist's of the two partitions A and B; the return value
+ * is the size of the partition; if not, A and B
+ * are undefined and the return value is 0
+ */
+int cubelist_partition(T, A, B, comp_debug)
+pcube *T; /* a list of cubes */
+pcube **A, **B; /* cubelist of partition and remainder */
+unsigned int comp_debug;
+{
+ register pcube *T1, p, seed, cof;
+ pcube *A1, *B1;
+ bool change;
+ int count, numcube;
+
+ numcube = CUBELISTSIZE(T);
+
+ /* Mark all cubes -- covered cubes belong to the partition */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ RESET(p, COVERED);
+ }
+
+ /*
+ * Extract a partition from the cubelist T; start with the first cube as a
+ * seed, and then pull in all cubes which share a variable with the seed;
+ * iterate until no new cubes are brought into the partition.
+ */
+ seed = set_save(T[2]);
+ cof = T[0];
+ SET(T[2], COVERED);
+ count = 1;
+
+ do {
+ change = FALSE;
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (! TESTP(p, COVERED) && ccommon(p, seed, cof)) {
+ INLINEset_and(seed, seed, p);
+ SET(p, COVERED);
+ change = TRUE;
+ count++;
+ }
+
+ }
+ } while (change);
+
+ set_free(seed);
+
+ if (comp_debug) {
+ (void) printf("COMPONENT_REDUCTION: split into %d %d\n",
+ count, numcube - count);
+ }
+
+ if (count != numcube) {
+ /* Allocate and setup the cubelist's for the two partitions */
+ *A = A1 = ALLOC(pcube, numcube+3);
+ *B = B1 = ALLOC(pcube, numcube+3);
+ (*A)[0] = set_save(T[0]);
+ (*B)[0] = set_save(T[0]);
+ A1 = *A + 2;
+ B1 = *B + 2;
+
+ /* Loop over the cubes in T and distribute to A and B */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (TESTP(p, COVERED)) {
+ *A1++ = p;
+ } else {
+ *B1++ = p;
+ }
+ }
+
+ /* Stuff needed at the end of the cubelist's */
+ *A1++ = NULL;
+ (*A)[1] = (pcube) A1;
+ *B1++ = NULL;
+ (*B)[1] = (pcube) B1;
+ }
+
+ return numcube - count;
+}
+
+/*
+ * quick cofactor against a single output function
+ */
+pcover cof_output(T, i)
+pcover T;
+register int i;
+{
+ pcover T1;
+ register pcube p, last, pdest, mask;
+
+ mask = cube.var_mask[cube.output];
+ T1 = new_cover(T->count);
+ foreach_set(T, last, p) {
+ if (is_in_set(p, i)) {
+ pdest = GETSET(T1, T1->count++);
+ INLINEset_or(pdest, p, mask);
+ RESET(pdest, PRIME);
+ }
+ }
+ return T1;
+}
+
+
+/*
+ * quick intersection against a single output function
+ */
+pcover uncof_output(T, i)
+pcover T;
+int i;
+{
+ register pcube p, last, mask;
+
+ if (T == NULL) {
+ return T;
+ }
+
+ mask = cube.var_mask[cube.output];
+ foreach_set(T, last, p) {
+ INLINEset_diff(p, p, mask);
+ set_insert(p, i);
+ }
+ return T;
+}
+
+
+/*
+ * A generic routine to perform an operation for each output function
+ *
+ * func() is called with a PLA for each output function (with the output
+ * part effectively removed).
+ * func1() is called after reforming the equivalent output function
+ *
+ * Each function returns TRUE if process is to continue
+ */
+foreach_output_function(PLA, func, func1)
+pPLA PLA;
+int (*func)();
+int (*func1)();
+{
+ pPLA PLA1;
+ int i;
+
+ /* Loop for each output function */
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+
+ /* cofactor on the output part */
+ PLA1 = new_PLA();
+ PLA1->F = cof_output(PLA->F, i + cube.first_part[cube.output]);
+ PLA1->R = cof_output(PLA->R, i + cube.first_part[cube.output]);
+ PLA1->D = cof_output(PLA->D, i + cube.first_part[cube.output]);
+
+ /* Call a routine to do something with the cover */
+ if ((*func)(PLA1, i) == 0) {
+ free_PLA(PLA1);
+ return;
+ }
+
+ /* intersect with the particular output part again */
+ PLA1->F = uncof_output(PLA1->F, i + cube.first_part[cube.output]);
+ PLA1->R = uncof_output(PLA1->R, i + cube.first_part[cube.output]);
+ PLA1->D = uncof_output(PLA1->D, i + cube.first_part[cube.output]);
+
+ /* Call a routine to do something with the final result */
+ if ((*func1)(PLA1, i) == 0) {
+ free_PLA(PLA1);
+ return;
+ }
+
+ /* Cleanup for next go-around */
+ free_PLA(PLA1);
+
+
+ }
+}
+
+static pcover Fmin;
+static pcube phase;
+
+/*
+ * minimize each output function individually
+ */
+void so_espresso(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+ Fmin = new_cover(PLA->F->count);
+ if (strategy == 0) {
+ foreach_output_function(PLA, so_do_espresso, so_save);
+ } else {
+ foreach_output_function(PLA, so_do_exact, so_save);
+ }
+ sf_free(PLA->F);
+ PLA->F = Fmin;
+}
+
+
+/*
+ * minimize each output function, choose function or complement based on the
+ * one with the fewer number of terms
+ */
+void so_both_espresso(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+ phase = set_save(cube.fullset);
+ Fmin = new_cover(PLA->F->count);
+ if (strategy == 0) {
+ foreach_output_function(PLA, so_both_do_espresso, so_both_save);
+ } else {
+ foreach_output_function(PLA, so_both_do_exact, so_both_save);
+ }
+ sf_free(PLA->F);
+ PLA->F = Fmin;
+ PLA->phase = phase;
+}
+
+
+int so_do_espresso(PLA, i)
+pPLA PLA;
+int i;
+{
+ char word[32];
+
+ /* minimize the single-output function (on-set) */
+ skip_make_sparse = 1;
+ (void) sprintf(word, "ESPRESSO-POS(%d)", i);
+ EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F);
+ return 1;
+}
+
+
+int so_do_exact(PLA, i)
+pPLA PLA;
+int i;
+{
+ char word[32];
+
+ /* minimize the single-output function (on-set) */
+ skip_make_sparse = 1;
+ (void) sprintf(word, "EXACT-POS(%d)", i);
+ EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F);
+ return 1;
+}
+
+
+/*ARGSUSED*/
+int so_save(PLA, i)
+pPLA PLA;
+int i;
+{
+ Fmin = sf_append(Fmin, PLA->F); /* disposes of PLA->F */
+ PLA->F = NULL;
+ return 1;
+}
+
+
+int so_both_do_espresso(PLA, i)
+pPLA PLA;
+int i;
+{
+ char word[32];
+
+ /* minimize the single-output function (on-set) */
+ (void) sprintf(word, "ESPRESSO-POS(%d)", i);
+ skip_make_sparse = 1;
+ EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F);
+
+ /* minimize the single-output function (off-set) */
+ (void) sprintf(word, "ESPRESSO-NEG(%d)", i);
+ skip_make_sparse = 1;
+ EXEC_S(PLA->R = espresso(PLA->R, PLA->D, PLA->F), word, PLA->R);
+
+ return 1;
+}
+
+
+int so_both_do_exact(PLA, i)
+pPLA PLA;
+int i;
+{
+ char word[32];
+
+ /* minimize the single-output function (on-set) */
+ (void) sprintf(word, "EXACT-POS(%d)", i);
+ skip_make_sparse = 1;
+ EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F);
+
+ /* minimize the single-output function (off-set) */
+ (void) sprintf(word, "EXACT-NEG(%d)", i);
+ skip_make_sparse = 1;
+ EXEC_S(PLA->R = minimize_exact(PLA->R, PLA->D, PLA->F, 1), word, PLA->R);
+
+ return 1;
+}
+
+
+int so_both_save(PLA, i)
+pPLA PLA;
+int i;
+{
+ if (PLA->F->count > PLA->R->count) {
+ sf_free(PLA->F);
+ PLA->F = PLA->R;
+ PLA->R = NULL;
+ i += cube.first_part[cube.output];
+ set_remove(phase, i);
+ } else {
+ sf_free(PLA->R);
+ PLA->R = NULL;
+ }
+ Fmin = sf_append(Fmin, PLA->F);
+ PLA->F = NULL;
+ return 1;
+}
diff --git a/src/misc/espresso/cvrmisc.c b/src/misc/espresso/cvrmisc.c
new file mode 100644
index 00000000..0f3de195
--- /dev/null
+++ b/src/misc/espresso/cvrmisc.c
@@ -0,0 +1,142 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+
+/* cost -- compute the cost of a cover */
+void cover_cost(F, cost)
+IN pcover F;
+INOUT pcost cost;
+{
+ register pcube p, last;
+ pcube *T;
+ int var;
+
+ /* use the routine used by cofactor to decide splitting variables */
+ massive_count(T = cube1list(F));
+ free_cubelist(T);
+
+ cost->cubes = F->count;
+ cost->total = cost->in = cost->out = cost->mv = cost->primes = 0;
+
+ /* Count transistors (zeros) for each binary variable (inputs) */
+ for(var = 0; var < cube.num_binary_vars; var++)
+ cost->in += cdata.var_zeros[var];
+
+ /* Count transistors for each mv variable based on sparse/dense */
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++)
+ if (cube.sparse[var])
+ cost->mv += F->count * cube.part_size[var] - cdata.var_zeros[var];
+ else
+ cost->mv += cdata.var_zeros[var];
+
+ /* Count the transistors (ones) for the output variable */
+ if (cube.num_binary_vars != cube.num_vars) {
+ var = cube.num_vars - 1;
+ cost->out = F->count * cube.part_size[var] - cdata.var_zeros[var];
+ }
+
+ /* Count the number of nonprime cubes */
+ foreach_set(F, last, p)
+ cost->primes += TESTP(p, PRIME) != 0;
+
+ /* Count the total number of literals */
+ cost->total = cost->in + cost->out + cost->mv;
+}
+
+
+/* fmt_cost -- return a string which reports the "cost" of a cover */
+char *fmt_cost(cost)
+IN pcost cost;
+{
+ static char s[200];
+
+ if (cube.num_binary_vars == cube.num_vars - 1)
+ (void) sprintf(s, "c=%d(%d) in=%d out=%d tot=%d",
+ cost->cubes, cost->cubes - cost->primes, cost->in,
+ cost->out, cost->total);
+ else
+ (void) sprintf(s, "c=%d(%d) in=%d mv=%d out=%d",
+ cost->cubes, cost->cubes - cost->primes, cost->in,
+ cost->mv, cost->out);
+ return s;
+}
+
+
+char *print_cost(F)
+IN pcover F;
+{
+ cost_t cost;
+ cover_cost(F, &cost);
+ return fmt_cost(&cost);
+}
+
+
+/* copy_cost -- copy a cost function from s to d */
+void copy_cost(s, d)
+pcost s, d;
+{
+ d->cubes = s->cubes;
+ d->in = s->in;
+ d->out = s->out;
+ d->mv = s->mv;
+ d->total = s->total;
+ d->primes = s->primes;
+}
+
+
+/* size_stamp -- print single line giving the size of a cover */
+void size_stamp(T, name)
+IN pcover T;
+IN char *name;
+{
+ (void) printf("# %s\tCost is %s\n", name, print_cost(T));
+ (void) fflush(stdout);
+}
+
+
+/* print_trace -- print a line reporting size and time after a function */
+void print_trace(T, name, time)
+pcover T;
+char *name;
+long time;
+{
+ (void) printf("# %s\tTime was %s, cost is %s\n",
+ name, print_time(time), print_cost(T));
+ (void) fflush(stdout);
+}
+
+
+/* totals -- add time spent in the function into the totals */
+void totals(time, i, T, cost)
+long time;
+int i;
+pcover T;
+pcost cost;
+{
+ time = ptime() - time;
+ total_time[i] += time;
+ total_calls[i]++;
+ cover_cost(T, cost);
+ if (trace) {
+ (void) printf("# %s\tTime was %s, cost is %s\n",
+ total_name[i], print_time(time), fmt_cost(cost));
+ (void) fflush(stdout);
+ }
+}
+
+
+/* fatal -- report fatal error message and take a dive */
+void fatal(s)
+char *s;
+{
+ (void) fprintf(stderr, "espresso: %s\n", s);
+ exit(1);
+}
diff --git a/src/misc/espresso/cvrout.c b/src/misc/espresso/cvrout.c
new file mode 100644
index 00000000..4bd1c53b
--- /dev/null
+++ b/src/misc/espresso/cvrout.c
@@ -0,0 +1,609 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: cvrout.c
+ purpose: cube and cover output routines
+*/
+
+#include "espresso.h"
+
+void fprint_pla(fp, PLA, output_type)
+INOUT FILE *fp;
+IN pPLA PLA;
+IN int output_type;
+{
+ int num;
+ register pcube last, p;
+
+ if ((output_type & CONSTRAINTS_type) != 0) {
+ output_symbolic_constraints(fp, PLA, 0);
+ output_type &= ~ CONSTRAINTS_type;
+ if (output_type == 0) {
+ return;
+ }
+ }
+
+ if ((output_type & SYMBOLIC_CONSTRAINTS_type) != 0) {
+ output_symbolic_constraints(fp, PLA, 1);
+ output_type &= ~ SYMBOLIC_CONSTRAINTS_type;
+ if (output_type == 0) {
+ return;
+ }
+ }
+
+ if (output_type == PLEASURE_type) {
+ pls_output(PLA);
+ } else if (output_type == EQNTOTT_type) {
+ eqn_output(PLA);
+ } else if (output_type == KISS_type) {
+ kiss_output(fp, PLA);
+ } else {
+ fpr_header(fp, PLA, output_type);
+
+ num = 0;
+ if (output_type & F_type) num += (PLA->F)->count;
+ if (output_type & D_type) num += (PLA->D)->count;
+ if (output_type & R_type) num += (PLA->R)->count;
+ (void) fprintf(fp, ".p %d\n", num);
+
+ /* quick patch 01/17/85 to support TPLA ! */
+ if (output_type == F_type) {
+ foreach_set(PLA->F, last, p) {
+ print_cube(fp, p, "01");
+ }
+ (void) fprintf(fp, ".e\n");
+ } else {
+ if (output_type & F_type) {
+ foreach_set(PLA->F, last, p) {
+ print_cube(fp, p, "~1");
+ }
+ }
+ if (output_type & D_type) {
+ foreach_set(PLA->D, last, p) {
+ print_cube(fp, p, "~2");
+ }
+ }
+ if (output_type & R_type) {
+ foreach_set(PLA->R, last, p) {
+ print_cube(fp, p, "~0");
+ }
+ }
+ (void) fprintf(fp, ".end\n");
+ }
+ }
+}
+
+void fpr_header(fp, PLA, output_type)
+FILE *fp;
+pPLA PLA;
+int output_type;
+{
+ register int i, var;
+ int first, last;
+
+ /* .type keyword gives logical type */
+ if (output_type != F_type) {
+ (void) fprintf(fp, ".type ");
+ if (output_type & F_type) putc('f', fp);
+ if (output_type & D_type) putc('d', fp);
+ if (output_type & R_type) putc('r', fp);
+ putc('\n', fp);
+ }
+
+ /* Check for binary or multiple-valued labels */
+ if (cube.num_mv_vars <= 1) {
+ (void) fprintf(fp, ".i %d\n", cube.num_binary_vars);
+ if (cube.output != -1)
+ (void) fprintf(fp, ".o %d\n", cube.part_size[cube.output]);
+ } else {
+ (void) fprintf(fp, ".mv %d %d", cube.num_vars, cube.num_binary_vars);
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++)
+ (void) fprintf(fp, " %d", cube.part_size[var]);
+ (void) fprintf(fp, "\n");
+ }
+
+ /* binary valued labels */
+ if (PLA->label != NIL(char *) && PLA->label[1] != NIL(char)
+ && cube.num_binary_vars > 0) {
+ (void) fprintf(fp, ".ilb");
+ for(var = 0; var < cube.num_binary_vars; var++)
+ /* see (NIL) OUTLABELS comment below */
+ if(INLABEL(var) == NIL(char)){
+ (void) fprintf(fp, " (null)");
+ }
+ else{
+ (void) fprintf(fp, " %s", INLABEL(var));
+ }
+ putc('\n', fp);
+ }
+
+ /* output-part (last multiple-valued variable) labels */
+ if (PLA->label != NIL(char *) &&
+ PLA->label[cube.first_part[cube.output]] != NIL(char)
+ && cube.output != -1) {
+ (void) fprintf(fp, ".ob");
+ for(i = 0; i < cube.part_size[cube.output]; i++)
+ /* (NIL) OUTLABELS caused espresso to segfault under solaris */
+ if(OUTLABEL(i) == NIL(char)){
+ (void) fprintf(fp, " (null)");
+ }
+ else{
+ (void) fprintf(fp, " %s", OUTLABEL(i));
+ }
+ putc('\n', fp);
+ }
+
+ /* multiple-valued labels */
+ for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) {
+ first = cube.first_part[var];
+ last = cube.last_part[var];
+ if (PLA->label != NULL && PLA->label[first] != NULL) {
+ (void) fprintf(fp, ".label var=%d", var);
+ for(i = first; i <= last; i++) {
+ (void) fprintf(fp, " %s", PLA->label[i]);
+ }
+ putc('\n', fp);
+ }
+ }
+
+ if (PLA->phase != (pcube) NULL) {
+ first = cube.first_part[cube.output];
+ last = cube.last_part[cube.output];
+ (void) fprintf(fp, "#.phase ");
+ for(i = first; i <= last; i++)
+ putc(is_in_set(PLA->phase,i) ? '1' : '0', fp);
+ (void) fprintf(fp, "\n");
+ }
+}
+
+void pls_output(PLA)
+IN pPLA PLA;
+{
+ register pcube last, p;
+
+ (void) printf(".option unmerged\n");
+ makeup_labels(PLA);
+ pls_label(PLA, stdout);
+ pls_group(PLA, stdout);
+ (void) printf(".p %d\n", PLA->F->count);
+ foreach_set(PLA->F, last, p) {
+ print_expanded_cube(stdout, p, PLA->phase);
+ }
+ (void) printf(".end\n");
+}
+
+
+void pls_group(PLA, fp)
+pPLA PLA;
+FILE *fp;
+{
+ int var, i, col, len;
+
+ (void) fprintf(fp, "\n.group");
+ col = 6;
+ for(var = 0; var < cube.num_vars-1; var++) {
+ (void) fprintf(fp, " ("), col += 2;
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ len = strlen(PLA->label[i]);
+ if (col + len > 75)
+ (void) fprintf(fp, " \\\n"), col = 0;
+ else if (i != 0)
+ putc(' ', fp), col += 1;
+ (void) fprintf(fp, "%s", PLA->label[i]), col += len;
+ }
+ (void) fprintf(fp, ")"), col += 1;
+ }
+ (void) fprintf(fp, "\n");
+}
+
+
+void pls_label(PLA, fp)
+pPLA PLA;
+FILE *fp;
+{
+ int var, i, col, len;
+
+ (void) fprintf(fp, ".label");
+ col = 6;
+ for(var = 0; var < cube.num_vars; var++)
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ len = strlen(PLA->label[i]);
+ if (col + len > 75)
+ (void) fprintf(fp, " \\\n"), col = 0;
+ else
+ putc(' ', fp), col += 1;
+ (void) fprintf(fp, "%s", PLA->label[i]), col += len;
+ }
+}
+
+
+
+/*
+ eqntott output mode -- output algebraic equations
+*/
+void eqn_output(PLA)
+pPLA PLA;
+{
+ register pcube p, last;
+ register int i, var, col, len;
+ int x;
+ bool firstand, firstor;
+
+ if (cube.output == -1)
+ fatal("Cannot have no-output function for EQNTOTT output mode");
+ if (cube.num_mv_vars != 1)
+ fatal("Must have binary-valued function for EQNTOTT output mode");
+ makeup_labels(PLA);
+
+ /* Write a single equation for each output */
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+ (void) printf("%s = ", OUTLABEL(i));
+ col = strlen(OUTLABEL(i)) + 3;
+ firstor = TRUE;
+
+ /* Write product terms for each cube in this output */
+ foreach_set(PLA->F, last, p)
+ if (is_in_set(p, i + cube.first_part[cube.output])) {
+ if (firstor)
+ (void) printf("("), col += 1;
+ else
+ (void) printf(" | ("), col += 4;
+ firstor = FALSE;
+ firstand = TRUE;
+
+ /* print out a product term */
+ for(var = 0; var < cube.num_binary_vars; var++)
+ if ((x=GETINPUT(p, var)) != DASH) {
+ len = strlen(INLABEL(var));
+ if (col+len > 72)
+ (void) printf("\n "), col = 4;
+ if (! firstand)
+ (void) printf("&"), col += 1;
+ firstand = FALSE;
+ if (x == ZERO)
+ (void) printf("!"), col += 1;
+ (void) printf("%s", INLABEL(var)), col += len;
+ }
+ (void) printf(")"), col += 1;
+ }
+ (void) printf(";\n\n");
+ }
+}
+
+
+char *fmt_cube(c, out_map, s)
+register pcube c;
+register char *out_map, *s;
+{
+ register int i, var, last, len = 0;
+
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ s[len++] = "?01-" [GETINPUT(c, var)];
+ }
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ s[len++] = ' ';
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ s[len++] = "01" [is_in_set(c, i) != 0];
+ }
+ }
+ if (cube.output != -1) {
+ last = cube.last_part[cube.output];
+ s[len++] = ' ';
+ for(i = cube.first_part[cube.output]; i <= last; i++) {
+ s[len++] = out_map [is_in_set(c, i) != 0];
+ }
+ }
+ s[len] = '\0';
+ return s;
+}
+
+
+void print_cube(fp, c, out_map)
+register FILE *fp;
+register pcube c;
+register char *out_map;
+{
+ register int i, var, ch;
+ int last;
+
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ ch = "?01-" [GETINPUT(c, var)];
+ putc(ch, fp);
+ }
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ putc(' ', fp);
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ ch = "01" [is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ if (cube.output != -1) {
+ last = cube.last_part[cube.output];
+ putc(' ', fp);
+ for(i = cube.first_part[cube.output]; i <= last; i++) {
+ ch = out_map [is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ putc('\n', fp);
+}
+
+
+void print_expanded_cube(fp, c, phase)
+register FILE *fp;
+register pcube c;
+pcube phase;
+{
+ register int i, var, ch;
+ char *out_map;
+
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ ch = "~1" [is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ ch = "1~" [is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ if (cube.output != -1) {
+ var = cube.num_vars - 1;
+ putc(' ', fp);
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ if (phase == (pcube) NULL || is_in_set(phase, i)) {
+ out_map = "~1";
+ } else {
+ out_map = "~0";
+ }
+ ch = out_map[is_in_set(c, i) != 0];
+ putc(ch, fp);
+ }
+ }
+ putc('\n', fp);
+}
+
+
+char *pc1(c) pcube c;
+{static char s1[256];return fmt_cube(c, "01", s1);}
+char *pc2(c) pcube c;
+{static char s2[256];return fmt_cube(c, "01", s2);}
+
+
+void debug_print(T, name, level)
+pcube *T;
+char *name;
+int level;
+{
+ register pcube *T1, p, temp;
+ register int cnt;
+
+ cnt = CUBELISTSIZE(T);
+ temp = new_cube();
+ if (verbose_debug && level == 0)
+ (void) printf("\n");
+ (void) printf("%s[%d]: ord(T)=%d\n", name, level, cnt);
+ if (verbose_debug) {
+ (void) printf("cofactor=%s\n", pc1(T[0]));
+ for(T1 = T+2, cnt = 1; (p = *T1++) != (pcube) NULL; cnt++)
+ (void) printf("%4d. %s\n", cnt, pc1(set_or(temp, p, T[0])));
+ }
+ free_cube(temp);
+}
+
+
+void debug1_print(T, name, num)
+pcover T;
+char *name;
+int num;
+{
+ register int cnt = 1;
+ register pcube p, last;
+
+ if (verbose_debug && num == 0)
+ (void) printf("\n");
+ (void) printf("%s[%d]: ord(T)=%d\n", name, num, T->count);
+ if (verbose_debug)
+ foreach_set(T, last, p)
+ (void) printf("%4d. %s\n", cnt++, pc1(p));
+}
+
+
+void cprint(T)
+pcover T;
+{
+ register pcube p, last;
+
+ foreach_set(T, last, p)
+ (void) printf("%s\n", pc1(p));
+}
+
+
+int makeup_labels(PLA)
+pPLA PLA;
+{
+ int var, i, ind;
+
+ if (PLA->label == (char **) NULL)
+ PLA_labels(PLA);
+
+ for(var = 0; var < cube.num_vars; var++)
+ for(i = 0; i < cube.part_size[var]; i++) {
+ ind = cube.first_part[var] + i;
+ if (PLA->label[ind] == (char *) NULL) {
+ PLA->label[ind] = ALLOC(char, 15);
+ if (var < cube.num_binary_vars)
+ if ((i % 2) == 0)
+ (void) sprintf(PLA->label[ind], "v%d.bar", var);
+ else
+ (void) sprintf(PLA->label[ind], "v%d", var);
+ else
+ (void) sprintf(PLA->label[ind], "v%d.%d", var, i);
+ }
+ }
+}
+
+
+kiss_output(fp, PLA)
+FILE *fp;
+pPLA PLA;
+{
+ register pset last, p;
+
+ foreach_set(PLA->F, last, p) {
+ kiss_print_cube(fp, PLA, p, "~1");
+ }
+ foreach_set(PLA->D, last, p) {
+ kiss_print_cube(fp, PLA, p, "~2");
+ }
+}
+
+
+kiss_print_cube(fp, PLA, p, out_string)
+FILE *fp;
+pPLA PLA;
+pcube p;
+char *out_string;
+{
+ register int i, var;
+ int part, x;
+
+ for(var = 0; var < cube.num_binary_vars; var++) {
+ x = "?01-" [GETINPUT(p, var)];
+ putc(x, fp);
+ }
+
+ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ putc(' ', fp);
+ if (setp_implies(cube.var_mask[var], p)) {
+ putc('-', fp);
+ } else {
+ part = -1;
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ if (is_in_set(p, i)) {
+ if (part != -1) {
+ fatal("more than 1 part in a symbolic variable\n");
+ }
+ part = i;
+ }
+ }
+ if (part == -1) {
+ putc('~', fp); /* no parts, hope its an output ... */
+ } else {
+ (void) fputs(PLA->label[part], fp);
+ }
+ }
+ }
+
+ if ((var = cube.output) != -1) {
+ putc(' ', fp);
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ x = out_string [is_in_set(p, i) != 0];
+ putc(x, fp);
+ }
+ }
+
+ putc('\n', fp);
+}
+
+output_symbolic_constraints(fp, PLA, output_symbolic)
+FILE *fp;
+pPLA PLA;
+int output_symbolic;
+{
+ pset_family A;
+ register int i, j;
+ int size, var, npermute, *permute, *weight, noweight;
+
+ if ((cube.num_vars - cube.num_binary_vars) <= 1) {
+ return;
+ }
+ makeup_labels(PLA);
+
+ for(var=cube.num_binary_vars; var < cube.num_vars-1; var++) {
+
+ /* pull out the columns for variable "var" */
+ npermute = cube.part_size[var];
+ permute = ALLOC(int, npermute);
+ for(i=0; i < npermute; i++) {
+ permute[i] = cube.first_part[var] + i;
+ }
+ A = sf_permute(sf_save(PLA->F), permute, npermute);
+ FREE(permute);
+
+
+ /* Delete the singletons and the full sets */
+ noweight = 0;
+ for(i = 0; i < A->count; i++) {
+ size = set_ord(GETSET(A,i));
+ if (size == 1 || size == A->sf_size) {
+ sf_delset(A, i--);
+ noweight++;
+ }
+ }
+
+
+ /* Count how many times each is duplicated */
+ weight = ALLOC(int, A->count);
+ for(i = 0; i < A->count; i++) {
+ RESET(GETSET(A, i), COVERED);
+ }
+ for(i = 0; i < A->count; i++) {
+ weight[i] = 0;
+ if (! TESTP(GETSET(A,i), COVERED)) {
+ weight[i] = 1;
+ for(j = i+1; j < A->count; j++) {
+ if (setp_equal(GETSET(A,i), GETSET(A,j))) {
+ weight[i]++;
+ SET(GETSET(A,j), COVERED);
+ }
+ }
+ }
+ }
+
+
+ /* Print out the contraints */
+ if (! output_symbolic) {
+ (void) fprintf(fp,
+ "# Symbolic constraints for variable %d (Numeric form)\n", var);
+ (void) fprintf(fp, "# unconstrained weight = %d\n", noweight);
+ (void) fprintf(fp, "num_codes=%d\n", cube.part_size[var]);
+ for(i = 0; i < A->count; i++) {
+ if (weight[i] > 0) {
+ (void) fprintf(fp, "weight=%d: ", weight[i]);
+ for(j = 0; j < A->sf_size; j++) {
+ if (is_in_set(GETSET(A,i), j)) {
+ (void) fprintf(fp, " %d", j);
+ }
+ }
+ (void) fprintf(fp, "\n");
+ }
+ }
+ } else {
+ (void) fprintf(fp,
+ "# Symbolic constraints for variable %d (Symbolic form)\n", var);
+ for(i = 0; i < A->count; i++) {
+ if (weight[i] > 0) {
+ (void) fprintf(fp, "# w=%d: (", weight[i]);
+ for(j = 0; j < A->sf_size; j++) {
+ if (is_in_set(GETSET(A,i), j)) {
+ (void) fprintf(fp, " %s",
+ PLA->label[cube.first_part[var]+j]);
+ }
+ }
+ (void) fprintf(fp, " )\n");
+ }
+ }
+ FREE(weight);
+ }
+ }
+}
diff --git a/src/misc/espresso/dominate.c b/src/misc/espresso/dominate.c
new file mode 100644
index 00000000..a930d453
--- /dev/null
+++ b/src/misc/espresso/dominate.c
@@ -0,0 +1,98 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+
+int
+sm_row_dominance(A)
+sm_matrix *A;
+{
+ register sm_row *prow, *prow1;
+ register sm_col *pcol, *least_col;
+ register sm_element *p, *pnext;
+ int rowcnt;
+
+ rowcnt = A->nrows;
+
+ /* Check each row against all other rows */
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+
+ /* Among all columns with a 1 in this row, choose smallest */
+ least_col = sm_get_col(A, prow->first_col->col_num);
+ for(p = prow->first_col->next_col; p != 0; p = p->next_col) {
+ pcol = sm_get_col(A, p->col_num);
+ if (pcol->length < least_col->length) {
+ least_col = pcol;
+ }
+ }
+
+ /* Only check for containment against rows in this column */
+ for(p = least_col->first_row; p != 0; p = pnext) {
+ pnext = p->next_row;
+
+ prow1 = sm_get_row(A, p->row_num);
+ if ((prow1->length > prow->length) ||
+ (prow1->length == prow->length &&
+ prow1->row_num > prow->row_num)) {
+ if (sm_row_contains(prow, prow1)) {
+ sm_delrow(A, prow1->row_num);
+ }
+ }
+ }
+ }
+
+ return rowcnt - A->nrows;
+}
+
+int
+sm_col_dominance(A, weight)
+sm_matrix *A;
+int *weight;
+{
+ register sm_row *prow;
+ register sm_col *pcol, *pcol1;
+ register sm_element *p;
+ sm_row *least_row;
+ sm_col *next_col;
+ int colcnt;
+
+ colcnt = A->ncols;
+
+ /* Check each column against all other columns */
+ for(pcol = A->first_col; pcol != 0; pcol = next_col) {
+ next_col = pcol->next_col;
+
+ /* Check all rows to find the one with fewest elements */
+ least_row = sm_get_row(A, pcol->first_row->row_num);
+ for(p = pcol->first_row->next_row; p != 0; p = p->next_row) {
+ prow = sm_get_row(A, p->row_num);
+ if (prow->length < least_row->length) {
+ least_row = prow;
+ }
+ }
+
+ /* Only check for containment against columns in this row */
+ for(p = least_row->first_col; p != 0; p = p->next_col) {
+ pcol1 = sm_get_col(A, p->col_num);
+ if (weight != 0 && weight[pcol1->col_num] > weight[pcol->col_num])
+ continue;
+ if ((pcol1->length > pcol->length) ||
+ (pcol1->length == pcol->length &&
+ pcol1->col_num > pcol->col_num)) {
+ if (sm_col_contains(pcol, pcol1)) {
+ sm_delcol(A, pcol->col_num);
+ break;
+ }
+ }
+ }
+ }
+
+ return colcnt - A->ncols;
+}
diff --git a/src/misc/espresso/equiv.c b/src/misc/espresso/equiv.c
new file mode 100644
index 00000000..ba898a70
--- /dev/null
+++ b/src/misc/espresso/equiv.c
@@ -0,0 +1,94 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+
+find_equiv_outputs(PLA)
+pPLA PLA;
+{
+ int i, j, ipart, jpart, some_equiv;
+ pcover *R, *F;
+
+ some_equiv = FALSE;
+
+ makeup_labels(PLA);
+
+ F = ALLOC(pcover, cube.part_size[cube.output]);
+ R = ALLOC(pcover, cube.part_size[cube.output]);
+
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+ ipart = cube.first_part[cube.output] + i;
+ R[i] = cof_output(PLA->R, ipart);
+ F[i] = complement(cube1list(R[i]));
+ }
+
+ for(i = 0; i < cube.part_size[cube.output]-1; i++) {
+ for(j = i+1; j < cube.part_size[cube.output]; j++) {
+ ipart = cube.first_part[cube.output] + i;
+ jpart = cube.first_part[cube.output] + j;
+
+ if (check_equiv(F[i], F[j])) {
+ (void) printf("# Outputs %d and %d (%s and %s) are equivalent\n",
+ i, j, PLA->label[ipart], PLA->label[jpart]);
+ some_equiv = TRUE;
+ } else if (check_equiv(F[i], R[j])) {
+ (void) printf("# Outputs %d and NOT %d (%s and %s) are equivalent\n",
+ i, j, PLA->label[ipart], PLA->label[jpart]);
+ some_equiv = TRUE;
+ } else if (check_equiv(R[i], F[j])) {
+ (void) printf("# Outputs NOT %d and %d (%s and %s) are equivalent\n",
+ i, j, PLA->label[ipart], PLA->label[jpart]);
+ some_equiv = TRUE;
+ } else if (check_equiv(R[i], R[j])) {
+ (void) printf("# Outputs NOT %d and NOT %d (%s and %s) are equivalent\n",
+ i, j, PLA->label[ipart], PLA->label[jpart]);
+ some_equiv = TRUE;
+ }
+ }
+ }
+
+ if (! some_equiv) {
+ (void) printf("# No outputs are equivalent\n");
+ }
+
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+ free_cover(F[i]);
+ free_cover(R[i]);
+ }
+ FREE(F);
+ FREE(R);
+}
+
+
+
+int check_equiv(f1, f2)
+pcover f1, f2;
+{
+ register pcube *f1list, *f2list;
+ register pcube p, last;
+
+ f1list = cube1list(f1);
+ foreach_set(f2, last, p) {
+ if (! cube_is_covered(f1list, p)) {
+ return FALSE;
+ }
+ }
+ free_cubelist(f1list);
+
+ f2list = cube1list(f2);
+ foreach_set(f1, last, p) {
+ if (! cube_is_covered(f2list, p)) {
+ return FALSE;
+ }
+ }
+ free_cubelist(f2list);
+
+ return TRUE;
+}
diff --git a/src/misc/espresso/espresso.c b/src/misc/espresso/espresso.c
new file mode 100644
index 00000000..8f05d43f
--- /dev/null
+++ b/src/misc/espresso/espresso.c
@@ -0,0 +1,139 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * Module: espresso.c
+ * Purpose: The main espresso algorithm
+ *
+ * Returns a minimized version of the ON-set of a function
+ *
+ * The following global variables affect the operation of Espresso:
+ *
+ * MISCELLANEOUS:
+ * trace
+ * print trace information as the minimization progresses
+ *
+ * remove_essential
+ * remove essential primes
+ *
+ * single_expand
+ * if true, stop after first expand/irredundant
+ *
+ * LAST_GASP or SUPER_GASP strategy:
+ * use_super_gasp
+ * uses the super_gasp strategy rather than last_gasp
+ *
+ * SETUP strategy:
+ * recompute_onset
+ * recompute onset using the complement before starting
+ *
+ * unwrap_onset
+ * unwrap the function output part before first expand
+ *
+ * MAKE_SPARSE strategy:
+ * force_irredundant
+ * iterates make_sparse to force a minimal solution (used
+ * indirectly by make_sparse)
+ *
+ * skip_make_sparse
+ * skip the make_sparse step (used by opo only)
+ */
+
+#include "espresso.h"
+
+pcover espresso(F, D1, R)
+pcover F, D1, R;
+{
+ pcover E, D, Fsave;
+ pset last, p;
+ cost_t cost, best_cost;
+
+begin:
+ Fsave = sf_save(F); /* save original function */
+ D = sf_save(D1); /* make a scratch copy of D */
+
+ /* Setup has always been a problem */
+ if (recompute_onset) {
+ EXEC(E = simplify(cube1list(F)), "SIMPLIFY ", E);
+ free_cover(F);
+ F = E;
+ }
+ cover_cost(F, &cost);
+ if (unwrap_onset && (cube.part_size[cube.num_vars - 1] > 1)
+ && (cost.out != cost.cubes*cube.part_size[cube.num_vars-1])
+ && (cost.out < 5000))
+ EXEC(F = sf_contain(unravel(F, cube.num_vars - 1)), "SETUP ", F);
+
+ /* Initial expand and irredundant */
+ foreach_set(F, last, p) {
+ RESET(p, PRIME);
+ }
+ EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost);
+ EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost);
+
+ if (! single_expand) {
+ if (remove_essential) {
+ EXECUTE(E = essential(&F, &D), ESSEN_TIME, E, cost);
+ } else {
+ E = new_cover(0);
+ }
+
+ cover_cost(F, &cost);
+ do {
+
+ /* Repeat inner loop until solution becomes "stable" */
+ do {
+ copy_cost(&cost, &best_cost);
+ EXECUTE(F = reduce(F, D), REDUCE_TIME, F, cost);
+ EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost);
+ EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost);
+ } while (cost.cubes < best_cost.cubes);
+
+ /* Perturb solution to see if we can continue to iterate */
+ copy_cost(&cost, &best_cost);
+ if (use_super_gasp) {
+ F = super_gasp(F, D, R, &cost);
+ if (cost.cubes >= best_cost.cubes)
+ break;
+ } else {
+ F = last_gasp(F, D, R, &cost);
+ }
+
+ } while (cost.cubes < best_cost.cubes ||
+ (cost.cubes == best_cost.cubes && cost.total < best_cost.total));
+
+ /* Append the essential cubes to F */
+ F = sf_append(F, E); /* disposes of E */
+ if (trace) size_stamp(F, "ADJUST ");
+ }
+
+ /* Free the D which we used */
+ free_cover(D);
+
+ /* Attempt to make the PLA matrix sparse */
+ if (! skip_make_sparse) {
+ F = make_sparse(F, D1, R);
+ }
+
+ /*
+ * Check to make sure function is actually smaller !!
+ * This can only happen because of the initial unravel. If we fail,
+ * then run the whole thing again without the unravel.
+ */
+ if (Fsave->count < F->count) {
+ free_cover(F);
+ F = Fsave;
+ unwrap_onset = FALSE;
+ goto begin;
+ } else {
+ free_cover(Fsave);
+ }
+
+ return F;
+}
diff --git a/src/misc/espresso/espresso.h b/src/misc/espresso/espresso.h
new file mode 100644
index 00000000..1c7a8646
--- /dev/null
+++ b/src/misc/espresso/espresso.h
@@ -0,0 +1,782 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * espresso.h -- header file for Espresso-mv
+ */
+
+//#include "port.h"
+//#include "utility.h"
+#include "sparse.h"
+#include "mincov.h"
+
+#include "util_hack.h" // added
+
+#define ptime() util_cpu_time()
+#define print_time(t) util_print_time(t)
+
+#ifdef IBM_WATC
+#define void int
+#include "short.h"
+#endif
+
+#ifdef IBMPC /* set default options for IBM/PC */
+#define NO_INLINE
+#define BPI 16
+#endif
+
+/*-----THIS USED TO BE set.h----- */
+
+/*
+ * set.h -- definitions for packed arrays of bits
+ *
+ * This header file describes the data structures which comprise a
+ * facility for efficiently implementing packed arrays of bits
+ * (otherwise known as sets, cf. Pascal).
+ *
+ * A set is a vector of bits and is implemented here as an array of
+ * unsigned integers. The low order bits of set[0] give the index of
+ * the last word of set data. The higher order bits of set[0] are
+ * used to store data associated with the set. The set data is
+ * contained in elements set[1] ... set[LOOP(set)] as a packed bit
+ * array.
+ *
+ * A family of sets is a two-dimensional matrix of bits and is
+ * implemented with the data type "set_family".
+ *
+ * BPI == 32 and BPI == 16 have been tested and work.
+ */
+
+
+/* Define host machine characteristics of "unsigned int" */
+#ifndef BPI
+#define BPI 32 /* # bits per integer */
+#endif
+
+#if BPI == 32
+#define LOGBPI 5 /* log(BPI)/log(2) */
+#else
+#define LOGBPI 4 /* log(BPI)/log(2) */
+#endif
+
+/* Define the set type */
+typedef unsigned int *pset;
+
+/* Define the set family type -- an array of sets */
+typedef struct set_family {
+ int wsize; /* Size of each set in 'ints' */
+ int sf_size; /* User declared set size */
+ int capacity; /* Number of sets allocated */
+ int count; /* The number of sets in the family */
+ int active_count; /* Number of "active" sets */
+ pset data; /* Pointer to the set data */
+ struct set_family *next; /* For garbage collection */
+} set_family_t, *pset_family;
+
+/* Macros to set and test single elements */
+#define WHICH_WORD(element) (((element) >> LOGBPI) + 1)
+#define WHICH_BIT(element) ((element) & (BPI-1))
+
+/* # of ints needed to allocate a set with "size" elements */
+#if BPI == 32
+#define SET_SIZE(size) ((size) <= BPI ? 2 : (WHICH_WORD((size)-1) + 1))
+#else
+#define SET_SIZE(size) ((size) <= BPI ? 3 : (WHICH_WORD((size)-1) + 2))
+#endif
+
+/*
+ * Three fields are maintained in the first word of the set
+ * LOOP is the index of the last word used for set data
+ * LOOPCOPY is the index of the last word in the set
+ * SIZE is available for general use (e.g., recording # elements in set)
+ * NELEM retrieves the number of elements in the set
+ */
+#define LOOP(set) (set[0] & 0x03ff)
+#define PUTLOOP(set, i) (set[0] &= ~0x03ff, set[0] |= (i))
+#if BPI == 32
+#define LOOPCOPY(set) LOOP(set)
+#define SIZE(set) (set[0] >> 16)
+#define PUTSIZE(set, size) (set[0] &= 0xffff, set[0] |= ((size) << 16))
+#else
+#define LOOPCOPY(set) (LOOP(set) + 1)
+#define SIZE(set) (set[LOOP(set)+1])
+#define PUTSIZE(set, size) ((set[LOOP(set)+1]) = (size))
+#endif
+
+#define NELEM(set) (BPI * LOOP(set))
+#define LOOPINIT(size) ((size <= BPI) ? 1 : WHICH_WORD((size)-1))
+
+/*
+ * FLAGS store general information about the set
+ */
+#define SET(set, flag) (set[0] |= (flag))
+#define RESET(set, flag) (set[0] &= ~ (flag))
+#define TESTP(set, flag) (set[0] & (flag))
+
+/* Flag definitions are ... */
+#define PRIME 0x8000 /* cube is prime */
+#define NONESSEN 0x4000 /* cube cannot be essential prime */
+#define ACTIVE 0x2000 /* cube is still active */
+#define REDUND 0x1000 /* cube is redundant(at this point) */
+#define COVERED 0x0800 /* cube has been covered */
+#define RELESSEN 0x0400 /* cube is relatively essential */
+
+/* Most efficient way to look at all members of a set family */
+#define foreach_set(R, last, p)\
+ for(p=R->data,last=p+R->count*R->wsize;p<last;p+=R->wsize)
+#define foreach_remaining_set(R, last, pfirst, p)\
+ for(p=pfirst+R->wsize,last=R->data+R->count*R->wsize;p<last;p+=R->wsize)
+#define foreach_active_set(R, last, p)\
+ foreach_set(R,last,p) if (TESTP(p, ACTIVE))
+
+/* Another way that also keeps the index of the current set member in i */
+#define foreachi_set(R, i, p)\
+ for(p=R->data,i=0;i<R->count;p+=R->wsize,i++)
+#define foreachi_active_set(R, i, p)\
+ foreachi_set(R,i,p) if (TESTP(p, ACTIVE))
+
+/* Looping over all elements in a set:
+ * foreach_set_element(pset p, int i, unsigned val, int base) {
+ * .
+ * .
+ * .
+ * }
+ */
+#define foreach_set_element(p, i, val, base) \
+ for(i = LOOP(p); i > 0; ) \
+ for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) \
+ if (val & 1)
+
+/* Return a pointer to a given member of a set family */
+#define GETSET(family, index) ((family)->data + (family)->wsize * (index))
+
+/* Allocate and deallocate sets */
+#define set_new(size) set_clear(ALLOC(unsigned int, SET_SIZE(size)), size)
+#define set_full(size) set_fill(ALLOC(unsigned int, SET_SIZE(size)), size)
+#define set_save(r) set_copy(ALLOC(unsigned int, SET_SIZE(NELEM(r))), r)
+#define set_free(r) FREE(r)
+
+/* Check for set membership, remove set element and insert set element */
+#define is_in_set(set, e) (set[WHICH_WORD(e)] & (1 << WHICH_BIT(e)))
+#define set_remove(set, e) (set[WHICH_WORD(e)] &= ~ (1 << WHICH_BIT(e)))
+#define set_insert(set, e) (set[WHICH_WORD(e)] |= 1 << WHICH_BIT(e))
+
+/* Inline code substitution for those places that REALLY need it on a VAX */
+#ifdef NO_INLINE
+#define INLINEset_copy(r, a) (void) set_copy(r,a)
+#define INLINEset_clear(r, size) (void) set_clear(r, size)
+#define INLINEset_fill(r, size) (void) set_fill(r, size)
+#define INLINEset_and(r, a, b) (void) set_and(r, a, b)
+#define INLINEset_or(r, a, b) (void) set_or(r, a, b)
+#define INLINEset_diff(r, a, b) (void) set_diff(r, a, b)
+#define INLINEset_ndiff(r, a, b, f) (void) set_ndiff(r, a, b, f)
+#define INLINEset_xor(r, a, b) (void) set_xor(r, a, b)
+#define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f)
+#define INLINEset_merge(r, a, b, mask) (void) set_merge(r, a, b, mask)
+#define INLINEsetp_implies(a, b, when_false) \
+ if (! setp_implies(a,b)) when_false
+#define INLINEsetp_disjoint(a, b, when_false) \
+ if (! setp_disjoint(a,b)) when_false
+#define INLINEsetp_equal(a, b, when_false) \
+ if (! setp_equal(a,b)) when_false
+
+#else
+
+#define INLINEset_copy(r, a)\
+ {register int i_=LOOPCOPY(a); do r[i_]=a[i_]; while (--i_>=0);}
+#define INLINEset_clear(r, size)\
+ {register int i_=LOOPINIT(size); *r=i_; do r[i_] = 0; while (--i_ > 0);}
+#define INLINEset_fill(r, size)\
+ {register int i_=LOOPINIT(size); *r=i_; \
+ r[i_]=((unsigned int)(~0))>>(i_*BPI-size); while(--i_>0) r[i_]=~0;}
+#define INLINEset_and(r, a, b)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = a[i_] & b[i_]; while (--i_>0);}
+#define INLINEset_or(r, a, b)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = a[i_] | b[i_]; while (--i_>0);}
+#define INLINEset_diff(r, a, b)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = a[i_] & ~ b[i_]; while (--i_>0);}
+#define INLINEset_ndiff(r, a, b, fullset)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = fullset[i_] & (a[i_] | ~ b[i_]); while (--i_>0);}
+#ifdef IBM_WATC
+#define INLINEset_xor(r, a, b) (void) set_xor(r, a, b)
+#define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f)
+#else
+#define INLINEset_xor(r, a, b)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = a[i_] ^ b[i_]; while (--i_>0);}
+#define INLINEset_xnor(r, a, b, fullset)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = fullset[i_] & ~ (a[i_] ^ b[i_]); while (--i_>0);}
+#endif
+#define INLINEset_merge(r, a, b, mask)\
+ {register int i_=LOOP(a); PUTLOOP(r,i_);\
+ do r[i_] = (a[i_]&mask[i_]) | (b[i_]&~mask[i_]); while (--i_>0);}
+#define INLINEsetp_implies(a, b, when_false)\
+ {register int i_=LOOP(a); do if (a[i_]&~b[i_]) break; while (--i_>0);\
+ if (i_ != 0) when_false;}
+#define INLINEsetp_disjoint(a, b, when_false)\
+ {register int i_=LOOP(a); do if (a[i_]&b[i_]) break; while (--i_>0);\
+ if (i_ != 0) when_false;}
+#define INLINEsetp_equal(a, b, when_false)\
+ {register int i_=LOOP(a); do if (a[i_]!=b[i_]) break; while (--i_>0);\
+ if (i_ != 0) when_false;}
+
+#endif
+
+#if BPI == 32
+#define count_ones(v)\
+ (bit_count[v & 255] + bit_count[(v >> 8) & 255]\
+ + bit_count[(v >> 16) & 255] + bit_count[(v >> 24) & 255])
+#else
+#define count_ones(v) (bit_count[v & 255] + bit_count[(v >> 8) & 255])
+#endif
+
+/* Table for efficient bit counting */
+extern int bit_count[256];
+/*----- END OF set.h ----- */
+
+
+/* Define a boolean type */
+#define bool int
+#define FALSE 0
+#define TRUE 1
+#define MAYBE 2
+#define print_bool(x) ((x) == 0 ? "FALSE" : ((x) == 1 ? "TRUE" : "MAYBE"))
+
+/* Map many cube/cover types/routines into equivalent set types/routines */
+#define pcube pset
+#define new_cube() set_new(cube.size)
+#define free_cube(r) set_free(r)
+#define pcover pset_family
+#define new_cover(i) sf_new(i, cube.size)
+#define free_cover(r) sf_free(r)
+#define free_cubelist(T) FREE(T[0]); FREE(T);
+
+
+/* cost_t describes the cost of a cover */
+typedef struct cost_struct {
+ int cubes; /* number of cubes in the cover */
+ int in; /* transistor count, binary-valued variables */
+ int out; /* transistor count, output part */
+ int mv; /* transistor count, multiple-valued vars */
+ int total; /* total number of transistors */
+ int primes; /* number of prime cubes */
+} cost_t, *pcost;
+
+
+/* pair_t describes bit-paired variables */
+typedef struct pair_struct {
+ int cnt;
+ int *var1;
+ int *var2;
+} pair_t, *ppair;
+
+
+/* symbolic_list_t describes a single ".symbolic" line */
+typedef struct symbolic_list_struct {
+ int variable;
+ int pos;
+ struct symbolic_list_struct *next;
+} symbolic_list_t;
+
+
+/* symbolic_list_t describes a single ".symbolic" line */
+typedef struct symbolic_label_struct {
+ char *label;
+ struct symbolic_label_struct *next;
+} symbolic_label_t;
+
+
+/* symbolic_t describes a linked list of ".symbolic" lines */
+typedef struct symbolic_struct {
+ symbolic_list_t *symbolic_list; /* linked list of items */
+ int symbolic_list_length; /* length of symbolic_list list */
+ symbolic_label_t *symbolic_label; /* linked list of new names */
+ int symbolic_label_length; /* length of symbolic_label list */
+ struct symbolic_struct *next;
+} symbolic_t;
+
+
+/* PLA_t stores the logical representation of a PLA */
+typedef struct {
+ pcover F, D, R; /* on-set, off-set and dc-set */
+ char *filename; /* filename */
+ int pla_type; /* logical PLA format */
+ pcube phase; /* phase to split into on-set and off-set */
+ ppair pair; /* how to pair variables */
+ char **label; /* labels for the columns */
+ symbolic_t *symbolic; /* allow binary->symbolic mapping */
+ symbolic_t *symbolic_output;/* allow symbolic output mapping */
+} PLA_t, *pPLA;
+
+#define equal(a,b) (strcmp(a,b) == 0)
+
+/* This is a hack which I wish I hadn't done, but too painful to change */
+#define CUBELISTSIZE(T) (((pcube *) T[1] - T) - 3)
+
+/* For documentation purposes */
+#define IN
+#define OUT
+#define INOUT
+
+/* The pla_type field describes the input and output format of the PLA */
+#define F_type 1
+#define D_type 2
+#define R_type 4
+#define PLEASURE_type 8 /* output format */
+#define EQNTOTT_type 16 /* output format algebraic eqns */
+#define KISS_type 128 /* output format kiss */
+#define CONSTRAINTS_type 256 /* output the constraints (numeric) */
+#define SYMBOLIC_CONSTRAINTS_type 512 /* output the constraints (symbolic) */
+#define FD_type (F_type | D_type)
+#define FR_type (F_type | R_type)
+#define DR_type (D_type | R_type)
+#define FDR_type (F_type | D_type | R_type)
+
+/* Definitions for the debug variable */
+#define COMPL 0x0001
+#define ESSEN 0x0002
+#define EXPAND 0x0004
+#define EXPAND1 0x0008
+#define GASP 0x0010
+#define IRRED 0x0020
+#define REDUCE 0x0040
+#define REDUCE1 0x0080
+#define SPARSE 0x0100
+#define TAUT 0x0200
+#define EXACT 0x0400
+#define MINCOV 0x0800
+#define MINCOV1 0x1000
+#define SHARP 0x2000
+#define IRRED1 0x4000
+
+#define VERSION\
+ "UC Berkeley, Espresso Version #2.3, Release date 01/31/88"
+
+/* Define constants used for recording program statistics */
+#define TIME_COUNT 16
+#define READ_TIME 0
+#define COMPL_TIME 1
+#define ONSET_TIME 2
+#define ESSEN_TIME 3
+#define EXPAND_TIME 4
+#define IRRED_TIME 5
+#define REDUCE_TIME 6
+#define GEXPAND_TIME 7
+#define GIRRED_TIME 8
+#define GREDUCE_TIME 9
+#define PRIMES_TIME 10
+#define MINCOV_TIME 11
+#define MV_REDUCE_TIME 12
+#define RAISE_IN_TIME 13
+#define VERIFY_TIME 14
+#define WRITE_TIME 15
+
+
+/* For those who like to think about PLAs, macros to get at inputs/outputs */
+#define NUMINPUTS cube.num_binary_vars
+#define NUMOUTPUTS cube.part_size[cube.num_vars - 1]
+
+#define POSITIVE_PHASE(pos)\
+ (is_in_set(PLA->phase, cube.first_part[cube.output]+pos) != 0)
+
+#define INLABEL(var) PLA->label[cube.first_part[var] + 1]
+#define OUTLABEL(pos) PLA->label[cube.first_part[cube.output] + pos]
+
+#define GETINPUT(c, pos)\
+ ((c[WHICH_WORD(2*pos)] >> WHICH_BIT(2*pos)) & 3)
+#define GETOUTPUT(c, pos)\
+ (is_in_set(c, cube.first_part[cube.output] + pos) != 0)
+
+#define PUTINPUT(c, pos, value)\
+ c[WHICH_WORD(2*pos)] = (c[WHICH_WORD(2*pos)] & ~(3 << WHICH_BIT(2*pos)))\
+ | (value << WHICH_BIT(2*pos))
+#define PUTOUTPUT(c, pos, value)\
+ c[WHICH_WORD(pos)] = (c[WHICH_WORD(pos)] & ~(1 << WHICH_BIT(pos)))\
+ | (value << WHICH_BIT(pos))
+
+#define TWO 3
+#define DASH 3
+#define ONE 2
+#define ZERO 1
+
+
+#define EXEC(fct, name, S)\
+ {long t=ptime();fct;if(trace)print_trace(S,name,ptime()-t);}
+#define EXEC_S(fct, name, S)\
+ {long t=ptime();fct;if(summary)print_trace(S,name,ptime()-t);}
+#define EXECUTE(fct,i,S,cost)\
+ {long t=ptime();fct;totals(t,i,S,&(cost));}
+
+/*
+ * Global Variable Declarations
+ */
+
+extern unsigned int debug; /* debug parameter */
+extern bool verbose_debug; /* -v: whether to print a lot */
+extern char *total_name[TIME_COUNT]; /* basic function names */
+extern long total_time[TIME_COUNT]; /* time spent in basic fcts */
+extern int total_calls[TIME_COUNT]; /* # calls to each fct */
+
+extern bool echo_comments; /* turned off by -eat option */
+extern bool echo_unknown_commands; /* always true ?? */
+extern bool force_irredundant; /* -nirr command line option */
+extern bool skip_make_sparse;
+extern bool kiss; /* -kiss command line option */
+extern bool pos; /* -pos command line option */
+extern bool print_solution; /* -x command line option */
+extern bool recompute_onset; /* -onset command line option */
+extern bool remove_essential; /* -ness command line option */
+extern bool single_expand; /* -fast command line option */
+extern bool summary; /* -s command line option */
+extern bool trace; /* -t command line option */
+extern bool unwrap_onset; /* -nunwrap command line option */
+extern bool use_random_order; /* -random command line option */
+extern bool use_super_gasp; /* -strong command line option */
+extern char *filename; /* filename PLA was read from */
+extern bool debug_exact_minimization; /* dumps info for -do exact */
+
+
+/*
+ * pla_types are the input and output types for reading/writing a PLA
+ */
+struct pla_types_struct {
+ char *key;
+ int value;
+};
+
+
+/*
+ * The cube structure is a global structure which contains information
+ * on how a set maps into a cube -- i.e., number of parts per variable,
+ * number of variables, etc. Also, many fields are pre-computed to
+ * speed up various primitive operations.
+ */
+#define CUBE_TEMP 10
+
+struct cube_struct {
+ int size; /* set size of a cube */
+ int num_vars; /* number of variables in a cube */
+ int num_binary_vars; /* number of binary variables */
+ int *first_part; /* first element of each variable */
+ int *last_part; /* first element of each variable */
+ int *part_size; /* number of elements in each variable */
+ int *first_word; /* first word for each variable */
+ int *last_word; /* last word for each variable */
+ pset binary_mask; /* Mask to extract binary variables */
+ pset mv_mask; /* mask to get mv parts */
+ pset *var_mask; /* mask to extract a variable */
+ pset *temp; /* an array of temporary sets */
+ pset fullset; /* a full cube */
+ pset emptyset; /* an empty cube */
+ unsigned int inmask; /* mask to get odd word of binary part */
+ int inword; /* which word number for above */
+ int *sparse; /* should this variable be sparse? */
+ int num_mv_vars; /* number of multiple-valued variables */
+ int output; /* which variable is "output" (-1 if none) */
+};
+
+struct cdata_struct {
+ int *part_zeros; /* count of zeros for each element */
+ int *var_zeros; /* count of zeros for each variable */
+ int *parts_active; /* number of "active" parts for each var */
+ bool *is_unate; /* indicates given var is unate */
+ int vars_active; /* number of "active" variables */
+ int vars_unate; /* number of unate variables */
+ int best; /* best "binate" variable */
+};
+
+
+extern struct pla_types_struct pla_types[];
+extern struct cube_struct cube, temp_cube_save;
+extern struct cdata_struct cdata, temp_cdata_save;
+
+#ifdef lint
+#define DISJOINT 0x5555
+#else
+#if BPI == 32
+#define DISJOINT 0x55555555
+#else
+#define DISJOINT 0x5555
+#endif
+#endif
+
+/* function declarations */
+
+/* cofactor.c */ extern int binate_split_select();
+/* cofactor.c */ extern pcover cubeunlist();
+/* cofactor.c */ extern pcube *cofactor();
+/* cofactor.c */ extern pcube *cube1list();
+/* cofactor.c */ extern pcube *cube2list();
+/* cofactor.c */ extern pcube *cube3list();
+/* cofactor.c */ extern pcube *scofactor();
+/* cofactor.c */ extern void massive_count();
+/* compl.c */ extern pcover complement();
+/* compl.c */ extern pcover simplify();
+/* compl.c */ extern void simp_comp();
+/* contain.c */ extern int d1_rm_equal();
+/* contain.c */ extern int rm2_contain();
+/* contain.c */ extern int rm2_equal();
+/* contain.c */ extern int rm_contain();
+/* contain.c */ extern int rm_equal();
+/* contain.c */ extern int rm_rev_contain();
+/* contain.c */ extern pset *sf_list();
+/* contain.c */ extern pset *sf_sort();
+/* contain.c */ extern pset_family d1merge();
+/* contain.c */ extern pset_family dist_merge();
+/* contain.c */ extern pset_family sf_contain();
+/* contain.c */ extern pset_family sf_dupl();
+/* contain.c */ extern pset_family sf_ind_contain();
+/* contain.c */ extern pset_family sf_ind_unlist();
+/* contain.c */ extern pset_family sf_merge();
+/* contain.c */ extern pset_family sf_rev_contain();
+/* contain.c */ extern pset_family sf_union();
+/* contain.c */ extern pset_family sf_unlist();
+/* cubestr.c */ extern void cube_setup();
+/* cubestr.c */ extern void restore_cube_struct();
+/* cubestr.c */ extern void save_cube_struct();
+/* cubestr.c */ extern void setdown_cube();
+/* cvrin.c */ extern PLA_labels();
+/* cvrin.c */ extern char *get_word();
+/* cvrin.c */ extern int label_index();
+/* cvrin.c */ extern int read_pla();
+/* cvrin.c */ extern int read_symbolic();
+/* cvrin.c */ extern pPLA new_PLA();
+/* cvrin.c */ extern void PLA_summary();
+/* cvrin.c */ extern void free_PLA();
+/* cvrin.c */ extern void parse_pla();
+/* cvrin.c */ extern void read_cube();
+/* cvrin.c */ extern void skip_line();
+/* cvrm.c */ extern foreach_output_function();
+/* cvrm.c */ extern int cubelist_partition();
+/* cvrm.c */ extern int so_both_do_espresso();
+/* cvrm.c */ extern int so_both_do_exact();
+/* cvrm.c */ extern int so_both_save();
+/* cvrm.c */ extern int so_do_espresso();
+/* cvrm.c */ extern int so_do_exact();
+/* cvrm.c */ extern int so_save();
+/* cvrm.c */ extern pcover cof_output();
+/* cvrm.c */ extern pcover lex_sort();
+/* cvrm.c */ extern pcover mini_sort();
+/* cvrm.c */ extern pcover random_order();
+/* cvrm.c */ extern pcover size_sort();
+/* cvrm.c */ extern pcover sort_reduce();
+/* cvrm.c */ extern pcover uncof_output();
+/* cvrm.c */ extern pcover unravel();
+/* cvrm.c */ extern pcover unravel_range();
+/* cvrm.c */ extern void so_both_espresso();
+/* cvrm.c */ extern void so_espresso();
+/* cvrmisc.c */ extern char *fmt_cost();
+/* cvrmisc.c */ extern char *print_cost();
+/* cvrmisc.c */ extern char *strsav();
+/* cvrmisc.c */ extern void copy_cost();
+/* cvrmisc.c */ extern void cover_cost();
+/* cvrmisc.c */ extern void fatal();
+/* cvrmisc.c */ extern void print_trace();
+/* cvrmisc.c */ extern void size_stamp();
+/* cvrmisc.c */ extern void totals();
+/* cvrout.c */ extern char *fmt_cube();
+/* cvrout.c */ extern char *fmt_expanded_cube();
+/* cvrout.c */ extern char *pc1();
+/* cvrout.c */ extern char *pc2();
+/* cvrout.c */ extern char *pc3();
+/* cvrout.c */ extern int makeup_labels();
+/* cvrout.c */ extern kiss_output();
+/* cvrout.c */ extern kiss_print_cube();
+/* cvrout.c */ extern output_symbolic_constraints();
+/* cvrout.c */ extern void cprint();
+/* cvrout.c */ extern void debug1_print();
+/* cvrout.c */ extern void debug_print();
+/* cvrout.c */ extern void eqn_output();
+/* cvrout.c */ extern void fpr_header();
+/* cvrout.c */ extern void fprint_pla();
+/* cvrout.c */ extern void pls_group();
+/* cvrout.c */ extern void pls_label();
+/* cvrout.c */ extern void pls_output();
+/* cvrout.c */ extern void print_cube();
+/* cvrout.c */ extern void print_expanded_cube();
+/* cvrout.c */ extern void sf_debug_print();
+/* equiv.c */ extern find_equiv_outputs();
+/* equiv.c */ extern int check_equiv();
+/* espresso.c */ extern pcover espresso();
+/* essen.c */ extern bool essen_cube();
+/* essen.c */ extern pcover cb_consensus();
+/* essen.c */ extern pcover cb_consensus_dist0();
+/* essen.c */ extern pcover essential();
+/* exact.c */ extern pcover minimize_exact();
+/* exact.c */ extern pcover minimize_exact_literals();
+/* expand.c */ extern bool feasibly_covered();
+/* expand.c */ extern int most_frequent();
+/* expand.c */ extern pcover all_primes();
+/* expand.c */ extern pcover expand();
+/* expand.c */ extern pcover find_all_primes();
+/* expand.c */ extern void elim_lowering();
+/* expand.c */ extern void essen_parts();
+/* expand.c */ extern void essen_raising();
+/* expand.c */ extern void expand1();
+/* expand.c */ extern void mincov();
+/* expand.c */ extern void select_feasible();
+/* expand.c */ extern void setup_BB_CC();
+/* gasp.c */ extern pcover expand_gasp();
+/* gasp.c */ extern pcover irred_gasp();
+/* gasp.c */ extern pcover last_gasp();
+/* gasp.c */ extern pcover super_gasp();
+/* gasp.c */ extern void expand1_gasp();
+/* getopt.c */ extern int util_getopt();
+/* hack.c */ extern find_dc_inputs();
+/* hack.c */ extern find_inputs();
+/* hack.c */ extern form_bitvector();
+/* hack.c */ extern map_dcset();
+/* hack.c */ extern map_output_symbolic();
+/* hack.c */ extern map_symbolic();
+/* hack.c */ extern pcover map_symbolic_cover();
+/* hack.c */ extern symbolic_hack_labels();
+/* irred.c */ extern bool cube_is_covered();
+/* irred.c */ extern bool taut_special_cases();
+/* irred.c */ extern bool tautology();
+/* irred.c */ extern pcover irredundant();
+/* irred.c */ extern void mark_irredundant();
+/* irred.c */ extern void irred_split_cover();
+/* irred.c */ extern sm_matrix *irred_derive_table();
+/* map.c */ extern pset minterms();
+/* map.c */ extern void explode();
+/* map.c */ extern void map();
+/* opo.c */ extern output_phase_setup();
+/* opo.c */ extern pPLA set_phase();
+/* opo.c */ extern pcover opo();
+/* opo.c */ extern pcube find_phase();
+/* opo.c */ extern pset_family find_covers();
+/* opo.c */ extern pset_family form_cover_table();
+/* opo.c */ extern pset_family opo_leaf();
+/* opo.c */ extern pset_family opo_recur();
+/* opo.c */ extern void opoall();
+/* opo.c */ extern void phase_assignment();
+/* opo.c */ extern void repeated_phase_assignment();
+/* pair.c */ extern generate_all_pairs();
+/* pair.c */ extern int **find_pairing_cost();
+/* pair.c */ extern int find_best_cost();
+/* pair.c */ extern int greedy_best_cost();
+/* pair.c */ extern int minimize_pair();
+/* pair.c */ extern int pair_free();
+/* pair.c */ extern pair_all();
+/* pair.c */ extern pcover delvar();
+/* pair.c */ extern pcover pairvar();
+/* pair.c */ extern ppair pair_best_cost();
+/* pair.c */ extern ppair pair_new();
+/* pair.c */ extern ppair pair_save();
+/* pair.c */ extern print_pair();
+/* pair.c */ extern void find_optimal_pairing();
+/* pair.c */ extern void set_pair();
+/* pair.c */ extern void set_pair1();
+/* primes.c */ extern pcover primes_consensus();
+/* reduce.c */ extern bool sccc_special_cases();
+/* reduce.c */ extern pcover reduce();
+/* reduce.c */ extern pcube reduce_cube();
+/* reduce.c */ extern pcube sccc();
+/* reduce.c */ extern pcube sccc_cube();
+/* reduce.c */ extern pcube sccc_merge();
+/* set.c */ extern bool set_andp();
+/* set.c */ extern bool set_orp();
+/* set.c */ extern bool setp_disjoint();
+/* set.c */ extern bool setp_empty();
+/* set.c */ extern bool setp_equal();
+/* set.c */ extern bool setp_full();
+/* set.c */ extern bool setp_implies();
+/* set.c */ extern char *pbv1();
+/* set.c */ extern char *ps1();
+/* set.c */ extern int *sf_count();
+/* set.c */ extern int *sf_count_restricted();
+/* set.c */ extern int bit_index();
+/* set.c */ extern int set_dist();
+/* set.c */ extern int set_ord();
+/* set.c */ extern void set_adjcnt();
+/* set.c */ extern pset set_and();
+/* set.c */ extern pset set_clear();
+/* set.c */ extern pset set_copy();
+/* set.c */ extern pset set_diff();
+/* set.c */ extern pset set_fill();
+/* set.c */ extern pset set_merge();
+/* set.c */ extern pset set_or();
+/* set.c */ extern pset set_xor();
+/* set.c */ extern pset sf_and();
+/* set.c */ extern pset sf_or();
+/* set.c */ extern pset_family sf_active();
+/* set.c */ extern pset_family sf_addcol();
+/* set.c */ extern pset_family sf_addset();
+/* set.c */ extern pset_family sf_append();
+/* set.c */ extern pset_family sf_bm_read();
+/* set.c */ extern pset_family sf_compress();
+/* set.c */ extern pset_family sf_copy();
+/* set.c */ extern pset_family sf_copy_col();
+/* set.c */ extern pset_family sf_delc();
+/* set.c */ extern pset_family sf_delcol();
+/* set.c */ extern pset_family sf_inactive();
+/* set.c */ extern pset_family sf_join();
+/* set.c */ extern pset_family sf_new();
+/* set.c */ extern pset_family sf_permute();
+/* set.c */ extern pset_family sf_read();
+/* set.c */ extern pset_family sf_save();
+/* set.c */ extern pset_family sf_transpose();
+/* set.c */ extern void set_write();
+/* set.c */ extern void sf_bm_print();
+/* set.c */ extern void sf_cleanup();
+/* set.c */ extern void sf_delset();
+/* set.c */ extern void sf_free();
+/* set.c */ extern void sf_print();
+/* set.c */ extern void sf_write();
+/* setc.c */ extern bool ccommon();
+/* setc.c */ extern bool cdist0();
+/* setc.c */ extern bool full_row();
+/* setc.c */ extern int ascend();
+/* setc.c */ extern int cactive();
+/* setc.c */ extern int cdist();
+/* setc.c */ extern int cdist01();
+/* setc.c */ extern int cvolume();
+/* setc.c */ extern int d1_order();
+/* setc.c */ extern int d1_order_size();
+/* setc.c */ extern int desc1();
+/* setc.c */ extern int descend();
+/* setc.c */ extern int lex_order();
+/* setc.c */ extern int lex_order1();
+/* setc.c */ extern pset force_lower();
+/* setc.c */ extern void consensus();
+/* sharp.c */ extern pcover cb1_dsharp();
+/* sharp.c */ extern pcover cb_dsharp();
+/* sharp.c */ extern pcover cb_recur_dsharp();
+/* sharp.c */ extern pcover cb_recur_sharp();
+/* sharp.c */ extern pcover cb_sharp();
+/* sharp.c */ extern pcover cv_dsharp();
+/* sharp.c */ extern pcover cv_intersect();
+/* sharp.c */ extern pcover cv_sharp();
+/* sharp.c */ extern pcover dsharp();
+/* sharp.c */ extern pcover make_disjoint();
+/* sharp.c */ extern pcover sharp();
+/* sminterf.c */pset do_sm_minimum_cover();
+/* sparse.c */ extern pcover make_sparse();
+/* sparse.c */ extern pcover mv_reduce();
+#if !defined(__osf__) && !defined(__STDC__) && !defined(__hpux)
+/* ucbqsort.c */ extern qsort();
+#endif
+/* ucbqsort.c */ extern qst();
+/* unate.c */ extern pcover find_all_minimal_covers_petrick();
+/* unate.c */ extern pcover map_cover_to_unate();
+/* unate.c */ extern pcover map_unate_to_cover();
+/* unate.c */ extern pset_family exact_minimum_cover();
+/* unate.c */ extern pset_family gen_primes();
+/* unate.c */ extern pset_family unate_compl();
+/* unate.c */ extern pset_family unate_complement();
+/* unate.c */ extern pset_family unate_intersect();
+/* verify.c */ extern PLA_permute();
+/* verify.c */ extern bool PLA_verify();
+/* verify.c */ extern bool check_consistency();
+/* verify.c */ extern bool verify();
diff --git a/src/misc/espresso/essen.c b/src/misc/espresso/essen.c
new file mode 100644
index 00000000..6a46295d
--- /dev/null
+++ b/src/misc/espresso/essen.c
@@ -0,0 +1,179 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: essen.c
+ purpose: Find essential primes in a multiple-valued function
+*/
+
+#include "espresso.h"
+
+/*
+ essential -- return a cover consisting of the cubes of F which are
+ essential prime implicants (with respect to F u D); Further, remove
+ these cubes from the ON-set F, and add them to the OFF-set D.
+
+ Sometimes EXPAND can determine that a cube is not an essential prime.
+ If so, it will set the "NONESSEN" flag in the cube.
+
+ We count on IRREDUNDANT to have set the flag RELESSEN to indicate
+ that a prime was relatively essential (i.e., covers some minterm
+ not contained in any other prime in the current cover), or to have
+ reset the flag to indicate that a prime was relatively redundant
+ (i.e., all minterms covered by other primes in the current cover).
+ Of course, after executing irredundant, all of the primes in the
+ cover are relatively essential, but we can mark the primes which
+ were redundant at the start of irredundant and avoid an extra check
+ on these primes for essentiality.
+*/
+
+pcover essential(Fp, Dp)
+IN pcover *Fp, *Dp;
+{
+ register pcube last, p;
+ pcover E, F = *Fp, D = *Dp;
+
+ /* set all cubes in F active */
+ (void) sf_active(F);
+
+ /* Might as well start out with some cubes in E */
+ E = new_cover(10);
+
+ foreach_set(F, last, p) {
+ /* don't test a prime which EXPAND says is nonessential */
+ if (! TESTP(p, NONESSEN)) {
+ /* only test a prime which was relatively essential */
+ if (TESTP(p, RELESSEN)) {
+ /* Check essentiality */
+ if (essen_cube(F, D, p)) {
+ if (debug & ESSEN)
+ printf("ESSENTIAL: %s\n", pc1(p));
+ E = sf_addset(E, p);
+ RESET(p, ACTIVE);
+ F->active_count--;
+ }
+ }
+ }
+ }
+
+ *Fp = sf_inactive(F); /* delete the inactive cubes from F */
+ *Dp = sf_join(D, E); /* add the essentials to D */
+ sf_free(D);
+ return E;
+}
+
+/*
+ essen_cube -- check if a single cube is essential or not
+
+ The prime c is essential iff
+
+ consensus((F u D) # c, c) u D
+
+ does not contain c.
+*/
+bool essen_cube(F, D, c)
+IN pcover F, D;
+IN pcube c;
+{
+ pcover H, FD;
+ pcube *H1;
+ bool essen;
+
+ /* Append F and D together, and take the sharp-consensus with c */
+ FD = sf_join(F, D);
+ H = cb_consensus(FD, c);
+ free_cover(FD);
+
+ /* Add the don't care set, and see if this covers c */
+ H1 = cube2list(H, D);
+ essen = ! cube_is_covered(H1, c);
+ free_cubelist(H1);
+
+ free_cover(H);
+ return essen;
+}
+
+
+/*
+ * cb_consensus -- compute consensus(T # c, c)
+ */
+pcover cb_consensus(T, c)
+register pcover T;
+register pcube c;
+{
+ register pcube temp, last, p;
+ register pcover R;
+
+ R = new_cover(T->count*2);
+ temp = new_cube();
+ foreach_set(T, last, p) {
+ if (p != c) {
+ switch (cdist01(p, c)) {
+ case 0:
+ /* distance-0 needs special care */
+ R = cb_consensus_dist0(R, p, c);
+ break;
+
+ case 1:
+ /* distance-1 is easy because no sharping required */
+ consensus(temp, p, c);
+ R = sf_addset(R, temp);
+ break;
+ }
+ }
+ }
+ set_free(temp);
+ return R;
+}
+
+
+/*
+ * form the sharp-consensus for p and c when they intersect
+ * What we are forming is consensus(p # c, c).
+ */
+pcover cb_consensus_dist0(R, p, c)
+pcover R;
+register pcube p, c;
+{
+ int var;
+ bool got_one;
+ register pcube temp, mask;
+ register pcube p_diff_c=cube.temp[0], p_and_c=cube.temp[1];
+
+ /* If c contains p, then this gives us no information for essential test */
+ if (setp_implies(p, c)) {
+ return R;
+ }
+
+ /* For the multiple-valued variables */
+ temp = new_cube();
+ got_one = FALSE;
+ INLINEset_diff(p_diff_c, p, c);
+ INLINEset_and(p_and_c, p, c);
+
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ /* Check if c(var) is contained in p(var) -- if so, no news */
+ mask = cube.var_mask[var];
+ if (! setp_disjoint(p_diff_c, mask)) {
+ INLINEset_merge(temp, c, p_and_c, mask);
+ R = sf_addset(R, temp);
+ got_one = TRUE;
+ }
+ }
+
+ /* if no cube so far, add one for the intersection */
+ if (! got_one && cube.num_binary_vars > 0) {
+ /* Add a single cube for the intersection of p and c */
+ INLINEset_and(temp, p, c);
+ R = sf_addset(R, temp);
+ }
+
+ set_free(temp);
+ return R;
+}
diff --git a/src/misc/espresso/exact.c b/src/misc/espresso/exact.c
new file mode 100644
index 00000000..b1943636
--- /dev/null
+++ b/src/misc/espresso/exact.c
@@ -0,0 +1,181 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+
+static void dump_irredundant();
+static pcover do_minimize();
+
+
+/*
+ * minimize_exact -- main entry point for exact minimization
+ *
+ * Global flags which affect this routine are:
+ *
+ * debug
+ * skip_make_sparse
+ */
+
+pcover
+minimize_exact(F, D, R, exact_cover)
+pcover F, D, R;
+int exact_cover;
+{
+ return do_minimize(F, D, R, exact_cover, /*weighted*/ 0);
+}
+
+
+pcover
+minimize_exact_literals(F, D, R, exact_cover)
+pcover F, D, R;
+int exact_cover;
+{
+ return do_minimize(F, D, R, exact_cover, /*weighted*/ 1);
+}
+
+
+
+static pcover
+do_minimize(F, D, R, exact_cover, weighted)
+pcover F, D, R;
+int exact_cover;
+int weighted;
+{
+ pcover newF, E, Rt, Rp;
+ pset p, last;
+ int heur, level, *weights, i;
+ sm_matrix *table;
+ sm_row *cover;
+ sm_element *pe;
+ int debug_save = debug;
+
+ if (debug & EXACT) {
+ debug |= (IRRED | MINCOV);
+ }
+#if defined(sun) || defined(bsd4_2) /* hack ... */
+ if (debug & MINCOV) {
+ setlinebuf(stdout);
+ }
+#endif
+ level = (debug & MINCOV) ? 4 : 0;
+ heur = ! exact_cover;
+
+ /* Generate all prime implicants */
+ EXEC(F = primes_consensus(cube2list(F, D)), "PRIMES ", F);
+
+ /* Setup the prime implicant table */
+ EXEC(irred_split_cover(F, D, &E, &Rt, &Rp), "ESSENTIALS ", E);
+ EXEC(table = irred_derive_table(D, E, Rp), "PI-TABLE ", Rp);
+
+ /* Solve either a weighted or nonweighted covering problem */
+ if (weighted) {
+ /* correct only for all 2-valued variables */
+ weights = ALLOC(int, F->count);
+ foreach_set(Rp, last, p) {
+ weights[SIZE(p)] = cube.size - set_ord(p);
+ /* We have added the 0's in the output part instead of the 1's.
+ This loop corrects the literal count. */
+ for (i = cube.first_part[cube.output];
+ i <= cube.last_part[cube.output]; i++) {
+ is_in_set(p, i) ? weights[SIZE(p)]++ : weights[SIZE(p)]--;
+ }
+ }
+ } else {
+ weights = NIL(int);
+ }
+ EXEC(cover=sm_minimum_cover(table,weights,heur,level), "MINCOV ", F);
+ if (weights != 0) {
+ FREE(weights);
+ }
+
+ if (debug & EXACT) {
+ dump_irredundant(E, Rt, Rp, table);
+ }
+
+ /* Form the result cover */
+ newF = new_cover(100);
+ foreach_set(E, last, p) {
+ newF = sf_addset(newF, p);
+ }
+ sm_foreach_row_element(cover, pe) {
+ newF = sf_addset(newF, GETSET(F, pe->col_num));
+ }
+
+ free_cover(E);
+ free_cover(Rt);
+ free_cover(Rp);
+ sm_free(table);
+ sm_row_free(cover);
+ free_cover(F);
+
+ /* Attempt to make the results more sparse */
+ debug &= ~ (IRRED | SHARP | MINCOV);
+ if (! skip_make_sparse && R != 0) {
+ newF = make_sparse(newF, D, R);
+ }
+
+ debug = debug_save;
+ return newF;
+}
+
+static void
+dump_irredundant(E, Rt, Rp, table)
+pcover E, Rt, Rp;
+sm_matrix *table;
+{
+ FILE *fp_pi_table, *fp_primes;
+ pPLA PLA;
+ pset last, p;
+ char *file;
+
+ if (filename == 0 || strcmp(filename, "(stdin)") == 0) {
+ fp_pi_table = fp_primes = stdout;
+ } else {
+ file = ALLOC(char, strlen(filename)+20);
+ (void) sprintf(file, "%s.primes", filename);
+ if ((fp_primes = fopen(file, "w")) == NULL) {
+ (void) fprintf(stderr, "espresso: Unable to open %s\n", file);
+ fp_primes = stdout;
+ }
+ (void) sprintf(file, "%s.pi", filename);
+ if ((fp_pi_table = fopen(file, "w")) == NULL) {
+ (void) fprintf(stderr, "espresso: Unable to open %s\n", file);
+ fp_pi_table = stdout;
+ }
+ FREE(file);
+ }
+
+ PLA = new_PLA();
+ PLA_labels(PLA);
+
+ fpr_header(fp_primes, PLA, F_type);
+ free_PLA(PLA);
+
+ (void) fprintf(fp_primes, "# Essential primes are\n");
+ foreach_set(E, last, p) {
+ (void) fprintf(fp_primes, "%s\n", pc1(p));
+ }
+ (void) fprintf(fp_primes, "# Totally redundant primes are\n");
+ foreach_set(Rt, last, p) {
+ (void) fprintf(fp_primes, "%s\n", pc1(p));
+ }
+ (void) fprintf(fp_primes, "# Partially redundant primes are\n");
+ foreach_set(Rp, last, p) {
+ (void) fprintf(fp_primes, "%s\n", pc1(p));
+ }
+ if (fp_primes != stdout) {
+ (void) fclose(fp_primes);
+ }
+
+ sm_write(fp_pi_table, table);
+ if (fp_pi_table != stdout) {
+ (void) fclose(fp_pi_table);
+ }
+}
diff --git a/src/misc/espresso/expand.c b/src/misc/espresso/expand.c
new file mode 100644
index 00000000..2765d71c
--- /dev/null
+++ b/src/misc/espresso/expand.c
@@ -0,0 +1,693 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: expand.c
+ purpose: Perform the Espresso-II Expansion Step
+
+ The idea is to take each nonprime cube of the on-set and expand it
+ into a prime implicant such that we can cover as many other cubes
+ of the on-set. If no cube of the on-set can be covered, then we
+ expand each cube into a large prime implicant by transforming the
+ problem into a minimum covering problem which is solved by the
+ heuristics of minimum_cover.
+
+ These routines revolve around having a representation of the
+ OFF-set. (In contrast to the Espresso-II manuscript, we do NOT
+ require an "unwrapped" version of the OFF-set).
+
+ Some conventions on variable names:
+
+ SUPER_CUBE is the supercube of all cubes which can be covered
+ by an expansion of the cube being expanded
+
+ OVEREXPANDED_CUBE is the cube which would result from expanding
+ all parts which can expand individually of the cube being expanded
+
+ RAISE is the current expansion of the current cube
+
+ FREESET is the set of parts which haven't been raised or lowered yet.
+
+ INIT_LOWER is a set of parts to be removed from the free parts before
+ starting the expansion
+*/
+
+#include "espresso.h"
+
+/*
+ expand -- expand each nonprime cube of F into a prime implicant
+
+ If nonsparse is true, only the non-sparse variables will be expanded;
+ this is done by forcing all of the sparse variables out of the free set.
+*/
+
+pcover expand(F, R, nonsparse)
+INOUT pcover F;
+IN pcover R;
+IN bool nonsparse; /* expand non-sparse variables only */
+{
+ register pcube last, p;
+ pcube RAISE, FREESET, INIT_LOWER, SUPER_CUBE, OVEREXPANDED_CUBE;
+ int var, num_covered;
+ bool change;
+
+ /* Order the cubes according to "chewing-away from the edges" of mini */
+ if (use_random_order)
+ F = random_order(F);
+ else
+ F = mini_sort(F, ascend);
+
+ /* Allocate memory for variables needed by expand1() */
+ RAISE = new_cube();
+ FREESET = new_cube();
+ INIT_LOWER = new_cube();
+ SUPER_CUBE = new_cube();
+ OVEREXPANDED_CUBE = new_cube();
+
+ /* Setup the initial lowering set (differs only for nonsparse) */
+ if (nonsparse)
+ for(var = 0; var < cube.num_vars; var++)
+ if (cube.sparse[var])
+ (void) set_or(INIT_LOWER, INIT_LOWER, cube.var_mask[var]);
+
+ /* Mark all cubes as not covered, and maybe essential */
+ foreach_set(F, last, p) {
+ RESET(p, COVERED);
+ RESET(p, NONESSEN);
+ }
+
+ /* Try to expand each nonprime and noncovered cube */
+ foreach_set(F, last, p) {
+ /* do not expand if PRIME or if covered by previous expansion */
+ if (! TESTP(p, PRIME) && ! TESTP(p, COVERED)) {
+
+ /* expand the cube p, result is RAISE */
+ expand1(R, F, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE,
+ INIT_LOWER, &num_covered, p);
+ if (debug & EXPAND)
+ printf("EXPAND: %s (covered %d)\n", pc1(p), num_covered);
+ (void) set_copy(p, RAISE);
+ SET(p, PRIME);
+ RESET(p, COVERED); /* not really necessary */
+
+ /* See if we generated an inessential prime */
+ if (num_covered == 0 && ! setp_equal(p, OVEREXPANDED_CUBE)) {
+ SET(p, NONESSEN);
+ }
+ }
+ }
+
+ /* Delete any cubes of F which became covered during the expansion */
+ F->active_count = 0;
+ change = FALSE;
+ foreach_set(F, last, p) {
+ if (TESTP(p, COVERED)) {
+ RESET(p, ACTIVE);
+ change = TRUE;
+ } else {
+ SET(p, ACTIVE);
+ F->active_count++;
+ }
+ }
+ if (change)
+ F = sf_inactive(F);
+
+ free_cube(RAISE);
+ free_cube(FREESET);
+ free_cube(INIT_LOWER);
+ free_cube(SUPER_CUBE);
+ free_cube(OVEREXPANDED_CUBE);
+ return F;
+}
+
+/*
+ expand1 -- Expand a single cube against the OFF-set
+*/
+void expand1(BB, CC, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE,
+ INIT_LOWER, num_covered, c)
+pcover BB; /* Blocking matrix (OFF-set) */
+pcover CC; /* Covering matrix (ON-set) */
+pcube RAISE; /* The current parts which have been raised */
+pcube FREESET; /* The current parts which are free */
+pcube OVEREXPANDED_CUBE; /* Overexpanded cube of c */
+pcube SUPER_CUBE; /* Supercube of all cubes of CC we cover */
+pcube INIT_LOWER; /* Parts to initially remove from FREESET */
+int *num_covered; /* Number of cubes of CC which are covered */
+pcube c; /* The cube to be expanded */
+{
+ int bestindex;
+
+ if (debug & EXPAND1)
+ printf("\nEXPAND1: \t%s\n", pc1(c));
+
+ /* initialize BB and CC */
+ SET(c, PRIME); /* don't try to cover ourself */
+ setup_BB_CC(BB, CC);
+
+ /* initialize count of # cubes covered, and the supercube of them */
+ *num_covered = 0;
+ (void) set_copy(SUPER_CUBE, c);
+
+ /* Initialize the lowering, raising and unassigned sets */
+ (void) set_copy(RAISE, c);
+ (void) set_diff(FREESET, cube.fullset, RAISE);
+
+ /* If some parts are forced into lowering set, remove them */
+ if (! setp_empty(INIT_LOWER)) {
+ (void) set_diff(FREESET, FREESET, INIT_LOWER);
+ elim_lowering(BB, CC, RAISE, FREESET);
+ }
+
+ /* Determine what can be raised, and return the over-expanded cube */
+ essen_parts(BB, CC, RAISE, FREESET);
+ (void) set_or(OVEREXPANDED_CUBE, RAISE, FREESET);
+
+ /* While there are still cubes which can be covered, cover them ! */
+ if (CC->active_count > 0) {
+ select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered);
+ }
+
+ /* While there are still cubes covered by the overexpanded cube ... */
+ while (CC->active_count > 0) {
+ bestindex = most_frequent(CC, FREESET);
+ set_insert(RAISE, bestindex);
+ set_remove(FREESET, bestindex);
+ essen_parts(BB, CC, RAISE, FREESET);
+ }
+
+ /* Finally, when all else fails, choose the largest possible prime */
+ /* We will loop only if we decide unravelling OFF-set is too expensive */
+ while (BB->active_count > 0) {
+ mincov(BB, RAISE, FREESET);
+ }
+
+ /* Raise any remaining free coordinates */
+ (void) set_or(RAISE, RAISE, FREESET);
+}
+
+/*
+ essen_parts -- determine which parts are forced into the lowering
+ set to insure that the cube be orthognal to the OFF-set.
+
+ If any cube of the OFF-set is distance 1 from the raising cube,
+ then we must lower all parts of the conflicting variable. (If the
+ cube is distance 0, we detect this error here.)
+
+ If there are essentially lowered parts, we can remove from consideration
+ any cubes of the OFF-set which are more than distance 1 from the
+ overexpanded cube of RAISE.
+*/
+
+void essen_parts(BB, CC, RAISE, FREESET)
+pcover BB, CC;
+pcube RAISE, FREESET;
+{
+ register pcube p, r = RAISE;
+ pcube lastp, xlower = cube.temp[0];
+ int dist;
+
+ (void) set_copy(xlower, cube.emptyset);
+
+ foreach_active_set(BB, lastp, p) {
+#ifdef NO_INLINE
+ if ((dist = cdist01(p, r)) > 1) goto exit_if;
+#else
+ {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1)
+{x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto
+exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if(x=~(x|x>>1)&DISJOINT)if(dist==1||(
+dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube
+mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[
+var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[
+w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}}
+#endif
+ if (dist == 0) {
+ fatal("ON-set and OFF-set are not orthogonal");
+ } else {
+ (void) force_lower(xlower, p, r);
+ BB->active_count--;
+ RESET(p, ACTIVE);
+ }
+exit_if: ;
+ }
+
+ if (! setp_empty(xlower)) {
+ (void) set_diff(FREESET, FREESET, xlower);/* remove from free set */
+ elim_lowering(BB, CC, RAISE, FREESET);
+ }
+
+ if (debug & EXPAND1)
+ printf("ESSEN_PARTS:\tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+}
+
+/*
+ essen_raising -- determine which parts may always be added to
+ the raising set without restricting further expansions
+
+ General rule: if some part is not blocked by any cube of BB, then
+ this part can always be raised.
+*/
+
+void essen_raising(BB, RAISE, FREESET)
+register pcover BB;
+pcube RAISE, FREESET;
+{
+ register pcube last, p, xraise = cube.temp[0];
+
+ /* Form union of all cubes of BB, and then take complement wrt FREESET */
+ (void) set_copy(xraise, cube.emptyset);
+ foreach_active_set(BB, last, p)
+ INLINEset_or(xraise, xraise, p);
+ (void) set_diff(xraise, FREESET, xraise);
+
+ (void) set_or(RAISE, RAISE, xraise); /* add to raising set */
+ (void) set_diff(FREESET, FREESET, xraise); /* remove from free set */
+
+ if (debug & EXPAND1)
+ printf("ESSEN_RAISING:\tRAISE=%s FREESET=%s\n",
+ pc1(RAISE), pc2(FREESET));
+}
+
+/*
+ elim_lowering -- after removing parts from FREESET, we can reduce the
+ size of both BB and CC.
+
+ We mark as inactive any cube of BB which does not intersect the
+ overexpanded cube (i.e., RAISE + FREESET). Likewise, we remove
+ from CC any cube which is not covered by the overexpanded cube.
+*/
+
+void elim_lowering(BB, CC, RAISE, FREESET)
+pcover BB, CC;
+pcube RAISE, FREESET;
+{
+ register pcube p, r = set_or(cube.temp[0], RAISE, FREESET);
+ pcube last;
+
+ /*
+ * Remove sets of BB which are orthogonal to future expansions
+ */
+ foreach_active_set(BB, last, p) {
+#ifdef NO_INLINE
+ if (! cdist0(p, r))
+#else
+ {register int w,lastw;register unsigned int x;if((lastw=cube.inword)!=-1){x=p[
+lastw]&r[lastw];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w<lastw;w++){x=p[w]
+&r[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,lastw;register
+pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.
+var_mask[var];lastw=cube.last_word[var];for(w=cube.first_word[var];w<=lastw;w++)
+if(p[w]&r[w]&mask[w])goto nextvar;goto false;nextvar:;}}continue;false:
+#endif
+ BB->active_count--, RESET(p, ACTIVE);
+ }
+
+
+ /*
+ * Remove sets of CC which cannot be covered by future expansions
+ */
+ if (CC != (pcover) NULL) {
+ foreach_active_set(CC, last, p) {
+#ifdef NO_INLINE
+ if (! setp_implies(p, r))
+#else
+ INLINEsetp_implies(p, r, /* when false => */ goto false1);
+ /* when true => go to end of loop */ continue;
+ false1:
+#endif
+ CC->active_count--, RESET(p, ACTIVE);
+ }
+ }
+}
+
+/*
+ most_frequent -- When all else fails, select a reasonable part to raise
+ The active cubes of CC are the cubes which are covered by the
+ overexpanded cube of the original cube (however, we know that none
+ of them can actually be covered by a feasible expansion of the
+ original cube). We resort to the MINI strategy of selecting to
+ raise the part which will cover the same part in the most cubes of CC.
+*/
+int most_frequent(CC, FREESET)
+pcover CC;
+pcube FREESET;
+{
+ register int i, best_part, best_count, *count;
+ register pset p, last;
+
+ /* Count occurences of each variable */
+ count = ALLOC(int, cube.size);
+ for(i = 0; i < cube.size; i++)
+ count[i] = 0;
+ if (CC != (pcover) NULL)
+ foreach_active_set(CC, last, p)
+ set_adjcnt(p, count, 1);
+
+ /* Now find which free part occurs most often */
+ best_count = best_part = -1;
+ for(i = 0; i < cube.size; i++)
+ if (is_in_set(FREESET,i) && count[i] > best_count) {
+ best_part = i;
+ best_count = count[i];
+ }
+ FREE(count);
+
+ if (debug & EXPAND1)
+ printf("MOST_FREQUENT:\tbest=%d FREESET=%s\n", best_part, pc2(FREESET));
+ return best_part;
+}
+
+/*
+ setup_BB_CC -- set up the blocking and covering set families;
+
+ Note that the blocking family is merely the set of cubes of R, and
+ that CC is the set of cubes of F which might possibly be covered
+ (i.e., nonprime cubes, and cubes not already covered)
+*/
+
+void setup_BB_CC(BB, CC)
+register pcover BB, CC;
+{
+ register pcube p, last;
+
+ /* Create the block and cover set families */
+ BB->active_count = BB->count;
+ foreach_set(BB, last, p)
+ SET(p, ACTIVE);
+
+ if (CC != (pcover) NULL) {
+ CC->active_count = CC->count;
+ foreach_set(CC, last, p)
+ if (TESTP(p, COVERED) || TESTP(p, PRIME))
+ CC->active_count--, RESET(p, ACTIVE);
+ else
+ SET(p, ACTIVE);
+ }
+}
+
+/*
+ select_feasible -- Determine if there are cubes which can be covered,
+ and if so, raise those parts necessary to cover as many as possible.
+
+ We really don't check to maximize the number that can be covered;
+ instead, we check, for each fcc, how many other fcc remain fcc
+ after expanding to cover the fcc. (Essentially one-level lookahead).
+*/
+
+void select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered)
+pcover BB, CC;
+pcube RAISE, FREESET, SUPER_CUBE;
+int *num_covered;
+{
+ register pcube p, last, bestfeas, *feas;
+ register int i, j;
+ pcube *feas_new_lower;
+ int bestcount, bestsize, count, size, numfeas, lastfeas;
+ pcover new_lower;
+
+ /* Start out with all cubes covered by the over-expanded cube as
+ * the "possibly" feasibly-covered cubes (pfcc)
+ */
+ feas = ALLOC(pcube, CC->active_count);
+ numfeas = 0;
+ foreach_active_set(CC, last, p)
+ feas[numfeas++] = p;
+
+ /* Setup extra cubes to record parts forced low after a covering */
+ feas_new_lower = ALLOC(pcube, CC->active_count);
+ new_lower = new_cover(numfeas);
+ for(i = 0; i < numfeas; i++)
+ feas_new_lower[i] = GETSET(new_lower, i);
+
+
+loop:
+ /* Find the essentially raised parts -- this might cover some cubes
+ for us, without having to find out if they are fcc or not
+ */
+ essen_raising(BB, RAISE, FREESET);
+
+ /* Now check all "possibly" feasibly covered cubes to check feasibility */
+ lastfeas = numfeas;
+ numfeas = 0;
+ for(i = 0; i < lastfeas; i++) {
+ p = feas[i];
+
+ /* Check active because essen_parts might have removed it */
+ if (TESTP(p, ACTIVE)) {
+
+ /* See if the cube is already covered by RAISE --
+ * this can happen because of essen_raising() or because of
+ * the previous "loop"
+ */
+ if (setp_implies(p, RAISE)) {
+ (*num_covered) += 1;
+ (void) set_or(SUPER_CUBE, SUPER_CUBE, p);
+ CC->active_count--;
+ RESET(p, ACTIVE);
+ SET(p, COVERED);
+ /* otherwise, test if it is feasibly covered */
+ } else if (feasibly_covered(BB,p,RAISE,feas_new_lower[numfeas])) {
+ feas[numfeas] = p; /* save the fcc */
+ numfeas++;
+ }
+ }
+ }
+ if (debug & EXPAND1)
+ printf("SELECT_FEASIBLE: started with %d pfcc, ended with %d fcc\n",
+ lastfeas, numfeas);
+
+ /* Exit here if there are no feasibly covered cubes */
+ if (numfeas == 0) {
+ FREE(feas);
+ FREE(feas_new_lower);
+ free_cover(new_lower);
+ return;
+ }
+
+ /* Now find which is the best feasibly covered cube */
+ bestcount = 0;
+ bestsize = 9999;
+ for(i = 0; i < numfeas; i++) {
+ size = set_dist(feas[i], FREESET); /* # of newly raised parts */
+ count = 0; /* # of other cubes which remain fcc after raising */
+
+#define NEW
+#ifdef NEW
+ for(j = 0; j < numfeas; j++)
+ if (setp_disjoint(feas_new_lower[i], feas[j]))
+ count++;
+#else
+ for(j = 0; j < numfeas; j++)
+ if (setp_implies(feas[j], feas[i]))
+ count++;
+#endif
+ if (count > bestcount) {
+ bestcount = count;
+ bestfeas = feas[i];
+ bestsize = size;
+ } else if (count == bestcount && size < bestsize) {
+ bestfeas = feas[i];
+ bestsize = size;
+ }
+ }
+
+ /* Add the necessary parts to the raising set */
+ (void) set_or(RAISE, RAISE, bestfeas);
+ (void) set_diff(FREESET, FREESET, RAISE);
+ if (debug & EXPAND1)
+ printf("FEASIBLE: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+ essen_parts(BB, CC, RAISE, FREESET);
+ goto loop;
+/* NOTREACHED */
+}
+
+/*
+ feasibly_covered -- determine if the cube c is feasibly covered
+ (i.e., if it is possible to raise all of the necessary variables
+ while still insuring orthogonality with R). Also, if c is feasibly
+ covered, then compute the new set of parts which are forced into
+ the lowering set.
+*/
+
+bool feasibly_covered(BB, c, RAISE, new_lower)
+pcover BB;
+pcube c, RAISE, new_lower;
+{
+ register pcube p, r = set_or(cube.temp[0], RAISE, c);
+ int dist;
+ pcube lastp;
+
+ set_copy(new_lower, cube.emptyset);
+ foreach_active_set(BB, lastp, p) {
+#ifdef NO_INLINE
+ if ((dist = cdist01(p, r)) > 1) goto exit_if;
+#else
+ {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1)
+{x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto
+exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if(x=~(x|x>>1)&DISJOINT)if(dist==1||(
+dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube
+mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[
+var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[
+w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}}
+#endif
+ if (dist == 0)
+ return FALSE;
+ else
+ (void) force_lower(new_lower, p, r);
+ exit_if: ;
+ }
+ return TRUE;
+}
+
+/*
+ mincov -- transform the problem of expanding a cube to a maximally-
+ large prime implicant into the problem of selecting a minimum
+ cardinality cover over a family of sets.
+
+ When we get to this point, we must unravel the remaining off-set.
+ This may be painful.
+*/
+
+void mincov(BB, RAISE, FREESET)
+pcover BB;
+pcube RAISE, FREESET;
+{
+ int expansion, nset, var, dist;
+ pset_family B;
+ register pcube xraise=cube.temp[0], xlower, p, last, plower;
+
+#ifdef RANDOM_MINCOV
+#if defined(_POSIX_SOURCE) || defined(__SVR4)
+ dist = rand() % set_ord(FREESET);
+#else
+ dist = random() % set_ord(FREESET);
+#endif
+ for(var = 0; var < cube.size && dist >= 0; var++) {
+ if (is_in_set(FREESET, var)) {
+ dist--;
+ }
+ }
+
+ set_insert(RAISE, var);
+ set_remove(FREESET, var);
+ (void) essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET);
+#else
+
+ /* Create B which are those cubes which we must avoid intersecting */
+ B = new_cover(BB->active_count);
+ foreach_active_set(BB, last, p) {
+ plower = set_copy(GETSET(B, B->count++), cube.emptyset);
+ (void) force_lower(plower, p, RAISE);
+ }
+
+ /* Determine how many sets it will blow up into after the unravel */
+ nset = 0;
+ foreach_set(B, last, p) {
+ expansion = 1;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ if ((dist=set_dist(p, cube.var_mask[var])) > 1) {
+ expansion *= dist;
+ if (expansion > 500) goto heuristic_mincov;
+ }
+ }
+ nset += expansion;
+ if (nset > 500) goto heuristic_mincov;
+ }
+
+ B = unravel(B, cube.num_binary_vars);
+ xlower = do_sm_minimum_cover(B);
+
+ /* Add any remaining free parts to the raising set */
+ (void) set_or(RAISE, RAISE, set_diff(xraise, FREESET, xlower));
+ (void) set_copy(FREESET, cube.emptyset); /* free set is empty */
+ BB->active_count = 0; /* BB satisfied */
+ if (debug & EXPAND1) {
+ printf("MINCOV: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+ }
+ sf_free(B);
+ set_free(xlower);
+ return;
+
+heuristic_mincov:
+ sf_free(B);
+ /* most_frequent will pick first free part */
+ set_insert(RAISE, most_frequent(/*CC*/ (pcover) NULL, FREESET));
+ (void) set_diff(FREESET, FREESET, RAISE);
+ essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET);
+ return;
+#endif
+}
+
+/*
+ find_all_primes -- find all of the primes which cover the
+ currently reduced BB
+*/
+pcover find_all_primes(BB, RAISE, FREESET)
+pcover BB;
+register pcube RAISE, FREESET;
+{
+ register pset last, p, plower;
+ pset_family B, B1;
+
+ if (BB->active_count == 0) {
+ B1 = new_cover(1);
+ p = GETSET(B1, B1->count++);
+ (void) set_copy(p, RAISE);
+ SET(p, PRIME);
+ } else {
+ B = new_cover(BB->active_count);
+ foreach_active_set(BB, last, p) {
+ plower = set_copy(GETSET(B, B->count++), cube.emptyset);
+ (void) force_lower(plower, p, RAISE);
+ }
+ B = sf_rev_contain(unravel(B, cube.num_binary_vars));
+ B1 = exact_minimum_cover(B);
+ foreach_set(B1, last, p) {
+ INLINEset_diff(p, FREESET, p);
+ INLINEset_or(p, p, RAISE);
+ SET(p, PRIME);
+ }
+ free_cover(B);
+ }
+ return B1;
+}
+
+/*
+ all_primes -- foreach cube in F, generate all of the primes
+ which cover the cube.
+*/
+
+pcover all_primes(F, R)
+pcover F, R;
+{
+ register pcube last, p, RAISE, FREESET;
+ pcover Fall_primes, B1;
+
+ FREESET = new_cube();
+ RAISE = new_cube();
+ Fall_primes = new_cover(F->count);
+
+ foreach_set(F, last, p) {
+ if (TESTP(p, PRIME)) {
+ Fall_primes = sf_addset(Fall_primes, p);
+ } else {
+ /* Setup for call to essential parts */
+ (void) set_copy(RAISE, p);
+ (void) set_diff(FREESET, cube.fullset, RAISE);
+ setup_BB_CC(R, /* CC */ (pcover) NULL);
+ essen_parts(R, /* CC */ (pcover) NULL, RAISE, FREESET);
+
+ /* Find all of the primes, and add them to the prime set */
+ B1 = find_all_primes(R, RAISE, FREESET);
+ Fall_primes = sf_append(Fall_primes, B1);
+ }
+ }
+
+ set_free(RAISE);
+ set_free(FREESET);
+ return Fall_primes;
+}
diff --git a/src/misc/espresso/gasp.c b/src/misc/espresso/gasp.c
new file mode 100644
index 00000000..aa3254d3
--- /dev/null
+++ b/src/misc/espresso/gasp.c
@@ -0,0 +1,228 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: gasp.c
+
+ The "last_gasp" heuristic computes the reduction of each cube in
+ the cover (without replacement) and then performs an expansion of
+ these cubes. The cubes which expand to cover some other cube are
+ added to the original cover and irredundant finds a minimal subset.
+
+ If one of the reduced cubes expands to cover some other reduced
+ cube, then the new prime thus generated is a candidate for reducing
+ the size of the cover.
+
+ super_gasp is a variation on this strategy which extracts a minimal
+ subset from the set of all prime implicants which cover all
+ maximally reduced cubes.
+*/
+
+#include "espresso.h"
+
+
+/*
+ * reduce_gasp -- compute the maximal reduction of each cube of F
+ *
+ * If a cube does not reduce, it remains prime; otherwise, it is marked
+ * as nonprime. If the cube is redundant (should NEVER happen here) we
+ * just crap out ...
+ *
+ * A cover with all of the cubes of F is returned. Those that did
+ * reduce are marked "NONPRIME"; those that reduced are marked "PRIME".
+ * The cubes are in the same order as in F.
+ */
+static pcover reduce_gasp(F, D)
+pcover F, D;
+{
+ pcube p, last, cunder, *FD;
+ pcover G;
+
+ G = new_cover(F->count);
+ FD = cube2list(F, D);
+
+ /* Reduce cubes of F without replacement */
+ foreach_set(F, last, p) {
+ cunder = reduce_cube(FD, p);
+ if (setp_empty(cunder)) {
+ fatal("empty reduction in reduce_gasp, shouldn't happen");
+ } else if (setp_equal(cunder, p)) {
+ SET(cunder, PRIME); /* just to make sure */
+ G = sf_addset(G, p); /* it did not reduce ... */
+ } else {
+ RESET(cunder, PRIME); /* it reduced ... */
+ G = sf_addset(G, cunder);
+ }
+ if (debug & GASP) {
+ printf("REDUCE_GASP: %s reduced to %s\n", pc1(p), pc2(cunder));
+ }
+ free_cube(cunder);
+ }
+
+ free_cubelist(FD);
+ return G;
+}
+
+/*
+ * expand_gasp -- expand each nonprime cube of F into a prime implicant
+ *
+ * The gasp strategy differs in that only those cubes which expand to
+ * cover some other cube are saved; also, all cubes are expanded
+ * regardless of whether they become covered or not.
+ */
+
+pcover expand_gasp(F, D, R, Foriginal)
+INOUT pcover F;
+IN pcover D;
+IN pcover R;
+IN pcover Foriginal;
+{
+ int c1index;
+ pcover G;
+
+ /* Try to expand each nonprime and noncovered cube */
+ G = new_cover(10);
+ for(c1index = 0; c1index < F->count; c1index++) {
+ expand1_gasp(F, D, R, Foriginal, c1index, &G);
+ }
+ G = sf_dupl(G);
+ G = expand(G, R, /*nonsparse*/ FALSE); /* Make them prime ! */
+ return G;
+}
+
+
+
+/*
+ * expand1 -- Expand a single cube against the OFF-set, using the gasp strategy
+ */
+void expand1_gasp(F, D, R, Foriginal, c1index, G)
+pcover F; /* reduced cubes of ON-set */
+pcover D; /* DC-set */
+pcover R; /* OFF-set */
+pcover Foriginal; /* ON-set before reduction (same order as F) */
+int c1index; /* which index of F (or Freduced) to be checked */
+pcover *G;
+{
+ register int c2index;
+ register pcube p, last, c2under;
+ pcube RAISE, FREESET, temp, *FD, c2essential;
+ pcover F1;
+
+ if (debug & EXPAND1) {
+ printf("\nEXPAND1_GASP: \t%s\n", pc1(GETSET(F, c1index)));
+ }
+
+ RAISE = new_cube();
+ FREESET = new_cube();
+ temp = new_cube();
+
+ /* Initialize the OFF-set */
+ R->active_count = R->count;
+ foreach_set(R, last, p) {
+ SET(p, ACTIVE);
+ }
+ /* Initialize the reduced ON-set, all nonprime cubes become active */
+ F->active_count = F->count;
+ foreachi_set(F, c2index, c2under) {
+ if (c1index == c2index || TESTP(c2under, PRIME)) {
+ F->active_count--;
+ RESET(c2under, ACTIVE);
+ } else {
+ SET(c2under, ACTIVE);
+ }
+ }
+
+ /* Initialize the raising and unassigned sets */
+ (void) set_copy(RAISE, GETSET(F, c1index));
+ (void) set_diff(FREESET, cube.fullset, RAISE);
+
+ /* Determine parts which must be lowered */
+ essen_parts(R, F, RAISE, FREESET);
+
+ /* Determine parts which can always be raised */
+ essen_raising(R, RAISE, FREESET);
+
+ /* See which, if any, of the reduced cubes we can cover */
+ foreachi_set(F, c2index, c2under) {
+ if (TESTP(c2under, ACTIVE)) {
+ /* See if this cube can be covered by an expansion */
+ if (setp_implies(c2under, RAISE) ||
+ feasibly_covered(R, c2under, RAISE, temp)) {
+
+ /* See if c1under can expanded to cover c2 reduced against
+ * (F - c1) u c1under; if so, c2 can definitely be removed !
+ */
+
+ /* Copy F and replace c1 with c1under */
+ F1 = sf_save(Foriginal);
+ (void) set_copy(GETSET(F1, c1index), GETSET(F, c1index));
+
+ /* Reduce c2 against ((F - c1) u c1under) */
+ FD = cube2list(F1, D);
+ c2essential = reduce_cube(FD, GETSET(F1, c2index));
+ free_cubelist(FD);
+ sf_free(F1);
+
+ /* See if c2essential is covered by an expansion of c1under */
+ if (feasibly_covered(R, c2essential, RAISE, temp)) {
+ (void) set_or(temp, RAISE, c2essential);
+ RESET(temp, PRIME); /* cube not prime */
+ *G = sf_addset(*G, temp);
+ }
+ set_free(c2essential);
+ }
+ }
+ }
+
+ free_cube(RAISE);
+ free_cube(FREESET);
+ free_cube(temp);
+}
+
+/* irred_gasp -- Add new primes to F and find an irredundant subset */
+pcover irred_gasp(F, D, G)
+pcover F, D, G; /* G is disposed of */
+{
+ if (G->count != 0)
+ F = irredundant(sf_append(F, G), D);
+ else
+ free_cover(G);
+ return F;
+}
+
+
+/* last_gasp */
+pcover last_gasp(F, D, R, cost)
+pcover F, D, R;
+cost_t *cost;
+{
+ pcover G, G1;
+
+ EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
+ EXECUTE(G1 = expand_gasp(G, D, R, F), GEXPAND_TIME, G1, *cost);
+ free_cover(G);
+ EXECUTE(F = irred_gasp(F, D, G1), GIRRED_TIME, F, *cost);
+ return F;
+}
+
+
+/* super_gasp */
+pcover super_gasp(F, D, R, cost)
+pcover F, D, R;
+cost_t *cost;
+{
+ pcover G, G1;
+
+ EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
+ EXECUTE(G1 = all_primes(G, R), GEXPAND_TIME, G1, *cost);
+ free_cover(G);
+ EXEC(G = sf_dupl(sf_append(F, G1)), "NEWPRIMES", G);
+ EXECUTE(F = irredundant(G, D), IRRED_TIME, F, *cost);
+ return F;
+}
diff --git a/src/misc/espresso/gimpel.c b/src/misc/espresso/gimpel.c
new file mode 100644
index 00000000..648bb64a
--- /dev/null
+++ b/src/misc/espresso/gimpel.c
@@ -0,0 +1,106 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+
+/*
+ * check for:
+ *
+ * c1 c2 rest
+ * -- -- ---
+ * 1 1 0 0 0 0 <-- primary row
+ * 1 0 S1 <-- secondary row
+ * 0 1 T1
+ * 0 1 T2
+ * 0 1 Tn
+ * 0 0 R
+ */
+
+int
+gimpel_reduce(A, select, weight, lb, bound, depth, stats, best)
+sm_matrix *A;
+solution_t *select;
+int *weight;
+int lb;
+int bound;
+int depth;
+stats_t *stats;
+solution_t **best;
+{
+ register sm_row *prow, *save_sec;
+ register sm_col *c1, *c2;
+ register sm_element *p, *p1;
+ int c1_col_num, c2_col_num, primary_row_num, secondary_row_num;
+ int reduce_it;
+
+ reduce_it = 0;
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ if (prow->length == 2) {
+ c1 = sm_get_col(A, prow->first_col->col_num);
+ c2 = sm_get_col(A, prow->last_col->col_num);
+ if (c1->length == 2) {
+ reduce_it = 1;
+ } else if (c2->length == 2) {
+ c1 = sm_get_col(A, prow->last_col->col_num);
+ c2 = sm_get_col(A, prow->first_col->col_num);
+ reduce_it = 1;
+ }
+ if (reduce_it) {
+ primary_row_num = prow->row_num;
+ secondary_row_num = c1->first_row->row_num;
+ if (secondary_row_num == primary_row_num) {
+ secondary_row_num = c1->last_row->row_num;
+ }
+ break;
+ }
+ }
+ }
+
+ if (reduce_it) {
+ c1_col_num = c1->col_num;
+ c2_col_num = c2->col_num;
+ save_sec = sm_row_dup(sm_get_row(A, secondary_row_num));
+ sm_row_remove(save_sec, c1_col_num);
+
+ for(p = c2->first_row; p != 0; p = p->next_row) {
+ if (p->row_num != primary_row_num) {
+ /* merge rows S1 and T */
+ for(p1 = save_sec->first_col; p1 != 0; p1 = p1->next_col) {
+ (void) sm_insert(A, p->row_num, p1->col_num);
+ }
+ }
+ }
+
+ sm_delcol(A, c1_col_num);
+ sm_delcol(A, c2_col_num);
+ sm_delrow(A, primary_row_num);
+ sm_delrow(A, secondary_row_num);
+
+ stats->gimpel_count++;
+ stats->gimpel++;
+ *best = sm_mincov(A, select, weight, lb-1, bound-1, depth, stats);
+ stats->gimpel--;
+
+ if (*best != NIL(solution_t)) {
+ /* is secondary row covered ? */
+ if (sm_row_intersects(save_sec, (*best)->row)) {
+ /* yes, actually select c2 */
+ solution_add(*best, weight, c2_col_num);
+ } else {
+ solution_add(*best, weight, c1_col_num);
+ }
+ }
+
+ sm_row_free(save_sec);
+ return 1;
+ } else {
+ return 0;
+ }
+}
diff --git a/src/misc/espresso/globals.c b/src/misc/espresso/globals.c
new file mode 100644
index 00000000..d04771e9
--- /dev/null
+++ b/src/misc/espresso/globals.c
@@ -0,0 +1,76 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+/*
+ * Global Variable Declarations
+ */
+
+unsigned int debug; /* debug parameter */
+bool verbose_debug; /* -v: whether to print a lot */
+char *total_name[TIME_COUNT]; /* basic function names */
+long total_time[TIME_COUNT]; /* time spent in basic fcts */
+int total_calls[TIME_COUNT]; /* # calls to each fct */
+
+bool echo_comments; /* turned off by -eat option */
+bool echo_unknown_commands; /* always true ?? */
+bool force_irredundant; /* -nirr command line option */
+bool skip_make_sparse;
+bool kiss; /* -kiss command line option */
+bool pos; /* -pos command line option */
+bool print_solution; /* -x command line option */
+bool recompute_onset; /* -onset command line option */
+bool remove_essential; /* -ness command line option */
+bool single_expand; /* -fast command line option */
+bool summary; /* -s command line option */
+bool trace; /* -t command line option */
+bool unwrap_onset; /* -nunwrap command line option */
+bool use_random_order; /* -random command line option */
+bool use_super_gasp; /* -strong command line option */
+char *filename; /* filename PLA was read from */
+
+struct pla_types_struct pla_types[] = {
+ "-f", F_type,
+ "-r", R_type,
+ "-d", D_type,
+ "-fd", FD_type,
+ "-fr", FR_type,
+ "-dr", DR_type,
+ "-fdr", FDR_type,
+ "-fc", F_type | CONSTRAINTS_type,
+ "-rc", R_type | CONSTRAINTS_type,
+ "-dc", D_type | CONSTRAINTS_type,
+ "-fdc", FD_type | CONSTRAINTS_type,
+ "-frc", FR_type | CONSTRAINTS_type,
+ "-drc", DR_type | CONSTRAINTS_type,
+ "-fdrc", FDR_type | CONSTRAINTS_type,
+ "-pleasure", PLEASURE_type,
+ "-eqn", EQNTOTT_type,
+ "-eqntott", EQNTOTT_type,
+ "-kiss", KISS_type,
+ "-cons", CONSTRAINTS_type,
+ "-scons", SYMBOLIC_CONSTRAINTS_type,
+ 0, 0
+};
+
+
+struct cube_struct cube, temp_cube_save;
+struct cdata_struct cdata, temp_cdata_save;
+
+int bit_count[256] = {
+ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
diff --git a/src/misc/espresso/hack.c b/src/misc/espresso/hack.c
new file mode 100644
index 00000000..927f5341
--- /dev/null
+++ b/src/misc/espresso/hack.c
@@ -0,0 +1,641 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+map_dcset(PLA)
+pPLA PLA;
+{
+ int var, i;
+ pcover Tplus, Tminus, Tplusbar, Tminusbar;
+ pcover newf, term1, term2, dcset, dcsetbar;
+ pcube cplus, cminus, last, p;
+
+ if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char))
+ return;
+
+ /* try to find a binary variable named "DONT_CARE" */
+ var = -1;
+ for(i = 0; i < cube.num_binary_vars * 2; i++) {
+ if (strncmp(PLA->label[i], "DONT_CARE", 9) == 0 ||
+ strncmp(PLA->label[i], "DONTCARE", 8) == 0 ||
+ strncmp(PLA->label[i], "dont_care", 9) == 0 ||
+ strncmp(PLA->label[i], "dontcare", 8) == 0) {
+ var = i/2;
+ break;
+ }
+ }
+ if (var == -1) {
+ return;
+ }
+
+ /* form the cofactor cubes for the don't-care variable */
+ cplus = set_save(cube.fullset);
+ cminus = set_save(cube.fullset);
+ set_remove(cplus, var*2);
+ set_remove(cminus, var*2 + 1);
+
+ /* form the don't-care set */
+ EXEC(simp_comp(cofactor(cube1list(PLA->F), cplus), &Tplus, &Tplusbar),
+ "simpcomp+", Tplus);
+ EXEC(simp_comp(cofactor(cube1list(PLA->F), cminus), &Tminus, &Tminusbar),
+ "simpcomp-", Tminus);
+ EXEC(term1 = cv_intersect(Tplus, Tminusbar), "term1 ", term1);
+ EXEC(term2 = cv_intersect(Tminus, Tplusbar), "term2 ", term2);
+ EXEC(dcset = sf_union(term1, term2), "union ", dcset);
+ EXEC(simp_comp(cube1list(dcset), &PLA->D, &dcsetbar), "simplify", PLA->D);
+ EXEC(newf = cv_intersect(PLA->F, dcsetbar), "separate ", PLA->F);
+ free_cover(PLA->F);
+ PLA->F = newf;
+ free_cover(Tplus);
+ free_cover(Tminus);
+ free_cover(Tplusbar);
+ free_cover(Tminusbar);
+ free_cover(dcsetbar);
+
+ /* remove any cubes dependent on the DONT_CARE variable */
+ (void) sf_active(PLA->F);
+ foreach_set(PLA->F, last, p) {
+ if (! is_in_set(p, var*2) || ! is_in_set(p, var*2+1)) {
+ RESET(p, ACTIVE);
+ }
+ }
+ PLA->F = sf_inactive(PLA->F);
+
+ /* resize the cube and delete the don't-care variable */
+ setdown_cube();
+ for(i = 2*var+2; i < cube.size; i++) {
+ PLA->label[i-2] = PLA->label[i];
+ }
+ for(i = var+1; i < cube.num_vars; i++) {
+ cube.part_size[i-1] = cube.part_size[i];
+ }
+ cube.num_binary_vars--;
+ cube.num_vars--;
+ cube_setup();
+ PLA->F = sf_delc(PLA->F, 2*var, 2*var+1);
+ PLA->D = sf_delc(PLA->D, 2*var, 2*var+1);
+}
+
+map_output_symbolic(PLA)
+pPLA PLA;
+{
+ pset_family newF, newD;
+ pset compress;
+ symbolic_t *p1;
+ symbolic_list_t *p2;
+ int i, bit, tot_size, base, old_size;
+
+ /* Remove the DC-set from the ON-set (is this necessary ??) */
+ if (PLA->D->count > 0) {
+ sf_free(PLA->F);
+ PLA->F = complement(cube2list(PLA->D, PLA->R));
+ }
+
+ /* tot_size = width added for all symbolic variables */
+ tot_size = 0;
+ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ if (p2->pos<0 || p2->pos>=cube.part_size[cube.output]) {
+ fatal("symbolic-output index out of range");
+/* } else if (p2->variable != cube.output) {
+ fatal("symbolic-output label must be an output");*/
+ }
+ }
+ tot_size += 1 << p1->symbolic_list_length;
+ }
+
+ /* adjust the indices to skip over new outputs */
+ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ p2->pos += tot_size;
+ }
+ }
+
+ /* resize the cube structure -- add enough for the one-hot outputs */
+ old_size = cube.size;
+ cube.part_size[cube.output] += tot_size;
+ setdown_cube();
+ cube_setup();
+
+ /* insert space in the output part for the one-hot output */
+ base = cube.first_part[cube.output];
+ PLA->F = sf_addcol(PLA->F, base, tot_size);
+ PLA->D = sf_addcol(PLA->D, base, tot_size);
+ PLA->R = sf_addcol(PLA->R, base, tot_size);
+
+ /* do the real work */
+ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ newF = new_cover(100);
+ newD = new_cover(100);
+ find_inputs(NIL(set_family_t), PLA, p1->symbolic_list, base, 0,
+ &newF, &newD);
+/*
+ * Not sure what this means
+ find_dc_inputs(PLA, p1->symbolic_list,
+ base, 1 << p1->symbolic_list_length, &newF, &newD);
+ */
+ free_cover(PLA->F);
+ PLA->F = newF;
+/*
+ * retain OLD DC-set -- but we've lost the don't-care arc information
+ * (it defaults to branch to the zero state)
+ free_cover(PLA->D);
+ PLA->D = newD;
+ */
+ free_cover(newD);
+ base += 1 << p1->symbolic_list_length;
+ }
+
+ /* delete the old outputs, and resize the cube */
+ compress = set_full(newF->sf_size);
+ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ bit = cube.first_part[cube.output] + p2->pos;
+ set_remove(compress, bit);
+ }
+ }
+ cube.part_size[cube.output] -= newF->sf_size - set_ord(compress);
+ setdown_cube();
+ cube_setup();
+ PLA->F = sf_compress(PLA->F, compress);
+ PLA->D = sf_compress(PLA->D, compress);
+ if (cube.size != PLA->F->sf_size) fatal("error");
+
+ /* Quick minimization */
+ PLA->F = sf_contain(PLA->F);
+ PLA->D = sf_contain(PLA->D);
+ for(i = 0; i < cube.num_vars; i++) {
+ PLA->F = d1merge(PLA->F, i);
+ PLA->D = d1merge(PLA->D, i);
+ }
+ PLA->F = sf_contain(PLA->F);
+ PLA->D = sf_contain(PLA->D);
+
+ free_cover(PLA->R);
+ PLA->R = new_cover(0);
+
+ symbolic_hack_labels(PLA, PLA->symbolic_output,
+ compress, cube.size, old_size, tot_size);
+ set_free(compress);
+}
+
+
+find_inputs(A, PLA, list, base, value, newF, newD)
+pcover A;
+pPLA PLA;
+symbolic_list_t *list;
+int base, value;
+pcover *newF, *newD;
+{
+ pcover S, S1;
+ register pset last, p;
+
+ /*
+ * A represents th 'input' values for which the outputs assume
+ * the integer value 'value
+ */
+ if (list == NIL(symbolic_list_t)) {
+ /*
+ * Simulate these inputs against the on-set; then, insert into the
+ * new on-set a 1 in the proper position
+ */
+ S = cv_intersect(A, PLA->F);
+ foreach_set(S, last, p) {
+ set_insert(p, base + value);
+ }
+ *newF = sf_append(*newF, S);
+
+ /*
+ * 'simulate' these inputs against the don't-care set
+ S = cv_intersect(A, PLA->D);
+ *newD = sf_append(*newD, S);
+ */
+
+ } else {
+ /* intersect and recur with the OFF-set */
+ S = cof_output(PLA->R, cube.first_part[cube.output] + list->pos);
+ if (A != NIL(set_family_t)) {
+ S1 = cv_intersect(A, S);
+ free_cover(S);
+ S = S1;
+ }
+ find_inputs(S, PLA, list->next, base, value*2, newF, newD);
+ free_cover(S);
+
+ /* intersect and recur with the ON-set */
+ S = cof_output(PLA->F, cube.first_part[cube.output] + list->pos);
+ if (A != NIL(set_family_t)) {
+ S1 = cv_intersect(A, S);
+ free_cover(S);
+ S = S1;
+ }
+ find_inputs(S, PLA, list->next, base, value*2 + 1, newF, newD);
+ free_cover(S);
+ }
+}
+
+
+#if 0
+find_dc_inputs(PLA, list, base, maxval, newF, newD)
+pPLA PLA;
+symbolic_list_t *list;
+int base, maxval;
+pcover *newF, *newD;
+{
+ pcover A, S, S1;
+ symbolic_list_t *p2;
+ register pset p, last;
+ register int i;
+
+ /* painfully find the points for which the symbolic output is dc */
+ A = NIL(set_family_t);
+ for(p2=list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ S = cof_output(PLA->D, cube.first_part[cube.output] + p2->pos);
+ if (A == NIL(set_family_t)) {
+ A = S;
+ } else {
+ S1 = cv_intersect(A, S);
+ free_cover(S);
+ free_cover(A);
+ A = S1;
+ }
+ }
+
+ S = cv_intersect(A, PLA->F);
+ *newF = sf_append(*newF, S);
+
+ S = cv_intersect(A, PLA->D);
+ foreach_set(S, last, p) {
+ for(i = base; i < base + maxval; i++) {
+ set_insert(p, i);
+ }
+ }
+ *newD = sf_append(*newD, S);
+ free_cover(A);
+}
+#endif
+
+map_symbolic(PLA)
+pPLA PLA;
+{
+ symbolic_t *p1;
+ symbolic_list_t *p2;
+ int var, base, num_vars, num_binary_vars, *new_part_size;
+ int new_size, size_added, num_deleted_vars, num_added_vars, newvar;
+ pset compress;
+
+ /* Verify legal values are in the symbolic lists */
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ if (p2->variable < 0 || p2->variable >= cube.num_binary_vars) {
+ fatal(".symbolic requires binary variables");
+ }
+ }
+ }
+
+ /*
+ * size_added = width added for all symbolic variables
+ * num_deleted_vars = # binary variables to be deleted
+ * num_added_vars = # new mv variables
+ * compress = a cube which will be used to compress the set families
+ */
+ size_added = 0;
+ num_added_vars = 0;
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ size_added += 1 << p1->symbolic_list_length;
+ num_added_vars++;
+ }
+ compress = set_full(PLA->F->sf_size + size_added);
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ set_remove(compress, p2->variable*2);
+ set_remove(compress, p2->variable*2+1);
+ }
+ }
+ num_deleted_vars = ((PLA->F->sf_size + size_added) - set_ord(compress))/2;
+
+ /* compute the new cube constants */
+ num_vars = cube.num_vars - num_deleted_vars + num_added_vars;
+ num_binary_vars = cube.num_binary_vars - num_deleted_vars;
+ new_size = cube.size - num_deleted_vars*2 + size_added;
+ new_part_size = ALLOC(int, num_vars);
+ new_part_size[num_vars-1] = cube.part_size[cube.num_vars-1];
+ for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) {
+ new_part_size[var-num_deleted_vars] = cube.part_size[var];
+ }
+
+ /* re-size the covers, opening room for the new mv variables */
+ base = cube.first_part[cube.output];
+ PLA->F = sf_addcol(PLA->F, base, size_added);
+ PLA->D = sf_addcol(PLA->D, base, size_added);
+ PLA->R = sf_addcol(PLA->R, base, size_added);
+
+ /* compute the values for the new mv variables */
+ newvar = (cube.num_vars - 1) - num_deleted_vars;
+ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ PLA->F = map_symbolic_cover(PLA->F, p1->symbolic_list, base);
+ PLA->D = map_symbolic_cover(PLA->D, p1->symbolic_list, base);
+ PLA->R = map_symbolic_cover(PLA->R, p1->symbolic_list, base);
+ base += 1 << p1->symbolic_list_length;
+ new_part_size[newvar++] = 1 << p1->symbolic_list_length;
+ }
+
+ /* delete the binary variables which disappear */
+ PLA->F = sf_compress(PLA->F, compress);
+ PLA->D = sf_compress(PLA->D, compress);
+ PLA->R = sf_compress(PLA->R, compress);
+
+ symbolic_hack_labels(PLA, PLA->symbolic, compress,
+ new_size, cube.size, size_added);
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_vars = num_vars;
+ cube.num_binary_vars = num_binary_vars;
+ cube.part_size = new_part_size;
+ cube_setup();
+ set_free(compress);
+}
+
+
+pcover map_symbolic_cover(T, list, base)
+pcover T;
+symbolic_list_t *list;
+int base;
+{
+ pset last, p;
+ foreach_set(T, last, p) {
+ form_bitvector(p, base, 0, list);
+ }
+ return T;
+}
+
+
+form_bitvector(p, base, value, list)
+pset p; /* old cube, looking at binary variables */
+int base; /* where in mv cube the new variable starts */
+int value; /* current value for this recursion */
+symbolic_list_t *list; /* current place in the symbolic list */
+{
+ if (list == NIL(symbolic_list_t)) {
+ set_insert(p, base + value);
+ } else {
+ switch(GETINPUT(p, list->variable)) {
+ case ZERO:
+ form_bitvector(p, base, value*2, list->next);
+ break;
+ case ONE:
+ form_bitvector(p, base, value*2+1, list->next);
+ break;
+ case TWO:
+ form_bitvector(p, base, value*2, list->next);
+ form_bitvector(p, base, value*2+1, list->next);
+ break;
+ default:
+ fatal("bad cube in form_bitvector");
+ }
+ }
+}
+
+
+symbolic_hack_labels(PLA, list, compress, new_size, old_size, size_added)
+pPLA PLA;
+symbolic_t *list;
+pset compress;
+int new_size, old_size, size_added;
+{
+ int i, base;
+ char **oldlabel;
+ symbolic_t *p1;
+ symbolic_label_t *p3;
+
+ /* hack with the labels */
+ if ((oldlabel = PLA->label) == NIL(char *))
+ return;
+ PLA->label = ALLOC(char *, new_size);
+ for(i = 0; i < new_size; i++) {
+ PLA->label[i] = NIL(char);
+ }
+
+ /* copy the binary variable labels and unchanged mv variable labels */
+ base = 0;
+ for(i = 0; i < cube.first_part[cube.output]; i++) {
+ if (is_in_set(compress, i)) {
+ PLA->label[base++] = oldlabel[i];
+ } else {
+ if (oldlabel[i] != NIL(char)) {
+ FREE(oldlabel[i]);
+ }
+ }
+ }
+
+ /* add the user-defined labels for the symbolic outputs */
+ for(p1 = list; p1 != NIL(symbolic_t); p1 = p1->next) {
+ p3 = p1->symbolic_label;
+ for(i = 0; i < (1 << p1->symbolic_list_length); i++) {
+ if (p3 == NIL(symbolic_label_t)) {
+ PLA->label[base+i] = ALLOC(char, 10);
+ (void) sprintf(PLA->label[base+i], "X%d", i);
+ } else {
+ PLA->label[base+i] = p3->label;
+ p3 = p3->next;
+ }
+ }
+ base += 1 << p1->symbolic_list_length;
+ }
+
+ /* copy the labels for the binary outputs which remain */
+ for(i = cube.first_part[cube.output]; i < old_size; i++) {
+ if (is_in_set(compress, i + size_added)) {
+ PLA->label[base++] = oldlabel[i];
+ } else {
+ if (oldlabel[i] != NIL(char)) {
+ FREE(oldlabel[i]);
+ }
+ }
+ }
+ FREE(oldlabel);
+}
+
+static pcover fsm_simplify(F)
+pcover F;
+{
+ pcover D, R;
+ D = new_cover(0);
+ R = complement(cube1list(F));
+ F = espresso(F, D, R);
+ free_cover(D);
+ free_cover(R);
+ return F;
+}
+
+
+disassemble_fsm(PLA, verbose_mode)
+pPLA PLA;
+int verbose_mode;
+{
+ int nin, nstates, nout;
+ int before, after, present_state, next_state, i, j;
+ pcube next_state_mask, present_state_mask, state_mask, p, p1, last;
+ pcover go_nowhere, F, tF;
+
+ /* We make the DISGUSTING assumption that the first 'n' outputs have
+ * been created by .symbolic-output, and represent a one-hot encoding
+ * of the next state. 'n' is the size of the second-to-last multiple-
+ * valued variable (i.e., before the outputs
+ */
+
+ if (cube.num_vars - cube.num_binary_vars != 2) {
+ (void) fprintf(stderr,
+ "use .symbolic and .symbolic-output to specify\n");
+ (void) fprintf(stderr,
+ "the present state and next state field information\n");
+ fatal("disassemble_pla: need two multiple-valued variables\n");
+ }
+
+ nin = cube.num_binary_vars;
+ nstates = cube.part_size[cube.num_binary_vars];
+ nout = cube.part_size[cube.num_vars - 1];
+ if (nout < nstates) {
+ (void) fprintf(stderr,
+ "use .symbolic and .symbolic-output to specify\n");
+ (void) fprintf(stderr,
+ "the present state and next state field information\n");
+ fatal("disassemble_pla: # outputs < # states\n");
+ }
+
+
+ present_state = cube.first_part[cube.num_binary_vars];
+ present_state_mask = new_cube();
+ for(i = 0; i < nstates; i++) {
+ set_insert(present_state_mask, i + present_state);
+ }
+
+ next_state = cube.first_part[cube.num_binary_vars+1];
+ next_state_mask = new_cube();
+ for(i = 0; i < nstates; i++) {
+ set_insert(next_state_mask, i + next_state);
+ }
+
+ state_mask = set_or(new_cube(), next_state_mask, present_state_mask);
+
+ F = new_cover(10);
+
+
+ /*
+ * check for arcs which go from ANY state to state #i
+ */
+ for(i = 0; i < nstates; i++) {
+ tF = new_cover(10);
+ foreach_set(PLA->F, last, p) {
+ if (setp_implies(present_state_mask, p)) { /* from any state ! */
+ if (is_in_set(p, next_state + i)) {
+ tF = sf_addset(tF, p);
+ }
+ }
+ }
+ before = tF->count;
+ if (before > 0) {
+ tF = fsm_simplify(tF);
+ /* don't allow the next state to disappear ... */
+ foreach_set(tF, last, p) {
+ set_insert(p, next_state + i);
+ }
+ after = tF->count;
+ F = sf_append(F, tF);
+ if (verbose_mode) {
+ printf("# state EVERY to %d, before=%d after=%d\n",
+ i, before, after);
+ }
+ }
+ }
+
+
+ /*
+ * some 'arcs' may NOT have a next state -- handle these
+ * we must unravel the present state part
+ */
+ go_nowhere = new_cover(10);
+ foreach_set(PLA->F, last, p) {
+ if (setp_disjoint(p, next_state_mask)) { /* no next state !! */
+ go_nowhere = sf_addset(go_nowhere, p);
+ }
+ }
+ before = go_nowhere->count;
+ go_nowhere = unravel_range(go_nowhere,
+ cube.num_binary_vars, cube.num_binary_vars);
+ after = go_nowhere->count;
+ F = sf_append(F, go_nowhere);
+ if (verbose_mode) {
+ printf("# state ANY to NOWHERE, before=%d after=%d\n", before, after);
+ }
+
+
+ /*
+ * minimize cover for all arcs from state #i to state #j
+ */
+ for(i = 0; i < nstates; i++) {
+ for(j = 0; j < nstates; j++) {
+ tF = new_cover(10);
+ foreach_set(PLA->F, last, p) {
+ /* not EVERY state */
+ if (! setp_implies(present_state_mask, p)) {
+ if (is_in_set(p, present_state + i)) {
+ if (is_in_set(p, next_state + j)) {
+ p1 = set_save(p);
+ set_diff(p1, p1, state_mask);
+ set_insert(p1, present_state + i);
+ set_insert(p1, next_state + j);
+ tF = sf_addset(tF, p1);
+ set_free(p1);
+ }
+ }
+ }
+ }
+ before = tF->count;
+ if (before > 0) {
+ tF = fsm_simplify(tF);
+ /* don't allow the next state to disappear ... */
+ foreach_set(tF, last, p) {
+ set_insert(p, next_state + j);
+ }
+ after = tF->count;
+ F = sf_append(F, tF);
+ if (verbose_mode) {
+ printf("# state %d to %d, before=%d after=%d\n",
+ i, j, before, after);
+ }
+ }
+ }
+ }
+
+
+ free_cube(state_mask);
+ free_cube(present_state_mask);
+ free_cube(next_state_mask);
+
+ free_cover(PLA->F);
+ PLA->F = F;
+ free_cover(PLA->D);
+ PLA->D = new_cover(0);
+
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_binary_vars = nin;
+ cube.num_vars = nin + 3;
+ cube.part_size = ALLOC(int, cube.num_vars);
+ cube.part_size[cube.num_binary_vars] = nstates;
+ cube.part_size[cube.num_binary_vars+1] = nstates;
+ cube.part_size[cube.num_binary_vars+2] = nout - nstates;
+ cube_setup();
+
+ foreach_set(PLA->F, last, p) {
+ kiss_print_cube(stdout, PLA, p, "~1");
+ }
+}
diff --git a/src/misc/espresso/indep.c b/src/misc/espresso/indep.c
new file mode 100644
index 00000000..10b363a0
--- /dev/null
+++ b/src/misc/espresso/indep.c
@@ -0,0 +1,134 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+static sm_matrix *build_intersection_matrix();
+
+
+#if 0
+/*
+ * verify that all rows in 'indep' are actually independent !
+ */
+static int
+verify_indep_set(A, indep)
+sm_matrix *A;
+sm_row *indep;
+{
+ register sm_row *prow, *prow1;
+ register sm_element *p, *p1;
+
+ for(p = indep->first_col; p != 0; p = p->next_col) {
+ prow = sm_get_row(A, p->col_num);
+ for(p1 = p->next_col; p1 != 0; p1 = p1->next_col) {
+ prow1 = sm_get_row(A, p1->col_num);
+ if (sm_row_intersects(prow, prow1)) {
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+#endif
+
+solution_t *
+sm_maximal_independent_set(A, weight)
+sm_matrix *A;
+int *weight;
+{
+ register sm_row *best_row, *prow;
+ register sm_element *p;
+ int least_weight;
+ sm_row *save;
+ sm_matrix *B;
+ solution_t *indep;
+
+ indep = solution_alloc();
+ B = build_intersection_matrix(A);
+
+ while (B->nrows > 0) {
+ /* Find the row which is disjoint from a maximum number of rows */
+ best_row = B->first_row;
+ for(prow = B->first_row->next_row; prow != 0; prow = prow->next_row) {
+ if (prow->length < best_row->length) {
+ best_row = prow;
+ }
+ }
+
+ /* Find which element in this row has least weight */
+ if (weight == NIL(int)) {
+ least_weight = 1;
+ } else {
+ prow = sm_get_row(A, best_row->row_num);
+ least_weight = weight[prow->first_col->col_num];
+ for(p = prow->first_col->next_col; p != 0; p = p->next_col) {
+ if (weight[p->col_num] < least_weight) {
+ least_weight = weight[p->col_num];
+ }
+ }
+ }
+ indep->cost += least_weight;
+ (void) sm_row_insert(indep->row, best_row->row_num);
+
+ /* Discard the rows which intersect this row */
+ save = sm_row_dup(best_row);
+ for(p = save->first_col; p != 0; p = p->next_col) {
+ sm_delrow(B, p->col_num);
+ sm_delcol(B, p->col_num);
+ }
+ sm_row_free(save);
+ }
+
+ sm_free(B);
+
+/*
+ if (! verify_indep_set(A, indep->row)) {
+ fail("sm_maximal_independent_set: row set is not independent");
+ }
+*/
+ return indep;
+}
+
+static sm_matrix *
+build_intersection_matrix(A)
+sm_matrix *A;
+{
+ register sm_row *prow, *prow1;
+ register sm_element *p, *p1;
+ register sm_col *pcol;
+ sm_matrix *B;
+
+ /* Build row-intersection matrix */
+ B = sm_alloc();
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+
+ /* Clear flags on all rows we can reach from row 'prow' */
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ pcol = sm_get_col(A, p->col_num);
+ for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) {
+ prow1 = sm_get_row(A, p1->row_num);
+ prow1->flag = 0;
+ }
+ }
+
+ /* Now record which rows can be reached */
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ pcol = sm_get_col(A, p->col_num);
+ for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) {
+ prow1 = sm_get_row(A, p1->row_num);
+ if (! prow1->flag) {
+ prow1->flag = 1;
+ (void) sm_insert(B, prow->row_num, prow1->row_num);
+ }
+ }
+ }
+ }
+
+ return B;
+}
diff --git a/src/misc/espresso/irred.c b/src/misc/espresso/irred.c
new file mode 100644
index 00000000..384e698f
--- /dev/null
+++ b/src/misc/espresso/irred.c
@@ -0,0 +1,440 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+static void fcube_is_covered();
+static void ftautology();
+static bool ftaut_special_cases();
+
+
+static int Rp_current;
+
+/*
+ * irredundant -- Return a minimal subset of F
+ */
+
+pcover
+irredundant(F, D)
+pcover F, D;
+{
+ mark_irredundant(F, D);
+ return sf_inactive(F);
+}
+
+
+/*
+ * mark_irredundant -- find redundant cubes, and mark them "INACTIVE"
+ */
+
+void
+mark_irredundant(F, D)
+pcover F, D;
+{
+ pcover E, Rt, Rp;
+ pset p, p1, last;
+ sm_matrix *table;
+ sm_row *cover;
+ sm_element *pe;
+
+ /* extract a minimum cover */
+ irred_split_cover(F, D, &E, &Rt, &Rp);
+ table = irred_derive_table(D, E, Rp);
+ cover = sm_minimum_cover(table, NIL(int), /* heuristic */ 1, /* debug */ 0);
+
+ /* mark the cubes for the result */
+ foreach_set(F, last, p) {
+ RESET(p, ACTIVE);
+ RESET(p, RELESSEN);
+ }
+ foreach_set(E, last, p) {
+ p1 = GETSET(F, SIZE(p));
+ assert(setp_equal(p1, p));
+ SET(p1, ACTIVE);
+ SET(p1, RELESSEN); /* for essen(), mark as rel. ess. */
+ }
+ sm_foreach_row_element(cover, pe) {
+ p1 = GETSET(F, pe->col_num);
+ SET(p1, ACTIVE);
+ }
+
+ if (debug & IRRED) {
+ printf("# IRRED: F=%d E=%d R=%d Rt=%d Rp=%d Rc=%d Final=%d Bound=%d\n",
+ F->count, E->count, Rt->count+Rp->count, Rt->count, Rp->count,
+ cover->length, E->count + cover->length, 0);
+ }
+
+ free_cover(E);
+ free_cover(Rt);
+ free_cover(Rp);
+ sm_free(table);
+ sm_row_free(cover);
+}
+
+/*
+ * irred_split_cover -- find E, Rt, and Rp from the cover F, D
+ *
+ * E -- relatively essential cubes
+ * Rt -- totally redundant cubes
+ * Rp -- partially redundant cubes
+ */
+
+void
+irred_split_cover(F, D, E, Rt, Rp)
+pcover F, D;
+pcover *E, *Rt, *Rp;
+{
+ register pcube p, last;
+ register int index;
+ pcover R;
+ pcube *FD, *ED;
+
+ /* number the cubes of F -- these numbers track into E, Rp, Rt, etc. */
+ index = 0;
+ foreach_set(F, last, p) {
+ PUTSIZE(p, index);
+ index++;
+ }
+
+ *E = new_cover(10);
+ *Rt = new_cover(10);
+ *Rp = new_cover(10);
+ R = new_cover(10);
+
+ /* Split F into E and R */
+ FD = cube2list(F, D);
+ foreach_set(F, last, p) {
+ if (cube_is_covered(FD, p)) {
+ R = sf_addset(R, p);
+ } else {
+ *E = sf_addset(*E, p);
+ }
+ if (debug & IRRED1) {
+ (void) printf("IRRED1: zr=%d ze=%d to-go=%d time=%s\n",
+ R->count, (*E)->count, F->count - (R->count + (*E)->count),
+ print_time(ptime()));
+ }
+ }
+ free_cubelist(FD);
+
+ /* Split R into Rt and Rp */
+ ED = cube2list(*E, D);
+ foreach_set(R, last, p) {
+ if (cube_is_covered(ED, p)) {
+ *Rt = sf_addset(*Rt, p);
+ } else {
+ *Rp = sf_addset(*Rp, p);
+ }
+ if (debug & IRRED1) {
+ (void) printf("IRRED1: zr=%d zrt=%d to-go=%d time=%s\n",
+ (*Rp)->count, (*Rt)->count,
+ R->count - ((*Rp)->count +(*Rt)->count), print_time(ptime()));
+ }
+ }
+ free_cubelist(ED);
+
+ free_cover(R);
+}
+
+/*
+ * irred_derive_table -- given the covers D, E and the set of
+ * partially redundant primes Rp, build a covering table showing
+ * possible selections of primes to cover Rp.
+ */
+
+sm_matrix *
+irred_derive_table(D, E, Rp)
+pcover D, E, Rp;
+{
+ register pcube last, p, *list;
+ sm_matrix *table;
+ int size_last_dominance, i;
+
+ /* Mark each cube in DE as not part of the redundant set */
+ foreach_set(D, last, p) {
+ RESET(p, REDUND);
+ }
+ foreach_set(E, last, p) {
+ RESET(p, REDUND);
+ }
+
+ /* Mark each cube in Rp as partially redundant */
+ foreach_set(Rp, last, p) {
+ SET(p, REDUND); /* belongs to redundant set */
+ }
+
+ /* For each cube in Rp, find ways to cover its minterms */
+ list = cube3list(D, E, Rp);
+ table = sm_alloc();
+ size_last_dominance = 0;
+ i = 0;
+ foreach_set(Rp, last, p) {
+ Rp_current = SIZE(p);
+ fcube_is_covered(list, p, table);
+ RESET(p, REDUND); /* can now consider this cube redundant */
+ if (debug & IRRED1) {
+ (void) printf("IRRED1: %d of %d to-go=%d, table=%dx%d time=%s\n",
+ i, Rp->count, Rp->count - i,
+ table->nrows, table->ncols, print_time(ptime()));
+ }
+ /* try to keep memory limits down by reducing table as we go along */
+ if (table->nrows - size_last_dominance > 1000) {
+ (void) sm_row_dominance(table);
+ size_last_dominance = table->nrows;
+ if (debug & IRRED1) {
+ (void) printf("IRRED1: delete redundant rows, now %dx%d\n",
+ table->nrows, table->ncols);
+ }
+ }
+ i++;
+ }
+ free_cubelist(list);
+
+ return table;
+}
+
+/* cube_is_covered -- determine if a cubelist "covers" a single cube */
+bool
+cube_is_covered(T, c)
+pcube *T, c;
+{
+ return tautology(cofactor(T,c));
+}
+
+
+
+/* tautology -- answer the tautology question for T */
+bool
+tautology(T)
+pcube *T; /* T will be disposed of */
+{
+ register pcube cl, cr;
+ register int best, result;
+ static int taut_level = 0;
+
+ if (debug & TAUT) {
+ debug_print(T, "TAUTOLOGY", taut_level++);
+ }
+
+ if ((result = taut_special_cases(T)) == MAYBE) {
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, TAUT);
+ result = tautology(scofactor(T, cl, best)) &&
+ tautology(scofactor(T, cr, best));
+ free_cubelist(T);
+ free_cube(cl);
+ free_cube(cr);
+ }
+
+ if (debug & TAUT) {
+ printf("exit TAUTOLOGY[%d]: %s\n", --taut_level, print_bool(result));
+ }
+ return result;
+}
+
+/*
+ * taut_special_cases -- check special cases for tautology
+ */
+
+bool
+taut_special_cases(T)
+pcube *T; /* will be disposed if answer is determined */
+{
+ register pcube *T1, *Tsave, p, ceil=cube.temp[0], temp=cube.temp[1];
+ pcube *A, *B;
+ int var;
+
+ /* Check for a row of all 1's which implies tautology */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, T[0])) {
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which implies no tautology */
+start:
+ INLINEset_copy(ceil, T[0]);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ free_cubelist(T);
+ return FALSE;
+ }
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If function is unate (and no row of all 1's), then no tautology */
+ if (cdata.vars_unate == cdata.vars_active) {
+ free_cubelist(T);
+ return FALSE;
+
+ /* If active in a single variable (and no column of 0's) then tautology */
+ } else if (cdata.vars_active == 1) {
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate variables, and reduce cover if there are any */
+ } else if (cdata.vars_unate != 0) {
+ /* Form a cube "ceil" with full variables in the unate variables */
+ (void) set_copy(ceil, cube.emptyset);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (cdata.is_unate[var]) {
+ INLINEset_or(ceil, ceil, cube.var_mask[var]);
+ }
+ }
+
+ /* Save only those cubes that are "full" in all unate variables */
+ for(Tsave = T1 = T+2; (p = *T1++) != 0; ) {
+ if (setp_implies(ceil, set_or(temp, p, T[0]))) {
+ *Tsave++ = p;
+ }
+ }
+ *Tsave++ = NULL;
+ T[1] = (pcube) Tsave;
+
+ if (debug & TAUT) {
+ printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n",
+ cdata.vars_unate, CUBELISTSIZE(T));
+ }
+ goto start;
+
+ /* Check for component reduction */
+ } else if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T) / 2) {
+ if (cubelist_partition(T, &A, &B, debug & TAUT) == 0) {
+ return MAYBE;
+ } else {
+ free_cubelist(T);
+ if (tautology(A)) {
+ free_cubelist(B);
+ return TRUE;
+ } else {
+ return tautology(B);
+ }
+ }
+ }
+
+ /* We tried as hard as we could, but must recurse from here on */
+ return MAYBE;
+}
+
+/* fcube_is_covered -- determine exactly how a cubelist "covers" a cube */
+static void
+fcube_is_covered(T, c, table)
+pcube *T, c;
+sm_matrix *table;
+{
+ ftautology(cofactor(T,c), table);
+}
+
+
+/* ftautology -- find ways to make a tautology */
+static void
+ftautology(T, table)
+pcube *T; /* T will be disposed of */
+sm_matrix *table;
+{
+ register pcube cl, cr;
+ register int best;
+ static int ftaut_level = 0;
+
+ if (debug & TAUT) {
+ debug_print(T, "FIND_TAUTOLOGY", ftaut_level++);
+ }
+
+ if (ftaut_special_cases(T, table) == MAYBE) {
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, TAUT);
+
+ ftautology(scofactor(T, cl, best), table);
+ ftautology(scofactor(T, cr, best), table);
+
+ free_cubelist(T);
+ free_cube(cl);
+ free_cube(cr);
+ }
+
+ if (debug & TAUT) {
+ (void) printf("exit FIND_TAUTOLOGY[%d]: table is %d by %d\n",
+ --ftaut_level, table->nrows, table->ncols);
+ }
+}
+
+static bool
+ftaut_special_cases(T, table)
+pcube *T; /* will be disposed if answer is determined */
+sm_matrix *table;
+{
+ register pcube *T1, *Tsave, p, temp = cube.temp[0], ceil = cube.temp[1];
+ int var, rownum;
+
+ /* Check for a row of all 1's in the essential cubes */
+ for(T1 = T+2; (p = *T1++) != 0; ) {
+ if (! TESTP(p, REDUND)) {
+ if (full_row(p, T[0])) {
+ /* subspace is covered by essentials -- no new rows for table */
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+ }
+
+ /* Collect column counts, determine unate variables, etc. */
+start:
+ massive_count(T);
+
+ /* If function is unate, find the rows of all 1's */
+ if (cdata.vars_unate == cdata.vars_active) {
+ /* find which nonessentials cover this subspace */
+ rownum = table->last_row ? table->last_row->row_num+1 : 0;
+ (void) sm_insert(table, rownum, Rp_current);
+ for(T1 = T+2; (p = *T1++) != 0; ) {
+ if (TESTP(p, REDUND)) {
+ /* See if a redundant cube covers this leaf */
+ if (full_row(p, T[0])) {
+ (void) sm_insert(table, rownum, (int) SIZE(p));
+ }
+ }
+ }
+ free_cubelist(T);
+ return TRUE;
+
+ /* Perform unate reduction if there are any unate variables */
+ } else if (cdata.vars_unate != 0) {
+ /* Form a cube "ceil" with full variables in the unate variables */
+ (void) set_copy(ceil, cube.emptyset);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (cdata.is_unate[var]) {
+ INLINEset_or(ceil, ceil, cube.var_mask[var]);
+ }
+ }
+
+ /* Save only those cubes that are "full" in all unate variables */
+ for(Tsave = T1 = T+2; (p = *T1++) != 0; ) {
+ if (setp_implies(ceil, set_or(temp, p, T[0]))) {
+ *Tsave++ = p;
+ }
+ }
+ *Tsave++ = 0;
+ T[1] = (pcube) Tsave;
+
+ if (debug & TAUT) {
+ printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n",
+ cdata.vars_unate, CUBELISTSIZE(T));
+ }
+ goto start;
+ }
+
+ /* Not much we can do about it */
+ return MAYBE;
+}
diff --git a/src/misc/espresso/main.c b/src/misc/espresso/main.c
new file mode 100644
index 00000000..0a511c0e
--- /dev/null
+++ b/src/misc/espresso/main.c
@@ -0,0 +1,746 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * Main driver for espresso
+ *
+ * Old style -do xxx, -out xxx, etc. are still supported.
+ */
+
+#include "espresso.h"
+#include "main.h" /* table definitions for options */
+
+static FILE *last_fp;
+static int input_type = FD_type;
+
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ int i, j, first, last, strategy, out_type, option;
+ pPLA PLA, PLA1;
+ pcover F, Fold, Dold;
+ pset last1, p;
+ cost_t cost;
+ bool error, exact_cover;
+ long start;
+ extern char *util_optarg;
+ extern int util_optind;
+
+ start = ptime();
+
+ error = FALSE;
+ init_runtime();
+#ifdef RANDOM
+ srandom(314973);
+#endif
+
+ option = 0; /* default -D: ESPRESSO */
+ out_type = F_type; /* default -o: default is ON-set only */
+ debug = 0; /* default -d: no debugging info */
+ verbose_debug = FALSE; /* default -v: not verbose */
+ print_solution = TRUE; /* default -x: print the solution (!) */
+ summary = FALSE; /* default -s: no summary */
+ trace = FALSE; /* default -t: no trace information */
+ strategy = 0; /* default -S: strategy number */
+ first = -1; /* default -R: select range */
+ last = -1;
+ remove_essential = TRUE; /* default -e: */
+ force_irredundant = TRUE;
+ unwrap_onset = TRUE;
+ single_expand = FALSE;
+ pos = FALSE;
+ recompute_onset = FALSE;
+ use_super_gasp = FALSE;
+ use_random_order = FALSE;
+ kiss = FALSE;
+ echo_comments = TRUE;
+ echo_unknown_commands = TRUE;
+ exact_cover = FALSE; /* for -qm option, the default */
+
+ backward_compatibility_hack(&argc, argv, &option, &out_type);
+
+
+ /* parse command line options*/
+ while ((i = util_getopt(argc, argv, "D:S:de:o:r:stv:x")) != EOF) {
+ switch(i) {
+ case 'D': /* -Dcommand invokes a subcommand */
+ for(j = 0; option_table[j].name != 0; j++) {
+ if (strcmp(util_optarg, option_table[j].name) == 0) {
+ option = j;
+ break;
+ }
+ }
+ if (option_table[j].name == 0) {
+ (void) fprintf(stderr, "%s: bad subcommand \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ case 'o': /* -ooutput selects and output option */
+ for(j = 0; pla_types[j].key != 0; j++) {
+ if (strcmp(util_optarg, pla_types[j].key+1) == 0) {
+ out_type = pla_types[j].value;
+ break;
+ }
+ }
+ if (pla_types[j].key == 0) {
+ (void) fprintf(stderr, "%s: bad output type \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ case 'e': /* -eespresso selects an option for espresso */
+ for(j = 0; esp_opt_table[j].name != 0; j++) {
+ if (strcmp(util_optarg, esp_opt_table[j].name) == 0) {
+ *(esp_opt_table[j].variable) = esp_opt_table[j].value;
+ break;
+ }
+ }
+ if (esp_opt_table[j].name == 0) {
+ (void) fprintf(stderr, "%s: bad espresso option \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ case 'd': /* -d turns on (softly) all debug switches */
+ debug = debug_table[0].value;
+ trace = TRUE;
+ summary = TRUE;
+ break;
+
+ case 'v': /* -vdebug invokes a debug option */
+ verbose_debug = TRUE;
+ for(j = 0; debug_table[j].name != 0; j++) {
+ if (strcmp(util_optarg, debug_table[j].name) == 0) {
+ debug |= debug_table[j].value;
+ break;
+ }
+ }
+ if (debug_table[j].name == 0) {
+ (void) fprintf(stderr, "%s: bad debug type \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ case 't':
+ trace = TRUE;
+ break;
+
+ case 's':
+ summary = TRUE;
+ break;
+
+ case 'x': /* -x suppress printing of results */
+ print_solution = FALSE;
+ break;
+
+ case 'S': /* -S sets a strategy for several cmds */
+ strategy = atoi(util_optarg);
+ break;
+
+ case 'r': /* -r selects range (outputs or vars) */
+ if (sscanf(util_optarg, "%d-%d", &first, &last) < 2) {
+ (void) fprintf(stderr, "%s: bad output range \"%s\"\n",
+ argv[0], util_optarg);
+ exit(1);
+ }
+ break;
+
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ /* provide version information and summaries */
+ if (summary || trace) {
+ /* echo command line and arguments */
+ printf("#");
+ for(i = 0; i < argc; i++) {
+ printf(" %s", argv[i]);
+ }
+ printf("\n");
+ printf("# %s\n", VERSION);
+ }
+
+ /* the remaining arguments are argv[util_optind ... argc-1] */
+ PLA = PLA1 = NIL(PLA_t);
+ switch(option_table[option].num_plas) {
+ case 2:
+ if (util_optind+2 < argc) fatal("trailing arguments on command line");
+ getPLA(util_optind++, argc, argv, option, &PLA, out_type);
+ getPLA(util_optind++, argc, argv, option, &PLA1, out_type);
+ break;
+ case 1:
+ if (util_optind+1 < argc) fatal("trailing arguments on command line");
+ getPLA(util_optind++, argc, argv, option, &PLA, out_type);
+ break;
+ }
+ if (util_optind < argc) fatal("trailing arguments on command line");
+
+ if (summary || trace) {
+ if (PLA != NIL(PLA_t)) PLA_summary(PLA);
+ if (PLA1 != NIL(PLA_t)) PLA_summary(PLA1);
+ }
+
+/*
+ * Now a case-statement to decide what to do
+ */
+
+ switch(option_table[option].key) {
+
+
+/******************** Espresso operations ********************/
+
+ case KEY_ESPRESSO:
+ Fold = sf_save(PLA->F);
+ PLA->F = espresso(PLA->F, PLA->D, PLA->R);
+ EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
+ if (error) {
+ print_solution = FALSE;
+ PLA->F = Fold;
+ (void) check_consistency(PLA);
+ } else {
+ free_cover(Fold);
+ }
+ break;
+
+ case KEY_MANY_ESPRESSO: {
+ int pla_type;
+ do {
+ EXEC(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F);
+ if (print_solution) {
+ fprint_pla(stdout, PLA, out_type);
+ (void) fflush(stdout);
+ }
+ pla_type = PLA->pla_type;
+ free_PLA(PLA);
+ setdown_cube();
+ FREE(cube.part_size);
+ } while (read_pla(last_fp, TRUE, TRUE, pla_type, &PLA) != EOF);
+ exit(0);
+ }
+
+ case KEY_simplify:
+ EXEC(PLA->F = simplify(cube1list(PLA->F)), "SIMPLIFY ", PLA->F);
+ break;
+
+ case KEY_so: /* minimize all functions as single-output */
+ if (strategy < 0 || strategy > 1) {
+ strategy = 0;
+ }
+ so_espresso(PLA, strategy);
+ break;
+
+ case KEY_so_both: /* minimize all functions as single-output */
+ if (strategy < 0 || strategy > 1) {
+ strategy = 0;
+ }
+ so_both_espresso(PLA, strategy);
+ break;
+
+ case KEY_expand: /* execute expand */
+ EXECUTE(PLA->F=expand(PLA->F,PLA->R,FALSE),EXPAND_TIME, PLA->F, cost);
+ break;
+
+ case KEY_irred: /* extract minimal irredundant subset */
+ EXECUTE(PLA->F = irredundant(PLA->F, PLA->D), IRRED_TIME, PLA->F, cost);
+ break;
+
+ case KEY_reduce: /* perform reduction */
+ EXECUTE(PLA->F = reduce(PLA->F, PLA->D), REDUCE_TIME, PLA->F, cost);
+ break;
+
+ case KEY_essen: /* check for essential primes */
+ foreach_set(PLA->F, last1, p) {
+ SET(p, RELESSEN);
+ RESET(p, NONESSEN);
+ }
+ EXECUTE(F = essential(&(PLA->F), &(PLA->D)), ESSEN_TIME, PLA->F, cost);
+ free_cover(F);
+ break;
+
+ case KEY_super_gasp:
+ PLA->F = super_gasp(PLA->F, PLA->D, PLA->R, &cost);
+ break;
+
+ case KEY_gasp:
+ PLA->F = last_gasp(PLA->F, PLA->D, PLA->R, &cost);
+ break;
+
+ case KEY_make_sparse: /* make_sparse step of Espresso */
+ PLA->F = make_sparse(PLA->F, PLA->D, PLA->R);
+ break;
+
+ case KEY_exact:
+ exact_cover = TRUE;
+
+ case KEY_qm:
+ Fold = sf_save(PLA->F);
+ PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, exact_cover);
+ EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
+ if (error) {
+ print_solution = FALSE;
+ PLA->F = Fold;
+ (void) check_consistency(PLA);
+ }
+ free_cover(Fold);
+ break;
+
+ case KEY_primes: /* generate all prime implicants */
+ EXEC(PLA->F = primes_consensus(cube2list(PLA->F, PLA->D)),
+ "PRIMES ", PLA->F);
+ break;
+
+ case KEY_map: /* print out a Karnaugh map of function */
+ map(PLA->F);
+ print_solution = FALSE;
+ break;
+
+
+
+/******************** Output phase and bit pairing ********************/
+
+ case KEY_opo: /* sasao output phase assignment */
+ phase_assignment(PLA, strategy);
+ break;
+
+ case KEY_opoall: /* try all phase assignments (!) */
+ if (first < 0 || first >= cube.part_size[cube.output]) {
+ first = 0;
+ }
+ if (last < 0 || last >= cube.part_size[cube.output]) {
+ last = cube.part_size[cube.output] - 1;
+ }
+ opoall(PLA, first, last, strategy);
+ break;
+
+ case KEY_pair: /* find an optimal pairing */
+ find_optimal_pairing(PLA, strategy);
+ break;
+
+ case KEY_pairall: /* try all pairings !! */
+ pair_all(PLA, strategy);
+ break;
+
+
+
+/******************** Simple cover operations ********************/
+
+ case KEY_echo: /* echo the PLA */
+ break;
+
+ case KEY_taut: /* tautology check */
+ printf("ON-set is%sa tautology\n",
+ tautology(cube1list(PLA->F)) ? " " : " not ");
+ print_solution = FALSE;
+ break;
+
+ case KEY_contain: /* single cube containment */
+ PLA->F = sf_contain(PLA->F);
+ break;
+
+ case KEY_intersect: /* cover intersection */
+ PLA->F = cv_intersect(PLA->F, PLA1->F);
+ break;
+
+ case KEY_union: /* cover union */
+ PLA->F = sf_union(PLA->F, PLA1->F);
+ break;
+
+ case KEY_disjoint: /* make cover disjoint */
+ PLA->F = make_disjoint(PLA->F);
+ break;
+
+ case KEY_dsharp: /* cover disjoint-sharp */
+ PLA->F = cv_dsharp(PLA->F, PLA1->F);
+ break;
+
+ case KEY_sharp: /* cover sharp */
+ PLA->F = cv_sharp(PLA->F, PLA1->F);
+ break;
+
+ case KEY_lexsort: /* lexical sort order */
+ PLA->F = lex_sort(PLA->F);
+ break;
+
+ case KEY_stats: /* print info on size */
+ if (! summary) PLA_summary(PLA);
+ print_solution = FALSE;
+ break;
+
+ case KEY_minterms: /* explode into minterms */
+ if (first < 0 || first >= cube.num_vars) {
+ first = 0;
+ }
+ if (last < 0 || last >= cube.num_vars) {
+ last = cube.num_vars - 1;
+ }
+ PLA->F = sf_dupl(unravel_range(PLA->F, first, last));
+ break;
+
+ case KEY_d1merge: /* distance-1 merge */
+ if (first < 0 || first >= cube.num_vars) {
+ first = 0;
+ }
+ if (last < 0 || last >= cube.num_vars) {
+ last = cube.num_vars - 1;
+ }
+ for(i = first; i <= last; i++) {
+ PLA->F = d1merge(PLA->F, i);
+ }
+ break;
+
+ case KEY_d1merge_in: /* distance-1 merge inputs only */
+ for(i = 0; i < cube.num_binary_vars; i++) {
+ PLA->F = d1merge(PLA->F, i);
+ }
+ break;
+
+ case KEY_PLA_verify: /* check two PLAs for equivalence */
+ EXECUTE(error = PLA_verify(PLA, PLA1), VERIFY_TIME, PLA->F, cost);
+ if (error) {
+ printf("PLA comparison failed; the PLA's are not equivalent\n");
+ exit(1);
+ } else {
+ printf("PLA's compared equal\n");
+ exit(0);
+ }
+ break; /* silly */
+
+ case KEY_verify: /* check two covers for equivalence */
+ Fold = PLA->F; Dold = PLA->D; F = PLA1->F;
+ EXECUTE(error=verify(F, Fold, Dold), VERIFY_TIME, PLA->F, cost);
+ if (error) {
+ printf("PLA comparison failed; the PLA's are not equivalent\n");
+ exit(1);
+ } else {
+ printf("PLA's compared equal\n");
+ exit(0);
+ }
+ break; /* silly */
+
+ case KEY_check: /* check consistency */
+ (void) check_consistency(PLA);
+ print_solution = FALSE;
+ break;
+
+ case KEY_mapdc: /* compute don't care set */
+ map_dcset(PLA);
+ out_type = FD_type;
+ break;
+
+ case KEY_equiv:
+ find_equiv_outputs(PLA);
+ print_solution = FALSE;
+ break;
+
+ case KEY_separate: /* remove PLA->D from PLA->F */
+ PLA->F = complement(cube2list(PLA->D, PLA->R));
+ break;
+
+ case KEY_xor: {
+ pcover T1 = cv_intersect(PLA->F, PLA1->R);
+ pcover T2 = cv_intersect(PLA1->F, PLA->R);
+ free_cover(PLA->F);
+ PLA->F = sf_contain(sf_join(T1, T2));
+ free_cover(T1);
+ free_cover(T2);
+ break;
+ }
+
+ case KEY_fsm: {
+ disassemble_fsm(PLA, summary);
+ print_solution = FALSE;
+ break;
+ }
+
+ case KEY_test: {
+ pcover T, E;
+ T = sf_join(PLA->D, PLA->R);
+ E = new_cover(10);
+ sf_free(PLA->F);
+ EXECUTE(PLA->F = complement(cube1list(T)), COMPL_TIME, PLA->F, cost);
+ EXECUTE(PLA->F = expand(PLA->F, T, FALSE), EXPAND_TIME, PLA->F, cost);
+ EXECUTE(PLA->F = irredundant(PLA->F, E), IRRED_TIME, PLA->F, cost);
+ sf_free(T);
+ T = sf_join(PLA->F, PLA->R);
+ EXECUTE(PLA->D = expand(PLA->D, T, FALSE), EXPAND_TIME, PLA->D, cost);
+ EXECUTE(PLA->D = irredundant(PLA->D, E), IRRED_TIME, PLA->D, cost);
+ sf_free(T);
+ sf_free(E);
+ break;
+ }
+
+
+ }
+
+ /* Print a runtime summary if trace mode enabled */
+ if (trace) {
+ runtime();
+ }
+
+ /* Print total runtime */
+ if (summary || trace) {
+ print_trace(PLA->F, option_table[option].name, ptime()-start);
+ }
+
+ /* Output the solution */
+ if (print_solution) {
+ EXECUTE(fprint_pla(stdout, PLA, out_type), WRITE_TIME, PLA->F, cost);
+ }
+
+ /* Crash and burn if there was a verify error */
+ if (error) {
+ fatal("cover verification failed");
+ }
+
+ /* cleanup all used memory */
+ free_PLA(PLA);
+ FREE(cube.part_size);
+ setdown_cube(); /* free the cube/cdata structure data */
+ sf_cleanup(); /* free unused set structures */
+ sm_cleanup(); /* sparse matrix cleanup */
+
+ exit(0);
+}
+
+
+getPLA(opt, argc, argv, option, PLA, out_type)
+int opt;
+int argc;
+char *argv[];
+int option;
+pPLA *PLA;
+int out_type;
+{
+ FILE *fp;
+ int needs_dcset, needs_offset;
+ char *fname;
+
+ if (opt >= argc) {
+ fp = stdin;
+ fname = "(stdin)";
+ } else {
+ fname = argv[opt];
+ if (strcmp(fname, "-") == 0) {
+ fp = stdin;
+ } else if ((fp = fopen(argv[opt], "r")) == NULL) {
+ (void) fprintf(stderr, "%s: Unable to open %s\n", argv[0], fname);
+ exit(1);
+ }
+ }
+ if (option_table[option].key == KEY_echo) {
+ needs_dcset = (out_type & D_type) != 0;
+ needs_offset = (out_type & R_type) != 0;
+ } else {
+ needs_dcset = option_table[option].needs_dcset;
+ needs_offset = option_table[option].needs_offset;
+ }
+
+ if (read_pla(fp, needs_dcset, needs_offset, input_type, PLA) == EOF) {
+ (void) fprintf(stderr, "%s: Unable to find PLA on file %s\n", argv[0], fname);
+ exit(1);
+ }
+ (*PLA)->filename = util_strsav(fname);
+ filename = (*PLA)->filename;
+/* (void) fclose(fp);*/
+/* hackto support -Dmany */
+ last_fp = fp;
+}
+
+
+runtime()
+{
+ int i;
+ long total = 1, temp;
+
+ for(i = 0; i < TIME_COUNT; i++) {
+ total += total_time[i];
+ }
+ for(i = 0; i < TIME_COUNT; i++) {
+ if (total_calls[i] != 0) {
+ temp = 100 * total_time[i];
+ printf("# %s\t%2d call(s) for %s (%2ld.%01ld%%)\n",
+ total_name[i], total_calls[i], print_time(total_time[i]),
+ temp/total, (10 * (temp%total)) / total);
+ }
+ }
+}
+
+
+init_runtime()
+{
+ total_name[READ_TIME] = "READ ";
+ total_name[WRITE_TIME] = "WRITE ";
+ total_name[COMPL_TIME] = "COMPL ";
+ total_name[REDUCE_TIME] = "REDUCE ";
+ total_name[EXPAND_TIME] = "EXPAND ";
+ total_name[ESSEN_TIME] = "ESSEN ";
+ total_name[IRRED_TIME] = "IRRED ";
+ total_name[GREDUCE_TIME] = "REDUCE_GASP";
+ total_name[GEXPAND_TIME] = "EXPAND_GASP";
+ total_name[GIRRED_TIME] = "IRRED_GASP ";
+ total_name[MV_REDUCE_TIME] ="MV_REDUCE ";
+ total_name[RAISE_IN_TIME] = "RAISE_IN ";
+ total_name[VERIFY_TIME] = "VERIFY ";
+ total_name[PRIMES_TIME] = "PRIMES ";
+ total_name[MINCOV_TIME] = "MINCOV ";
+}
+
+
+subcommands()
+{
+ int i, col;
+ printf(" ");
+ col = 16;
+ for(i = 0; option_table[i].name != 0; i++) {
+ if ((col + strlen(option_table[i].name) + 1) > 76) {
+ printf(",\n ");
+ col = 16;
+ } else if (i != 0) {
+ printf(", ");
+ }
+ printf("%s", option_table[i].name);
+ col += strlen(option_table[i].name) + 2;
+ }
+ printf("\n");
+}
+
+
+usage()
+{
+ printf("%s\n\n", VERSION);
+ printf("SYNOPSIS: espresso [options] [file]\n\n");
+ printf(" -d Enable debugging\n");
+ printf(" -e[opt] Select espresso option:\n");
+ printf(" fast, ness, nirr, nunwrap, onset, pos, strong,\n");
+ printf(" eat, eatdots, kiss, random\n");
+ printf(" -o[type] Select output format:\n");
+ printf(" f, fd, fr, fdr, pleasure, eqntott, kiss, cons\n");
+ printf(" -rn-m Select range for subcommands:\n");
+ printf(" d1merge: first and last variables (0 ... m-1)\n");
+ printf(" minterms: first and last variables (0 ... m-1)\n");
+ printf(" opoall: first and last outputs (0 ... m-1)\n");
+ printf(" -s Provide short execution summary\n");
+ printf(" -t Provide longer execution trace\n");
+ printf(" -x Suppress printing of solution\n");
+ printf(" -v[type] Verbose debugging detail (-v '' for all)\n");
+ printf(" -D[cmd] Execute subcommand 'cmd':\n");
+ subcommands();
+ printf(" -Sn Select strategy for subcommands:\n");
+ printf(" opo: bit2=exact bit1=repeated bit0=skip sparse\n");
+ printf(" opoall: 0=minimize, 1=exact\n");
+ printf(" pair: 0=algebraic, 1=strongd, 2=espresso, 3=exact\n");
+ printf(" pairall: 0=minimize, 1=exact, 2=opo\n");
+ printf(" so_espresso: 0=minimize, 1=exact\n");
+ printf(" so_both: 0=minimize, 1=exact\n");
+}
+
+/*
+ * Hack for backward compatibility (ACK! )
+ */
+
+backward_compatibility_hack(argc, argv, option, out_type)
+int *argc;
+char **argv;
+int *option;
+int *out_type;
+{
+ int i, j;
+
+ /* Scan the argument list for something to do (default is ESPRESSO) */
+ *option = 0;
+ for(i = 1; i < (*argc)-1; i++) {
+ if (strcmp(argv[i], "-do") == 0) {
+ for(j = 0; option_table[j].name != 0; j++)
+ if (strcmp(argv[i+1], option_table[j].name) == 0) {
+ *option = j;
+ delete_arg(argc, argv, i+1);
+ delete_arg(argc, argv, i);
+ break;
+ }
+ if (option_table[j].name == 0) {
+ (void) fprintf(stderr,
+ "espresso: bad keyword \"%s\" following -do\n",argv[i+1]);
+ exit(1);
+ }
+ break;
+ }
+ }
+
+ for(i = 1; i < (*argc)-1; i++) {
+ if (strcmp(argv[i], "-out") == 0) {
+ for(j = 0; pla_types[j].key != 0; j++)
+ if (strcmp(pla_types[j].key+1, argv[i+1]) == 0) {
+ *out_type = pla_types[j].value;
+ delete_arg(argc, argv, i+1);
+ delete_arg(argc, argv, i);
+ break;
+ }
+ if (pla_types[j].key == 0) {
+ (void) fprintf(stderr,
+ "espresso: bad keyword \"%s\" following -out\n",argv[i+1]);
+ exit(1);
+ }
+ break;
+ }
+ }
+
+ for(i = 1; i < (*argc); i++) {
+ if (argv[i][0] == '-') {
+ for(j = 0; esp_opt_table[j].name != 0; j++) {
+ if (strcmp(argv[i]+1, esp_opt_table[j].name) == 0) {
+ delete_arg(argc, argv, i);
+ *(esp_opt_table[j].variable) = esp_opt_table[j].value;
+ break;
+ }
+ }
+ }
+ }
+
+ if (check_arg(argc, argv, "-fdr")) input_type = FDR_type;
+ if (check_arg(argc, argv, "-fr")) input_type = FR_type;
+ if (check_arg(argc, argv, "-f")) input_type = F_type;
+}
+
+
+/* delete_arg -- delete an argument from the argument list */
+delete_arg(argc, argv, num)
+int *argc, num;
+register char *argv[];
+{
+ register int i;
+ (*argc)--;
+ for(i = num; i < *argc; i++) {
+ argv[i] = argv[i+1];
+ }
+}
+
+
+/* check_arg -- scan argv for an argument, and return TRUE if found */
+bool check_arg(argc, argv, s)
+int *argc;
+register char *argv[], *s;
+{
+ register int i;
+ for(i = 1; i < *argc; i++) {
+ if (strcmp(argv[i], s) == 0) {
+ delete_arg(argc, argv, i);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
diff --git a/src/misc/espresso/main.h b/src/misc/espresso/main.h
new file mode 100644
index 00000000..00657f39
--- /dev/null
+++ b/src/misc/espresso/main.h
@@ -0,0 +1,122 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+enum keys {
+ KEY_ESPRESSO, KEY_PLA_verify, KEY_check, KEY_contain, KEY_d1merge,
+ KEY_disjoint, KEY_dsharp, KEY_echo, KEY_essen, KEY_exact, KEY_expand,
+ KEY_gasp, KEY_intersect, KEY_irred, KEY_lexsort, KEY_make_sparse,
+ KEY_map, KEY_mapdc, KEY_minterms, KEY_opo, KEY_opoall,
+ KEY_pair, KEY_pairall, KEY_primes, KEY_qm, KEY_reduce, KEY_sharp,
+ KEY_simplify, KEY_so, KEY_so_both, KEY_stats, KEY_super_gasp, KEY_taut,
+ KEY_test, KEY_equiv, KEY_union, KEY_verify, KEY_MANY_ESPRESSO,
+ KEY_separate, KEY_xor, KEY_d1merge_in, KEY_fsm,
+ KEY_unknown
+};
+
+/* Lookup table for program options */
+struct {
+ char *name;
+ enum keys key;
+ int num_plas;
+ bool needs_offset;
+ bool needs_dcset;
+} option_table [] = {
+ /* ways to minimize functions */
+ "ESPRESSO", KEY_ESPRESSO, 1, TRUE, TRUE, /* must be first */
+ "many", KEY_MANY_ESPRESSO, 1, TRUE, TRUE,
+ "exact", KEY_exact, 1, TRUE, TRUE,
+ "qm", KEY_qm, 1, TRUE, TRUE,
+ "single_output", KEY_so, 1, TRUE, TRUE,
+ "so", KEY_so, 1, TRUE, TRUE,
+ "so_both", KEY_so_both, 1, TRUE, TRUE,
+ "simplify", KEY_simplify, 1, FALSE, FALSE,
+ "echo", KEY_echo, 1, FALSE, FALSE,
+
+ /* output phase assignment and assignment of inputs to two-bit decoders */
+ "opo", KEY_opo, 1, TRUE, TRUE,
+ "opoall", KEY_opoall, 1, TRUE, TRUE,
+ "pair", KEY_pair, 1, TRUE, TRUE,
+ "pairall", KEY_pairall, 1, TRUE, TRUE,
+
+ /* Ways to check covers */
+ "check", KEY_check, 1, TRUE, TRUE,
+ "stats", KEY_stats, 1, FALSE, FALSE,
+ "verify", KEY_verify, 2, FALSE, TRUE,
+ "PLAverify", KEY_PLA_verify, 2, FALSE, TRUE,
+
+ /* hacks */
+ "equiv", KEY_equiv, 1, TRUE, TRUE,
+ "map", KEY_map, 1, FALSE, FALSE,
+ "mapdc", KEY_mapdc, 1, FALSE, FALSE,
+ "fsm", KEY_fsm, 1, FALSE, TRUE,
+
+ /* the basic boolean operations on covers */
+ "contain", KEY_contain, 1, FALSE, FALSE,
+ "d1merge", KEY_d1merge, 1, FALSE, FALSE,
+ "d1merge_in", KEY_d1merge_in, 1, FALSE, FALSE,
+ "disjoint", KEY_disjoint, 1, TRUE, FALSE,
+ "dsharp", KEY_dsharp, 2, FALSE, FALSE,
+ "intersect", KEY_intersect, 2, FALSE, FALSE,
+ "minterms", KEY_minterms, 1, FALSE, FALSE,
+ "primes", KEY_primes, 1, FALSE, TRUE,
+ "separate", KEY_separate, 1, TRUE, TRUE,
+ "sharp", KEY_sharp, 2, FALSE, FALSE,
+ "union", KEY_union, 2, FALSE, FALSE,
+ "xor", KEY_xor, 2, TRUE, TRUE,
+
+ /* debugging only -- call each step of the espresso algorithm */
+ "essen", KEY_essen, 1, FALSE, TRUE,
+ "expand", KEY_expand, 1, TRUE, FALSE,
+ "gasp", KEY_gasp, 1, TRUE, TRUE,
+ "irred", KEY_irred, 1, FALSE, TRUE,
+ "make_sparse", KEY_make_sparse, 1, TRUE, TRUE,
+ "reduce", KEY_reduce, 1, FALSE, TRUE,
+ "taut", KEY_taut, 1, FALSE, FALSE,
+ "super_gasp", KEY_super_gasp, 1, TRUE, TRUE,
+ "lexsort", KEY_lexsort, 1, FALSE, FALSE,
+ "test", KEY_test, 1, TRUE, TRUE,
+ 0, KEY_unknown, 0, FALSE, FALSE /* must be last */
+};
+
+
+struct {
+ char *name;
+ int value;
+} debug_table[] = {
+ "", EXPAND + ESSEN + IRRED + REDUCE + SPARSE + GASP + SHARP + MINCOV,
+ "compl", COMPL, "essen", ESSEN,
+ "expand", EXPAND, "expand1", EXPAND1|EXPAND,
+ "irred", IRRED, "irred1", IRRED1|IRRED,
+ "reduce", REDUCE, "reduce1", REDUCE1|REDUCE,
+ "mincov", MINCOV, "mincov1", MINCOV1|MINCOV,
+ "sparse", SPARSE, "sharp", SHARP,
+ "taut", TAUT, "gasp", GASP,
+ "exact", EXACT,
+ 0,
+};
+
+
+struct {
+ char *name;
+ int *variable;
+ int value;
+} esp_opt_table[] = {
+ "eat", &echo_comments, FALSE,
+ "eatdots", &echo_unknown_commands, FALSE,
+ "fast", &single_expand, TRUE,
+ "kiss", &kiss, TRUE,
+ "ness", &remove_essential, FALSE,
+ "nirr", &force_irredundant, FALSE,
+ "nunwrap", &unwrap_onset, FALSE,
+ "onset", &recompute_onset, TRUE,
+ "pos", &pos, TRUE,
+ "random", &use_random_order, TRUE,
+ "strong", &use_super_gasp, TRUE,
+ 0,
+};
diff --git a/src/misc/espresso/map.c b/src/misc/espresso/map.c
new file mode 100644
index 00000000..5ccf264c
--- /dev/null
+++ b/src/misc/espresso/map.c
@@ -0,0 +1,115 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+static pcube Gcube;
+static pset Gminterm;
+
+pset minterms(T)
+pcover T;
+{
+ int size, var;
+ register pcube last;
+
+ size = 1;
+ for(var = 0; var < cube.num_vars; var++)
+ size *= cube.part_size[var];
+ Gminterm = set_new(size);
+
+ foreach_set(T, last, Gcube)
+ explode(cube.num_vars-1, 0);
+
+ return Gminterm;
+}
+
+
+void explode(var, z)
+int var, z;
+{
+ int i, last = cube.last_part[var];
+ for(i=cube.first_part[var], z *= cube.part_size[var]; i<=last; i++, z++)
+ if (is_in_set(Gcube, i))
+ if (var == 0)
+ set_insert(Gminterm, z);
+ else
+ explode(var-1, z);
+}
+
+
+static int mapindex[16][16] = {
+ 0, 1, 3, 2, 16, 17, 19, 18, 80, 81, 83, 82, 64, 65, 67, 66,
+ 4, 5, 7, 6, 20, 21, 23, 22, 84, 85, 87, 86, 68, 69, 71, 70,
+ 12, 13, 15, 14, 28, 29, 31, 30, 92, 93, 95, 94, 76, 77, 79, 78,
+ 8, 9, 11, 10, 24, 25, 27, 26, 88, 89, 91, 90, 72, 73, 75, 74,
+
+ 32, 33, 35, 34, 48, 49, 51, 50, 112,113,115,114, 96, 97, 99, 98,
+ 36, 37, 39, 38, 52, 53, 55, 54, 116,117,119,118, 100,101,103,102,
+ 44, 45, 47, 46, 60, 61, 63, 62, 124,125,127,126, 108,109,111,110,
+ 40, 41, 43, 42, 56, 57, 59, 58, 120,121,123,122, 104,105,107,106,
+
+
+ 160,161,163,162, 176,177,179,178, 240,241,243,242, 224,225,227,226,
+ 164,165,167,166, 180,181,183,182, 244,245,247,246, 228,229,231,230,
+ 172,173,175,174, 188,189,191,190, 252,253,255,254, 236,237,239,238,
+ 168,169,171,170, 184,185,187,186, 248,249,251,250, 232,233,235,234,
+
+ 128,129,131,130, 144,145,147,146, 208,209,211,210, 192,193,195,194,
+ 132,133,135,134, 148,149,151,150, 212,213,215,214, 196,197,199,198,
+ 140,141,143,142, 156,157,159,158, 220,221,223,222, 204,205,207,206,
+ 136,137,139,138, 152,153,155,154, 216,217,219,218, 200,201,203,202
+};
+
+#define POWER2(n) (1 << n)
+void map(T)
+pcover T;
+{
+ int j, k, l, other_input_offset, output_offset, outnum, ind;
+ int largest_input_ind, numout;
+ char c;
+ pset m;
+ bool some_output;
+
+ m = minterms(T);
+ largest_input_ind = POWER2(cube.num_binary_vars);
+ numout = cube.part_size[cube.num_vars-1];
+
+ for(outnum = 0; outnum < numout; outnum++) {
+ output_offset = outnum * largest_input_ind;
+ printf("\n\nOutput space # %d\n", outnum);
+ for(l = 0; l <= MAX(cube.num_binary_vars - 8, 0); l++) {
+ other_input_offset = l * 256;
+ for(k = 0; k < 16; k++) {
+ some_output = FALSE;
+ for(j = 0; j < 16; j++) {
+ ind = mapindex[k][j] + other_input_offset;
+ if (ind < largest_input_ind) {
+ c = is_in_set(m, ind+output_offset) ? '1' : '.';
+ putchar(c);
+ some_output = TRUE;
+ }
+ if ((j+1)%4 == 0)
+ putchar(' ');
+ if ((j+1)%8 == 0)
+ printf(" ");
+ }
+ if (some_output)
+ putchar('\n');
+ if ((k+1)%4 == 0) {
+ if (k != 15 && mapindex[k+1][0] >= largest_input_ind)
+ break;
+ putchar('\n');
+ }
+ if ((k+1)%8 == 0)
+ putchar('\n');
+ }
+ }
+ }
+ set_free(m);
+}
diff --git a/src/misc/espresso/matrix.c b/src/misc/espresso/matrix.c
new file mode 100644
index 00000000..747fe54f
--- /dev/null
+++ b/src/misc/espresso/matrix.c
@@ -0,0 +1,574 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+#include "sparse_int.h"
+
+/*
+ * free-lists are only used if 'FAST_AND_LOOSE' is set; this is because
+ * we lose the debugging capability of libmm_t which trashes objects when
+ * they are free'd. However, FAST_AND_LOOSE is much faster if matrices
+ * are created and freed frequently.
+ */
+
+#ifdef FAST_AND_LOOSE
+sm_element *sm_element_freelist;
+sm_row *sm_row_freelist;
+sm_col *sm_col_freelist;
+#endif
+
+
+sm_matrix *
+sm_alloc()
+{
+ register sm_matrix *A;
+
+ A = ALLOC(sm_matrix, 1);
+ A->rows = NIL(sm_row *);
+ A->cols = NIL(sm_col *);
+ A->nrows = A->ncols = 0;
+ A->rows_size = A->cols_size = 0;
+ A->first_row = A->last_row = NIL(sm_row);
+ A->first_col = A->last_col = NIL(sm_col);
+ A->user_word = NIL(char); /* for our user ... */
+ return A;
+}
+
+
+sm_matrix *
+sm_alloc_size(row, col)
+int row, col;
+{
+ register sm_matrix *A;
+
+ A = sm_alloc();
+ sm_resize(A, row, col);
+ return A;
+}
+
+
+void
+sm_free(A)
+sm_matrix *A;
+{
+#ifdef FAST_AND_LOOSE
+ register sm_row *prow;
+
+ if (A->first_row != 0) {
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ /* add the elements to the free list of elements */
+ prow->last_col->next_col = sm_element_freelist;
+ sm_element_freelist = prow->first_col;
+ }
+
+ /* Add the linked list of rows to the row-free-list */
+ A->last_row->next_row = sm_row_freelist;
+ sm_row_freelist = A->first_row;
+
+ /* Add the linked list of cols to the col-free-list */
+ A->last_col->next_col = sm_col_freelist;
+ sm_col_freelist = A->first_col;
+ }
+#else
+ register sm_row *prow, *pnext_row;
+ register sm_col *pcol, *pnext_col;
+
+ for(prow = A->first_row; prow != 0; prow = pnext_row) {
+ pnext_row = prow->next_row;
+ sm_row_free(prow);
+ }
+ for(pcol = A->first_col; pcol != 0; pcol = pnext_col) {
+ pnext_col = pcol->next_col;
+ pcol->first_row = pcol->last_row = NIL(sm_element);
+ sm_col_free(pcol);
+ }
+#endif
+
+ /* Free the arrays to map row/col numbers into pointers */
+ FREE(A->rows);
+ FREE(A->cols);
+ FREE(A);
+}
+
+
+sm_matrix *
+sm_dup(A)
+sm_matrix *A;
+{
+ register sm_row *prow;
+ register sm_element *p;
+ register sm_matrix *B;
+
+ B = sm_alloc();
+ if (A->last_row != 0) {
+ sm_resize(B, A->last_row->row_num, A->last_col->col_num);
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) sm_insert(B, p->row_num, p->col_num);
+ }
+ }
+ }
+ return B;
+}
+
+
+void
+sm_resize(A, row, col)
+register sm_matrix *A;
+int row, col;
+{
+ register int i, new_size;
+
+ if (row >= A->rows_size) {
+ new_size = MAX(A->rows_size*2, row+1);
+ A->rows = REALLOC(sm_row *, A->rows, new_size);
+ for(i = A->rows_size; i < new_size; i++) {
+ A->rows[i] = NIL(sm_row);
+ }
+ A->rows_size = new_size;
+ }
+
+ if (col >= A->cols_size) {
+ new_size = MAX(A->cols_size*2, col+1);
+ A->cols = REALLOC(sm_col *, A->cols, new_size);
+ for(i = A->cols_size; i < new_size; i++) {
+ A->cols[i] = NIL(sm_col);
+ }
+ A->cols_size = new_size;
+ }
+}
+
+
+/*
+ * insert -- insert a value into the matrix
+ */
+sm_element *
+sm_insert(A, row, col)
+register sm_matrix *A;
+register int row, col;
+{
+ register sm_row *prow;
+ register sm_col *pcol;
+ register sm_element *element;
+ sm_element *save_element;
+
+ if (row >= A->rows_size || col >= A->cols_size) {
+ sm_resize(A, row, col);
+ }
+
+ prow = A->rows[row];
+ if (prow == NIL(sm_row)) {
+ prow = A->rows[row] = sm_row_alloc();
+ prow->row_num = row;
+ sorted_insert(sm_row, A->first_row, A->last_row, A->nrows,
+ next_row, prev_row, row_num, row, prow);
+ }
+
+ pcol = A->cols[col];
+ if (pcol == NIL(sm_col)) {
+ pcol = A->cols[col] = sm_col_alloc();
+ pcol->col_num = col;
+ sorted_insert(sm_col, A->first_col, A->last_col, A->ncols,
+ next_col, prev_col, col_num, col, pcol);
+ }
+
+ /* get a new item, save its address */
+ sm_element_alloc(element);
+ save_element = element;
+
+ /* insert it into the row list */
+ sorted_insert(sm_element, prow->first_col, prow->last_col,
+ prow->length, next_col, prev_col, col_num, col, element);
+
+ /* if it was used, also insert it into the column list */
+ if (element == save_element) {
+ sorted_insert(sm_element, pcol->first_row, pcol->last_row,
+ pcol->length, next_row, prev_row, row_num, row, element);
+ } else {
+ /* otherwise, it was already in matrix -- free element we allocated */
+ sm_element_free(save_element);
+ }
+ return element;
+}
+
+
+sm_element *
+sm_find(A, rownum, colnum)
+sm_matrix *A;
+int rownum, colnum;
+{
+ sm_row *prow;
+ sm_col *pcol;
+
+ prow = sm_get_row(A, rownum);
+ if (prow == NIL(sm_row)) {
+ return NIL(sm_element);
+ } else {
+ pcol = sm_get_col(A, colnum);
+ if (pcol == NIL(sm_col)) {
+ return NIL(sm_element);
+ }
+ if (prow->length < pcol->length) {
+ return sm_row_find(prow, colnum);
+ } else {
+ return sm_col_find(pcol, rownum);
+ }
+ }
+}
+
+
+void
+sm_remove(A, rownum, colnum)
+sm_matrix *A;
+int rownum, colnum;
+{
+ sm_remove_element(A, sm_find(A, rownum, colnum));
+}
+
+
+
+void
+sm_remove_element(A, p)
+register sm_matrix *A;
+register sm_element *p;
+{
+ register sm_row *prow;
+ register sm_col *pcol;
+
+ if (p == 0) return;
+
+ /* Unlink the element from its row */
+ prow = sm_get_row(A, p->row_num);
+ dll_unlink(p, prow->first_col, prow->last_col,
+ next_col, prev_col, prow->length);
+
+ /* if no more elements in the row, discard the row header */
+ if (prow->first_col == NIL(sm_element)) {
+ sm_delrow(A, p->row_num);
+ }
+
+ /* Unlink the element from its column */
+ pcol = sm_get_col(A, p->col_num);
+ dll_unlink(p, pcol->first_row, pcol->last_row,
+ next_row, prev_row, pcol->length);
+
+ /* if no more elements in the column, discard the column header */
+ if (pcol->first_row == NIL(sm_element)) {
+ sm_delcol(A, p->col_num);
+ }
+
+ sm_element_free(p);
+}
+
+void
+sm_delrow(A, i)
+sm_matrix *A;
+int i;
+{
+ register sm_element *p, *pnext;
+ sm_col *pcol;
+ sm_row *prow;
+
+ prow = sm_get_row(A, i);
+ if (prow != NIL(sm_row)) {
+ /* walk across the row */
+ for(p = prow->first_col; p != 0; p = pnext) {
+ pnext = p->next_col;
+
+ /* unlink the item from the column (and delete it) */
+ pcol = sm_get_col(A, p->col_num);
+ sm_col_remove_element(pcol, p);
+
+ /* discard the column if it is now empty */
+ if (pcol->first_row == NIL(sm_element)) {
+ sm_delcol(A, pcol->col_num);
+ }
+ }
+
+ /* discard the row -- we already threw away the elements */
+ A->rows[i] = NIL(sm_row);
+ dll_unlink(prow, A->first_row, A->last_row,
+ next_row, prev_row, A->nrows);
+ prow->first_col = prow->last_col = NIL(sm_element);
+ sm_row_free(prow);
+ }
+}
+
+void
+sm_delcol(A, i)
+sm_matrix *A;
+int i;
+{
+ register sm_element *p, *pnext;
+ sm_row *prow;
+ sm_col *pcol;
+
+ pcol = sm_get_col(A, i);
+ if (pcol != NIL(sm_col)) {
+ /* walk down the column */
+ for(p = pcol->first_row; p != 0; p = pnext) {
+ pnext = p->next_row;
+
+ /* unlink the element from the row (and delete it) */
+ prow = sm_get_row(A, p->row_num);
+ sm_row_remove_element(prow, p);
+
+ /* discard the row if it is now empty */
+ if (prow->first_col == NIL(sm_element)) {
+ sm_delrow(A, prow->row_num);
+ }
+ }
+
+ /* discard the column -- we already threw away the elements */
+ A->cols[i] = NIL(sm_col);
+ dll_unlink(pcol, A->first_col, A->last_col,
+ next_col, prev_col, A->ncols);
+ pcol->first_row = pcol->last_row = NIL(sm_element);
+ sm_col_free(pcol);
+ }
+}
+
+void
+sm_copy_row(dest, dest_row, prow)
+register sm_matrix *dest;
+int dest_row;
+sm_row *prow;
+{
+ register sm_element *p;
+
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) sm_insert(dest, dest_row, p->col_num);
+ }
+}
+
+
+void
+sm_copy_col(dest, dest_col, pcol)
+register sm_matrix *dest;
+int dest_col;
+sm_col *pcol;
+{
+ register sm_element *p;
+
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ (void) sm_insert(dest, dest_col, p->row_num);
+ }
+}
+
+
+sm_row *
+sm_longest_row(A)
+sm_matrix *A;
+{
+ register sm_row *large_row, *prow;
+ register int max_length;
+
+ max_length = 0;
+ large_row = NIL(sm_row);
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ if (prow->length > max_length) {
+ max_length = prow->length;
+ large_row = prow;
+ }
+ }
+ return large_row;
+}
+
+
+sm_col *
+sm_longest_col(A)
+sm_matrix *A;
+{
+ register sm_col *large_col, *pcol;
+ register int max_length;
+
+ max_length = 0;
+ large_col = NIL(sm_col);
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ if (pcol->length > max_length) {
+ max_length = pcol->length;
+ large_col = pcol;
+ }
+ }
+ return large_col;
+}
+
+int
+sm_num_elements(A)
+sm_matrix *A;
+{
+ register sm_row *prow;
+ register int num;
+
+ num = 0;
+ sm_foreach_row(A, prow) {
+ num += prow->length;
+ }
+ return num;
+}
+
+int
+sm_read(fp, A)
+FILE *fp;
+sm_matrix **A;
+{
+ int i, j, err;
+
+ *A = sm_alloc();
+ while (! feof(fp)) {
+ err = fscanf(fp, "%d %d", &i, &j);
+ if (err == EOF) {
+ return 1;
+ } else if (err != 2) {
+ return 0;
+ }
+ (void) sm_insert(*A, i, j);
+ }
+ return 1;
+}
+
+
+int
+sm_read_compressed(fp, A)
+FILE *fp;
+sm_matrix **A;
+{
+ int i, j, k, nrows, ncols;
+ unsigned long x;
+
+ *A = sm_alloc();
+ if (fscanf(fp, "%d %d", &nrows, &ncols) != 2) {
+ return 0;
+ }
+ sm_resize(*A, nrows, ncols);
+
+ for(i = 0; i < nrows; i++) {
+ if (fscanf(fp, "%lx", &x) != 1) {
+ return 0;
+ }
+ for(j = 0; j < ncols; j += 32) {
+ if (fscanf(fp, "%lx", &x) != 1) {
+ return 0;
+ }
+ for(k = j; x != 0; x >>= 1, k++) {
+ if (x & 1) {
+ (void) sm_insert(*A, i, k);
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+
+void
+sm_write(fp, A)
+FILE *fp;
+sm_matrix *A;
+{
+ register sm_row *prow;
+ register sm_element *p;
+
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) fprintf(fp, "%d %d\n", p->row_num, p->col_num);
+ }
+ }
+}
+
+void
+sm_print(fp, A)
+FILE *fp;
+sm_matrix *A;
+{
+ register sm_row *prow;
+ register sm_col *pcol;
+ int c;
+
+ if (A->last_col->col_num >= 100) {
+ (void) fprintf(fp, " ");
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ (void) fprintf(fp, "%d", (pcol->col_num / 100)%10);
+ }
+ putc('\n', fp);
+ }
+
+ if (A->last_col->col_num >= 10) {
+ (void) fprintf(fp, " ");
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ (void) fprintf(fp, "%d", (pcol->col_num / 10)%10);
+ }
+ putc('\n', fp);
+ }
+
+ (void) fprintf(fp, " ");
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ (void) fprintf(fp, "%d", pcol->col_num % 10);
+ }
+ putc('\n', fp);
+
+ (void) fprintf(fp, " ");
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ (void) fprintf(fp, "-");
+ }
+ putc('\n', fp);
+
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ (void) fprintf(fp, "%3d:", prow->row_num);
+
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ c = sm_row_find(prow, pcol->col_num) ? '1' : '.';
+ putc(c, fp);
+ }
+ putc('\n', fp);
+ }
+}
+
+
+void
+sm_dump(A, s, max)
+sm_matrix *A;
+char *s;
+int max;
+{
+ FILE *fp = stdout;
+
+ (void) fprintf(fp, "%s %d rows by %d cols\n", s, A->nrows, A->ncols);
+ if (A->nrows < max) {
+ sm_print(fp, A);
+ }
+}
+
+void
+sm_cleanup()
+{
+#ifdef FAST_AND_LOOSE
+ register sm_element *p, *pnext;
+ register sm_row *prow, *pnextrow;
+ register sm_col *pcol, *pnextcol;
+
+ for(p = sm_element_freelist; p != 0; p = pnext) {
+ pnext = p->next_col;
+ FREE(p);
+ }
+ sm_element_freelist = 0;
+
+ for(prow = sm_row_freelist; prow != 0; prow = pnextrow) {
+ pnextrow = prow->next_row;
+ FREE(prow);
+ }
+ sm_row_freelist = 0;
+
+ for(pcol = sm_col_freelist; pcol != 0; pcol = pnextcol) {
+ pnextcol = pcol->next_col;
+ FREE(pcol);
+ }
+ sm_col_freelist = 0;
+#endif
+}
diff --git a/src/misc/espresso/mincov.c b/src/misc/espresso/mincov.c
new file mode 100644
index 00000000..ee18a3f1
--- /dev/null
+++ b/src/misc/espresso/mincov.c
@@ -0,0 +1,378 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+/*
+ * mincov.c
+ */
+
+#define USE_GIMPEL
+#define USE_INDEP_SET
+
+static int select_column();
+static void select_essential();
+static int verify_cover();
+
+#define fail(why) {\
+ (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
+ __FILE__, __LINE__, why);\
+ (void) fflush(stdout);\
+ abort();\
+}
+
+sm_row *
+sm_minimum_cover(A, weight, heuristic, debug_level)
+sm_matrix *A;
+int *weight;
+int heuristic; /* set to 1 for a heuristic covering */
+int debug_level; /* how deep in the recursion to provide info */
+{
+ stats_t stats;
+ solution_t *best, *select;
+ sm_row *prow, *sol;
+ sm_col *pcol;
+ sm_matrix *dup_A;
+ int nelem, bound;
+ double sparsity;
+
+ /* Avoid sillyness */
+ if (A->nrows <= 0) {
+ return sm_row_alloc(); /* easy to cover */
+ }
+
+ /* Initialize debugging structure */
+ stats.start_time = util_cpu_time();
+ stats.debug = debug_level > 0;
+ stats.max_print_depth = debug_level;
+ stats.max_depth = -1;
+ stats.nodes = 0;
+ stats.component = stats.comp_count = 0;
+ stats.gimpel = stats.gimpel_count = 0;
+ stats.no_branching = heuristic != 0;
+ stats.lower_bound = -1;
+
+ /* Check the matrix sparsity */
+ nelem = 0;
+ sm_foreach_row(A, prow) {
+ nelem += prow->length;
+ }
+ sparsity = (double) nelem / (double) (A->nrows * A->ncols);
+
+ /* Determine an upper bound on the solution */
+ bound = 1;
+ sm_foreach_col(A, pcol) {
+ bound += WEIGHT(weight, pcol->col_num);
+ }
+
+ /* Perform the covering */
+ select = solution_alloc();
+ dup_A = sm_dup(A);
+ best = sm_mincov(dup_A, select, weight, 0, bound, 0, &stats);
+ sm_free(dup_A);
+ solution_free(select);
+
+ if (stats.debug) {
+ if (stats.no_branching) {
+ (void) printf("**** heuristic covering ...\n");
+ (void) printf("lower bound = %d\n", stats.lower_bound);
+ }
+ (void) printf("matrix = %d by %d with %d elements (%4.3f%%)\n",
+ A->nrows, A->ncols, nelem, sparsity * 100.0);
+ (void) printf("cover size = %d elements\n", best->row->length);
+ (void) printf("cover cost = %d\n", best->cost);
+ (void) printf("time = %s\n",
+ util_print_time(util_cpu_time() - stats.start_time));
+ (void) printf("components = %d\n", stats.comp_count);
+ (void) printf("gimpel = %d\n", stats.gimpel_count);
+ (void) printf("nodes = %d\n", stats.nodes);
+ (void) printf("max_depth = %d\n", stats.max_depth);
+ }
+
+ sol = sm_row_dup(best->row);
+ if (! verify_cover(A, sol)) {
+ fail("mincov: internal error -- cover verification failed\n");
+ }
+ solution_free(best);
+ return sol;
+}
+
+/*
+ * Find the best cover for 'A' (given that 'select' already selected);
+ *
+ * - abort search if a solution cannot be found which beats 'bound'
+ *
+ * - if any solution meets 'lower_bound', then it is the optimum solution
+ * and can be returned without further work.
+ */
+
+solution_t *
+sm_mincov(A, select, weight, lb, bound, depth, stats)
+sm_matrix *A;
+solution_t *select;
+int *weight;
+int lb;
+int bound;
+int depth;
+stats_t *stats;
+{
+ sm_matrix *A1, *A2, *L, *R;
+ sm_element *p;
+ solution_t *select1, *select2, *best, *best1, *best2, *indep;
+ int pick, lb_new, debug;
+
+ /* Start out with some debugging information */
+ stats->nodes++;
+ if (depth > stats->max_depth) stats->max_depth = depth;
+ debug = stats->debug && (depth <= stats->max_print_depth);
+
+ /* Apply row dominance, column dominance, and select essentials */
+ select_essential(A, select, weight, bound);
+ if (select->cost >= bound) {
+ return NIL(solution_t);
+ }
+
+ /* See if gimpel's reduction technique applies ... */
+#ifdef USE_GIMPEL
+ if ( weight == NIL(int)) { /* hack until we fix it */
+ if (gimpel_reduce(A, select, weight, lb, bound, depth, stats, &best)) {
+ return best;
+ }
+ }
+#endif
+
+#ifdef USE_INDEP_SET
+ /* Determine bound from here to final solution using independent-set */
+ indep = sm_maximal_independent_set(A, weight);
+
+ /* make sure the lower bound is monotonically increasing */
+ lb_new = MAX(select->cost + indep->cost, lb);
+ pick = select_column(A, weight, indep);
+ solution_free(indep);
+#else
+ lb_new = select->cost + (A->nrows > 0);
+ pick = select_column(A, weight, NIL(solution_t));
+#endif
+
+ if (depth == 0) {
+ stats->lower_bound = lb_new + stats->gimpel;
+ }
+
+ if (debug) {
+ (void) printf("ABSMIN[%2d]%s", depth, stats->component ? "*" : " ");
+ (void) printf(" %3dx%3d sel=%3d bnd=%3d lb=%3d %12s ",
+ A->nrows, A->ncols, select->cost + stats->gimpel,
+ bound + stats->gimpel, lb_new + stats->gimpel,
+ util_print_time(util_cpu_time()-stats->start_time));
+ }
+
+ /* Check for bounding based on no better solution possible */
+ if (lb_new >= bound) {
+ if (debug) (void) printf("bounded\n");
+ best = NIL(solution_t);
+
+
+ /* Check for new best solution */
+ } else if (A->nrows == 0) {
+ best = solution_dup(select);
+ if (debug) (void) printf("BEST\n");
+ if (stats->debug && stats->component == 0) {
+ (void) printf("new 'best' solution %d at level %d (time is %s)\n",
+ best->cost + stats->gimpel, depth,
+ util_print_time(util_cpu_time() - stats->start_time));
+ }
+
+
+ /* Check for a partition of the problem */
+ } else if (sm_block_partition(A, &L, &R)) {
+ /* Make L the smaller problem */
+ if (L->ncols > R->ncols) {
+ A1 = L;
+ L = R;
+ R = A1;
+ }
+ if (debug) (void) printf("comp %d %d\n", L->nrows, R->nrows);
+ stats->comp_count++;
+
+ /* Solve problem for L */
+ select1 = solution_alloc();
+ stats->component++;
+ best1 = sm_mincov(L, select1, weight, 0,
+ bound-select->cost, depth+1, stats);
+ stats->component--;
+ solution_free(select1);
+ sm_free(L);
+
+ /* Add best solution to the selected set */
+ if (best1 == NIL(solution_t)) {
+ best = NIL(solution_t);
+ } else {
+ for(p = best1->row->first_col; p != 0; p = p->next_col) {
+ solution_add(select, weight, p->col_num);
+ }
+ solution_free(best1);
+
+ /* recur for the remaining block */
+ best = sm_mincov(R, select, weight, lb_new, bound, depth+1, stats);
+ }
+ sm_free(R);
+
+ /* We've tried as hard as possible, but now we must split and recur */
+ } else {
+ if (debug) (void) printf("pick=%d\n", pick);
+
+ /* Assume we choose this column to be in the covering set */
+ A1 = sm_dup(A);
+ select1 = solution_dup(select);
+ solution_accept(select1, A1, weight, pick);
+ best1 = sm_mincov(A1, select1, weight, lb_new, bound, depth+1, stats);
+ solution_free(select1);
+ sm_free(A1);
+
+ /* Update the upper bound if we found a better solution */
+ if (best1 != NIL(solution_t) && bound > best1->cost) {
+ bound = best1->cost;
+ }
+
+ /* See if this is a heuristic covering (no branching) */
+ if (stats->no_branching) {
+ return best1;
+ }
+
+ /* Check for reaching lower bound -- if so, don't actually branch */
+ if (best1 != NIL(solution_t) && best1->cost == lb_new) {
+ return best1;
+ }
+
+ /* Now assume we cannot have that column */
+ A2 = sm_dup(A);
+ select2 = solution_dup(select);
+ solution_reject(select2, A2, weight, pick);
+ best2 = sm_mincov(A2, select2, weight, lb_new, bound, depth+1, stats);
+ solution_free(select2);
+ sm_free(A2);
+
+ best = solution_choose_best(best1, best2);
+ }
+
+ return best;
+}
+
+static int
+select_column(A, weight, indep)
+sm_matrix *A;
+int *weight;
+solution_t *indep;
+{
+ register sm_col *pcol;
+ register sm_row *prow, *indep_cols;
+ register sm_element *p, *p1;
+ double w, best;
+ int best_col;
+
+ indep_cols = sm_row_alloc();
+ if (indep != NIL(solution_t)) {
+ /* Find which columns are in the independent sets */
+ for(p = indep->row->first_col; p != 0; p = p->next_col) {
+ prow = sm_get_row(A, p->col_num);
+ for(p1 = prow->first_col; p1 != 0; p1 = p1->next_col) {
+ (void) sm_row_insert(indep_cols, p1->col_num);
+ }
+ }
+ } else {
+ /* select out of all columns */
+ sm_foreach_col(A, pcol) {
+ (void) sm_row_insert(indep_cols, pcol->col_num);
+ }
+ }
+
+ /* Find the best column */
+ best_col = -1;
+ best = -1;
+
+ /* Consider only columns which are in some independent row */
+ sm_foreach_row_element(indep_cols, p1) {
+ pcol = sm_get_col(A, p1->col_num);
+
+ /* Compute the total 'value' of all things covered by the column */
+ w = 0.0;
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ prow = sm_get_row(A, p->row_num);
+ w += 1.0 / ((double) prow->length - 1.0);
+ }
+
+ /* divide this by the relative cost of choosing this column */
+ w = w / (double) WEIGHT(weight, pcol->col_num);
+
+ /* maximize this ratio */
+ if (w > best) {
+ best_col = pcol->col_num;
+ best = w;
+ }
+ }
+
+ sm_row_free(indep_cols);
+ return best_col;
+}
+
+static void
+select_essential(A, select, weight, bound)
+sm_matrix *A;
+solution_t *select;
+int *weight;
+int bound; /* must beat this solution */
+{
+ register sm_element *p;
+ register sm_row *prow, *essen;
+ int delcols, delrows, essen_count;
+
+ do {
+ /* Check for dominated columns */
+ delcols = sm_col_dominance(A, weight);
+
+ /* Find the rows with only 1 element (the essentials) */
+ essen = sm_row_alloc();
+ sm_foreach_row(A, prow) {
+ if (prow->length == 1) {
+ (void) sm_row_insert(essen, prow->first_col->col_num);
+ }
+ }
+
+ /* Select all of the elements */
+ sm_foreach_row_element(essen, p) {
+ solution_accept(select, A, weight, p->col_num);
+ /* Make sure solution still looks good */
+ if (select->cost >= bound) {
+ sm_row_free(essen);
+ return;
+ }
+ }
+ essen_count = essen->length;
+ sm_row_free(essen);
+
+ /* Check for dominated rows */
+ delrows = sm_row_dominance(A);
+
+ } while (delcols > 0 || delrows > 0 || essen_count > 0);
+}
+
+static int
+verify_cover(A, cover)
+sm_matrix *A;
+sm_row *cover;
+{
+ sm_row *prow;
+
+ sm_foreach_row(A, prow) {
+ if (! sm_row_intersects(prow, cover)) {
+ return 0;
+ }
+ }
+ return 1;
+}
diff --git a/src/misc/espresso/mincov.h b/src/misc/espresso/mincov.h
new file mode 100644
index 00000000..95310774
--- /dev/null
+++ b/src/misc/espresso/mincov.h
@@ -0,0 +1,11 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/* exported */
+extern sm_row *sm_minimum_cover();
diff --git a/src/misc/espresso/mincov_int.h b/src/misc/espresso/mincov_int.h
new file mode 100644
index 00000000..e81850f2
--- /dev/null
+++ b/src/misc/espresso/mincov_int.h
@@ -0,0 +1,55 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+//#include "utility.h"
+#include "sparse.h"
+#include "mincov.h"
+
+#include "util_hack.h" // added
+
+
+typedef struct stats_struct stats_t;
+struct stats_struct {
+ int debug; /* 1 if debugging is enabled */
+ int max_print_depth; /* dump stats for levels up to this level */
+ int max_depth; /* deepest the recursion has gone */
+ int nodes; /* total nodes visited */
+ int component; /* currently solving a component */
+ int comp_count; /* number of components detected */
+ int gimpel_count; /* number of times Gimpel reduction applied */
+ int gimpel; /* currently inside Gimpel reduction */
+ long start_time; /* cpu time when the covering started */
+ int no_branching;
+ int lower_bound;
+};
+
+
+
+typedef struct solution_struct solution_t;
+struct solution_struct {
+ sm_row *row;
+ int cost;
+};
+
+
+extern solution_t *solution_alloc();
+extern void solution_free();
+extern solution_t *solution_dup();
+extern void solution_accept();
+extern void solution_reject();
+extern void solution_add();
+extern solution_t *solution_choose_best();
+
+extern solution_t *sm_maximal_independent_set();
+extern solution_t *sm_mincov();
+extern int gimpel_reduce();
+
+
+#define WEIGHT(weight, col) (weight == NIL(int) ? 1 : weight[col])
diff --git a/src/misc/espresso/module.make b/src/misc/espresso/module.make
new file mode 100644
index 00000000..53ce982a
--- /dev/null
+++ b/src/misc/espresso/module.make
@@ -0,0 +1,39 @@
+SRC += src/misc/espresso/cofactor.c \
+ src/misc/espresso/cols.c \
+ src/misc/espresso/compl.c \
+ src/misc/espresso/contain.c \
+ src/misc/espresso/cubehack.c \
+ src/misc/espresso/cubestr.c \
+ src/misc/espresso/cvrin.c \
+ src/misc/espresso/cvrm.c \
+ src/misc/espresso/cvrmisc.c \
+ src/misc/espresso/cvrout.c \
+ src/misc/espresso/dominate.c \
+ src/misc/espresso/equiv.c \
+ src/misc/espresso/espresso.c \
+ src/misc/espresso/essen.c \
+ src/misc/espresso/exact.c \
+ src/misc/espresso/expand.c \
+ src/misc/espresso/gasp.c \
+ src/misc/espresso/gimpel.c \
+ src/misc/espresso/globals.c \
+ src/misc/espresso/hack.c \
+ src/misc/espresso/indep.c \
+ src/misc/espresso/irred.c \
+ src/misc/espresso/map.c \
+ src/misc/espresso/matrix.c \
+ src/misc/espresso/mincov.c \
+ src/misc/espresso/opo.c \
+ src/misc/espresso/pair.c \
+ src/misc/espresso/part.c \
+ src/misc/espresso/primes.c \
+ src/misc/espresso/reduce.c \
+ src/misc/espresso/rows.c \
+ src/misc/espresso/set.c \
+ src/misc/espresso/setc.c \
+ src/misc/espresso/sharp.c \
+ src/misc/espresso/sminterf.c \
+ src/misc/espresso/solution.c \
+ src/misc/espresso/sparse.c \
+ src/misc/espresso/unate.c \
+ src/misc/espresso/verify.c
diff --git a/src/misc/espresso/opo.c b/src/misc/espresso/opo.c
new file mode 100644
index 00000000..8daa0771
--- /dev/null
+++ b/src/misc/espresso/opo.c
@@ -0,0 +1,624 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+/*
+ * Phase assignment technique (T. Sasao):
+ *
+ * 1. create a function with 2*m outputs which implements the
+ * original function and its complement for each output
+ *
+ * 2. minimize this function
+ *
+ * 3. choose the minimum number of prime implicants from the
+ * result of step 2 which are needed to realize either a function
+ * or its complement for each output
+ *
+ * Step 3 is performed in a rather crude way -- by simply multiplying
+ * out a large expression of the form:
+ *
+ * I = (ab + cdef)(acd + bgh) ...
+ *
+ * which is a product of m expressions where each expression has two
+ * product terms -- one representing which primes are needed for the
+ * function, and one representing which primes are needed for the
+ * complement. The largest product term resulting shows which primes
+ * to keep to implement one function or the other for each output.
+ * For problems with many outputs, this may grind to a
+ * halt.
+ *
+ * Untried: form complement of I and use unate_complement ...
+ *
+ * I have unsuccessfully tried several modifications to the basic
+ * algorithm. The first is quite simple: use Sasao's technique, but
+ * only commit to a single output at a time (rather than all
+ * outputs). The goal would be that the later minimizations can "take
+ * into account" the partial assignment at each step. This is
+ * expensive (m+1 minimizations rather than 2), and the results are
+ * discouraging.
+ *
+ * The second modification is rather complicated. The result from the
+ * minimization in step 2 is guaranteed to be minimal. Hence, for
+ * each output, the set of primes with a 1 in that output are both
+ * necessary and sufficient to implement the function. Espresso
+ * achieves the minimality using the routine MAKE_SPARSE. The
+ * modification is to prevent MAKE_SPARSE from running. Hence, there
+ * are potentially many subsets of the set of primes with a 1 in a
+ * column which can be used to implement that output. We use
+ * IRREDUNDANT to enumerate all possible subsets and then proceed as
+ * before.
+ */
+
+static int opo_no_make_sparse;
+static int opo_repeated;
+static int opo_exact;
+static void minimize();
+
+void phase_assignment(PLA, opo_strategy)
+pPLA PLA;
+int opo_strategy;
+{
+ opo_no_make_sparse = opo_strategy % 2;
+ skip_make_sparse = opo_no_make_sparse;
+ opo_repeated = (opo_strategy / 2) % 2;
+ opo_exact = (opo_strategy / 4) % 2;
+
+ /* Determine a phase assignment */
+ if (PLA->phase != NULL) {
+ FREE(PLA->phase);
+ }
+
+ if (opo_repeated) {
+ PLA->phase = set_save(cube.fullset);
+ repeated_phase_assignment(PLA);
+ } else {
+ PLA->phase = find_phase(PLA, 0, (pcube) NULL);
+ }
+
+ /* Now minimize with this assignment */
+ skip_make_sparse = FALSE;
+ (void) set_phase(PLA);
+ minimize(PLA);
+}
+
+/*
+ * repeated_phase_assignment -- an alternate strategy which commits
+ * to a single phase assignment a step at a time. Performs m + 1
+ * minimizations !
+ */
+void repeated_phase_assignment(PLA)
+pPLA PLA;
+{
+ int i;
+ pcube phase;
+
+ for(i = 0; i < cube.part_size[cube.output]; i++) {
+
+ /* Find best assignment for all undecided outputs */
+ phase = find_phase(PLA, i, PLA->phase);
+
+ /* Commit for only a single output ... */
+ if (! is_in_set(phase, cube.first_part[cube.output] + i)) {
+ set_remove(PLA->phase, cube.first_part[cube.output] + i);
+ }
+
+ if (trace || summary) {
+ printf("\nOPO loop for output #%d\n", i);
+ printf("PLA->phase is %s\n", pc1(PLA->phase));
+ printf("phase is %s\n", pc1(phase));
+ }
+ set_free(phase);
+ }
+}
+
+
+/*
+ * find_phase -- find a phase assignment for the PLA for all outputs starting
+ * with output number first_output.
+ */
+pcube find_phase(PLA, first_output, phase1)
+pPLA PLA;
+int first_output;
+pcube phase1;
+{
+ pcube phase;
+ pPLA PLA1;
+
+ phase = set_save(cube.fullset);
+
+ /* setup the double-phase characteristic function, resize the cube */
+ PLA1 = new_PLA();
+ PLA1->F = sf_save(PLA->F);
+ PLA1->R = sf_save(PLA->R);
+ PLA1->D = sf_save(PLA->D);
+ if (phase1 != NULL) {
+ PLA1->phase = set_save(phase1);
+ (void) set_phase(PLA1);
+ }
+ EXEC_S(output_phase_setup(PLA1, first_output), "OPO-SETUP ", PLA1->F);
+
+ /* minimize the double-phase function */
+ minimize(PLA1);
+
+ /* set the proper phases according to what gives a minimum solution */
+ EXEC_S(PLA1->F = opo(phase, PLA1->F, PLA1->D, PLA1->R, first_output),
+ "OPO ", PLA1->F);
+ free_PLA(PLA1);
+
+ /* set the cube structure to reflect the old size */
+ setdown_cube();
+ cube.part_size[cube.output] -=
+ (cube.part_size[cube.output] - first_output) / 2;
+ cube_setup();
+
+ return phase;
+}
+
+/*
+ * opo -- multiply the expression out to determine a minimum subset of
+ * primes.
+ */
+
+/*ARGSUSED*/
+pcover opo(phase, T, D, R, first_output)
+pcube phase;
+pcover T, D, R;
+int first_output;
+{
+ int offset, output, i, last_output, ind;
+ pset pdest, select, p, p1, last, last1, not_covered, tmp;
+ pset_family temp, T1, T2;
+
+ /* must select all primes for outputs [0 .. first_output-1] */
+ select = set_full(T->count);
+ for(output = 0; output < first_output; output++) {
+ ind = cube.first_part[cube.output] + output;
+ foreachi_set(T, i, p) {
+ if (is_in_set(p, ind)) {
+ set_remove(select, i);
+ }
+ }
+ }
+
+ /* Recursively perform the intersections */
+ offset = (cube.part_size[cube.output] - first_output) / 2;
+ last_output = first_output + offset - 1;
+ temp = opo_recur(T, D, select, offset, first_output, last_output);
+
+ /* largest set is on top -- select primes which are inferred from it */
+ pdest = temp->data;
+ T1 = new_cover(T->count);
+ foreachi_set(T, i, p) {
+ if (! is_in_set(pdest, i)) {
+ T1 = sf_addset(T1, p);
+ }
+ }
+
+ set_free(select);
+ sf_free(temp);
+
+ /* finding phases is difficult -- see which functions are not covered */
+ T2 = complement(cube1list(T1));
+ not_covered = new_cube();
+ tmp = new_cube();
+ foreach_set(T, last, p) {
+ foreach_set(T2, last1, p1) {
+ if (cdist0(p, p1)) {
+ (void) set_or(not_covered, not_covered, set_and(tmp, p, p1));
+ }
+ }
+ }
+ free_cover(T);
+ free_cover(T2);
+ set_free(tmp);
+
+ /* Now reflect the phase choice in a single cube */
+ for(output = first_output; output <= last_output; output++) {
+ ind = cube.first_part[cube.output] + output;
+ if (is_in_set(not_covered, ind)) {
+ if (is_in_set(not_covered, ind + offset)) {
+ fatal("error in output phase assignment");
+ } else {
+ set_remove(phase, ind);
+ }
+ }
+ }
+ set_free(not_covered);
+ return T1;
+}
+
+pset_family opo_recur(T, D, select, offset, first, last)
+pcover T, D;
+pcube select;
+int offset, first, last;
+{
+ static int level = 0;
+ int middle;
+ pset_family sl, sr, temp;
+
+ level++;
+ if (first == last) {
+#if 0
+ if (opo_no_make_sparse) {
+ temp = form_cover_table(T, D, select, first, first + offset);
+ } else {
+ temp = opo_leaf(T, select, first, first + offset);
+ }
+#else
+ temp = opo_leaf(T, select, first, first + offset);
+#endif
+ } else {
+ middle = (first + last) / 2;
+ sl = opo_recur(T, D, select, offset, first, middle);
+ sr = opo_recur(T, D, select, offset, middle+1, last);
+ temp = unate_intersect(sl, sr, level == 1);
+ if (trace) {
+ printf("# OPO[%d]: %4d = %4d x %4d, time = %s\n", level - 1,
+ temp->count, sl->count, sr->count, print_time(ptime()));
+ (void) fflush(stdout);
+ }
+ free_cover(sl);
+ free_cover(sr);
+ }
+ level--;
+ return temp;
+}
+
+
+pset_family opo_leaf(T, select, out1, out2)
+register pcover T;
+pset select;
+int out1, out2;
+{
+ register pset_family temp;
+ register pset p, pdest;
+ register int i;
+
+ out1 += cube.first_part[cube.output];
+ out2 += cube.first_part[cube.output];
+
+ /* Allocate space for the result */
+ temp = sf_new(2, T->count);
+
+ /* Find which primes are needed for the ON-set of this fct */
+ pdest = GETSET(temp, temp->count++);
+ (void) set_copy(pdest, select);
+ foreachi_set(T, i, p) {
+ if (is_in_set(p, out1)) {
+ set_remove(pdest, i);
+ }
+ }
+
+ /* Find which primes are needed for the OFF-set of this fct */
+ pdest = GETSET(temp, temp->count++);
+ (void) set_copy(pdest, select);
+ foreachi_set(T, i, p) {
+ if (is_in_set(p, out2)) {
+ set_remove(pdest, i);
+ }
+ }
+
+ return temp;
+}
+
+#if 0
+pset_family form_cover_table(F, D, select, f, fbar)
+pcover F, D;
+pset select;
+int f, fbar; /* indices of f and fbar in the output part */
+{
+ register int i;
+ register pcube p;
+ pset_family f_table, fbar_table;
+
+ /* setup required for fcube_is_covered */
+ Rp_size = F->count;
+ Rp_start = set_new(Rp_size);
+ foreachi_set(F, i, p) {
+ PUTSIZE(p, i);
+ }
+ foreachi_set(D, i, p) {
+ RESET(p, REDUND);
+ }
+
+ f_table = find_covers(F, D, select, f);
+ fbar_table = find_covers(F, D, select, fbar);
+ f_table = sf_append(f_table, fbar_table);
+
+ set_free(Rp_start);
+ return f_table;
+}
+
+
+pset_family find_covers(F, D, select, n)
+pcover F, D;
+register pset select;
+int n;
+{
+ register pset p, last, new;
+ pcover F1;
+ pcube *Flist;
+ pset_family f_table, table;
+ int i;
+
+ n += cube.first_part[cube.output];
+
+ /* save cubes in this output, and remove the output variable */
+ F1 = new_cover(F->count);
+ foreach_set(F, last, p)
+ if (is_in_set(p, n)) {
+ new = GETSET(F1, F1->count++);
+ set_or(new, p, cube.var_mask[cube.output]);
+ PUTSIZE(new, SIZE(p));
+ SET(new, REDUND);
+ }
+
+ /* Find ways (sop form) to fail to cover output indexed by n */
+ Flist = cube2list(F1, D);
+ table = sf_new(10, Rp_size);
+ foreach_set(F1, last, p) {
+ set_fill(Rp_start, Rp_size);
+ set_remove(Rp_start, SIZE(p));
+ table = sf_append(table, fcube_is_covered(Flist, p));
+ RESET(p, REDUND);
+ }
+ set_fill(Rp_start, Rp_size);
+ foreach_set(table, last, p) {
+ set_diff(p, Rp_start, p);
+ }
+
+ /* complement this to get possible ways to cover the function */
+ for(i = 0; i < Rp_size; i++) {
+ if (! is_in_set(select, i)) {
+ p = set_new(Rp_size);
+ set_insert(p, i);
+ table = sf_addset(table, p);
+ set_free(p);
+ }
+ }
+ f_table = unate_compl(table);
+
+ /* what a pain, but we need bitwise complement of this */
+ set_fill(Rp_start, Rp_size);
+ foreach_set(f_table, last, p) {
+ set_diff(p, Rp_start, p);
+ }
+
+ free_cubelist(Flist);
+ sf_free(F1);
+ return f_table;
+}
+#endif
+
+/*
+ * Take a PLA (ON-set, OFF-set and DC-set) and create the
+ * "double-phase characteristic function" which is merely a new
+ * function which has twice as many outputs and realizes both the
+ * function and the complement.
+ *
+ * The cube structure is assumed to represent the PLA upon entering.
+ * It will be modified to represent the double-phase function upon
+ * exit.
+ *
+ * Only the outputs numbered starting with "first_output" are
+ * duplicated in the output part
+ */
+
+output_phase_setup(PLA, first_output)
+INOUT pPLA PLA;
+int first_output;
+{
+ pcover F, R, D;
+ pcube mask, mask1, last;
+ int first_part, offset;
+ bool save;
+ register pcube p, pr, pf;
+ register int i, last_part;
+
+ if (cube.output == -1)
+ fatal("output_phase_setup: must have an output");
+
+ F = PLA->F;
+ D = PLA->D;
+ R = PLA->R;
+ first_part = cube.first_part[cube.output] + first_output;
+ last_part = cube.last_part[cube.output];
+ offset = cube.part_size[cube.output] - first_output;
+
+ /* Change the output size, setup the cube structure */
+ setdown_cube();
+ cube.part_size[cube.output] += offset;
+ cube_setup();
+
+ /* Create a mask to select that part of the cube which isn't changing */
+ mask = set_save(cube.fullset);
+ for(i = first_part; i < cube.size; i++)
+ set_remove(mask, i);
+ mask1 = set_save(mask);
+ for(i = cube.first_part[cube.output]; i < first_part; i++) {
+ set_remove(mask1, i);
+ }
+
+ PLA->F = new_cover(F->count + R->count);
+ PLA->R = new_cover(F->count + R->count);
+ PLA->D = new_cover(D->count);
+
+ foreach_set(F, last, p) {
+ pf = GETSET(PLA->F, (PLA->F)->count++);
+ pr = GETSET(PLA->R, (PLA->R)->count++);
+ INLINEset_and(pf, mask, p);
+ INLINEset_and(pr, mask1, p);
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i))
+ set_insert(pf, i);
+ save = FALSE;
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i))
+ save = TRUE, set_insert(pr, i+offset);
+ if (! save) PLA->R->count--;
+ }
+
+ foreach_set(R, last, p) {
+ pf = GETSET(PLA->F, (PLA->F)->count++);
+ pr = GETSET(PLA->R, (PLA->R)->count++);
+ INLINEset_and(pf, mask1, p);
+ INLINEset_and(pr, mask, p);
+ save = FALSE;
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i))
+ save = TRUE, set_insert(pf, i+offset);
+ if (! save) PLA->F->count--;
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i))
+ set_insert(pr, i);
+ }
+
+ foreach_set(D, last, p) {
+ pf = GETSET(PLA->D, (PLA->D)->count++);
+ INLINEset_and(pf, mask, p);
+ for(i = first_part; i <= last_part; i++)
+ if (is_in_set(p, i)) {
+ set_insert(pf, i);
+ set_insert(pf, i+offset);
+ }
+ }
+
+ free_cover(F);
+ free_cover(D);
+ free_cover(R);
+ set_free(mask);
+ set_free(mask1);
+}
+
+/*
+ * set_phase -- given a "cube" which describes which phases of the output
+ * are to be implemented, compute the appropriate on-set and off-set
+ */
+pPLA set_phase(PLA)
+INOUT pPLA PLA;
+{
+ pcover F1, R1;
+ register pcube last, p, outmask;
+ register pcube temp=cube.temp[0], phase=PLA->phase, phase1=cube.temp[1];
+
+ outmask = cube.var_mask[cube.num_vars - 1];
+ set_diff(phase1, outmask, phase);
+ set_or(phase1, set_diff(temp, cube.fullset, outmask), phase1);
+ F1 = new_cover((PLA->F)->count + (PLA->R)->count);
+ R1 = new_cover((PLA->F)->count + (PLA->R)->count);
+
+ foreach_set(PLA->F, last, p) {
+ if (! setp_disjoint(set_and(temp, p, phase), outmask))
+ set_copy(GETSET(F1, F1->count++), temp);
+ if (! setp_disjoint(set_and(temp, p, phase1), outmask))
+ set_copy(GETSET(R1, R1->count++), temp);
+ }
+ foreach_set(PLA->R, last, p) {
+ if (! setp_disjoint(set_and(temp, p, phase), outmask))
+ set_copy(GETSET(R1, R1->count++), temp);
+ if (! setp_disjoint(set_and(temp, p, phase1), outmask))
+ set_copy(GETSET(F1, F1->count++), temp);
+ }
+ free_cover(PLA->F);
+ free_cover(PLA->R);
+ PLA->F = F1;
+ PLA->R = R1;
+ return PLA;
+}
+
+#define POW2(x) (1 << (x))
+
+void opoall(PLA, first_output, last_output, opo_strategy)
+pPLA PLA;
+int first_output, last_output;
+int opo_strategy;
+{
+ pcover F, D, R, best_F, best_D, best_R;
+ int i, j, ind, num;
+ pcube bestphase;
+
+ opo_exact = opo_strategy;
+
+ if (PLA->phase != NULL) {
+ set_free(PLA->phase);
+ }
+
+ bestphase = set_save(cube.fullset);
+ best_F = sf_save(PLA->F);
+ best_D = sf_save(PLA->D);
+ best_R = sf_save(PLA->R);
+
+ for(i = 0; i < POW2(last_output - first_output + 1); i++) {
+
+ /* save the initial PLA covers */
+ F = sf_save(PLA->F);
+ D = sf_save(PLA->D);
+ R = sf_save(PLA->R);
+
+ /* compute the phase cube for this iteration */
+ PLA->phase = set_save(cube.fullset);
+ num = i;
+ for(j = last_output; j >= first_output; j--) {
+ if (num % 2 == 0) {
+ ind = cube.first_part[cube.output] + j;
+ set_remove(PLA->phase, ind);
+ }
+ num /= 2;
+ }
+
+ /* set the phase and minimize */
+ (void) set_phase(PLA);
+ printf("# phase is %s\n", pc1(PLA->phase));
+ summary = TRUE;
+ minimize(PLA);
+
+ /* see if this is the best so far */
+ if (PLA->F->count < best_F->count) {
+ /* save new best solution */
+ set_copy(bestphase, PLA->phase);
+ sf_free(best_F);
+ sf_free(best_D);
+ sf_free(best_R);
+ best_F = PLA->F;
+ best_D = PLA->D;
+ best_R = PLA->R;
+ } else {
+ /* throw away the solution */
+ free_cover(PLA->F);
+ free_cover(PLA->D);
+ free_cover(PLA->R);
+ }
+ set_free(PLA->phase);
+
+ /* restore the initial PLA covers */
+ PLA->F = F;
+ PLA->D = D;
+ PLA->R = R;
+ }
+
+ /* one more minimization to restore the best answer */
+ PLA->phase = bestphase;
+ sf_free(PLA->F);
+ sf_free(PLA->D);
+ sf_free(PLA->R);
+ PLA->F = best_F;
+ PLA->D = best_D;
+ PLA->R = best_R;
+}
+
+static void minimize(PLA)
+pPLA PLA;
+{
+ if (opo_exact) {
+ EXEC_S(PLA->F = minimize_exact(PLA->F,PLA->D,PLA->R,1), "EXACT", PLA->F);
+ } else {
+ EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), "ESPRESSO ",PLA->F);
+ }
+}
diff --git a/src/misc/espresso/pair.c b/src/misc/espresso/pair.c
new file mode 100644
index 00000000..a8077176
--- /dev/null
+++ b/src/misc/espresso/pair.c
@@ -0,0 +1,675 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+void set_pair(PLA)
+pPLA PLA;
+{
+ set_pair1(PLA, TRUE);
+}
+
+void set_pair1(PLA, adjust_labels)
+pPLA PLA;
+bool adjust_labels;
+{
+ int i, var, *paired, newvar;
+ int old_num_vars, old_num_binary_vars, old_size, old_mv_start;
+ int *new_part_size, new_num_vars, new_num_binary_vars, new_mv_start;
+ ppair pair = PLA->pair;
+ char scratch[1000], **oldlabel, *var1, *var1bar, *var2, *var2bar;
+
+ if (adjust_labels)
+ makeup_labels(PLA);
+
+ /* Check the pair structure for valid entries and see which binary
+ variables are left unpaired
+ */
+ paired = ALLOC(bool, cube.num_binary_vars);
+ for(var = 0; var < cube.num_binary_vars; var++)
+ paired[var] = FALSE;
+ for(i = 0; i < pair->cnt; i++)
+ if ((pair->var1[i] > 0 && pair->var1[i] <= cube.num_binary_vars) &&
+ (pair->var2[i] > 0 && pair->var2[i] <= cube.num_binary_vars)) {
+ paired[pair->var1[i]-1] = TRUE;
+ paired[pair->var2[i]-1] = TRUE;
+ } else
+ fatal("can only pair binary-valued variables");
+
+ PLA->F = delvar(pairvar(PLA->F, pair), paired);
+ PLA->R = delvar(pairvar(PLA->R, pair), paired);
+ PLA->D = delvar(pairvar(PLA->D, pair), paired);
+
+ /* Now painfully adjust the cube size */
+ old_size = cube.size;
+ old_num_vars = cube.num_vars;
+ old_num_binary_vars = cube.num_binary_vars;
+ old_mv_start = cube.first_part[cube.num_binary_vars];
+ /* Create the new cube.part_size vector and setup the cube structure */
+ new_num_binary_vars = 0;
+ for(var = 0; var < old_num_binary_vars; var++)
+ new_num_binary_vars += (paired[var] == FALSE);
+ new_num_vars = new_num_binary_vars + pair->cnt;
+ new_num_vars += old_num_vars - old_num_binary_vars;
+ new_part_size = ALLOC(int, new_num_vars);
+ for(var = 0; var < pair->cnt; var++)
+ new_part_size[new_num_binary_vars + var] = 4;
+ for(var = 0; var < old_num_vars - old_num_binary_vars; var++)
+ new_part_size[new_num_binary_vars + pair->cnt + var] =
+ cube.part_size[old_num_binary_vars + var];
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_vars = new_num_vars;
+ cube.num_binary_vars = new_num_binary_vars;
+ cube.part_size = new_part_size;
+ cube_setup();
+
+ /* hack with the labels to get them correct */
+ if (adjust_labels) {
+ oldlabel = PLA->label;
+ PLA->label = ALLOC(char *, cube.size);
+ for(var = 0; var < pair->cnt; var++) {
+ newvar = cube.num_binary_vars*2 + var*4;
+ var1 = oldlabel[ (pair->var1[var]-1) * 2 + 1];
+ var2 = oldlabel[ (pair->var2[var]-1) * 2 + 1];
+ var1bar = oldlabel[ (pair->var1[var]-1) * 2];
+ var2bar = oldlabel[ (pair->var2[var]-1) * 2];
+ (void) sprintf(scratch, "%s+%s", var1bar, var2bar);
+ PLA->label[newvar] = util_strsav(scratch);
+ (void) sprintf(scratch, "%s+%s", var1bar, var2);
+ PLA->label[newvar+1] = util_strsav(scratch);
+ (void) sprintf(scratch, "%s+%s", var1, var2bar);
+ PLA->label[newvar+2] = util_strsav(scratch);
+ (void) sprintf(scratch, "%s+%s", var1, var2);
+ PLA->label[newvar+3] = util_strsav(scratch);
+ }
+ /* Copy the old labels for the unpaired binary vars */
+ i = 0;
+ for(var = 0; var < old_num_binary_vars; var++) {
+ if (paired[var] == FALSE) {
+ PLA->label[2*i] = oldlabel[2*var];
+ PLA->label[2*i+1] = oldlabel[2*var+1];
+ oldlabel[2*var] = oldlabel[2*var+1] = (char *) NULL;
+ i++;
+ }
+ }
+ /* Copy the old labels for the remaining unpaired vars */
+ new_mv_start = cube.num_binary_vars*2 + pair->cnt*4;
+ for(i = old_mv_start; i < old_size; i++) {
+ PLA->label[new_mv_start + i - old_mv_start] = oldlabel[i];
+ oldlabel[i] = (char *) NULL;
+ }
+ /* free remaining entries in oldlabel */
+ for(i = 0; i < old_size; i++)
+ if (oldlabel[i] != (char *) NULL)
+ FREE(oldlabel[i]);
+ FREE(oldlabel);
+ }
+
+ /* the paired variables should not be sparse (cf. mv_reduce/raise_in)*/
+ for(var = 0; var < pair->cnt; var++)
+ cube.sparse[cube.num_binary_vars + var] = 0;
+ FREE(paired);
+}
+
+pcover pairvar(A, pair)
+pcover A;
+ppair pair;
+{
+ register pcube last, p;
+ register int val, p1, p2, b1, b0;
+ int insert_col, pairnum;
+
+ insert_col = cube.first_part[cube.num_vars - 1];
+
+ /* stretch the cover matrix to make room for the paired variables */
+ A = sf_delcol(A, insert_col, -4*pair->cnt);
+
+ /* compute the paired values */
+ foreach_set(A, last, p) {
+ for(pairnum = 0; pairnum < pair->cnt; pairnum++) {
+ p1 = cube.first_part[pair->var1[pairnum] - 1];
+ p2 = cube.first_part[pair->var2[pairnum] - 1];
+ b1 = is_in_set(p, p2+1);
+ b0 = is_in_set(p, p2);
+ val = insert_col + pairnum * 4;
+ if (/* a0 */ is_in_set(p, p1)) {
+ if (b0)
+ set_insert(p, val + 3);
+ if (b1)
+ set_insert(p, val + 2);
+ }
+ if (/* a1 */ is_in_set(p, p1+1)) {
+ if (b0)
+ set_insert(p, val + 1);
+ if (b1)
+ set_insert(p, val);
+ }
+ }
+ }
+ return A;
+}
+
+
+/* delvar -- delete variables from A, minimize the number of column shifts */
+pcover delvar(A, paired)
+pcover A;
+bool paired[];
+{
+ bool run;
+ int first_run, run_length, var, offset = 0;
+
+ run = FALSE; run_length = 0;
+ for(var = 0; var < cube.num_binary_vars; var++)
+ if (paired[var])
+ if (run)
+ run_length += cube.part_size[var];
+ else {
+ run = TRUE;
+ first_run = cube.first_part[var];
+ run_length = cube.part_size[var];
+ }
+ else
+ if (run) {
+ A = sf_delcol(A, first_run-offset, run_length);
+ run = FALSE;
+ offset += run_length;
+ }
+ if (run)
+ A = sf_delcol(A, first_run-offset, run_length);
+ return A;
+}
+
+/*
+ find_optimal_pairing -- find which binary variables should be paired
+ to maximally reduce the number of terms
+
+ This is essentially the technique outlined by T. Sasao in the
+ Trans. on Comp., Oct 1984. We estimate the cost of pairing each
+ pair individually using 1 of 4 strategies: (1) algebraic division
+ of F by the pair (exactly T. Sasao technique); (2) strong division
+ of F by the paired variables (using REDUCE/EXPAND/ IRREDUNDANT from
+ espresso); (3) full minimization using espresso; (4) exact
+ minimization. These are in order of both increasing accuracy and
+ increasing difficulty (!)
+
+ Once the n squared pairs have been evaluated, T. Sasao proposes a
+ graph covering of nodes by disjoint edges. For now, I solve this
+ problem exhaustively (complexity = (n-1)*(n-3)*...*3*1 for n
+ variables when n is even). Note that solving this problem exactly
+ is the same as evaluating the cost function for all possible
+ pairings.
+
+ n pairs
+
+ 1, 2 1
+ 3, 4 3
+ 5, 6 15
+ 7, 8 105
+ 9,10 945
+ 11,12 10,395
+ 13,14 135,135
+ 15,16 2,027,025
+ 17,18 34,459,425
+ 19,20 654,729,075
+*/
+void find_optimal_pairing(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+ int i, j, **cost_array;
+
+ cost_array = find_pairing_cost(PLA, strategy);
+
+ if (summary) {
+ printf(" ");
+ for(i = 0; i < cube.num_binary_vars; i++)
+ printf("%3d ", i+1);
+ printf("\n");
+ for(i = 0; i < cube.num_binary_vars; i++) {
+ printf("%3d ", i+1);
+ for(j = 0; j < cube.num_binary_vars; j++)
+ printf("%3d ", cost_array[i][j]);
+ printf("\n");
+ }
+ }
+
+ if (cube.num_binary_vars <= 14) {
+ PLA->pair = pair_best_cost(cost_array);
+ } else {
+ (void) greedy_best_cost(cost_array, &(PLA->pair));
+ }
+ printf("# ");
+ print_pair(PLA->pair);
+
+ for(i = 0; i < cube.num_binary_vars; i++)
+ FREE(cost_array[i]);
+ FREE(cost_array);
+
+ set_pair(PLA);
+ EXEC_S(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F);
+}
+
+int **find_pairing_cost(PLA, strategy)
+pPLA PLA;
+int strategy;
+{
+ int var1, var2, **cost_array;
+ int i, j, xnum_binary_vars, xnum_vars, *xpart_size, cost;
+ pcover T, Fsave, Dsave, Rsave;
+ pset mask;
+/* char *s;*/
+
+ /* data is returned in the cost array */
+ cost_array = ALLOC(int *, cube.num_binary_vars);
+ for(i = 0; i < cube.num_binary_vars; i++)
+ cost_array[i] = ALLOC(int, cube.num_binary_vars);
+ for(i = 0; i < cube.num_binary_vars; i++)
+ for(j = 0; j < cube.num_binary_vars; j++)
+ cost_array[i][j] = 0;
+
+ /* Setup the pair structure for pairing variables together */
+ PLA->pair = pair_new(1);
+ PLA->pair->cnt = 1;
+
+ for(var1 = 0; var1 < cube.num_binary_vars-1; var1++) {
+ for(var2 = var1+1; var2 < cube.num_binary_vars; var2++) {
+ /* if anything but simple strategy, perform setup */
+ if (strategy > 0) {
+ /* save the original covers */
+ Fsave = sf_save(PLA->F);
+ Dsave = sf_save(PLA->D);
+ Rsave = sf_save(PLA->R);
+
+ /* save the original cube structure */
+ xnum_binary_vars = cube.num_binary_vars;
+ xnum_vars = cube.num_vars;
+ xpart_size = ALLOC(int, cube.num_vars);
+ for(i = 0; i < cube.num_vars; i++)
+ xpart_size[i] = cube.part_size[i];
+
+ /* pair two variables together */
+ PLA->pair->var1[0] = var1 + 1;
+ PLA->pair->var2[0] = var2 + 1;
+ set_pair1(PLA, /* adjust_labels */ FALSE);
+ }
+
+
+ /* decide how to best estimate worth of this pairing */
+ switch(strategy) {
+ case 3:
+ /*s = "exact minimization";*/
+ PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1);
+ cost = Fsave->count - PLA->F->count;
+ break;
+ case 2:
+ /*s = "full minimization";*/
+ PLA->F = espresso(PLA->F, PLA->D, PLA->R);
+ cost = Fsave->count - PLA->F->count;
+ break;
+ case 1:
+ /*s = "strong division";*/
+ PLA->F = reduce(PLA->F, PLA->D);
+ PLA->F = expand(PLA->F, PLA->R, FALSE);
+ PLA->F = irredundant(PLA->F, PLA->D);
+ cost = Fsave->count - PLA->F->count;
+ break;
+ case 0:
+ /*s = "weak division";*/
+ mask = new_cube();
+ set_or(mask, cube.var_mask[var1], cube.var_mask[var2]);
+ T = dist_merge(sf_save(PLA->F), mask);
+ cost = PLA->F->count - T->count;
+ sf_free(T);
+ set_free(mask);
+ }
+
+ cost_array[var1][var2] = cost;
+
+ if (strategy > 0) {
+ /* restore the original cube structure -- free the new ones */
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_binary_vars = xnum_binary_vars;
+ cube.num_vars = xnum_vars;
+ cube.part_size = xpart_size;
+ cube_setup();
+
+ /* restore the original cover(s) -- free the new ones */
+ sf_free(PLA->F);
+ sf_free(PLA->D);
+ sf_free(PLA->R);
+ PLA->F = Fsave;
+ PLA->D = Dsave;
+ PLA->R = Rsave;
+ }
+ }
+ }
+
+ pair_free(PLA->pair);
+ PLA->pair = NULL;
+ return cost_array;
+}
+
+static int best_cost;
+static int **cost_array;
+static ppair best_pair;
+static pset best_phase;
+static pPLA global_PLA;
+static pcover best_F, best_D, best_R;
+static int pair_minim_strategy;
+
+
+print_pair(pair)
+ppair pair;
+{
+ int i;
+
+ printf("pair is");
+ for(i = 0; i < pair->cnt; i++)
+ printf (" (%d %d)", pair->var1[i], pair->var2[i]);
+ printf("\n");
+}
+
+
+int greedy_best_cost(cost_array_local, pair_p)
+int **cost_array_local;
+ppair *pair_p;
+{
+ int i, j, besti, bestj, maxcost, total_cost;
+ pset cand;
+ ppair pair;
+
+ pair = pair_new(cube.num_binary_vars);
+ cand = set_full(cube.num_binary_vars);
+ total_cost = 0;
+
+ while (set_ord(cand) >= 2) {
+ maxcost = -1;
+ for(i = 0; i < cube.num_binary_vars; i++) {
+ if (is_in_set(cand, i)) {
+ for(j = i+1; j < cube.num_binary_vars; j++) {
+ if (is_in_set(cand, j)) {
+ if (cost_array_local[i][j] > maxcost) {
+ maxcost = cost_array_local[i][j];
+ besti = i;
+ bestj = j;
+ }
+ }
+ }
+ }
+ }
+ pair->var1[pair->cnt] = besti+1;
+ pair->var2[pair->cnt] = bestj+1;
+ pair->cnt++;
+ set_remove(cand, besti);
+ set_remove(cand, bestj);
+ total_cost += maxcost;
+ }
+ set_free(cand);
+ *pair_p = pair;
+ return total_cost;
+}
+
+
+ppair pair_best_cost(cost_array_local)
+int **cost_array_local;
+{
+ ppair pair;
+ pset candidate;
+
+ best_cost = -1;
+ best_pair = NULL;
+ cost_array = cost_array_local;
+
+ pair = pair_new(cube.num_binary_vars);
+ candidate = set_full(cube.num_binary_vars);
+ generate_all_pairs(pair, cube.num_binary_vars, candidate, find_best_cost);
+ pair_free(pair);
+ set_free(candidate);
+ return best_pair;
+}
+
+
+int find_best_cost(pair)
+register ppair pair;
+{
+ register int i, cost;
+
+ cost = 0;
+ for(i = 0; i < pair->cnt; i++)
+ cost += cost_array[pair->var1[i]-1][pair->var2[i]-1];
+ if (cost > best_cost) {
+ best_cost = cost;
+ best_pair = pair_save(pair, pair->cnt);
+ }
+ if ((debug & MINCOV) && trace) {
+ printf("cost is %d ", cost);
+ print_pair(pair);
+ }
+}
+
+/*
+ pair_all: brute-force approach to try all possible pairings
+
+ pair_strategy is:
+ 2) for espresso
+ 3) for minimize_exact
+ 4) for phase assignment
+*/
+
+pair_all(PLA, pair_strategy)
+pPLA PLA;
+int pair_strategy;
+{
+ ppair pair;
+ pset candidate;
+
+ global_PLA = PLA;
+ pair_minim_strategy = pair_strategy;
+ best_cost = PLA->F->count + 1;
+ best_pair = NULL;
+ best_phase = NULL;
+ best_F = best_D = best_R = NULL;
+ pair = pair_new(cube.num_binary_vars);
+ candidate = set_fill(set_new(cube.num_binary_vars), cube.num_binary_vars);
+
+ generate_all_pairs(pair, cube.num_binary_vars, candidate, minimize_pair);
+
+ pair_free(pair);
+ set_free(candidate);
+
+ PLA->pair = best_pair;
+ PLA->phase = best_phase;
+/* not really necessary
+ if (phase != NULL)
+ (void) set_phase(PLA->phase);
+*/
+ set_pair(PLA);
+ printf("# ");
+ print_pair(PLA->pair);
+
+ sf_free(PLA->F);
+ sf_free(PLA->D);
+ sf_free(PLA->R);
+ PLA->F = best_F;
+ PLA->D = best_D;
+ PLA->R = best_R;
+}
+
+
+/*
+ * minimize_pair -- called as each pair is generated
+ */
+int minimize_pair(pair)
+ppair pair;
+{
+ pcover Fsave, Dsave, Rsave;
+ int i, xnum_binary_vars, xnum_vars, *xpart_size;
+
+ /* save the original covers */
+ Fsave = sf_save(global_PLA->F);
+ Dsave = sf_save(global_PLA->D);
+ Rsave = sf_save(global_PLA->R);
+
+ /* save the original cube structure */
+ xnum_binary_vars = cube.num_binary_vars;
+ xnum_vars = cube.num_vars;
+ xpart_size = ALLOC(int, cube.num_vars);
+ for(i = 0; i < cube.num_vars; i++)
+ xpart_size[i] = cube.part_size[i];
+
+ /* setup the paired variables */
+ global_PLA->pair = pair;
+ set_pair1(global_PLA, /* adjust_labels */ FALSE);
+
+ /* call the minimizer */
+ if (summary)
+ print_pair(pair);
+ switch(pair_minim_strategy) {
+ case 2:
+ EXEC_S(phase_assignment(global_PLA,0), "OPO ", global_PLA->F);
+ if (summary)
+ printf("# phase is %s\n", pc1(global_PLA->phase));
+ break;
+ case 1:
+ EXEC_S(global_PLA->F = minimize_exact(global_PLA->F, global_PLA->D,
+ global_PLA->R, 1), "EXACT ", global_PLA->F);
+ break;
+ case 0:
+ EXEC_S(global_PLA->F = espresso(global_PLA->F, global_PLA->D,
+ global_PLA->R), "ESPRESSO ", global_PLA->F);
+ break;
+ default:
+ break;
+ }
+
+ /* see if we have a new best solution */
+ if (global_PLA->F->count < best_cost) {
+ best_cost = global_PLA->F->count;
+ best_pair = pair_save(pair, pair->cnt);
+ best_phase = global_PLA->phase!=NULL?set_save(global_PLA->phase):NULL;
+ if (best_F != NULL) sf_free(best_F);
+ if (best_D != NULL) sf_free(best_D);
+ if (best_R != NULL) sf_free(best_R);
+ best_F = sf_save(global_PLA->F);
+ best_D = sf_save(global_PLA->D);
+ best_R = sf_save(global_PLA->R);
+ }
+
+ /* restore the original cube structure -- free the new ones */
+ setdown_cube();
+ FREE(cube.part_size);
+ cube.num_binary_vars = xnum_binary_vars;
+ cube.num_vars = xnum_vars;
+ cube.part_size = xpart_size;
+ cube_setup();
+
+ /* restore the original cover(s) -- free the new ones */
+ sf_free(global_PLA->F);
+ sf_free(global_PLA->D);
+ sf_free(global_PLA->R);
+ global_PLA->F = Fsave;
+ global_PLA->D = Dsave;
+ global_PLA->R = Rsave;
+ global_PLA->pair = NULL;
+ global_PLA->phase = NULL;
+}
+
+generate_all_pairs(pair, n, candidate, action)
+ppair pair;
+int n;
+pset candidate;
+int (*action)();
+{
+ int i, j;
+ pset recur_candidate;
+ ppair recur_pair;
+
+ if (set_ord(candidate) < 2) {
+ (*action)(pair);
+ return;
+ }
+
+ recur_pair = pair_save(pair, n);
+ recur_candidate = set_save(candidate);
+
+ /* Find first variable still in the candidate set */
+ for(i = 0; i < n; i++)
+ if (is_in_set(candidate, i))
+ break;
+
+ /* Try all pairs of i with other variables */
+ for(j = i+1; j < n; j++)
+ if (is_in_set(candidate, j)) {
+ /* pair (i j) -- remove from candidate set for future pairings */
+ set_remove(recur_candidate, i);
+ set_remove(recur_candidate, j);
+
+ /* add to the pair array */
+ recur_pair->var1[recur_pair->cnt] = i+1;
+ recur_pair->var2[recur_pair->cnt] = j+1;
+ recur_pair->cnt++;
+
+ /* recur looking for the end ... */
+ generate_all_pairs(recur_pair, n, recur_candidate, action);
+
+ /* now break this pair, and restore candidate set */
+ recur_pair->cnt--;
+ set_insert(recur_candidate, i);
+ set_insert(recur_candidate, j);
+ }
+
+ /* if odd, generate all pairs which do NOT include i */
+ if ((set_ord(candidate) % 2) == 1) {
+ set_remove(recur_candidate, i);
+ generate_all_pairs(recur_pair, n, recur_candidate, action);
+ }
+
+ pair_free(recur_pair);
+ set_free(recur_candidate);
+}
+
+ppair pair_new(n)
+register int n;
+{
+ register ppair pair1;
+
+ pair1 = ALLOC(pair_t, 1);
+ pair1->cnt = 0;
+ pair1->var1 = ALLOC(int, n);
+ pair1->var2 = ALLOC(int, n);
+ return pair1;
+}
+
+
+ppair pair_save(pair, n)
+register ppair pair;
+register int n;
+{
+ register int k;
+ register ppair pair1;
+
+ pair1 = pair_new(n);
+ pair1->cnt = pair->cnt;
+ for(k = 0; k < pair->cnt; k++) {
+ pair1->var1[k] = pair->var1[k];
+ pair1->var2[k] = pair->var2[k];
+ }
+ return pair1;
+}
+
+
+int pair_free(pair)
+register ppair pair;
+{
+ FREE(pair->var1);
+ FREE(pair->var2);
+ FREE(pair);
+}
diff --git a/src/misc/espresso/part.c b/src/misc/espresso/part.c
new file mode 100644
index 00000000..42843aeb
--- /dev/null
+++ b/src/misc/espresso/part.c
@@ -0,0 +1,122 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+static int visit_col();
+
+static void
+copy_row(A, prow)
+register sm_matrix *A;
+register sm_row *prow;
+{
+ register sm_element *p;
+
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) sm_insert(A, p->row_num, p->col_num);
+ }
+}
+
+
+static int
+visit_row(A, prow, rows_visited, cols_visited)
+sm_matrix *A;
+sm_row *prow;
+int *rows_visited;
+int *cols_visited;
+{
+ sm_element *p;
+ sm_col *pcol;
+
+ if (! prow->flag) {
+ prow->flag = 1;
+ (*rows_visited)++;
+ if (*rows_visited == A->nrows) {
+ return 1;
+ }
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ pcol = sm_get_col(A, p->col_num);
+ if (! pcol->flag) {
+ if (visit_col(A, pcol, rows_visited, cols_visited)) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+static int
+visit_col(A, pcol, rows_visited, cols_visited)
+sm_matrix *A;
+sm_col *pcol;
+int *rows_visited;
+int *cols_visited;
+{
+ sm_element *p;
+ sm_row *prow;
+
+ if (! pcol->flag) {
+ pcol->flag = 1;
+ (*cols_visited)++;
+ if (*cols_visited == A->ncols) {
+ return 1;
+ }
+ for(p = pcol->first_row; p != 0; p = p->next_row) {
+ prow = sm_get_row(A, p->row_num);
+ if (! prow->flag) {
+ if (visit_row(A, prow, rows_visited, cols_visited)) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int
+sm_block_partition(A, L, R)
+sm_matrix *A;
+sm_matrix **L, **R;
+{
+ int cols_visited, rows_visited;
+ register sm_row *prow;
+ register sm_col *pcol;
+
+ /* Avoid the trivial case */
+ if (A->nrows == 0) {
+ return 0;
+ }
+
+ /* Reset the visited flags for each row and column */
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ prow->flag = 0;
+ }
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ pcol->flag = 0;
+ }
+
+ cols_visited = rows_visited = 0;
+ if (visit_row(A, A->first_row, &rows_visited, &cols_visited)) {
+ /* we found all of the rows */
+ return 0;
+ } else {
+ *L = sm_alloc();
+ *R = sm_alloc();
+ for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ if (prow->flag) {
+ copy_row(*L, prow);
+ } else {
+ copy_row(*R, prow);
+ }
+ }
+ return 1;
+ }
+}
diff --git a/src/misc/espresso/primes.c b/src/misc/espresso/primes.c
new file mode 100644
index 00000000..3e40da27
--- /dev/null
+++ b/src/misc/espresso/primes.c
@@ -0,0 +1,170 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+static bool primes_consensus_special_cases();
+static pcover primes_consensus_merge();
+static pcover and_with_cofactor();
+
+
+/* primes_consensus -- generate primes using consensus */
+pcover primes_consensus(T)
+pcube *T; /* T will be disposed of */
+{
+ register pcube cl, cr;
+ register int best;
+ pcover Tnew, Tl, Tr;
+
+ if (primes_consensus_special_cases(T, &Tnew) == MAYBE) {
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, COMPL);
+
+ Tl = primes_consensus(scofactor(T, cl, best));
+ Tr = primes_consensus(scofactor(T, cr, best));
+ Tnew = primes_consensus_merge(Tl, Tr, cl, cr);
+
+ free_cube(cl);
+ free_cube(cr);
+ free_cubelist(T);
+ }
+
+ return Tnew;
+}
+
+static bool
+primes_consensus_special_cases(T, Tnew)
+pcube *T; /* will be disposed if answer is determined */
+pcover *Tnew; /* returned only if answer determined */
+{
+ register pcube *T1, p, ceil, cof=T[0];
+ pcube last;
+ pcover A;
+
+ /* Check for no cubes in the cover */
+ if (T[2] == NULL) {
+ *Tnew = new_cover(0);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for only a single cube in the cover */
+ if (T[3] == NULL) {
+ *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2]));
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for a row of all 1's (implies function is a tautology) */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Check for a column of all 0's which can be factored out */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ p = new_cube();
+ (void) set_diff(p, cube.fullset, ceil);
+ (void) set_or(cof, cof, p);
+ free_cube(p);
+
+ A = primes_consensus(T);
+ foreach_set(A, last, p) {
+ INLINEset_and(p, p, ceil);
+ }
+ *Tnew = A;
+ set_free(ceil);
+ return TRUE;
+ }
+ set_free(ceil);
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If single active variable not factored out above, then tautology ! */
+ if (cdata.vars_active == 1) {
+ *Tnew = sf_addset(new_cover(1), cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Check for unate cover */
+ } else if (cdata.vars_unate == cdata.vars_active) {
+ A = cubeunlist(T);
+ *Tnew = sf_contain(A);
+ free_cubelist(T);
+ return TRUE;
+
+ /* Not much we can do about it */
+ } else {
+ return MAYBE;
+ }
+}
+
+static pcover
+primes_consensus_merge(Tl, Tr, cl, cr)
+pcover Tl, Tr;
+pcube cl, cr;
+{
+ register pcube pl, pr, lastl, lastr, pt;
+ pcover T, Tsave;
+
+ Tl = and_with_cofactor(Tl, cl);
+ Tr = and_with_cofactor(Tr, cr);
+
+ T = sf_new(500, Tl->sf_size);
+ pt = T->data;
+ Tsave = sf_contain(sf_join(Tl, Tr));
+
+ foreach_set(Tl, lastl, pl) {
+ foreach_set(Tr, lastr, pr) {
+ if (cdist01(pl, pr) == 1) {
+ consensus(pt, pl, pr);
+ if (++T->count >= T->capacity) {
+ Tsave = sf_union(Tsave, sf_contain(T));
+ T = sf_new(500, Tl->sf_size);
+ pt = T->data;
+ } else {
+ pt += T->wsize;
+ }
+ }
+ }
+ }
+ free_cover(Tl);
+ free_cover(Tr);
+
+ Tsave = sf_union(Tsave, sf_contain(T));
+ return Tsave;
+}
+
+
+static pcover
+and_with_cofactor(A, cof)
+pset_family A;
+register pset cof;
+{
+ register pset last, p;
+
+ foreach_set(A, last, p) {
+ INLINEset_and(p, p, cof);
+ if (cdist(p, cube.fullset) > 0) {
+ RESET(p, ACTIVE);
+ } else {
+ SET(p, ACTIVE);
+ }
+ }
+ return sf_inactive(A);
+}
diff --git a/src/misc/espresso/reduce.c b/src/misc/espresso/reduce.c
new file mode 100644
index 00000000..00e4507f
--- /dev/null
+++ b/src/misc/espresso/reduce.c
@@ -0,0 +1,258 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: reduce.c
+ purpose: Perform the Espresso-II reduction step
+
+ Reduction is a technique used to explore larger regions of the
+ optimization space. We replace each cube of F with a smaller
+ cube while still maintaining a cover of the same logic function.
+*/
+
+#include "espresso.h"
+
+static bool toggle = TRUE;
+
+
+/*
+ reduce -- replace each cube in F with its reduction
+
+ The reduction of a cube is the smallest cube contained in the cube
+ which can replace the cube in the original cover without changing
+ the cover. This is equivalent to the super cube of all of the
+ essential points in the cube. This can be computed directly.
+
+ The problem is that the order in which the cubes are reduced can
+ greatly affect the final result. We alternate between two ordering
+ strategies:
+
+ (1) Order the cubes in ascending order of distance from the
+ largest cube breaking ties by ordering cubes of equal distance
+ in descending order of size (sort_reduce)
+
+ (2) Order the cubes in descending order of the inner-product of
+ the cube and the column sums (mini_sort)
+
+ The real workhorse of this section is the routine SCCC which is
+ used to find the Smallest Cube Containing the Complement of a cover.
+ Reduction as proposed by Espresso-II takes a cube and computes its
+ maximal reduction as the intersection between the cube and the
+ smallest cube containing the complement of (F u D - {c}) cofactored
+ against c.
+
+ As usual, the unate-recursive paradigm is used to compute SCCC.
+ The SCCC of a unate cover is trivial to compute, and thus we perform
+ Shannon Cofactor expansion attempting to drive the cover to be unate
+ as fast as possible.
+*/
+
+pcover reduce(F, D)
+INOUT pcover F;
+IN pcover D;
+{
+ register pcube last, p, cunder, *FD;
+
+ /* Order the cubes */
+ if (use_random_order)
+ F = random_order(F);
+ else {
+ F = toggle ? sort_reduce(F) : mini_sort(F, descend);
+ toggle = ! toggle;
+ }
+
+ /* Try to reduce each cube */
+ FD = cube2list(F, D);
+ foreach_set(F, last, p) {
+ cunder = reduce_cube(FD, p); /* reduce the cube */
+ if (setp_equal(cunder, p)) { /* see if it actually did */
+ SET(p, ACTIVE); /* cube remains active */
+ SET(p, PRIME); /* cube remains prime ? */
+ } else {
+ if (debug & REDUCE) {
+ printf("REDUCE: %s to %s %s\n",
+ pc1(p), pc2(cunder), print_time(ptime()));
+ }
+ set_copy(p, cunder); /* save reduced version */
+ RESET(p, PRIME); /* cube is no longer prime */
+ if (setp_empty(cunder))
+ RESET(p, ACTIVE); /* if null, kill the cube */
+ else
+ SET(p, ACTIVE); /* cube is active */
+ }
+ free_cube(cunder);
+ }
+ free_cubelist(FD);
+
+ /* Delete any cubes of F which reduced to the empty cube */
+ return sf_inactive(F);
+}
+
+/* reduce_cube -- find the maximal reduction of a cube */
+pcube reduce_cube(FD, p)
+IN pcube *FD, p;
+{
+ pcube cunder;
+
+ cunder = sccc(cofactor(FD, p));
+ return set_and(cunder, cunder, p);
+}
+
+
+/* sccc -- find Smallest Cube Containing the Complement of a cover */
+pcube sccc(T)
+INOUT pcube *T; /* T will be disposed of */
+{
+ pcube r;
+ register pcube cl, cr;
+ register int best;
+ static int sccc_level = 0;
+
+ if (debug & REDUCE1) {
+ debug_print(T, "SCCC", sccc_level++);
+ }
+
+ if (sccc_special_cases(T, &r) == MAYBE) {
+ cl = new_cube();
+ cr = new_cube();
+ best = binate_split_select(T, cl, cr, REDUCE1);
+ r = sccc_merge(sccc(scofactor(T, cl, best)),
+ sccc(scofactor(T, cr, best)), cl, cr);
+ free_cubelist(T);
+ }
+
+ if (debug & REDUCE1)
+ printf("SCCC[%d]: result is %s\n", --sccc_level, pc1(r));
+ return r;
+}
+
+
+pcube sccc_merge(left, right, cl, cr)
+INOUT register pcube left, right; /* will be disposed of ... */
+INOUT register pcube cl, cr; /* will be disposed of ... */
+{
+ INLINEset_and(left, left, cl);
+ INLINEset_and(right, right, cr);
+ INLINEset_or(left, left, right);
+ free_cube(right);
+ free_cube(cl);
+ free_cube(cr);
+ return left;
+}
+
+
+/*
+ sccc_cube -- find the smallest cube containing the complement of a cube
+
+ By DeMorgan's law and the fact that the smallest cube containing a
+ cover is the "or" of the positional cubes, it is simple to see that
+ the SCCC is the universe if the cube has more than two active
+ variables. If there is only a single active variable, then the
+ SCCC is merely the bitwise complement of the cube in that
+ variable. A last special case is no active variables, in which
+ case the SCCC is empty.
+
+ This is "anded" with the incoming cube result.
+*/
+pcube sccc_cube(result, p)
+register pcube result, p;
+{
+ register pcube temp=cube.temp[0], mask;
+ int var;
+
+ if ((var = cactive(p)) >= 0) {
+ mask = cube.var_mask[var];
+ INLINEset_xor(temp, p, mask);
+ INLINEset_and(result, result, temp);
+ }
+ return result;
+}
+
+/*
+ * sccc_special_cases -- check the special cases for sccc
+ */
+
+bool sccc_special_cases(T, result)
+INOUT pcube *T; /* will be disposed if answer is determined */
+OUT pcube *result; /* returned only if answer determined */
+{
+ register pcube *T1, p, temp = cube.temp[1], ceil, cof = T[0];
+ pcube *A, *B;
+
+ /* empty cover => complement is universe => SCCC is universe */
+ if (T[2] == NULL) {
+ *result = set_save(cube.fullset);
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* row of 1's => complement is empty => SCCC is empty */
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ if (full_row(p, cof)) {
+ *result = new_cube();
+ free_cubelist(T);
+ return TRUE;
+ }
+ }
+
+ /* Collect column counts, determine unate variables, etc. */
+ massive_count(T);
+
+ /* If cover is unate (or single cube), apply simple rules to find SCCCU */
+ if (cdata.vars_unate == cdata.vars_active || T[3] == NULL) {
+ *result = set_save(cube.fullset);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ (void) sccc_cube(*result, set_or(temp, p, cof));
+ }
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for column of 0's (which can be easily factored( */
+ ceil = set_save(cof);
+ for(T1 = T+2; (p = *T1++) != NULL; ) {
+ INLINEset_or(ceil, ceil, p);
+ }
+ if (! setp_equal(ceil, cube.fullset)) {
+ *result = sccc_cube(set_save(cube.fullset), ceil);
+ if (setp_equal(*result, cube.fullset)) {
+ free_cube(ceil);
+ } else {
+ *result = sccc_merge(sccc(cofactor(T,ceil)),
+ set_save(cube.fullset), ceil, *result);
+ }
+ free_cubelist(T);
+ return TRUE;
+ }
+ free_cube(ceil);
+
+ /* Single active column at this point => tautology => SCCC is empty */
+ if (cdata.vars_active == 1) {
+ *result = new_cube();
+ free_cubelist(T);
+ return TRUE;
+ }
+
+ /* Check for components */
+ if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T)/2) {
+ if (cubelist_partition(T, &A, &B, debug & REDUCE1) == 0) {
+ return MAYBE;
+ } else {
+ free_cubelist(T);
+ *result = sccc(A);
+ ceil = sccc(B);
+ (void) set_and(*result, *result, ceil);
+ set_free(ceil);
+ return TRUE;
+ }
+ }
+
+ /* Not much we can do about it */
+ return MAYBE;
+}
diff --git a/src/misc/espresso/rows.c b/src/misc/espresso/rows.c
new file mode 100644
index 00000000..bf0c0baa
--- /dev/null
+++ b/src/misc/espresso/rows.c
@@ -0,0 +1,314 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+#include "sparse_int.h"
+
+
+/*
+ * allocate a new row vector
+ */
+sm_row *
+sm_row_alloc()
+{
+ register sm_row *prow;
+
+#ifdef FAST_AND_LOOSE
+ if (sm_row_freelist == NIL(sm_row)) {
+ prow = ALLOC(sm_row, 1);
+ } else {
+ prow = sm_row_freelist;
+ sm_row_freelist = prow->next_row;
+ }
+#else
+ prow = ALLOC(sm_row, 1);
+#endif
+
+ prow->row_num = 0;
+ prow->length = 0;
+ prow->first_col = prow->last_col = NIL(sm_element);
+ prow->next_row = prow->prev_row = NIL(sm_row);
+ prow->flag = 0;
+ prow->user_word = NIL(char); /* for our user ... */
+ return prow;
+}
+
+
+/*
+ * free a row vector -- for FAST_AND_LOOSE, this is real cheap for rows;
+ * however, freeing a column must still walk down the column discarding
+ * the elements one-by-one; that is the only use for the extra '-DCOLS'
+ * compile flag ...
+ */
+void
+sm_row_free(prow)
+register sm_row *prow;
+{
+#if defined(FAST_AND_LOOSE) && ! defined(COLS)
+ if (prow->first_col != NIL(sm_element)) {
+ /* Add the linked list of row items to the free list */
+ prow->last_col->next_col = sm_element_freelist;
+ sm_element_freelist = prow->first_col;
+ }
+
+ /* Add the row to the free list of rows */
+ prow->next_row = sm_row_freelist;
+ sm_row_freelist = prow;
+#else
+ register sm_element *p, *pnext;
+
+ for(p = prow->first_col; p != 0; p = pnext) {
+ pnext = p->next_col;
+ sm_element_free(p);
+ }
+ FREE(prow);
+#endif
+}
+
+
+/*
+ * duplicate an existing row
+ */
+sm_row *
+sm_row_dup(prow)
+register sm_row *prow;
+{
+ register sm_row *pnew;
+ register sm_element *p;
+
+ pnew = sm_row_alloc();
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) sm_row_insert(pnew, p->col_num);
+ }
+ return pnew;
+}
+
+
+/*
+ * insert an element into a row vector
+ */
+sm_element *
+sm_row_insert(prow, col)
+register sm_row *prow;
+register int col;
+{
+ register sm_element *test, *element;
+
+ /* get a new item, save its address */
+ sm_element_alloc(element);
+ test = element;
+ sorted_insert(sm_element, prow->first_col, prow->last_col, prow->length,
+ next_col, prev_col, col_num, col, test);
+
+ /* if item was not used, free it */
+ if (element != test) {
+ sm_element_free(element);
+ }
+
+ /* either way, return the current new value */
+ return test;
+}
+
+
+/*
+ * remove an element from a row vector
+ */
+void
+sm_row_remove(prow, col)
+register sm_row *prow;
+register int col;
+{
+ register sm_element *p;
+
+ for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col)
+ ;
+ if (p != 0 && p->col_num == col) {
+ dll_unlink(p, prow->first_col, prow->last_col,
+ next_col, prev_col, prow->length);
+ sm_element_free(p);
+ }
+}
+
+
+/*
+ * find an element (if it is in the row vector)
+ */
+sm_element *
+sm_row_find(prow, col)
+sm_row *prow;
+int col;
+{
+ register sm_element *p;
+
+ for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col)
+ ;
+ if (p != 0 && p->col_num == col) {
+ return p;
+ } else {
+ return NIL(sm_element);
+ }
+}
+
+/*
+ * return 1 if row p2 contains row p1; 0 otherwise
+ */
+int
+sm_row_contains(p1, p2)
+sm_row *p1, *p2;
+{
+ register sm_element *q1, *q2;
+
+ q1 = p1->first_col;
+ q2 = p2->first_col;
+ while (q1 != 0) {
+ if (q2 == 0 || q1->col_num < q2->col_num) {
+ return 0;
+ } else if (q1->col_num == q2->col_num) {
+ q1 = q1->next_col;
+ q2 = q2->next_col;
+ } else {
+ q2 = q2->next_col;
+ }
+ }
+ return 1;
+}
+
+
+/*
+ * return 1 if row p1 and row p2 share an element in common
+ */
+int
+sm_row_intersects(p1, p2)
+sm_row *p1, *p2;
+{
+ register sm_element *q1, *q2;
+
+ q1 = p1->first_col;
+ q2 = p2->first_col;
+ if (q1 == 0 || q2 == 0) return 0;
+ for(;;) {
+ if (q1->col_num < q2->col_num) {
+ if ((q1 = q1->next_col) == 0) {
+ return 0;
+ }
+ } else if (q1->col_num > q2->col_num) {
+ if ((q2 = q2->next_col) == 0) {
+ return 0;
+ }
+ } else {
+ return 1;
+ }
+ }
+}
+
+
+/*
+ * compare two rows, lexical ordering
+ */
+int
+sm_row_compare(p1, p2)
+sm_row *p1, *p2;
+{
+ register sm_element *q1, *q2;
+
+ q1 = p1->first_col;
+ q2 = p2->first_col;
+ while(q1 != 0 && q2 != 0) {
+ if (q1->col_num != q2->col_num) {
+ return q1->col_num - q2->col_num;
+ }
+ q1 = q1->next_col;
+ q2 = q2->next_col;
+ }
+
+ if (q1 != 0) {
+ return 1;
+ } else if (q2 != 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+/*
+ * return the intersection
+ */
+sm_row *
+sm_row_and(p1, p2)
+sm_row *p1, *p2;
+{
+ register sm_element *q1, *q2;
+ register sm_row *result;
+
+ result = sm_row_alloc();
+ q1 = p1->first_col;
+ q2 = p2->first_col;
+ if (q1 == 0 || q2 == 0) return result;
+ for(;;) {
+ if (q1->col_num < q2->col_num) {
+ if ((q1 = q1->next_col) == 0) {
+ return result;
+ }
+ } else if (q1->col_num > q2->col_num) {
+ if ((q2 = q2->next_col) == 0) {
+ return result;
+ }
+ } else {
+ (void) sm_row_insert(result, q1->col_num);
+ if ((q1 = q1->next_col) == 0) {
+ return result;
+ }
+ if ((q2 = q2->next_col) == 0) {
+ return result;
+ }
+ }
+ }
+}
+
+int
+sm_row_hash(prow, modulus)
+sm_row *prow;
+int modulus;
+{
+ register int sum;
+ register sm_element *p;
+
+ sum = 0;
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ sum = (sum*17 + p->col_num) % modulus;
+ }
+ return sum;
+}
+
+/*
+ * remove an element from a row vector (given a pointer to the element)
+ */
+void
+sm_row_remove_element(prow, p)
+register sm_row *prow;
+register sm_element *p;
+{
+ dll_unlink(p, prow->first_col, prow->last_col,
+ next_col, prev_col, prow->length);
+ sm_element_free(p);
+}
+
+
+void
+sm_row_print(fp, prow)
+FILE *fp;
+sm_row *prow;
+{
+ sm_element *p;
+
+ for(p = prow->first_col; p != 0; p = p->next_col) {
+ (void) fprintf(fp, " %d", p->col_num);
+ }
+}
diff --git a/src/misc/espresso/set.c b/src/misc/espresso/set.c
new file mode 100644
index 00000000..fce88288
--- /dev/null
+++ b/src/misc/espresso/set.c
@@ -0,0 +1,820 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * set.c -- routines for maniuplating sets and set families
+ */
+
+/* LINTLIBRARY */
+
+#include "espresso.h"
+static pset_family set_family_garbage = NULL;
+
+static int intcpy(d, s, n)
+register unsigned int *d, *s;
+register long n;
+{
+ register int i;
+ for(i = 0; i < n; i++) {
+ *d++ = *s++;
+ }
+}
+
+
+/* bit_index -- find first bit (from LSB) in a word (MSB=bit n, LSB=bit 0) */
+int bit_index(a)
+register unsigned int a;
+{
+ register int i;
+ if (a == 0)
+ return -1;
+ for(i = 0; (a & 1) == 0; a >>= 1, i++)
+ ;
+ return i;
+}
+
+
+/* set_ord -- count number of elements in a set */
+int set_ord(a)
+register pset a;
+{
+ register int i, sum = 0;
+ register unsigned int val;
+ for(i = LOOP(a); i > 0; i--)
+ if ((val = a[i]) != 0)
+ sum += count_ones(val);
+ return sum;
+}
+
+/* set_dist -- distance between two sets (# elements in common) */
+int set_dist(a, b)
+register pset a, b;
+{
+ register int i, sum = 0;
+ register unsigned int val;
+ for(i = LOOP(a); i > 0; i--)
+ if ((val = a[i] & b[i]) != 0)
+ sum += count_ones(val);
+ return sum;
+}
+
+/* set_clear -- make "r" the empty set of "size" elements */
+pset set_clear(r, size)
+register pset r;
+int size;
+{
+ register int i = LOOPINIT(size);
+ *r = i; do r[i] = 0; while (--i > 0);
+ return r;
+}
+
+/* set_fill -- make "r" the universal set of "size" elements */
+pset set_fill(r, size)
+register pset r;
+register int size;
+{
+ register int i = LOOPINIT(size);
+ *r = i;
+ r[i] = ~ (unsigned) 0;
+ r[i] >>= i * BPI - size;
+ while (--i > 0)
+ r[i] = ~ (unsigned) 0;
+ return r;
+}
+
+/* set_copy -- copy set a into set r */
+pset set_copy(r, a)
+register pset r, a;
+{
+ register int i = LOOPCOPY(a);
+ do r[i] = a[i]; while (--i >= 0);
+ return r;
+}
+
+/* set_and -- compute intersection of sets "a" and "b" */
+pset set_and(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ PUTLOOP(r,i); do r[i] = a[i] & b[i]; while (--i > 0);
+ return r;
+}
+
+/* set_or -- compute union of sets "a" and "b" */
+pset set_or(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ PUTLOOP(r,i); do r[i] = a[i] | b[i]; while (--i > 0);
+ return r;
+}
+
+/* set_diff -- compute difference of sets "a" and "b" */
+pset set_diff(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ PUTLOOP(r,i); do r[i] = a[i] & ~b[i]; while (--i > 0);
+ return r;
+}
+
+/* set_xor -- compute exclusive-or of sets "a" and "b" */
+pset set_xor(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+#ifdef IBM_WATC
+ PUTLOOP(r,i); do r[i] = (a[i]&~b[i]) | (~a[i]&b[i]); while (--i > 0);
+#else
+ PUTLOOP(r,i); do r[i] = a[i] ^ b[i]; while (--i > 0);
+#endif
+ return r;
+}
+
+/* set_merge -- compute "a" & "mask" | "b" & ~ "mask" */
+pset set_merge(r, a, b, mask)
+register pset r, a, b, mask;
+{
+ register int i = LOOP(a);
+ PUTLOOP(r,i); do r[i] = (a[i]&mask[i]) | (b[i]&~mask[i]); while (--i > 0);
+ return r;
+}
+
+/* set_andp -- compute intersection of sets "a" and "b" , TRUE if nonempty */
+bool set_andp(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ register unsigned int x = 0;
+ PUTLOOP(r,i); do {r[i] = a[i] & b[i]; x |= r[i];} while (--i > 0);
+ return x != 0;
+}
+
+/* set_orp -- compute union of sets "a" and "b" , TRUE if nonempty */
+bool set_orp(r, a, b)
+register pset r, a, b;
+{
+ register int i = LOOP(a);
+ register unsigned int x = 0;
+ PUTLOOP(r,i); do {r[i] = a[i] | b[i]; x |= r[i];} while (--i > 0);
+ return x != 0;
+}
+
+/* setp_empty -- check if the set "a" is empty */
+bool setp_empty(a)
+register pset a;
+{
+ register int i = LOOP(a);
+ do if (a[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/* setp_full -- check if the set "a" is the full set of "size" elements */
+bool setp_full(a, size)
+register pset a;
+register int size;
+{
+ register int i = LOOP(a);
+ register unsigned int test;
+ test = ~ (unsigned) 0;
+ test >>= i * BPI - size;
+ if (a[i] != test)
+ return FALSE;
+ while (--i > 0)
+ if (a[i] != (~(unsigned) 0))
+ return FALSE;
+ return TRUE;
+}
+
+/* setp_equal -- check if the set "a" equals set "b" */
+bool setp_equal(a, b)
+register pset a, b;
+{
+ register int i = LOOP(a);
+ do if (a[i] != b[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/* setp_disjoint -- check if intersection of "a" and "b" is empty */
+bool setp_disjoint(a, b)
+register pset a, b;
+{
+ register int i = LOOP(a);
+ do if (a[i] & b[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/* setp_implies -- check if "a" implies "b" ("b" contains "a") */
+bool setp_implies(a, b)
+register pset a, b;
+{
+ register int i = LOOP(a);
+ do if (a[i] & ~b[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/* sf_or -- form the "or" of all sets in a set family */
+pset sf_or(A)
+pset_family A;
+{
+ register pset or, last, p;
+
+ or = set_new(A->sf_size);
+ foreach_set(A, last, p)
+ INLINEset_or(or, or, p);
+ return or;
+}
+
+/* sf_and -- form the "and" of all sets in a set family */
+pset sf_and(A)
+pset_family A;
+{
+ register pset and, last, p;
+
+ and = set_fill(set_new(A->sf_size), A->sf_size);
+ foreach_set(A, last, p)
+ INLINEset_and(and, and, p);
+ return and;
+}
+
+/* sf_active -- make all members of the set family active */
+pset_family sf_active(A)
+pset_family A;
+{
+ register pset p, last;
+ foreach_set(A, last, p) {
+ SET(p, ACTIVE);
+ }
+ A->active_count = A->count;
+ return A;
+}
+
+
+/* sf_inactive -- remove all inactive cubes in a set family */
+pset_family sf_inactive(A)
+pset_family A;
+{
+ register pset p, last, pdest;
+
+ pdest = A->data;
+ foreach_set(A, last, p) {
+ if (TESTP(p, ACTIVE)) {
+ if (pdest != p) {
+ INLINEset_copy(pdest, p);
+ }
+ pdest += A->wsize;
+ } else {
+ A->count--;
+ }
+ }
+ return A;
+}
+
+
+/* sf_copy -- copy a set family */
+pset_family sf_copy(R, A)
+pset_family R, A;
+{
+ R->sf_size = A->sf_size;
+ R->wsize = A->wsize;
+/*R->capacity = A->count;*/
+/*R->data = REALLOC(unsigned int, R->data, (long) R->capacity * R->wsize);*/
+ R->count = A->count;
+ R->active_count = A->active_count;
+ intcpy(R->data, A->data, (long) A->wsize * A->count);
+ return R;
+}
+
+
+/* sf_join -- join A and B into a single set_family */
+pset_family sf_join(A, B)
+pset_family A, B;
+{
+ pset_family R;
+ long asize = A->count * A->wsize;
+ long bsize = B->count * B->wsize;
+
+ if (A->sf_size != B->sf_size) fatal("sf_join: sf_size mismatch");
+ R = sf_new(A->count + B->count, A->sf_size);
+ R->count = A->count + B->count;
+ R->active_count = A->active_count + B->active_count;
+ intcpy(R->data, A->data, asize);
+ intcpy(R->data + asize, B->data, bsize);
+ return R;
+}
+
+
+/* sf_append -- append the sets of B to the end of A, and dispose of B */
+pset_family sf_append(A, B)
+pset_family A, B;
+{
+ long asize = A->count * A->wsize;
+ long bsize = B->count * B->wsize;
+
+ if (A->sf_size != B->sf_size) fatal("sf_append: sf_size mismatch");
+ A->capacity = A->count + B->count;
+ A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize);
+ intcpy(A->data + asize, B->data, bsize);
+ A->count += B->count;
+ A->active_count += B->active_count;
+ sf_free(B);
+ return A;
+}
+
+
+/* sf_new -- allocate "num" sets of "size" elements each */
+pset_family sf_new(num, size)
+int num, size;
+{
+ pset_family A;
+ if (set_family_garbage == NULL) {
+ A = ALLOC(set_family_t, 1);
+ } else {
+ A = set_family_garbage;
+ set_family_garbage = A->next;
+ }
+ A->sf_size = size;
+ A->wsize = SET_SIZE(size);
+ A->capacity = num;
+ A->data = ALLOC(unsigned int, (long) A->capacity * A->wsize);
+ A->count = 0;
+ A->active_count = 0;
+ return A;
+}
+
+
+/* sf_save -- create a duplicate copy of a set family */
+pset_family sf_save(A)
+register pset_family A;
+{
+ return sf_copy(sf_new(A->count, A->sf_size), A);
+}
+
+
+/* sf_free -- free the storage allocated for a set family */
+void sf_free(A)
+pset_family A;
+{
+ FREE(A->data);
+ A->next = set_family_garbage;
+ set_family_garbage = A;
+}
+
+
+/* sf_cleanup -- free all of the set families from the garbage list */
+void sf_cleanup()
+{
+ register pset_family p, pnext;
+ for(p = set_family_garbage; p != (pset_family) NULL; p = pnext) {
+ pnext = p->next;
+ FREE(p);
+ }
+ set_family_garbage = (pset_family) NULL;
+}
+
+
+/* sf_addset -- add a set to the end of a set family */
+pset_family sf_addset(A, s)
+pset_family A;
+pset s;
+{
+ register pset p;
+
+ if (A->count >= A->capacity) {
+ A->capacity = A->capacity + A->capacity/2 + 1;
+ A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize);
+ }
+ p = GETSET(A, A->count++);
+ INLINEset_copy(p, s);
+ return A;
+}
+
+/* sf_delset -- delete a set from a set family */
+void sf_delset(A, i)
+pset_family A;
+int i;
+{ (void) set_copy(GETSET(A,i), GETSET(A, --A->count));}
+
+/* sf_print -- print a set_family as a set (list the element numbers) */
+void sf_print(A)
+pset_family A;
+{
+ char *ps1();
+ register pset p;
+ register int i;
+ foreachi_set(A, i, p)
+ printf("A[%d] = %s\n", i, ps1(p));
+}
+
+/* sf_bm_print -- print a set_family as a bit-matrix */
+void sf_bm_print(A)
+pset_family A;
+{
+ char *pbv1();
+ register pset p;
+ register int i;
+ foreachi_set(A, i, p)
+ printf("[%4d] %s\n", i, pbv1(p, A->sf_size));
+}
+
+
+/* sf_write -- output a set family in an unintelligable manner */
+void sf_write(fp, A)
+FILE *fp;
+pset_family A;
+{
+ register pset p, last;
+ (void) fprintf(fp, "%d %d\n", A->count, A->sf_size);
+ foreach_set(A, last, p)
+ set_write(fp, p);
+ (void) fflush(fp);
+}
+
+
+/* sf_read -- read a set family written by sf_write */
+pset_family sf_read(fp)
+FILE *fp;
+{
+ int i, j;
+ register pset p, last;
+ pset_family A;
+
+ (void) fscanf(fp, "%d %d\n", &i, &j);
+ A = sf_new(i, j);
+ A->count = i;
+ foreach_set(A, last, p) {
+ (void) fscanf(fp, "%x", p);
+ for(j = 1; j <= LOOP(p); j++)
+ (void) fscanf(fp, "%x", p+j);
+ }
+ return A;
+}
+
+
+/* set_write -- output a set in an unintelligable manner */
+void set_write(fp, a)
+register FILE *fp;
+register pset a;
+{
+ register int n = LOOP(a), j;
+
+ for(j = 0; j <= n; j++) {
+ (void) fprintf(fp, "%x ", a[j]);
+ if ((j+1) % 8 == 0 && j != n)
+ (void) fprintf(fp, "\n\t");
+ }
+ (void) fprintf(fp, "\n");
+}
+
+
+/* sf_bm_read -- read a set family written by sf_bm_print (almost) */
+pset_family sf_bm_read(fp)
+FILE *fp;
+{
+ int i, j, rows, cols;
+ register pset pdest;
+ pset_family A;
+
+ (void) fscanf(fp, "%d %d\n", &rows, &cols);
+ A = sf_new(rows, cols);
+ for(i = 0; i < rows; i++) {
+ pdest = GETSET(A, A->count++);
+ (void) set_clear(pdest, A->sf_size);
+ for(j = 0; j < cols; j++) {
+ switch(getc(fp)) {
+ case '0':
+ break;
+ case '1':
+ set_insert(pdest, j);
+ break;
+ default:
+ fatal("Error reading set family");
+ }
+ }
+ if (getc(fp) != '\n') {
+ fatal("Error reading set family (at end of line)");
+ }
+ }
+ return A;
+}
+
+
+
+/* ps1 -- convert a set into a printable string */
+#define largest_string 120
+static char s1[largest_string];
+char *ps1(a)
+register pset a;
+{
+ register int i, num, l, len = 0, n = NELEM(a);
+ char temp[20];
+ bool first = TRUE;
+
+ s1[len++] = '[';
+ for(i = 0; i < n; i++)
+ if (is_in_set(a,i)) {
+ if (! first)
+ s1[len++] = ',';
+ first = FALSE; num = i;
+ /* Generate digits (reverse order) */
+ l = 0; do temp[l++] = num % 10 + '0'; while ((num /= 10) > 0);
+ /* Copy them back in correct order */
+ do s1[len++] = temp[--l]; while (l > 0);
+ if (len > largest_string-15) {
+ s1[len++] = '.'; s1[len++] = '.'; s1[len++] = '.';
+ break;
+ }
+ }
+
+ s1[len++] = ']';
+ s1[len++] = '\0';
+ return s1;
+}
+
+/* pbv1 -- print bit-vector */
+char *pbv1(s, n)
+pset s;
+int n;
+{
+ register int i;
+ for(i = 0; i < n; i++)
+ s1[i] = is_in_set(s,i) ? '1' : '0';
+ s1[n] = '\0';
+ return s1;
+}
+
+
+/* set_adjcnt -- adjust the counts for a set by "weight" */
+void
+set_adjcnt(a, count, weight)
+register pset a;
+register int *count, weight;
+{
+ register int i, base;
+ register unsigned int val;
+
+ for(i = LOOP(a); i > 0; ) {
+ for(val = a[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) {
+ if (val & 1) {
+ count[base] += weight;
+ }
+ }
+ }
+}
+
+
+
+/* sf_count -- perform a column sum over a set family */
+int *sf_count(A)
+pset_family A;
+{
+ register pset p, last;
+ register int i, base, *count;
+ register unsigned int val;
+
+ count = ALLOC(int, A->sf_size);
+ for(i = A->sf_size - 1; i >= 0; i--) {
+ count[i] = 0;
+ }
+
+ foreach_set(A, last, p) {
+ for(i = LOOP(p); i > 0; ) {
+ for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) {
+ if (val & 1) {
+ count[base]++;
+ }
+ }
+ }
+ }
+ return count;
+}
+
+
+/* sf_count_restricted -- perform a column sum over a set family, restricting
+ * to only the columns which are in r; also, the columns are weighted by the
+ * number of elements which are in each row
+ */
+int *sf_count_restricted(A, r)
+pset_family A;
+register pset r;
+{
+ register pset p;
+ register int i, base, *count;
+ register unsigned int val;
+ int weight;
+ pset last;
+
+ count = ALLOC(int, A->sf_size);
+ for(i = A->sf_size - 1; i >= 0; i--) {
+ count[i] = 0;
+ }
+
+ /* Loop for each set */
+ foreach_set(A, last, p) {
+ weight = 1024 / (set_ord(p) - 1);
+ for(i = LOOP(p); i > 0; ) {
+ for(val=p[i]&r[i], base= --i<<LOGBPI; val!=0; base++, val >>= 1) {
+ if (val & 1) {
+ count[base] += weight;
+ }
+ }
+ }
+ }
+ return count;
+}
+
+
+/*
+ * sf_delc -- delete columns first ... last of A
+ */
+pset_family sf_delc(A, first, last)
+pset_family A;
+int first, last;
+{
+ return sf_delcol(A, first, last-first + 1);
+}
+
+
+/*
+ * sf_addcol -- add columns to a set family; includes a quick check to see
+ * if there is already enough room (and hence, can avoid copying)
+ */
+pset_family sf_addcol(A, firstcol, n)
+pset_family A;
+int firstcol, n;
+{
+ int maxsize;
+
+ /* Check if adding columns at the end ... */
+ if (firstcol == A->sf_size) {
+ /* If so, check if there is already enough room */
+ maxsize = BPI * LOOPINIT(A->sf_size);
+ if ((A->sf_size + n) <= maxsize) {
+ A->sf_size += n;
+ return A;
+ }
+ }
+ return sf_delcol(A, firstcol, -n);
+}
+
+/*
+ * sf_delcol -- add/delete columns to/from a set family
+ *
+ * if n > 0 then n columns starting from firstcol are deleted if n < 0
+ * then n blank columns are inserted starting at firstcol
+ * (i.e., the first new column number is firstcol)
+ *
+ * This is done by copying columns in the array which is a relatively
+ * slow operation.
+ */
+pset_family sf_delcol(A, firstcol, n)
+pset_family A;
+register int firstcol, n;
+{
+ register pset p, last, pdest;
+ register int i;
+ pset_family B;
+
+ B = sf_new(A->count, A->sf_size - n);
+ foreach_set(A, last, p) {
+ pdest = GETSET(B, B->count++);
+ INLINEset_clear(pdest, B->sf_size);
+ for(i = 0; i < firstcol; i++)
+ if (is_in_set(p, i))
+ set_insert(pdest, i);
+ for(i = n > 0 ? firstcol + n : firstcol; i < A->sf_size; i++)
+ if (is_in_set(p, i))
+ set_insert(pdest, i - n);
+ }
+ sf_free(A);
+ return B;
+}
+
+
+/*
+ * sf_copy_col -- copy column "srccol" from "src" to column "dstcol" of "dst"
+ */
+pset_family sf_copy_col(dst, dstcol, src, srccol)
+pset_family dst, src;
+int dstcol, srccol;
+{
+ register pset last, p, pdest;
+ register int word_test, word_set;
+ unsigned int bit_set, bit_test;
+
+ /* CHEAT! form these constants outside the loop */
+ word_test = WHICH_WORD(srccol);
+ bit_test = 1 << WHICH_BIT(srccol);
+ word_set = WHICH_WORD(dstcol);
+ bit_set = 1 << WHICH_BIT(dstcol);
+
+ pdest = dst->data;
+ foreach_set(src, last, p) {
+ if ((p[word_test] & bit_test) != 0)
+ pdest[word_set] |= bit_set;
+/*
+ * equivalent code for this is ...
+ * if (is_in_set(p, srccol)) set_insert(pdest, destcol);
+ */
+ pdest += dst->wsize;
+ }
+ return dst;
+}
+
+
+
+/*
+ * sf_compress -- delete columns from a matrix
+ */
+pset_family sf_compress(A, c)
+pset_family A; /* will be freed */
+register pset c;
+{
+ register pset p;
+ register int i, bcol;
+ pset_family B;
+
+ /* create a clean set family for the result */
+ B = sf_new(A->count, set_ord(c));
+ for(i = 0; i < A->count; i++) {
+ p = GETSET(B, B->count++);
+ INLINEset_clear(p, B->sf_size);
+ }
+
+ /* copy each column of A which has a 1 in c */
+ bcol = 0;
+ for(i = 0; i < A->sf_size; i++) {
+ if (is_in_set(c, i)) {
+ (void) sf_copy_col(B, bcol++, A, i);
+ }
+ }
+ sf_free(A);
+ return B;
+}
+
+
+
+/*
+ * sf_transpose -- transpose a bit matrix
+ *
+ * There are trickier ways of doing this, but this works.
+ */
+pset_family sf_transpose(A)
+pset_family A;
+{
+ pset_family B;
+ register pset p;
+ register int i, j;
+
+ B = sf_new(A->sf_size, A->count);
+ B->count = A->sf_size;
+ foreachi_set(B, i, p) {
+ INLINEset_clear(p, B->sf_size);
+ }
+ foreachi_set(A, i, p) {
+ for(j = 0; j < A->sf_size; j++) {
+ if (is_in_set(p, j)) {
+ set_insert(GETSET(B, j), i);
+ }
+ }
+ }
+ sf_free(A);
+ return B;
+}
+
+
+/*
+ * sf_permute -- permute the columns of a set_family
+ *
+ * permute is an array of integers containing column numbers of A which
+ * are to be retained.
+ */
+pset_family sf_permute(A, permute, npermute)
+pset_family A;
+register int *permute, npermute;
+{
+ pset_family B;
+ register pset p, last, pdest;
+ register int j;
+
+ B = sf_new(A->count, npermute);
+ B->count = A->count;
+ foreach_set(B, last, p)
+ INLINEset_clear(p, npermute);
+
+ pdest = B->data;
+ foreach_set(A, last, p) {
+ for(j = 0; j < npermute; j++)
+ if (is_in_set(p, permute[j]))
+ set_insert(pdest, j);
+ pdest += B->wsize;
+ }
+ sf_free(A);
+ return B;
+}
diff --git a/src/misc/espresso/setc.c b/src/misc/espresso/setc.c
new file mode 100644
index 00000000..a6112ebc
--- /dev/null
+++ b/src/misc/espresso/setc.c
@@ -0,0 +1,483 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ setc.c -- massive bit-hacking for performing special "cube"-type
+ operations on a set
+
+ The basic trick used for binary valued variables is the following:
+
+ If a[w] and b[w] contain a full word of binary variables, then:
+
+ 1) to get the full word of their intersection, we use
+
+ x = a[w] & b[w];
+
+
+ 2) to see if the intersection is null in any variables, we examine
+
+ x = ~(x | x >> 1) & DISJOINT;
+
+ this will have a single 1 in each binary variable for which
+ the intersection is null. In particular, if this is zero,
+ then there are no disjoint variables; or, if this is nonzero,
+ then there is at least one disjoint variable. A "count_ones"
+ over x will tell in how many variables they have an null
+ intersection.
+
+
+ 3) to get a mask which selects the disjoint variables, we use
+
+ (x | x << 1)
+
+ this provides a selector which can be used to see where
+ they have an null intersection
+
+
+ cdist return distance between two cubes
+ cdist0 return true if two cubes are distance 0 apart
+ cdist01 return distance, or 2 if distance exceeds 1
+ consensus compute consensus of two cubes distance 1 apart
+ force_lower expand hack (for now), related to consensus
+*/
+
+#include "espresso.h"
+
+/* see if the cube has a full row of 1's (with respect to cof) */
+bool full_row(p, cof)
+IN register pcube p, cof;
+{
+ register int i = LOOP(p);
+ do if ((p[i] | cof[i]) != cube.fullset[i]) return FALSE; while (--i > 0);
+ return TRUE;
+}
+
+/*
+ cdist0 -- return TRUE if a and b are distance 0 apart
+*/
+
+bool cdist0(a, b)
+register pcube a, b;
+{
+ { /* Check binary variables */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] & b[last];
+ if (~(x | x >> 1) & cube.inmask)
+ return FALSE; /* disjoint in some variable */
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] & b[w];
+ if (~(x | x >> 1) & DISJOINT)
+ return FALSE; /* disjoint in some variable */
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (a[w] & b[w] & mask[w])
+ goto nextvar;
+ return FALSE; /* disjoint in this variable */
+ nextvar: ;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ cdist01 -- return the "distance" between two cubes (defined as the
+ number of null variables in their intersection). If the distance
+ exceeds 1, the value 2 is returned.
+*/
+
+int cdist01(a, b)
+register pset a, b;
+{
+ int dist = 0;
+
+ { /* Check binary variables */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] & b[last];
+ if (x = ~ (x | x >> 1) & cube.inmask)
+ if ((dist = count_ones(x)) > 1)
+ return 2;
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] & b[w];
+ if (x = ~ (x | x >> 1) & DISJOINT)
+ if (dist == 1 || (dist += count_ones(x)) > 1)
+ return 2;
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (a[w] & b[w] & mask[w])
+ goto nextvar;
+ if (++dist > 1)
+ return 2;
+ nextvar: ;
+ }
+ }
+ return dist;
+}
+
+/*
+ cdist -- return the "distance" between two cubes (defined as the
+ number of null variables in their intersection).
+*/
+
+int cdist(a, b)
+register pset a, b;
+{
+ int dist = 0;
+
+ { /* Check binary variables */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] & b[last];
+ if (x = ~ (x | x >> 1) & cube.inmask)
+ dist = count_ones(x);
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] & b[w];
+ if (x = ~ (x | x >> 1) & DISJOINT)
+ dist += count_ones(x);
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (a[w] & b[w] & mask[w])
+ goto nextvar;
+ dist++;
+ nextvar: ;
+ }
+ }
+ return dist;
+}
+
+/*
+ force_lower -- Determine which variables of a do not intersect b.
+*/
+
+pset force_lower(xlower, a, b)
+INOUT pset xlower;
+IN register pset a, b;
+{
+
+ { /* Check binary variables (if any) */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] & b[last];
+ if (x = ~(x | x >> 1) & cube.inmask)
+ xlower[last] |= (x | (x << 1)) & a[last];
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] & b[w];
+ if (x = ~(x | x >> 1) & DISJOINT)
+ xlower[w] |= (x | (x << 1)) & a[w];
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (a[w] & b[w] & mask[w])
+ goto nextvar;
+ for(w = cube.first_word[var]; w <= last; w++)
+ xlower[w] |= a[w] & mask[w];
+ nextvar: ;
+ }
+ }
+ return xlower;
+}
+
+/*
+ consensus -- multiple-valued consensus
+
+ Although this looks very messy, the idea is to compute for r the
+ "and" of the cubes a and b for each variable, unless the "and" is
+ null in a variable, in which case the "or" of a and b is computed
+ for this variable.
+
+ Because we don't check how many variables are null in the
+ intersection of a and b, the returned value for r really only
+ represents the consensus when a and b are distance 1 apart.
+*/
+
+void consensus(r, a, b)
+INOUT pcube r;
+IN register pcube a, b;
+{
+ INLINEset_clear(r, cube.size);
+
+ { /* Check binary variables (if any) */
+ register int w, last; register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ r[last] = x = a[last] & b[last];
+ if (x = ~(x | x >> 1) & cube.inmask)
+ r[last] |= (x | (x << 1)) & (a[last] | b[last]);
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ r[w] = x = a[w] & b[w];
+ if (x = ~(x | x >> 1) & DISJOINT)
+ r[w] |= (x | (x << 1)) & (a[w] | b[w]);
+ }
+ }
+ }
+
+
+ { /* Check the multiple-valued variables */
+ bool empty; int var; unsigned int x;
+ register int w, last; register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var];
+ last = cube.last_word[var];
+ empty = TRUE;
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (x = a[w] & b[w] & mask[w])
+ empty = FALSE, r[w] |= x;
+ if (empty)
+ for(w = cube.first_word[var]; w <= last; w++)
+ r[w] |= mask[w] & (a[w] | b[w]);
+ }
+ }
+}
+
+/*
+ cactive -- return the index of the single active variable in
+ the cube, or return -1 if there are none or more than 2.
+*/
+
+int cactive(a)
+register pcube a;
+{
+ int active = -1, dist = 0, bit_index();
+
+ { /* Check binary variables */
+ register int w, last;
+ register unsigned int x;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last];
+ if (x = ~ (x & x >> 1) & cube.inmask) {
+ if ((dist = count_ones(x)) > 1)
+ return -1; /* more than 2 active variables */
+ active = (last-1)*(BPI/2) + bit_index(x) / 2;
+ }
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w];
+ if (x = ~ (x & x >> 1) & DISJOINT) {
+ if ((dist += count_ones(x)) > 1)
+ return -1; /* more than 2 active variables */
+ active = (w-1)*(BPI/2) + bit_index(x) / 2;
+ }
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ register int w, var, last;
+ register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var];
+ last = cube.last_word[var];
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (mask[w] & ~ a[w]) {
+ if (++dist > 1)
+ return -1;
+ active = var;
+ break;
+ }
+ }
+ }
+ return active;
+}
+
+/*
+ ccommon -- return TRUE if a and b are share "active" variables
+ active variables include variables that are empty;
+*/
+
+bool ccommon(a, b, cof)
+register pcube a, b, cof;
+{
+ { /* Check binary variables */
+ int last;
+ register int w;
+ register unsigned int x, y;
+ if ((last = cube.inword) != -1) {
+
+ /* Check the partial word of binary variables */
+ x = a[last] | cof[last];
+ y = b[last] | cof[last];
+ if (~(x & x>>1) & ~(y & y>>1) & cube.inmask)
+ return TRUE;
+
+ /* Check the full words of binary variables */
+ for(w = 1; w < last; w++) {
+ x = a[w] | cof[w];
+ y = b[w] | cof[w];
+ if (~(x & x>>1) & ~(y & y>>1) & DISJOINT)
+ return TRUE;
+ }
+ }
+ }
+
+ { /* Check the multiple-valued variables */
+ int var;
+ register int w, last;
+ register pcube mask;
+ for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ mask = cube.var_mask[var]; last = cube.last_word[var];
+ /* Check for some part missing from a */
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (mask[w] & ~a[w] & ~cof[w]) {
+
+ /* If so, check for some part missing from b */
+ for(w = cube.first_word[var]; w <= last; w++)
+ if (mask[w] & ~b[w] & ~cof[w])
+ return TRUE; /* both active */
+ break;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*
+ These routines compare two sets (cubes) for the qsort() routine and
+ return:
+
+ -1 if set a is to precede set b
+ 0 if set a and set b are equal
+ 1 if set a is to follow set b
+
+ Usually the SIZE field of the set is assumed to contain the size
+ of the set (which will save recomputing the set size during the
+ sort). For distance-1 merging, the global variable cube.temp[0] is
+ a mask which mask's-out the merging variable.
+*/
+
+/* descend -- comparison for descending sort on set size */
+int descend(a, b)
+pset *a, *b;
+{
+ register pset a1 = *a, b1 = *b;
+ if (SIZE(a1) > SIZE(b1)) return -1;
+ else if (SIZE(a1) < SIZE(b1)) return 1;
+ else {
+ register int i = LOOP(a1);
+ do
+ if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1;
+ while (--i > 0);
+ }
+ return 0;
+}
+
+/* ascend -- comparison for ascending sort on set size */
+int ascend(a, b)
+pset *a, *b;
+{
+ register pset a1 = *a, b1 = *b;
+ if (SIZE(a1) > SIZE(b1)) return 1;
+ else if (SIZE(a1) < SIZE(b1)) return -1;
+ else {
+ register int i = LOOP(a1);
+ do
+ if (a1[i] > b1[i]) return 1; else if (a1[i] < b1[i]) return -1;
+ while (--i > 0);
+ }
+ return 0;
+}
+
+
+/* lex_order -- comparison for "lexical" ordering of cubes */
+int lex_order(a, b)
+pset *a, *b;
+{
+ register pset a1 = *a, b1 = *b;
+ register int i = LOOP(a1);
+ do
+ if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1;
+ while (--i > 0);
+ return 0;
+}
+
+
+/* d1_order -- comparison for distance-1 merge routine */
+int d1_order(a, b)
+pset *a, *b;
+{
+ register pset a1 = *a, b1 = *b, c1 = cube.temp[0];
+ register int i = LOOP(a1);
+ register unsigned int x1, x2;
+ do
+ if ((x1 = a1[i] | c1[i]) > (x2 = b1[i] | c1[i])) return -1;
+ else if (x1 < x2) return 1;
+ while (--i > 0);
+ return 0;
+}
+
+
+/* desc1 -- comparison (without indirection) for descending sort */
+/* also has effect of handling NULL pointers,and a NULL pointer has smallest
+order */
+int desc1(a, b)
+register pset a, b;
+{
+ if (a == (pset) NULL)
+ return (b == (pset) NULL) ? 0 : 1;
+ else if (b == (pset) NULL)
+ return -1;
+ if (SIZE(a) > SIZE(b)) return -1;
+ else if (SIZE(a) < SIZE(b)) return 1;
+ else {
+ register int i = LOOP(a);
+ do
+ if (a[i] > b[i]) return -1; else if (a[i] < b[i]) return 1;
+ while (--i > 0);
+ }
+ return 0;
+}
diff --git a/src/misc/espresso/sharp.c b/src/misc/espresso/sharp.c
new file mode 100644
index 00000000..53435078
--- /dev/null
+++ b/src/misc/espresso/sharp.c
@@ -0,0 +1,247 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ sharp.c -- perform sharp, disjoint sharp, and intersection
+*/
+
+#include "espresso.h"
+
+long start_time;
+
+
+/* cv_sharp -- form the sharp product between two covers */
+pcover cv_sharp(A, B)
+pcover A, B;
+{
+ pcube last, p;
+ pcover T;
+
+ T = new_cover(0);
+ foreach_set(A, last, p)
+ T = sf_union(T, cb_sharp(p, B));
+ return T;
+}
+
+
+/* cb_sharp -- form the sharp product between a cube and a cover */
+pcover cb_sharp(c, T)
+pcube c;
+pcover T;
+{
+ if (T->count == 0) {
+ T = sf_addset(new_cover(1), c);
+ } else {
+ start_time = ptime();
+ T = cb_recur_sharp(c, T, 0, T->count-1, 0);
+ }
+ return T;
+}
+
+
+/* recursive formulation to provide balanced merging */
+pcover cb_recur_sharp(c, T, first, last, level)
+pcube c;
+pcover T;
+int first, last, level;
+{
+ pcover temp, left, right;
+ int middle;
+
+ if (first == last) {
+ temp = sharp(c, GETSET(T, first));
+ } else {
+ middle = (first + last) / 2;
+ left = cb_recur_sharp(c, T, first, middle, level+1);
+ right = cb_recur_sharp(c, T, middle+1, last, level+1);
+ temp = cv_intersect(left, right);
+ if ((debug & SHARP) && level < 4) {
+ printf("# SHARP[%d]: %4d = %4d x %4d, time = %s\n",
+ level, temp->count, left->count, right->count,
+ print_time(ptime() - start_time));
+ (void) fflush(stdout);
+ }
+ free_cover(left);
+ free_cover(right);
+ }
+ return temp;
+}
+
+
+/* sharp -- form the sharp product between two cubes */
+pcover sharp(a, b)
+pcube a, b;
+{
+ register int var;
+ register pcube d=cube.temp[0], temp=cube.temp[1], temp1=cube.temp[2];
+ pcover r = new_cover(cube.num_vars);
+
+ if (cdist0(a, b)) {
+ set_diff(d, a, b);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (! setp_empty(set_and(temp, d, cube.var_mask[var]))) {
+ set_diff(temp1, a, cube.var_mask[var]);
+ set_or(GETSET(r, r->count++), temp, temp1);
+ }
+ }
+ } else {
+ r = sf_addset(r, a);
+ }
+ return r;
+}
+
+pcover make_disjoint(A)
+pcover A;
+{
+ pcover R, new;
+ register pset last, p;
+
+ R = new_cover(0);
+ foreach_set(A, last, p) {
+ new = cb_dsharp(p, R);
+ R = sf_append(R, new);
+ }
+ return R;
+}
+
+
+/* cv_dsharp -- disjoint-sharp product between two covers */
+pcover cv_dsharp(A, B)
+pcover A, B;
+{
+ register pcube last, p;
+ pcover T;
+
+ T = new_cover(0);
+ foreach_set(A, last, p) {
+ T = sf_union(T, cb_dsharp(p, B));
+ }
+ return T;
+}
+
+
+/* cb1_dsharp -- disjoint-sharp product between a cover and a cube */
+pcover cb1_dsharp(T, c)
+pcover T;
+pcube c;
+{
+ pcube last, p;
+ pcover R;
+
+ R = new_cover(T->count);
+ foreach_set(T, last, p) {
+ R = sf_union(R, dsharp(p, c));
+ }
+ return R;
+}
+
+
+/* cb_dsharp -- disjoint-sharp product between a cube and a cover */
+pcover cb_dsharp(c, T)
+pcube c;
+pcover T;
+{
+ pcube last, p;
+ pcover Y, Y1;
+
+ if (T->count == 0) {
+ Y = sf_addset(new_cover(1), c);
+ } else {
+ Y = new_cover(T->count);
+ set_copy(GETSET(Y,Y->count++), c);
+ foreach_set(T, last, p) {
+ Y1 = cb1_dsharp(Y, p);
+ free_cover(Y);
+ Y = Y1;
+ }
+ }
+ return Y;
+}
+
+
+/* dsharp -- form the disjoint-sharp product between two cubes */
+pcover dsharp(a, b)
+pcube a, b;
+{
+ register pcube mask, diff, and, temp, temp1 = cube.temp[0];
+ int var;
+ pcover r;
+
+ r = new_cover(cube.num_vars);
+
+ if (cdist0(a, b)) {
+ diff = set_diff(new_cube(), a, b);
+ and = set_and(new_cube(), a, b);
+ mask = new_cube();
+ for(var = 0; var < cube.num_vars; var++) {
+ /* check if position var of "a and not b" is not empty */
+ if (! setp_disjoint(diff, cube.var_mask[var])) {
+
+ /* coordinate var equals the difference between a and b */
+ temp = GETSET(r, r->count++);
+ (void) set_and(temp, diff, cube.var_mask[var]);
+
+ /* coordinates 0 ... var-1 equal the intersection */
+ INLINEset_and(temp1, and, mask);
+ INLINEset_or(temp, temp, temp1);
+
+ /* coordinates var+1 .. cube.num_vars equal a */
+ set_or(mask, mask, cube.var_mask[var]);
+ INLINEset_diff(temp1, a, mask);
+ INLINEset_or(temp, temp, temp1);
+ }
+ }
+ free_cube(diff);
+ free_cube(and);
+ free_cube(mask);
+ } else {
+ r = sf_addset(r, a);
+ }
+ return r;
+}
+
+/* cv_intersect -- form the intersection of two covers */
+
+#define MAGIC 500 /* save 500 cubes before containment */
+
+pcover cv_intersect(A, B)
+pcover A, B;
+{
+ register pcube pi, pj, lasti, lastj, pt;
+ pcover T, Tsave = NULL;
+
+ /* How large should each temporary result cover be ? */
+ T = new_cover(MAGIC);
+ pt = T->data;
+
+ /* Form pairwise intersection of each cube of A with each cube of B */
+ foreach_set(A, lasti, pi) {
+ foreach_set(B, lastj, pj) {
+ if (cdist0(pi, pj)) {
+ (void) set_and(pt, pi, pj);
+ if (++T->count >= T->capacity) {
+ if (Tsave == NULL)
+ Tsave = sf_contain(T);
+ else
+ Tsave = sf_union(Tsave, sf_contain(T));
+ T = new_cover(MAGIC);
+ pt = T->data;
+ } else
+ pt += T->wsize;
+ }
+ }
+ }
+
+
+ if (Tsave == NULL)
+ Tsave = sf_contain(T);
+ else
+ Tsave = sf_union(Tsave, sf_contain(T));
+ return Tsave;
+}
diff --git a/src/misc/espresso/sminterf.c b/src/misc/espresso/sminterf.c
new file mode 100644
index 00000000..50a6db4e
--- /dev/null
+++ b/src/misc/espresso/sminterf.c
@@ -0,0 +1,44 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "espresso.h"
+
+
+pset
+do_sm_minimum_cover(A)
+pset_family A;
+{
+ sm_matrix *M;
+ sm_row *sparse_cover;
+ sm_element *pe;
+ pset cover;
+ register int i, base, rownum;
+ register unsigned val;
+ register pset last, p;
+
+ M = sm_alloc();
+ rownum = 0;
+ foreach_set(A, last, p) {
+ foreach_set_element(p, i, val, base) {
+ (void) sm_insert(M, rownum, base);
+ }
+ rownum++;
+ }
+
+ sparse_cover = sm_minimum_cover(M, NIL(int), 1, 0);
+ sm_free(M);
+
+ cover = set_new(A->sf_size);
+ sm_foreach_row_element(sparse_cover, pe) {
+ set_insert(cover, pe->col_num);
+ }
+ sm_row_free(sparse_cover);
+
+ return cover;
+}
diff --git a/src/misc/espresso/solution.c b/src/misc/espresso/solution.c
new file mode 100644
index 00000000..26119185
--- /dev/null
+++ b/src/misc/espresso/solution.c
@@ -0,0 +1,114 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#include "mincov_int.h"
+
+
+solution_t *
+solution_alloc()
+{
+ solution_t *sol;
+
+ sol = ALLOC(solution_t, 1);
+ sol->cost = 0;
+ sol->row = sm_row_alloc();
+ return sol;
+}
+
+
+void
+solution_free(sol)
+solution_t *sol;
+{
+ sm_row_free(sol->row);
+ FREE(sol);
+}
+
+
+solution_t *
+solution_dup(sol)
+solution_t *sol;
+{
+ solution_t *new_sol;
+
+ new_sol = ALLOC(solution_t, 1);
+ new_sol->cost = sol->cost;
+ new_sol->row = sm_row_dup(sol->row);
+ return new_sol;
+}
+
+
+void
+solution_add(sol, weight, col)
+solution_t *sol;
+int *weight;
+int col;
+{
+ (void) sm_row_insert(sol->row, col);
+ sol->cost += WEIGHT(weight, col);
+}
+
+
+void
+solution_accept(sol, A, weight, col)
+solution_t *sol;
+sm_matrix *A;
+int *weight;
+int col;
+{
+ register sm_element *p, *pnext;
+ sm_col *pcol;
+
+ solution_add(sol, weight, col);
+
+ /* delete rows covered by this column */
+ pcol = sm_get_col(A, col);
+ for(p = pcol->first_row; p != 0; p = pnext) {
+ pnext = p->next_row; /* grab it before it disappears */
+ sm_delrow(A, p->row_num);
+ }
+}
+
+
+/* ARGSUSED */
+void
+solution_reject(sol, A, weight, col)
+solution_t *sol;
+sm_matrix *A;
+int *weight;
+int col;
+{
+ sm_delcol(A, col);
+}
+
+
+solution_t *
+solution_choose_best(best1, best2)
+solution_t *best1, *best2;
+{
+ if (best1 != NIL(solution_t)) {
+ if (best2 != NIL(solution_t)) {
+ if (best1->cost <= best2->cost) {
+ solution_free(best2);
+ return best1;
+ } else {
+ solution_free(best1);
+ return best2;
+ }
+ } else {
+ return best1;
+ }
+ } else {
+ if (best2 != NIL(solution_t)) {
+ return best2;
+ } else {
+ return NIL(solution_t);
+ }
+ }
+}
diff --git a/src/misc/espresso/sparse.c b/src/misc/espresso/sparse.c
new file mode 100644
index 00000000..137ce7c1
--- /dev/null
+++ b/src/misc/espresso/sparse.c
@@ -0,0 +1,146 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ module: sparse.c
+
+ make_sparse is a last-step cleanup to reduce the total number
+ of literals in the cover.
+
+ This is done by reducing the "sparse" variables (using a modified
+ version of irredundant rather than reduce), followed by expanding
+ the "dense" variables (using modified version of expand).
+*/
+
+#include "espresso.h"
+
+pcover make_sparse(F, D, R)
+pcover F, D, R;
+{
+ cost_t cost, best_cost;
+
+ cover_cost(F, &best_cost);
+
+ do {
+ EXECUTE(F = mv_reduce(F, D), MV_REDUCE_TIME, F, cost);
+ if (cost.total == best_cost.total)
+ break;
+ copy_cost(&cost, &best_cost);
+
+ EXECUTE(F = expand(F, R, TRUE), RAISE_IN_TIME, F, cost);
+ if (cost.total == best_cost.total)
+ break;
+ copy_cost(&cost, &best_cost);
+ } while (force_irredundant);
+
+ return F;
+}
+
+/*
+ mv_reduce -- perform an "optimal" reduction of the variables which
+ we desire to be sparse
+
+ This could be done using "reduce" and then saving just the desired
+ part of the reduction. Instead, this version uses IRRED to find
+ which cubes of an output are redundant. Note that this gets around
+ the cube-ordering problem.
+
+ In normal use, it is expected that the cover is irredundant and
+ hence no cubes will be reduced to the empty cube (however, this is
+ checked for and such cubes will be deleted)
+*/
+
+pcover
+mv_reduce(F, D)
+pcover F, D;
+{
+ register int i, var;
+ register pcube p, p1, last;
+ int index;
+ pcover F1, D1;
+ pcube *F_cube_table;
+
+ /* loop for each multiple-valued variable */
+ for(var = 0; var < cube.num_vars; var++) {
+
+ if (cube.sparse[var]) {
+
+ /* loop for each part of the variable */
+ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+
+ /* remember mapping of F1 cubes back to F cubes */
+ F_cube_table = ALLOC(pcube, F->count);
+
+ /* 'cofactor' against part #i of variable #var */
+ F1 = new_cover(F->count);
+ foreach_set(F, last, p) {
+ if (is_in_set(p, i)) {
+ F_cube_table[F1->count] = p;
+ p1 = GETSET(F1, F1->count++);
+ (void) set_diff(p1, p, cube.var_mask[var]);
+ set_insert(p1, i);
+ }
+ }
+
+ /* 'cofactor' against part #i of variable #var */
+ /* not really necessary -- just more efficient ? */
+ D1 = new_cover(D->count);
+ foreach_set(D, last, p) {
+ if (is_in_set(p, i)) {
+ p1 = GETSET(D1, D1->count++);
+ (void) set_diff(p1, p, cube.var_mask[var]);
+ set_insert(p1, i);
+ }
+ }
+
+ mark_irredundant(F1, D1);
+
+ /* now remove part i from cubes which are redundant */
+ index = 0;
+ foreach_set(F1, last, p1) {
+ if (! TESTP(p1, ACTIVE)) {
+ p = F_cube_table[index];
+
+ /* don't reduce a variable which is full
+ * (unless it is the output variable)
+ */
+ if (var == cube.num_vars-1 ||
+ ! setp_implies(cube.var_mask[var], p)) {
+ set_remove(p, i);
+ }
+ RESET(p, PRIME);
+ }
+ index++;
+ }
+
+ free_cover(F1);
+ free_cover(D1);
+ FREE(F_cube_table);
+ }
+ }
+ }
+
+ /* Check if any cubes disappeared */
+ (void) sf_active(F);
+ for(var = 0; var < cube.num_vars; var++) {
+ if (cube.sparse[var]) {
+ foreach_active_set(F, last, p) {
+ if (setp_disjoint(p, cube.var_mask[var])) {
+ RESET(p, ACTIVE);
+ F->active_count--;
+ }
+ }
+ }
+ }
+
+ if (F->count != F->active_count) {
+ F = sf_inactive(F);
+ }
+ return F;
+}
diff --git a/src/misc/espresso/sparse.h b/src/misc/espresso/sparse.h
new file mode 100644
index 00000000..212a32ed
--- /dev/null
+++ b/src/misc/espresso/sparse.h
@@ -0,0 +1,135 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+#ifndef SPARSE_H
+#define SPARSE_H
+
+/*
+ * sparse.h -- sparse matrix package header file
+ */
+
+typedef struct sm_element_struct sm_element;
+typedef struct sm_row_struct sm_row;
+typedef struct sm_col_struct sm_col;
+typedef struct sm_matrix_struct sm_matrix;
+
+
+/*
+ * sparse matrix element
+ */
+struct sm_element_struct {
+ int row_num; /* row number of this element */
+ int col_num; /* column number of this element */
+ sm_element *next_row; /* next row in this column */
+ sm_element *prev_row; /* previous row in this column */
+ sm_element *next_col; /* next column in this row */
+ sm_element *prev_col; /* previous column in this row */
+ char *user_word; /* user-defined word */
+};
+
+
+/*
+ * row header
+ */
+struct sm_row_struct {
+ int row_num; /* the row number */
+ int length; /* number of elements in this row */
+ int flag; /* user-defined word */
+ sm_element *first_col; /* first element in this row */
+ sm_element *last_col; /* last element in this row */
+ sm_row *next_row; /* next row (in sm_matrix linked list) */
+ sm_row *prev_row; /* previous row (in sm_matrix linked list) */
+ char *user_word; /* user-defined word */
+};
+
+
+/*
+ * column header
+ */
+struct sm_col_struct {
+ int col_num; /* the column number */
+ int length; /* number of elements in this column */
+ int flag; /* user-defined word */
+ sm_element *first_row; /* first element in this column */
+ sm_element *last_row; /* last element in this column */
+ sm_col *next_col; /* next column (in sm_matrix linked list) */
+ sm_col *prev_col; /* prev column (in sm_matrix linked list) */
+ char *user_word; /* user-defined word */
+};
+
+
+/*
+ * A sparse matrix
+ */
+struct sm_matrix_struct {
+ sm_row **rows; /* pointer to row headers (by row #) */
+ int rows_size; /* alloc'ed size of above array */
+ sm_col **cols; /* pointer to column headers (by col #) */
+ int cols_size; /* alloc'ed size of above array */
+ sm_row *first_row; /* first row (linked list of all rows) */
+ sm_row *last_row; /* last row (linked list of all rows) */
+ int nrows; /* number of rows */
+ sm_col *first_col; /* first column (linked list of columns) */
+ sm_col *last_col; /* last column (linked list of columns) */
+ int ncols; /* number of columns */
+ char *user_word; /* user-defined word */
+};
+
+
+#define sm_get_col(A, colnum) \
+ (((colnum) >= 0 && (colnum) < (A)->cols_size) ? \
+ (A)->cols[colnum] : (sm_col *) 0)
+
+#define sm_get_row(A, rownum) \
+ (((rownum) >= 0 && (rownum) < (A)->rows_size) ? \
+ (A)->rows[rownum] : (sm_row *) 0)
+
+#define sm_foreach_row(A, prow) \
+ for(prow = A->first_row; prow != 0; prow = prow->next_row)
+
+#define sm_foreach_col(A, pcol) \
+ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col)
+
+#define sm_foreach_row_element(prow, p) \
+ for(p = prow->first_col; p != 0; p = p->next_col)
+
+#define sm_foreach_col_element(pcol, p) \
+ for(p = pcol->first_row; p != 0; p = p->next_row)
+
+#define sm_put(x, val) \
+ (x->user_word = (char *) val)
+
+#define sm_get(type, x) \
+ ((type) (x->user_word))
+
+extern sm_matrix *sm_alloc(), *sm_alloc_size(), *sm_dup();
+extern void sm_free(), sm_delrow(), sm_delcol(), sm_resize();
+extern void sm_write(), sm_print(), sm_dump(), sm_cleanup();
+extern void sm_copy_row(), sm_copy_col();
+extern void sm_remove(), sm_remove_element();
+extern sm_element *sm_insert(), *sm_find();
+extern sm_row *sm_longest_row();
+extern sm_col *sm_longest_col();
+extern int sm_read(), sm_read_compressed();
+
+extern sm_row *sm_row_alloc(), *sm_row_dup(), *sm_row_and();
+extern void sm_row_free(), sm_row_remove(), sm_row_print();
+extern sm_element *sm_row_insert(), *sm_row_find();
+extern int sm_row_contains(), sm_row_intersects();
+extern int sm_row_compare(), sm_row_hash();
+
+extern sm_col *sm_col_alloc(), *sm_col_dup(), *sm_col_and();
+extern void sm_col_free(), sm_col_remove(), sm_col_print();
+extern sm_element *sm_col_insert(), *sm_col_find();
+extern int sm_col_contains(), sm_col_intersects();
+extern int sm_col_compare(), sm_col_hash();
+
+extern int sm_row_dominance(), sm_col_dominance(), sm_block_partition();
+
+#endif
diff --git a/src/misc/espresso/sparse_int.h b/src/misc/espresso/sparse_int.h
new file mode 100644
index 00000000..49b2509a
--- /dev/null
+++ b/src/misc/espresso/sparse_int.h
@@ -0,0 +1,121 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+//#include "port.h"
+//#include "utility.h"
+#include "sparse.h"
+
+#include "util_hack.h" // added
+
+
+
+/*
+ * sorted, double-linked list insertion
+ *
+ * type: object type
+ *
+ * first, last: fields (in header) to head and tail of the list
+ * count: field (in header) of length of the list
+ *
+ * next, prev: fields (in object) to link next and previous objects
+ * value: field (in object) which controls the order
+ *
+ * newval: value field for new object
+ * e: an object to use if insertion needed (set to actual value used)
+ */
+
+#define sorted_insert(type, first, last, count, next, prev, value, newval, e) \
+ if (last == 0) { \
+ e->value = newval; \
+ first = e; \
+ last = e; \
+ e->next = 0; \
+ e->prev = 0; \
+ count++; \
+ } else if (last->value < newval) { \
+ e->value = newval; \
+ last->next = e; \
+ e->prev = last; \
+ last = e; \
+ e->next = 0; \
+ count++; \
+ } else if (first->value > newval) { \
+ e->value = newval; \
+ first->prev = e; \
+ e->next = first; \
+ first = e; \
+ e->prev = 0; \
+ count++; \
+ } else { \
+ type *p; \
+ for(p = first; p->value < newval; p = p->next) \
+ ; \
+ if (p->value > newval) { \
+ e->value = newval; \
+ p = p->prev; \
+ p->next->prev = e; \
+ e->next = p->next; \
+ p->next = e; \
+ e->prev = p; \
+ count++; \
+ } else { \
+ e = p; \
+ } \
+ }
+
+
+/*
+ * double linked-list deletion
+ */
+#define dll_unlink(p, first, last, next, prev, count) { \
+ if (p->prev == 0) { \
+ first = p->next; \
+ } else { \
+ p->prev->next = p->next; \
+ } \
+ if (p->next == 0) { \
+ last = p->prev; \
+ } else { \
+ p->next->prev = p->prev; \
+ } \
+ count--; \
+}
+
+
+#ifdef FAST_AND_LOOSE
+extern sm_element *sm_element_freelist;
+extern sm_row *sm_row_freelist;
+extern sm_col *sm_col_freelist;
+
+#define sm_element_alloc(newobj) \
+ if (sm_element_freelist == NIL(sm_element)) { \
+ newobj = ALLOC(sm_element, 1); \
+ } else { \
+ newobj = sm_element_freelist; \
+ sm_element_freelist = sm_element_freelist->next_col; \
+ } \
+ newobj->user_word = NIL(char); \
+
+#define sm_element_free(e) \
+ (e->next_col = sm_element_freelist, sm_element_freelist = e)
+
+#else
+
+#define sm_element_alloc(newobj) \
+ newobj = ALLOC(sm_element, 1); \
+ newobj->user_word = NIL(char);
+#define sm_element_free(e) \
+ FREE(e)
+#endif
+
+
+extern void sm_row_remove_element();
+extern void sm_col_remove_element();
+
+/* LINTLIBRARY */
diff --git a/src/misc/espresso/unate.c b/src/misc/espresso/unate.c
new file mode 100644
index 00000000..bd71207f
--- /dev/null
+++ b/src/misc/espresso/unate.c
@@ -0,0 +1,441 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ * unate.c -- routines for dealing with unate functions
+ */
+
+#include "espresso.h"
+
+static pset_family abs_covered();
+static pset_family abs_covered_many();
+static int abs_select_restricted();
+
+pcover map_cover_to_unate(T)
+pcube *T;
+{
+ register unsigned int word_test, word_set, bit_test, bit_set;
+ register pcube p, pA;
+ pset_family A;
+ pcube *T1;
+ int ncol, i;
+
+ A = sf_new(CUBELISTSIZE(T), cdata.vars_unate);
+ A->count = CUBELISTSIZE(T);
+ foreachi_set(A, i, p) {
+ (void) set_clear(p, A->sf_size);
+ }
+ ncol = 0;
+
+ for(i = 0; i < cube.size; i++) {
+ if (cdata.part_zeros[i] > 0) {
+ assert(ncol <= cdata.vars_unate);
+
+ /* Copy a column from T to A */
+ word_test = WHICH_WORD(i);
+ bit_test = 1 << WHICH_BIT(i);
+ word_set = WHICH_WORD(ncol);
+ bit_set = 1 << WHICH_BIT(ncol);
+
+ pA = A->data;
+ for(T1 = T+2; (p = *T1++) != 0; ) {
+ if ((p[word_test] & bit_test) == 0) {
+ pA[word_set] |= bit_set;
+ }
+ pA += A->wsize;
+ }
+
+ ncol++;
+ }
+ }
+
+ return A;
+}
+
+pcover map_unate_to_cover(A)
+pset_family A;
+{
+ register int i, ncol, lp;
+ register pcube p, pB;
+ int var, nunate, *unate;
+ pcube last;
+ pset_family B;
+
+ B = sf_new(A->count, cube.size);
+ B->count = A->count;
+
+ /* Find the unate variables */
+ unate = ALLOC(int, cube.num_vars);
+ nunate = 0;
+ for(var = 0; var < cube.num_vars; var++) {
+ if (cdata.is_unate[var]) {
+ unate[nunate++] = var;
+ }
+ }
+
+ /* Loop for each set of A */
+ pB = B->data;
+ foreach_set(A, last, p) {
+
+ /* Initialize this set of B */
+ INLINEset_fill(pB, cube.size);
+
+ /* Now loop for the unate variables; if the part is in A,
+ * then this variable of B should be a single 1 in the unate
+ * part.
+ */
+ for(ncol = 0; ncol < nunate; ncol++) {
+ if (is_in_set(p, ncol)) {
+ lp = cube.last_part[unate[ncol]];
+ for(i = cube.first_part[unate[ncol]]; i <= lp; i++) {
+ if (cdata.part_zeros[i] == 0) {
+ set_remove(pB, i);
+ }
+ }
+ }
+ }
+ pB += B->wsize;
+ }
+
+ FREE(unate);
+ return B;
+}
+
+/*
+ * unate_compl
+ */
+
+pset_family unate_compl(A)
+pset_family A;
+{
+ register pset p, last;
+
+ /* Make sure A is single-cube containment minimal */
+/* A = sf_rev_contain(A);*/
+
+ foreach_set(A, last, p) {
+ PUTSIZE(p, set_ord(p));
+ }
+
+ /* Recursively find the complement */
+ A = unate_complement(A);
+
+ /* Now, we can guarantee a minimal result by containing the result */
+ A = sf_rev_contain(A);
+ return A;
+}
+
+
+/*
+ * Assume SIZE(p) records the size of each set
+ */
+pset_family unate_complement(A)
+pset_family A; /* disposes of A */
+{
+ pset_family Abar;
+ register pset p, p1, restrict;
+ register int i;
+ int max_i, min_set_ord, j;
+
+ /* Check for no sets in the matrix -- complement is the universe */
+ if (A->count == 0) {
+ sf_free(A);
+ Abar = sf_new(1, A->sf_size);
+ (void) set_clear(GETSET(Abar, Abar->count++), A->sf_size);
+
+ /* Check for a single set in the maxtrix -- compute de Morgan complement */
+ } else if (A->count == 1) {
+ p = A->data;
+ Abar = sf_new(A->sf_size, A->sf_size);
+ for(i = 0; i < A->sf_size; i++) {
+ if (is_in_set(p, i)) {
+ p1 = set_clear(GETSET(Abar, Abar->count++), A->sf_size);
+ set_insert(p1, i);
+ }
+ }
+ sf_free(A);
+
+ } else {
+
+ /* Select splitting variable as the variable which belongs to a set
+ * of the smallest size, and which has greatest column count
+ */
+ restrict = set_new(A->sf_size);
+ min_set_ord = A->sf_size + 1;
+ foreachi_set(A, i, p) {
+ if (SIZE(p) < min_set_ord) {
+ set_copy(restrict, p);
+ min_set_ord = SIZE(p);
+ } else if (SIZE(p) == min_set_ord) {
+ set_or(restrict, restrict, p);
+ }
+ }
+
+ /* Check for no data (shouldn't happen ?) */
+ if (min_set_ord == 0) {
+ A->count = 0;
+ Abar = A;
+
+ /* Check for "essential" columns */
+ } else if (min_set_ord == 1) {
+ Abar = unate_complement(abs_covered_many(A, restrict));
+ sf_free(A);
+ foreachi_set(Abar, i, p) {
+ set_or(p, p, restrict);
+ }
+
+ /* else, recur as usual */
+ } else {
+ max_i = abs_select_restricted(A, restrict);
+
+ /* Select those rows of A which are not covered by max_i,
+ * recursively find all minimal covers of these rows, and
+ * then add back in max_i
+ */
+ Abar = unate_complement(abs_covered(A, max_i));
+ foreachi_set(Abar, i, p) {
+ set_insert(p, max_i);
+ }
+
+ /* Now recur on A with all zero's on column max_i */
+ foreachi_set(A, i, p) {
+ if (is_in_set(p, max_i)) {
+ set_remove(p, max_i);
+ j = SIZE(p) - 1;
+ PUTSIZE(p, j);
+ }
+ }
+
+ Abar = sf_append(Abar, unate_complement(A));
+ }
+ set_free(restrict);
+ }
+
+ return Abar;
+}
+
+pset_family exact_minimum_cover(T)
+IN pset_family T;
+{
+ register pset p, last, p1;
+ register int i, n;
+ int lev, lvl;
+ pset nlast;
+ pset_family temp;
+ long start = ptime();
+ struct {
+ pset_family sf;
+ int level;
+ } stack[32]; /* 32 suffices for 2 ** 32 cubes ! */
+
+ if (T->count <= 0)
+ return sf_new(1, T->sf_size);
+ for(n = T->count, lev = 0; n != 0; n >>= 1, lev++) ;
+
+ /* A simple heuristic ordering */
+ T = lex_sort(sf_save(T));
+
+ /* Push a full set on the stack to get things started */
+ n = 1;
+ stack[0].sf = sf_new(1, T->sf_size);
+ stack[0].level = lev;
+ set_fill(GETSET(stack[0].sf, stack[0].sf->count++), T->sf_size);
+
+ nlast = GETSET(T, T->count - 1);
+ foreach_set(T, last, p) {
+
+ /* "unstack" the set into a family */
+ temp = sf_new(set_ord(p), T->sf_size);
+ for(i = 0; i < T->sf_size; i++)
+ if (is_in_set(p, i)) {
+ p1 = set_fill(GETSET(temp, temp->count++), T->sf_size);
+ set_remove(p1, i);
+ }
+ stack[n].sf = temp;
+ stack[n++].level = lev;
+
+ /* Pop the stack and perform (leveled) intersections */
+ while (n > 1 && (stack[n-1].level==stack[n-2].level || p == nlast)) {
+ temp = unate_intersect(stack[n-1].sf, stack[n-2].sf, FALSE);
+ lvl = MIN(stack[n-1].level, stack[n-2].level) - 1;
+ if (debug & MINCOV && lvl < 10) {
+ printf("# EXACT_MINCOV[%d]: %4d = %4d x %4d, time = %s\n",
+ lvl, temp->count, stack[n-1].sf->count,
+ stack[n-2].sf->count, print_time(ptime() - start));
+ (void) fflush(stdout);
+ }
+ sf_free(stack[n-2].sf);
+ sf_free(stack[n-1].sf);
+ stack[n-2].sf = temp;
+ stack[n-2].level = lvl;
+ n--;
+ }
+ }
+
+ temp = stack[0].sf;
+ p1 = set_fill(set_new(T->sf_size), T->sf_size);
+ foreach_set(temp, last, p)
+ INLINEset_diff(p, p1, p);
+ set_free(p1);
+ if (debug & MINCOV1) {
+ printf("MINCOV: family of all minimal coverings is\n");
+ sf_print(temp);
+ }
+ sf_free(T); /* this is the copy of T we made ... */
+ return temp;
+}
+
+/*
+ * unate_intersect -- intersect two unate covers
+ *
+ * If largest_only is TRUE, then only the largest cube(s) are returned
+ */
+
+#define MAGIC 500 /* save 500 cubes before containment */
+
+pset_family unate_intersect(A, B, largest_only)
+pset_family A, B;
+bool largest_only;
+{
+ register pset pi, pj, lasti, lastj, pt;
+ pset_family T, Tsave;
+ bool save;
+ int maxord, ord;
+
+ /* How large should each temporary result cover be ? */
+ T = sf_new(MAGIC, A->sf_size);
+ Tsave = NULL;
+ maxord = 0;
+ pt = T->data;
+
+ /* Form pairwise intersection of each set of A with each cube of B */
+ foreach_set(A, lasti, pi) {
+
+ foreach_set(B, lastj, pj) {
+
+ save = set_andp(pt, pi, pj);
+
+ /* Check if we want the largest only */
+ if (save && largest_only) {
+ if ((ord = set_ord(pt)) > maxord) {
+ /* discard Tsave and T */
+ if (Tsave != NULL) {
+ sf_free(Tsave);
+ Tsave = NULL;
+ }
+ pt = T->data;
+ T->count = 0;
+ /* Re-create pt (which was just thrown away) */
+ (void) set_and(pt, pi, pj);
+ maxord = ord;
+ } else if (ord < maxord) {
+ save = FALSE;
+ }
+ }
+
+ if (save) {
+ if (++T->count >= T->capacity) {
+ T = sf_contain(T);
+ Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T);
+ T = sf_new(MAGIC, A->sf_size);
+ pt = T->data;
+ } else {
+ pt += T->wsize;
+ }
+ }
+ }
+ }
+
+
+ /* Contain the final result and merge it into Tsave */
+ T = sf_contain(T);
+ Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T);
+
+ return Tsave;
+}
+
+/*
+ * abs_covered -- after selecting a new column for the selected set,
+ * create a new matrix which is only those rows which are still uncovered
+ */
+static pset_family
+abs_covered(A, pick)
+pset_family A;
+register int pick;
+{
+ register pset last, p, pdest;
+ register pset_family Aprime;
+
+ Aprime = sf_new(A->count, A->sf_size);
+ pdest = Aprime->data;
+ foreach_set(A, last, p)
+ if (! is_in_set(p, pick)) {
+ INLINEset_copy(pdest, p);
+ Aprime->count++;
+ pdest += Aprime->wsize;
+ }
+ return Aprime;
+}
+
+
+/*
+ * abs_covered_many -- after selecting many columns for ther selected set,
+ * create a new matrix which is only those rows which are still uncovered
+ */
+static pset_family
+abs_covered_many(A, pick_set)
+pset_family A;
+register pset pick_set;
+{
+ register pset last, p, pdest;
+ register pset_family Aprime;
+
+ Aprime = sf_new(A->count, A->sf_size);
+ pdest = Aprime->data;
+ foreach_set(A, last, p)
+ if (setp_disjoint(p, pick_set)) {
+ INLINEset_copy(pdest, p);
+ Aprime->count++;
+ pdest += Aprime->wsize;
+ }
+ return Aprime;
+}
+
+
+/*
+ * abs_select_restricted -- select the column of maximum column count which
+ * also belongs to the set "restrict"; weight each column of a set as
+ * 1 / (set_ord(p) - 1).
+ */
+static int
+abs_select_restricted(A, restrict)
+pset_family A;
+pset restrict;
+{
+ register int i, best_var, best_count, *count;
+
+ /* Sum the elements in these columns */
+ count = sf_count_restricted(A, restrict);
+
+ /* Find which variable has maximum weight */
+ best_var = -1;
+ best_count = 0;
+ for(i = 0; i < A->sf_size; i++) {
+ if (count[i] > best_count) {
+ best_var = i;
+ best_count = count[i];
+ }
+ }
+ FREE(count);
+
+ if (best_var == -1)
+ fatal("abs_select_restricted: should not have best_var == -1");
+
+ return best_var;
+}
diff --git a/src/misc/espresso/util_old.h b/src/misc/espresso/util_old.h
new file mode 100644
index 00000000..5451cbe9
--- /dev/null
+++ b/src/misc/espresso/util_old.h
@@ -0,0 +1,301 @@
+/*
+ * Revision Control Information
+ *
+ * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/util/RCS/util.h,v $
+ * $Author: sis $
+ * $Revision: 1.9 $
+ * $Date: 1993/06/07 21:04:07 $
+ *
+ */
+#ifndef UTIL_H
+#define UTIL_H
+
+#if defined(_IBMR2)
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE /* Argh! IBM strikes again */
+#endif
+#ifndef _ALL_SOURCE
+#define _ALL_SOURCE /* Argh! IBM strikes again */
+#endif
+#ifndef _ANSI_C_SOURCE
+#define _ANSI_C_SOURCE /* Argh! IBM strikes again */
+#endif
+#endif
+
+#if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__)
+#include <unistd.h>
+#endif
+
+#if defined(_IBMR2) && !defined(__STDC__)
+#define _BSD
+#endif
+
+#include "ansi.h" /* since some files don't include sis.h */
+
+/* This was taken out and defined at compile time in the SIS Makefile
+ that uses the OctTools. When the OctTools are used, USE_MM is defined,
+ because the OctTools contain libmm.a. Otherwise, USE_MM is not defined,
+ since the mm package is not distributed with SIS, only with Oct. */
+
+/* #define USE_MM */ /* choose libmm.a as the memory allocator */
+
+#define NIL(type) ((type *) 0)
+
+#ifdef USE_MM
+/*
+ * assumes the memory manager is libmm.a
+ * - allows malloc(0) or realloc(obj, 0)
+ * - catches out of memory (and calls MMout_of_memory())
+ * - catch free(0) and realloc(0, size) in the macros
+ */
+#define ALLOC(type, num) \
+ ((type *) malloc(sizeof(type) * (num)))
+#define REALLOC(type, obj, num) \
+ (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num)))
+#define FREE(obj) \
+ ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#else
+/*
+ * enforce strict semantics on the memory allocator
+ * - when in doubt, delete the '#define USE_MM' above
+ */
+#define ALLOC(type, num) \
+ ((type *) MMalloc((long) sizeof(type) * (long) (num)))
+#define REALLOC(type, obj, num) \
+ ((type *) MMrealloc((char *) (obj), (long) sizeof(type) * (long) (num)))
+#define FREE(obj) \
+ ((obj) ? (free((void *) (obj)), (obj) = 0) : 0)
+#endif
+
+
+/* Ultrix (and SABER) have 'fixed' certain functions which used to be int */
+#if defined(ultrix) || defined(SABER) || defined(aiws) || defined(__hpux) || defined(__STDC__) || defined(apollo)
+#define VOID_HACK void
+#else
+#define VOID_HACK int
+#endif
+
+
+/* No machines seem to have much of a problem with these */
+#include <stdio.h>
+#include <ctype.h>
+
+
+/* Some machines fail to define some functions in stdio.h */
+#if !defined(__STDC__) && !defined(sprite) && !defined(_IBMR2) && !defined(__osf__)
+extern FILE *popen(), *tmpfile();
+extern int pclose();
+#ifndef clearerr /* is a macro on many machines, but not all */
+extern VOID_HACK clearerr();
+#endif
+#ifndef rewind
+extern VOID_HACK rewind();
+#endif
+#endif
+
+#ifndef PORT_H
+#include <sys/types.h>
+#include <signal.h>
+#if defined(ultrix)
+#if defined(_SIZE_T_)
+#define ultrix4
+#else
+#if defined(SIGLOST)
+#define ultrix3
+#else
+#define ultrix2
+#endif
+#endif
+#endif
+#endif
+
+/* most machines don't give us a header file for these */
+#if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__) || defined(sunos4) || defined(__hpux)
+#include <stdlib.h>
+#if defined(__hpux)
+#include <errno.h> /* For perror() defininition */
+#endif /* __hpux */
+#else
+extern VOID_HACK abort(), free(), exit(), perror();
+extern char *getenv();
+#ifdef ultrix4
+extern void *malloc(), *realloc(), *calloc();
+#else
+extern char *malloc(), *realloc(), *calloc();
+#endif
+#if defined(aiws)
+extern int sprintf();
+#else
+#ifndef _IBMR2
+extern char *sprintf();
+#endif
+#endif
+extern int system();
+extern double atof();
+#endif
+
+#ifndef PORT_H
+#if defined(ultrix3) || defined(sunos4) || defined(_IBMR2) || defined(__STDC__)
+#define SIGNAL_FN void
+#else
+/* sequent, ultrix2, 4.3BSD (vax, hp), sunos3 */
+#define SIGNAL_FN int
+#endif
+#endif
+
+/* some call it strings.h, some call it string.h; others, also have memory.h */
+#if defined(__STDC__) || defined(sprite)
+#include <string.h>
+#else
+#if defined(ultrix4) || defined(__hpux)
+#include <strings.h>
+#else
+#if defined(_IBMR2) || defined(__osf__)
+#include<string.h>
+#include<strings.h>
+#else
+/* ANSI C string.h -- 1/11/88 Draft Standard */
+/* ugly, awful hack */
+#ifndef PORT_H
+extern char *strcpy(), *strncpy(), *strcat(), *strncat(), *strerror();
+extern char *strpbrk(), *strtok(), *strchr(), *strrchr(), *strstr();
+extern int strcoll(), strxfrm(), strncmp(), strlen(), strspn(), strcspn();
+extern char *memmove(), *memccpy(), *memchr(), *memcpy(), *memset();
+extern int memcmp(), strcmp();
+#endif
+#endif
+#endif
+#endif
+
+/* a few extras */
+#if defined(__hpux)
+#define random() lrand48()
+#define srandom(a) srand48(a)
+#define bzero(a,b) memset(a, 0, b)
+#else
+#if !defined(__osf__) && !defined(linux)
+/* these are defined as macros in stdlib.h */
+extern VOID_HACK srandom();
+extern long random();
+#endif
+#endif
+
+/* code from sis-1.3 commented out below
+#if defined(__STDC__) || defined(sprite)
+#include <assert.h>
+#else
+#ifndef NDEBUG
+#define assert(ex) {\
+ if (! (ex)) {\
+ (void) fprintf(stderr,\
+ "Assertion failed: file %s, line %d\n\"%s\"\n",\
+ __FILE__, __LINE__, "ex");\
+ (void) fflush(stdout);\
+ abort();\
+ }\
+}
+#else
+#define assert(ex) {ex;}
+#endif
+#endif
+*/
+
+ /* Sunil 5/3/97:
+ sis-1.4: dont let the assert call go to the OS, since
+ much of the code in SIS has actual computation done in
+ the assert function. %$#$@@#! The OS version of assert
+ will do nothing if NDEBUG is set. We cant let that happen...
+ */
+# ifdef NDEBUG
+# define assert(ex) {ex;}
+# else
+# define assert(ex) {\
+ if (! (ex)) {\
+ (void) fprintf(stderr,\
+ "Assertion failed: file %s, line %d\n\"%s\"\n",\
+ __FILE__, __LINE__, "ex");\
+ (void) fflush(stdout);\
+ abort();\
+ }\
+}
+# endif
+
+
+#define fail(why) {\
+ (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
+ __FILE__, __LINE__, why);\
+ (void) fflush(stdout);\
+ abort();\
+}
+
+
+#ifdef lint
+#undef putc /* correct lint '_flsbuf' bug */
+#undef ALLOC /* allow for lint -h flag */
+#undef REALLOC
+#define ALLOC(type, num) (((type *) 0) + (num))
+#define REALLOC(type, obj, num) ((obj) + (num))
+#endif
+
+/*
+#if !defined(__osf__)
+#define MAXPATHLEN 1024
+#endif
+*/
+
+/* These arguably do NOT belong in util.h */
+#ifndef ABS
+#define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+
+#ifndef USE_MM
+EXTERN void MMout_of_memory ARGS((long));
+EXTERN char *MMalloc ARGS((long));
+EXTERN char *MMrealloc ARGS((char *, long));
+EXTERN void MMfree ARGS((char *));
+#endif
+
+EXTERN void util_print_cpu_stats ARGS((FILE *));
+EXTERN long util_cpu_time ARGS((void));
+EXTERN void util_getopt_reset ARGS((void));
+EXTERN int util_getopt ARGS((int, char **, char *));
+EXTERN char *util_path_search ARGS((char *));
+EXTERN char *util_file_search ARGS((char *, char *, char *));
+EXTERN int util_pipefork ARGS((char **, FILE **, FILE **, int *));
+EXTERN char *util_print_time ARGS((long));
+EXTERN int util_save_image ARGS((char *, char *));
+EXTERN char *util_strsav ARGS((char *));
+EXTERN int util_do_nothing ARGS((void));
+EXTERN char *util_tilde_expand ARGS((char *));
+EXTERN char *util_tempnam ARGS((char *, char *));
+EXTERN FILE *util_tmpfile ARGS((void));
+EXTERN long getSoftDataLimit();
+
+#define ptime() util_cpu_time()
+#define print_time(t) util_print_time(t)
+
+/* util_getopt() global variables (ack !) */
+extern int util_optind;
+extern char *util_optarg;
+
+#include <math.h>
+#ifndef HUGE_VAL
+#ifndef HUGE
+#define HUGE 8.9884656743115790e+307
+#endif
+#define HUGE_VAL HUGE
+#endif
+#ifndef MAXINT
+#define MAXINT (1 << 30)
+#endif
+
+#include <varargs.h>
+#endif
diff --git a/src/misc/espresso/verify.c b/src/misc/espresso/verify.c
new file mode 100644
index 00000000..64342787
--- /dev/null
+++ b/src/misc/espresso/verify.c
@@ -0,0 +1,193 @@
+/*
+ * Revision Control Information
+ *
+ * $Source$
+ * $Author$
+ * $Revision$
+ * $Date$
+ *
+ */
+/*
+ */
+
+#include "espresso.h"
+
+/*
+ * verify -- check that all minterms of F are contained in (Fold u Dold)
+ * and that all minterms of Fold are contained in (F u Dold).
+ */
+bool verify(F, Fold, Dold)
+pcover F, Fold, Dold;
+{
+ pcube p, last, *FD;
+ bool verify_error = FALSE;
+
+ /* Make sure the function didn't grow too large */
+ FD = cube2list(Fold, Dold);
+ foreach_set(F, last, p)
+ if (! cube_is_covered(FD, p)) {
+ printf("some minterm in F is not covered by Fold u Dold\n");
+ verify_error = TRUE;
+ if (verbose_debug) printf("%s\n", pc1(p)); else break;
+ }
+ free_cubelist(FD);
+
+ /* Make sure minimized function covers the original function */
+ FD = cube2list(F, Dold);
+ foreach_set(Fold, last, p)
+ if (! cube_is_covered(FD, p)) {
+ printf("some minterm in Fold is not covered by F u Dold\n");
+ verify_error = TRUE;
+ if (verbose_debug) printf("%s\n", pc1(p)); else break;
+ }
+ free_cubelist(FD);
+
+ return verify_error;
+}
+
+
+
+/*
+ * PLA_verify -- verify that two PLA's are identical
+ *
+ * If names are given, row and column permutations are done to make
+ * the comparison meaningful.
+ *
+ */
+bool PLA_verify(PLA1, PLA2)
+pPLA PLA1, PLA2;
+{
+ /* Check if both have names given; if so, attempt to permute to
+ * match the names
+ */
+ if (PLA1->label != NULL && PLA1->label[0] != NULL &&
+ PLA2->label != NULL && PLA2->label[0] != NULL) {
+ PLA_permute(PLA1, PLA2);
+ } else {
+ (void) fprintf(stderr, "Warning: cannot permute columns without names\n");
+ return TRUE;
+ }
+
+ if (PLA1->F->sf_size != PLA2->F->sf_size) {
+ (void) fprintf(stderr, "PLA_verify: PLA's are not the same size\n");
+ return TRUE;
+ }
+
+ return verify(PLA2->F, PLA1->F, PLA1->D);
+}
+
+
+
+/*
+ * Permute the columns of PLA1 so that they match the order of PLA2
+ * Discard any columns of PLA1 which are not in PLA2
+ * Association is strictly by the names of the columns of the cover.
+ */
+PLA_permute(PLA1, PLA2)
+pPLA PLA1, PLA2;
+{
+ register int i, j, *permute, npermute;
+ register char *labi;
+ char **label;
+
+ /* determine which columns of PLA1 to save, and place these in the list
+ * "permute"; the order in this list is the final output order
+ */
+ npermute = 0;
+ permute = ALLOC(int, PLA2->F->sf_size);
+ for(i = 0; i < PLA2->F->sf_size; i++) {
+ labi = PLA2->label[i];
+ for(j = 0; j < PLA1->F->sf_size; j++) {
+ if (strcmp(labi, PLA1->label[j]) == 0) {
+ permute[npermute++] = j;
+ break;
+ }
+ }
+ }
+
+ /* permute columns */
+ if (PLA1->F != NULL) {
+ PLA1->F = sf_permute(PLA1->F, permute, npermute);
+ }
+ if (PLA1->R != NULL) {
+ PLA1->R = sf_permute(PLA1->R, permute, npermute);
+ }
+ if (PLA1->D != NULL) {
+ PLA1->D = sf_permute(PLA1->D, permute, npermute);
+ }
+
+ /* permute the labels */
+ label = ALLOC(char *, cube.size);
+ for(i = 0; i < npermute; i++) {
+ label[i] = PLA1->label[permute[i]];
+ }
+ for(i = npermute; i < cube.size; i++) {
+ label[i] = NULL;
+ }
+ FREE(PLA1->label);
+ PLA1->label = label;
+
+ FREE(permute);
+}
+
+
+
+/*
+ * check_consistency -- test that the ON-set, OFF-set and DC-set form
+ * a partition of the boolean space.
+ */
+bool check_consistency(PLA)
+pPLA PLA;
+{
+ bool verify_error = FALSE;
+ pcover T;
+
+ T = cv_intersect(PLA->F, PLA->D);
+ if (T->count == 0)
+ printf("ON-SET and DC-SET are disjoint\n");
+ else {
+ printf("Some minterm(s) belong to both the ON-SET and DC-SET !\n");
+ if (verbose_debug)
+ cprint(T);
+ verify_error = TRUE;
+ }
+ (void) fflush(stdout);
+ free_cover(T);
+
+ T = cv_intersect(PLA->F, PLA->R);
+ if (T->count == 0)
+ printf("ON-SET and OFF-SET are disjoint\n");
+ else {
+ printf("Some minterm(s) belong to both the ON-SET and OFF-SET !\n");
+ if (verbose_debug)
+ cprint(T);
+ verify_error = TRUE;
+ }
+ (void) fflush(stdout);
+ free_cover(T);
+
+ T = cv_intersect(PLA->D, PLA->R);
+ if (T->count == 0)
+ printf("DC-SET and OFF-SET are disjoint\n");
+ else {
+ printf("Some minterm(s) belong to both the OFF-SET and DC-SET !\n");
+ if (verbose_debug)
+ cprint(T);
+ verify_error = TRUE;
+ }
+ (void) fflush(stdout);
+ free_cover(T);
+
+ if (tautology(cube3list(PLA->F, PLA->D, PLA->R)))
+ printf("Union of ON-SET, OFF-SET and DC-SET is the universe\n");
+ else {
+ T = complement(cube3list(PLA->F, PLA->D, PLA->R));
+ printf("There are minterms left unspecified !\n");
+ if (verbose_debug)
+ cprint(T);
+ verify_error = TRUE;
+ free_cover(T);
+ }
+ (void) fflush(stdout);
+ return verify_error;
+}
diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h
index 0d0c93a8..666d7388 100644
--- a/src/misc/extra/extra.h
+++ b/src/misc/extra/extra.h
@@ -37,9 +37,11 @@
/* Nested includes */
/*---------------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include <time.h>
-#include "util.h"
#include "st.h"
#include "cuddInt.h"
@@ -155,6 +157,7 @@ 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 );
/*=== extraBddKmap.c ================================================================*/
@@ -408,6 +411,27 @@ extern void Extra_IntVecPush( Extra_IntVec_t * p, int Entry );
extern int Extra_IntVecPop( Extra_IntVec_t * p );
extern void Extra_IntVecSort( Extra_IntVec_t * p );
+/*=== extraUtilUtil.c ================================================================*/
+
+#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
+#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#define REALLOC(type, obj, num) \
+ (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num)))
+
+extern long Extra_CpuTime();
+extern int Extra_GetSoftDataLimit();
+extern void Extra_UtilGetoptReset();
+extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring );
+extern char * Extra_UtilPrintTime( long t );
+extern char * Extra_UtilStrsav( char *s );
+extern char * Extra_UtilTildeExpand( char *fname );
+extern char * Extra_UtilFileSearch( char *file, char *path, char *mode );
+extern void (*Extra_UtilMMoutOfMemory)();
+
+extern char * globalUtilOptarg;
+extern int globalUtilOptind;
+
/**AutomaticEnd***************************************************************/
#endif /* __EXTRA_H__ */
diff --git a/src/misc/extra/extraBddMisc.c b/src/misc/extra/extraBddMisc.c
index 7d806ec7..00e2ac94 100644
--- a/src/misc/extra/extraBddMisc.c
+++ b/src/misc/extra/extraBddMisc.c
@@ -52,8 +52,8 @@ static DdNode * extraTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdN
static DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute );
// file "cuddUtils.c"
-static void ddSupportStep ARGS((DdNode *f, int *support));
-static void ddClearFlag ARGS((DdNode *f));
+static void ddSupportStep(DdNode *f, int *support);
+static void ddClearFlag(DdNode *f);
/**AutomaticEnd***************************************************************/
@@ -796,6 +796,25 @@ DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f )
} /* end of Extra_SupportNeg */
+/**Function********************************************************************
+
+ Synopsis [Returns 1 if the BDD is the BDD of elementary variable.]
+
+ Description []
+
+ SideEffects [None]
+
+ SeeAlso [Cudd_VectorSupport Cudd_Support]
+
+******************************************************************************/
+int Extra_bddIsVar( DdNode * bFunc )
+{
+ bFunc = Cudd_Regular( bFunc );
+ if ( cuddIsConstant(bFunc) )
+ return 0;
+ return cuddIsConstant( cuddT(bFunc) ) && cuddIsConstant( Cudd_Regular(cuddE(bFunc)) );
+}
+
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
diff --git a/src/misc/extra/extraUtil.h b/src/misc/extra/extraUtil.h
new file mode 100644
index 00000000..d3f432c2
--- /dev/null
+++ b/src/misc/extra/extraUtil.h
@@ -0,0 +1,60 @@
+/**CFile****************************************************************
+
+ FileName [extraUtil.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [Various reusable software utilities.]
+
+ Description []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraUtil.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __EXTRA_UTIL_H__
+#define __EXTRA_UTIL_H__
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes */
+/*---------------------------------------------------------------------------*/
+
+#include <string.h>
+#include <time.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+/*===========================================================================*/
+/* Various Utilities */
+/*===========================================================================*/
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* __EXTRA_UTIL_H__ */
diff --git a/src/misc/extra/extraUtilFile.c b/src/misc/extra/extraUtilFile.c
index 03b31fea..b00125d1 100644
--- a/src/misc/extra/extraUtilFile.c
+++ b/src/misc/extra/extraUtilFile.c
@@ -172,7 +172,7 @@ char * Extra_FileNameGeneric( char * FileName )
char * pRes;
// find the generic name of the file
- pRes = util_strsav( FileName );
+ pRes = Extra_UtilStrsav( FileName );
// find the pointer to the "." symbol in the file name
// pUnd = strstr( FileName, "_" );
pUnd = NULL;
@@ -391,7 +391,7 @@ char * Extra_StringAppend( char * pStrGiven, char * pStrAdd )
free( pStrGiven );
}
else
- pTemp = util_strsav( pStrAdd );
+ pTemp = Extra_UtilStrsav( pStrAdd );
return pTemp;
}
diff --git a/src/misc/extra/extraUtilUtil.c b/src/misc/extra/extraUtilUtil.c
new file mode 100644
index 00000000..71d3f652
--- /dev/null
+++ b/src/misc/extra/extraUtilUtil.c
@@ -0,0 +1,330 @@
+/**CFile****************************************************************
+
+ FileName [extraUtilUtil.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [extra]
+
+ Synopsis [Old SIS utilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: extraUtilUtil.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "stdio.h"
+#include "extra.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define EXTRA_RLIMIT_DATA_DEFAULT 67108864 // assume 64MB by default
+
+/* File : getopt.c
+ * Author : Henry Spencer, University of Toronto
+ * Updated: 28 April 1984
+ *
+ * Changes: (R Rudell)
+ * changed index() to strchr();
+ * added getopt_reset() to reset the getopt argument parsing
+ *
+ * Purpose: get option letter from argv.
+ */
+
+char * globalUtilOptarg; // Global argument pointer (util_optarg)
+int globalUtilOptind = 0; // Global argv index (util_optind)
+
+static char *pScanStr;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [util_cpu_time()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+long Extra_CpuTime()
+{
+ return clock();
+}
+
+/**Function*************************************************************
+
+ Synopsis [getSoftDataLimit()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_GetSoftDataLimit()
+{
+ return EXTRA_RLIMIT_DATA_DEFAULT;
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_getopt_reset()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_UtilGetoptReset()
+{
+ globalUtilOptarg = 0;
+ globalUtilOptind = 0;
+ pScanStr = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_getopt()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_UtilGetopt( int argc, char *argv[], char *optstring )
+{
+ register int c;
+ register char *place;
+
+ globalUtilOptarg = NULL;
+
+ if (pScanStr == NULL || *pScanStr == '\0') {
+ if (globalUtilOptind == 0) globalUtilOptind++;
+ if (globalUtilOptind >= argc) return EOF;
+ place = argv[globalUtilOptind];
+ if (place[0] != '-' || place[1] == '\0') return EOF;
+ globalUtilOptind++;
+ if (place[1] == '-' && place[2] == '\0') return EOF;
+ pScanStr = place+1;
+ }
+
+ c = *pScanStr++;
+ place = strchr(optstring, c);
+ if (place == NULL || c == ':') {
+ (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
+ return '?';
+ }
+ if (*++place == ':') {
+ if (*pScanStr != '\0') {
+ globalUtilOptarg = pScanStr;
+ pScanStr = NULL;
+ } else {
+ if (globalUtilOptind >= argc) {
+ (void) fprintf(stderr, "%s: %c requires an argument\n",
+ argv[0], c);
+ return '?';
+ }
+ globalUtilOptarg = argv[globalUtilOptind];
+ globalUtilOptind++;
+ }
+ }
+ return c;
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_print_time()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_UtilPrintTime( long t )
+{
+ static char s[40];
+
+ (void) sprintf(s, "%ld.%02ld sec", t/1000, (t%1000)/10);
+ return s;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Extra_UtilStrsav()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_UtilStrsav( char *s )
+{
+ if(s == NULL) { /* added 7/95, for robustness */
+ return s;
+ }
+ else {
+ return strcpy(ALLOC(char, strlen(s)+1), s);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_tilde_expand()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_UtilTildeExpand( char *fname )
+{
+ return Extra_UtilStrsav( fname );
+}
+
+/**Function*************************************************************
+
+ Synopsis [check_file()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Extra_UtilCheckFile(char *filename, char *mode)
+{
+ FILE *fp;
+ int got_file;
+
+ if (strcmp(mode, "x") == 0) {
+ mode = "r";
+ }
+ fp = fopen(filename, mode);
+ got_file = (fp != 0);
+ if (fp != 0) {
+ (void) fclose(fp);
+ }
+ return got_file;
+}
+
+/**Function*************************************************************
+
+ Synopsis [util_file_search()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Extra_UtilFileSearch(char *file, char *path, char *mode)
+//char *file; // file we're looking for
+//char *path; // search path, colon separated
+//char *mode; // "r", "w", or "x"
+{
+ int quit;
+ char *buffer, *filename, *save_path, *cp;
+
+ if (path == 0 || strcmp(path, "") == 0) {
+ path = "."; /* just look in the current directory */
+ }
+
+ save_path = path = Extra_UtilStrsav(path);
+ quit = 0;
+ do {
+ cp = strchr(path, ':');
+ if (cp != 0) {
+ *cp = '\0';
+ } else {
+ quit = 1;
+ }
+
+ /* cons up the filename out of the path and file name */
+ if (strcmp(path, ".") == 0) {
+ buffer = Extra_UtilStrsav(file);
+ } else {
+ buffer = ALLOC(char, strlen(path) + strlen(file) + 4);
+ (void) sprintf(buffer, "%s/%s", path, file);
+ }
+ filename = Extra_UtilTildeExpand(buffer);
+ FREE(buffer);
+
+ /* see if we can access it */
+ if (Extra_UtilCheckFile(filename, mode)) {
+ FREE(save_path);
+ return filename;
+ }
+ FREE(filename);
+ path = ++cp;
+ } while (! quit);
+
+ FREE(save_path);
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [MMout_of_memory()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+/* MMout_of_memory -- out of memory for lazy people, flush and exit */
+void Extra_UtilMMout_Of_Memory( long size )
+{
+ (void) fflush(stdout);
+ (void) fprintf(stderr, "\nout of memory allocating %u bytes\n",
+ (unsigned) size);
+ assert( 0 );
+ exit(1);
+}
+
+/**Function*************************************************************
+
+ Synopsis [MMoutOfMemory()]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void (*Extra_UtilMMoutOfMemory)() = Extra_UtilMMout_Of_Memory;
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/misc/extra/module.make b/src/misc/extra/module.make
index 8e7b1772..c4da05e4 100644
--- a/src/misc/extra/module.make
+++ b/src/misc/extra/module.make
@@ -2,10 +2,12 @@ SRC += src/misc/extra/extraBddAuto.c \
src/misc/extra/extraBddKmap.c \
src/misc/extra/extraBddMisc.c \
src/misc/extra/extraBddSymm.c \
+ src/misc/extra/extraBddUnate.c \
src/misc/extra/extraUtilBitMatrix.c \
src/misc/extra/extraUtilCanon.c \
src/misc/extra/extraUtilFile.c \
src/misc/extra/extraUtilMemory.c \
src/misc/extra/extraUtilMisc.c \
src/misc/extra/extraUtilProgress.c \
- src/misc/extra/extraUtilReader.c
+ src/misc/extra/extraUtilReader.c \
+ src/misc/extra/extraUtilUtil.c
diff --git a/src/misc/mvc/mvc.h b/src/misc/mvc/mvc.h
index b670dc97..363b1e57 100644
--- a/src/misc/mvc/mvc.h
+++ b/src/misc/mvc/mvc.h
@@ -24,9 +24,8 @@
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
-#include "util.h"
#include "extra.h"
-//#include "vm.h"
+#include "extra.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
diff --git a/src/misc/st/st.c b/src/misc/st/st.c
index 13e9bd6a..e1e5022a 100644
--- a/src/misc/st/st.c
+++ b/src/misc/st/st.c
@@ -8,9 +8,13 @@
*
*/
#include <stdio.h>
-#include "util.h"
+#include "extra.h"
#include "st.h"
+#ifndef ABS
+# define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+
#define ST_NUMCMP(x,y) ((x) != (y))
#define ST_NUMHASH(x,size) (ABS((long)x)%(size))
#define ST_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size)
@@ -41,8 +45,8 @@ int reorder_flag;
st_table *new;
new = ALLOC(st_table, 1);
- if (new == NIL(st_table)) {
- return NIL(st_table);
+ if (new == NULL) {
+ return NULL;
}
new->compare = compare;
new->hash = hash;
@@ -55,9 +59,9 @@ int reorder_flag;
}
new->num_bins = size;
new->bins = ALLOC(st_table_entry *, size);
- if (new->bins == NIL(st_table_entry *)) {
+ if (new->bins == NULL) {
FREE(new);
- return NIL(st_table);
+ return NULL;
}
for(i = 0; i < size; i++) {
new->bins[i] = 0;
@@ -85,7 +89,7 @@ st_table *table;
for(i = 0; i < table->num_bins ; i++) {
ptr = table->bins[i];
- while (ptr != NIL(st_table_entry)) {
+ while (ptr != NULL) {
next = ptr->next;
FREE(ptr);
ptr = next;
@@ -96,7 +100,7 @@ st_table *table;
}
#define PTR_NOT_EQUAL(table, ptr, user_key)\
-(ptr != NIL(st_table_entry) && !EQUAL(table->compare, user_key, (ptr)->key))
+(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key))
#define FIND_ENTRY(table, hash_val, key, ptr, last) \
(last) = &(table)->bins[hash_val];\
@@ -104,7 +108,7 @@ st_table *table;
while (PTR_NOT_EQUAL((table), (ptr), (key))) {\
(last) = &(ptr)->next; (ptr) = *(last);\
}\
- if ((ptr) != NIL(st_table_entry) && (table)->reorder_flag) {\
+ if ((ptr) != NULL && (table)->reorder_flag) {\
*(last) = (ptr)->next;\
(ptr)->next = (table)->bins[hash_val];\
(table)->bins[hash_val] = (ptr);\
@@ -123,10 +127,10 @@ char **value;
FIND_ENTRY(table, hash_val, key, ptr, last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
return 0;
} else {
- if (value != NIL(char *)) {
+ if (value != NULL) {
*value = ptr->record;
}
return 1;
@@ -146,10 +150,10 @@ int *value;
FIND_ENTRY(table, hash_val, key, ptr, last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
return 0;
} else {
- if (value != NIL(int)) {
+ if (value != 0) {
*value = (long) ptr->record;
}
return 1;
@@ -187,7 +191,7 @@ char *value;
FIND_ENTRY(table, hash_val, key, ptr, last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
if (table->num_entries/table->num_bins >= table->max_density) {
if (rehash(table) == ST_OUT_OF_MEM) {
return ST_OUT_OF_MEM;
@@ -195,7 +199,7 @@ char *value;
hash_val = do_hash(key, table);
}
new = ALLOC(st_table_entry, 1);
- if (new == NIL(st_table_entry)) {
+ if (new == NULL) {
return ST_OUT_OF_MEM;
}
new->key = key;
@@ -227,7 +231,7 @@ char *value;
}
hash_val = do_hash(key, table);
new = ALLOC(st_table_entry, 1);
- if (new == NIL(st_table_entry)) {
+ if (new == NULL) {
return ST_OUT_OF_MEM;
}
new->key = key;
@@ -251,7 +255,7 @@ char ***slot;
FIND_ENTRY(table, hash_val, key, ptr, last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
if (table->num_entries / table->num_bins >= table->max_density) {
if (rehash(table) == ST_OUT_OF_MEM) {
return ST_OUT_OF_MEM;
@@ -259,7 +263,7 @@ char ***slot;
hash_val = do_hash(key, table);
}
new = ALLOC(st_table_entry, 1);
- if (new == NIL(st_table_entry)) {
+ if (new == NULL) {
return ST_OUT_OF_MEM;
}
new->key = key;
@@ -267,10 +271,10 @@ char ***slot;
new->next = table->bins[hash_val];
table->bins[hash_val] = new;
table->num_entries++;
- if (slot != NIL(char **)) *slot = &new->record;
+ if (slot != NULL) *slot = &new->record;
return 0;
} else {
- if (slot != NIL(char **)) *slot = &ptr->record;
+ if (slot != NULL) *slot = &ptr->record;
return 1;
}
}
@@ -288,10 +292,10 @@ char ***slot;
FIND_ENTRY(table, hash_val, key, ptr, last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
return 0;
} else {
- if (slot != NIL(char **)) {
+ if (slot != NULL) {
*slot = &ptr->record;
}
return 1;
@@ -317,7 +321,7 @@ register st_table *table;
}
table->num_entries = 0;
table->bins = ALLOC(st_table_entry *, table->num_bins);
- if (table->bins == NIL(st_table_entry *)) {
+ if (table->bins == NULL) {
table->bins = old_bins;
table->num_bins = old_num_bins;
table->num_entries = old_num_entries;
@@ -331,7 +335,7 @@ register st_table *table;
/* copy data over */
for (i = 0; i < old_num_bins; i++) {
ptr = old_bins[i];
- while (ptr != NIL(st_table_entry)) {
+ while (ptr != NULL) {
next = ptr->next;
hash_val = do_hash(ptr->key, table);
ptr->next = table->bins[hash_val];
@@ -354,25 +358,25 @@ st_table *old_table;
int i, j, num_bins = old_table->num_bins;
new_table = ALLOC(st_table, 1);
- if (new_table == NIL(st_table)) {
- return NIL(st_table);
+ if (new_table == NULL) {
+ return NULL;
}
*new_table = *old_table;
new_table->bins = ALLOC(st_table_entry *, num_bins);
- if (new_table->bins == NIL(st_table_entry *)) {
+ if (new_table->bins == NULL) {
FREE(new_table);
- return NIL(st_table);
+ return NULL;
}
for(i = 0; i < num_bins ; i++) {
- new_table->bins[i] = NIL(st_table_entry);
+ new_table->bins[i] = NULL;
ptr = old_table->bins[i];
- while (ptr != NIL(st_table_entry)) {
+ while (ptr != NULL) {
new = ALLOC(st_table_entry, 1);
- if (new == NIL(st_table_entry)) {
+ if (new == NULL) {
for (j = 0; j <= i; j++) {
newptr = new_table->bins[j];
- while (newptr != NIL(st_table_entry)) {
+ while (newptr != NULL) {
next = newptr->next;
FREE(newptr);
newptr = next;
@@ -380,7 +384,7 @@ st_table *old_table;
}
FREE(new_table->bins);
FREE(new_table);
- return NIL(st_table);
+ return NULL;
}
*new = *ptr;
new->next = new_table->bins[i];
@@ -405,12 +409,12 @@ char **value;
FIND_ENTRY(table, hash_val, key, ptr ,last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
*last = ptr->next;
- if (value != NIL(char *)) *value = ptr->record;
+ if (value != NULL) *value = ptr->record;
*keyp = ptr->key;
FREE(ptr);
table->num_entries--;
@@ -431,12 +435,12 @@ char **value;
FIND_ENTRY(table, hash_val, key, ptr ,last);
- if (ptr == NIL(st_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
*last = ptr->next;
- if (value != NIL(char *)) *value = ptr->record;
+ if (value != NULL) *value = ptr->record;
*keyp = (long) ptr->key;
FREE(ptr);
table->num_entries--;
@@ -455,7 +459,7 @@ char *arg;
for(i = 0; i < table->num_bins; i++) {
last = &table->bins[i]; ptr = *last;
- while (ptr != NIL(st_table_entry)) {
+ while (ptr != NULL) {
retval = (*func)(ptr->key, ptr->record, arg);
switch (retval) {
case ST_CONTINUE:
@@ -528,11 +532,11 @@ st_table *table;
st_generator *gen;
gen = ALLOC(st_generator, 1);
- if (gen == NIL(st_generator)) {
- return NIL(st_generator);
+ if (gen == NULL) {
+ return NULL;
}
gen->table = table;
- gen->entry = NIL(st_table_entry);
+ gen->entry = NULL;
gen->index = 0;
return gen;
}
@@ -546,16 +550,16 @@ char **value_p;
{
register int i;
- if (gen->entry == NIL(st_table_entry)) {
+ if (gen->entry == NULL) {
/* try to find next entry */
for(i = gen->index; i < gen->table->num_bins; i++) {
- if (gen->table->bins[i] != NIL(st_table_entry)) {
+ if (gen->table->bins[i] != NULL) {
gen->index = i+1;
gen->entry = gen->table->bins[i];
break;
}
}
- if (gen->entry == NIL(st_table_entry)) {
+ if (gen->entry == NULL) {
return 0; /* that's all folks ! */
}
}
@@ -576,21 +580,21 @@ long *value_p;
{
register int i;
- if (gen->entry == NIL(st_table_entry)) {
+ if (gen->entry == NULL) {
/* try to find next entry */
for(i = gen->index; i < gen->table->num_bins; i++) {
- if (gen->table->bins[i] != NIL(st_table_entry)) {
+ if (gen->table->bins[i] != NULL) {
gen->index = i+1;
gen->entry = gen->table->bins[i];
break;
}
}
- if (gen->entry == NIL(st_table_entry)) {
+ if (gen->entry == NULL) {
return 0; /* that's all folks ! */
}
}
*key_p = gen->entry->key;
- if (value_p != NIL(long)) {
+ if (value_p != 0) {
*value_p = (long) gen->entry->record;
}
gen->entry = gen->entry->next;
diff --git a/src/misc/st/st.h b/src/misc/st/st.h
index c51873e9..1802cf9b 100644
--- a/src/misc/st/st.h
+++ b/src/misc/st/st.h
@@ -48,28 +48,28 @@ enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE};
typedef enum st_retval (*ST_PFSR)();
typedef int (*ST_PFI)();
-EXTERN st_table *st_init_table_with_params ARGS((ST_PFI, ST_PFI, int, int, double, int));
-EXTERN st_table *st_init_table ARGS((ST_PFI, ST_PFI));
-EXTERN void st_free_table ARGS((st_table *));
-EXTERN int st_lookup ARGS((st_table *, char *, char **));
-EXTERN int st_lookup_int ARGS((st_table *, char *, int *));
-EXTERN int st_insert ARGS((st_table *, char *, char *));
-EXTERN int st_add_direct ARGS((st_table *, char *, char *));
-EXTERN int st_find_or_add ARGS((st_table *, char *, char ***));
-EXTERN int st_find ARGS((st_table *, char *, char ***));
-EXTERN st_table *st_copy ARGS((st_table *));
-EXTERN int st_delete ARGS((st_table *, char **, char **));
-EXTERN int st_delete_int ARGS((st_table *, long *, char **));
-EXTERN int st_foreach ARGS((st_table *, ST_PFSR, char *));
-EXTERN int st_strhash ARGS((char *, int));
-EXTERN int st_numhash ARGS((char *, int));
-EXTERN int st_ptrhash ARGS((char *, int));
-EXTERN int st_numcmp ARGS((char *, char *));
-EXTERN int st_ptrcmp ARGS((char *, char *));
-EXTERN st_generator *st_init_gen ARGS((st_table *));
-EXTERN int st_gen ARGS((st_generator *, char **, char **));
-EXTERN int st_gen_int ARGS((st_generator *, char **, long *));
-EXTERN void st_free_gen ARGS((st_generator *));
+extern st_table *st_init_table_with_params (ST_PFI, ST_PFI, int, int, double, int);
+extern st_table *st_init_table (ST_PFI, ST_PFI);
+extern void st_free_table (st_table *);
+extern int st_lookup (st_table *, char *, char **);
+extern int st_lookup_int (st_table *, char *, int *);
+extern int st_insert (st_table *, char *, char *);
+extern int st_add_direct (st_table *, char *, char *);
+extern int st_find_or_add (st_table *, char *, char ***);
+extern int st_find (st_table *, char *, char ***);
+extern st_table *st_copy (st_table *);
+extern int st_delete (st_table *, char **, char **);
+extern int st_delete_int (st_table *, long *, char **);
+extern int st_foreach (st_table *, ST_PFSR, char *);
+extern int st_strhash (char *, int);
+extern int st_numhash (char *, int);
+extern int st_ptrhash (char *, int);
+extern int st_numcmp (char *, char *);
+extern int st_ptrcmp (char *, char *);
+extern st_generator *st_init_gen (st_table *);
+extern int st_gen (st_generator *, char **, char **);
+extern int st_gen_int (st_generator *, char **, long *);
+extern void st_free_gen (st_generator *);
#define ST_DEFAULT_MAX_DENSITY 5
diff --git a/src/misc/st/stmm.c b/src/misc/st/stmm.c
index b75b0134..c9b2320b 100644
--- a/src/misc/st/stmm.c
+++ b/src/misc/st/stmm.c
@@ -8,9 +8,13 @@
*
*/
#include <stdio.h>
-#include "util.h"
+#include "extra.h"
#include "stmm.h"
+#ifndef ABS
+# define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+
#define STMM_NUMCMP(x,y) ((x) != (y))
#define STMM_NUMHASH(x,size) (ABS((long)x)%(size))
#define STMM_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size)
@@ -41,8 +45,8 @@ stmm_init_table_with_params (compare, hash, size, density, grow_factor,
stmm_table *new;
new = ALLOC (stmm_table, 1);
- if (new == NIL (stmm_table)) {
- return NIL (stmm_table);
+ if (new == NULL) {
+ return NULL;
}
new->compare = compare;
new->hash = hash;
@@ -55,9 +59,9 @@ stmm_init_table_with_params (compare, hash, size, density, grow_factor,
}
new->num_bins = size;
new->bins = ALLOC (stmm_table_entry *, size);
- if (new->bins == NIL (stmm_table_entry *)) {
+ if (new->bins == NULL) {
FREE (new);
- return NIL (stmm_table);
+ return NULL;
}
for (i = 0; i < size; i++) {
new->bins[i] = 0;
@@ -90,7 +94,7 @@ stmm_free_table (table)
for ( i = 0; i < table->num_bins; i++ )
{
ptr = table->bins[i];
- while ( ptr != NIL( stmm_table_entry ) )
+ while ( ptr != NULL )
{
next = ptr->next;
FREE( ptr );
@@ -123,7 +127,7 @@ stmm_clean (table)
#define PTR_NOT_EQUAL(table, ptr, user_key)\
-(ptr != NIL(stmm_table_entry) && !EQUAL(table->compare, user_key, (ptr)->key))
+(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key))
#define FIND_ENTRY(table, hash_val, key, ptr, last) \
(last) = &(table)->bins[hash_val];\
@@ -131,7 +135,7 @@ stmm_clean (table)
while (PTR_NOT_EQUAL((table), (ptr), (key))) {\
(last) = &(ptr)->next; (ptr) = *(last);\
}\
- if ((ptr) != NIL(stmm_table_entry) && (table)->reorder_flag) {\
+ if ((ptr) != NULL && (table)->reorder_flag) {\
*(last) = (ptr)->next;\
(ptr)->next = (table)->bins[hash_val];\
(table)->bins[hash_val] = (ptr);\
@@ -150,11 +154,11 @@ stmm_lookup (table, key, value)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
else {
- if (value != NIL (char *))
+ if (value != NULL)
{
*value = ptr->record;
}
@@ -175,11 +179,11 @@ stmm_lookup_int (table, key, value)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
else {
- if (value != NIL (int))
+ if (value != 0)
{
*value = (long) ptr->record;
}
@@ -223,7 +227,7 @@ stmm_insert (table, key, value)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
if (table->num_entries / table->num_bins >= table->max_density) {
if (rehash (table) == STMM_OUT_OF_MEM) {
return STMM_OUT_OF_MEM;
@@ -233,7 +237,7 @@ stmm_insert (table, key, value)
// new = ALLOC( stmm_table_entry, 1 );
new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan);
- if (new == NIL (stmm_table_entry)) {
+ if (new == NULL) {
return STMM_OUT_OF_MEM;
}
@@ -269,7 +273,7 @@ stmm_add_direct (table, key, value)
// new = ALLOC( stmm_table_entry, 1 );
new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan);
- if (new == NIL (stmm_table_entry)) {
+ if (new == NULL) {
return STMM_OUT_OF_MEM;
}
@@ -294,7 +298,7 @@ stmm_find_or_add (table, key, slot)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
if (table->num_entries / table->num_bins >= table->max_density) {
if (rehash (table) == STMM_OUT_OF_MEM) {
return STMM_OUT_OF_MEM;
@@ -304,7 +308,7 @@ stmm_find_or_add (table, key, slot)
// new = ALLOC( stmm_table_entry, 1 );
new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan);
- if (new == NIL (stmm_table_entry)) {
+ if (new == NULL) {
return STMM_OUT_OF_MEM;
}
@@ -313,12 +317,12 @@ stmm_find_or_add (table, key, slot)
new->next = table->bins[hash_val];
table->bins[hash_val] = new;
table->num_entries++;
- if (slot != NIL (char **))
+ if (slot != NULL)
*slot = &new->record;
return 0;
}
else {
- if (slot != NIL (char **))
+ if (slot != NULL)
*slot = &ptr->record;
return 1;
}
@@ -337,11 +341,11 @@ stmm_find (table, key, slot)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
else {
- if (slot != NIL (char **))
+ if (slot != NULL)
{
*slot = &ptr->record;
}
@@ -368,7 +372,7 @@ rehash (table)
}
table->num_entries = 0;
table->bins = ALLOC (stmm_table_entry *, table->num_bins);
- if (table->bins == NIL (stmm_table_entry *)) {
+ if (table->bins == NULL) {
table->bins = old_bins;
table->num_bins = old_num_bins;
table->num_entries = old_num_entries;
@@ -382,7 +386,7 @@ rehash (table)
/* copy data over */
for (i = 0; i < old_num_bins; i++) {
ptr = old_bins[i];
- while (ptr != NIL (stmm_table_entry)) {
+ while (ptr != NULL) {
next = ptr->next;
hash_val = do_hash (ptr->key, table);
ptr->next = table->bins[hash_val];
@@ -405,15 +409,15 @@ stmm_copy (old_table)
int i, /*j, */ num_bins = old_table->num_bins;
new_table = ALLOC (stmm_table, 1);
- if (new_table == NIL (stmm_table)) {
- return NIL (stmm_table);
+ if (new_table == NULL) {
+ return NULL;
}
*new_table = *old_table;
new_table->bins = ALLOC (stmm_table_entry *, num_bins);
- if (new_table->bins == NIL (stmm_table_entry *)) {
+ if (new_table->bins == NULL) {
FREE (new_table);
- return NIL (stmm_table);
+ return NULL;
}
// allocate the memory manager for the new table
@@ -421,20 +425,20 @@ stmm_copy (old_table)
Extra_MmFixedStart (sizeof (stmm_table_entry));
for (i = 0; i < num_bins; i++) {
- new_table->bins[i] = NIL (stmm_table_entry);
+ new_table->bins[i] = NULL;
ptr = old_table->bins[i];
- while (ptr != NIL (stmm_table_entry)) {
+ while (ptr != NULL) {
// new = ALLOC( stmm_table_entry, 1 );
new =
(stmm_table_entry *) Extra_MmFixedEntryFetch (new_table->
pMemMan);
- if (new == NIL (stmm_table_entry)) {
+ if (new == NULL) {
/*
for ( j = 0; j <= i; j++ )
{
newptr = new_table->bins[j];
- while ( newptr != NIL( stmm_table_entry ) )
+ while ( newptr != NULL )
{
next = newptr->next;
FREE( newptr );
@@ -446,7 +450,7 @@ stmm_copy (old_table)
FREE (new_table->bins);
FREE (new_table);
- return NIL (stmm_table);
+ return NULL;
}
*new = *ptr;
new->next = new_table->bins[i];
@@ -471,12 +475,12 @@ stmm_delete (table, keyp, value)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
*last = ptr->next;
- if (value != NIL (char *))
+ if (value != NULL)
*value = ptr->record;
*keyp = ptr->key;
// FREE( ptr );
@@ -500,12 +504,12 @@ stmm_delete_int (table, keyp, value)
FIND_ENTRY (table, hash_val, key, ptr, last);
- if (ptr == NIL (stmm_table_entry)) {
+ if (ptr == NULL) {
return 0;
}
*last = ptr->next;
- if (value != NIL (char *))
+ if (value != NULL)
*value = ptr->record;
*keyp = (long) ptr->key;
// FREE( ptr );
@@ -528,7 +532,7 @@ stmm_foreach (table, func, arg)
for (i = 0; i < table->num_bins; i++) {
last = &table->bins[i];
ptr = *last;
- while (ptr != NIL (stmm_table_entry)) {
+ while (ptr != NULL) {
retval = (*func) (ptr->key, ptr->record, arg);
switch (retval) {
case STMM_CONTINUE:
@@ -604,11 +608,11 @@ stmm_init_gen (table)
stmm_generator *gen;
gen = ALLOC (stmm_generator, 1);
- if (gen == NIL (stmm_generator)) {
- return NIL (stmm_generator);
+ if (gen == NULL) {
+ return NULL;
}
gen->table = table;
- gen->entry = NIL (stmm_table_entry);
+ gen->entry = NULL;
gen->index = 0;
return gen;
}
@@ -622,16 +626,16 @@ stmm_gen (gen, key_p, value_p)
{
register int i;
- if (gen->entry == NIL (stmm_table_entry)) {
+ if (gen->entry == NULL) {
/* try to find next entry */
for (i = gen->index; i < gen->table->num_bins; i++) {
- if (gen->table->bins[i] != NIL (stmm_table_entry)) {
+ if (gen->table->bins[i] != NULL) {
gen->index = i + 1;
gen->entry = gen->table->bins[i];
break;
}
}
- if (gen->entry == NIL (stmm_table_entry)) {
+ if (gen->entry == NULL) {
return 0; /* that's all folks ! */
}
}
@@ -652,21 +656,21 @@ stmm_gen_int (gen, key_p, value_p)
{
register int i;
- if (gen->entry == NIL (stmm_table_entry)) {
+ if (gen->entry == NULL) {
/* try to find next entry */
for (i = gen->index; i < gen->table->num_bins; i++) {
- if (gen->table->bins[i] != NIL (stmm_table_entry)) {
+ if (gen->table->bins[i] != NULL) {
gen->index = i + 1;
gen->entry = gen->table->bins[i];
break;
}
}
- if (gen->entry == NIL (stmm_table_entry)) {
+ if (gen->entry == NULL) {
return 0; /* that's all folks ! */
}
}
*key_p = gen->entry->key;
- if (value_p != NIL (long))
+ if (value_p != 0)
{
*value_p = (long) gen->entry->record;
}
diff --git a/src/misc/st/stmm.h b/src/misc/st/stmm.h
index 1fe3dfd2..d7b8a3f3 100644
--- a/src/misc/st/stmm.h
+++ b/src/misc/st/stmm.h
@@ -93,7 +93,7 @@ EXTERN void stmm_clean ARGS ((stmm_table *));
// added by Zhihong: no need for memory allocation
#define stmm_foreach_item2(tb, /* stmm_generator */gen, key, value) \
- for(gen.table=(tb), gen.entry=NIL(stmm_table_entry), gen.index=0; \
+ for(gen.table=(tb), gen.entry=NULL, gen.index=0; \
stmm_gen(&(gen),key,value);)
#define stmm_foreach_item(table, gen, key, value) \
diff --git a/src/misc/util/cpu_stats.c b/src/misc/util/cpu_stats.c
deleted file mode 100644
index aa2d18ef..00000000
--- a/src/misc/util/cpu_stats.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Revision Control Information
- *
- * /projects/hsis/CVS/utilities/util/cpu_stats.c,v
- * rajeev
- * 1.4
- * 1995/08/08 22:41:17
- *
- */
-/* LINTLIBRARY */
-
-#include <stdio.h>
-#include "util.h"
-
-
-#include <sys/types.h>
-//#include <sys/time.h>
-#ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-#endif
-
-#if defined(_IBMR2)
-#define etext _etext
-#define edata _edata
-#define end _end
-#endif
-
-#ifndef __CYGWIN32__
-extern int end, etext, edata;
-#endif
-
-void
-util_print_cpu_stats(fp)
-FILE *fp;
-{
- (void) fprintf(fp, "Usage statistics not available\n");
-}
-
-#if 0
-
-void
-util_print_cpu_stats(fp)
-FILE *fp;
-{
-#if HAVE_SYS_RESOURCE_H && !defined(__CYGWIN32__)
- struct rusage rusage;
-#ifdef RLIMIT_DATA
- struct rlimit rlp;
-#endif
- int text, data, vm_limit, vm_soft_limit;
- double user, system, scale;
- char hostname[257];
- int vm_text, vm_init_data, vm_uninit_data, vm_sbrk_data;
-
- /* Get the hostname */
- (void) gethostname(hostname, 256);
- hostname[256] = '\0'; /* just in case */
-
- /* Get the virtual memory sizes */
- vm_text = ((int) (&etext)) / 1024.0 + 0.5;
- vm_init_data = ((int) (&edata) - (int) (&etext)) / 1024.0 + 0.5;
- vm_uninit_data = ((int) (&end) - (int) (&edata)) / 1024.0 + 0.5;
- vm_sbrk_data = (sizeof(char) * ((char *) sbrk(0) - (char *) (&end))) / 1024.0 + 0.5;
-
- /* Get virtual memory limits */
-#ifdef RLIMIT_DATA /* In HP-UX, with cc, this constant does not exist */
- (void) getrlimit(RLIMIT_DATA, &rlp);
- vm_limit = rlp.rlim_max / 1024.0 + 0.5;
- vm_soft_limit = rlp.rlim_cur / 1024.0 + 0.5;
-#else
- vm_limit = -1;
- vm_soft_limit = -1;
-#endif
-
- /* Get usage stats */
- (void) getrusage(RUSAGE_SELF, &rusage);
- user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec/1.0e6;
- system = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec/1.0e6;
- scale = (user + system)*100.0;
- if (scale == 0.0) scale = 0.001;
-
- (void) fprintf(fp, "Runtime Statistics\n");
- (void) fprintf(fp, "------------------\n");
- (void) fprintf(fp, "Machine name: %s\n", hostname);
- (void) fprintf(fp, "User time %6.1f seconds\n", user);
- (void) fprintf(fp, "System time %6.1f seconds\n\n", system);
-
- text = rusage.ru_ixrss / scale + 0.5;
- data = (rusage.ru_idrss + rusage.ru_isrss) / scale + 0.5;
- (void) fprintf(fp, "Average resident text size = %5dK\n", text);
- (void) fprintf(fp, "Average resident data+stack size = %5dK\n", data);
- (void) fprintf(fp, "Maximum resident size = %5ldK\n\n",
- rusage.ru_maxrss/2);
- (void) fprintf(fp, "Virtual text size = %5dK\n",
- vm_text);
- (void) fprintf(fp, "Virtual data size = %5dK\n",
- vm_init_data + vm_uninit_data + vm_sbrk_data);
- (void) fprintf(fp, " data size initialized = %5dK\n",
- vm_init_data);
- (void) fprintf(fp, " data size uninitialized = %5dK\n",
- vm_uninit_data);
- (void) fprintf(fp, " data size sbrk = %5dK\n",
- vm_sbrk_data);
- /* In some platforms, this constant does not exist */
-#ifdef RLIMIT_DATA
- (void) fprintf(fp, "Virtual memory limit = %5dK (%dK)\n\n",
- vm_soft_limit, vm_limit);
-#endif
- (void) fprintf(fp, "Major page faults = %ld\n", rusage.ru_majflt);
- (void) fprintf(fp, "Minor page faults = %ld\n", rusage.ru_minflt);
- (void) fprintf(fp, "Swaps = %ld\n", rusage.ru_nswap);
- (void) fprintf(fp, "Input blocks = %ld\n", rusage.ru_inblock);
- (void) fprintf(fp, "Output blocks = %ld\n", rusage.ru_oublock);
- (void) fprintf(fp, "Context switch (voluntary) = %ld\n", rusage.ru_nvcsw);
- (void) fprintf(fp, "Context switch (involuntary) = %ld\n", rusage.ru_nivcsw);
-#else /* Do not have sys/resource.h */
- (void) fprintf(fp, "Usage statistics not available\n");
-#endif
-}
-
-#endif
-
diff --git a/src/misc/util/cpu_time.c b/src/misc/util/cpu_time.c
deleted file mode 100644
index d264bdc9..00000000
--- a/src/misc/util/cpu_time.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/**CFile***********************************************************************
-
- FileName [ cpu_time.c ]
-
- PackageName [ util ]
-
- Synopsis [ System time calls ]
-
- Description [ The problem is that all unix systems have a different notion
- of how fast time goes (i.e., the units returned by). This
- returns a consistent result. ]
-
- Author [ Stephen Edwards <sedwards@eecs.berkeley.edu> and others ]
-
- Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California.
- All rights reserved.
-
- Permission is hereby granted, without written agreement and without license
- or royalty fees, to use, copy, modify, and distribute this software and its
- documentation for any purpose, provided that the above copyright notice and
- the following two paragraphs appear in all copies of this software.
-
- IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
- DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
- CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
- "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
- MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
-
-******************************************************************************/
-
-#include "util.h"
-
-#if HAVE_SYS_TYPES_H
-# include<sys/types.h>
-#endif
-
-#if HAVE_SYS_TIMES_H
-# include<sys/times.h>
-#endif
-
-/**AutomaticStart*************************************************************/
-
-/*---------------------------------------------------------------------------*/
-/* Static function prototypes */
-/*---------------------------------------------------------------------------*/
-
-/**AutomaticEnd***************************************************************/
-
-/**Function********************************************************************
-
- Synopsis [ Return elapsed time in milliseconds ]
-
- Description [ Return a long which represents the elapsed time in
- milliseconds since some constant reference. <P>
-
- There are two possibilities:
- <OL>
- <LI> The system is non-POSIX compliant, so unistd.h
- and hence sysconf() can't tell us the clock tick
- speed. At this point, we have to resort to
- using the user-settable CLOCK_RESOLUTION definition
- to get the right speed
- <LI> The system is POSIX-compliant. unistd.h gives
- us sysconf(), which tells us the clock rate.
- </OL>
- ]
-
- SideEffects [ none ]
-
-******************************************************************************/
-
-/*
-long
-util_cpu_time()
-{
- long t = 0;
-
-#if HAVE_SYSCONF == 1
-
- // Code for POSIX systems
-
- struct tms buffer;
- long nticks; // number of clock ticks per second
-
- nticks = sysconf(_SC_CLK_TCK);
- times(&buffer);
- t = buffer.tms_utime * (1000.0/nticks);
-
-#else
-# ifndef vms
-
- // Code for non-POSIX systems
-
- struct tms buffer;
-
- time(&buffer);
- t = buffer.tms_utime * 1000.0 / CLOCK_RESOLUTION;
-
-# else
-
- // Code for VMS (?)
-
- struct {int p1, p2, p3, p4;} buffer;
- static long ref_time;
- times(&buffer);
- t = buffer.p1 * 10;
- if (ref_time == 0)
- ref_time = t;
- t = t - ref_time;
-
-# endif // vms
-#endif // _POSIX_VERSION
-
- return t;
-}
-*/
-
-
-long
-util_cpu_time()
-{
- return clock();
-}
diff --git a/src/misc/util/datalimit.c b/src/misc/util/datalimit.c
deleted file mode 100644
index 96c2ce95..00000000
--- a/src/misc/util/datalimit.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/**CFile************************************************************************
-
- FileName [datalimit.c]
-
- PackageName [util]
-
- Synopsis [Routine to obtain the maximum data size available to a program. The
- routine is based on "getrlimit". If the system does not have this function,
- the default value RLIMIT_DATA_DEFAULT is assumed. This function provides an
- informative value, it does not restrict the size of the program in any way.]
-
- Author [Fabio Somenzi <fabio@colorado.edu>]
-
- Copyright [This file was created at the University of Colorado at
- Boulder. The University of Colorado at Boulder makes no warranty
- about the suitability of this software for any purpose. It is
- presented on an AS IS basis.]
-
-******************************************************************************/
-
-#include "util.h"
-
-static char rcsid[] UNUSED = "$Id: datalimit.c,v 1.1.1.1 2003/02/24 22:24:04 wjiang Exp $";
-
-#if HAVE_SYS_RESOURCE_H
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <sys/resource.h>
-#endif
-
-/*---------------------------------------------------------------------------*/
-/* Type declarations */
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* Structure declarations */
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* Macro declarations */
-/*---------------------------------------------------------------------------*/
-
-#ifndef RLIMIT_DATA_DEFAULT
-#define RLIMIT_DATA_DEFAULT 67108864 /* assume 64MB by default */
-#endif
-
-/*---------------------------------------------------------------------------*/
-/* Variable declarations */
-/*---------------------------------------------------------------------------*/
-
-/**AutomaticStart*************************************************************/
-
-/*---------------------------------------------------------------------------*/
-/* Static function prototypes */
-/*---------------------------------------------------------------------------*/
-
-/**AutomaticEnd***************************************************************/
-
-/*---------------------------------------------------------------------------*/
-/* Definition of exported functions */
-/*---------------------------------------------------------------------------*/
-
-/**Function********************************************************************
-
- Synopsis [Function that computes the data limit of the process.]
-
- SideEffects []
-
-******************************************************************************/
-int
-getSoftDataLimit()
-{
-#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && defined(RLIMIT_DATA)
- struct rlimit rl;
- int result;
-
- result = getrlimit(RLIMIT_DATA, &rl);
- if (result != 0 || rl.rlim_cur == RLIM_INFINITY)
- return(RLIMIT_DATA_DEFAULT);
- else
- return(rl.rlim_cur);
-#else
- return(RLIMIT_DATA_DEFAULT);
-#endif
-
-} /* end of getSoftDataLimit */
-
-/*---------------------------------------------------------------------------*/
-/* Definition of internal functions */
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* Definition of static functions */
-/*---------------------------------------------------------------------------*/
diff --git a/src/misc/util/getopt.c b/src/misc/util/getopt.c
deleted file mode 100644
index 778c34d6..00000000
--- a/src/misc/util/getopt.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Revision Control Information
- *
- * /projects/hsis/CVS/utilities/util/getopt.c,v
- * rajeev
- * 1.3
- * 1995/08/08 22:41:22
- *
- */
-/* LINTLIBRARY */
-
-#include <stdio.h>
-#include "util.h"
-
-
-/* File : getopt.c
- * Author : Henry Spencer, University of Toronto
- * Updated: 28 April 1984
- *
- * Changes: (R Rudell)
- * changed index() to strchr();
- * added getopt_reset() to reset the getopt argument parsing
- *
- * Purpose: get option letter from argv.
- */
-
-char *util_optarg; /* Global argument pointer. */
-int util_optind = 0; /* Global argv index. */
-static char *scan;
-
-
-void
-util_getopt_reset()
-{
- util_optarg = 0;
- util_optind = 0;
- scan = 0;
-}
-
-
-
-int
-util_getopt(argc, argv, optstring)
-int argc;
-char *argv[];
-char *optstring;
-{
- register int c;
- register char *place;
-
- util_optarg = NIL(char);
-
- if (scan == NIL(char) || *scan == '\0') {
- if (util_optind == 0) util_optind++;
- if (util_optind >= argc) return EOF;
- place = argv[util_optind];
- if (place[0] != '-' || place[1] == '\0') return EOF;
- util_optind++;
- if (place[1] == '-' && place[2] == '\0') return EOF;
- scan = place+1;
- }
-
- c = *scan++;
- place = strchr(optstring, c);
- if (place == NIL(char) || c == ':') {
- (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
- return '?';
- }
- if (*++place == ':') {
- if (*scan != '\0') {
- util_optarg = scan;
- scan = NIL(char);
- } else {
- if (util_optind >= argc) {
- (void) fprintf(stderr, "%s: %c requires an argument\n",
- argv[0], c);
- return '?';
- }
- util_optarg = argv[util_optind];
- util_optind++;
- }
- }
- return c;
-}
diff --git a/src/misc/util/leaks.h b/src/misc/util/leaks.h
index daa628b1..1a32062a 100644
--- a/src/misc/util/leaks.h
+++ b/src/misc/util/leaks.h
@@ -1,8 +1,8 @@
-///////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
// This file is used to detect memory leaks using Visual Studio 6.0
-// The idea comes from the following webpage:
-// http://www.michaelmoser.org/memory.htm
-//////////////////////////////////////
+// The idea comes from this page: http://www.michaelmoser.org/memory.htm
+// In addition to this file, it required the presence of "stdlib_hack.h"
+//////////////////////////////////////////////////////////////////////////
#ifndef __LEAKS_H__
#define __LEAKS_H__
diff --git a/src/misc/util/module.make b/src/misc/util/module.make
index 06eba7e4..d6d908e7 100644
--- a/src/misc/util/module.make
+++ b/src/misc/util/module.make
@@ -1,8 +1 @@
-SRC += src/misc/util/cpu_stats.c \
- src/misc/util/cpu_time.c \
- src/misc/util/datalimit.c \
- src/misc/util/getopt.c \
- src/misc/util/pathsearch.c \
- src/misc/util/safe_mem.c \
- src/misc/util/strsav.c \
- src/misc/util/texpand.c
+SRC +=
diff --git a/src/misc/util/pathsearch.c b/src/misc/util/pathsearch.c
deleted file mode 100644
index d4d845eb..00000000
--- a/src/misc/util/pathsearch.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Revision Control Information
- *
- * /projects/hsis/CVS/utilities/util/pathsearch.c,v
- * rajeev
- * 1.3
- * 1995/08/08 22:41:24
- *
- */
-/* LINTLIBRARY */
-
-#if HAVE_SYS_FILE_H
-# include <sys/file.h>
-#endif
-
-#if HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-
-#include "util.h"
-
-/**Function********************************************************************
-
- Synopsis [ Check that a given file is present and accessible ]
-
- SideEffects [none]
-******************************************************************************/
-static int
-check_file(filename, mode)
-char *filename;
-char *mode;
-{
-#if defined(HAVE_SYS_STAT_H)
- struct stat stat_rec;
- int access_char = mode[0];
- int access_mode = R_OK;
-
- /* First check that the file is a regular file. */
-
- if (stat(filename,&stat_rec) == 0
- && (stat_rec.st_mode&S_IFMT) == S_IFREG) {
- if (access_char == 'w') {
- access_mode = W_OK;
- } else if (access_char == 'x') {
- access_mode = X_OK;
- }
- return access(filename,access_mode) == 0;
- }
- return 0;
-
-#else
-
- FILE *fp;
- int got_file;
-
- if (strcmp(mode, "x") == 0) {
- mode = "r";
- }
- fp = fopen(filename, mode);
- got_file = (fp != 0);
- if (fp != 0) {
- (void) fclose(fp);
- }
- return got_file;
-
-#endif
-}
-
-/**Function********************************************************************
-
- Synopsis [ Search for a program in all possible paths ]
-
- SideEffects [none]
-
-******************************************************************************/
-char *
-util_path_search(prog)
-char *prog;
-{
-#ifdef HAVE_GETENV
- return util_file_search(prog, getenv("PATH"), "x");
-#else
- return util_file_search(prog, NIL(char), "x");
-#endif
-}
-
-char *
-util_file_search(file, path, mode)
-char *file; /* file we're looking for */
-char *path; /* search path, colon separated */
-char *mode; /* "r", "w", or "x" */
-{
- int quit;
- char *buffer, *filename, *save_path, *cp;
-
- if (path == 0 || strcmp(path, "") == 0) {
- path = "."; /* just look in the current directory */
- }
-
- save_path = path = util_strsav(path);
- quit = 0;
- do {
- cp = strchr(path, ':');
- if (cp != 0) {
- *cp = '\0';
- } else {
- quit = 1;
- }
-
- /* cons up the filename out of the path and file name */
- if (strcmp(path, ".") == 0) {
- buffer = util_strsav(file);
- } else {
- buffer = ALLOC(char, strlen(path) + strlen(file) + 4);
- (void) sprintf(buffer, "%s/%s", path, file);
- }
- filename = util_tilde_expand(buffer);
- FREE(buffer);
-
- /* see if we can access it */
- if (check_file(filename, mode)) {
- FREE(save_path);
- return filename;
- }
- FREE(filename);
- path = ++cp;
- } while (! quit);
-
- FREE(save_path);
- return 0;
-}
diff --git a/src/misc/util/safe_mem.c b/src/misc/util/safe_mem.c
deleted file mode 100644
index 5a8a5de8..00000000
--- a/src/misc/util/safe_mem.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Revision Control Information
- *
- * /projects/hsis/CVS/utilities/util/safe_mem.c,v
- * rajeev
- * 1.3
- * 1995/08/08 22:41:29
- *
- */
-/* LINTLIBRARY */
-
-#include "util.h"
-
-/*
- * These are interface routines to be placed between a program and the
- * system memory allocator.
- *
- * It forces well-defined semantics for several 'borderline' cases:
- *
- * malloc() of a 0 size object is guaranteed to return something
- * which is not 0, and can safely be freed (but not dereferenced)
- * free() accepts (silently) an 0 pointer
- * realloc of a 0 pointer is allowed, and is equiv. to malloc()
- * For the IBM/PC it forces no object > 64K; note that the size argument
- * to malloc/realloc is a 'long' to catch this condition
- *
- * The function pointer MMoutOfMemory() contains a vector to handle a
- * 'out-of-memory' error (which, by default, points at a simple wrap-up
- * and exit routine).
- */
-
-extern char *MMalloc();
-extern void MMout_of_memory();
-extern char *MMrealloc();
-
-
-void (*MMoutOfMemory)() = MMout_of_memory;
-
-
-/* MMout_of_memory -- out of memory for lazy people, flush and exit */
-void
-MMout_of_memory(size)
-long size;
-{
- (void) fflush(stdout);
- (void) fprintf(stderr, "\nout of memory allocating %u bytes\n",
- (unsigned) size);
- assert( 0 );
- exit(1);
-}
-
-
-char *
-MMalloc(size)
-long size;
-{
- char *p;
-
-#ifdef IBMPC
- if (size > 65000L) {
- if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size);
- return NIL(char);
- }
-#endif
- if (size == 0) size = sizeof(long);
- if ((p = (char *) malloc((unsigned) size)) == NIL(char)) {
- if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size);
- return NIL(char);
- }
- return p;
-}
-
-
-char *
-MMrealloc(obj, size)
-char *obj;
-long size;
-{
- char *p;
-
-#ifdef IBMPC
- if (size > 65000L) {
- if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size);
- return NIL(char);
- }
-#endif
- if (obj == NIL(char)) return MMalloc(size);
- if (size <= 0) size = sizeof(long);
- if ((p = (char *) realloc(obj, (unsigned) size)) == NIL(char)) {
- if (MMoutOfMemory != (void (*)()) 0 ) (*MMoutOfMemory)(size);
- return NIL(char);
- }
- return p;
-}
-
-
-void
-MMfree(obj)
-char *obj;
-{
- if (obj != 0) {
- free(obj);
- }
-}
diff --git a/src/misc/util/strsav.c b/src/misc/util/strsav.c
deleted file mode 100644
index 8da1f0c9..00000000
--- a/src/misc/util/strsav.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Revision Control Information
- *
- * /projects/hsis/CVS/utilities/util/strsav.c,v
- * shiple
- * 1.4
- * 1995/08/30 17:37:58
- *
- */
-/* LINTLIBRARY */
-
-#include <stdio.h>
-#include "util.h"
-
-
-/*
- * util_strsav -- save a copy of a string
- */
-char *
-util_strsav(s)
-char *s;
-{
- if(s == NIL(char)) { /* added 7/95, for robustness */
- return s;
- }
- else {
- return strcpy(ALLOC(char, strlen(s)+1), s);
- }
-}
-
-/*
- * util_inttostr -- converts an integer into a string
- */
-char *
-util_inttostr(i)
- int i;
-{
- unsigned int mod, len;
- char *s;
-
- if (i == 0)
- len = 1;
- else {
- if (i < 0) {
- len = 1;
- mod = -i;
- }
- else {
- len = 0;
- mod = i;
- }
- len += (unsigned)floor(log10(mod)) + 1;
- }
-
- s = ALLOC(char, len + 1);
- sprintf(s, "%d", i);
-
- return s;
-}
-
-/*
- * util_strcat3 -- Creates a new string which is the concatenation of 3
- * strings. It is the responsibility of the caller to free this string
- * using FREE.
- */
-char *
-util_strcat3(
- char * str1,
- char * str2,
- char * str3)
-{
- char *str = ALLOC(char, strlen(str1) + strlen(str2) + strlen(str3) + 1);
-
- (void) strcpy(str, str1);
- (void) strcat(str, str2);
- (void) strcat(str, str3);
-
- return (str);
-}
-
-/*
- * util_strcat4 -- Creates a new string which is the concatenation of 4
- * strings. It is the responsibility of the caller to free this string
- * using FREE.
- */
-char *
-util_strcat4(
- char * str1,
- char * str2,
- char * str3,
- char * str4)
-{
- char *str = ALLOC(char, strlen(str1) + strlen(str2) + strlen(str3) +
- strlen(str4) + 1);
-
- (void) strcpy(str, str1);
- (void) strcat(str, str2);
- (void) strcat(str, str3);
- (void) strcat(str, str4);
-
- return (str);
-}
-
-
-#if !HAVE_STRSTR
-/**Function********************************************************************
-
- Synopsis [required]
-
- Description [optional]
-
- SideEffects [required]
-
- SeeAlso [optional]
-
-******************************************************************************/
-char *
-strstr(
- const char * s,
- const char * pat)
-{
- int len;
-
- len = strlen(pat);
- for (; *s != '\0'; ++s)
- if (*s == *pat && memcmp(s, pat, len) == 0) {
- return (char *)s; /* UGH */
- }
- return NULL;
-}
-#endif /* !HAVE_STRSTR */
-
-#if !HAVE_STRCHR
-/**Function********************************************************************
-
- Synopsis [required]
-
- Description [optional]
-
- SideEffects [required]
-
- SeeAlso [optional]
-
-******************************************************************************/
-char *
-strchr(const char * s,
- int c)
-{
- for (; *s != '\0'; s++) {
- if (*s == c) {
- return (char *)s;
- }
- }
- return NULL;
-
-}
-#endif /* !HAVE_STRCHR */
diff --git a/src/misc/util/texpand.c b/src/misc/util/texpand.c
deleted file mode 100644
index 37f71cbd..00000000
--- a/src/misc/util/texpand.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Revision Control Information
- *
- * /projects/hsis/CVS/utilities/util/texpand.c,v
- * rajeev
- * 1.3
- * 1995/08/08 22:41:36
- *
- */
-
-#include "util.h"
-
-#if HAVE_PWD_H
-# include <pwd.h>
-#endif
-
-
-char *
-util_tilde_expand(fname)
-char *fname;
-{
-#if HAVE_PWD_H
- struct passwd *userRecord;
- char username[256], *filename, *dir;
- register int i, j;
-
- filename = ALLOC(char, strlen(fname) + 256);
-
- /* Clear the return string */
- i = 0;
- filename[0] = '\0';
-
- /* Tilde? */
- if (fname[0] == '~') {
- j = 0;
- i = 1;
- while ((fname[i] != '\0') && (fname[i] != '/')) {
- username[j++] = fname[i++];
- }
- username[j] = '\0';
- dir = (char *)0;
- if (username[0] == '\0') {
- /* ~/ resolves to home directory of current user */
- userRecord = getpwuid(getuid());
- if (userRecord) dir = userRecord->pw_dir;
- } else {
- /* Special check for ~octtools */
- if (!strcmp(username,"octtools"))
- dir = getenv("OCTTOOLS");
- /* ~user/ resolves to home directory of 'user' */
- if (!dir) {
- userRecord = getpwnam(username);
- if (userRecord) dir = userRecord->pw_dir;
- }
- }
- if (dir) (void) strcat(filename, dir);
- else i = 0; /* leave fname as-is */
- } /* if tilde */
-
- /* Concantenate remaining portion of file name */
- (void) strcat(filename, fname + i);
- return filename;
-#else
- return util_strsav(fname);
-#endif
-}
diff --git a/src/misc/util/util.h b/src/misc/util/util.h
deleted file mode 100644
index 0b147347..00000000
--- a/src/misc/util/util.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/**CHeaderFile*****************************************************************
-
- FileName [ util.h ]
-
- PackageName [ util ]
-
- Synopsis [ Very low-level utilities ]
-
- Description [ Includes file access, pipes, forks, time, and temporary file
- access. ]
-
- Author [ Stephen Edwards <sedwards@eecs.berkeley.edu> and many others]
-
- Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California.
- All rights reserved.
-
- Permission is hereby granted, without written agreement and without license
- or royalty fees, to use, copy, modify, and distribute this software and its
- documentation for any purpose, provided that the above copyright notice and
- the following two paragraphs appear in all copies of this software.
-
- IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
- DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
- CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
- "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
- MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
-
- Revision [$Id: util.h,v 1.11 1998/05/04 02:05:08 hsv Exp $]
-
-******************************************************************************/
-
-#ifndef _UTIL
-#define _UTIL
-
-////////////////////////////////////////////
-#include "leaks.h"
-////////////////////////////////////////////
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-//////////////// added by alanmi, November 22, 2001 ////////////////
-//#include <ctype.h>
-#include <time.h>
-#include <signal.h>
-
-#ifndef SIGALRM
-#define SIGALRM SIGINT
-#endif
-
-#ifndef SIGSTOP
-#define SIGSTOP SIGINT
-#endif
-
-#ifndef SIGXCPU
-#define SIGXCPU SIGINT
-#endif
-
-#ifndef SIGUSR1
-#define SIGUSR1 SIGINT
-#endif
-
-#ifndef SIGKILL
-#define SIGKILL SIGINT
-#endif
-
-#ifndef HUGE
-#define HUGE HUGE_VAL
-#endif
-
-#if defined(__STDC__)
-#define SIGNAL_FN void
-#endif
-
-#define alarm(n) ((void)0)
-#define kill(a,b) ((void)0)
-
-#define random rand
-#define srandom srand
-////////////////////////////////////////////////////////////////////
-
-
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#if HAVE_VARARGS_H
-///////////////////////////////////////
-#undef __STDC__
-# include <varargs.h>
-#define __STDC__ 1
-////////////////// alanmi Feb 03, 2001
-#endif
-
-#ifndef STDC_HEADERS
-#define STDC_HEADERS 1
-#endif
-
-#ifndef HAVE_STRCHR
-#define HAVE_STRCHR 1
-#endif
-
-#ifndef HAVE_GETENV
-#define HAVE_GETENV 1
-#endif
-
-#if STDC_HEADERS
-//# include <stdlib.h>
-# include <string.h>
-#else
-# ifdef HAVE_STRCHR
-char * strchr();
-int strcmp();
-# else
-# define strchr index
-# endif
-# ifdef HAVE_GETENV
-char * getenv();
-# endif
-#endif /* STDC_HEADERS */
-
-#if HAVE_ERRNO_H
-# include <errno.h>
-#endif
-
-/*
- * Ensure we have reasonable assert() and fail() functions
- */
-
-#ifndef HAVE_ASSERT_H
-#define HAVE_ASSERT_H 1
-#endif
-
-#if HAVE_ASSERT_H
-# include <assert.h>
-#else
-# ifdef NDEBUG
-# define assert(ex) ;
-# else
-# define assert(ex) {\
- if (! (ex)) {\
- (void) fprintf(stderr,\
- "Assertion failed: file %s, line %d\n\"%s\"\n",\
- __FILE__, __LINE__, "ex");\
- (void) fflush(stdout);\
- abort();\
- }\
-}
-# endif
-#endif
-
-#define fail(why) {\
- (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
- __FILE__, __LINE__, why);\
- (void) fflush(stdout);\
- abort();\
-}
-
-/*
- * Support for ANSI function prototypes in non-ANSI compilers
- *
- * Usage:
- * extern int foo ARGS((char *, double))
- */
-
-#ifndef ARGS
-# ifdef __STDC__
-# define ARGS(args) args
-# else
-# define ARGS(args) ()
-# endif
-#endif
-
-#ifndef NULLARGS
-# ifdef __STDC__
-# define NULLARGS (void)
-# else
-# define NULLARGS ()
-# endif
-#endif
-
-/*
- * A little support for C++ compilers
- */
-
-#ifdef __cplusplus
-# define EXTERN extern "C"
-#else
-# define EXTERN extern
-#endif
-
-/*
- * Support to define unused varibles
- */
-#if (__GNUC__ >2 || __GNUC_MINOR__ >=7) && !defined(UNUSED)
-#define UNUSED __attribute__ ((unused))
-#else
-#define UNUSED
-#endif
-
-/*
- * A neater way to define zero pointers
- *
- * Usage:
- * int * fred;
- * fred = NIL(int);
- */
-
-#define NIL(type) ((type *) 0)
-
-/*
- * Left over from SIS and Octtools:
- */
-
-//#define USE_MM
-// uncommented this line,
-// because to detect memory leaks, we need to work with malloc(), etc directly
-#define USE_MM
-
-
-
-#ifdef USE_MM
-/*
- * assumes the memory manager is libmm.a (a deprecated (?) Octtools library)
- * - allows malloc(0) or realloc(obj, 0)
- * - catches out of memory (and calls MMout_of_memory())
- * - catch free(0) and realloc(0, size) in the macros
- */
-# define ALLOC(type, num) \
- ((type *) malloc(sizeof(type) * (num)))
-# define REALLOC(type, obj, num) \
- (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \
- ((type *) malloc(sizeof(type) * (num)))
-# define FREE(obj) \
- ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
-#else
-/*
- * enforce strict semantics on the memory allocator
- */
-# define ALLOC(type, num) \
- ((type *) MMalloc((long) sizeof(type) * (long) (num)))
-# define REALLOC(type, obj, num) \
- ((type *) MMrealloc((char *) (obj), (long) sizeof(type) * (long) (num)))
-# define FREE(obj) \
- ((obj) ? (free((void *) (obj)), (obj) = 0) : 0)
-EXTERN void MMout_of_memory ARGS((long));
-EXTERN char *MMalloc ARGS((long));
-EXTERN char *MMrealloc ARGS((char *, long));
-EXTERN void MMfree ARGS((char *));
-#endif
-
-#ifndef TRUE
-# define TRUE 1
-#endif
-
-#ifndef FALSE
-# define FALSE 0
-#endif
-
-#ifndef ABS
-# define ABS(a) ((a) < 0 ? -(a) : (a))
-#endif
-
-#ifndef MAX
-# define MAX(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-#ifndef MIN
-# define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-#define ptime() util_cpu_time()
-#define print_time(t) util_print_time(t)
-
-#ifndef HUGE_VAL
-# ifndef HUGE
-# define HUGE 8.9884656743115790e+307
-# endif
-# define HUGE_VAL HUGE
-#endif
-
-#ifndef MAXINT
-# define MAXINT (1 << 30)
-#endif
-
-EXTERN void util_print_cpu_stats ARGS((FILE *));
-EXTERN long util_cpu_time ARGS((void));
-EXTERN void util_getopt_reset ARGS((void));
-EXTERN int util_getopt ARGS((int, char **, char *));
-EXTERN char *util_path_search ARGS((char *));
-EXTERN char *util_file_search ARGS((char *, char *, char *));
-EXTERN char *util_print_time ARGS((long));
-EXTERN int util_save_image ARGS((char *, char *));
-EXTERN char *util_strsav ARGS((char *));
-EXTERN char *util_inttostr ARGS((int));
-EXTERN char *util_strcat3 ARGS((char *, char *, char *));
-EXTERN char *util_strcat4 ARGS((char *, char *, char *, char *));
-EXTERN int util_do_nothing ARGS((void));
-EXTERN char *util_tilde_expand ARGS((char *));
-EXTERN char *util_tempnam ARGS((char *, char *));
-EXTERN FILE *util_tmpfile ARGS((void));
-EXTERN void util_srandom ARGS((long));
-EXTERN long util_random ARGS(());
-EXTERN int getSoftDataLimit ARGS(());
-
-/*
- * Global variables for util_getopt()
- */
-
-extern int util_optind;
-extern char *util_optarg;
-
-/**AutomaticStart*************************************************************/
-
-/*---------------------------------------------------------------------------*/
-/* Function prototypes */
-/*---------------------------------------------------------------------------*/
-
-/**AutomaticEnd***************************************************************/
-
-#endif /* _UTIL */
diff --git a/src/misc/util/util_hack.h b/src/misc/util/util_hack.h
new file mode 100644
index 00000000..57914c47
--- /dev/null
+++ b/src/misc/util/util_hack.h
@@ -0,0 +1,87 @@
+/**CFile****************************************************************
+
+ FileName [util_hack.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [This file is used to simulate the presence of "util.h".]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: util_hack.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __UTIL_HACK_H__
+#define __UTIL_HACK_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+#include <math.h>
+
+#define EXTERN extern
+#define NIL(type) ((type *) 0)
+#define random rand
+#define srandom srand
+
+#define util_cpu_time Extra_CpuTime
+#define getSoftDataLimit Extra_GetSoftDataLimit
+#define util_getopt_reset Extra_UtilGetoptReset
+#define util_getopt Extra_UtilGetopt
+#define util_print_time Extra_UtilPrintTime
+#define util_strsav Extra_UtilStrsav
+#define util_tilde_expand Extra_UtilTildeExpand
+#define util_file_search Extra_UtilFileSearch
+#define MMoutOfMemory Extra_UtilMMoutOfMemory
+
+#define util_optarg globalUtilOptarg
+#define util_optind globalUtilOptind
+
+#ifndef ARGS
+# ifdef __STDC__
+# define ARGS(args) args
+# else
+# define ARGS(args) ()
+# endif
+#endif
+
+#ifndef ABS
+# define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
+#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
+#define REALLOC(type, obj, num) \
+ (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \
+ ((type *) malloc(sizeof(type) * (num)))
+
+extern long Extra_CpuTime();
+extern int Extra_GetSoftDataLimit();
+extern void Extra_UtilGetoptReset();
+extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring );
+extern char * Extra_UtilPrintTime( long t );
+extern char * Extra_UtilStrsav( char *s );
+extern char * Extra_UtilTildeExpand( char *fname );
+extern char * Extra_UtilFileSearch( char *file, char *path, char *mode );
+
+extern char * globalUtilOptarg;
+extern int globalUtilOptind;
+
+#endif
diff --git a/src/misc/vec/vecInt.h b/src/misc/vec/vecInt.h
index 7a96b0d7..06526332 100644
--- a/src/misc/vec/vecInt.h
+++ b/src/misc/vec/vecInt.h
@@ -25,7 +25,6 @@
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
-#include <stdio.h>
#include "extra.h"
////////////////////////////////////////////////////////////////////////
@@ -484,7 +483,7 @@ static inline void Vec_IntPushMem( Extra_MmStep_t * pMemMan, Vec_Int_t * p, int
/**Function*************************************************************
- Synopsis []
+ Synopsis [Inserts the entry while preserving the increasing order.]
Description []
diff --git a/src/opt/cut/cut.h b/src/opt/cut/cut.h
index 5c9b2e8e..b724c976 100644
--- a/src/opt/cut/cut.h
+++ b/src/opt/cut/cut.h
@@ -30,7 +30,7 @@
////////////////////////////////////////////////////////////////////////
#define CUT_SIZE_MIN 3 // the min K of the K-feasible cut computation
-#define CUT_SIZE_MAX 8 // the max K of the K-feasible cut computation
+#define CUT_SIZE_MAX 12 // the max K of the K-feasible cut computation
#define CUT_SHIFT 8 // the number of bits for storing latch number in the cut leaves
#define CUT_MASK 0xFF // the mask to get the stored latch number
@@ -55,7 +55,7 @@ struct Cut_ParamsStruct_t_
int fFilter; // filter dominated cuts
int fSeq; // compute sequential cuts
int fDrop; // drop cuts on the fly
- int fMulti; // compute cuts in multi-input AND gate graph
+ int fMulti; // compute factor-cuts
int fRecord; // record the cut computation flow
int fVerbose; // the verbosiness flag
};
@@ -105,6 +105,7 @@ extern void Cut_NodeFreeCuts( Cut_Man_t * p, int Node );
/*=== cutCut.c ==========================================================*/
extern void Cut_CutPrint( Cut_Cut_t * pCut, int fSeq );
extern void Cut_CutPrintList( Cut_Cut_t * pList, int fSeq );
+extern int Cut_CutCountList( Cut_Cut_t * pList );
/*=== cutMan.c ==========================================================*/
extern Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams );
extern void Cut_ManStop( Cut_Man_t * p );
diff --git a/src/opt/cut/cutInt.h b/src/opt/cut/cutInt.h
index 51ff07f9..eca2fcd5 100644
--- a/src/opt/cut/cutInt.h
+++ b/src/opt/cut/cutInt.h
@@ -80,6 +80,7 @@ struct Cut_ManStruct_t_
int nCutsLimit;
int nNodes;
int nNodesMulti;
+ int nNodesMulti0;
// runtime
int timeMerge;
int timeUnion;
@@ -122,7 +123,6 @@ extern void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut );
extern int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 );
extern Cut_Cut_t * Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList );
extern void Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList );
-extern int Cut_CutCountList( Cut_Cut_t * pList );
extern Cut_Cut_t * Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 );
extern void Cut_CutNumberList( Cut_Cut_t * pList );
extern Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node );
diff --git a/src/opt/cut/cutMan.c b/src/opt/cut/cutMan.c
index b2d62fce..8269da06 100644
--- a/src/opt/cut/cutMan.c
+++ b/src/opt/cut/cutMan.c
@@ -153,6 +153,15 @@ void Cut_ManPrintStats( Cut_Man_t * p )
printf( "Cuts per node = %8.1f\n", ((float)(p->nCutsCur-p->nCutsTriv))/p->nNodes );
printf( "The cut size = %8d bytes.\n", p->EntrySize );
printf( "Peak memory = %8.2f Mb.\n", (float)p->nCutsPeak * p->EntrySize / (1<<20) );
+ if ( p->pParams->fMulti )
+ {
+ printf( "Factor-cut computation statistics:\n" );
+ printf( "Total nodes = %8d.\n", p->nNodes );
+ printf( "Factor nodes = %8d.\n", p->nNodesMulti );
+ printf( "Factor nodes 0 = %8d.\n", p->nNodesMulti0 );
+ printf( "Factor cuts = %8d.\n", p->nCutsMulti );
+ printf( "Cuts per node = %8.1f\n", ((float)(p->nCutsMulti))/(p->nNodesMulti-p->nNodesMulti0) );
+ }
PRT( "Merge ", p->timeMerge );
PRT( "Union ", p->timeUnion );
PRT( "Filter", p->timeFilter );
diff --git a/src/opt/cut/cutNode.c b/src/opt/cut/cutNode.c
index 0268ba19..cace83bd 100644
--- a/src/opt/cut/cutNode.c
+++ b/src/opt/cut/cutNode.c
@@ -355,10 +355,19 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC
{
Cut_Cut_t * pStop0, * pStop1, * pTemp0, * pTemp1;
int i, nCutsOld, Limit;
+ // start with the elementary cut
+ if ( fTriv )
+ {
+// printf( "Creating trivial cut %d.\n", Node );
+ pTemp0 = Cut_CutCreateTriv( p, Node );
+ Cut_ListAdd( pSuper, pTemp0 );
+ p->nNodeCuts++;
+ }
// get the cut lists of children
if ( pList0 == NULL || pList1 == NULL )
return;
- // start the new list
+
+ // remember the old number of cuts
nCutsOld = p->nCutsCur;
Limit = p->pParams->nVarsMax;
// get the simultation bit of the node
@@ -373,15 +382,7 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC
Cut_ListForEachCut( pList1, pStop1 )
if ( pStop1->nLeaves == (unsigned)Limit )
break;
- // start with the elementary cut
- if ( fTriv )
- {
-// printf( "Creating trivial cut %d.\n", Node );
- pTemp0 = Cut_CutCreateTriv( p, Node );
- Cut_ListAdd( pSuper, pTemp0 );
- p->nNodeCuts++;
- nCutsOld++;
- }
+
// small by small
Cut_ListForEachCutStop( pList0, pTemp0, pStop0 )
Cut_ListForEachCutStop( pList1, pTemp1, pStop1 )
@@ -424,6 +425,8 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC
{
p->nCutsMulti += p->nCutsCur - nCutsOld;
p->nNodesMulti++;
+ if ( p->nCutsCur == nCutsOld )
+ p->nNodesMulti0++;
}
}
diff --git a/src/opt/dec/dec.h b/src/opt/dec/dec.h
index b6b2524b..7b8b2e94 100644
--- a/src/opt/dec/dec.h
+++ b/src/opt/dec/dec.h
@@ -628,19 +628,75 @@ static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eE
SeeAlso []
***********************************************************************/
-static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
-{
- Dec_Edge_t eNode0, eNode1;
- // derive the first AND
- eEdge0.fCompl = !eEdge0.fCompl;
- eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
- eEdge0.fCompl = !eEdge0.fCompl;
- // derive the second AND
- eEdge1.fCompl = !eEdge1.fCompl;
- eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
- eEdge1.fCompl = !eEdge1.fCompl;
- // derive the final OR
- return Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type )
+{
+ Dec_Edge_t eNode0, eNode1, eNode;
+ if ( Type == 0 )
+ {
+ // derive the first AND
+ eEdge0.fCompl ^= 1;
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ eEdge0.fCompl ^= 1;
+ // derive the second AND
+ eEdge1.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ }
+ else
+ {
+ // derive the first AND
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ // derive the second AND
+ eEdge0.fCompl ^= 1;
+ eEdge1.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ eNode.fCompl ^= 1;
+ }
+ return eNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates an XOR node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type )
+{
+ Dec_Edge_t eNode0, eNode1, eNode;
+ if ( Type == 0 )
+ {
+ // derive the first AND
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+ // derive the second AND
+ eEdgeC.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ }
+ else
+ {
+ // complement the arguments
+ eEdgeT.fCompl ^= 1;
+ eEdgeE.fCompl ^= 1;
+ // derive the first AND
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+ // derive the second AND
+ eEdgeC.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ eNode.fCompl ^= 1;
+ }
+ return eNode;
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/dec/decAbc.c b/src/opt/dec/decAbc.c
index af76cd84..066b3bb2 100644
--- a/src/opt/dec/decAbc.c
+++ b/src/opt/dec/decAbc.c
@@ -18,7 +18,7 @@
#include "abc.h"
#include "dec.h"
-//#include "aig.h"
+#include "aig.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -214,7 +214,6 @@ void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpda
SeeAlso []
***********************************************************************/
-/*
Aig_Node_t * Dec_GraphToNetworkAig( Aig_Man_t * pMan, Dec_Graph_t * pGraph )
{
Dec_Node_t * pNode;
@@ -236,7 +235,7 @@ Aig_Node_t * Dec_GraphToNetworkAig( Aig_Man_t * pMan, Dec_Graph_t * pGraph )
// complement the result if necessary
return Aig_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
}
-*/
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/opt/fxu/fxuInt.h b/src/opt/fxu/fxuInt.h
index 385cccef..d82a68db 100644
--- a/src/opt/fxu/fxuInt.h
+++ b/src/opt/fxu/fxuInt.h
@@ -23,7 +23,6 @@
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
-#include "util.h"
#include "extra.h"
#include "vec.h"
diff --git a/src/opt/rwr/rwrDec.c b/src/opt/rwr/rwrDec.c
index 45fcb02c..ef7af34f 100644
--- a/src/opt/rwr/rwrDec.c
+++ b/src/opt/rwr/rwrDec.c
@@ -135,7 +135,7 @@ Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t *
eNode1.fCompl = !eNode1.fCompl;
// create the decomposition node(s)
if ( pNode->fExor )
- eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1 );
+ eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 );
else
eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
// save the result
diff --git a/src/opt/rwr/rwrEva.c b/src/opt/rwr/rwrEva.c
index 3f3163f1..71d0b24d 100644
--- a/src/opt/rwr/rwrEva.c
+++ b/src/opt/rwr/rwrEva.c
@@ -66,7 +66,7 @@ int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int
Required = fUpdateLevel? Abc_NodeReadRequiredLevel(pNode) : ABC_INFINITY;
// get the node's cuts
clk = clock();
- pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode );
+ pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0 );
assert( pCut != NULL );
p->timeCut += clock() - clk;
@@ -140,8 +140,9 @@ p->timeRes += clock() - clk;
Dec_GraphNode(p->pGraph, i)->pFunc = pFanin;
p->nScores[p->pMap[uTruthBest]]++;
- p->nNodesRewritten++;
p->nNodesGained += GainBest;
+ if ( fUseZeros || GainBest > 0 )
+ p->nNodesRewritten++;
// report the progress
if ( fVeryVerbose )
diff --git a/src/sat/aig/aig.h b/src/sat/aig/aig.h
index ee029789..c83af527 100644
--- a/src/sat/aig/aig.h
+++ b/src/sat/aig/aig.h
@@ -300,8 +300,9 @@ extern void Aig_ManStop( Aig_Man_t * p );
/*=== aigNode.c =============================================================*/
extern Aig_Node_t * Aig_NodeCreateConst( Aig_Man_t * p );
extern Aig_Node_t * Aig_NodeCreatePi( Aig_Man_t * p );
-extern Aig_Node_t * Aig_NodeCreatePo( Aig_Man_t * p, Aig_Node_t * pFanin );
+extern Aig_Node_t * Aig_NodeCreatePo( Aig_Man_t * p );
extern Aig_Node_t * Aig_NodeCreateAnd( Aig_Man_t * p, Aig_Node_t * pFanin0, Aig_Node_t * pFanin1 );
+extern Aig_Node_t * Aig_NodeConnectPo( Aig_Man_t * p, Aig_Node_t * pNode, Aig_Node_t * pFanin );
extern void Aig_NodeConnectAnd( Aig_Node_t * pFanin0, Aig_Node_t * pFanin1, Aig_Node_t * pNode );
extern void Aig_NodeDisconnectAnd( Aig_Node_t * pNode );
extern void Aig_NodeDeleteAnd_rec( Aig_Man_t * pMan, Aig_Node_t * pRoot );
diff --git a/src/sat/aig/aigNode.c b/src/sat/aig/aigNode.c
index 991cc7e5..ce458353 100644
--- a/src/sat/aig/aigNode.c
+++ b/src/sat/aig/aigNode.c
@@ -104,12 +104,30 @@ Aig_Node_t * Aig_NodeCreatePi( Aig_Man_t * p )
SeeAlso []
***********************************************************************/
-Aig_Node_t * Aig_NodeCreatePo( Aig_Man_t * p, Aig_Node_t * pFanin )
+Aig_Node_t * Aig_NodeCreatePo( Aig_Man_t * p )
{
Aig_Node_t * pNode;
pNode = Aig_NodeCreate( p );
pNode->Type = AIG_PO;
Vec_PtrPush( p->vPos, pNode );
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a primary output node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Node_t * Aig_NodeConnectPo( Aig_Man_t * p, Aig_Node_t * pNode, Aig_Node_t * pFanin )
+{
+ assert( Aig_NodeIsPo(pNode) );
+ assert( !Aig_IsComplement(pNode) );
// connect to the fanin
pNode->Fans[0].fComp = Aig_IsComplement(pFanin);
pNode->Fans[0].iNode = Aig_Regular(pFanin)->Id;
@@ -224,13 +242,14 @@ void Aig_NodeDeleteAnd_rec( Aig_Man_t * pMan, Aig_Node_t * pRoot )
assert( !Aig_IsComplement(pRoot) );
assert( pRoot->nRefs == 0 );
assert( Aig_NodeIsAnd(pRoot) );
- // save the children
+ // remember the children
pNode0 = Aig_NodeFanin0(pRoot);
pNode1 = Aig_NodeFanin1(pRoot);
// disconnect the node
Aig_NodeDisconnectAnd( pRoot );
// recycle the node
Vec_PtrWriteEntry( pMan->vNodes, pRoot->Id, NULL );
+ memset( pRoot, 0, sizeof(Aig_Node_t) ); // this is a temporary hack to skip dead children below!!!
Aig_MemFixedEntryRecycle( pMan->mmNodes, (char *)pRoot );
// call recursively
if ( Aig_NodeIsAnd(pNode0) && pNode0->nRefs == 0 )
diff --git a/src/sat/aig/fraigCore.c b/src/sat/aig/fraigCore.c
index decf05ee..525d4a14 100644
--- a/src/sat/aig/fraigCore.c
+++ b/src/sat/aig/fraigCore.c
@@ -92,7 +92,7 @@ Aig_ProofType_t Aig_FraigProveOutput( Aig_Man_t * pMan )
// solve the miter
clk = clock();
pMan->pSat->verbosity = pMan->pParam->fSatVerbose;
- status = solver_solve( pMan->pSat, NULL, NULL, pMan->pParam->nSeconds );
+ status = solver_solve( pMan->pSat, NULL, NULL, 0, 0 );//pMan->pParam->nConfLimit, pMan->pParam->nImpLimit );
if ( status == l_Undef )
{
// printf( "The problem timed out.\n" );
diff --git a/src/sat/aig/rwrMffc.c b/src/sat/aig/rwrMffc.c
new file mode 100644
index 00000000..663534b3
--- /dev/null
+++ b/src/sat/aig/rwrMffc.c
@@ -0,0 +1,303 @@
+/**CFile****************************************************************
+
+ FileName [rwrMffc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [Procedures working with Maximum Fanout-Free Cones.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: rwrMffc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Aig_NodeDeref_rec( Aig_Node_t * pNode );
+extern int Aig_NodeRef_rec( Aig_Node_t * pNode );
+extern void Aig_NodeMffsConeSupp( Aig_Node_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp );
+extern void Aig_NodeFactorConeSupp( Aig_Node_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_MffcTest( Aig_Man_t * pMan )
+{
+ Aig_Node_t * pNode, * pNodeA, * pNodeB, * pNodeC, * pLeaf;
+ Vec_Ptr_t * vCone, * vSupp;
+ int i, k;//, nNodes1, nNodes2;
+ int nSizes = 0;
+ int nCones = 0;
+ int nMuxes = 0;
+ int nExors = 0;
+
+ vCone = Vec_PtrAlloc( 100 );
+ vSupp = Vec_PtrAlloc( 100 );
+
+ // mark the multiple-fanout nodes
+ Aig_ManForEachAnd( pMan, pNode, i )
+ if ( pNode->nRefs > 1 )
+ pNode->fMarkA = 1;
+ // unmark the control inputs of MUXes and inputs of EXOR gates
+ Aig_ManForEachAnd( pMan, pNode, i )
+ {
+ if ( !Aig_NodeIsMuxType(pNode) )
+ continue;
+
+ pNodeC = Aig_NodeRecognizeMux( pNode, &pNodeA, &pNodeB );
+ // if real children are used, skip
+ if ( Aig_NodeFanin0(pNode)->nRefs > 1 || Aig_NodeFanin1(pNode)->nRefs > 1 )
+ continue;
+/*
+
+ if ( pNodeC->nRefs == 2 )
+ pNodeC->fMarkA = 0;
+ if ( Aig_Regular(pNodeA) == Aig_Regular(pNodeB) && Aig_Regular(pNodeA)->nRefs == 2 )
+ Aig_Regular(pNodeA)->fMarkA = 0;
+*/
+
+ if ( Aig_Regular(pNodeA) == Aig_Regular(pNodeB) )
+ nExors++;
+ else
+ nMuxes++;
+ }
+ // mark the PO drivers
+ Aig_ManForEachPo( pMan, pNode, i )
+ {
+ Aig_NodeFanin0(pNode)->fMarkA = 1;
+ Aig_NodeFanin0(pNode)->fMarkB = 1;
+ }
+
+
+ // print sizes of MFFCs
+ Aig_ManForEachAnd( pMan, pNode, i )
+ {
+ if ( !pNode->fMarkA )
+ continue;
+
+// nNodes1 = Aig_NodeDeref_rec( pNode );
+// Aig_NodeMffsConeSupp( pNode, vCone, vSupp );
+// nNodes2 = Aig_NodeRef_rec( pNode );
+// assert( nNodes1 == nNodes2 );
+
+ Aig_NodeFactorConeSupp( pNode, vCone, vSupp );
+
+ printf( "%6d : Fan = %4d. Co = %5d. Su = %5d. %s ",
+ pNode->Id, pNode->nRefs, Vec_PtrSize(vCone), Vec_PtrSize(vSupp), pNode->fMarkB? "po" : " " );
+
+ Vec_PtrForEachEntry( vSupp, pLeaf, k )
+ printf( " %d", pLeaf->Id );
+
+ printf( "\n" );
+
+ nSizes += Vec_PtrSize(vCone);
+ nCones++;
+ }
+ printf( "Nodes = %6d. MFFC sizes = %6d. Cones = %6d. nExors = %6d. Muxes = %6d.\n",
+ Aig_ManAndNum(pMan), nSizes, nCones, nExors, nMuxes );
+
+ // unmark the nodes
+ Aig_ManForEachNode( pMan, pNode, i )
+ {
+ pNode->fMarkA = 0;
+ pNode->fMarkB = 0;
+ pNode->fMarkC = 0;
+ }
+
+ Vec_PtrFree( vCone );
+ Vec_PtrFree( vSupp );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dereferences the node's MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_NodeDeref_rec( Aig_Node_t * pNode )
+{
+ Aig_Node_t * pNode0, * pNode1;
+ int Counter = 1;
+ if ( Aig_NodeIsPi(pNode) )
+ return 0;
+ pNode0 = Aig_NodeFanin0(pNode);
+ pNode1 = Aig_NodeFanin1(pNode);
+ assert( pNode0->nRefs > 0 );
+ assert( pNode1->nRefs > 0 );
+ if ( --pNode0->nRefs == 0 )
+ Counter += Aig_NodeDeref_rec( pNode0 );
+ if ( --pNode1->nRefs == 0 )
+ Counter += Aig_NodeDeref_rec( pNode1 );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [References the node's MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_NodeRef_rec( Aig_Node_t * pNode )
+{
+ Aig_Node_t * pNode0, * pNode1;
+ int Counter = 1;
+ if ( Aig_NodeIsPi(pNode) )
+ return 0;
+ pNode0 = Aig_NodeFanin0(pNode);
+ pNode1 = Aig_NodeFanin1(pNode);
+ if ( pNode0->nRefs++ == 0 )
+ Counter += Aig_NodeRef_rec( pNode0 );
+ if ( pNode1->nRefs++ == 0 )
+ Counter += Aig_NodeRef_rec( pNode1 );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the internal and leaf nodes in the derefed MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_NodeMffsConeSupp_rec( Aig_Node_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost )
+{
+ // skip visited nodes
+ if ( Aig_NodeIsTravIdCurrent(pNode) )
+ return;
+ Aig_NodeSetTravIdCurrent(pNode);
+ // add to the new support nodes
+ if ( !fTopmost && (Aig_NodeIsPi(pNode) || pNode->nRefs > 0) )
+ {
+ Vec_PtrPush( vSupp, pNode );
+ return;
+ }
+ // recur on the children
+ Aig_NodeMffsConeSupp_rec( Aig_NodeFanin0(pNode), vCone, vSupp, 0 );
+ Aig_NodeMffsConeSupp_rec( Aig_NodeFanin1(pNode), vCone, vSupp, 0 );
+ // collect the internal node
+ Vec_PtrPush( vCone, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the support of the derefed MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_NodeMffsConeSupp( Aig_Node_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp )
+{
+ assert( Aig_NodeIsAnd(pNode) );
+ assert( !Aig_IsComplement(pNode) );
+ Vec_PtrClear( vCone );
+ Vec_PtrClear( vSupp );
+ Aig_ManIncrementTravId( pNode->pMan );
+ Aig_NodeMffsConeSupp_rec( pNode, vCone, vSupp, 1 );
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Collects the internal and leaf nodes of the factor-cut of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_NodeFactorConeSupp_rec( Aig_Node_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost )
+{
+ // skip visited nodes
+ if ( Aig_NodeIsTravIdCurrent(pNode) )
+ return;
+ Aig_NodeSetTravIdCurrent(pNode);
+ // add to the new support nodes
+ if ( !fTopmost && (Aig_NodeIsPi(pNode) || pNode->fMarkA) )
+ {
+ Vec_PtrPush( vSupp, pNode );
+ return;
+ }
+ // recur on the children
+ Aig_NodeFactorConeSupp_rec( Aig_NodeFanin0(pNode), vCone, vSupp, 0 );
+ Aig_NodeFactorConeSupp_rec( Aig_NodeFanin1(pNode), vCone, vSupp, 0 );
+ // collect the internal node
+ assert( fTopmost || !pNode->fMarkA );
+ Vec_PtrPush( vCone, pNode );
+
+ assert( pNode->fMarkC == 0 );
+ pNode->fMarkC = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the support of the derefed MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_NodeFactorConeSupp( Aig_Node_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp )
+{
+ assert( Aig_NodeIsAnd(pNode) );
+ assert( !Aig_IsComplement(pNode) );
+ Vec_PtrClear( vCone );
+ Vec_PtrClear( vSupp );
+ Aig_ManIncrementTravId( pNode->pMan );
+ Aig_NodeFactorConeSupp_rec( pNode, vCone, vSupp, 1 );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/sat/aig/rwrTruth.c b/src/sat/aig/rwrTruth.c
index 2c402184..63a437ce 100644
--- a/src/sat/aig/rwrTruth.c
+++ b/src/sat/aig/rwrTruth.c
@@ -444,6 +444,8 @@ Aig_Node_t * Aig_TruthDecompose( Aig_Truth_t * p )
assert( 0 );
}
+
+ return NULL;
}
diff --git a/src/sat/aig/rwr_.c b/src/sat/aig/rwr_.c
new file mode 100644
index 00000000..45e76f75
--- /dev/null
+++ b/src/sat/aig/rwr_.c
@@ -0,0 +1,48 @@
+/**CFile****************************************************************
+
+ FileName [rwr_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: rwr_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/sat/asat/asatmem.c b/src/sat/asat/asatmem.c
new file mode 100644
index 00000000..24c1b1a8
--- /dev/null
+++ b/src/sat/asat/asatmem.c
@@ -0,0 +1,527 @@
+/**CFile****************************************************************
+
+ FileName [asatmem.c]
+
+ PackageName [SAT solver.]
+
+ Synopsis [Memory management.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2004.]
+
+ Revision [$Id: asatmem.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "asatmem.h"
+#include "extra.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+struct Asat_MmFixed_t_
+{
+ // information about individual entries
+ int nEntrySize; // the size of one entry
+ int nEntriesAlloc; // the total number of entries allocated
+ int nEntriesUsed; // the number of entries in use
+ int nEntriesMax; // the max number of entries in use
+ char * pEntriesFree; // the linked list of free entries
+
+ // this is where the memory is stored
+ int nChunkSize; // the size of one chunk
+ int nChunksAlloc; // the maximum number of memory chunks
+ int nChunks; // the current number of memory chunks
+ char ** pChunks; // the allocated memory
+
+ // statistics
+ int nMemoryUsed; // memory used in the allocated entries
+ int nMemoryAlloc; // memory allocated
+};
+
+struct Asat_MmFlex_t_
+{
+ // information about individual entries
+ int nEntriesUsed; // the number of entries allocated
+ char * pCurrent; // the current pointer to free memory
+ char * pEnd; // the first entry outside the free memory
+
+ // this is where the memory is stored
+ int nChunkSize; // the size of one chunk
+ int nChunksAlloc; // the maximum number of memory chunks
+ int nChunks; // the current number of memory chunks
+ char ** pChunks; // the allocated memory
+
+ // statistics
+ int nMemoryUsed; // memory used in the allocated entries
+ int nMemoryAlloc; // memory allocated
+};
+
+struct Asat_MmStep_t_
+{
+ int nMems; // the number of fixed memory managers employed
+ Asat_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc
+ int nMapSize; // the size of the memory array
+ Asat_MmFixed_t ** pMap; // maps the number of bytes into its memory manager
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates memory pieces of fixed size.]
+
+ Description [The size of the chunk is computed as the minimum of
+ 1024 entries and 64K. Can only work with entry size at least 4 byte long.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Asat_MmFixed_t * Asat_MmFixedStart( int nEntrySize )
+{
+ Asat_MmFixed_t * p;
+
+ p = ALLOC( Asat_MmFixed_t, 1 );
+ memset( p, 0, sizeof(Asat_MmFixed_t) );
+
+ p->nEntrySize = nEntrySize;
+ p->nEntriesAlloc = 0;
+ p->nEntriesUsed = 0;
+ p->pEntriesFree = NULL;
+
+ if ( nEntrySize * (1 << 10) < (1<<16) )
+ p->nChunkSize = (1 << 10);
+ else
+ p->nChunkSize = (1<<16) / nEntrySize;
+ if ( p->nChunkSize < 8 )
+ p->nChunkSize = 8;
+
+ p->nChunksAlloc = 64;
+ p->nChunks = 0;
+ p->pChunks = ALLOC( char *, p->nChunksAlloc );
+
+ p->nMemoryUsed = 0;
+ p->nMemoryAlloc = 0;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Asat_MmFixedStop( Asat_MmFixed_t * p, int fVerbose )
+{
+ int i;
+ if ( p == NULL )
+ return;
+ if ( fVerbose )
+ {
+ printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
+ p->nEntrySize, p->nChunkSize, p->nChunks );
+ printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
+ p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
+ }
+ for ( i = 0; i < p->nChunks; i++ )
+ free( p->pChunks[i] );
+ free( p->pChunks );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Asat_MmFixedEntryFetch( Asat_MmFixed_t * p )
+{
+ char * pTemp;
+ int i;
+
+ // check if there are still free entries
+ if ( p->nEntriesUsed == p->nEntriesAlloc )
+ { // need to allocate more entries
+ assert( p->pEntriesFree == NULL );
+ if ( p->nChunks == p->nChunksAlloc )
+ {
+ p->nChunksAlloc *= 2;
+ p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc );
+ }
+ p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize );
+ p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
+ // transform these entries into a linked list
+ pTemp = p->pEntriesFree;
+ for ( i = 1; i < p->nChunkSize; i++ )
+ {
+ *((char **)pTemp) = pTemp + p->nEntrySize;
+ pTemp += p->nEntrySize;
+ }
+ // set the last link
+ *((char **)pTemp) = NULL;
+ // add the chunk to the chunk storage
+ p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
+ // add to the number of entries allocated
+ p->nEntriesAlloc += p->nChunkSize;
+ }
+ // incrememt the counter of used entries
+ p->nEntriesUsed++;
+ if ( p->nEntriesMax < p->nEntriesUsed )
+ p->nEntriesMax = p->nEntriesUsed;
+ // return the first entry in the free entry list
+ pTemp = p->pEntriesFree;
+ p->pEntriesFree = *((char **)pTemp);
+ return pTemp;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Asat_MmFixedEntryRecycle( Asat_MmFixed_t * p, char * pEntry )
+{
+ // decrement the counter of used entries
+ p->nEntriesUsed--;
+ // add the entry to the linked list of free entries
+ *((char **)pEntry) = p->pEntriesFree;
+ p->pEntriesFree = pEntry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description [Relocates all the memory except the first chunk.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Asat_MmFixedRestart( Asat_MmFixed_t * p )
+{
+ int i;
+ char * pTemp;
+
+ // deallocate all chunks except the first one
+ for ( i = 1; i < p->nChunks; i++ )
+ free( p->pChunks[i] );
+ p->nChunks = 1;
+ // transform these entries into a linked list
+ pTemp = p->pChunks[0];
+ for ( i = 1; i < p->nChunkSize; i++ )
+ {
+ *((char **)pTemp) = pTemp + p->nEntrySize;
+ pTemp += p->nEntrySize;
+ }
+ // set the last link
+ *((char **)pTemp) = NULL;
+ // set the free entry list
+ p->pEntriesFree = p->pChunks[0];
+ // set the correct statistics
+ p->nMemoryAlloc = p->nEntrySize * p->nChunkSize;
+ p->nMemoryUsed = 0;
+ p->nEntriesAlloc = p->nChunkSize;
+ p->nEntriesUsed = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Asat_MmFixedReadMemUsage( Asat_MmFixed_t * p )
+{
+ return p->nMemoryAlloc;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Allocates entries of flexible size.]
+
+ Description [Can only work with entry size at least 4 byte long.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Asat_MmFlex_t * Asat_MmFlexStart()
+{
+ Asat_MmFlex_t * p;
+
+ p = ALLOC( Asat_MmFlex_t, 1 );
+ memset( p, 0, sizeof(Asat_MmFlex_t) );
+
+ p->nEntriesUsed = 0;
+ p->pCurrent = NULL;
+ p->pEnd = NULL;
+
+ p->nChunkSize = (1 << 12);
+ p->nChunksAlloc = 64;
+ p->nChunks = 0;
+ p->pChunks = ALLOC( char *, p->nChunksAlloc );
+
+ p->nMemoryUsed = 0;
+ p->nMemoryAlloc = 0;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Asat_MmFlexStop( Asat_MmFlex_t * p, int fVerbose )
+{
+ int i;
+ if ( p == NULL )
+ return;
+ if ( fVerbose )
+ {
+ printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
+ p->nChunkSize, p->nChunks );
+ printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
+ p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
+ }
+ for ( i = 0; i < p->nChunks; i++ )
+ free( p->pChunks[i] );
+ free( p->pChunks );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Asat_MmFlexEntryFetch( Asat_MmFlex_t * p, int nBytes )
+{
+ char * pTemp;
+ // check if there are still free entries
+ if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
+ { // need to allocate more entries
+ if ( p->nChunks == p->nChunksAlloc )
+ {
+ p->nChunksAlloc *= 2;
+ p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc );
+ }
+ if ( nBytes > p->nChunkSize )
+ {
+ // resize the chunk size if more memory is requested than it can give
+ // (ideally, this should never happen)
+ p->nChunkSize = 2 * nBytes;
+ }
+ p->pCurrent = ALLOC( char, p->nChunkSize );
+ p->pEnd = p->pCurrent + p->nChunkSize;
+ p->nMemoryAlloc += p->nChunkSize;
+ // add the chunk to the chunk storage
+ p->pChunks[ p->nChunks++ ] = p->pCurrent;
+ }
+ assert( p->pCurrent + nBytes <= p->pEnd );
+ // increment the counter of used entries
+ p->nEntriesUsed++;
+ // keep track of the memory used
+ p->nMemoryUsed += nBytes;
+ // return the next entry
+ pTemp = p->pCurrent;
+ p->pCurrent += nBytes;
+ return pTemp;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Asat_MmFlexReadMemUsage( Asat_MmFlex_t * p )
+{
+ return p->nMemoryAlloc;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the hierarchical memory manager.]
+
+ Description [This manager can allocate entries of any size.
+ Iternally they are mapped into the entries with the number of bytes
+ equal to the power of 2. The smallest entry size is 8 bytes. The
+ next one is 16 bytes etc. So, if the user requests 6 bytes, he gets
+ 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc.
+ The input parameters "nSteps" says how many fixed memory managers
+ are employed internally. Calling this procedure with nSteps equal
+ to 10 results in 10 hierarchically arranged internal memory managers,
+ which can allocate up to 4096 (1Kb) entries. Requests for larger
+ entries are handed over to malloc() and then free()ed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Asat_MmStep_t * Asat_MmStepStart( int nSteps )
+{
+ Asat_MmStep_t * p;
+ int i, k;
+ p = ALLOC( Asat_MmStep_t, 1 );
+ p->nMems = nSteps;
+ // start the fixed memory managers
+ p->pMems = ALLOC( Asat_MmFixed_t *, p->nMems );
+ for ( i = 0; i < p->nMems; i++ )
+ p->pMems[i] = Asat_MmFixedStart( (8<<i) );
+ // set up the mapping of the required memory size into the corresponding manager
+ p->nMapSize = (4<<p->nMems);
+ p->pMap = ALLOC( Asat_MmFixed_t *, p->nMapSize+1 );
+ p->pMap[0] = NULL;
+ for ( k = 1; k <= 4; k++ )
+ p->pMap[k] = p->pMems[0];
+ for ( i = 0; i < p->nMems; i++ )
+ for ( k = (4<<i)+1; k <= (8<<i); k++ )
+ p->pMap[k] = p->pMems[i];
+//for ( i = 1; i < 100; i ++ )
+//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the memory manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Asat_MmStepStop( Asat_MmStep_t * p, int fVerbose )
+{
+ int i;
+ for ( i = 0; i < p->nMems; i++ )
+ Asat_MmFixedStop( p->pMems[i], fVerbose );
+ free( p->pMems );
+ free( p->pMap );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Asat_MmStepEntryFetch( Asat_MmStep_t * p, int nBytes )
+{
+ if ( nBytes == 0 )
+ return NULL;
+ if ( nBytes > p->nMapSize )
+ {
+// printf( "Allocating %d bytes.\n", nBytes );
+ return ALLOC( char, nBytes );
+ }
+ return Asat_MmFixedEntryFetch( p->pMap[nBytes] );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Recycles the entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Asat_MmStepEntryRecycle( Asat_MmStep_t * p, char * pEntry, int nBytes )
+{
+ if ( nBytes == 0 )
+ return;
+ if ( nBytes > p->nMapSize )
+ {
+ free( pEntry );
+ return;
+ }
+ Asat_MmFixedEntryRecycle( p->pMap[nBytes], pEntry );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Asat_MmStepReadMemUsage( Asat_MmStep_t * p )
+{
+ int i, nMemTotal = 0;
+ for ( i = 0; i < p->nMems; i++ )
+ nMemTotal += p->pMems[i]->nMemoryAlloc;
+ return nMemTotal;
+}
diff --git a/src/sat/asat/asatmem.h b/src/sat/asat/asatmem.h
new file mode 100644
index 00000000..56115e7d
--- /dev/null
+++ b/src/sat/asat/asatmem.h
@@ -0,0 +1,76 @@
+/**CFile****************************************************************
+
+ FileName [asatmem.h]
+
+ PackageName [SAT solver.]
+
+ Synopsis [Memory management.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2004.]
+
+ Revision [$Id: asatmem.h,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __ASAT_MEM_H__
+#define __ASAT_MEM_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+//#include "leaks.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Asat_MmFixed_t_ Asat_MmFixed_t;
+typedef struct Asat_MmFlex_t_ Asat_MmFlex_t;
+typedef struct Asat_MmStep_t_ Asat_MmStep_t;
+
+////////////////////////////////////////////////////////////////////////
+/// GLOBAL VARIABLES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// fixed-size-block memory manager
+extern Asat_MmFixed_t * Asat_MmFixedStart( int nEntrySize );
+extern void Asat_MmFixedStop( Asat_MmFixed_t * p, int fVerbose );
+extern char * Asat_MmFixedEntryFetch( Asat_MmFixed_t * p );
+extern void Asat_MmFixedEntryRecycle( Asat_MmFixed_t * p, char * pEntry );
+extern void Asat_MmFixedRestart( Asat_MmFixed_t * p );
+extern int Asat_MmFixedReadMemUsage( Asat_MmFixed_t * p );
+// flexible-size-block memory manager
+extern Asat_MmFlex_t * Asat_MmFlexStart();
+extern void Asat_MmFlexStop( Asat_MmFlex_t * p, int fVerbose );
+extern char * Asat_MmFlexEntryFetch( Asat_MmFlex_t * p, int nBytes );
+extern int Asat_MmFlexReadMemUsage( Asat_MmFlex_t * p );
+// hierarchical memory manager
+extern Asat_MmStep_t * Asat_MmStepStart( int nSteps );
+extern void Asat_MmStepStop( Asat_MmStep_t * p, int fVerbose );
+extern char * Asat_MmStepEntryFetch( Asat_MmStep_t * p, int nBytes );
+extern void Asat_MmStepEntryRecycle( Asat_MmStep_t * p, char * pEntry, int nBytes );
+extern int Asat_MmStepReadMemUsage( Asat_MmStep_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/src/sat/asat/module.make b/src/sat/asat/module.make
index 882176fa..d5cf69bf 100644
--- a/src/sat/asat/module.make
+++ b/src/sat/asat/module.make
@@ -1,2 +1,3 @@
SRC += src/sat/asat/added.c \
+ src/sat/asat/asatmem.c \
src/sat/asat/solver.c
diff --git a/src/sat/asat/solver.c b/src/sat/asat/solver.c
index 3927fac3..1130d437 100644
--- a/src/sat/asat/solver.c
+++ b/src/sat/asat/solver.c
@@ -26,6 +26,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "solver.h"
+//#define ASAT_USE_SYSTEM_MEMORY_MANAGEMENT
+
//=================================================================================================
// Simple (var/literal) helpers:
@@ -275,7 +277,14 @@ static clause* clause_new(solver* s, lit* begin, lit* end, int learnt)
assert(end - begin > 1);
assert(learnt >= 0 && learnt < 2);
size = end - begin;
- c = (clause*)malloc(sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float));
+
+// c = (clause*)malloc(sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float));
+#ifdef ASAT_USE_SYSTEM_MEMORY_MANAGEMENT
+ c = (clause*)malloc(sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float));
+#else
+ c = (clause*)Asat_MmStepEntryFetch( s->pMem, sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float) );
+#endif
+
c->size_learnt = (size << 1) | learnt;
assert(((unsigned int)c & 1) == 0);
@@ -324,7 +333,12 @@ static void clause_remove(solver* s, clause* c)
s->solver_stats.clauses_literals -= clause_size(c);
}
+#ifdef ASAT_USE_SYSTEM_MEMORY_MANAGEMENT
free(c);
+#else
+ Asat_MmStepEntryRecycle( s->pMem, (char *)c, sizeof(clause) + sizeof(lit) * clause_size(c) + clause_learnt(c) * sizeof(float) );
+#endif
+
}
@@ -829,12 +843,24 @@ static lbool solver_search(solver* s, int nof_conflicts, int nof_learnts)
// NO CONFLICT
int next;
- if (nof_conflicts >= 0 && conflictC >= nof_conflicts){
+ if (nof_conflicts >= 0 && conflictC >= nof_conflicts)
+ {
// Reached bound on number of conflicts:
s->progress_estimate = solver_progress(s);
solver_canceluntil(s,s->root_level);
vec_delete(&learnt_clause);
- return l_Undef; }
+ return l_Undef;
+ }
+
+ if ( s->nConfLimit && s->solver_stats.conflicts > s->nConfLimit ||
+ s->nImpLimit && s->solver_stats.propagations > s->nImpLimit )
+ {
+ // Reached bound on number of conflicts:
+ s->progress_estimate = solver_progress(s);
+ solver_canceluntil(s,s->root_level);
+ vec_delete(&learnt_clause);
+ return l_Undef;
+ }
if (solver_dlevel(s) == 0)
// Simplify the set of problem clauses:
@@ -922,18 +948,28 @@ solver* solver_new(void)
s->solver_stats.max_literals = 0;
s->solver_stats.tot_literals = 0;
+#ifdef ASAT_USE_SYSTEM_MEMORY_MANAGEMENT
+ s->pMem = NULL;
+#else
+ s->pMem = Asat_MmStepStart( 10 );
+#endif
+
return s;
}
void solver_delete(solver* s)
{
+
+#ifdef ASAT_USE_SYSTEM_MEMORY_MANAGEMENT
int i;
for (i = 0; i < vec_size(&s->clauses); i++)
free(vec_begin(&s->clauses)[i]);
-
for (i = 0; i < vec_size(&s->learnts); i++)
free(vec_begin(&s->learnts)[i]);
+#else
+ Asat_MmStepStop( s->pMem, 0 );
+#endif
// delete vectors
vec_delete(&s->clauses);
@@ -1056,14 +1092,18 @@ bool solver_simplify(solver* s)
}
-bool solver_solve(solver* s, lit* begin, lit* end, int nSeconds)
+bool solver_solve(solver* s, lit* begin, lit* end, int nConfLimit, int nImpLimit )
{
double nof_conflicts = 100;
double nof_learnts = solver_nclauses(s) / 3;
lbool status = l_Undef;
lbool* values = s->assigns;
lit* i;
- int timeStart = clock();
+
+ // set the external limits
+ s->nConfLimit = nConfLimit; // external limit on the number of conflicts
+ s->nImpLimit = nImpLimit; // external limit on the number of implications
+
for (i = begin; i < end; i++)
if ((lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)]) == l_False || (assume(s,*i), solver_propagate(s) != 0)){
@@ -1098,9 +1138,18 @@ bool solver_solve(solver* s, lit* begin, lit* end, int nSeconds)
status = solver_search(s,(int)nof_conflicts, (int)nof_learnts);
nof_conflicts *= 1.5;
nof_learnts *= 1.1;
- // if the runtime limit is exceeded, quit the restart loop
- if ( (nSeconds >= 0) && (clock() - timeStart >= nSeconds * CLOCKS_PER_SEC) )
+
+ // quit the loop if reached an external limit
+ if ( s->nConfLimit && s->solver_stats.conflicts > s->nConfLimit )
+ {
+// printf( "Reached the limit on the number of conflicts (%d).\n", s->nConfLimit );
break;
+ }
+ if ( s->nImpLimit && s->solver_stats.propagations > s->nImpLimit )
+ {
+// printf( "Reached the limit on the number of implications (%d).\n", s->nImpLimit );
+ break;
+ }
}
if (s->verbosity >= 1)
printf("==============================================================================\n");
diff --git a/src/sat/asat/solver.h b/src/sat/asat/solver.h
index 9618603c..d798a7a9 100644
--- a/src/sat/asat/solver.h
+++ b/src/sat/asat/solver.h
@@ -27,6 +27,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#endif
#include "solver_vec.h"
+#include "asatmem.h"
//=================================================================================================
// Simple types:
@@ -67,7 +68,7 @@ extern void solver_delete(solver* s);
extern bool solver_addclause(solver* s, lit* begin, lit* end);
extern bool solver_simplify(solver* s);
-extern int solver_solve(solver* s, lit* begin, lit* end, int nSeconds);
+extern int solver_solve(solver* s, lit* begin, lit* end, int nConfLimit, int nImpLimit );
extern int * solver_get_model( solver * p, int * pVars, int nVars );
extern int solver_nvars(solver* s);
@@ -132,6 +133,12 @@ struct solver_t
double progress_estimate;
int verbosity; // Verbosity level. 0=silent, 1=some progress report, 2=everything
+ int nConfLimit; // external limit on the number of conflicts
+ int nImpLimit; // external limit on the number of implications
+
+ // the memory manager
+ Asat_MmStep_t * pMem;
+
stats solver_stats;
};
diff --git a/src/sat/csat/csat_apis.c b/src/sat/csat/csat_apis.c
index d25e42db..d286ea9c 100644
--- a/src/sat/csat/csat_apis.c
+++ b/src/sat/csat/csat_apis.c
@@ -17,14 +17,15 @@
***********************************************************************/
#include "abc.h"
-#include "fraig.h"
#include "csat_apis.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-#define ABC_DEFAULT_TIMEOUT 60 // 60 seconds
+#define ABC_DEFAULT_CONF_LIMIT 0 // limit on conflicts
+#define ABC_DEFAULT_IMP_LIMIT 0 // limit on implications
+
struct ABC_ManagerStruct_t
{
@@ -37,19 +38,24 @@ struct ABC_ManagerStruct_t
Extra_MmFlex_t * pMmNames; // memory manager for signal names
// solving parameters
int mode; // 0 = brute-force SAT; 1 = resource-aware FRAIG
- int nSeconds; // time limit for pure SAT solving
- Fraig_Params_t Params; // the set of parameters to call FRAIG package
+ int nConfLimit; // time limit for pure SAT solving
+ int nImpLimit; // time limit for pure SAT solving
+// Fraig_Params_t Params; // the set of parameters to call FRAIG package
// information about the target
int nog; // the numbers of gates in the target
Vec_Ptr_t * vNodes; // the gates in the target
Vec_Int_t * vValues; // the values of gate's outputs in the target
// solution
- ABC_Target_ResultT * pResult; // the result of solving the target
+ CSAT_Target_ResultT * pResult; // the result of solving the target
};
-static ABC_Target_ResultT * ABC_TargetResAlloc( int nVars );
+static CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars );
static char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode );
+// procedures to start and stop the ABC framework
+extern void Abc_Start();
+extern void Abc_Stop();
+
// some external procedures
extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName );
@@ -71,16 +77,18 @@ extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName );
ABC_Manager ABC_InitManager()
{
ABC_Manager_t * mng;
+ Abc_Start();
mng = ALLOC( ABC_Manager_t, 1 );
memset( mng, 0, sizeof(ABC_Manager_t) );
mng->pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP );
- mng->pNtk->pName = util_strsav("csat_network");
+ mng->pNtk->pName = Extra_UtilStrsav("csat_network");
mng->tName2Node = stmm_init_table(strcmp, stmm_strhash);
mng->tNode2Name = stmm_init_table(stmm_ptrcmp, stmm_ptrhash);
mng->pMmNames = Extra_MmFlexStart();
mng->vNodes = Vec_PtrAlloc( 100 );
mng->vValues = Vec_IntAlloc( 100 );
- mng->nSeconds = ABC_DEFAULT_TIMEOUT;
+ mng->nConfLimit = ABC_DEFAULT_CONF_LIMIT;
+ mng->nImpLimit = ABC_DEFAULT_IMP_LIMIT;
return mng;
}
@@ -95,7 +103,7 @@ ABC_Manager ABC_InitManager()
SeeAlso []
***********************************************************************/
-void ABC_QuitManager( ABC_Manager mng )
+void ABC_ReleaseManager( ABC_Manager mng )
{
if ( mng->tNode2Name ) stmm_free_table( mng->tNode2Name );
if ( mng->tName2Node ) stmm_free_table( mng->tName2Node );
@@ -106,6 +114,7 @@ void ABC_QuitManager( ABC_Manager mng )
if ( mng->vValues ) Vec_IntFree( mng->vValues );
FREE( mng->pDumpFileName );
free( mng );
+ Abc_Stop();
}
/**Function*************************************************************
@@ -119,7 +128,7 @@ void ABC_QuitManager( ABC_Manager mng )
SeeAlso []
***********************************************************************/
-void ABC_SetSolveOption( ABC_Manager mng, enum ABC_OptionT option )
+void ABC_SetSolveOption( ABC_Manager mng, enum CSAT_OptionT option )
{
mng->mode = option;
if ( option == 0 )
@@ -160,23 +169,23 @@ int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, cha
// consider different cases, create the node, and map the node into the name
switch( type )
{
- case ABC_BPI:
- case ABC_BPPI:
+ case CSAT_BPI:
+ case CSAT_BPPI:
if ( nofi != 0 )
{ printf( "ABC_AddGate: The PI/PPI gate \"%s\" has fanins.\n", name ); return 0; }
// create the PI
pObj = Abc_NtkCreatePi( mng->pNtk );
stmm_insert( mng->tNode2Name, (char *)pObj, name );
break;
- case ABC_CONST:
- case ABC_BAND:
- case ABC_BNAND:
- case ABC_BOR:
- case ABC_BNOR:
- case ABC_BXOR:
- case ABC_BXNOR:
- case ABC_BINV:
- case ABC_BBUF:
+ case CSAT_CONST:
+ case CSAT_BAND:
+ case CSAT_BNAND:
+ case CSAT_BOR:
+ case CSAT_BNOR:
+ case CSAT_BXOR:
+ case CSAT_BXNOR:
+ case CSAT_BINV:
+ case CSAT_BBUF:
// create the node
pObj = Abc_NtkCreateNode( mng->pNtk );
// create the fanins
@@ -189,51 +198,51 @@ int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, cha
// create the node function
switch( type )
{
- case ABC_CONST:
+ case CSAT_CONST:
if ( nofi != 0 )
{ printf( "ABC_AddGate: The constant gate \"%s\" has fanins.\n", name ); return 0; }
pSop = Abc_SopCreateConst1( mng->pNtk->pManFunc );
break;
- case ABC_BAND:
+ case CSAT_BAND:
if ( nofi < 1 )
{ printf( "ABC_AddGate: The AND gate \"%s\" no fanins.\n", name ); return 0; }
pSop = Abc_SopCreateAnd( mng->pNtk->pManFunc, nofi, NULL );
break;
- case ABC_BNAND:
+ case CSAT_BNAND:
if ( nofi < 1 )
{ printf( "ABC_AddGate: The NAND gate \"%s\" no fanins.\n", name ); return 0; }
pSop = Abc_SopCreateNand( mng->pNtk->pManFunc, nofi );
break;
- case ABC_BOR:
+ case CSAT_BOR:
if ( nofi < 1 )
{ printf( "ABC_AddGate: The OR gate \"%s\" no fanins.\n", name ); return 0; }
pSop = Abc_SopCreateOr( mng->pNtk->pManFunc, nofi, NULL );
break;
- case ABC_BNOR:
+ case CSAT_BNOR:
if ( nofi < 1 )
{ printf( "ABC_AddGate: The NOR gate \"%s\" no fanins.\n", name ); return 0; }
pSop = Abc_SopCreateNor( mng->pNtk->pManFunc, nofi );
break;
- case ABC_BXOR:
+ case CSAT_BXOR:
if ( nofi < 1 )
{ printf( "ABC_AddGate: The XOR gate \"%s\" no fanins.\n", name ); return 0; }
if ( nofi > 2 )
{ printf( "ABC_AddGate: The XOR gate \"%s\" has more than two fanins.\n", name ); return 0; }
pSop = Abc_SopCreateXor( mng->pNtk->pManFunc, nofi );
break;
- case ABC_BXNOR:
+ case CSAT_BXNOR:
if ( nofi < 1 )
{ printf( "ABC_AddGate: The XNOR gate \"%s\" no fanins.\n", name ); return 0; }
if ( nofi > 2 )
{ printf( "ABC_AddGate: The XNOR gate \"%s\" has more than two fanins.\n", name ); return 0; }
pSop = Abc_SopCreateNxor( mng->pNtk->pManFunc, nofi );
break;
- case ABC_BINV:
+ case CSAT_BINV:
if ( nofi != 1 )
{ printf( "ABC_AddGate: The inverter gate \"%s\" does not have exactly one fanin.\n", name ); return 0; }
pSop = Abc_SopCreateInv( mng->pNtk->pManFunc );
break;
- case ABC_BBUF:
+ case CSAT_BBUF:
if ( nofi != 1 )
{ printf( "ABC_AddGate: The buffer gate \"%s\" does not have exactly one fanin.\n", name ); return 0; }
pSop = Abc_SopCreateBuf( mng->pNtk->pManFunc );
@@ -243,8 +252,8 @@ int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, cha
}
Abc_ObjSetData( pObj, pSop );
break;
- case ABC_BPPO:
- case ABC_BPO:
+ case CSAT_BPPO:
+ case CSAT_BPO:
if ( nofi != 1 )
{ printf( "ABC_AddGate: The PO/PPO gate \"%s\" does not have exactly one fanin.\n", name ); return 0; }
// create the PO
@@ -268,38 +277,46 @@ int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, cha
/**Function*************************************************************
- Synopsis [Checks integraty of the manager.]
+ Synopsis [This procedure also finalizes construction of the ABC network.]
- Description [Checks if there are gates that are not used by any primary output.
- If no such gates exist, return 1 else return 0.]
+ Description []
SideEffects []
SeeAlso []
***********************************************************************/
-int ABC_Check_Integrity( ABC_Manager mng )
+void ABC_Network_Finalize( ABC_Manager mng )
{
Abc_Ntk_t * pNtk = mng->pNtk;
Abc_Obj_t * pObj;
int i;
-
- // this procedure also finalizes construction of the ABC network
- Abc_NtkFixNonDrivenNets( pNtk );
Abc_NtkForEachPi( pNtk, pObj, i )
Abc_NtkLogicStoreName( pObj, ABC_GetNodeName(mng, pObj) );
Abc_NtkForEachPo( pNtk, pObj, i )
Abc_NtkLogicStoreName( pObj, ABC_GetNodeName(mng, pObj) );
assert( Abc_NtkLatchNum(pNtk) == 0 );
+}
- // make sure everything is okay with the network structure
- if ( !Abc_NtkDoCheck( pNtk ) )
- {
- printf( "ABC_Check_Integrity: The internal network check has failed.\n" );
- return 0;
- }
+/**Function*************************************************************
+
+ Synopsis [Checks integraty of the manager.]
+
+ Description [Checks if there are gates that are not used by any primary output.
+ If no such gates exist, return 1 else return 0.]
+
+ SideEffects []
+
+ SeeAlso []
- // check that there is no dangling nodes
+***********************************************************************/
+int ABC_Check_Integrity( ABC_Manager mng )
+{
+ Abc_Ntk_t * pNtk = mng->pNtk;
+ Abc_Obj_t * pObj;
+ int i;
+
+ // check that there are no dangling nodes
Abc_NtkForEachNode( pNtk, pObj, i )
{
if ( i == 0 )
@@ -310,6 +327,13 @@ int ABC_Check_Integrity( ABC_Manager mng )
return 0;
}
}
+
+ // make sure everything is okay with the network structure
+ if ( !Abc_NtkDoCheck( pNtk ) )
+ {
+ printf( "ABC_Check_Integrity: The internal network check has failed.\n" );
+ return 0;
+ }
return 1;
}
@@ -326,7 +350,7 @@ int ABC_Check_Integrity( ABC_Manager mng )
***********************************************************************/
void ABC_SetTimeLimit( ABC_Manager mng, int runtime )
{
- mng->nSeconds = runtime;
+ printf( "ABC_SetTimeLimit: The resource limit is not implemented (warning).\n" );
}
/**Function*************************************************************
@@ -356,9 +380,25 @@ void ABC_SetLearnLimit( ABC_Manager mng, int num )
SeeAlso []
***********************************************************************/
+void ABC_SetLearnBacktrackLimit( ABC_Manager mng, int num )
+{
+ printf( "ABC_SetLearnBacktrackLimit: The resource limit is not implemented (warning).\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
void ABC_SetSolveBacktrackLimit( ABC_Manager mng, int num )
{
- printf( "ABC_SetSolveBacktrackLimit: The resource limit is not implemented (warning).\n" );
+ mng->nConfLimit = num;
}
/**Function*************************************************************
@@ -372,9 +412,9 @@ void ABC_SetSolveBacktrackLimit( ABC_Manager mng, int num )
SeeAlso []
***********************************************************************/
-void ABC_SetLearnBacktrackLimit( ABC_Manager mng, int num )
+void ABC_SetSolveImplicationLimit( ABC_Manager mng, int num )
{
- printf( "ABC_SetLearnBacktrackLimit: The resource limit is not implemented (warning).\n" );
+ mng->nImpLimit = num;
}
/**Function*************************************************************
@@ -391,7 +431,7 @@ void ABC_SetLearnBacktrackLimit( ABC_Manager mng, int num )
void ABC_EnableDump( ABC_Manager mng, char * dump_file )
{
FREE( mng->pDumpFileName );
- mng->pDumpFileName = util_strsav( dump_file );
+ mng->pDumpFileName = Extra_UtilStrsav( dump_file );
}
/**Function*************************************************************
@@ -447,9 +487,6 @@ int ABC_AddTarget( ABC_Manager mng, int nog, char ** names, int * values )
***********************************************************************/
void ABC_SolveInit( ABC_Manager mng )
{
- Fraig_Params_t * pParams = &mng->Params;
- int nWords1, nWords2, nWordsMin;
-
// check if the target is available
assert( mng->nog == Vec_PtrSize(mng->vNodes) );
if ( mng->nog == 0 )
@@ -459,30 +496,8 @@ void ABC_SolveInit( ABC_Manager mng )
if ( mng->pTarget ) Abc_NtkDelete( mng->pTarget );
// set the new target network
- mng->pTarget = Abc_NtkCreateCone( mng->pNtk, mng->vNodes, mng->vValues );
-
- // to determine the number of simulation patterns
- // use the following strategy
- // at least 64 words (32 words random and 32 words dynamic)
- // no more than 256M for one circuit (128M + 128M)
- nWords1 = 32;
- nWords2 = (1<<27) / (Abc_NtkNodeNum(mng->pTarget) + Abc_NtkCiNum(mng->pTarget));
- nWordsMin = ABC_MIN( nWords1, nWords2 );
-
- // set parameters for fraiging
- memset( pParams, 0, sizeof(Fraig_Params_t) );
- pParams->nPatsRand = nWordsMin * 32; // the number of words of random simulation info
- pParams->nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info
- pParams->nBTLimit = 10; // the max number of backtracks to perform at a node
- pParams->nSeconds = mng->nSeconds; // the time out for the final proof
- pParams->fFuncRed = mng->mode; // performs only one level hashing
- pParams->fFeedBack = 1; // enables solver feedback
- pParams->fDist1Pats = 1; // enables distance-1 patterns
- pParams->fDoSparse = 0; // performs equiv tests for sparse functions
- pParams->fChoicing = 0; // enables recording structural choices
- pParams->fTryProve = 1; // tries to solve the final miter
- pParams->fVerbose = 0; // the verbosiness flag
- pParams->fVerboseP = 0; // the verbosiness flag for proof reporting
+ mng->pTarget = Abc_NtkCreateTarget( mng->pNtk, mng->vNodes, mng->vValues );
+
}
/**Function*************************************************************
@@ -511,78 +526,35 @@ void ABC_AnalyzeTargets( ABC_Manager mng )
SeeAlso []
***********************************************************************/
-enum ABC_StatusT ABC_Solve( ABC_Manager mng )
+enum CSAT_StatusT ABC_Solve( ABC_Manager mng )
{
- Fraig_Man_t * pMan;
- Abc_Ntk_t * pCnf;
- int * pModel;
int RetValue, i;
// check if the target network is available
if ( mng->pTarget == NULL )
{ printf( "ABC_Solve: Target network is not derived by ABC_SolveInit().\n" ); return UNDETERMINED; }
- // optimizations of the target go here
- // for example, to enable one pass of rewriting, uncomment this line
-// Abc_NtkRewrite( mng->pTarget, 0, 1, 0 );
+ // try to prove the miter using a number of techniques
+ RetValue = Abc_NtkMiterProve( &mng->pTarget, mng->nConfLimit, mng->nImpLimit, 1, 1, 0 );
- if ( mng->mode == 0 ) // brute-force SAT
- {
- // transform the AIG into a logic network for efficient CNF construction
- pCnf = Abc_NtkRenode( mng->pTarget, 0, 100, 1, 0, 0 );
- RetValue = Abc_NtkMiterSat( pCnf, mng->nSeconds, 0 );
-
- // analyze the result
- mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) );
- if ( RetValue == -1 )
- mng->pResult->status = UNDETERMINED;
- else if ( RetValue == 1 )
- mng->pResult->status = UNSATISFIABLE;
- else if ( RetValue == 0 )
- {
- mng->pResult->status = SATISFIABLE;
- // create the array of PI names and values
- for ( i = 0; i < mng->pResult->no_sig; i++ )
- {
- mng->pResult->names[i] = ABC_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)); // returns the same string that was given
- mng->pResult->values[i] = pCnf->pModel[i];
- }
- FREE( mng->pTarget->pModel );
- }
- else assert( 0 );
- Abc_NtkDelete( pCnf );
- }
- else if ( mng->mode == 1 ) // resource-aware fraiging
+ // analyze the result
+ mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) );
+ if ( RetValue == -1 )
+ mng->pResult->status = UNDETERMINED;
+ else if ( RetValue == 1 )
+ mng->pResult->status = UNSATISFIABLE;
+ else if ( RetValue == 0 )
{
- // transform the target into a fraig
- pMan = Abc_NtkToFraig( mng->pTarget, &mng->Params, 0, 0 );
- Fraig_ManProveMiter( pMan );
- RetValue = Fraig_ManCheckMiter( pMan );
-
- // analyze the result
- mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) );
- if ( RetValue == -1 )
- mng->pResult->status = UNDETERMINED;
- else if ( RetValue == 1 )
- mng->pResult->status = UNSATISFIABLE;
- else if ( RetValue == 0 )
+ mng->pResult->status = SATISFIABLE;
+ // create the array of PI names and values
+ for ( i = 0; i < mng->pResult->no_sig; i++ )
{
- mng->pResult->status = SATISFIABLE;
- pModel = Fraig_ManReadModel( pMan );
- assert( pModel != NULL );
- // create the array of PI names and values
- for ( i = 0; i < mng->pResult->no_sig; i++ )
- {
- mng->pResult->names[i] = ABC_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)); // returns the same string that was given
- mng->pResult->values[i] = pModel[i];
- }
+ mng->pResult->names[i] = Extra_UtilStrsav( ABC_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)) );
+ mng->pResult->values[i] = mng->pTarget->pModel[i];
}
- else assert( 0 );
- // delete the fraig manager
- Fraig_ManFree( pMan );
+ FREE( mng->pTarget->pModel );
}
- else
- assert( 0 );
+ else assert( 0 );
// delete the target
Abc_NtkDelete( mng->pTarget );
@@ -602,7 +574,7 @@ enum ABC_StatusT ABC_Solve( ABC_Manager mng )
SeeAlso []
***********************************************************************/
-ABC_Target_ResultT * ABC_Get_Target_Result( ABC_Manager mng, int TargetID )
+CSAT_Target_ResultT * ABC_Get_Target_Result( ABC_Manager mng, int TargetID )
{
return mng->pResult;
}
@@ -615,7 +587,7 @@ ABC_Target_ResultT * ABC_Get_Target_Result( ABC_Manager mng, int TargetID )
SideEffects []
- SeeAlso []
+ SeeAlso []
***********************************************************************/
void ABC_Dump_Bench_File( ABC_Manager mng )
@@ -647,11 +619,11 @@ void ABC_Dump_Bench_File( ABC_Manager mng )
SeeAlso []
***********************************************************************/
-ABC_Target_ResultT * ABC_TargetResAlloc( int nVars )
+CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars )
{
- ABC_Target_ResultT * p;
- p = ALLOC( ABC_Target_ResultT, 1 );
- memset( p, 0, sizeof(ABC_Target_ResultT) );
+ CSAT_Target_ResultT * p;
+ p = ALLOC( CSAT_Target_ResultT, 1 );
+ memset( p, 0, sizeof(CSAT_Target_ResultT) );
p->no_sig = nVars;
p->names = ALLOC( char *, nVars );
p->values = ALLOC( int, nVars );
@@ -671,7 +643,7 @@ ABC_Target_ResultT * ABC_TargetResAlloc( int nVars )
SeeAlso []
***********************************************************************/
-void ABC_TargetResFree( ABC_Target_ResultT * p )
+void ABC_TargetResFree( CSAT_Target_ResultT * p )
{
if ( p == NULL )
return;
@@ -702,100 +674,6 @@ char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode )
}
-
-/**Function*************************************************************
-
- Synopsis [This procedure applies a rewriting script to the network.]
-
- Description [Rewriting is performed without regard for the number of
- logic levels. This corresponds to "circuit compression for formal
- verification" (Per Bjesse et al, ICCAD 2004) but implemented in a more
- exhaustive way than in the above paper.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void ABC_PerformRewriting( ABC_Manager mng )
-{
- void * pAbc;
- char Command[1000];
- int clkBalan, clkResyn, clk;
- int fPrintStats = 1;
- int fUseResyn = 1;
-
- // procedures to get the ABC framework and execute commands in it
- extern void * Abc_FrameGetGlobalFrame();
- extern void Abc_FrameReplaceCurrentNetwork( void * p, Abc_Ntk_t * pNtk );
- extern int Cmd_CommandExecute( void * p, char * sCommand );
- extern Abc_Ntk_t * Abc_FrameReadNtk( void * p );
-
-
- // get the pointer to the ABC framework
- pAbc = Abc_FrameGetGlobalFrame();
- assert( pAbc != NULL );
-
- // replace the current network by the target network
- Abc_FrameReplaceCurrentNetwork( pAbc, mng->pTarget );
-
-clk = clock();
- //////////////////////////////////////////////////////////////////////////
- // balance
- sprintf( Command, "balance" );
- if ( Cmd_CommandExecute( pAbc, Command ) )
- {
- fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
- return;
- }
-clkBalan = clock() - clk;
-
- //////////////////////////////////////////////////////////////////////////
- // print stats
- if ( fPrintStats )
- {
- sprintf( Command, "print_stats" );
- if ( Cmd_CommandExecute( pAbc, Command ) )
- {
- fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
- return;
- }
- }
-
-clk = clock();
- //////////////////////////////////////////////////////////////////////////
- // synthesize
- if ( fUseResyn )
- {
- sprintf( Command, "balance; rewrite -l; rewrite -lz; balance; rewrite -lz; balance" );
- if ( Cmd_CommandExecute( pAbc, Command ) )
- {
- fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
- return;
- }
- }
-clkResyn = clock() - clk;
-
- //////////////////////////////////////////////////////////////////////////
- // print stats
- if ( fPrintStats )
- {
- sprintf( Command, "print_stats" );
- if ( Cmd_CommandExecute( pAbc, Command ) )
- {
- fprintf( stdout, "Cannot execute command \"%s\".\n", Command );
- return;
- }
- }
- printf( "Balancing = %6.2f sec ", (float)(clkBalan)/(float)(CLOCKS_PER_SEC) );
- printf( "Rewriting = %6.2f sec ", (float)(clkResyn)/(float)(CLOCKS_PER_SEC) );
- printf( "\n" );
-
- // read the target network from the current network
- mng->pTarget = Abc_NtkDup( Abc_FrameReadNtk(pAbc) );
-}
-
-
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/sat/csat/csat_apis.h b/src/sat/csat/csat_apis.h
index a6179710..faba9ee4 100644
--- a/src/sat/csat/csat_apis.h
+++ b/src/sat/csat/csat_apis.h
@@ -12,13 +12,17 @@
Date [Ver. 1.0. Started - August 28, 2005]
- Revision [$Id: csat_apis.h,v 1.00 2005/08/28 00:00:00 alanmi Exp $]
+ Revision [$Id: csat_apis.h,v 1.5 2005/12/30 10:54:40 rmukherj Exp $]
***********************************************************************/
#ifndef __ABC_APIS_H__
#define __ABC_APIS_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -42,27 +46,35 @@ typedef struct ABC_ManagerStruct_t * ABC_Manager;
#define _ABC_GATE_TYPE_
enum GateType
{
- ABC_CONST = 0, // constant gate
- ABC_BPI, // boolean PI
- ABC_BPPI, // bit level PSEUDO PRIMARY INPUT
- ABC_BAND, // bit level AND
- ABC_BNAND, // bit level NAND
- ABC_BOR, // bit level OR
- ABC_BNOR, // bit level NOR
- ABC_BXOR, // bit level XOR
- ABC_BXNOR, // bit level XNOR
- ABC_BINV, // bit level INVERTER
- ABC_BBUF, // bit level BUFFER
- ABC_BPPO, // bit level PSEUDO PRIMARY OUTPUT
- ABC_BPO // boolean PO
+ CSAT_CONST = 0, // constant gate
+ CSAT_BPI, // boolean PI
+ CSAT_BPPI, // bit level PSEUDO PRIMARY INPUT
+ CSAT_BAND, // bit level AND
+ CSAT_BNAND, // bit level NAND
+ CSAT_BOR, // bit level OR
+ CSAT_BNOR, // bit level NOR
+ CSAT_BXOR, // bit level XOR
+ CSAT_BXNOR, // bit level XNOR
+ CSAT_BINV, // bit level INVERTER
+ CSAT_BBUF, // bit level BUFFER
+ CSAT_BMUX, // bit level MUX --not supported
+ CSAT_BDFF, // bit level D-type FF
+ CSAT_BSDFF, // bit level scan FF --not supported
+ CSAT_BTRIH, // bit level TRISTATE gate with active high control --not supported
+ CSAT_BTRIL, // bit level TRISTATE gate with active low control --not supported
+ CSAT_BBUS, // bit level BUS --not supported
+ CSAT_BPPO, // bit level PSEUDO PRIMARY OUTPUT
+ CSAT_BPO, // boolean PO
+ CSAT_BCNF, // boolean constraint
+ CSAT_BDC, // boolean don't care gate (2 input)
};
#endif
-//ABC_StatusT defines the return value by ABC_Solve();
+//CSAT_StatusT defines the return value by ABC_Solve();
#ifndef _ABC_STATUS_
#define _ABC_STATUS_
-enum ABC_StatusT
+enum CSAT_StatusT
{
UNDETERMINED = 0,
UNSATISFIABLE,
@@ -76,11 +88,23 @@ enum ABC_StatusT
#endif
-// ABC_OptionT defines the solver option about learning
+// to identify who called the CSAT solver
+#ifndef _ABC_CALLER_
+#define _ABC_CALLER_
+enum CSAT_CallerT
+{
+ BLS = 0,
+ SATORI,
+ NONE
+};
+#endif
+
+
+// CSAT_OptionT defines the solver option about learning
// which is used by ABC_SetSolveOption();
#ifndef _ABC_OPTION_
#define _ABC_OPTION_
-enum ABC_OptionT
+enum CSAT_OptionT
{
BASE_LINE = 0,
IMPLICT_LEARNING, //default
@@ -91,10 +115,10 @@ enum ABC_OptionT
#ifndef _ABC_Target_Result
#define _ABC_Target_Result
-typedef struct _ABC_Target_ResultT ABC_Target_ResultT;
-struct _ABC_Target_ResultT
+typedef struct _CSAT_Target_ResultT CSAT_Target_ResultT;
+struct _CSAT_Target_ResultT
{
- enum ABC_StatusT status; // solve status of the target
+ enum CSAT_StatusT status; // solve status of the target
int num_dec; // num of decisions to solve the target
int num_imp; // num of implications to solve the target
int num_cftg; // num of conflict gates learned
@@ -118,10 +142,13 @@ struct _ABC_Target_ResultT
////////////////////////////////////////////////////////////////////////
// create a new manager
-extern ABC_Manager ABC_InitManager(void);
+extern ABC_Manager ABC_InitManager(void);
+
+// release a manager
+extern void ABC_ReleaseManager(ABC_Manager mng);
// set solver options for learning
-extern void ABC_SetSolveOption(ABC_Manager mng, enum ABC_OptionT option);
+extern void ABC_SetSolveOption(ABC_Manager mng, enum CSAT_OptionT option);
// add a gate to the circuit
// the meaning of the parameters are:
@@ -130,16 +157,19 @@ extern void ABC_SetSolveOption(ABC_Manager mng, enum ABC_Option
// nofi: number of fanins of the gate to be added;
// fanins: the name array of fanins of the gate to be added
extern int ABC_AddGate(ABC_Manager mng,
- enum GateType type,
- char* name,
- int nofi,
- char** fanins,
- int dc_attr);
+ enum GateType type,
+ char* name,
+ int nofi,
+ char** fanins,
+ int dc_attr);
// check if there are gates that are not used by any primary ouput.
// if no such gates exist, return 1 else return 0;
extern int ABC_Check_Integrity(ABC_Manager mng);
+// THIS PROCEDURE SHOULD BE CALLED AFTER THE NETWORK IS CONSTRUCTED!!!
+extern void ABC_Network_Finalize( ABC_Manager mng );
+
// set time limit for solving a target.
// runtime: time limit (in second).
extern void ABC_SetTimeLimit(ABC_Manager mng, int runtime);
@@ -160,21 +190,24 @@ extern void ABC_SolveInit(ABC_Manager mng);
extern void ABC_AnalyzeTargets(ABC_Manager mng);
// solve the targets added by ABC_AddTarget()
-extern enum ABC_StatusT ABC_Solve(ABC_Manager mng);
+extern enum CSAT_StatusT ABC_Solve(ABC_Manager mng);
// get the solve status of a target
// TargetID: the target id returned by ABC_AddTarget().
-extern ABC_Target_ResultT * ABC_Get_Target_Result(ABC_Manager mng, int TargetID);
+extern CSAT_Target_ResultT * ABC_Get_Target_Result(ABC_Manager mng, int TargetID);
extern void ABC_Dump_Bench_File(ABC_Manager mng);
// ADDED PROCEDURES:
-extern void ABC_QuitManager( ABC_Manager mng );
-extern void ABC_TargetResFree( ABC_Target_ResultT * p );
+extern void ABC_TargetResFree( CSAT_Target_ResultT * p );
-extern void ABC_PerformRewriting( ABC_Manager mng );
+extern void CSAT_SetCaller(ABC_Manager mng, enum CSAT_CallerT caller);
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/src/sat/fraig/fraig.h b/src/sat/fraig/fraig.h
index 237030af..4637c030 100644
--- a/src/sat/fraig/fraig.h
+++ b/src/sat/fraig/fraig.h
@@ -44,6 +44,8 @@ struct Fraig_ParamsStruct_t_
int nPatsDyna; // the number of words of dynamic simulation info
int nBTLimit; // the max number of backtracks to perform
int nSeconds; // the timeout for the final proof
+ int nConfLimit;
+ int nImpLimit;
int fFuncRed; // performs only one level hashing
int fFeedBack; // enables solver feedback
int fDist1Pats; // enables distance-1 patterns
diff --git a/src/sat/fraig/fraigCanon.c b/src/sat/fraig/fraigCanon.c
index fab01368..4ebb9a9f 100644
--- a/src/sat/fraig/fraigCanon.c
+++ b/src/sat/fraig/fraigCanon.c
@@ -49,7 +49,7 @@
Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 )
{
Fraig_Node_t * pNodeNew, * pNodeOld, * pNodeRepr;
- int RetValue;
+// int RetValue;
// check for trivial cases
if ( p1 == p2 )