summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2009-01-18 08:01:00 -0800
committerAlan Mishchenko <alanmi@berkeley.edu>2009-01-18 08:01:00 -0800
commitf936cc0680c98ffe51b3a1716c996072d5dbf76c (patch)
tree784a2a809fb6b972ec6a8e2758ab758ca590d01a /src
parentc9ad5880cc61787dec6d018111b63023407ce0e6 (diff)
downloadabc-f936cc0680c98ffe51b3a1716c996072d5dbf76c.tar.gz
abc-f936cc0680c98ffe51b3a1716c996072d5dbf76c.tar.bz2
abc-f936cc0680c98ffe51b3a1716c996072d5dbf76c.zip
Version abc90118
Diffstat (limited to 'src')
-rw-r--r--src/aig/aig/aig.h15
-rw-r--r--src/aig/aig/aigCanon.c694
-rw-r--r--src/aig/aig/aigDup.c1
-rw-r--r--src/aig/aig/aigMan.c24
-rw-r--r--src/aig/aig/aigMffc.c28
-rw-r--r--src/aig/aig/aigObj.c9
-rw-r--r--src/aig/aig/aigScl.c57
-rw-r--r--src/aig/aig/aigTsim.c6
-rw-r--r--src/aig/aig/module.make1
-rw-r--r--src/aig/bbr/bbrImage.c8
-rw-r--r--src/aig/bdc/bdcCore.c3
-rw-r--r--src/aig/bdc/bdcInt.h2
-rw-r--r--src/aig/cec/cec.h100
-rw-r--r--src/aig/cec/cecAig.c151
-rw-r--r--src/aig/cec/cecClass.c569
-rw-r--r--src/aig/cec/cecCnf.c328
-rw-r--r--src/aig/cec/cecCore.c233
-rw-r--r--src/aig/cec/cecInt.h220
-rw-r--r--src/aig/cec/cecMan.c (renamed from src/aig/saig/saigLoc.c)21
-rw-r--r--src/aig/cec/cecSat.c322
-rw-r--r--src/aig/cec/cecSim.c459
-rw-r--r--src/aig/cec/cecStatus.c187
-rw-r--r--src/aig/cec/module.make8
-rw-r--r--src/aig/cgt/cgt.h3
-rw-r--r--src/aig/cgt/cgtAig.c381
-rw-r--r--src/aig/cgt/cgtCore.c112
-rw-r--r--src/aig/cgt/cgtDecide.c220
-rw-r--r--src/aig/cgt/cgtInt.h21
-rw-r--r--src/aig/cgt/cgtMan.c50
-rw-r--r--src/aig/cnf/cnfWrite.c2
-rw-r--r--src/aig/dar/dar.h5
-rw-r--r--src/aig/dar/darCore.c9
-rw-r--r--src/aig/dar/darLib.c36
-rw-r--r--src/aig/dar/darRefact.c2
-rw-r--r--src/aig/dar/darScript.c17
-rw-r--r--src/aig/dch/dch.h1
-rw-r--r--src/aig/dch/dchCore.c1
-rw-r--r--src/aig/fra/fraSec.c2
-rw-r--r--src/aig/fsim/fsim.h97
-rw-r--r--src/aig/fsim/fsimCore.c83
-rw-r--r--src/aig/fsim/fsimFront.c364
-rw-r--r--src/aig/fsim/fsimInt.h134
-rw-r--r--src/aig/fsim/fsimMan.c207
-rw-r--r--src/aig/fsim/fsimSim.c560
-rw-r--r--src/aig/fsim/fsimSwitch.c588
-rw-r--r--src/aig/fsim/fsimTsim.c410
-rw-r--r--src/aig/fsim/module.make6
-rw-r--r--src/aig/hop/hop.h5
-rw-r--r--src/aig/hop/hopObj.c1
-rw-r--r--src/aig/hop/hopTruth.c12
-rw-r--r--src/aig/ioa/ioaWriteAig.c6
-rw-r--r--src/aig/kit/kit.h15
-rw-r--r--src/aig/kit/kitDsd.c128
-rw-r--r--src/aig/kit/kitTruth.c124
-rw-r--r--src/aig/mfx/mfx.h1
-rw-r--r--src/aig/mfx/mfxCore.c65
-rw-r--r--src/aig/mfx/mfxInt.h3
-rw-r--r--src/aig/mfx/mfxMan.c2
-rw-r--r--src/aig/mfx/mfxResub.c36
-rw-r--r--src/aig/ntl/ntl.h31
-rw-r--r--src/aig/ntl/ntlCheck.c2
-rw-r--r--src/aig/ntl/ntlCore.c4
-rw-r--r--src/aig/ntl/ntlExtract.c4
-rw-r--r--src/aig/ntl/ntlFraig.c51
-rw-r--r--src/aig/ntl/ntlInsert.c51
-rw-r--r--src/aig/ntl/ntlMan.c82
-rw-r--r--src/aig/ntl/ntlReadBlif.c3
-rw-r--r--src/aig/ntl/ntlSweep.c9
-rw-r--r--src/aig/ntl/ntlTable.c37
-rw-r--r--src/aig/ntl/ntlUtil.c2
-rw-r--r--src/aig/ntl/ntlWriteBlif.c12
-rw-r--r--src/aig/nwk/nwk.h13
-rw-r--r--src/aig/nwk/nwkBidec.c53
-rw-r--r--src/aig/nwk/nwkMan.c42
-rw-r--r--src/aig/nwk/nwkMap.c26
-rw-r--r--src/aig/nwk/nwkMerge.c6
-rw-r--r--src/aig/nwk/nwkStrash.c1
-rw-r--r--src/aig/nwk2/nwk.h2
-rw-r--r--src/aig/nwk2/nwkMan.c2
-rw-r--r--src/aig/saig/module.make10
-rw-r--r--src/aig/saig/saig.h32
-rw-r--r--src/aig/saig/saigAbs.c259
-rw-r--r--src/aig/saig/saigBmc.c82
-rw-r--r--src/aig/saig/saigDup.c6
-rw-r--r--src/aig/saig/saigMiter.c210
-rw-r--r--src/aig/saig/saigPhase.c10
-rw-r--r--src/aig/saig/saigSimExt.c325
-rw-r--r--src/aig/saig/saigSimFast.c443
-rw-r--r--src/aig/saig/saigSimMv.c726
-rw-r--r--src/aig/saig/saigSimSeq.c513
-rw-r--r--src/aig/saig/saigStrSim.c971
-rw-r--r--src/aig/saig/saigSwitch.c582
-rw-r--r--src/aig/saig/saigWnd.c809
-rw-r--r--src/aig/ssw/ssw.h20
-rw-r--r--src/aig/ssw/sswAig.c1
-rw-r--r--src/aig/ssw/sswClass.c6
-rw-r--r--src/aig/ssw/sswCore.c10
-rw-r--r--src/aig/ssw/sswDyn.c106
-rw-r--r--src/aig/ssw/sswInt.h18
-rw-r--r--src/aig/ssw/sswIslands.c543
-rw-r--r--src/aig/ssw/sswMan.c5
-rw-r--r--src/aig/ssw/sswPart.c2
-rw-r--r--src/aig/ssw/sswSim.c229
-rw-r--r--src/base/abc/abc.h18
-rw-r--r--src/base/abc/abcHie.c3
-rw-r--r--src/base/abci/abc.c1478
-rw-r--r--src/base/abci/abc.zipbin62408 -> 0 bytes
-rw-r--r--src/base/abci/abcBidec.c33
-rw-r--r--src/base/abci/abcCut.c75
-rw-r--r--src/base/abci/abcDar.c726
-rw-r--r--src/base/abci/abcDelay.c297
-rw-r--r--src/base/abci/abcIf.c58
-rw-r--r--src/base/abci/abcMap.c6
-rw-r--r--src/base/abci/abcMerge.c352
-rw-r--r--src/base/abci/abcPrint.c82
-rw-r--r--src/base/abci/abcStrash.c8
-rw-r--r--src/base/abci/module.make1
-rw-r--r--src/base/cmd/cmd.c1
-rw-r--r--src/base/cmd/cmd.h8
-rw-r--r--src/base/io/io.c45
-rw-r--r--src/base/io/ioAbc.h3
-rw-r--r--src/base/io/ioReadAiger.c2
-rw-r--r--src/base/io/ioReadBlifMv.c3
-rw-r--r--src/base/io/ioUtil.c2
-rw-r--r--src/base/io/ioWriteBook.c985
-rw-r--r--src/base/io/io_.c48
-rw-r--r--src/base/io/module.make1
-rw-r--r--src/base/main/main.c6
-rw-r--r--src/base/main/main.h11
-rw-r--r--src/base/main/mainFrame.c2
-rw-r--r--src/base/main/mainInt.h10
-rw-r--r--src/map/amap/amap.h83
-rw-r--r--src/map/amap/amapCore.c103
-rw-r--r--src/map/amap/amapGraph.c389
-rw-r--r--src/map/amap/amapInt.h380
-rw-r--r--src/map/amap/amapLib.c361
-rw-r--r--src/map/amap/amapMan.c99
-rw-r--r--src/map/amap/amapMatch.c538
-rw-r--r--src/map/amap/amapMerge.c521
-rw-r--r--src/map/amap/amapOutput.c181
-rw-r--r--src/map/amap/amapParse.c457
-rw-r--r--src/map/amap/amapPerm.c344
-rw-r--r--src/map/amap/amapRead.c412
-rw-r--r--src/map/amap/amapRule.c368
-rw-r--r--src/map/amap/amapUniq.c312
-rw-r--r--src/map/amap/module.make12
-rw-r--r--src/map/if/if.h9
-rw-r--r--src/map/if/ifCut.c295
-rw-r--r--src/map/if/ifMan.c2
-rw-r--r--src/map/if/ifMap.c10
-rw-r--r--src/map/if/ifReduce.c4
-rw-r--r--src/map/if/ifUtil.c5
-rw-r--r--src/map/mapper/mapperTime.c2
-rw-r--r--src/map/mio/mio.c193
-rw-r--r--src/map/mio/mio.h3
-rw-r--r--src/map/mio/mio81214.zipbin0 -> 16939 bytes
-rw-r--r--src/map/mio/mioApi.c25
-rw-r--r--src/map/mio/mioGENERIC.c46
-rw-r--r--src/map/mio/mioInt.h5
-rw-r--r--src/map/mio/mioRead.c81
-rw-r--r--src/map/mio/mioUtils.c13
-rw-r--r--src/map/super/superGate.c7
-rw-r--r--src/misc/avl/avl.c616
-rw-r--r--src/misc/avl/avl.doc166
-rw-r--r--src/misc/avl/avl.h80
-rw-r--r--src/misc/extra/extra.h21
-rw-r--r--src/misc/extra/extraUtilMemory.c4
-rw-r--r--src/misc/extra/extraUtilUtil.c16
-rw-r--r--src/misc/util/leaks.h30
-rw-r--r--src/misc/util/stdlib_hack.h4
-rw-r--r--src/misc/vec/vec.h8
-rw-r--r--src/opt/cut/cut.h2
-rw-r--r--src/opt/cut/cutNode.c7
-rw-r--r--src/opt/lpk/lpkAbcDsd.c7
-rw-r--r--src/opt/lpk/lpkCore.c4
-rw-r--r--src/opt/mfs/mfs.h1
-rw-r--r--src/opt/mfs/mfsCore.c248
-rw-r--r--src/opt/mfs/mfsCore_.c388
-rw-r--r--src/opt/mfs/mfsInt.h5
-rw-r--r--src/opt/mfs/mfsMan.c25
-rw-r--r--src/opt/mfs/mfsResub.c67
-rw-r--r--src/opt/mfs/mfsResub_.c560
-rw-r--r--src/opt/sim/simSwitch.c2
-rw-r--r--src/sat/bsat/satInterP.c150
-rw-r--r--src/sat/bsat/satStore.h2
185 files changed, 24256 insertions, 1187 deletions
diff --git a/src/aig/aig/aig.h b/src/aig/aig/aig.h
index 0cdd5b1a..3db9b845 100644
--- a/src/aig/aig/aig.h
+++ b/src/aig/aig/aig.h
@@ -144,6 +144,7 @@ struct Aig_Man_t_
void * pImpData; // implication checking data
void * pManTime; // the timing manager
void * pManCuts;
+ int * pFastSim;
Vec_Ptr_t * vMapped;
Vec_Int_t * vFlopNums;
Vec_Int_t * vFlopReprs;
@@ -154,6 +155,7 @@ struct Aig_Man_t_
int fCreatePios;
Vec_Int_t * vEquPairs;
Vec_Vec_t * vClockDoms;
+ Vec_Int_t * vProbs; // probability of node being 1
// timing statistics
int time1;
int time2;
@@ -195,14 +197,14 @@ struct Aig_ManCut_t_
};
#ifdef WIN32
-#define DLLEXPORT __declspec(dllexport)
-#define DLLIMPORT __declspec(dllimport)
+#define ABC_DLLEXPORT __declspec(dllexport)
+#define ABC_DLLIMPORT __declspec(dllimport)
#else /* defined(WIN32) */
-#define DLLIMPORT
+#define ABC_DLLIMPORT
#endif /* defined(WIN32) */
#ifndef ABC_DLL
-#define ABC_DLL DLLIMPORT
+#define ABC_DLL ABC_DLLIMPORT
#endif
static inline Aig_Cut_t * Aig_ObjCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj ) { return p->pCuts[pObj->Id]; }
@@ -338,6 +340,7 @@ static inline int Aig_ObjSetLevel( Aig_Obj_t * pObj, int i ) { assert(
static inline void Aig_ObjClean( Aig_Obj_t * pObj ) { memset( pObj, 0, sizeof(Aig_Obj_t) ); }
static inline Aig_Obj_t * Aig_ObjFanout0( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert(p->pFanData && pObj->Id < p->nFansAlloc); return Aig_ManObj(p, p->pFanData[5*pObj->Id] >> 1); }
static inline Aig_Obj_t * Aig_ObjEquiv( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquivs? p->pEquivs[pObj->Id] : NULL; }
+static inline void Aig_ObjSetEquiv( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pEqu ) { assert(p->pEquivs); p->pEquivs[pObj->Id] = pEqu; }
static inline Aig_Obj_t * Aig_ObjRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pReprs? p->pReprs[pObj->Id] : NULL; }
static inline void Aig_ObjSetRepr( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) { assert(p->pReprs); p->pReprs[pObj->Id] = pRepr; }
static inline Aig_Obj_t * Aig_ObjHaig( Aig_Obj_t * pObj ) { assert( Aig_Regular(pObj)->pHaig ); return Aig_NotCond( Aig_Regular(pObj)->pHaig, Aig_IsComplement(pObj) ); }
@@ -529,9 +532,9 @@ extern void Aig_ManStartMemory( Aig_Man_t * p );
extern void Aig_ManStopMemory( Aig_Man_t * p );
/*=== aigMffc.c ==========================================================*/
extern int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin );
-extern int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin );
+extern int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin, float * pPower, float * pProbs );
extern int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp );
-extern int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode );
+extern int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode, float * pPower );
extern int Aig_NodeMffsLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves );
extern int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult );
/*=== aigObj.c ==========================================================*/
diff --git a/src/aig/aig/aigCanon.c b/src/aig/aig/aigCanon.c
new file mode 100644
index 00000000..febad8ae
--- /dev/null
+++ b/src/aig/aig/aigCanon.c
@@ -0,0 +1,694 @@
+/**CFile****************************************************************
+
+ FileName [aigCanon.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [AIG package.]
+
+ Synopsis [Processing the library of semi-canonical AIGs.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: aigCanon.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "kit.h"
+#include "bdc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define RMAN_MAXVARS 12
+#define RMAX_MAXWORD (RMAN_MAXVARS <= 5 ? 1 : (1 << (RMAN_MAXVARS - 5)))
+
+typedef struct Aig_VSig_t_ Aig_VSig_t;
+struct Aig_VSig_t_
+{
+ int nOnes;
+ short nCofOnes[RMAN_MAXVARS];
+};
+
+typedef struct Aig_Tru_t_ Aig_Tru_t;
+struct Aig_Tru_t_
+{
+ Aig_Tru_t * pNext;
+ int Id;
+ unsigned nVisits : 27;
+ unsigned nVars : 5;
+ unsigned pTruth[0];
+};
+
+typedef struct Aig_RMan_t_ Aig_RMan_t;
+struct Aig_RMan_t_
+{
+ int nVars; // the largest variable number
+ Aig_Man_t * pAig; // recorded subgraphs
+ // hash table
+ int nBins;
+ Aig_Tru_t ** pBins;
+ int nEntries;
+ Aig_MmFlex_t* pMemTrus;
+ // bidecomposion
+ Bdc_Man_t * pBidec;
+ // temporaries
+ unsigned pTruthInit[RMAX_MAXWORD]; // canonical truth table
+ unsigned pTruth[RMAX_MAXWORD]; // current truth table
+ unsigned pTruthC[RMAX_MAXWORD]; // canonical truth table
+ unsigned pTruthTemp[RMAX_MAXWORD]; // temporary truth table
+ Aig_VSig_t pMints[2*RMAN_MAXVARS]; // minterm count
+ char pPerm[RMAN_MAXVARS]; // permutation
+ char pPermR[RMAN_MAXVARS]; // reverse permutation
+ // statistics
+ int nVarFuncs[RMAN_MAXVARS+1];
+ int nTotal;
+ int nTtDsd;
+ int nTtDsdPart;
+ int nTtDsdNot;
+ int nUniqueVars;
+};
+
+static Aig_RMan_t * s_pRMan = NULL;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates recording manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_RMan_t * Aig_RManStart()
+{
+ static Bdc_Par_t Pars = {0}, * pPars = &Pars;
+ Aig_RMan_t * p;
+ p = ALLOC( Aig_RMan_t, 1 );
+ memset( p, 0, sizeof(Aig_RMan_t) );
+ p->nVars = RMAN_MAXVARS;
+ p->pAig = Aig_ManStart( 1000000 );
+ Aig_IthVar( p->pAig, p->nVars-1 );
+ // create hash table
+ p->nBins = Aig_PrimeCudd(5000);
+ p->pBins = CALLOC( Aig_Tru_t *, p->nBins );
+ p->pMemTrus = Aig_MmFlexStart();
+ // bi-decomposition manager
+ pPars->nVarsMax = p->nVars;
+ pPars->fVerbose = 0;
+ p->pBidec = Bdc_ManAlloc( pPars );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the hash key.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Aig_RManTableHash( unsigned * pTruth, int nVars, int nBins, int * pPrimes )
+{
+ int i, nWords = Kit_TruthWordNum( nVars );
+ unsigned uHash = 0;
+ for ( i = 0; i < nWords; i++ )
+ uHash ^= pTruth[i] * pPrimes[i & 0xf];
+ return (int)(uHash % nBins);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the given record.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Tru_t ** Aig_RManTableLookup( Aig_RMan_t * p, unsigned * pTruth, int nVars )
+{
+ static int s_Primes[16] = {
+ 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177,
+ 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 };
+ Aig_Tru_t ** ppSpot, * pEntry;
+ ppSpot = p->pBins + Aig_RManTableHash( pTruth, nVars, p->nBins, s_Primes );
+ for ( pEntry = *ppSpot; pEntry; ppSpot = &pEntry->pNext, pEntry = pEntry->pNext )
+ if ( Kit_TruthIsEqual( pEntry->pTruth, pTruth, nVars ) )
+ return ppSpot;
+ return ppSpot;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find or add new entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_RManTableResize( Aig_RMan_t * p )
+{
+ Aig_Tru_t * pEntry, * pNext;
+ Aig_Tru_t ** pBinsOld, ** ppPlace;
+ int nBinsOld, Counter, i, clk;
+ assert( p->pBins != NULL );
+clk = clock();
+ // save the old Bins
+ pBinsOld = p->pBins;
+ nBinsOld = p->nBins;
+ // get the new Bins
+ p->nBins = Aig_PrimeCudd( 3 * nBinsOld );
+ p->pBins = CALLOC( Aig_Tru_t *, p->nBins );
+ // rehash the entries from the old table
+ Counter = 0;
+ for ( i = 0; i < nBinsOld; i++ )
+ for ( pEntry = pBinsOld[i], pNext = pEntry? pEntry->pNext : NULL;
+ pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL )
+ {
+ // get the place where this entry goes in the Bins
+ ppPlace = Aig_RManTableLookup( p, pEntry->pTruth, pEntry->nVars );
+ assert( *ppPlace == NULL ); // should not be there
+ // add the entry to the list
+ *ppPlace = pEntry;
+ pEntry->pNext = NULL;
+ Counter++;
+ }
+ assert( Counter == p->nEntries );
+// PRT( "Time", clock() - clk );
+ free( pBinsOld );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find or add new entry.]
+
+ Description [Returns 1 if this is a new entry.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_RManTableFindOrAdd( Aig_RMan_t * p, unsigned * pTruth, int nVars )
+{
+ Aig_Tru_t ** ppSpot, * pEntry;
+ int nBytes;
+ ppSpot = Aig_RManTableLookup( p, pTruth, nVars );
+ if ( *ppSpot )
+ {
+ (*ppSpot)->nVisits++;
+ return 0;
+ }
+ nBytes = sizeof(Aig_Tru_t) + sizeof(unsigned) * Kit_TruthWordNum(nVars);
+ if ( p->nEntries == 3*p->nBins )
+ Aig_RManTableResize( p );
+ pEntry = (Aig_Tru_t *)Aig_MmFlexEntryFetch( p->pMemTrus, nBytes );
+ pEntry->Id = p->nEntries++;
+ pEntry->nVars = nVars;
+ pEntry->nVisits = 1;
+ pEntry->pNext = NULL;
+ memcpy( pEntry->pTruth, pTruth, sizeof(unsigned) * Kit_TruthWordNum(nVars) );
+ *ppSpot = pEntry;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates recording manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_RManStop( Aig_RMan_t * p )
+{
+ int i;
+ printf( "Total funcs = %10d\n", p->nTotal );
+ printf( "Full DSD funcs = %10d\n", p->nTtDsd );
+ printf( "Part DSD funcs = %10d\n", p->nTtDsdPart );
+ printf( "Non- DSD funcs = %10d\n", p->nTtDsdNot );
+ printf( "Uniq-var funcs = %10d\n", p->nUniqueVars );
+ printf( "Unique funcs = %10d\n", p->nEntries );
+ printf( "Distribution of functions:\n" );
+ for ( i = 5; i <= p->nVars; i++ )
+ printf( "%2d = %8d\n", i, p->nVarFuncs[i] );
+ Aig_MmFlexStop( p->pMemTrus, 0 );
+ Aig_ManStop( p->pAig );
+ Bdc_ManFree( p->pBidec );
+ free( p->pBins );
+ free( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Stops recording.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_RManQuit()
+{
+ extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
+ char Buffer[20];
+ if ( s_pRMan == NULL )
+ return;
+ // dump the library file
+ sprintf( Buffer, "aiglib%02d.aig", s_pRMan->nVars );
+ Ioa_WriteAiger( s_pRMan->pAig, Buffer, 0, 1 );
+ // quit the manager
+ Aig_RManStop( s_pRMan );
+ s_pRMan = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if all variables are unique.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_RManPrintVarProfile( unsigned * pTruth, int nVars, unsigned * pTruthAux )
+{
+ short pStore2[32];
+ int i;
+ Kit_TruthCountOnesInCofsSlow( pTruth, nVars, pStore2, pTruthAux );
+ for ( i = 0; i < nVars; i++ )
+ printf( "%2d/%2d ", pStore2[2*i], pStore2[2*i+1] );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorts numbers in the increasing order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_RManSortNums( short * pArray, int nVars )
+{
+ int i, j, best_i, tmp;
+ for ( i = 0; i < nVars-1; i++ )
+ {
+ best_i = i;
+ for ( j = i+1; j < nVars; j++ )
+ if ( pArray[j] > pArray[best_i] )
+ best_i = j;
+ tmp = pArray[i]; pArray[i] = pArray[best_i]; pArray[best_i] = tmp;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints signatures for all variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_RManPrintSigs( Aig_VSig_t * pSigs, int nVars )
+{
+ int v, i, k;
+ for ( v = 0; v < nVars; v++ )
+ {
+ printf( "%2d : ", v );
+ for ( k = 0; k < 2; k++ )
+ {
+ printf( "%5d ", pSigs[2*v+k].nOnes );
+ printf( "(" );
+ for ( i = 0; i < nVars; i++ )
+ printf( "%4d ", pSigs[2*v+k].nCofOnes[i] );
+ printf( ") " );
+ }
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes signatures for all variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_RManComputeVSigs( unsigned * pTruth, int nVars, Aig_VSig_t * pSigs, unsigned * pAux )
+{
+ int v;
+ for ( v = 0; v < nVars; v++ )
+ {
+ Kit_TruthCofactor0New( pAux, pTruth, nVars, v );
+ pSigs[2*v+0].nOnes = Kit_TruthCountOnes( pAux, nVars );
+ Kit_TruthCountOnesInCofs0( pAux, nVars, pSigs[2*v+0].nCofOnes );
+ Aig_RManSortNums( pSigs[2*v+0].nCofOnes, nVars );
+
+ Kit_TruthCofactor1New( pAux, pTruth, nVars, v );
+ pSigs[2*v+1].nOnes = Kit_TruthCountOnes( pAux, nVars );
+ Kit_TruthCountOnesInCofs0( pAux, nVars, pSigs[2*v+1].nCofOnes );
+ Aig_RManSortNums( pSigs[2*v+1].nCofOnes, nVars );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computs signatures for all variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Aig_RManCompareSigs( Aig_VSig_t * p0, Aig_VSig_t * p1, int nVars )
+{
+// return memcmp( p0, p1, sizeof(int) + sizeof(short) * nVars );
+ return memcmp( p0, p1, sizeof(int) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if all variables are unique.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_RManVarsAreUnique( Aig_VSig_t * pMints, int nVars )
+{
+ int i;
+ for ( i = 0; i < nVars - 1; i++ )
+ if ( Aig_RManCompareSigs( &pMints[2*i], &pMints[2*(i+1)], nVars ) == 0 )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if all variables are unique.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_RManPrintUniqueVars( Aig_VSig_t * pMints, int nVars )
+{
+ int i;
+ for ( i = 0; i < nVars; i++ )
+ if ( Aig_RManCompareSigs( &pMints[2*i], &pMints[2*i+1], nVars ) == 0 )
+ printf( "=" );
+ else
+ printf( "x" );
+ printf( "\n" );
+
+ printf( "0" );
+ for ( i = 1; i < nVars; i++ )
+ if ( Aig_RManCompareSigs( &pMints[2*(i-1)], &pMints[2*i], nVars ) == 0 )
+ printf( "-" );
+ else if ( i < 10 )
+ printf( "%c", '0' + i );
+ else
+ printf( "%c", 'A' + i-10 );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Canonicize the truth table.]
+
+ Description [Returns the phase. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Aig_RManSemiCanonicize( unsigned * pOut, unsigned * pIn, int nVars, char * pCanonPerm, Aig_VSig_t * pSigs, int fReturnIn )
+{
+ Aig_VSig_t TempSig;
+ int i, Temp, fChange, Counter;
+ unsigned * pTemp, uCanonPhase = 0;
+ // collect signatures
+ Aig_RManComputeVSigs( pIn, nVars, pSigs, pOut );
+ // canonicize phase
+ for ( i = 0; i < nVars; i++ )
+ {
+// if ( pStore[2*i+0] <= pStore[2*i+1] )
+ if ( Aig_RManCompareSigs( &pSigs[2*i+0], &pSigs[2*i+1], nVars ) <= 0 )
+ continue;
+ uCanonPhase |= (1 << i);
+ TempSig = pSigs[2*i+0];
+ pSigs[2*i+0] = pSigs[2*i+1];
+ pSigs[2*i+1] = TempSig;
+ Kit_TruthChangePhase( pIn, nVars, i );
+ }
+ // permute
+ Counter = 0;
+ do {
+ fChange = 0;
+ for ( i = 0; i < nVars-1; i++ )
+ {
+// if ( pStore[2*i] <= pStore[2*(i+1)] )
+ if ( Aig_RManCompareSigs( &pSigs[2*i], &pSigs[2*(i+1)], nVars ) <= 0 )
+ continue;
+ Counter++;
+ fChange = 1;
+
+ Temp = pCanonPerm[i];
+ pCanonPerm[i] = pCanonPerm[i+1];
+ pCanonPerm[i+1] = Temp;
+
+ TempSig = pSigs[2*i];
+ pSigs[2*i] = pSigs[2*(i+1)];
+ pSigs[2*(i+1)] = TempSig;
+
+ TempSig = pSigs[2*i+1];
+ pSigs[2*i+1] = pSigs[2*(i+1)+1];
+ pSigs[2*(i+1)+1] = TempSig;
+
+ Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ }
+ } while ( fChange );
+
+ // swap if it was moved an even number of times
+ if ( fReturnIn ^ !(Counter & 1) )
+ Kit_TruthCopy( pOut, pIn, nVars );
+ return uCanonPhase;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Aig_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj )
+{ return Aig_NotCond( Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); }
+
+/**Function*************************************************************
+
+ Synopsis [Records one function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_RManSaveOne( Aig_RMan_t * p, unsigned * pTruth, int nVars )
+{
+ int i, nNodes, RetValue;
+ Bdc_Fun_t * pFunc;
+ Aig_Obj_t * pTerm;
+ // perform decomposition
+ RetValue = Bdc_ManDecompose( p->pBidec, pTruth, NULL, nVars, NULL, 1000 );
+ if ( RetValue < 0 )
+ {
+ printf( "Decomposition failed.\n" );
+ return;
+ }
+ // convert back into HOP
+ Bdc_FuncSetCopy( Bdc_ManFunc( p->pBidec, 0 ), Aig_ManConst1(p->pAig) );
+ for ( i = 0; i < nVars; i++ )
+ Bdc_FuncSetCopy( Bdc_ManFunc( p->pBidec, i+1 ), Aig_IthVar(p->pAig, i) );
+ nNodes = Bdc_ManNodeNum(p->pBidec);
+ for ( i = nVars + 1; i < nNodes; i++ )
+ {
+ pFunc = Bdc_ManFunc( p->pBidec, i );
+ Bdc_FuncSetCopy( pFunc, Aig_And( p->pAig,
+ Bdc_FunCopyHop(Bdc_FuncFanin0(pFunc)),
+ Bdc_FunCopyHop(Bdc_FuncFanin1(pFunc)) ) );
+ }
+ pTerm = Bdc_FunCopyHop( Bdc_ManRoot(p->pBidec) );
+ pTerm = Aig_ObjCreatePo( p->pAig, pTerm );
+// assert( pTerm->fPhase == 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Records one function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_RManRecord( unsigned * pTruth, int nVarsInit )
+{
+ int fVerify = 1;
+ Kit_DsdNtk_t * pNtk;
+ Kit_DsdObj_t * pObj;
+ unsigned uPhaseC;
+ int i, nVars, nWords;
+ int fUniqueVars;
+
+ if ( nVarsInit > RMAN_MAXVARS )
+ {
+ printf( "The number of variables in too large.\n" );
+ return;
+ }
+
+ if ( s_pRMan == NULL )
+ s_pRMan = Aig_RManStart();
+ s_pRMan->nTotal++;
+ // canonicize the function
+ pNtk = Kit_DsdDecompose( pTruth, nVarsInit );
+ pObj = Kit_DsdNonDsdPrimeMax( pNtk );
+ if ( pObj == NULL || pObj->nFans == 3 )
+ {
+ s_pRMan->nTtDsd++;
+ Kit_DsdNtkFree( pNtk );
+ return;
+ }
+ nVars = pObj->nFans;
+ s_pRMan->nVarFuncs[nVars]++;
+ if ( nVars < nVarsInit )
+ s_pRMan->nTtDsdPart++;
+ else
+ s_pRMan->nTtDsdNot++;
+ // compute the number of words
+ nWords = Aig_TruthWordNum( nVars );
+ // copy the function
+ memcpy( s_pRMan->pTruthInit, Kit_DsdObjTruth(pObj), 4*nWords );
+ Kit_DsdNtkFree( pNtk );
+ // canonicize the output
+ if ( s_pRMan->pTruthInit[0] & 1 )
+ Kit_TruthNot( s_pRMan->pTruthInit, s_pRMan->pTruthInit, nVars );
+ memcpy( s_pRMan->pTruth, s_pRMan->pTruthInit, 4*nWords );
+
+ // canonize the function
+ for ( i = 0; i < nVars; i++ )
+ s_pRMan->pPerm[i] = i;
+ uPhaseC = Aig_RManSemiCanonicize( s_pRMan->pTruthTemp, s_pRMan->pTruth, nVars, s_pRMan->pPerm, s_pRMan->pMints, 1 );
+ // check unique variables
+ fUniqueVars = Aig_RManVarsAreUnique( s_pRMan->pMints, nVars );
+ s_pRMan->nUniqueVars += fUniqueVars;
+
+/*
+ printf( "%4d : ", s_pRMan->nTotal );
+ printf( "%2d %2d ", nVarsInit, nVars );
+ Extra_PrintBinary( stdout, &uPhaseC, nVars );
+ printf( " " );
+ for ( i = 0; i < nVars; i++ )
+ printf( "%2d/%2d ", s_pRMan->pMints[2*i], s_pRMan->pMints[2*i+1] );
+ printf( "\n" );
+ Aig_RManPrintUniqueVars( s_pRMan->pMints, nVars );
+Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<<nVars ); printf( "\n\n" );
+*/
+/*
+ printf( "\n" );
+ printf( "%4d : ", s_pRMan->nTotal );
+ printf( "%2d %2d ", nVarsInit, nVars );
+ printf( " " );
+ printf( "\n" );
+ Aig_RManPrintUniqueVars( s_pRMan->pMints, nVars );
+// Aig_RManPrintSigs( s_pRMan->pMints, nVars );
+*/
+
+//Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<<nVars ); printf( "\n\n" );
+
+ if ( Aig_RManTableFindOrAdd( s_pRMan, s_pRMan->pTruth, nVars ) )
+ Aig_RManSaveOne( s_pRMan, s_pRMan->pTruth, nVars );
+
+ if ( fVerify )
+ {
+ // derive reverse permutation
+ for ( i = 0; i < nVars; i++ )
+ s_pRMan->pPermR[i] = s_pRMan->pPerm[i];
+ // implement permutation
+ Kit_TruthPermute( s_pRMan->pTruthTemp, s_pRMan->pTruth, nVars, s_pRMan->pPermR, 1 );
+ // implement polarity
+ for ( i = 0; i < nVars; i++ )
+ if ( uPhaseC & (1 << i) )
+ Kit_TruthChangePhase( s_pRMan->pTruth, nVars, i );
+
+ // perform verification
+ if ( fUniqueVars && !Kit_TruthIsEqual( s_pRMan->pTruth, s_pRMan->pTruthInit, nVars ) )
+ printf( "Verification failed.\n" );
+ }
+//Aig_RManPrintVarProfile( s_pRMan->pTruth, nVars, s_pRMan->pTruthTemp );
+//Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<<nVars ); printf( "\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/aig/aigDup.c b/src/aig/aig/aigDup.c
index 9fb19b36..ade1edc0 100644
--- a/src/aig/aig/aigDup.c
+++ b/src/aig/aig/aigDup.c
@@ -978,6 +978,7 @@ Aig_Man_t * Aig_ManDupOneOutput( Aig_Man_t * p, int iPoNum, int fAddRegs )
return pNew;
}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/aig/aig/aigMan.c b/src/aig/aig/aigMan.c
index da138395..a13550df 100644
--- a/src/aig/aig/aigMan.c
+++ b/src/aig/aig/aigMan.c
@@ -199,17 +199,19 @@ void Aig_ManStop( Aig_Man_t * p )
assert( !pObj->fMarkA && !pObj->fMarkB );
// Aig_TableProfile( p );
Aig_MmFixedStop( p->pMemObjs, 0 );
- if ( p->vPis ) Vec_PtrFree( p->vPis );
- if ( p->vPos ) Vec_PtrFree( p->vPos );
- if ( p->vObjs ) Vec_PtrFree( p->vObjs );
- if ( p->vBufs ) Vec_PtrFree( p->vBufs );
- if ( p->vLevelR ) Vec_IntFree( p->vLevelR );
- if ( p->vLevels ) Vec_VecFree( p->vLevels );
- if ( p->vFlopNums) Vec_IntFree( p->vFlopNums );
- if ( p->vFlopReprs)Vec_IntFree( p->vFlopReprs );
- if ( p->pManExdc ) Aig_ManStop( p->pManExdc );
- if ( p->vOnehots ) Vec_VecFree( (Vec_Vec_t *)p->vOnehots );
- if ( p->vClockDoms)Vec_VecFree( p->vClockDoms );
+ if ( p->vPis ) Vec_PtrFree( p->vPis );
+ if ( p->vPos ) Vec_PtrFree( p->vPos );
+ if ( p->vObjs ) Vec_PtrFree( p->vObjs );
+ if ( p->vBufs ) Vec_PtrFree( p->vBufs );
+ if ( p->vLevelR ) Vec_IntFree( p->vLevelR );
+ if ( p->vLevels ) Vec_VecFree( p->vLevels );
+ if ( p->vFlopNums) Vec_IntFree( p->vFlopNums );
+ if ( p->vFlopReprs) Vec_IntFree( p->vFlopReprs );
+ if ( p->pManExdc ) Aig_ManStop( p->pManExdc );
+ if ( p->vOnehots ) Vec_VecFree( (Vec_Vec_t *)p->vOnehots );
+ if ( p->vClockDoms) Vec_VecFree( p->vClockDoms );
+ if ( p->vProbs ) Vec_IntFree( p->vProbs );
+ FREE( p->pFastSim );
FREE( p->pData );
FREE( p->pSeqModel );
FREE( p->pName );
diff --git a/src/aig/aig/aigMffc.c b/src/aig/aig/aigMffc.c
index 47ce896d..10887712 100644
--- a/src/aig/aig/aigMffc.c
+++ b/src/aig/aig/aigMffc.c
@@ -39,17 +39,22 @@
SeeAlso []
***********************************************************************/
-int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin )
+int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin, float * pPower, float * pProbs )
{
+ float Power0 = 0.0, Power1 = 0.0;
Aig_Obj_t * pFanin;
int Counter = 0;
+ if ( pProbs )
+ *pPower = 0.0;
if ( Aig_ObjIsPi(pNode) )
return 0;
// consider the first fanin
pFanin = Aig_ObjFanin0(pNode);
assert( pFanin->nRefs > 0 );
if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) )
- Counter += Aig_NodeDeref_rec( pFanin, LevelMin );
+ Counter += Aig_NodeDeref_rec( pFanin, LevelMin, &Power0, pProbs );
+ if ( pProbs )
+ *pPower += Power0 + 2.0 * pProbs[pFanin->Id] * (1.0 - pProbs[pFanin->Id]);
// skip the buffer
if ( Aig_ObjIsBuf(pNode) )
return Counter;
@@ -58,7 +63,9 @@ int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin )
pFanin = Aig_ObjFanin1(pNode);
assert( pFanin->nRefs > 0 );
if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) )
- Counter += Aig_NodeDeref_rec( pFanin, LevelMin );
+ Counter += Aig_NodeDeref_rec( pFanin, LevelMin, &Power1, pProbs );
+ if ( pProbs )
+ *pPower += Power1 + 2.0 * pProbs[pFanin->Id] * (1.0 - pProbs[pFanin->Id]);
return Counter + 1;
}
@@ -173,7 +180,7 @@ int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t
assert( Aig_ObjIsNode(pNode) );
if ( vSupp ) Vec_PtrClear( vSupp );
Aig_ManIncrementTravId( p );
- ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin );
+ ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin, NULL, NULL );
Aig_NodeMffsSupp_rec( p, pNode, LevelMin, vSupp, 1, NULL );
ConeSize2 = Aig_NodeRef_rec( pNode, LevelMin );
assert( ConeSize1 == ConeSize2 );
@@ -192,13 +199,14 @@ int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t
SeeAlso []
***********************************************************************/
-int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode )
+int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode, float * pPower )
{
int ConeSize1, ConeSize2;
+ assert( (pPower != NULL) == (p->vProbs != NULL) );
assert( !Aig_IsComplement(pNode) );
assert( Aig_ObjIsNode(pNode) );
Aig_ManIncrementTravId( p );
- ConeSize1 = Aig_NodeDeref_rec( pNode, 0 );
+ ConeSize1 = Aig_NodeDeref_rec( pNode, 0, pPower, p->vProbs? (float *)p->vProbs->pArray : NULL );
ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 );
assert( ConeSize1 == ConeSize2 );
assert( ConeSize1 > 0 );
@@ -225,7 +233,7 @@ int Aig_NodeMffsLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves
Aig_ManIncrementTravId( p );
Vec_PtrForEachEntry( vLeaves, pObj, i )
pObj->nRefs++;
- ConeSize1 = Aig_NodeDeref_rec( pNode, 0 );
+ ConeSize1 = Aig_NodeDeref_rec( pNode, 0, NULL, NULL );
ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 );
Vec_PtrForEachEntry( vLeaves, pObj, i )
pObj->nRefs--;
@@ -256,7 +264,7 @@ int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves
if ( LevelMax == 0 )
return 0;
// dereference the cut
- ConeSize1 = Aig_NodeDeref_rec( pNode, 0 );
+ ConeSize1 = Aig_NodeDeref_rec( pNode, 0, NULL, NULL );
// try expanding each node in the boundary
ConeBest = AIG_INFINITY;
pLeafBest = NULL;
@@ -264,7 +272,7 @@ int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves
{
if ( (int)pObj->Level != LevelMax )
continue;
- ConeCur1 = Aig_NodeDeref_rec( pObj, 0 );
+ ConeCur1 = Aig_NodeDeref_rec( pObj, 0, NULL, NULL );
if ( ConeBest > ConeCur1 )
{
ConeBest = ConeCur1;
@@ -276,7 +284,7 @@ int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves
assert( pLeafBest != NULL );
assert( Aig_ObjIsNode(pLeafBest) );
// deref the best leaf
- ConeCur1 = Aig_NodeDeref_rec( pLeafBest, 0 );
+ ConeCur1 = Aig_NodeDeref_rec( pLeafBest, 0, NULL, NULL );
// collect the cut nodes
Vec_PtrClear( vResult );
Aig_ManIncrementTravId( p );
diff --git a/src/aig/aig/aigObj.c b/src/aig/aig/aigObj.c
index 3ceed094..2c373ee1 100644
--- a/src/aig/aig/aigObj.c
+++ b/src/aig/aig/aigObj.c
@@ -116,6 +116,15 @@ Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost )
assert( !Aig_IsComplement(pObj->pHaig) );
// printf( "Creating HAIG node %d equivalent to node %d.\n", pObj->pHaig->Id, pObj->Id );
}
+ // create the power counter
+ if ( p->vProbs )
+ {
+ float Prob0 = Aig_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId0(pObj) ) );
+ float Prob1 = Aig_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId1(pObj) ) );
+ Prob0 = Aig_ObjFaninC0(pObj)? 1.0 - Prob0 : Prob0;
+ Prob1 = Aig_ObjFaninC1(pObj)? 1.0 - Prob1 : Prob1;
+ Vec_IntSetEntry( p->vProbs, pObj->Id, Aig_Float2Int(Prob0 * Prob1) );
+ }
return pObj;
}
diff --git a/src/aig/aig/aigScl.c b/src/aig/aig/aigScl.c
index 153ac421..57b7b989 100644
--- a/src/aig/aig/aigScl.c
+++ b/src/aig/aig/aigScl.c
@@ -232,6 +232,7 @@ int Aig_ManSeqCleanup( Aig_Man_t * p )
Vec_PtrFree( vNodes );
p->nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p);
p->nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p);
+ Aig_ManSetPioNumbers( p );
// remove dangling nodes
return Aig_ManCleanup( p );
}
@@ -579,6 +580,58 @@ void Aig_ManComputeSccs( Aig_Man_t * p )
/**Function*************************************************************
+ Synopsis [Performs partitioned register sweep.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManSclPart( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int fVerbose )
+{
+ Vec_Ptr_t * vResult;
+ Vec_Int_t * vPart;
+ int i, nCountPis, nCountRegs;
+ int * pMapBack;
+ Aig_Man_t * pTemp, * pNew;
+ int nClasses;
+
+ if ( pAig->vClockDoms )
+ {
+ vResult = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( (Vec_Ptr_t *)pAig->vClockDoms, vPart, i )
+ Vec_PtrPush( vResult, Vec_IntDup(vPart) );
+ }
+ else
+ vResult = Aig_ManRegPartitionSimple( pAig, 0, 0 );
+
+ Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+ Vec_PtrForEachEntry( vResult, vPart, i )
+ {
+ pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack );
+ Aig_ManSetRegNum( pTemp, pTemp->nRegs );
+ if (nCountPis>0)
+ {
+ pNew = Aig_ManScl( pTemp, fLatchConst, fLatchEqual, fVerbose );
+ nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack );
+ if ( fVerbose )
+ printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d\n",
+ i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), 0, nClasses );
+ Aig_ManStop( pNew );
+ }
+ Aig_ManStop( pTemp );
+ free( pMapBack );
+ }
+ pNew = Aig_ManDupRepr( pAig, 0 );
+ Aig_ManSeqCleanup( pNew );
+ Vec_VecFree( (Vec_Vec_t*)vResult );
+ return pNew;
+}
+
+/**Function*************************************************************
+
Synopsis [Gives the current ABC network to AIG manager for processing.]
Description []
@@ -596,6 +649,10 @@ Aig_Man_t * Aig_ManScl( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int
Aig_Man_t * pAigInit, * pAigNew;
Aig_Obj_t * pFlop1, * pFlop2;
int i, Entry1, Entry2, nTruePis;//, nRegs;
+
+ if ( pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0 )
+ return Aig_ManSclPart( pAig, fLatchConst, fLatchEqual, fVerbose);
+
// store the original AIG
assert( pAig->vFlopNums == NULL );
pAigInit = pAig;
diff --git a/src/aig/aig/aigTsim.c b/src/aig/aig/aigTsim.c
index 7b48a73d..c411100b 100644
--- a/src/aig/aig/aigTsim.c
+++ b/src/aig/aig/aigTsim.c
@@ -44,10 +44,10 @@ static inline int Aig_XsimInv( int Value )
}
static inline int Aig_XsimAnd( int Value0, int Value1 )
{
- if ( Value0 == AIG_XVS0 || Value1 == AIG_XVS0 )
- return AIG_XVS0;
if ( Value0 == AIG_XVSX || Value1 == AIG_XVSX )
return AIG_XVSX;
+ if ( Value0 == AIG_XVS0 || Value1 == AIG_XVS0 )
+ return AIG_XVS0;
assert( Value0 == AIG_XVS1 && Value1 == AIG_XVS1 );
return AIG_XVS1;
}
@@ -371,7 +371,7 @@ Vec_Ptr_t * Aig_ManTernarySimulate( Aig_Man_t * p, int fVerbose )
}
// printf( "%d ", Aig_TsiStateCount(pTsi, pState) );
-// Aig_TsiStatePrint( pTsi, pState );
+//Aig_TsiStatePrint( pTsi, pState );
// check if this state exists
if ( Aig_TsiStateLookup( pTsi, pState, pTsi->nWords ) )
break;
diff --git a/src/aig/aig/module.make b/src/aig/aig/module.make
index b1b8c5c2..5fea4341 100644
--- a/src/aig/aig/module.make
+++ b/src/aig/aig/module.make
@@ -1,4 +1,5 @@
SRC += src/aig/aig/aigCheck.c \
+ src/aig/aig/aigCanon.c \
src/aig/aig/aigCuts.c \
src/aig/aig/aigDfs.c \
src/aig/aig/aigDup.c \
diff --git a/src/aig/bbr/bbrImage.c b/src/aig/bbr/bbrImage.c
index f362162c..afc8dc39 100644
--- a/src/aig/bbr/bbrImage.c
+++ b/src/aig/bbr/bbrImage.c
@@ -19,7 +19,7 @@
***********************************************************************/
#include "bbr.h"
-#include "mtr.h"
+#include "mtr.h"
/*
The ideas implemented in this file are inspired by the paper:
@@ -721,7 +721,7 @@ int Bbr_BuildTreeNode( DdManager * dd,
Bbr_ImageNode_t * pNode1, * pNode2;
Bbr_ImageVar_t * pVar;
Bbr_ImageNode_t * pNode;
- DdNode * bCube, * bTemp, * bSuppTemp, * bParts;
+ DdNode * bCube, * bTemp, * bSuppTemp;//, * bParts;
int iNode1, iNode2;
int iVarBest, nSupp, v;
@@ -773,7 +773,7 @@ int Bbr_BuildTreeNode( DdManager * dd,
Bbr_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 );
pNode1 = pNodes[iNode1];
pNode2 = pNodes[iNode2];
-
+/*
// it is not possible that a var appears only in these two
// otherwise, it would have a different cost
bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts );
@@ -781,7 +781,7 @@ int Bbr_BuildTreeNode( DdManager * dd,
if ( pVars[v] && pVars[v]->bParts == bParts )
assert( 0 );
Cudd_RecursiveDeref( dd, bParts );
-
+*/
// combines two nodes
pNode = Bbr_CombineTwoNodes( dd, b1, pNode1, pNode2 );
}
diff --git a/src/aig/bdc/bdcCore.c b/src/aig/bdc/bdcCore.c
index e812da3d..9067d315 100644
--- a/src/aig/bdc/bdcCore.c
+++ b/src/aig/bdc/bdcCore.c
@@ -72,7 +72,8 @@ Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars )
p->nNodesAlloc = 512;
p->pNodes = ALLOC( Bdc_Fun_t, p->nNodesAlloc );
// memory
- p->vMemory = Vec_IntStart( 4 * p->nWords * p->nNodesAlloc );
+ p->vMemory = Vec_IntStart( 8 * p->nWords * p->nNodesAlloc );
+ Vec_IntClear(p->vMemory);
// set up hash table
p->nTableSize = (1 << p->pPars->nVarsMax);
p->pTable = ALLOC( Bdc_Fun_t *, p->nTableSize );
diff --git a/src/aig/bdc/bdcInt.h b/src/aig/bdc/bdcInt.h
index ab800269..a35663ef 100644
--- a/src/aig/bdc/bdcInt.h
+++ b/src/aig/bdc/bdcInt.h
@@ -124,7 +124,7 @@ struct Bdc_Man_t_
static inline Bdc_Fun_t * Bdc_FunNew( Bdc_Man_t * p ) { Bdc_Fun_t * pRes; if ( p->nNodes >= p->nNodesAlloc || p->nNodesNew >= p->nNodesMax ) return NULL; pRes = p->pNodes + p->nNodes++; p->nNodesNew++; memset( pRes, 0, sizeof(Bdc_Fun_t) ); return pRes; }
static inline Bdc_Fun_t * Bdc_FunWithId( Bdc_Man_t * p, int Id ) { assert( Id < p->nNodes ); return p->pNodes + Id; }
static inline int Bdc_FunId( Bdc_Man_t * p, Bdc_Fun_t * pFun ) { return pFun - p->pNodes; }
-static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->uSupp = 0; pF->uUniq = 0; pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); }
+static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->uSupp = 0; pF->uUniq = 0; pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); assert( pF->puOff && pF->puOn ); }
static inline void Bdc_IsfClean( Bdc_Isf_t * p ) { p->uSupp = 0; p->uUniq = 0; }
static inline void Bdc_IsfCopy( Bdc_Isf_t * p, Bdc_Isf_t * q ) { Bdc_Isf_t T = *p; *p = *q; *q = T; }
static inline void Bdc_IsfNot( Bdc_Isf_t * p ) { unsigned * puT = p->puOn; p->puOn = p->puOff; p->puOff = puT; }
diff --git a/src/aig/cec/cec.h b/src/aig/cec/cec.h
new file mode 100644
index 00000000..fb0bb830
--- /dev/null
+++ b/src/aig/cec/cec.h
@@ -0,0 +1,100 @@
+/**CFile****************************************************************
+
+ FileName [cec.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinatinoal equivalence checking.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __CEC_H__
+#define __CEC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+// dynamic SAT parameters
+typedef struct Cec_ParSat_t_ Cec_ParSat_t;
+struct Cec_ParSat_t_
+{
+ int nBTLimit; // conflict limit at a node
+ int nSatVarMax; // the max number of SAT variables
+ int nCallsRecycle; // calls to perform before recycling SAT solver
+ int fFirstStop; // stop on the first sat output
+ int fPolarFlip; // uses polarity adjustment
+ int fVerbose; // verbose stats
+};
+
+// combinational SAT sweeping parameters
+typedef struct Cec_ParCsw_t_ Cec_ParCsw_t;
+struct Cec_ParCsw_t_
+{
+ int nWords; // the number of simulation words
+ int nRounds; // the number of simulation rounds
+ int nBTlimit; // conflict limit at a node
+ int fRewriting; // enables AIG rewriting
+ int fVerbose; // verbose stats
+};
+
+// combinational equivalence checking parameters
+typedef struct Cec_ParCec_t_ Cec_ParCec_t;
+struct Cec_ParCec_t_
+{
+ int nIters; // iterations of SAT solving/sweeping
+ int nBTLimitBeg; // starting backtrack limit
+ int nBTlimitMulti; // multiple of backtrack limit
+ int fUseSmartCnf; // use smart CNF computation
+ int fRewriting; // enables AIG rewriting
+ int fSatSweeping; // enables SAT sweeping
+ int fFirstStop; // stop on the first sat output
+ int fVerbose; // verbose stats
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cecCore.c ==========================================================*/
+extern void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p );
+extern void Cec_ManCswSetDefaultParams( Cec_ParCsw_t * p );
+extern void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p );
+extern int Cec_Solve( Aig_Man_t * pAig0, Aig_Man_t * pAig1, Cec_ParCec_t * p );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/cec/cecAig.c b/src/aig/cec/cecAig.c
new file mode 100644
index 00000000..2a6f5683
--- /dev/null
+++ b/src/aig/cec/cecAig.c
@@ -0,0 +1,151 @@
+/**CFile****************************************************************
+
+ FileName [cecAig.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinatinoal equivalence checking.]
+
+ Synopsis [AIG manipulation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Derives combinational miter of the two AIGs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Cec_DeriveMiter_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj )
+{
+ if ( pObj->pData )
+ return pObj->pData;
+ Cec_DeriveMiter_rec( pNew, Aig_ObjFanin0(pObj) );
+ if ( Aig_ObjIsBuf(pObj) )
+ return pObj->pData = Aig_ObjChild0Copy(pObj);
+ Cec_DeriveMiter_rec( pNew, Aig_ObjFanin1(pObj) );
+ pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ Aig_Regular(pObj->pData)->pHaig = pObj->pHaig;
+ return pObj->pData;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives combinational miter of the two AIGs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Cec_DeriveMiter( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Bar_Progress_t * pProgress = NULL;
+ Aig_Man_t * pNew;
+ Aig_Obj_t * pObj0, * pObj1, * pObjNew;
+ int i;
+ assert( Aig_ManPiNum(p0) == Aig_ManPiNum(p1) );
+ assert( Aig_ManPoNum(p0) == Aig_ManPoNum(p1) );
+ // create the new manager
+ pNew = Aig_ManStart( Aig_ManNodeNum(p0) + Aig_ManNodeNum(p1) );
+ pNew->pName = Aig_UtilStrsav( p0->pName );
+ // create the PIs
+ Aig_ManCleanData( p0 );
+ Aig_ManCleanData( p1 );
+ Aig_ManConst1(p0)->pData = Aig_ManConst1(pNew);
+ Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew);
+ Aig_ManForEachPi( p0, pObj0, i )
+ {
+ pObjNew = Aig_ObjCreatePi( pNew );
+ pObj0->pData = pObjNew;
+ Aig_ManPi(p1, i)->pData = pObjNew;
+ }
+ // add logic for the POs
+ pProgress = Bar_ProgressStart( stdout, Aig_ManPoNum(p0) );
+ Aig_ManForEachPo( p0, pObj0, i )
+ {
+ Bar_ProgressUpdate( pProgress, i, "Miter..." );
+ pObj1 = Aig_ManPo( p1, i );
+ Cec_DeriveMiter_rec( pNew, Aig_ObjFanin0(pObj0) );
+ Cec_DeriveMiter_rec( pNew, Aig_ObjFanin0(pObj1) );
+ pObjNew = Aig_Exor( pNew, Aig_ObjChild0Copy(pObj0), Aig_ObjChild0Copy(pObj1) );
+ Aig_ObjCreatePo( pNew, pObjNew );
+ }
+ Bar_ProgressStop( pProgress );
+ Aig_ManCleanup( pNew );
+ Aig_ManSetRegNum( pNew, 0 );
+ // check the resulting network
+// if ( !Aig_ManCheck(pNew) )
+// printf( "Cec_DeriveMiter(): The check has failed.\n" );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates AIG in the DFS order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Cec_Duplicate( Aig_Man_t * p )
+{
+ Aig_Man_t * pNew;
+ Aig_Obj_t * pObj;
+ int i;
+ // create the new manager
+ pNew = Aig_ManStart( Aig_ManNodeNum(p) );
+ pNew->pName = Aig_UtilStrsav( p->pName );
+ // create the PIs
+ Aig_ManCleanData( p );
+ Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+ Aig_ManForEachPi( p, pObj, i )
+ pObj->pData = Aig_ObjCreatePi( pNew );
+ // add logic for the POs
+ Aig_ManForEachPo( p, pObj, i )
+ {
+ Cec_DeriveMiter_rec( pNew, Aig_ObjFanin0(pObj) );
+ Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
+ }
+ Aig_ManCleanup( pNew );
+ Aig_ManSetRegNum( pNew, 0 );
+ assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) );
+ // check the resulting network
+// if ( !Aig_ManCheck(pNew) )
+// printf( "Cec_DeriveMiter(): The check has failed.\n" );
+ return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/cec/cecClass.c b/src/aig/cec/cecClass.c
new file mode 100644
index 00000000..f3f6bf11
--- /dev/null
+++ b/src/aig/cec/cecClass.c
@@ -0,0 +1,569 @@
+/**CFile****************************************************************
+
+ FileName [cecClass.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinatinoal equivalence checking.]
+
+ Synopsis [Equivalence class representation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecClass.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Caig_ManSpecReduce( Caig_Man_t * p )
+{
+ Aig_Man_t * pAig;
+ Aig_Obj_t ** pCopy;
+ Aig_Obj_t * pMiter, * pRes0, * pRes1, * pRepr;
+ int i;
+ pCopy = ALLOC( Aig_Obj_t *, p->nObjs );
+ pCopy[0] = NULL;
+ pAig = Aig_ManStart( p->nNodes );
+ for ( i = 1; i < p->nObjs; i++ )
+ {
+ if ( p->pFans0[i] == 0 ) // pi always has zero first fanin
+ {
+ pCopy[i] = Aig_ObjCreatePi( pAig );
+ continue;
+ }
+ if ( p->pFans1[i] == 0 ) // po always has non-zero 1st fanin and zero 2nd fanin
+ continue;
+ pRes0 = pCopy[ Cec_Lit2Var(p->pFans0[i]) ];
+ pRes0 = Aig_NotCond( pRes0, Cec_LitIsCompl(p->pFans0[i]) );
+ pRes1 = pCopy[ Cec_Lit2Var(p->pFans1[i]) ];
+ pRes1 = Aig_NotCond( pRes1, Cec_LitIsCompl(p->pFans1[i]) );
+ pCopy[i] = Aig_And( pAig, pRes0, pRes1 );
+ if ( p->pReprs[i] < 0 )
+ continue;
+ assert( p->pReprs[i] < i );
+ pRepr = p->pReprs[i]? pCopy[ p->pReprs[i] ] : Aig_ManConst1(pAig);
+ if ( Aig_Regular(pCopy[i]) == Aig_Regular(pRepr) )
+ continue;
+ pMiter = Aig_Exor( pAig, pCopy[i], pRepr );
+ Aig_ObjCreatePo( pAig, Aig_NotCond(pMiter, Aig_ObjPhaseReal(pMiter)) );
+ }
+ free( pCopy );
+ Aig_ManSetRegNum( pAig, 0 );
+ Aig_ManCleanup( pAig );
+ return pAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Caig_ManCountOne( Caig_Man_t * p, int i )
+{
+ int Ent, nLits = 0;
+ assert( p->pReprs[i] < 0 && p->pNexts[i] > 0 );
+ for ( Ent = p->pNexts[i]; Ent; Ent = p->pNexts[Ent] )
+ {
+ assert( p->pReprs[Ent] == i );
+ nLits++;
+ }
+ return 1 + nLits;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Caig_ManCountLiterals( Caig_Man_t * p )
+{
+ int i, nLits = 0;
+ for ( i = 1; i < p->nObjs; i++ )
+ if ( p->pReprs[i] < 0 && p->pNexts[i] > 0 )
+ nLits += Caig_ManCountOne(p, i) - 1;
+ return nLits;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Caig_ManPrintOne( Caig_Man_t * p, int i, int Counter )
+{
+ int Ent;
+ printf( "Class %4d : Num = %2d {", Counter, Caig_ManCountOne(p, i) );
+ for ( Ent = i; Ent; Ent = p->pNexts[Ent] )
+ printf(" %d", Ent );
+ printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Caig_ManPrintClasses( Caig_Man_t * p, int fVerbose )
+{
+ int i, Counter = 0, Counter1 = 0, CounterX = 0, nLits;
+ for ( i = 1; i < p->nObjs; i++ )
+ {
+ if ( p->pReprs[i] < 0 && p->pNexts[i] > 0 )
+ Counter++;
+ if ( p->pReprs[i] == 0 )
+ Counter1++;
+ if ( p->pReprs[i] < 0 && p->pNexts[i] == 0 )
+ CounterX++;
+ }
+ nLits = Caig_ManCountLiterals( p );
+ printf( "Class = %6d. Const1 = %6d. Other = %6d. Lits = %7d. Total = %7d.\n",
+ Counter, Counter1, CounterX, nLits, nLits+Counter1 );
+ if ( fVerbose )
+ for ( i = 1; i < p->nObjs; i++ )
+ if ( p->pReprs[i] < 0 && p->pNexts[i] > 0 )
+ Caig_ManPrintOne( p, i, ++Counter );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Caig_ManCollectSimsSimple( Caig_Man_t * p, int i )
+{
+ int Ent;
+ Vec_PtrClear( p->vSims );
+ for ( Ent = i; Ent; Ent = p->pNexts[Ent] )
+ Vec_PtrPush( p->vSims, p->pSims + Ent );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Caig_ManCollectSimsNormal( Caig_Man_t * p, int i )
+{
+ unsigned * pSim;
+ int Ent;
+ Vec_PtrClear( p->vSims );
+ for ( Ent = i; Ent; Ent = p->pNexts[Ent] )
+ {
+ pSim = Caig_ManSimDeref( p, Ent );
+ Vec_PtrPush( p->vSims, pSim + 1 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Caig_ManCompareEqual( unsigned * p0, unsigned * p1, int nWords )
+{
+ int w;
+ if ( (p0[0] & 1) == (p1[0] & 1) )
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p0[w] != p1[w] )
+ return 0;
+ return 1;
+ }
+ else
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p0[w] != ~p1[w] )
+ return 0;
+ return 1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Caig_ManCompareConst( unsigned * p, int nWords )
+{
+ int w;
+ if ( p[0] & 1 )
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p[w] != ~0 )
+ return 0;
+ return 1;
+ }
+ else
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p[w] != 0 )
+ return 0;
+ return 1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Caig_ManClassCreate( Caig_Man_t * p, Vec_Int_t * vClass )
+{
+ int * pNext, Repr, Ent, i;
+ assert( Vec_IntSize(vClass) > 0 );
+ Vec_IntForEachEntry( vClass, Ent, i )
+ {
+ if ( i == 0 )
+ {
+ Repr = Ent;
+ p->pReprs[Ent] = -1;
+ pNext = p->pNexts + Ent;
+ }
+ else
+ {
+ p->pReprs[Ent] = Repr;
+ *pNext = Ent;
+ pNext = p->pNexts + Ent;
+ }
+ }
+ *pNext = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Caig_ManClassRefineOne( Caig_Man_t * p, int i, Vec_Ptr_t * vSims )
+{
+ unsigned * pSim0, * pSim1;
+ int Ent, c = 0, d = 0;
+ Vec_IntClear( p->vClassOld );
+ Vec_IntClear( p->vClassNew );
+ pSim0 = Vec_PtrEntry( vSims, c++ );
+ Vec_IntPush( p->vClassOld, i );
+ for ( Ent = p->pNexts[i]; Ent; Ent = p->pNexts[Ent] )
+ {
+ pSim1 = Vec_PtrEntry( vSims, c++ );
+ if ( Caig_ManCompareEqual( pSim0, pSim1, p->nWords ) )
+ Vec_IntPush( p->vClassOld, Ent );
+ else
+ {
+ Vec_IntPush( p->vClassNew, Ent );
+ Vec_PtrWriteEntry( vSims, d++, pSim1 );
+ }
+ }
+ Vec_PtrShrink( vSims, d );
+ if ( Vec_IntSize(p->vClassNew) == 0 )
+ return 0;
+ Caig_ManClassCreate( p, p->vClassOld );
+ Caig_ManClassCreate( p, p->vClassNew );
+ if ( Vec_IntSize(p->vClassNew) > 1 )
+ return 1 + Caig_ManClassRefineOne( p, Vec_IntEntry(p->vClassNew,0), vSims );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Caig_ManHashKey( unsigned * pSim, int nWords, int nTableSize )
+{
+ static int s_Primes[16] = {
+ 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177,
+ 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 };
+ unsigned uHash = 0;
+ int i;
+ if ( pSim[0] & 1 )
+ for ( i = 0; i < nWords; i++ )
+ uHash ^= ~pSim[i] * s_Primes[i & 0xf];
+ else
+ for ( i = 0; i < nWords; i++ )
+ uHash ^= pSim[i] * s_Primes[i & 0xf];
+ return (int)(uHash % nTableSize);
+
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Caig_ManClassesCreate( Caig_Man_t * p )
+{
+ int * pTable, nTableSize, i, Key;
+ nTableSize = Aig_PrimeCudd( 100 + p->nObjs / 10 );
+ pTable = CALLOC( int, nTableSize );
+ p->pReprs = ALLOC( int, p->nObjs );
+ p->pNexts = CALLOC( int, p->nObjs );
+ for ( i = 1; i < p->nObjs; i++ )
+ {
+ if ( Caig_ManCompareConst( p->pSims + i, 1 ) )
+ {
+ p->pReprs[i] = 0;
+ continue;
+ }
+ Key = Caig_ManHashKey( p->pSims + i, 1, nTableSize );
+ if ( pTable[Key] == 0 )
+ p->pReprs[i] = -1;
+ else
+ {
+ p->pNexts[ pTable[Key] ] = i;
+ p->pReprs[i] = p->pReprs[ pTable[Key] ];
+ if ( p->pReprs[i] == -1 )
+ p->pReprs[i] = pTable[Key];
+ }
+ pTable[Key] = i;
+ }
+ FREE( pTable );
+Caig_ManPrintClasses( p, 0 );
+ // refine classes
+ p->vSims = Vec_PtrAlloc( 100 );
+ p->vClassOld = Vec_IntAlloc( 100 );
+ p->vClassNew = Vec_IntAlloc( 100 );
+ for ( i = 1; i < p->nObjs; i++ )
+ if ( p->pReprs[i] < 0 && p->pNexts[i] > 0 )
+ {
+ Caig_ManCollectSimsSimple( p, i );
+ Caig_ManClassRefineOne( p, i, p->vSims );
+ }
+ // clean memory
+ memset( p->pSims, 0, sizeof(unsigned) * p->nObjs );
+Caig_ManPrintClasses( p, 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Caig_ManSimulateSimple( Caig_Man_t * p )
+{
+ unsigned Res0, Res1;
+ int i;
+ for ( i = 1; i < p->nObjs; i++ )
+ {
+ if ( p->pFans0[i] == 0 ) // pi
+ {
+ p->pSims[i] = Aig_ManRandom( 0 );
+ continue;
+ }
+ Res0 = p->pSims[Cec_Lit2Var(p->pFans0[i])];
+ Res1 = p->pSims[Cec_Lit2Var(p->pFans1[i])];
+ p->pSims[i] = (Cec_LitIsCompl(p->pFans0[i]) ? ~Res0: Res0) &
+ (Cec_LitIsCompl(p->pFans1[i]) ? ~Res1: Res1);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Caig_ManProcessClass( Caig_Man_t * p, int i )
+{
+ Caig_ManCollectSimsNormal( p, i );
+ Caig_ManClassRefineOne( p, i, p->vSims );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Caig_ManProcessRefined( Caig_Man_t * p, Vec_Int_t * vRefined )
+{
+ Vec_Int_t * vClasses;
+ int * pTable, nTableSize, i, Key, iNode;
+ unsigned * pSim;
+ if ( Vec_IntSize(vRefined) == 0 )
+ return;
+ nTableSize = Aig_PrimeCudd( 100 + Vec_IntSize(vRefined) / 5 );
+ pTable = CALLOC( int, nTableSize );
+ vClasses = Vec_IntAlloc( 100 );
+ Vec_IntForEachEntry( vRefined, iNode, i )
+ {
+ pSim = Caig_ManSimRead( p, iNode );
+ assert( !Caig_ManCompareConst( pSim + 1, p->nWords ) );
+ Key = Caig_ManHashKey( pSim + 1, p->nWords, nTableSize );
+ if ( pTable[Key] == 0 )
+ {
+ assert( p->pReprs[iNode] == 0 );
+ assert( p->pNexts[iNode] == 0 );
+ p->pReprs[iNode] = -1;
+ Vec_IntPush( vClasses, iNode );
+ }
+ else
+ {
+ p->pNexts[ pTable[Key] ] = iNode;
+ p->pReprs[iNode] = p->pReprs[ pTable[Key] ];
+ if ( p->pReprs[iNode] == -1 )
+ p->pReprs[iNode] = pTable[Key];
+ assert( p->pReprs[iNode] > 0 );
+ }
+ pTable[Key] = iNode;
+ }
+ FREE( pTable );
+ // refine classes
+ Vec_IntForEachEntry( vClasses, iNode, i )
+ {
+ if ( p->pNexts[iNode] == 0 )
+ {
+ Caig_ManSimDeref( p, iNode );
+ continue;
+ }
+ Caig_ManCollectSimsNormal( p, iNode );
+ Caig_ManClassRefineOne( p, iNode, p->vSims );
+ }
+ Vec_IntFree( vClasses );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Caig_Man_t * Caig_ManClassesPrepare( Aig_Man_t * pAig, int nWords, int nIters )
+{
+ Caig_Man_t * p;
+ int i;
+ Aig_ManRandom( 1 );
+ p = Caig_ManCreate( pAig );
+ p->nWords = 1;
+ Caig_ManSimulateSimple( p );
+ Caig_ManClassesCreate( p );
+ p->nWords = nWords;
+ for ( i = 0; i < nIters; i++ )
+ {
+ Caig_ManSimulateRound( p, 0 );
+Caig_ManPrintClasses( p, 0 );
+ }
+ return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/cec/cecCnf.c b/src/aig/cec/cecCnf.c
new file mode 100644
index 00000000..8b8c011d
--- /dev/null
+++ b/src/aig/cec/cecCnf.c
@@ -0,0 +1,328 @@
+/**CFile****************************************************************
+
+ FileName [cecCnf.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinatinoal equivalence checking.]
+
+ Synopsis [CNF computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecCnf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Addes clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_AddClausesMux( Cec_ManSat_t * p, Aig_Obj_t * pNode )
+{
+ Aig_Obj_t * pNodeI, * pNodeT, * pNodeE;
+ int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+ assert( !Aig_IsComplement( pNode ) );
+ assert( Aig_ObjIsMuxType( pNode ) );
+ // get nodes (I = if, T = then, E = else)
+ pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+ // get the variable numbers
+ VarF = Cec_ObjSatNum(p,pNode);
+ VarI = Cec_ObjSatNum(p,pNodeI);
+ VarT = Cec_ObjSatNum(p,Aig_Regular(pNodeT));
+ VarE = Cec_ObjSatNum(p,Aig_Regular(pNodeE));
+ // get the complementation flags
+ fCompT = Aig_IsComplement(pNodeT);
+ fCompE = Aig_IsComplement(pNodeE);
+
+ // f = ITE(i, t, e)
+
+ // i' + t' + f
+ // i' + t + f'
+ // i + e' + f
+ // i + e + f'
+
+ // create four clauses
+ pLits[0] = toLitCond(VarI, 1);
+ pLits[1] = toLitCond(VarT, 1^fCompT);
+ pLits[2] = toLitCond(VarF, 0);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 1);
+ pLits[1] = toLitCond(VarT, 0^fCompT);
+ pLits[2] = toLitCond(VarF, 1);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 0);
+ pLits[1] = toLitCond(VarE, 1^fCompE);
+ pLits[2] = toLitCond(VarF, 0);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 0);
+ pLits[1] = toLitCond(VarE, 0^fCompE);
+ pLits[2] = toLitCond(VarF, 1);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+
+ // two additional clauses
+ // t' & e' -> f'
+ // t & e -> f
+
+ // t + e + f'
+ // t' + e' + f
+
+ if ( VarT == VarE )
+ {
+// assert( fCompT == !fCompE );
+ return;
+ }
+
+ pLits[0] = toLitCond(VarT, 0^fCompT);
+ pLits[1] = toLitCond(VarE, 0^fCompE);
+ pLits[2] = toLitCond(VarF, 1);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarT, 1^fCompT);
+ pLits[1] = toLitCond(VarE, 1^fCompE);
+ pLits[2] = toLitCond(VarF, 0);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Addes clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_AddClausesSuper( Cec_ManSat_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper )
+{
+ Aig_Obj_t * pFanin;
+ int * pLits, nLits, RetValue, i;
+ assert( !Aig_IsComplement(pNode) );
+ assert( Aig_ObjIsNode( pNode ) );
+ // create storage for literals
+ nLits = Vec_PtrSize(vSuper) + 1;
+ pLits = ALLOC( int, nLits );
+ // suppose AND-gate is A & B = C
+ // add !A => !C or A + !C
+ Vec_PtrForEachEntry( vSuper, pFanin, i )
+ {
+ pLits[0] = toLitCond(Cec_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin));
+ pLits[1] = toLitCond(Cec_ObjSatNum(p,pNode), 1);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Aig_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ }
+ // add A & B => C or !A + !B + C
+ Vec_PtrForEachEntry( vSuper, pFanin, i )
+ {
+ pLits[i] = toLitCond(Cec_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin));
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Aig_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] );
+ }
+ }
+ pLits[nLits-1] = toLitCond(Cec_ObjSatNum(p,pNode), 0);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits );
+ assert( RetValue );
+ free( pLits );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes )
+{
+ // if the new node is complemented or a PI, another gate begins
+ if ( Aig_IsComplement(pObj) || Aig_ObjIsPi(pObj) ||
+ (!fFirst && Aig_ObjRefs(pObj) > 1) ||
+ (fUseMuxes && Aig_ObjIsMuxType(pObj)) )
+ {
+ Vec_PtrPushUnique( vSuper, pObj );
+ return;
+ }
+ // go through the branches
+ Cec_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes );
+ Cec_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper )
+{
+ assert( !Aig_IsComplement(pObj) );
+ assert( !Aig_ObjIsPi(pObj) );
+ Vec_PtrClear( vSuper );
+ Cec_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the solver clause database.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ObjAddToFrontier( Cec_ManSat_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier )
+{
+ assert( !Aig_IsComplement(pObj) );
+ if ( Cec_ObjSatNum(p,pObj) )
+ return;
+ assert( Cec_ObjSatNum(p,pObj) == 0 );
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+ Vec_PtrPush( p->vUsedNodes, pObj );
+ Cec_ObjSetSatNum( p, pObj, p->nSatVars++ );
+ if ( Aig_ObjIsNode(pObj) )
+ Vec_PtrPush( vFrontier, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the solver clause database.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_CnfNodeAddToSolver( Cec_ManSat_t * p, Aig_Obj_t * pObj )
+{
+ Vec_Ptr_t * vFrontier;
+ Aig_Obj_t * pNode, * pFanin;
+ int i, k, fUseMuxes = 1;
+ // quit if CNF is ready
+ if ( Cec_ObjSatNum(p,pObj) )
+ return;
+ // start the frontier
+ vFrontier = Vec_PtrAlloc( 100 );
+ Cec_ObjAddToFrontier( p, pObj, vFrontier );
+ // explore nodes in the frontier
+ Vec_PtrForEachEntry( vFrontier, pNode, i )
+ {
+ // create the supergate
+ assert( Cec_ObjSatNum(p,pNode) );
+ if ( fUseMuxes && Aig_ObjIsMuxType(pNode) )
+ {
+ Vec_PtrClear( p->vFanins );
+ Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) );
+ Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) );
+ Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) );
+ Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) );
+ Vec_PtrForEachEntry( p->vFanins, pFanin, k )
+ Cec_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+ Cec_AddClausesMux( p, pNode );
+ }
+ else
+ {
+ Cec_CollectSuper( pNode, fUseMuxes, p->vFanins );
+ Vec_PtrForEachEntry( p->vFanins, pFanin, k )
+ Cec_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+ Cec_AddClausesSuper( p, pNode, p->vFanins );
+ }
+ assert( Vec_PtrSize(p->vFanins) > 1 );
+ }
+ Vec_PtrFree( vFrontier );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/cec/cecCore.c b/src/aig/cec/cecCore.c
new file mode 100644
index 00000000..86287a96
--- /dev/null
+++ b/src/aig/cec/cecCore.c
@@ -0,0 +1,233 @@
+/**CFile****************************************************************
+
+ FileName [cecCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinatinoal equivalence checking.]
+
+ Synopsis [Core procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p )
+{
+ memset( p, 0, sizeof(Cec_ParSat_t) );
+ p->nBTLimit = 100; // conflict limit at a node
+ p->nSatVarMax = 2000; // the max number of SAT variables
+ p->nCallsRecycle = 10; // calls to perform before recycling SAT solver
+ p->fFirstStop = 0; // stop on the first sat output
+ p->fPolarFlip = 0; // uses polarity adjustment
+ p->fVerbose = 0; // verbose stats
+}
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManCswSetDefaultParams( Cec_ParCsw_t * p )
+{
+ memset( p, 0, sizeof(Cec_ParCsw_t) );
+ p->nWords = 15; // the number of simulation words
+ p->nRounds = 10; // the number of simulation rounds
+ p->nBTlimit = 10; // conflict limit at a node
+ p->fRewriting = 0; // enables AIG rewriting
+ p->fVerbose = 1; // verbose stats
+}
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p )
+{
+ memset( p, 0, sizeof(Cec_ParCec_t) );
+ p->nIters = 5; // iterations of SAT solving/sweeping
+ p->nBTLimitBeg = 2; // starting backtrack limit
+ p->nBTlimitMulti = 8; // multiple of backtrack limiter
+ p->fUseSmartCnf = 0; // use smart CNF computation
+ p->fRewriting = 0; // enables AIG rewriting
+ p->fSatSweeping = 0; // enables SAT sweeping
+ p->fFirstStop = 0; // stop on the first sat output
+ p->fVerbose = 1; // verbose stats
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs equivalence checking.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_Sweep( Aig_Man_t * pAig, int nBTLimit )
+{
+ Cec_MtrStatus_t Status;
+ Cec_ParCsw_t ParsCsw, * pParsCsw = &ParsCsw;
+ Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
+ Caig_Man_t * pCaig;
+ Aig_Man_t * pSRAig;
+ int clk;
+
+ Cec_ManCswSetDefaultParams( pParsCsw );
+ pParsCsw->nBTlimit = nBTLimit;
+ pCaig = Caig_ManClassesPrepare( pAig, pParsCsw->nWords, pParsCsw->nRounds );
+
+ pSRAig = Caig_ManSpecReduce( pCaig );
+ Aig_ManPrintStats( pSRAig );
+
+ Cec_ManSatSetDefaultParams( pParsSat );
+ pParsSat->fFirstStop = 0;
+ pParsSat->nBTLimit = pParsCsw->nBTlimit;
+clk = clock();
+ Status = Cec_SatSolveOutputs( pSRAig, pParsSat );
+ Cec_MiterStatusPrint( Status, "SRM ", clock() - clk );
+
+ Aig_ManStop( pSRAig );
+
+ Caig_ManDelete( pCaig );
+
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs equivalence checking.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_Solve( Aig_Man_t * pAig0, Aig_Man_t * pAig1, Cec_ParCec_t * pPars )
+{
+ Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
+ Cec_MtrStatus_t Status;
+ Aig_Man_t * pMiter;
+ int i, clk = clock();
+ if ( pPars->fVerbose )
+ {
+ Status = Cec_MiterStatusTrivial( pAig0 );
+ Status.nNodes += pAig1? Aig_ManNodeNum( pAig1 ) : 0;
+ Cec_MiterStatusPrint( Status, "Init ", 0 );
+ }
+ // create combinational miter
+ if ( pAig1 == NULL )
+ {
+ Status = Cec_MiterStatus( pAig0 );
+ if ( Status.nSat > 0 && pPars->fFirstStop )
+ {
+ if ( pPars->fVerbose )
+ printf( "Output %d is trivially SAT.\n", Status.iOut );
+ return 0;
+ }
+ if ( Status.nUndec == 0 )
+ {
+ if ( pPars->fVerbose )
+ printf( "The miter has no undecided outputs.\n" );
+ return 1;
+ }
+ pMiter = Cec_Duplicate( pAig0 );
+ }
+ else
+ {
+ pMiter = Cec_DeriveMiter( pAig0, pAig1 );
+ Status = Cec_MiterStatus( pMiter );
+ if ( Status.nSat > 0 && pPars->fFirstStop )
+ {
+ if ( pPars->fVerbose )
+ printf( "Output %d is trivially SAT.\n", Status.iOut );
+ Aig_ManStop( pMiter );
+ return 0;
+ }
+ if ( Status.nUndec == 0 )
+ {
+ if ( pPars->fVerbose )
+ printf( "The problem is solved by structrual hashing.\n" );
+ Aig_ManStop( pMiter );
+ return 1;
+ }
+ }
+ if ( pPars->fVerbose )
+ Cec_MiterStatusPrint( Status, "Strash", clock() - clk );
+ // start parameter structures
+ Cec_ManSatSetDefaultParams( pParsSat );
+ pParsSat->fFirstStop = pPars->fFirstStop;
+ pParsSat->nBTLimit = pPars->nBTLimitBeg;
+ for ( i = 0; i < pPars->nIters; i++ )
+ {
+ // try SAT solving
+ clk = clock();
+ pParsSat->nBTLimit *= pPars->nBTlimitMulti;
+ Status = Cec_SatSolveOutputs( pMiter, pParsSat );
+ if ( pPars->fVerbose )
+ Cec_MiterStatusPrint( Status, "SAT ", clock() - clk );
+ if ( Status.nSat && pParsSat->fFirstStop )
+ break;
+ if ( Status.nUndec == 0 )
+ break;
+
+ // try rewriting
+
+ // try SAT sweeping
+ Cec_Sweep( pMiter, 10 );
+ i = i;
+ }
+ Aig_ManStop( pMiter );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/cec/cecInt.h b/src/aig/cec/cecInt.h
new file mode 100644
index 00000000..93221f83
--- /dev/null
+++ b/src/aig/cec/cecInt.h
@@ -0,0 +1,220 @@
+/**CFile****************************************************************
+
+ FileName [cecInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinatinoal equivalence checking.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __CEC_INT_H__
+#define __CEC_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig.h"
+#include "satSolver.h"
+#include "bar.h"
+#include "cec.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cec_ManSat_t_ Cec_ManSat_t;
+struct Cec_ManSat_t_
+{
+ // parameters
+ Cec_ParSat_t * pPars;
+ // AIGs used in the package
+ Aig_Man_t * pAig; // the AIG whose outputs are considered
+ Vec_Int_t * vStatus; // status for each output
+ // SAT solving
+ sat_solver * pSat; // recyclable SAT solver
+ int nSatVars; // the counter of SAT variables
+ int * pSatVars; // mapping of each node into its SAT var
+ Vec_Ptr_t * vUsedNodes; // nodes whose SAT vars are assigned
+ int nRecycles; // the number of times SAT solver was recycled
+ int nCallsSince; // the number of calls since the last recycle
+ Vec_Ptr_t * vFanins; // fanins of the CNF node
+ // SAT calls statistics
+ int nSatUnsat; // the number of proofs
+ int nSatSat; // the number of failure
+ int nSatUndec; // the number of timeouts
+ // runtime stats
+ int timeSatUnsat; // unsat
+ int timeSatSat; // sat
+ int timeSatUndec; // undecided
+ int timeTotal; // total runtime
+};
+
+typedef struct Cec_ManCla_t_ Cec_ManCla_t;
+
+typedef struct Cec_ManCsw_t_ Cec_ManCsw_t;
+struct Cec_ManCsw_t_
+{
+ // parameters
+ Cec_ParCsw_t * pPars;
+ // AIGs used in the package
+ Aig_Man_t * pAig; // the AIG for SAT sweeping
+ Aig_Man_t * pFraig; // the AIG after SAT sweeping
+ // equivalence classes
+ Cec_ManCla_t * ppClasses; // equivalence classes of nodes
+ // choice node statistics
+ int nLits; // the number of lits in the cand equiv classes
+ int nReprs; // the number of proved equivalent pairs
+ int nEquivs; // the number of final equivalences
+ int nChoices; // the number of final choice nodes
+};
+
+typedef struct Cec_ManCec_t_ Cec_ManCec_t;
+struct Cec_ManCec_t_
+{
+ // parameters
+ Cec_ParCec_t * pPars;
+ // AIGs used in the package
+ Aig_Man_t * pAig; // the miter for equivalence checking
+ // mapping of PI/PO nodes
+
+ // counter-example
+ int * pCex; // counter-example
+ int iOutput; // the output for this counter-example
+
+ // statistics
+
+};
+
+typedef struct Cec_MtrStatus_t_ Cec_MtrStatus_t;
+struct Cec_MtrStatus_t_
+{
+ int nInputs; // the total number of inputs
+ int nNodes; // the total number of nodes
+ int nOutputs; // the total number of outputs
+ int nUnsat; // the number of UNSAT outputs
+ int nSat; // the number of SAT outputs
+ int nUndec; // the number of undecided outputs
+ int iOut; // the satisfied output
+};
+
+// combinational simulation manager
+typedef struct Caig_Man_t_ Caig_Man_t;
+struct Caig_Man_t_
+{
+ // parameters
+ Aig_Man_t * pAig; // the AIG to be used for simulation
+ int nWords; // the number of words to simulate
+ // AIG representation
+ int nPis; // the number of primary inputs
+ int nPos; // the number of primary outputs
+ int nNodes; // the number of internal nodes
+ int nObjs; // nPis + nNodes + nPos + 1
+ int * pFans0; // fanin0 for all objects
+ int * pFans1; // fanin1 for all objects
+ // simulation info
+ unsigned short* pRefs; // reference counter for each node
+ unsigned * pSims; // simlulation information for each node
+ // recycable memory
+ unsigned * pMems; // allocated simulaton memory
+ int nWordsAlloc; // the number of allocated entries
+ int nMems; // the number of used entries
+ int nMemsMax; // the max number of used entries
+ int MemFree; // next free entry
+ // equivalence class representation
+ int * pReprs; // representatives of each node
+ int * pNexts; // nexts for each node
+ // temporaries
+ Vec_Ptr_t * vSims; // pointers to sim info
+ Vec_Int_t * vClassOld; // old class numbers
+ Vec_Int_t * vClassNew; // new class numbers
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Cec_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; }
+static inline int Cec_Lit2Var( int Lit ) { return Lit >> 1; }
+static inline int Cec_LitIsCompl( int Lit ) { return Lit & 1; }
+static inline int Cec_LitNot( int Lit ) { return Lit ^ 1; }
+static inline int Cec_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); }
+static inline int Cec_LitRegular( int Lit ) { return Lit & ~01; }
+
+static inline int Cec_ObjSatNum( Cec_ManSat_t * p, Aig_Obj_t * pObj ) { return p->pSatVars[pObj->Id]; }
+static inline void Cec_ObjSetSatNum( Cec_ManSat_t * p, Aig_Obj_t * pObj, int Num ) { p->pSatVars[pObj->Id] = Num; }
+
+static inline Aig_Obj_t * Cec_ObjFraig( Aig_Obj_t * pObj ) { return pObj->pData; }
+static inline void Cec_ObjSetFraig( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { pObj->pData = pNode; }
+
+static inline int Cec_ObjIsConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj )
+{
+ return Aig_ObjRepr(pAig, pObj) == Aig_ManConst1(pAig);
+}
+static inline void Cec_ObjSetConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj )
+{
+ assert( !Cec_ObjIsConst1Cand( pAig, pObj ) );
+ Aig_ObjSetRepr( pAig, pObj, Aig_ManConst1(pAig) );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cecAig.c ==========================================================*/
+extern Aig_Man_t * Cec_Duplicate( Aig_Man_t * p );
+extern Aig_Man_t * Cec_DeriveMiter( Aig_Man_t * p0, Aig_Man_t * p1 );
+/*=== cecClass.c ==========================================================*/
+extern Aig_Man_t * Caig_ManSpecReduce( Caig_Man_t * p );
+extern int Caig_ManCompareEqual( unsigned * p0, unsigned * p1, int nWords );
+extern int Caig_ManCompareConst( unsigned * p, int nWords );
+extern void Caig_ManProcessClass( Caig_Man_t * p, int i );
+extern void Caig_ManProcessRefined( Caig_Man_t * p, Vec_Int_t * vRefined );
+extern Caig_Man_t * Caig_ManClassesPrepare( Aig_Man_t * pAig, int nWords, int nIters );
+/*=== cecCnf.c ==========================================================*/
+extern void Cec_CnfNodeAddToSolver( Cec_ManSat_t * p, Aig_Obj_t * pObj );
+/*=== cecSat.c ==========================================================*/
+extern Cec_MtrStatus_t Cec_SatSolveOutputs( Aig_Man_t * pAig, Cec_ParSat_t * pPars );
+/*=== cecSim.c ==========================================================*/
+extern Caig_Man_t * Caig_ManCreate( Aig_Man_t * pAig );
+extern void Caig_ManDelete( Caig_Man_t * p );
+extern unsigned * Caig_ManSimRead( Caig_Man_t * p, int i );
+extern unsigned * Caig_ManSimRef( Caig_Man_t * p, int i );
+extern unsigned * Caig_ManSimDeref( Caig_Man_t * p, int i );
+extern int Caig_ManSimulateRound( Caig_Man_t * p, int fMiter );
+extern int Cec_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose );
+/*=== cecStatus.c ==========================================================*/
+extern int Cec_OutputStatus( Aig_Man_t * p, Aig_Obj_t * pObj );
+extern Cec_MtrStatus_t Cec_MiterStatus( Aig_Man_t * p );
+extern Cec_MtrStatus_t Cec_MiterStatusTrivial( Aig_Man_t * p );
+extern void Cec_MiterStatusPrint( Cec_MtrStatus_t S, char * pString, int Time );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/saig/saigLoc.c b/src/aig/cec/cecMan.c
index edbf231c..86415c53 100644
--- a/src/aig/saig/saigLoc.c
+++ b/src/aig/cec/cecMan.c
@@ -1,12 +1,12 @@
/**CFile****************************************************************
- FileName [saigLoc.c]
+ FileName [cecMan.c]
SystemName [ABC: Logic synthesis and verification system.]
- PackageName [Sequential AIG package.]
+ PackageName [Combinatinoal equivalence checking.]
- Synopsis [Localization.]
+ Synopsis [Manager pcocures.]
Author [Alan Mishchenko]
@@ -14,11 +14,11 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: saigLoc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: cecMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
-#include "saig.h"
+#include "cecInt.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -40,6 +40,17 @@
***********************************************************************/
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/aig/cec/cecSat.c b/src/aig/cec/cecSat.c
index 37f63f05..9cf13ebc 100644
--- a/src/aig/cec/cecSat.c
+++ b/src/aig/cec/cecSat.c
@@ -4,23 +4,21 @@
SystemName [ABC: Logic synthesis and verification system.]
- PackageName [Combinational equivalence checking.]
+ PackageName [Combinatinoal equivalence checking.]
- Synopsis [Backend calling the SAT solver.]
+ Synopsis [SAT solver calls.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
- Date [Ver. 1.0. Started - June 30, 2007.]
+ Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: cecSat.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+ Revision [$Id: cecSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
-#include "aig.h"
-#include "cnf.h"
-#include "solver.h"
+#include "cecInt.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -32,7 +30,7 @@
/**Function*************************************************************
- Synopsis [Writes CNF into a file.]
+ Synopsis [Creates the manager.]
Description []
@@ -41,33 +39,25 @@
SeeAlso []
***********************************************************************/
-solver * Cnf_WriteIntoSolverNew( Cnf_Dat_t * p )
+Cec_ManSat_t * Cec_ManCreate( Aig_Man_t * pAig, Cec_ParSat_t * pPars )
{
- solver * pSat;
- int i, status;
- pSat = solver_new();
- for ( i = 0; i < p->nVars; i++ )
- solver_newVar( pSat );
- for ( i = 0; i < p->nClauses; i++ )
- {
- if ( !solver_addClause( pSat, p->pClauses[i+1]-p->pClauses[i], p->pClauses[i] ) )
- {
- solver_delete( pSat );
- return NULL;
- }
- }
- status = solver_simplify(pSat);
- if ( status == 0 )
- {
- solver_delete( pSat );
- return NULL;
- }
- return pSat;
+ Cec_ManSat_t * p;
+ // create interpolation manager
+ p = ALLOC( Cec_ManSat_t, 1 );
+ memset( p, 0, sizeof(Cec_ManSat_t) );
+ p->pPars = pPars;
+ p->pAig = pAig;
+ // SAT solving
+ p->nSatVars = 1;
+ p->pSatVars = CALLOC( int, Aig_ManObjNumMax(pAig) );
+ p->vUsedNodes = Vec_PtrAlloc( 1000 );
+ p->vFanins = Vec_PtrAlloc( 100 );
+ return p;
}
/**Function*************************************************************
- Synopsis [Adds the OR-clause.]
+ Synopsis [Frees the manager.]
Description []
@@ -76,25 +66,19 @@ solver * Cnf_WriteIntoSolverNew( Cnf_Dat_t * p )
SeeAlso []
***********************************************************************/
-int Cnf_DataWriteAndClausesNew( void * p, Cnf_Dat_t * pCnf )
+void Cec_ManStop( Cec_ManSat_t * p )
{
-/*
- sat_solver * pSat = p;
- Aig_Obj_t * pObj;
- int i, Lit;
- Aig_ManForEachPo( pCnf->pMan, pObj, i )
- {
- Lit = toLitCond( pCnf->pVarNums[pObj->Id], 0 );
- if ( !sat_solver_addclause( pSat, &Lit, &Lit+1 ) )
- return 0;
- }
-*/
- return 1;
+ if ( p->pSat )
+ sat_solver_delete( p->pSat );
+ Vec_PtrFree( p->vUsedNodes );
+ Vec_PtrFree( p->vFanins );
+ FREE( p->pSatVars );
+ free( p );
}
/**Function*************************************************************
- Synopsis [Adds the OR-clause.]
+ Synopsis [Recycles the SAT solver.]
Description []
@@ -103,25 +87,38 @@ int Cnf_DataWriteAndClausesNew( void * p, Cnf_Dat_t * pCnf )
SeeAlso []
***********************************************************************/
-int Cnf_DataWriteOrClauseNew( solver * pSat, Cnf_Dat_t * pCnf )
+void Cec_ManSatSolverRecycle( Cec_ManSat_t * p )
{
- Aig_Obj_t * pObj;
- int i, * pLits;
- pLits = ALLOC( int, Aig_ManPoNum(pCnf->pMan) );
- Aig_ManForEachPo( pCnf->pMan, pObj, i )
- pLits[i] = solver_mkLit_args( pCnf->pVarNums[pObj->Id], 0 );
- if ( !solver_addClause( pSat, Aig_ManPoNum(pCnf->pMan), pLits ) )
+ int Lit;
+ if ( p->pSat )
{
- free( pLits );
- return 0;
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( p->vUsedNodes, pObj, i )
+ Cec_ObjSetSatNum( p, pObj, 0 );
+ Vec_PtrClear( p->vUsedNodes );
+// memset( p->pSatVars, 0, sizeof(int) * Aig_ManObjNumMax(p->pAigTotal) );
+ sat_solver_delete( p->pSat );
}
- free( pLits );
- return 1;
+ p->pSat = sat_solver_new();
+ sat_solver_setnvars( p->pSat, 1000 );
+ // var 0 is not used
+ // var 1 is reserved for const1 node - add the clause
+ p->nSatVars = 1;
+// p->nSatVars = 0;
+ Lit = toLit( p->nSatVars );
+ if ( p->pPars->fPolarFlip )
+ Lit = lit_neg( Lit );
+ sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+ Cec_ObjSetSatNum( p, Aig_ManConst1(p->pAig), p->nSatVars++ );
+
+ p->nRecycles++;
+ p->nCallsSince = 0;
}
/**Function*************************************************************
- Synopsis [Writes the given clause in a file in DIMACS format.]
+ Synopsis [Runs equivalence test for the two nodes.]
Description []
@@ -130,36 +127,66 @@ int Cnf_DataWriteOrClauseNew( solver * pSat, Cnf_Dat_t * pCnf )
SeeAlso []
***********************************************************************/
-void Sat_SolverPrintStatsNew( FILE * pFile, solver * pSat )
+int Cec_ManSatCheckNode( Cec_ManSat_t * p, Aig_Obj_t * pNode )
{
-// printf( "starts : %8d\n", solver_num_assigns(pSat) );
- printf( "vars : %8d\n", solver_num_vars(pSat) );
- printf( "clauses : %8d\n", solver_num_clauses(pSat) );
- printf( "conflicts : %8d\n", solver_num_learnts(pSat) );
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns a counter-example.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
+ int nBTLimit = p->pPars->nBTLimit;
+ int Lit, RetValue, status, clk;
+
+ // sanity checks
+ assert( !Aig_IsComplement(pNode) );
+
+ p->nCallsSince++; // experiment with this!!!
+
+ // check if SAT solver needs recycling
+ if ( p->pSat == NULL ||
+ (p->pPars->nSatVarMax &&
+ p->nSatVars > p->pPars->nSatVarMax &&
+ p->nCallsSince > p->pPars->nCallsRecycle) )
+ Cec_ManSatSolverRecycle( p );
+
+ // if the nodes do not have SAT variables, allocate them
+ Cec_CnfNodeAddToSolver( p, pNode );
+
+ // propage unit clauses
+ if ( p->pSat->qtail != p->pSat->qhead )
+ {
+ status = sat_solver_simplify(p->pSat);
+ assert( status != 0 );
+ assert( p->pSat->qtail == p->pSat->qhead );
+ }
-***********************************************************************/
-int * Sat_SolverGetModelNew( solver * pSat, int * pVars, int nVars )
-{
- int * pModel;
- int i;
- pModel = ALLOC( int, nVars+1 );
- for ( i = 0; i < nVars; i++ )
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+ Lit = toLitCond( Cec_ObjSatNum(p,pNode), pNode->fPhase );
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNode->fPhase ) Lit = lit_neg( Lit );
+ }
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+clk = clock();
+ RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1,
+ (sint64)nBTLimit, (sint64)0, (sint64)0, (sint64)0 );
+ if ( RetValue == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ Lit = lit_neg( Lit );
+ RetValue = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+ assert( RetValue );
+ p->timeSatUnsat++;
+ return 1;
+ }
+ else if ( RetValue == l_True )
{
- assert( pVars[i] >= 0 && pVars[i] < solver_num_vars(pSat) );
- pModel[i] = (int)(solver_modelValue_Var( pSat, pVars[i] ) == solver_l_True);
+p->timeSatSat += clock() - clk;
+ p->timeSatSat++;
+ return 0;
+ }
+ else // if ( RetValue == l_Undef )
+ {
+p->timeSatUndec += clock() - clk;
+ p->timeSatUndec++;
+ return -1;
}
- return pModel;
}
/**Function*************************************************************
@@ -173,112 +200,51 @@ int * Sat_SolverGetModelNew( solver * pSat, int * pVars, int nVars )
SeeAlso []
***********************************************************************/
-int Cec_RunSat( Aig_Man_t * pMan, sint64 nConfLimit, sint64 nInsLimit, int fFlipBits, int fAndOuts, int fVerbose )
+Cec_MtrStatus_t Cec_SatSolveOutputs( Aig_Man_t * pAig, Cec_ParSat_t * pPars )
{
- solver * pSat;
- Cnf_Dat_t * pCnf;
- int status, RetValue, clk = clock();
- Vec_Int_t * vCiIds;
-
- assert( Aig_ManRegNum(pMan) == 0 );
- pMan->pData = NULL;
-
- // derive CNF
- pCnf = Cnf_Derive( pMan, Aig_ManPoNum(pMan) );
-// pCnf = Cnf_DeriveSimple( pMan, Aig_ManPoNum(pMan) );
-
- // convert into SAT solver
- pSat = Cnf_WriteIntoSolverNew( pCnf );
- if ( pSat == NULL )
- {
- Cnf_DataFree( pCnf );
- return 1;
- }
-
-
- if ( fAndOuts )
+ Bar_Progress_t * pProgress = NULL;
+ Cec_MtrStatus_t Status;
+ Cec_ManSat_t * p;
+ Aig_Obj_t * pObj;
+ int i, status;
+ Status = Cec_MiterStatus( pAig );
+ p = Cec_ManCreate( pAig, pPars );
+ pProgress = Bar_ProgressStart( stdout, Aig_ManPoNum(pAig) );
+ Aig_ManForEachPo( pAig, pObj, i )
{
- assert( 0 );
- // assert each output independently
- if ( !Cnf_DataWriteAndClausesNew( pSat, pCnf ) )
+ Bar_ProgressUpdate( pProgress, i, "SAT..." );
+ if ( Cec_OutputStatus(pAig, pObj) )
+ continue;
+ status = Cec_ManSatCheckNode( p, Aig_ObjFanin0(pObj) );
+ if ( status == 1 )
{
- solver_delete( pSat );
- Cnf_DataFree( pCnf );
- return 1;
+ Status.nUndec--, Status.nUnsat++;
+ Aig_ObjPatchFanin0( pAig, pObj, Aig_ManConst0(pAig) );
}
- }
- else
- {
- // add the OR clause for the outputs
- if ( !Cnf_DataWriteOrClauseNew( pSat, pCnf ) )
+ if ( status == 0 )
{
- solver_delete( pSat );
- Cnf_DataFree( pCnf );
- return 1;
+ Status.nUndec--, Status.nSat++;
+ Aig_ObjPatchFanin0( pAig, pObj, Aig_ManConst1(pAig) );
}
+ if ( status == -1 )
+ continue;
+ // save the pattern (if it is first)
+ if ( Status.iOut == -1 )
+ {
+ }
+ // quit if at least one of them is solved
+ if ( status == 0 && pPars->fFirstStop )
+ break;
}
- vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan );
- Cnf_DataFree( pCnf );
-
-
-// printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
-// PRT( "Time", clock() - clk );
-
- // simplify the problem
- clk = clock();
- status = solver_simplify(pSat);
-// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
-// PRT( "Time", clock() - clk );
- if ( status == 0 )
- {
- Vec_IntFree( vCiIds );
- solver_delete( pSat );
-// printf( "The problem is UNSATISFIABLE after simplification.\n" );
- return 1;
- }
-
- // solve the miter
- clk = clock();
- if ( fVerbose )
- solver_set_verbosity( pSat, 1 );
- status = solver_solve( pSat, 0, NULL );
- if ( status == solver_l_Undef )
- {
-// printf( "The problem timed out.\n" );
- RetValue = -1;
- }
- else if ( status == solver_l_True )
- {
-// printf( "The problem is SATISFIABLE.\n" );
- RetValue = 0;
- }
- else if ( status == solver_l_False )
- {
-// printf( "The problem is UNSATISFIABLE.\n" );
- RetValue = 1;
- }
- else
- assert( 0 );
-// PRT( "SAT sat_solver time", clock() - clk );
-// printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts );
-
- // if the problem is SAT, get the counterexample
- if ( status == solver_l_True )
- {
- pMan->pData = Sat_SolverGetModelNew( pSat, vCiIds->pArray, vCiIds->nSize );
- }
- // free the sat_solver
- if ( fVerbose )
- Sat_SolverPrintStatsNew( stdout, pSat );
-//sat_solver_store_write( pSat, "trace.cnf" );
-//sat_solver_store_free( pSat );
- solver_delete( pSat );
- Vec_IntFree( vCiIds );
- return RetValue;
+ Aig_ManCleanup( pAig );
+ Bar_ProgressStop( pProgress );
+ printf( " Confs = %8d. Recycles = %6d.\n", p->pPars->nBTLimit, p->nRecycles );
+ Cec_ManStop( p );
+ return Status;
}
-
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/cec/cecSim.c b/src/aig/cec/cecSim.c
new file mode 100644
index 00000000..8a5f3cd5
--- /dev/null
+++ b/src/aig/cec/cecSim.c
@@ -0,0 +1,459 @@
+/**CFile****************************************************************
+
+ FileName [cecSim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinatinoal equivalence checking.]
+
+ Synopsis [AIG simulation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Count PIs with fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Caig_ManCountRelevantPis( Aig_Man_t * pAig )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Aig_ManForEachPi( pAig, pObj, i )
+ if ( Aig_ObjRefs(pObj) )
+ Counter++;
+ else
+ pObj->iData = -1;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count PIs with fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Caig_ManCountRelevantPos( Aig_Man_t * pAig )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Aig_ManForEachPo( pAig, pObj, i )
+ if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
+ Counter++;
+ else
+ pObj->iData = -1;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the PO corresponding to the PO driver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Caig_ManFindPo( Aig_Man_t * pAig, int iNode )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManForEachPo( pAig, pObj, i )
+ if ( pObj->iData == iNode )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates fast simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Caig_ManCreate_rec( Caig_Man_t * p, Aig_Obj_t * pObj )
+{
+ int iFan0, iFan1;
+ assert( !Aig_IsComplement(pObj) );
+ assert( !Aig_ObjIsConst1(pObj) );
+ if ( pObj->iData )
+ return pObj->iData;
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ iFan0 = Caig_ManCreate_rec( p, Aig_ObjFanin0(pObj) );
+ iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj);
+ iFan1 = Caig_ManCreate_rec( p, Aig_ObjFanin1(pObj) );
+ iFan1 = (iFan1 << 1) | Aig_ObjFaninC1(pObj);
+ }
+ else if ( Aig_ObjIsPo(pObj) )
+ {
+ iFan0 = Caig_ManCreate_rec( p, Aig_ObjFanin0(pObj) );
+ iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj);
+ iFan1 = 0;
+ }
+ else
+ iFan0 = iFan1 = 0;
+ assert( Aig_ObjRefs(pObj) < (1<<16) );
+ p->pFans0[p->nObjs] = iFan0;
+ p->pFans1[p->nObjs] = iFan1;
+ p->pRefs[p->nObjs] = (unsigned short)Aig_ObjRefs(pObj);
+ return pObj->iData = p->nObjs++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates fast simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Caig_Man_t * Caig_ManCreate( Aig_Man_t * pAig )
+{
+ Caig_Man_t * p;
+ Aig_Obj_t * pObj;
+ int i, nObjs;
+ Aig_ManCleanData( pAig );
+ p = (Caig_Man_t *)ALLOC( Caig_Man_t, 1 );
+ memset( p, 0, sizeof(Caig_Man_t) );
+ p->pAig = pAig;
+ p->nPis = Caig_ManCountRelevantPis(pAig);
+ p->nPos = Caig_ManCountRelevantPos(pAig);
+ p->nNodes = Aig_ManNodeNum(pAig);
+ nObjs = p->nPis + p->nPos + p->nNodes + 1;
+ p->pFans0 = ALLOC( int, nObjs );
+ p->pFans1 = ALLOC( int, nObjs );
+ p->pRefs = ALLOC( unsigned short, nObjs );
+ p->pSims = CALLOC( unsigned, nObjs );
+ // add objects
+ p->nObjs = 1;
+ Aig_ManForEachPo( pAig, pObj, i )
+ if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
+ Caig_ManCreate_rec( p, pObj );
+ assert( p->nObjs == nObjs );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates fast simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Caig_ManDelete( Caig_Man_t * p )
+{
+ if ( p->vSims ) Vec_PtrFree( p->vSims );
+ if ( p->vClassOld ) Vec_IntFree( p->vClassOld );
+ if ( p->vClassNew ) Vec_IntFree( p->vClassNew );
+ FREE( p->pFans0 );
+ FREE( p->pFans1 );
+ FREE( p->pRefs );
+ FREE( p->pSims );
+ FREE( p->pMems );
+ FREE( p->pReprs );
+ FREE( p->pNexts );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [References simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Caig_ManSimRead( Caig_Man_t * p, int i )
+{
+ assert( i && p->pSims[i] > 0 );
+ return p->pMems + p->pSims[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [References simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Caig_ManSimRef( Caig_Man_t * p, int i )
+{
+ unsigned * pSim;
+ assert( i );
+ assert( p->pSims[i] == 0 );
+ if ( p->MemFree == 0 )
+ {
+ int * pPlace, Ent;
+ if ( p->nWordsAlloc == 0 )
+ {
+ assert( p->pMems == NULL );
+ p->nWordsAlloc = (1<<17); // -> 1Mb
+ p->nMems = 1;
+ }
+ p->nWordsAlloc *= 2;
+ p->pMems = REALLOC( unsigned, p->pMems, p->nWordsAlloc );
+ pPlace = &p->MemFree;
+ for ( Ent = p->nMems * (p->nWords + 1);
+ Ent + p->nWords + 1 < p->nWordsAlloc;
+ Ent += p->nWords + 1 )
+ {
+ *pPlace = Ent;
+ pPlace = p->pMems + Ent;
+ }
+ *pPlace = 0;
+ }
+ p->pSims[i] = p->MemFree;
+ pSim = p->pMems + p->MemFree;
+ p->MemFree = pSim[0];
+ pSim[0] = p->pRefs[i];
+ p->nMems++;
+ if ( p->nMemsMax < p->nMems )
+ p->nMemsMax = p->nMems;
+ return pSim;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dereference simulaton info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Caig_ManSimDeref( Caig_Man_t * p, int i )
+{
+ unsigned * pSim;
+ assert( i );
+ assert( p->pSims[i] > 0 );
+ pSim = p->pMems + p->pSims[i];
+ if ( --pSim[0] == 0 )
+ {
+ pSim[0] = p->MemFree;
+ p->MemFree = p->pSims[i];
+ p->pSims[i] = 0;
+ p->nMems--;
+ }
+ return pSim;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one round.]
+
+ Description [Returns the number of PO entry if failed; 0 otherwise.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Caig_ManSimulateRound( Caig_Man_t * p, int fMiter )
+{
+ Vec_Int_t * vRefined = NULL;
+ unsigned * pRes0, * pRes1, * pRes;
+ int i, w, iFan0, iFan1;
+ if ( p->pReprs )
+ vRefined = Vec_IntAlloc( 1000 );
+ for ( i = 1; i < p->nObjs; i++ )
+ {
+ if ( p->pFans0[i] == 0 ) // pi always has zero first fanin
+ {
+ pRes = Caig_ManSimRef( p, i );
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = Aig_ManRandom( 0 );
+ goto references;
+ }
+ if ( p->pFans1[i] == 0 ) // po always has non-zero 1st fanin and zero 2nd fanin
+ {
+ if ( fMiter )
+ {
+ unsigned Const = Cec_LitIsCompl(p->pFans0[i])? ~0 : 0;
+ pRes0 = Caig_ManSimDeref( p, Cec_Lit2Var(p->pFans0[i]) );
+ for ( w = 1; w <= p->nWords; w++ )
+ if ( pRes0[w] != Const )
+ return i;
+ }
+ continue;
+ }
+ pRes = Caig_ManSimRef( p, i );
+ iFan0 = p->pFans0[i];
+ iFan1 = p->pFans1[i];
+ pRes0 = Caig_ManSimDeref( p, Cec_Lit2Var(p->pFans0[i]) );
+ pRes1 = Caig_ManSimDeref( p, Cec_Lit2Var(p->pFans1[i]) );
+ if ( Cec_LitIsCompl(iFan0) && Cec_LitIsCompl(iFan1) )
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = ~(pRes0[w] | pRes1[w]);
+ else if ( Cec_LitIsCompl(iFan0) && !Cec_LitIsCompl(iFan1) )
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = ~pRes0[w] & pRes1[w];
+ else if ( !Cec_LitIsCompl(iFan0) && Cec_LitIsCompl(iFan1) )
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = pRes0[w] & ~pRes1[w];
+ else if ( !Cec_LitIsCompl(iFan0) && !Cec_LitIsCompl(iFan1) )
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = pRes0[w] & pRes1[w];
+references:
+ if ( p->pReprs == NULL )
+ continue;
+ // if this node is candidate constant, collect it
+ if ( p->pReprs[i] == 0 && !Caig_ManCompareConst(pRes + 1, p->nWords) )
+ {
+ pRes[0]++;
+ Vec_IntPush( vRefined, i );
+ }
+ // if the node belongs to a class, save it
+ if ( p->pReprs[i] > 0 || p->pNexts[i] > 0 )
+ pRes[0]++;
+ // if this is the last node of the class, process it
+ if ( p->pReprs[i] > 0 && p->pNexts[i] == 0 )
+ Caig_ManProcessClass( p, p->pReprs[i] );
+ }
+ if ( p->pReprs )
+ Caig_ManProcessRefined( p, vRefined );
+ if ( p->pReprs )
+ Vec_IntFree( vRefined );
+ assert( p->nMems == 1 );
+/*
+ if ( p->nMems > 1 )
+ {
+ for ( i = 1; i < p->nObjs; i++ )
+ if ( p->pSims[i] )
+ {
+ int x = 0;
+ }
+ }
+*/
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the bug is detected, 0 otherwise.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose )
+{
+ Caig_Man_t * p;
+ Cec_MtrStatus_t Status;
+ int i, RetValue = 0, clk, clkTotal = clock();
+/*
+ p = Caig_ManClassesPrepare( pAig, nWords, nIters );
+// if ( fVerbose )
+ printf( "Maxcut = %6d. AIG mem = %8.3f Mb. Sim mem = %8.3f Mb.\n",
+ p->nMemsMax,
+ 1.0*(p->nObjs * 14)/(1<<20),
+ 1.0*(p->nMemsMax * (nWords+1))/(1<<20) );
+ Caig_ManDelete( p );
+ return 0;
+*/
+ Status = Cec_MiterStatus( pAig );
+ if ( Status.nSat > 0 )
+ {
+ printf( "Miter is trivially satisfiable (output %d).\n", Status.iOut );
+ return 1;
+ }
+ if ( Status.nUndec == 0 )
+ {
+ printf( "Miter is trivially unsatisfiable.\n" );
+ return 0;
+ }
+ Aig_ManRandom( 1 );
+ p = Caig_ManCreate( pAig );
+ p->nWords = nWords;
+ for ( i = 0; i < nIters; i++ )
+ {
+ clk = clock();
+ RetValue = Caig_ManSimulateRound( p, fMiter );
+ if ( fVerbose )
+ {
+ printf( "Iter %3d out of %3d and timeout %3d sec. ", i+1, nIters, TimeLimit );
+ printf("Time = %7.2f sec\r", (1.0*clock()-clkTotal)/CLOCKS_PER_SEC);
+ }
+ if ( RetValue > 0 )
+ {
+ int iOut = Caig_ManFindPo(p->pAig, RetValue);
+ if ( fVerbose )
+ printf( "Miter is satisfiable after simulation (output %d).\n", iOut );
+ break;
+ }
+ if ( (clock() - clk)/CLOCKS_PER_SEC >= TimeLimit )
+ {
+ printf( "No bug detected after %d rounds with time limit %d seconds.\n", i+1, TimeLimit );
+ break;
+ }
+ }
+ if ( fVerbose )
+ printf( "Maxcut = %6d. AIG mem = %8.3f Mb. Sim mem = %8.3f Mb.\n",
+ p->nMemsMax,
+ 1.0*(p->nObjs * 14)/(1<<20),
+ 1.0*(p->nMemsMax * 4 * (nWords+1))/(1<<20) );
+ Caig_ManDelete( p );
+ return RetValue > 0;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/cec/cecStatus.c b/src/aig/cec/cecStatus.c
new file mode 100644
index 00000000..79d6ec66
--- /dev/null
+++ b/src/aig/cec/cecStatus.c
@@ -0,0 +1,187 @@
+/**CFile****************************************************************
+
+ FileName [cecStatus.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinatinoal equivalence checking.]
+
+ Synopsis [Miter status.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecStatus.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the output is known.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_OutputStatus( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pChild;
+ assert( Aig_ObjIsPo(pObj) );
+ pChild = Aig_ObjChild0(pObj);
+ // check if the output is constant 0
+ if ( pChild == Aig_ManConst0(p) )
+ return 1;
+ // check if the output is constant 1
+ if ( pChild == Aig_ManConst1(p) )
+ return 1;
+ // check if the output is a primary input
+ if ( Aig_ObjIsPi(Aig_Regular(pChild)) )
+ return 1;
+ // check if the output is 1 for the 0000 pattern
+ if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns number of used inputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_CountInputs( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Aig_ManForEachPi( p, pObj, i )
+ Counter += (int)(pObj->nRefs > 0);
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks the status of the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cec_MtrStatus_t Cec_MiterStatus( Aig_Man_t * p )
+{
+ Cec_MtrStatus_t Status;
+ Aig_Obj_t * pObj, * pChild;
+ int i;
+ assert( p->nRegs == 0 );
+ memset( &Status, 0, sizeof(Cec_MtrStatus_t) );
+ Status.iOut = -1;
+ Status.nInputs = Cec_CountInputs( p );
+ Status.nNodes = Aig_ManNodeNum( p );
+ Status.nOutputs = Aig_ManPoNum(p);
+ Aig_ManForEachPo( p, pObj, i )
+ {
+ pChild = Aig_ObjChild0(pObj);
+ // check if the output is constant 0
+ if ( pChild == Aig_ManConst0(p) )
+ Status.nUnsat++;
+ // check if the output is constant 1
+ else if ( pChild == Aig_ManConst1(p) )
+ {
+ Status.nSat++;
+ if ( Status.iOut == -1 )
+ Status.iOut = i;
+ }
+ // check if the output is a primary input
+ else if ( Aig_ObjIsPi(Aig_Regular(pChild)) )
+ {
+ Status.nSat++;
+ if ( Status.iOut == -1 )
+ Status.iOut = i;
+ }
+ // check if the output is 1 for the 0000 pattern
+ else if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) )
+ {
+ Status.nSat++;
+ if ( Status.iOut == -1 )
+ Status.iOut = i;
+ }
+ else
+ Status.nUndec++;
+ }
+ return Status;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks the status of the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cec_MtrStatus_t Cec_MiterStatusTrivial( Aig_Man_t * p )
+{
+ Cec_MtrStatus_t Status;
+ memset( &Status, 0, sizeof(Cec_MtrStatus_t) );
+ Status.iOut = -1;
+ Status.nInputs = Aig_ManPiNum(p);
+ Status.nNodes = Aig_ManNodeNum( p );
+ Status.nOutputs = Aig_ManPoNum(p);
+ Status.nUndec = Aig_ManPoNum(p);
+ return Status;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the status of the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_MiterStatusPrint( Cec_MtrStatus_t S, char * pString, int Time )
+{
+ printf( "%s:", pString );
+ printf( " I =%6d", S.nInputs );
+ printf( " N =%7d", S.nNodes );
+ printf( " " );
+ printf( " ? =%6d", S.nUndec );
+ printf( " U =%6d", S.nUnsat );
+ printf( " S =%6d", S.nSat );
+ printf(" %7.2f sec\n", (float)(Time)/(float)(CLOCKS_PER_SEC));
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/cec/module.make b/src/aig/cec/module.make
new file mode 100644
index 00000000..29f8c859
--- /dev/null
+++ b/src/aig/cec/module.make
@@ -0,0 +1,8 @@
+SRC += src/aig/cec/cecAig.c \
+ src/aig/cec/cecClass.c \
+ src/aig/cec/cecCnf.c \
+ src/aig/cec/cecCore.c \
+ src/aig/cec/cecMan.c \
+ src/aig/cec/cecSat.c \
+ src/aig/cec/cecSim.c \
+ src/aig/cec/cecStatus.c
diff --git a/src/aig/cgt/cgt.h b/src/aig/cgt/cgt.h
index b9997d56..f8c1cc2e 100644
--- a/src/aig/cgt/cgt.h
+++ b/src/aig/cgt/cgt.h
@@ -52,8 +52,9 @@ struct Cgt_Par_t_
int nConfMax; // the max number of conflicts at a node
int nVarsMin; // the min number of variables to recycle the SAT solver
int nFlopsMin; // the min number of flops needed to recycle the SAT solver
+ int fAreaOnly; // derive clock gating to minimize area
int fVerbose; // verbosity flag
-
+ int fVeryVerbose; // verbosity flag
};
////////////////////////////////////////////////////////////////////////
diff --git a/src/aig/cgt/cgtAig.c b/src/aig/cgt/cgtAig.c
index b30d3f16..d411c25a 100644
--- a/src/aig/cgt/cgtAig.c
+++ b/src/aig/cgt/cgtAig.c
@@ -67,7 +67,7 @@ void Cgt_ManDetectCandidates_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nLevel
void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands )
{
Vec_PtrClear( vCands );
- if ( !Aig_ObjIsNode(Aig_ObjFanin0(pObj)) )
+ if ( !Aig_ObjIsNode(pObj) )
return;
Aig_ManIncrementTravId( pAig );
Cgt_ManDetectCandidates_rec( pAig, pObj, nLevelMax, vCands );
@@ -136,6 +136,67 @@ void Cgt_ManDetectFanout( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_P
/**Function*************************************************************
+ Synopsis [Computes visited nodes in the topological order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cgt_ManCollectVisited_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vVisited )
+{
+ if ( Aig_ObjIsPi(pObj) )
+ return;
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(pAig, pObj);
+ assert( Aig_ObjIsNode(pObj) );
+ Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin0(pObj), vVisited );
+ Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin1(pObj), vVisited );
+ Vec_PtrPush( vVisited, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes visited nodes in the topological order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cgt_ManCollectVisited( Aig_Man_t * pAig, Vec_Ptr_t * vFanout, Vec_Ptr_t * vVisited )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrClear( vVisited );
+ Aig_ManIncrementTravId( pAig );
+ Vec_PtrForEachEntry( vFanout, pObj, i )
+ Cgt_ManCollectVisited_rec( pAig, pObj, vVisited );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Aig_Obj_t * Aig_ObjChild0CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj )
+{ return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId0(pObj)), Aig_ObjFaninC0(pObj)); }
+static inline Aig_Obj_t * Aig_ObjChild1CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj )
+{ return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId1(pObj)), Aig_ObjFaninC1(pObj)); }
+
+/**Function*************************************************************
+
Synopsis [Derives miter for clock-gating.]
Description []
@@ -145,15 +206,46 @@ void Cgt_ManDetectFanout( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_P
SeeAlso []
***********************************************************************/
-Aig_Obj_t * Cgt_ManConstructMiter( Cgt_Man_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObjLo )
+Aig_Obj_t * Cgt_ManConstructCareCondition( Cgt_Man_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObjLo, Vec_Ptr_t * vCopy0, Vec_Ptr_t * vCopy1 )
{
- Aig_Obj_t * pMiter, * pRoot;
+ Aig_Obj_t * pMiter, * pObj, * pTemp;
int i;
assert( Aig_ObjIsPi(pObjLo) );
- pMiter = Aig_ManConst0( pNew );
+ // detect nodes and their cone
Cgt_ManDetectFanout( p->pAig, pObjLo, p->pPars->nOdcMax, p->vFanout );
- Vec_PtrForEachEntry( p->vFanout, pRoot, i )
- pMiter = Aig_Or( pNew, pMiter, Aig_Exor(pNew, pRoot->pData, pRoot->pNext) );
+ Cgt_ManCollectVisited( p->pAig, p->vFanout, p->vVisited );
+ // add new variables if the observability condition depends on PI variables
+ Vec_PtrForEachEntry( p->vVisited, pObj, i )
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId0(pObj)) == NULL )
+ {
+ pTemp = Aig_ObjCreatePi( pNew );
+ Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId0(pObj), pTemp );
+ Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId0(pObj), pTemp );
+ }
+ if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin1(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId1(pObj)) == NULL )
+ {
+ pTemp = Aig_ObjCreatePi( pNew );
+ Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId1(pObj), pTemp );
+ Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId1(pObj), pTemp );
+ }
+ }
+ // construct AIGs for the nodes
+ Vec_PtrForEachEntry( p->vVisited, pObj, i )
+ {
+ pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy0, pObj), Aig_ObjChild1CopyVec(vCopy0, pObj) );
+ Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObj), pTemp );
+ pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy1, pObj), Aig_ObjChild1CopyVec(vCopy1, pObj) );
+ Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObj), pTemp );
+ }
+ // construct the care miter
+ pMiter = Aig_ManConst0( pNew );
+ Vec_PtrForEachEntry( p->vFanout, pObj, i )
+ {
+ pTemp = Aig_Exor( pNew, Vec_PtrEntry(vCopy0, Aig_ObjId(pObj)), Vec_PtrEntry(vCopy1, Aig_ObjId(pObj)) );
+ pMiter = Aig_Or( pNew, pMiter, pTemp );
+ }
return pMiter;
}
@@ -171,11 +263,12 @@ Aig_Obj_t * Cgt_ManConstructMiter( Cgt_Man_t * p, Aig_Man_t * pNew, Aig_Obj_t *
Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p )
{
Aig_Man_t * pNew;
- Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pCare, * pMiter;
+ Vec_Ptr_t * vCopy0, * vCopy1;
int i;
assert( Aig_ManRegNum(p->pAig) );
- Aig_ManCleanNext( p->pAig );
pNew = Aig_ManStart( Aig_ManObjNumMax(p->pAig) );
+ pNew->pName = Aig_UtilStrsav( "CG_miter" );
// build the first frame
Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew);
Aig_ManForEachPi( p->pAig, pObj, i )
@@ -184,26 +277,128 @@ Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p )
pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
// Saig_ManForEachPo( p->pAig, pObj, i )
// pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
- // build the second frame
- Aig_ManConst1(p->pAig)->pNext = Aig_ManConst1(pNew);
- Saig_ManForEachPi( p->pAig, pObj, i )
- pObj->pNext = Aig_ObjCreatePi( pNew );
- Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
- pObjLo->pNext = Aig_ObjChild0Copy(pObjLi);
- Aig_ManForEachNode( p->pAig, pObj, i )
- if ( Aig_ObjLevel(pObj) <= p->pPars->nOdcMax )
- pObj->pNext = Aig_And( pNew, Aig_ObjChild0Next(pObj), Aig_ObjChild1Next(pObj) );
- // construct clock-gating miters for each register input
- Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
- pObjLi->pData = Aig_ObjCreatePo( pNew, Cgt_ManConstructMiter(p, pNew, pObjLo) );
- Aig_ManCleanNext( p->pAig );
- Aig_ManSetPioNumbers( p->pAig );
+ if ( p->pPars->nOdcMax > 0 )
+ {
+ // create storage for observability conditions
+ vCopy0 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) );
+ vCopy1 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) );
+ // initialize register outputs
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ {
+ Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
+ Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
+ }
+ // compute observability condition for each latch output
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ {
+ // set the constants
+ Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ManConst0(pNew) );
+ Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ManConst1(pNew) );
+ // compute condition
+ pCare = Cgt_ManConstructCareCondition( p, pNew, pObjLo, vCopy0, vCopy1 );
+ // restore the values
+ Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
+ Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
+ // compute the miter
+ pMiter = Aig_Exor( pNew, pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
+ pMiter = Aig_And( pNew, pMiter, pCare );
+ pObjLi->pData = Aig_ObjCreatePo( pNew, pMiter );
+ }
+ Vec_PtrFree( vCopy0 );
+ Vec_PtrFree( vCopy1 );
+ }
+ else
+ {
+ // construct clock-gating miters for each register input
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ {
+ pMiter = Aig_Exor( pNew, pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
+ pObjLi->pData = Aig_ObjCreatePo( pNew, pMiter );
+ }
+ }
Aig_ManCleanup( pNew );
+ Aig_ManSetPioNumbers( pNew );
return pNew;
}
/**Function*************************************************************
+ Synopsis [Adds relevant constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Cgt_ManConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pNew )
+{
+ Aig_Obj_t * pObj0, * pObj1;
+ if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) )
+ return pObj->pData;
+ Aig_ObjSetTravIdCurrent( pCare, pObj );
+ if ( Aig_ObjIsPi(pObj) )
+ return pObj->pData = NULL;
+ pObj0 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pNew );
+ if ( pObj0 == NULL )
+ return pObj->pData = NULL;
+ pObj1 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pNew );
+ if ( pObj1 == NULL )
+ return pObj->pData = NULL;
+ pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) );
+ pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) );
+ return pObj->pData = Aig_And( pNew, pObj0, pObj1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Builds constraints belonging to the given partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cgt_ManConstructCare( Aig_Man_t * pNew, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, Vec_Ptr_t * vLeaves )
+{
+ Vec_Int_t * vOuts;
+ Aig_Obj_t * pLeaf, * pPi, * pPo, * pObjAig;
+ int i, k, iOut;
+ // go through the PIs of the partition
+ // label the corresponding PIs of the care set
+ Aig_ManIncrementTravId( pCare );
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ {
+ pPi = Aig_ManPi( pCare, Aig_ObjPioNum(pLeaf) );
+ Aig_ObjSetTravIdCurrent( pCare, pPi );
+ pPi->pData = pLeaf->pData;
+ }
+ // construct the constraints
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ {
+ vOuts = Vec_VecEntry( vSuppsInv, Aig_ObjPioNum(pLeaf) );
+ Vec_IntForEachEntry( vOuts, iOut, k )
+ {
+ pPo = Aig_ManPo( pCare, iOut );
+ if ( Aig_ObjIsTravIdCurrent( pCare, pPo ) )
+ continue;
+ Aig_ObjSetTravIdCurrent( pCare, pPo );
+ if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(pCare) )
+ continue;
+ pObjAig = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pPo), pNew );
+ if ( pObjAig == NULL )
+ continue;
+ pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) );
+ Aig_ObjCreatePo( pNew, pObjAig );
+ }
+ }
+}
+
+/**Function*************************************************************
+
Synopsis [Duplicates the AIG recursively.]
Description []
@@ -213,15 +408,19 @@ Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p )
SeeAlso []
***********************************************************************/
-Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj )
+Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vLeaves )
{
if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
return pObj->pData;
Aig_ObjSetTravIdCurrent(pAig, pObj);
if ( Aig_ObjIsPi(pObj) )
- return pObj->pData = Aig_ObjCreatePi( pNew );
- Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj) );
- Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin1(pObj) );
+ {
+ pObj->pData = Aig_ObjCreatePi( pNew );
+ Vec_PtrPush( vLeaves, pObj );
+ return pObj->pData;
+ }
+ Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj), vLeaves );
+ Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin1(pObj), vLeaves );
return pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
}
@@ -236,34 +435,80 @@ Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj
SeeAlso []
***********************************************************************/
-Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pAig, int nVarsMin, int nFlopsMin, int iStart )
+Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pFrame, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs )
{
+ Vec_Ptr_t * vRoots, * vLeaves, * vPos;
Aig_Man_t * pNew;
Aig_Obj_t * pObj;
int i;
- assert( Aig_ManRegNum(pAig) == 0 );
+ assert( Aig_ManRegNum(pFrame) == 0 );
+ vRoots = Vec_PtrAlloc( 100 );
+ vLeaves = Vec_PtrAlloc( 100 );
+ vPos = Vec_PtrAlloc( 100 );
pNew = Aig_ManStart( nVarsMin );
- Aig_ManIncrementTravId( pAig );
- Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew);
- Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
- for ( i = iStart; i < iStart + nFlopsMin && i < Aig_ManPoNum(pAig); i++ )
+ pNew->pName = Aig_UtilStrsav( "partition" );
+ Aig_ManIncrementTravId( pFrame );
+ Aig_ManConst1(pFrame)->pData = Aig_ManConst1(pNew);
+ Aig_ObjSetTravIdCurrent( pFrame, Aig_ManConst1(pFrame) );
+ for ( i = iStart; i < iStart + nFlopsMin && i < Aig_ManPoNum(pFrame); i++ )
{
- pObj = Aig_ManPo( pAig, i );
- Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj) );
- pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
+ pObj = Aig_ManPo( pFrame, i );
+ Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves );
+ Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) );
+ Vec_PtrPush( vPos, pObj );
}
- for ( ; Aig_ManObjNum(pNew) < nVarsMin && i < Aig_ManPoNum(pAig); i++ )
+ for ( ; Aig_ManObjNum(pNew) < nVarsMin && i < Aig_ManPoNum(pFrame); i++ )
{
- pObj = Aig_ManPo( pAig, i );
- Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj) );
- pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
+ pObj = Aig_ManPo( pFrame, i );
+ Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves );
+ Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) );
+ Vec_PtrPush( vPos, pObj );
}
- assert( nFlopsMin >= Aig_ManPoNum(pAig) || Aig_ManPoNum(pNew) >= nFlopsMin );
+ assert( nFlopsMin >= Vec_PtrSize(vRoots) || Vec_PtrSize(vRoots) >= nFlopsMin );
+ // create constaints
+ if ( pCare )
+ Cgt_ManConstructCare( pNew, pCare, vSuppsInv, vLeaves );
+ // create POs
+ Vec_PtrForEachEntry( vPos, pObj, i )
+ pObj->pData = Aig_ObjCreatePo( pNew, Vec_PtrEntry(vRoots, i) );
+ if ( pnOutputs != NULL )
+ *pnOutputs = Vec_PtrSize( vPos );
+ Vec_PtrFree( vRoots );
+ Vec_PtrFree( vLeaves );
+ Vec_PtrFree( vPos );
return pNew;
}
/**Function*************************************************************
+ Synopsis [Implements one clock-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Cgt_ManBuildClockGate( Aig_Man_t * pNew, Vec_Ptr_t * vGates )
+{
+ Aig_Obj_t * pGate, * pTotal;
+ int i;
+ assert( Vec_PtrSize(vGates) > 0 );
+ pTotal = Aig_ManConst0(pNew);
+ Vec_PtrForEachEntry( vGates, pGate, i )
+ {
+ if ( Aig_Regular(pGate)->pNext )
+ pGate = Aig_NotCond( Aig_Regular(pGate)->pNext, Aig_IsComplement(pGate) );
+ else
+ pGate = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) );
+ pTotal = Aig_Or( pNew, pTotal, pGate );
+ }
+ return pTotal;
+}
+
+/**Function*************************************************************
+
Synopsis [Derives AIG after clock-gating.]
Description [The array contains, for each flop, its gate if present.]
@@ -273,34 +518,74 @@ Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pAig, int nVarsMin, int nFlopsMin,
SeeAlso []
***********************************************************************/
-Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Ptr_t * vGates )
+Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes )
{
Aig_Man_t * pNew;
- Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo, * pGate, * pGateNew;
- int i;
+ Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo, * pGateNew;
+ Vec_Ptr_t * vOne;
+ int i, k;
+ Aig_ManCleanNext( pAig );
+ // label nodes
+ Vec_VecForEachEntry( vGates, pObj, i, k )
+ {
+ if ( Aig_IsComplement(pObj) )
+ Aig_Regular(pObj)->fMarkB = 1;
+ else
+ Aig_Regular(pObj)->fMarkA = 1;
+ }
+ // construct AIG
assert( Aig_ManRegNum(pAig) );
pNew = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+ pNew->pName = Aig_UtilStrsav( pAig->pName );
+ pNew->pSpec = Aig_UtilStrsav( pAig->pSpec );
Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew);
Aig_ManForEachPi( pAig, pObj, i )
pObj->pData = Aig_ObjCreatePi( pNew );
- Aig_ManForEachNode( pAig, pObj, i )
- pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ if ( fReduce )
+ {
+ Aig_ManForEachNode( pAig, pObj, i )
+ {
+ assert( !(pObj->fMarkA && pObj->fMarkB) );
+ pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ if ( pObj->fMarkA )
+ {
+ pObj->pNext = pObj->pData;
+ pObj->pData = Aig_ManConst0(pNew);
+ }
+ else if ( pObj->fMarkB )
+ {
+ pObj->pNext = pObj->pData;
+ pObj->pData = Aig_ManConst1(pNew);
+ }
+ }
+ }
+ else
+ {
+ Aig_ManForEachNode( pAig, pObj, i )
+ pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ }
+ if ( pnUsedNodes != NULL )
+ *pnUsedNodes = Aig_ManNodeNum(pNew);
Saig_ManForEachPo( pAig, pObj, i )
pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
{
- pGate = Vec_PtrEntry( vGates, i );
- if ( pGate == NULL )
+ vOne = Vec_VecEntry( vGates, i );
+ if ( Vec_PtrSize(vOne) == 0 )
pObjNew = Aig_ObjChild0Copy(pObjLi);
else
{
- pGateNew = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) );
+// pGateNew = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) );
+ pGateNew = Cgt_ManBuildClockGate( pNew, vOne );
pObjNew = Aig_Mux( pNew, pGateNew, pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
}
pObjLi->pData = Aig_ObjCreatePo( pNew, pObjNew );
}
Aig_ManCleanup( pNew );
Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) );
+ // unlabel nodes
+ Aig_ManCleanMarkAB( pAig );
+ Aig_ManCleanNext( pAig );
return pNew;
}
diff --git a/src/aig/cgt/cgtCore.c b/src/aig/cgt/cgtCore.c
index a06820b4..f49cd46f 100644
--- a/src/aig/cgt/cgtCore.c
+++ b/src/aig/cgt/cgtCore.c
@@ -19,6 +19,7 @@
***********************************************************************/
#include "cgtInt.h"
+#include "bar.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -42,13 +43,14 @@
void Cgt_SetDefaultParams( Cgt_Par_t * p )
{
memset( p, 0, sizeof(Cgt_Par_t) );
- p->nLevelMax = 1000; // the max number of levels to look for clock-gates
+ p->nLevelMax = 25; // the max number of levels to look for clock-gates
p->nCandMax = 1000; // the max number of candidates at each node
p->nOdcMax = 0; // the max number of ODC levels to consider
- p->nConfMax = 1000; // the max number of conflicts at a node
- p->nVarsMin = 5000; // the min number of vars to recycle the SAT solver
- p->nFlopsMin = 25; // the min number of flops to recycle the SAT solver
- p->fVerbose = 0; // verbosity flag
+ p->nConfMax = 10; // the max number of conflicts at a node
+ p->nVarsMin = 1000; // the min number of vars to recycle the SAT solver
+ p->nFlopsMin = 5; // the min number of flops to recycle the SAT solver
+ p->fAreaOnly = 0; // derive clock-gating to minimize area
+ p->fVerbose = 1; // verbosity flag
}
/**Function*************************************************************
@@ -62,14 +64,14 @@ void Cgt_SetDefaultParams( Cgt_Par_t * p )
SeeAlso []
***********************************************************************/
-int Cgt_SimulationFilter( Cgt_Man_t * p, Aig_Obj_t * pCandFrame, Aig_Obj_t * pMiterFrame )
+int Cgt_SimulationFilter( Cgt_Man_t * p, Aig_Obj_t * pCandPart, Aig_Obj_t * pMiterPart )
{
unsigned * pInfoCand, * pInfoMiter;
int w, nWords = Aig_BitWordNum( p->nPatts );
- pInfoCand = Vec_PtrEntry( p->vPatts, Aig_ObjId(Aig_Regular(pCandFrame)) );
- pInfoMiter = Vec_PtrEntry( p->vPatts, Aig_ObjId(pMiterFrame) );
+ pInfoCand = Vec_PtrEntry( p->vPatts, Aig_ObjId(Aig_Regular(pCandPart)) );
+ pInfoMiter = Vec_PtrEntry( p->vPatts, Aig_ObjId(pMiterPart) );
// C => !M -- true is the same as C & M -- false
- if ( !Aig_IsComplement(pCandFrame) )
+ if ( !Aig_IsComplement(pCandPart) )
{
for ( w = 0; w < nWords; w++ )
if ( pInfoCand[w] & pInfoMiter[w] )
@@ -106,6 +108,7 @@ void Cgt_SimulationRecord( Cgt_Man_t * p )
if ( p->nPatts == 32 * p->nPattWords )
{
Vec_PtrReallocSimInfo( p->vPatts );
+ Vec_PtrCleanSimInfo( p->vPatts, p->nPattWords, 2 * p->nPattWords );
p->nPattWords *= 2;
}
}
@@ -121,15 +124,16 @@ void Cgt_SimulationRecord( Cgt_Man_t * p )
SeeAlso []
***********************************************************************/
-void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart )
+void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart, int nOutputs )
{
Vec_Ptr_t * vNodes = p->vFanout;
Aig_Obj_t * pMiter, * pCand, * pMiterFrame, * pCandFrame, * pMiterPart, * pCandPart;
- int i, k, RetValue;
+ int i, k, RetValue, nCalls;
assert( Vec_VecSize(p->vGatesAll) == Aig_ManPoNum(p->pFrame) );
// go through all the registers inputs of this range
- for ( i = iStart; i < iStart + Aig_ManPoNum(p->pPart); i++ )
+ for ( i = iStart; i < iStart + nOutputs; i++ )
{
+ nCalls = p->nCalls;
pMiter = Saig_ManLi( p->pAig, i );
Cgt_ManDetectCandidates( p->pAig, Aig_ObjFanin0(pMiter), p->pPars->nLevelMax, vNodes );
// go through the candidates of this PO
@@ -153,6 +157,8 @@ void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart )
if ( RetValue == 0 )
Cgt_SimulationRecord( p );
}
+ else
+ p->nCallsFiltered++;
// try reverse polarity
if ( Cgt_SimulationFilter( p, Aig_Not(pCandPart), pMiterPart ) )
{
@@ -165,9 +171,18 @@ void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart )
if ( RetValue == 0 )
Cgt_SimulationRecord( p );
}
+ else
+ p->nCallsFiltered++;
}
+
+ if ( p->pPars->fVerbose )
+ {
+// printf( "Flop %3d : Cand = %4d. Gate = %4d. SAT calls = %3d.\n",
+// i, Vec_PtrSize(vNodes), Vec_PtrSize(Vec_VecEntry(p->vGatesAll, i)), p->nCalls-nCalls );
+ }
+
}
-}
+}
/**Function*************************************************************
@@ -182,16 +197,33 @@ void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart )
***********************************************************************/
int Cgt_ClockGatingRange( Cgt_Man_t * p, int iStart )
{
- int iStop;
- p->pPart = Cgt_ManDupPartition( p->pFrame, p->pPars->nVarsMin, p->pPars->nFlopsMin, iStart );
- p->pCnf = Cnf_DeriveSimple( p->pPart, Aig_ManPoNum(p->pPart) );
+ int nOutputs, iStop, clk, clkTotal = clock();
+ int nCallsUnsat = p->nCallsUnsat;
+ int nCallsSat = p->nCallsSat;
+ int nCallsUndec = p->nCallsUndec;
+ int nCallsFiltered = p->nCallsFiltered;
+clk = clock();
+ p->pPart = Cgt_ManDupPartition( p->pFrame, p->pPars->nVarsMin, p->pPars->nFlopsMin, iStart, p->pCare, p->vSuppsInv, &nOutputs );
+ p->pCnf = Cnf_DeriveSimple( p->pPart, nOutputs );
p->pSat = Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 );
sat_solver_compress( p->pSat );
- p->vPatts = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pPart), 16 );
+ p->vPatts = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pPart), p->nPattWords );
Vec_PtrCleanSimInfo( p->vPatts, 0, p->nPattWords );
- Cgt_ClockGatingRangeCheck( p, iStart );
- iStop = iStart + Aig_ManPoNum(p->pPart);
+p->timePrepare += clock() - clk;
+ Cgt_ClockGatingRangeCheck( p, iStart, nOutputs );
+ iStop = iStart + nOutputs;
+ if ( p->pPars->fVeryVerbose )
+ {
+ printf( "%5d : D =%4d. C =%5d. Var =%6d. Pr =%5d. Cex =%5d. F =%4d. Saved =%6d. ",
+ iStart, iStop-iStart, Aig_ManPoNum(p->pPart)-nOutputs, p->pSat->size,
+ p->nCallsUnsat-nCallsUnsat,
+ p->nCallsSat -nCallsSat,
+ p->nCallsUndec-nCallsUndec,
+ p->nCallsFiltered-nCallsFiltered );
+ PRT( "Time", clock() - clkTotal );
+ }
Cgt_ManClean( p );
+ p->nRecycles++;
return iStop;
}
@@ -208,18 +240,30 @@ int Cgt_ClockGatingRange( Cgt_Man_t * p, int iStart )
***********************************************************************/
Vec_Vec_t * Cgt_ClockGatingCandidates( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars )
{
- Cgt_Par_t Pars;
+ Bar_Progress_t * pProgress = NULL;
+ Cgt_Par_t Pars;
Cgt_Man_t * p;
Vec_Vec_t * vGatesAll;
- int iStart;
+ int iStart, clk = clock(), clkTotal = clock();
+ // reset random numbers
+ Aig_ManRandom( 1 );
if ( pPars == NULL )
Cgt_SetDefaultParams( pPars = &Pars );
p = Cgt_ManCreate( pAig, pCare, pPars );
p->pFrame = Cgt_ManDeriveAigForGating( p );
+p->timeAig += clock() - clk;
assert( Aig_ManPoNum(p->pFrame) == Saig_ManRegNum(p->pAig) );
+ pProgress = Bar_ProgressStart( stdout, Aig_ManPoNum(p->pFrame) );
for ( iStart = 0; iStart < Aig_ManPoNum(p->pFrame); )
+ {
+ Bar_ProgressUpdate( pProgress, iStart, NULL );
iStart = Cgt_ClockGatingRange( p, iStart );
+ }
+ Bar_ProgressStop( pProgress );
vGatesAll = p->vGatesAll;
+ p->vGatesAll = NULL;
+p->timeTotal = clock() - clkTotal;
+ Cgt_ManStop( p );
return vGatesAll;
}
@@ -238,11 +282,29 @@ Aig_Man_t * Cgt_ClockGating( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pP
{
Aig_Man_t * pGated;
Vec_Vec_t * vGatesAll;
- Vec_Ptr_t * vGates;
+ Vec_Vec_t * vGates;
+ int nNodesUsed, clk = clock();
vGatesAll = Cgt_ClockGatingCandidates( pAig, pCare, pPars );
- vGates = Cgt_ManDecideSimple( pAig, vGatesAll );
- pGated = Cgt_ManDeriveGatedAig( pAig, vGates );
- Vec_PtrFree( vGates );
+ if ( pPars->fAreaOnly )
+ vGates = Cgt_ManDecideArea( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose );
+ else
+ vGates = Cgt_ManDecideSimple( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose );
+ if ( pPars->fVerbose )
+ {
+// printf( "Before CG: " );
+// Aig_ManPrintStats( pAig );
+ }
+ pGated = Cgt_ManDeriveGatedAig( pAig, vGates, pPars->fAreaOnly, &nNodesUsed );
+ if ( pPars->fVerbose )
+ {
+// printf( "After CG: " );
+// Aig_ManPrintStats( pGated );
+ printf( "Nodes: Before CG = %6d. After CG = %6d. (%6.2f %%). Total after CG = %6d.\n",
+ Aig_ManNodeNum(pAig), nNodesUsed,
+ 100.0*nNodesUsed/Aig_ManNodeNum(pAig),
+ Aig_ManNodeNum(pGated) );
+ }
+ Vec_VecFree( vGates );
Vec_VecFree( vGatesAll );
return pGated;
}
diff --git a/src/aig/cgt/cgtDecide.c b/src/aig/cgt/cgtDecide.c
index 8f57bd4a..0fb2a681 100644
--- a/src/aig/cgt/cgtDecide.c
+++ b/src/aig/cgt/cgtDecide.c
@@ -25,8 +25,11 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-extern int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand );
extern int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand );
+extern int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand );
+extern int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo );
+extern int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj );
+extern int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
@@ -34,7 +37,7 @@ extern int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Ob
/**Function*************************************************************
- Synopsis [Chooses what clock-gate to use for each register.]
+ Synopsis [Collects POs in the transitive fanout.]
Description []
@@ -43,11 +46,127 @@ extern int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Ob
SeeAlso []
***********************************************************************/
-Vec_Ptr_t * Cgt_ManDecide( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll )
+void Cgt_ManCollectFanoutPos_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout )
+{
+ Aig_Obj_t * pFanout;
+ int f, iFanout;
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(pAig, pObj);
+ if ( Aig_ObjIsPo(pObj) )
+ {
+ Vec_PtrPush( vFanout, pObj );
+ return;
+ }
+ Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f )
+ Cgt_ManCollectFanoutPos_rec( pAig, pFanout, vFanout );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects POs in the transitive fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cgt_ManCollectFanoutPos( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout )
+{
+ Vec_PtrClear( vFanout );
+ Aig_ManIncrementTravId( pAig );
+ Cgt_ManCollectFanoutPos_rec( pAig, pObj, vFanout );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if all PO fanouts can be gated by this node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cgt_ManCheckGateComplete( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, Aig_Obj_t * pGate, Vec_Ptr_t * vFanout )
{
Vec_Ptr_t * vGates;
- vGates = Vec_PtrStart( Saig_ManRegNum(pAig) );
- return vGates;
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( vFanout, pObj, i )
+ {
+ if ( Saig_ObjIsPo(pAig, pObj) )
+ return 0;
+ vGates = Vec_VecEntry( vGatesAll, Aig_ObjPioNum(pObj) - Saig_ManPoNum(pAig) );
+ if ( Vec_PtrFind( vGates, pGate ) == -1 )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the set of complete clock gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Cgt_ManCompleteGates( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose )
+{
+ Vec_Ptr_t * vFanout, * vGatesFull;
+ Aig_Obj_t * pGate, * pGateR;
+ int i, k;
+ vFanout = Vec_PtrAlloc( 100 );
+ vGatesFull = Vec_PtrAlloc( 100 );
+ Vec_VecForEachEntry( vGatesAll, pGate, i, k )
+ {
+ pGateR = Aig_Regular(pGate);
+ if ( pGateR->fMarkA )
+ continue;
+ pGateR->fMarkA = 1;
+ Cgt_ManCollectFanoutPos( pAig, pGateR, vFanout );
+ if ( Cgt_ManCheckGateComplete( pAig, vGatesAll, pGate, vFanout ) )
+ Vec_PtrPush( vGatesFull, pGate );
+ }
+ Vec_PtrFree( vFanout );
+ Vec_VecForEachEntry( vGatesAll, pGate, i, k )
+ Aig_Regular(pGate)->fMarkA = 0;
+ return vGatesFull;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Calculates coverage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Cgt_ManComputeCoverage( Aig_Man_t * pAig, Vec_Vec_t * vGates )
+{
+ int nFrames = 32;
+ int nWords = 1;
+ Ssw_Sml_t * pSml;
+ Vec_Ptr_t * vOne;
+ int i, nTransTotal = 0, nTransSaved = 0;
+ pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords );
+ Vec_VecForEachLevel( vGates, vOne, i )
+ {
+ nTransSaved += Ssw_SmlNodeCountOnesRealVec( pSml, vOne );
+ nTransTotal += 32 * nFrames * nWords;
+ }
+ Ssw_SmlStop( pSml );
+ return (float)100.0*nTransSaved/nTransTotal;
}
/**Function*************************************************************
@@ -62,14 +181,18 @@ Vec_Ptr_t * Cgt_ManDecide( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll )
SeeAlso []
***********************************************************************/
-Vec_Ptr_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll )
+Vec_Vec_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose )
{
+ int nFrames = 32;
+ int nWords = 1;
Ssw_Sml_t * pSml;
- Vec_Ptr_t * vGates, * vCands;
+ Vec_Vec_t * vGates;
+ Vec_Ptr_t * vCands;
Aig_Obj_t * pObjLi, * pObjLo, * pCand, * pCandBest;
- int i, k, nHitsCur, nHitsMax;
- vGates = Vec_PtrStart( Saig_ManRegNum(pAig) );
- pSml = Ssw_SmlSimulateSeq( pAig, 0, 32, 1 );
+ int i, k, nHitsCur, nHitsMax, Counter = 0, clk = clock();
+ int nTransTotal = 0, nTransSaved = 0;
+ vGates = Vec_VecStart( Saig_ManRegNum(pAig) );
+ pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords );
Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
{
nHitsMax = 0;
@@ -78,10 +201,10 @@ Vec_Ptr_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll )
Vec_PtrForEachEntry( vCands, pCand, k )
{
// check if this is indeed a clock-gate
- if ( !Ssw_SmlCheckXorImplication( pSml, pObjLi, pObjLo, pCand ) )
+ if ( nOdcMax == 0 && !Ssw_SmlCheckXorImplication( pSml, pObjLi, pObjLo, pCand ) )
printf( "Clock gate candidate is invalid!\n" );
// find its characteristic number
- nHitsCur = Ssw_SmlCountXorImplication( pSml, pObjLi, pObjLo, pCand );
+ nHitsCur = Ssw_SmlNodeCountOnesReal( pSml, pCand );
if ( nHitsMax < nHitsCur )
{
nHitsMax = nHitsCur;
@@ -89,9 +212,80 @@ Vec_Ptr_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll )
}
}
if ( pCandBest != NULL )
- Vec_PtrWriteEntry( vGates, i, pCandBest );
+ {
+ Vec_VecPush( vGates, i, pCandBest );
+ Counter++;
+ nTransSaved += nHitsMax;
+ }
+ nTransTotal += 32 * nFrames * nWords;
}
Ssw_SmlStop( pSml );
+ if ( fVerbose )
+ {
+ printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n",
+ Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) );
+// printf( "Gated transitions = %5.2f %%. (%5.2f %%.) ",
+// 100.0*nTransSaved/nTransTotal, Cgt_ManComputeCoverage(pAig, vGates) );
+ printf( "Gated transitions = %5.2f %%. ", Cgt_ManComputeCoverage(pAig, vGates) );
+ PRT( "Time", clock() - clk );
+ }
+/*
+ {
+ Vec_Ptr_t * vCompletes;
+ vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose );
+ printf( "Complete gates = %d. \n", Vec_PtrSize(vCompletes) );
+ Vec_PtrFree( vCompletes );
+ }
+*/
+ return vGates;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the set of complete clock gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Vec_t * Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose )
+{
+ Vec_Vec_t * vGates;
+ Vec_Ptr_t * vCompletes, * vOne;
+ Aig_Obj_t * pGate;
+ int i, k, Counter = 0, clk = clock();
+ // derive and label complete gates
+ vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose );
+ // label complete gates
+ Vec_PtrForEachEntry( vCompletes, pGate, i )
+ Aig_Regular(pGate)->fMarkA = 1;
+ // select only complete gates
+ vGates = Vec_VecStart( Saig_ManRegNum(pAig) );
+ Vec_VecForEachEntry( vGatesAll, pGate, i, k )
+ if ( Aig_Regular(pGate)->fMarkA )
+ Vec_VecPush( vGates, i, pGate );
+ // unlabel complete gates
+ Vec_PtrForEachEntry( vCompletes, pGate, i )
+ Aig_Regular(pGate)->fMarkA = 0;
+ // count the number of gated flops
+ Vec_VecForEachLevel( vGates, vOne, i )
+ {
+ Counter += (int)(Vec_PtrSize(vOne) > 0);
+// printf( "%d ", Vec_PtrSize(vOne) );
+ }
+// printf( "\n" );
+ if ( fVerbose )
+ {
+ printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n",
+ Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) );
+ printf( "Complete gates = %6d. Gated transitions = %5.2f %%. ",
+ Vec_PtrSize(vCompletes), Cgt_ManComputeCoverage(pAig, vGates) );
+ PRT( "Time", clock() - clk );
+ }
+ Vec_PtrFree( vCompletes );
return vGates;
}
diff --git a/src/aig/cgt/cgtInt.h b/src/aig/cgt/cgtInt.h
index 7b4b6e63..23d851f3 100644
--- a/src/aig/cgt/cgtInt.h
+++ b/src/aig/cgt/cgtInt.h
@@ -48,12 +48,16 @@ struct Cgt_Man_t_
// user's data
Cgt_Par_t * pPars; // user's parameters
Aig_Man_t * pAig; // user's AIG manager
- Aig_Man_t * pCare; // user's constraints
+ // user's constraints
+ Aig_Man_t * pCare; // constraint cones
+ Vec_Vec_t * vSuppsInv; // inverse support of the constraints
+ // result of clock-gating
Vec_Vec_t * vGatesAll; // the computed clock-gates
Vec_Ptr_t * vGates; // the selected clock-gates
// internal data
Aig_Man_t * pFrame; // clock gate AIG manager
Vec_Ptr_t * vFanout; // temporary storage for fanouts
+ Vec_Ptr_t * vVisited; // temporary storage for visited nodes
// SAT solving
Aig_Man_t * pPart; // partition
Cnf_Dat_t * pCnf; // CNF of the partition
@@ -62,14 +66,21 @@ struct Cgt_Man_t_
int nPatts; // the number of patterns accumulated
int nPattWords; // the number of pattern words
// statistics
+ int nRecycles; // recycles
int nCalls; // total calls
int nCallsSat; // satisfiable calls
int nCallsUnsat; // unsatisfiable calls
int nCallsUndec; // undecided calls
+ int nCallsFiltered; // filtered out calls
+ int timeAig; // constructing AIG
+ int timePrepare; // partitioning and SAT solving
int timeSat; // total runtime
int timeSatSat; // satisfiable runtime
int timeSatUnsat; // unsatisfiable runtime
int timeSatUndec; // undecided runtime
+ int timeDecision; // making decision about what gates to use
+ int timeOther; // other runtime
+ int timeTotal; // total runtime
};
////////////////////////////////////////////////////////////////////////
@@ -83,11 +94,11 @@ struct Cgt_Man_t_
/*=== cgtAig.c ==========================================================*/
extern void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands );
extern Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p );
-extern Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pAig, int nVarsMin, int nFlopsMin, int iStart );
-extern Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Ptr_t * vGates );
+extern Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pAig, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs );
+extern Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes );
/*=== cgtDecide.c ==========================================================*/
-extern Vec_Ptr_t * Cgt_ManDecide( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll );
-extern Vec_Ptr_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll );
+extern Vec_Vec_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose );
+extern Vec_Vec_t * Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose );
/*=== cgtMan.c ==========================================================*/
extern Cgt_Man_t * Cgt_ManCreate( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars );
extern void Cgt_ManClean( Cgt_Man_t * p );
diff --git a/src/aig/cgt/cgtMan.c b/src/aig/cgt/cgtMan.c
index 9615d2e6..a3385228 100644
--- a/src/aig/cgt/cgtMan.c
+++ b/src/aig/cgt/cgtMan.c
@@ -53,7 +53,19 @@ Cgt_Man_t * Cgt_ManCreate( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPar
p->pAig = pAig;
p->vGatesAll = Vec_VecStart( Saig_ManRegNum(pAig) );
p->vFanout = Vec_PtrAlloc( 1000 );
+ p->vVisited = Vec_PtrAlloc( 1000 );
p->nPattWords = 16;
+ if ( pCare == NULL )
+ return p;
+ // check out the constraints
+ if ( Aig_ManPiNum(pCare) != Aig_ManPiNum(pAig) )
+ {
+ printf( "The PI count of care (%d) and AIG (%d) differ. Careset is not used.\n",
+ Aig_ManPiNum(pCare), Aig_ManPiNum(pAig) );
+ return p;
+ }
+ p->pCare = pCare;
+ p->vSuppsInv = (Vec_Vec_t *)Aig_ManSupportsInverse( p->pCare );
return p;
}
@@ -106,27 +118,16 @@ void Cgt_ManClean( Cgt_Man_t * p )
***********************************************************************/
void Cgt_ManPrintStats( Cgt_Man_t * p )
{
+ printf( "Params: LevMax = %d. CandMax = %d. OdcMax = %d. ConfMax = %d. VarMin = %d. FlopMin = %d.\n",
+ p->pPars->nLevelMax, p->pPars->nCandMax, p->pPars->nOdcMax,
+ p->pPars->nConfMax, p->pPars->nVarsMin, p->pPars->nFlopsMin );
+ printf( "SAT : Calls = %d. Unsat = %d. Sat = %d. Fails = %d. Recycles = %d. ",
+ p->nCalls, p->nCallsUnsat, p->nCallsSat, p->nCallsUndec, p->nRecycles );
+ PRT( "Time", p->timeTotal );
/*
- double nMemory = 1.0*Aig_ManObjNumMax(p->pAig)*p->nFrames*(2*sizeof(int)+2*sizeof(void*))/(1<<20);
-
- printf( "Parameters: F = %d. AddF = %d. C-lim = %d. Constr = %d. MaxLev = %d. Mem = %0.2f Mb.\n",
- p->pPars->nFramesK, p->pPars->nFramesAddSim, p->pPars->nBTLimit, p->pPars->nConstrs, p->pPars->nMaxLevs, nMemory );
- printf( "AIG : PI = %d. PO = %d. Latch = %d. Node = %d. Ave SAT vars = %d.\n",
- Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), Saig_ManRegNum(p->pAig), Aig_ManNodeNum(p->pAig),
- 0/p->pPars->nIters );
- printf( "SAT calls : Proof = %d. Cex = %d. Fail = %d. Lits proved = %d.\n",
- p->nSatProof, p->nSatCallsSat, p->nSatFailsReal, Cgt_ManCountEquivs(p) );
- printf( "SAT solver: Vars max = %d. Calls max = %d. Recycles = %d. Sim rounds = %d.\n",
- p->nVarsMax, p->nCallsMax, p->nRecyclesTotal, p->nSimRounds );
- printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n",
- p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/(p->nNodesBeg?p->nNodesBeg:1),
- p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/(p->nRegsBeg?p->nRegsBeg:1) );
-
- p->timeOther = p->timeTotal-p->timeBmc-p->timeReduce-p->timeMarkCones-p->timeSimSat-p->timeSat;
- PRTP( "BMC ", p->timeBmc, p->timeTotal );
- PRTP( "Spec reduce", p->timeReduce, p->timeTotal );
- PRTP( "Mark cones ", p->timeMarkCones, p->timeTotal );
- PRTP( "Sim SAT ", p->timeSimSat, p->timeTotal );
+ p->timeOther = p->timeTotal-p->timeAig-p->timePrepare-p->timeSat-p->timeDecision;
+ PRTP( "AIG ", p->timeAig, p->timeTotal );
+ PRTP( "Prepare ", p->timePrepare, p->timeTotal );
PRTP( "SAT solving", p->timeSat, p->timeTotal );
PRTP( " unsat ", p->timeSatUnsat, p->timeTotal );
PRTP( " sat ", p->timeSatSat, p->timeTotal );
@@ -155,8 +156,13 @@ void Cgt_ManStop( Cgt_Man_t * p )
Aig_ManStop( p->pFrame );
Cgt_ManClean( p );
Vec_PtrFree( p->vFanout );
- Vec_PtrFree( p->vGates );
- Vec_VecFree( p->vGatesAll );
+ Vec_PtrFree( p->vVisited );
+ if ( p->vGates )
+ Vec_PtrFree( p->vGates );
+ if ( p->vGatesAll )
+ Vec_VecFree( p->vGatesAll );
+ if ( p->vSuppsInv )
+ Vec_VecFree( p->vSuppsInv );
free( p );
}
diff --git a/src/aig/cnf/cnfWrite.c b/src/aig/cnf/cnfWrite.c
index 860c7e3e..8a6a9160 100644
--- a/src/aig/cnf/cnfWrite.c
+++ b/src/aig/cnf/cnfWrite.c
@@ -422,7 +422,7 @@ Cnf_Dat_t * Cnf_DeriveSimple( Aig_Man_t * p, int nOutputs )
OutVar = pCnf->pVarNums[ Aig_ManConst1(p)->Id ];
assert( OutVar <= Aig_ManObjNumMax(p) );
*pClas++ = pLits;
- *pLits++ = 2 * OutVar;
+ *pLits++ = 2 * OutVar;
// write the output literals
Aig_ManForEachPo( p, pObj, i )
diff --git a/src/aig/dar/dar.h b/src/aig/dar/dar.h
index 99c0276d..c2d53c89 100644
--- a/src/aig/dar/dar.h
+++ b/src/aig/dar/dar.h
@@ -47,6 +47,7 @@ struct Dar_RwrPar_t_
int fFanout; // support fanout representation
int fUpdateLevel; // update level
int fUseZeros; // performs zero-cost replacement
+ int fPower; // enables power-aware rewriting
int fVerbose; // enables verbose output
int fVeryVerbose; // enables very verbose output
};
@@ -92,8 +93,8 @@ extern int Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars )
/*=== darScript.c ========================================================*/
extern Aig_Man_t * Dar_ManRewriteDefault( Aig_Man_t * pAig );
extern Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose );
-extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose );
-extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fVerbose );
+extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose );
+extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose );
extern Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose );
#ifdef __cplusplus
diff --git a/src/aig/dar/darCore.c b/src/aig/dar/darCore.c
index 3916a0b0..957b4cc9 100644
--- a/src/aig/dar/darCore.c
+++ b/src/aig/dar/darCore.c
@@ -47,6 +47,7 @@ void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars )
pPars->fFanout = 1;
pPars->fUpdateLevel = 0;
pPars->fUseZeros = 0;
+ pPars->fPower = 0;
pPars->fVerbose = 0;
pPars->fVeryVerbose = 0;
}
@@ -64,6 +65,7 @@ void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars )
***********************************************************************/
int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars )
{
+ extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
Dar_Man_t * p;
// Bar_Progress_t * pProgress;
Dar_Cut_t * pCut;
@@ -74,6 +76,8 @@ int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars )
Dar_LibPrepare( pPars->nSubgMax );
// create rewriting manager
p = Dar_ManStart( pAig, pPars );
+ if ( pPars->fPower )
+ pAig->vProbs = Saig_ManComputeSwitchProbs( pAig, 48, 16, 1 );
// remove dangling nodes
Aig_ManCleanup( pAig );
// if updating levels is requested, start fanout and timing
@@ -182,6 +186,11 @@ p->timeOther = p->timeTotal - p->timeCuts - p->timeEval;
// Aig_ManVerifyReverseLevel( pAig );
Aig_ManStopReverseLevels( pAig );
}
+ if ( pAig->vProbs )
+ {
+ Vec_IntFree( pAig->vProbs );
+ pAig->vProbs = NULL;
+ }
// stop the rewriting manager
Dar_ManStop( p );
Aig_ManCheckPhase( pAig );
diff --git a/src/aig/dar/darLib.c b/src/aig/dar/darLib.c
index b3cf1438..24693df2 100644
--- a/src/aig/dar/darLib.c
+++ b/src/aig/dar/darLib.c
@@ -44,6 +44,7 @@ struct Dar_LibDat_t_ // library object data
Aig_Obj_t * pFunc; // the corresponding AIG node if it exists
int Level; // level of this node after it is constructured
int TravId; // traversal ID of the library object data
+ float dProb; // probability of the node being 1
unsigned char fMffc; // set to one if node is part of MFFC
unsigned char nLats[3]; // the number of latches on the input/output stem
};
@@ -698,6 +699,12 @@ int Dar_LibCutMatch( Dar_Man_t * p, Dar_Cut_t * pCut )
pFanin = Aig_NotCond(pFanin, ((uPhase >> i) & 1) );
s_DarLib->pDatas[i].pFunc = pFanin;
s_DarLib->pDatas[i].Level = Aig_Regular(pFanin)->Level;
+ // copy the propability of node being one
+ if ( p->pPars->fPower )
+ {
+ float Prob = Aig_Int2Float( Vec_IntEntry( p->pAig->vProbs, Aig_ObjId(Aig_Regular(pFanin)) ) );
+ s_DarLib->pDatas[i].dProb = Aig_IsComplement(pFanin)? 1.0-Prob : Prob;
+ }
}
p->nCutsGood++;
return 1;
@@ -716,14 +723,14 @@ int Dar_LibCutMatch( Dar_Man_t * p, Dar_Cut_t * pCut )
SeeAlso []
***********************************************************************/
-int Dar_LibCutMarkMffc( Aig_Man_t * p, Aig_Obj_t * pRoot, int nLeaves )
+int Dar_LibCutMarkMffc( Aig_Man_t * p, Aig_Obj_t * pRoot, int nLeaves, float * pPower )
{
int i, nNodes;
// mark the cut leaves
for ( i = 0; i < nLeaves; i++ )
Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs++;
// label MFFC with current ID
- nNodes = Aig_NodeMffsLabel( p, pRoot );
+ nNodes = Aig_NodeMffsLabel( p, pRoot, pPower );
// unmark the cut leaves
for ( i = 0; i < nLeaves; i++ )
Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs--;
@@ -821,10 +828,13 @@ void Dar_LibEvalAssignNums( Dar_Man_t * p, int Class, Aig_Obj_t * pRoot )
SeeAlso []
***********************************************************************/
-int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required )
+int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required, float * pPower )
{
+ float Power0, Power1;
Dar_LibDat_t * pData;
int Area;
+ if ( pPower )
+ *pPower = (float)0.0;
if ( pObj->fTerm )
return 0;
assert( pObj->Num > 3 );
@@ -838,12 +848,21 @@ int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required
pData->TravId = Out;
// this is a new node - get a bound on the area of its branches
nNodesSaved--;
- Area = Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out, nNodesSaved, Required+1 );
+ Area = Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out, nNodesSaved, Required+1, pPower? &Power0 : NULL );
if ( Area > nNodesSaved )
return 0xff;
- Area += Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out, nNodesSaved, Required+1 );
+ Area += Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out, nNodesSaved, Required+1, pPower? &Power1 : NULL );
if ( Area > nNodesSaved )
return 0xff;
+ if ( pPower )
+ {
+ Dar_LibDat_t * pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num;
+ Dar_LibDat_t * pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num;
+ pData->dProb = (pObj->fCompl0? 1.0 - pData0->dProb : pData0->dProb)*
+ (pObj->fCompl1? 1.0 - pData1->dProb : pData1->dProb);
+ *pPower = Power0 + 2.0 * pData0->dProb * (1.0 - pData0->dProb) +
+ Power1 + 2.0 * pData1->dProb * (1.0 - pData1->dProb);
+ }
return Area + 1;
}
@@ -861,6 +880,7 @@ int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required
void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required )
{
int fTraining = 0;
+ float PowerSaved, PowerAdded;
Dar_LibObj_t * pObj;
int Out, k, Class, nNodesSaved, nNodesAdded, nNodesGained, clk;
clk = clock();
@@ -870,7 +890,7 @@ void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Requir
if ( !Dar_LibCutMatch(p, pCut) )
return;
// mark MFFC of the node
- nNodesSaved = Dar_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves );
+ nNodesSaved = Dar_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves, p->pPars->fPower? &PowerSaved : NULL );
// evaluate the cut
Class = s_DarLib->pMap[pCut->uTruth];
Dar_LibEvalAssignNums( p, Class, pRoot );
@@ -882,8 +902,10 @@ void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Requir
pObj = Dar_LibObj(s_DarLib, s_DarLib->pSubgr0[Class][Out]);
if ( Aig_Regular(s_DarLib->pDatas[pObj->Num].pFunc) == pRoot )
continue;
- nNodesAdded = Dar_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required );
+ nNodesAdded = Dar_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required, p->pPars->fPower? &PowerAdded : NULL );
nNodesGained = nNodesSaved - nNodesAdded;
+ if ( p->pPars->fPower && PowerSaved < PowerAdded )
+ continue;
if ( fTraining && nNodesGained >= 0 )
Dar_LibIncrementScore( Class, Out, nNodesGained + 1 );
if ( nNodesGained < 0 || (nNodesGained == 0 && !p->pPars->fUseZeros) )
diff --git a/src/aig/dar/darRefact.c b/src/aig/dar/darRefact.c
index d19d48e4..ecf032be 100644
--- a/src/aig/dar/darRefact.c
+++ b/src/aig/dar/darRefact.c
@@ -235,7 +235,7 @@ int Dar_RefactTryGraph( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Ptr_t * vCut, K
{
pNode->pFunc = Vec_PtrEntry(vCut, i);
pNode->Level = Aig_Regular(pNode->pFunc)->Level;
- assert( Aig_Regular(pNode->pFunc)->Level < (1<<14)-1 );
+ assert( Aig_Regular(pNode->pFunc)->Level < (1<<24)-1 );
}
//printf( "Trying:\n" );
// compute the AIG size after adding the internal nodes
diff --git a/src/aig/dar/darScript.c b/src/aig/dar/darScript.c
index d82239f8..6df776e6 100644
--- a/src/aig/dar/darScript.c
+++ b/src/aig/dar/darScript.c
@@ -153,7 +153,7 @@ void Dar_ManHaigPrintStats( Aig_Man_t * pAig )
SeeAlso []
***********************************************************************/
-Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose )
+Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose )
//alias compress2 "b -l; rw -l; rwz -l; b -l; rwz -l; b -l"
{
Aig_Man_t * pTemp;
@@ -167,6 +167,8 @@ Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, i
pParsRwr->fUpdateLevel = fUpdateLevel;
pParsRef->fUpdateLevel = fUpdateLevel;
+ pParsRwr->fPower = fPower;
+
pParsRwr->fVerbose = 0;//fVerbose;
pParsRef->fVerbose = 0;//fVerbose;
@@ -224,7 +226,7 @@ Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, i
SeeAlso []
***********************************************************************/
-Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fVerbose )
+Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose )
//alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l"
{
Aig_Man_t * pTemp;
@@ -238,6 +240,7 @@ Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel,
pParsRwr->fUpdateLevel = fUpdateLevel;
pParsRef->fUpdateLevel = fUpdateLevel;
pParsRwr->fFanout = fFanout;
+ pParsRwr->fPower = fPower;
pParsRwr->fVerbose = 0;//fVerbose;
pParsRef->fVerbose = 0;//fVerbose;
@@ -329,7 +332,7 @@ Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel,
SeeAlso []
***********************************************************************/
-Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose )
+Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose )
//alias resyn "b; rw; rwz; b; rwz; b"
//alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b"
{
@@ -344,7 +347,7 @@ Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateL
Aig_ManForEachObj( pAig, pObj, i )
pObj->pHaig = pObj;
- pAig = Dar_ManCompress (pAig, fBalance, fUpdateLevel, fVerbose);
+ pAig = Dar_ManCompress(pAig, fBalance, fUpdateLevel, fPower, fVerbose);
Vec_PtrPush( vAigs, pAig );
//Aig_ManPrintStats( pAig );
@@ -354,7 +357,7 @@ Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateL
pObj->pHaig = pObj;
}
- pAig = Dar_ManCompress2(pAig, fBalance, fUpdateLevel, 1, fVerbose);
+ pAig = Dar_ManCompress2(pAig, fBalance, fUpdateLevel, 1, fPower, fVerbose);
Vec_PtrPush( vAigs, pAig );
//Aig_ManPrintStats( pAig );
@@ -384,7 +387,7 @@ Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int
clk = clock();
// vAigs = Dar_ManChoiceSynthesisExt();
- vAigs = Dar_ManChoiceSynthesis( pAig, fBalance, fUpdateLevel, fVerbose );
+ vAigs = Dar_ManChoiceSynthesis( pAig, fBalance, fUpdateLevel, 0, fVerbose );
// swap the first and last network
// this should lead to the primary choice being "better" because of synthesis
@@ -441,7 +444,7 @@ Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars )
clk = clock();
// vAigs = Dar_ManChoiceSynthesisExt();
- vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, fVerbose );
+ vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, fVerbose );
// swap the first and last network
// this should lead to the primary choice being "better" because of synthesis
diff --git a/src/aig/dch/dch.h b/src/aig/dch/dch.h
index f1718a78..d0092a5f 100644
--- a/src/aig/dch/dch.h
+++ b/src/aig/dch/dch.h
@@ -47,6 +47,7 @@ struct Dch_Pars_t_
int fSynthesis; // set to 1 to perform synthesis
int fPolarFlip; // uses polarity adjustment
int fSimulateTfo; // uses simulatin of TFO classes
+ int fPower; // uses power-aware rewriting
int fVerbose; // verbose stats
int timeSynth; // synthesis runtime
int nNodesAhead; // the lookahead in terms of nodes
diff --git a/src/aig/dch/dchCore.c b/src/aig/dch/dchCore.c
index 76813d1a..27c039cf 100644
--- a/src/aig/dch/dchCore.c
+++ b/src/aig/dch/dchCore.c
@@ -48,6 +48,7 @@ void Dch_ManSetDefaultParams( Dch_Pars_t * p )
p->fSynthesis = 1; // derives three snapshots
p->fPolarFlip = 1; // uses polarity adjustment
p->fSimulateTfo = 1; // simulate TFO
+ p->fPower = 0; // power-aware rewriting
p->fVerbose = 0; // verbose stats
p->nNodesAhead = 1000; // the lookahead in terms of nodes
p->nCallsRecycle = 100; // calls to perform before recycling SAT solver
diff --git a/src/aig/fra/fraSec.c b/src/aig/fra/fraSec.c
index ca73b17d..7545059f 100644
--- a/src/aig/fra/fraSec.c
+++ b/src/aig/fra/fraSec.c
@@ -404,7 +404,7 @@ clk = clock();
pNew = Aig_ManDupOrdered( pTemp = pNew );
Aig_ManStop( pTemp );
// pNew = Dar_ManRewriteDefault( pTemp = pNew );
- pNew = Dar_ManCompress2( pTemp = pNew, 1, 0, 1, 0 );
+ pNew = Dar_ManCompress2( pTemp = pNew, 1, 0, 1, 0, 0 );
Aig_ManStop( pTemp );
if ( pParSec->fVerbose )
{
diff --git a/src/aig/fsim/fsim.h b/src/aig/fsim/fsim.h
new file mode 100644
index 00000000..c890ff29
--- /dev/null
+++ b/src/aig/fsim/fsim.h
@@ -0,0 +1,97 @@
+/**CFile****************************************************************
+
+ FileName [fsim.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast sequential AIG simulator.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: fsim.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __FSIM_H__
+#define __FSIM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fsim_Man_t_ Fsim_Man_t;
+
+// simulation parameters
+typedef struct Fsim_ParSim_t_ Fsim_ParSim_t;
+struct Fsim_ParSim_t_
+{
+ // user-controlled parameters
+ int nWords; // the number of machine words
+ int nIters; // the number of timeframes
+ int TimeLimit; // time limit in seconds
+ int fCheckMiter; // check if miter outputs are non-zero
+ int fVerbose; // enables verbose output
+ // internal parameters
+ int fCompressAig; // compresses internal data
+};
+
+// switching estimation parameters
+typedef struct Fsim_ParSwitch_t_ Fsim_ParSwitch_t;
+struct Fsim_ParSwitch_t_
+{
+ // user-controlled parameters
+ int nWords; // the number of machine words
+ int nIters; // the number of timeframes
+ int nPref; // the number of first timeframes to skip
+ int nRandPiNum; // PI trans prob (0=1/2; 1=1/4; 2=1/8, etc)
+ int fProbOne; // collect probability of one
+ int fProbTrans; // collect probatility of switching
+ int fVerbose; // enables verbose output
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fsimCore.c ==========================================================*/
+extern void Fsim_ManSetDefaultParamsSim( Fsim_ParSim_t * p );
+extern void Fsim_ManSetDefaultParamsSwitch( Fsim_ParSwitch_t * p );
+/*=== fsimSim.c ==========================================================*/
+extern int Fsim_ManSimulate( Aig_Man_t * pAig, Fsim_ParSim_t * pPars );
+/*=== fsimSwitch.c ==========================================================*/
+extern Vec_Int_t * Fsim_ManSwitchSimulate( Aig_Man_t * pAig, Fsim_ParSwitch_t * pPars );
+/*=== fsimTsim.c ==========================================================*/
+extern Vec_Ptr_t * Fsim_ManTerSimulate( Aig_Man_t * pAig, int fVerbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/fsim/fsimCore.c b/src/aig/fsim/fsimCore.c
new file mode 100644
index 00000000..2a159cbe
--- /dev/null
+++ b/src/aig/fsim/fsimCore.c
@@ -0,0 +1,83 @@
+/**CFile****************************************************************
+
+ FileName [fsimCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast sequential AIG simulator.]
+
+ Synopsis [Core procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: fsimCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fsimInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fsim_ManSetDefaultParamsSim( Fsim_ParSim_t * p )
+{
+ memset( p, 0, sizeof(Fsim_ParSim_t) );
+ // user-controlled parameters
+ p->nWords = 8; // the number of machine words
+ p->nIters = 32; // the number of timeframes
+ p->TimeLimit = 60; // time limit in seconds
+ p->fCheckMiter = 0; // check if miter outputs are non-zero
+ p->fVerbose = 1; // enables verbose output
+ // internal parameters
+ p->fCompressAig = 0; // compresses internal data
+}
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fsim_ManSetDefaultParamsSwitch( Fsim_ParSwitch_t * p )
+{
+ memset( p, 0, sizeof(Fsim_ParSwitch_t) );
+ // user-controlled parameters
+ p->nWords = 1; // the number of machine words
+ p->nIters = 48; // the number of timeframes
+ p->nPref = 16; // the number of first timeframes to skip
+ p->nRandPiNum = 0; // PI trans prob (0=1/2; 1=1/4; 2=1/8, etc)
+ p->fProbOne = 1; // collect probability of one
+ p->fProbTrans = 1; // collect probatility of switching
+ p->fVerbose = 1; // enables verbose output
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/fsim/fsimFront.c b/src/aig/fsim/fsimFront.c
new file mode 100644
index 00000000..d40b1c6f
--- /dev/null
+++ b/src/aig/fsim/fsimFront.c
@@ -0,0 +1,364 @@
+/**CFile****************************************************************
+
+ FileName [fsimFront.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast sequential AIG simulator.]
+
+ Synopsis [Simulation frontier.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: fsimFront.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fsimInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManStoreNum( Fsim_Man_t * p, int Num )
+{
+ unsigned x = (unsigned)Num;
+ assert( Num >= 0 );
+ while ( x & ~0x7f )
+ {
+ *p->pDataCur++ = (x & 0x7f) | 0x80;
+ x >>= 7;
+ }
+ *p->pDataCur++ = x;
+ assert( p->pDataCur - p->pDataAig < p->nDataAig );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Fsim_ManRestoreNum( Fsim_Man_t * p )
+{
+ int ch, i, x = 0;
+ for ( i = 0; (ch = *p->pDataCur++) & 0x80; i++ )
+ x |= (ch & 0x7f) << (7 * i);
+ assert( p->pDataCur - p->pDataAig < p->nDataAig );
+ return x | (ch << (7 * i));
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManStoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj )
+{
+ if ( p->pDataAig2 )
+ {
+ *p->pDataCur2++ = pObj->iNode;
+ *p->pDataCur2++ = pObj->iFan0;
+ *p->pDataCur2++ = pObj->iFan1;
+ return;
+ }
+ if ( pObj->iFan0 && pObj->iFan1 ) // and
+ {
+ assert( pObj->iNode );
+ assert( pObj->iNode >= p->iNodePrev );
+ assert( (pObj->iNode << 1) > pObj->iFan0 );
+ assert( pObj->iFan0 > pObj->iFan1 );
+ Fsim_ManStoreNum( p, ((pObj->iNode - p->iNodePrev) << 2) | 3 );
+ Fsim_ManStoreNum( p, (pObj->iNode << 1) - pObj->iFan0 );
+ Fsim_ManStoreNum( p, pObj->iFan0 - pObj->iFan1 );
+ p->iNodePrev = pObj->iNode;
+ }
+ else if ( !pObj->iFan0 && !pObj->iFan1 ) // ci
+ {
+ assert( pObj->iNode );
+ assert( pObj->iNode >= p->iNodePrev );
+ Fsim_ManStoreNum( p, ((pObj->iNode - p->iNodePrev) << 2) | 1 );
+ p->iNodePrev = pObj->iNode;
+ }
+ else // if ( !pObj->iFan0 && pObj->iFan1 ) // co
+ {
+ assert( pObj->iNode == 0 );
+ assert( pObj->iFan0 != 0 );
+ assert( pObj->iFan1 == 0 );
+ assert( ((p->iNodePrev << 1) | 1) >= pObj->iFan0 );
+ Fsim_ManStoreNum( p, (((p->iNodePrev << 1) | 1) - pObj->iFan0) << 1 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Fsim_ManRestoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj )
+{
+ int iValue = Fsim_ManRestoreNum( p );
+ if ( (iValue & 3) == 3 ) // and
+ {
+ pObj->iNode = (iValue >> 2) + p->iNodePrev;
+ pObj->iFan0 = (pObj->iNode << 1) - Fsim_ManRestoreNum( p );
+ pObj->iFan1 = pObj->iFan0 - Fsim_ManRestoreNum( p );
+ p->iNodePrev = pObj->iNode;
+ }
+ else if ( (iValue & 3) == 1 ) // ci
+ {
+ pObj->iNode = (iValue >> 2) + p->iNodePrev;
+ pObj->iFan0 = 0;
+ pObj->iFan1 = 0;
+ p->iNodePrev = pObj->iNode;
+ }
+ else // if ( (iValue & 1) == 0 ) // co
+ {
+ pObj->iNode = 0;
+ pObj->iFan0 = ((p->iNodePrev << 1) | 1) - (iValue >> 1);
+ pObj->iFan1 = 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determine the frontier.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Fsim_ManFrontFindNext( Fsim_Man_t * p, char * pFront )
+{
+ assert( p->iNumber < (1 << 30) - p->nFront );
+ while ( 1 )
+ {
+ if ( p->iNumber % p->nFront == 0 )
+ p->iNumber++;
+ if ( pFront[p->iNumber % p->nFront] == 0 )
+ {
+ pFront[p->iNumber % p->nFront] = 1;
+ return p->iNumber;
+ }
+ p->iNumber++;
+ }
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the frontier.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fsim_ManVerifyFront( Fsim_Man_t * p )
+{
+ Fsim_Obj_t * pObj;
+ int * pFans0, * pFans1; // representation of fanins
+ int * pFrontToId; // mapping of nodes into frontier variables
+ int i, iVar0, iVar1;
+ pFans0 = ALLOC( int, p->nObjs );
+ pFans1 = ALLOC( int, p->nObjs );
+ pFans0[0] = pFans1[0] = 0;
+ pFans0[1] = pFans1[1] = 0;
+ pFrontToId = CALLOC( int, p->nFront );
+ if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) )
+ pFrontToId[1] = 1;
+ Fsim_ManForEachObj( p, pObj, i )
+ {
+ if ( pObj->iNode )
+ pFrontToId[pObj->iNode % p->nFront] = i;
+ iVar0 = Fsim_Lit2Var(pObj->iFan0);
+ iVar1 = Fsim_Lit2Var(pObj->iFan1);
+ pFans0[i] = Fsim_Var2Lit(pFrontToId[iVar0 % p->nFront], Fsim_LitIsCompl(pObj->iFan0));
+ pFans1[i] = Fsim_Var2Lit(pFrontToId[iVar1 % p->nFront], Fsim_LitIsCompl(pObj->iFan1));
+ }
+ for ( i = 0; i < p->nObjs; i++ )
+ {
+ assert( pFans0[i] == p->pFans0[i] );
+ assert( pFans1[i] == p->pFans1[i] );
+ }
+ free( pFrontToId );
+ free( pFans0 );
+ free( pFans1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determine the frontier.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fsim_ManFront( Fsim_Man_t * p, int fCompressAig )
+{
+ Fsim_Obj_t Obj, * pObj = &Obj;
+ char * pFront; // places used for the frontier
+ int * pIdToFront; // mapping of nodes into frontier places
+ int i, iVar0, iVar1, nCrossCut = 0, nCrossCutMax = 0;
+ // start the frontier
+ pFront = CALLOC( char, p->nFront );
+ pIdToFront = ALLOC( int, p->nObjs );
+ pIdToFront[0] = -1;
+ pIdToFront[1] = -1;
+ // add constant node
+ p->iNumber = 1;
+ if ( p->pRefs[1] )
+ {
+ pIdToFront[1] = Fsim_ManFrontFindNext( p, pFront );
+ nCrossCut = 1;
+ }
+ // allocate room for data
+ if ( fCompressAig )
+ {
+ p->nDataAig = p->nObjs * 6;
+ p->pDataAig = ALLOC( unsigned char, p->nDataAig );
+ p->pDataCur = p->pDataAig;
+ p->iNodePrev = 0;
+ }
+ else
+ {
+ p->pDataAig2 = ALLOC( int, 3 * p->nObjs );
+ p->pDataCur2 = p->pDataAig2 + 6;
+ }
+ // iterate through the objects
+ for ( i = 2; i < p->nObjs; i++ )
+ {
+ if ( p->pFans0[i] == 0 ) // ci
+ {
+ // store node
+ pIdToFront[i] = Fsim_ManFrontFindNext( p, pFront );
+ pObj->iNode = pIdToFront[i];
+ pObj->iFan0 = 0;
+ pObj->iFan1 = 0;
+ Fsim_ManStoreObj( p, pObj );
+ // handle CIs without fanout
+ if ( p->pRefs[i] == 0 )
+ {
+ pFront[pIdToFront[i] % p->nFront] = 0;
+ pIdToFront[i] = -1;
+ }
+ }
+ else if ( p->pFans1[i] == 0 ) // co
+ {
+ assert( p->pRefs[i] == 0 );
+ // get the fanin
+ iVar0 = Fsim_Lit2Var(p->pFans0[i]);
+ assert( pIdToFront[iVar0] > 0 );
+ // store node
+ pObj->iNode = 0;
+ pObj->iFan0 = Fsim_Var2Lit(pIdToFront[iVar0], Fsim_LitIsCompl(p->pFans0[i]));
+ pObj->iFan1 = 0;
+ Fsim_ManStoreObj( p, pObj );
+ // deref the fanin
+ if ( --p->pRefs[iVar0] == 0 )
+ {
+ pFront[pIdToFront[iVar0] % p->nFront] = 0;
+ pIdToFront[iVar0] = -1;
+ nCrossCut--;
+ }
+ }
+ else
+ {
+ // get the fanins
+ iVar0 = Fsim_Lit2Var(p->pFans0[i]);
+ assert( pIdToFront[iVar0] > 0 );
+ iVar1 = Fsim_Lit2Var(p->pFans1[i]);
+ assert( pIdToFront[iVar1] > 0 );
+ // store node
+ pIdToFront[i] = Fsim_ManFrontFindNext( p, pFront );
+ pObj->iNode = pIdToFront[i];
+ pObj->iFan0 = Fsim_Var2Lit(pIdToFront[iVar0], Fsim_LitIsCompl(p->pFans0[i]));
+ pObj->iFan1 = Fsim_Var2Lit(pIdToFront[iVar1], Fsim_LitIsCompl(p->pFans1[i]));
+ Fsim_ManStoreObj( p, pObj );
+ // deref the fanins
+ if ( --p->pRefs[iVar0] == 0 )
+ {
+ pFront[pIdToFront[iVar0] % p->nFront] = 0;
+ pIdToFront[iVar0] = -1;
+ nCrossCut--;
+ }
+ if ( --p->pRefs[iVar1] == 0 )
+ {
+ pFront[pIdToFront[iVar1] % p->nFront] = 0;
+ pIdToFront[iVar1] = -1;
+ nCrossCut--;
+ }
+ // handle nodes without fanout (choice nodes)
+ if ( p->pRefs[i] == 0 )
+ {
+ pFront[pIdToFront[i] % p->nFront] = 0;
+ pIdToFront[i] = -1;
+ }
+ }
+ if ( p->pRefs[i] )
+ if ( nCrossCutMax < ++nCrossCut )
+ nCrossCutMax = nCrossCut;
+ }
+ assert( p->pDataAig2 == NULL || p->pDataCur2 - p->pDataAig2 == (3 * p->nObjs) );
+ assert( nCrossCut == 0 );
+ assert( nCrossCutMax == p->nCrossCutMax );
+ for ( i = 0; i < p->nFront; i++ )
+ assert( pFront[i] == 0 );
+ free( pFront );
+ free( pIdToFront );
+// Fsim_ManVerifyFront( p );
+ FREE( p->pFans0 );
+ FREE( p->pFans1 );
+ FREE( p->pRefs );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/fsim/fsimInt.h b/src/aig/fsim/fsimInt.h
new file mode 100644
index 00000000..0944bf0c
--- /dev/null
+++ b/src/aig/fsim/fsimInt.h
@@ -0,0 +1,134 @@
+/**CFile****************************************************************
+
+ FileName [fsimInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast sequential AIG simulator.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: fsimInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __FSIM_INT_H__
+#define __FSIM_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "saig.h"
+#include "fsim.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+// simulation object
+typedef struct Fsim_Obj_t_ Fsim_Obj_t;
+struct Fsim_Obj_t_
+{
+ int iNode; // the node ID
+ int iFan0; // the first fanin
+ int iFan1; // the second fanin
+};
+
+// fast sequential simulation manager
+struct Fsim_Man_t_
+{
+ // parameters
+ Aig_Man_t * pAig; // the AIG to be used for simulation
+ int nWords; // the number of simulation words
+ // AIG representation
+ int nPis; // the number of primary inputs
+ int nPos; // the number of primary outputs
+ int nCis; // the number of combinational inputs
+ int nCos; // the number of combinational outputs
+ int nNodes; // the number of internal nodes
+ int nObjs; // nCis + nNodes + nCos + 2
+ int * pFans0; // fanin0 for all objects
+ int * pFans1; // fanin1 for all objects
+ int * pRefs; // reference counter for each node
+ int * pRefsCopy; // reference counter for each node
+ Vec_Int_t * vCis2Ids; // mapping of CIs into their PI ids
+ Vec_Int_t * vLos; // register outputs
+ Vec_Int_t * vLis; // register inputs
+ // cross-cut representation
+ int nCrossCut; // temporary cross-cut variable
+ int nCrossCutMax; // maximum cross-cut variable
+ int nFront; // the size of frontier
+ // derived AIG representation
+ int nDataAig; // the length of allocated data
+ unsigned char * pDataAig; // AIG representation
+ unsigned char * pDataCur; // AIG representation (current position)
+ int iNodePrev; // previous extracted value
+ int iNumber; // the number of the last object
+ Fsim_Obj_t Obj; // current object
+ // temporary AIG representation
+ int * pDataAig2; // temporary representation
+ int * pDataCur2; // AIG representation (current position)
+ // simulation information
+ unsigned * pDataSim; // simulation data
+ unsigned * pDataSimCis; // simulation data for CIs
+ unsigned * pDataSimCos; // simulation data for COs
+ // other information
+ int * pData1;
+ int * pData2;
+};
+
+static inline unsigned * Fsim_SimData( Fsim_Man_t * p, int i ) { return p->pDataSim + i * p->nWords; }
+static inline unsigned * Fsim_SimDataCi( Fsim_Man_t * p, int i ) { return p->pDataSimCis + i * p->nWords; }
+static inline unsigned * Fsim_SimDataCo( Fsim_Man_t * p, int i ) { return p->pDataSimCos + i * p->nWords; }
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Fsim_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; }
+static inline int Fsim_Lit2Var( int Lit ) { return Lit >> 1; }
+static inline int Fsim_LitIsCompl( int Lit ) { return Lit & 1; }
+static inline int Fsim_LitNot( int Lit ) { return Lit ^ 1; }
+static inline int Fsim_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); }
+static inline int Fsim_LitRegular( int Lit ) { return Lit & ~01; }
+
+#define Fsim_ManForEachObj( p, pObj, i )\
+ for ( i = 2, p->pDataCur = p->pDataAig, p->iNodePrev = 0, pObj = &p->Obj;\
+ i < p->nObjs && Fsim_ManRestoreObj( p, pObj ); i++ )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fsimFront.c ========================================================*/
+extern void Fsim_ManFront( Fsim_Man_t * p, int fCompressAig );
+/*=== fsimMan.c ==========================================================*/
+extern Fsim_Man_t * Fsim_ManCreate( Aig_Man_t * pAig );
+extern void Fsim_ManDelete( Fsim_Man_t * p );
+extern void Fsim_ManTest( Aig_Man_t * pAig );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/aig/fsim/fsimMan.c b/src/aig/fsim/fsimMan.c
new file mode 100644
index 00000000..f7a40f40
--- /dev/null
+++ b/src/aig/fsim/fsimMan.c
@@ -0,0 +1,207 @@
+/**CFile****************************************************************
+
+ FileName [fsimMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast sequential AIG simulator.]
+
+ Synopsis [Simulation manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: fsimMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fsimInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates fast simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fsim_ManCreate_rec( Fsim_Man_t * p, Aig_Obj_t * pObj )
+{
+ int iFan0, iFan1, iTemp;
+ assert( !Aig_IsComplement(pObj) );
+ if ( pObj->iData )
+ return pObj->iData;
+ assert( !Aig_ObjIsConst1(pObj) );
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ iFan0 = Fsim_ManCreate_rec( p, Aig_ObjFanin0(pObj) );
+ iFan1 = Fsim_ManCreate_rec( p, Aig_ObjFanin1(pObj) );
+ assert( iFan0 != iFan1 );
+ if ( --p->pRefs[iFan0] == 0 )
+ p->nCrossCut--;
+ iFan0 = Fsim_Var2Lit( iFan0, Aig_ObjFaninC0(pObj) );
+ if ( --p->pRefs[iFan1] == 0 )
+ p->nCrossCut--;
+ iFan1 = Fsim_Var2Lit( iFan1, Aig_ObjFaninC1(pObj) );
+ if ( p->pAig->pEquivs )
+ Fsim_ManCreate_rec( p, Aig_ObjEquiv(p->pAig, pObj) );
+ }
+ else if ( Aig_ObjIsPo(pObj) )
+ {
+ assert( Aig_ObjRefs(pObj) == 0 );
+ iFan0 = Fsim_ManCreate_rec( p, Aig_ObjFanin0(pObj) );
+ if ( --p->pRefs[iFan0] == 0 )
+ p->nCrossCut--;
+ iFan0 = Fsim_Var2Lit( iFan0, Aig_ObjFaninC0(pObj) );
+ iFan1 = 0;
+ }
+ else
+ {
+ iFan0 = iFan1 = 0;
+ Vec_IntPush( p->vCis2Ids, Aig_ObjPioNum(pObj) );
+ }
+ if ( iFan0 < iFan1 )
+ iTemp = iFan0, iFan0 = iFan1, iFan1 = iTemp;
+ p->pFans0[p->nObjs] = iFan0;
+ p->pFans1[p->nObjs] = iFan1;
+ p->pRefs[p->nObjs] = Aig_ObjRefs(pObj);
+ if ( p->pRefs[p->nObjs] )
+ if ( p->nCrossCutMax < ++p->nCrossCut )
+ p->nCrossCutMax = p->nCrossCut;
+ return pObj->iData = p->nObjs++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates fast simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fsim_Man_t * Fsim_ManCreate( Aig_Man_t * pAig )
+{
+ Fsim_Man_t * p;
+ Aig_Obj_t * pObj;
+ int i, nObjs;
+ Aig_ManCleanData( pAig );
+ p = (Fsim_Man_t *)ALLOC( Fsim_Man_t, 1 );
+ memset( p, 0, sizeof(Fsim_Man_t) );
+ p->pAig = pAig;
+ p->nPis = Saig_ManPiNum(pAig);
+ p->nPos = Saig_ManPoNum(pAig);
+ p->nCis = Aig_ManPiNum(pAig);
+ p->nCos = Aig_ManPoNum(pAig);
+ p->nNodes = Aig_ManNodeNum(pAig);
+ nObjs = p->nCis + p->nCos + p->nNodes + 2;
+ p->pFans0 = ALLOC( int, nObjs );
+ p->pFans1 = ALLOC( int, nObjs );
+ p->pRefs = ALLOC( int, nObjs );
+ p->vCis2Ids = Vec_IntAlloc( Aig_ManPiNum(pAig) );
+ // add objects (0=unused; 1=const1)
+ p->pFans0[0] = p->pFans1[0] = 0;
+ p->pFans0[1] = p->pFans1[1] = 0;
+ p->pRefs[0] = 0;
+ p->nObjs = 2;
+ pObj = Aig_ManConst1( pAig );
+ pObj->iData = 1;
+ p->pRefs[1] = Aig_ObjRefs(pObj);
+ if ( p->pRefs[1] )
+ p->nCrossCut = 1;
+ Aig_ManForEachPi( pAig, pObj, i )
+ if ( Aig_ObjRefs(pObj) == 0 )
+ Fsim_ManCreate_rec( p, pObj );
+ Aig_ManForEachPo( pAig, pObj, i )
+ Fsim_ManCreate_rec( p, pObj );
+ assert( Vec_IntSize(p->vCis2Ids) == Aig_ManPiNum(pAig) );
+ assert( p->nObjs == nObjs );
+ // check references
+ assert( p->nCrossCut == 0 );
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ assert( p->pRefs[pObj->iData] == 0 );
+ p->pRefs[pObj->iData] = Aig_ObjRefs(pObj);
+ }
+ // collect flop outputs
+ p->vLos = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+ Saig_ManForEachLo( pAig, pObj, i )
+ Vec_IntPush( p->vLos, pObj->iData );
+ // collect flop inputs
+ p->vLis = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+ Saig_ManForEachLi( pAig, pObj, i )
+ Vec_IntPush( p->vLis, pObj->iData );
+ // determine the frontier size
+ p->nFront = 1 + (int)(1.1 * p->nCrossCutMax);
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes fast simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fsim_ManDelete( Fsim_Man_t * p )
+{
+ Vec_IntFree( p->vCis2Ids );
+ Vec_IntFree( p->vLos );
+ Vec_IntFree( p->vLis );
+ FREE( p->pDataAig2 );
+ FREE( p->pDataAig );
+ FREE( p->pFans0 );
+ FREE( p->pFans1 );
+ FREE( p->pRefs );
+ FREE( p->pDataSim );
+ FREE( p->pDataSimCis );
+ FREE( p->pDataSimCos );
+ FREE( p->pData1 );
+ FREE( p->pData2 );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Testing procedure.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fsim_ManTest( Aig_Man_t * pAig )
+{
+ Fsim_Man_t * p;
+ p = Fsim_ManCreate( pAig );
+ Fsim_ManFront( p, 0 );
+ Fsim_ManDelete( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/fsim/fsimSim.c b/src/aig/fsim/fsimSim.c
new file mode 100644
index 00000000..320c06a9
--- /dev/null
+++ b/src/aig/fsim/fsimSim.c
@@ -0,0 +1,560 @@
+/**CFile****************************************************************
+
+ FileName [fsimSim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast sequential AIG simulator.]
+
+ Synopsis [Simulation procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: fsimSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fsimInt.h"
+#include "ssw.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSimInfoRandom( Fsim_Man_t * p, unsigned * pInfo )
+{
+ int w;
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = Aig_ManRandom( 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSimInfoZero( Fsim_Man_t * p, unsigned * pInfo )
+{
+ int w;
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns index of the first pattern that failed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Fsim_ManSimInfoIsZero( Fsim_Man_t * p, unsigned * pInfo )
+{
+ int w;
+ for ( w = p->nWords-1; w >= 0; w-- )
+ if ( pInfo[w] )
+ return 32*(w-1) + Aig_WordFindFirstBit( pInfo[w] );
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSimInfoOne( Fsim_Man_t * p, unsigned * pInfo )
+{
+ int w;
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = ~0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSimInfoCopy( Fsim_Man_t * p, unsigned * pInfo, unsigned * pInfo0 )
+{
+ int w;
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSimulateCi( Fsim_Man_t * p, int iNode, int iCi )
+{
+ unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront );
+ unsigned * pInfo0 = Fsim_SimDataCi( p, iCi );
+ int w;
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 )
+{
+ unsigned * pInfo = Fsim_SimDataCo( p, iCo );
+ unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront );
+ int w;
+ if ( Fsim_LitIsCompl(iFan0) )
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = ~pInfo0[w];
+ else //if ( !Fsim_LitIsCompl(iFan0) )
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 )
+{
+ unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront );
+ unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront );
+ unsigned * pInfo1 = Fsim_SimData( p, Fsim_Lit2Var(iFan1) % p->nFront );
+ int w;
+ if ( Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) )
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
+ else if ( Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) )
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = ~pInfo0[w] & pInfo1[w];
+ else if ( !Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) )
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = pInfo0[w] & ~pInfo1[w];
+ else //if ( !Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) )
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = pInfo0[w] & pInfo1[w];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSimInfoInit( Fsim_Man_t * p )
+{
+ int iPioNum, i;
+ Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+ {
+ if ( iPioNum < p->nPis )
+ Fsim_ManSimInfoRandom( p, Fsim_SimDataCi(p, i) );
+ else
+ Fsim_ManSimInfoZero( p, Fsim_SimDataCi(p, i) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSimInfoTransfer( Fsim_Man_t * p )
+{
+ int iPioNum, i;
+ Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+ {
+ if ( iPioNum < p->nPis )
+ Fsim_ManSimInfoRandom( p, Fsim_SimDataCi(p, i) );
+ else
+ Fsim_ManSimInfoCopy( p, Fsim_SimDataCi(p, i), Fsim_SimDataCo(p, p->nPos+iPioNum-p->nPis) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Fsim_ManRestoreNum( Fsim_Man_t * p )
+{
+ int ch, i, x = 0;
+ for ( i = 0; (ch = *p->pDataCur++) & 0x80; i++ )
+ x |= (ch & 0x7f) << (7 * i);
+ assert( p->pDataCur - p->pDataAig < p->nDataAig );
+ return x | (ch << (7 * i));
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Fsim_ManRestoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj )
+{
+ int iValue = Fsim_ManRestoreNum( p );
+ if ( (iValue & 3) == 3 ) // and
+ {
+ pObj->iNode = (iValue >> 2) + p->iNodePrev;
+ pObj->iFan0 = (pObj->iNode << 1) - Fsim_ManRestoreNum( p );
+ pObj->iFan1 = pObj->iFan0 - Fsim_ManRestoreNum( p );
+ p->iNodePrev = pObj->iNode;
+ }
+ else if ( (iValue & 3) == 1 ) // ci
+ {
+ pObj->iNode = (iValue >> 2) + p->iNodePrev;
+ pObj->iFan0 = 0;
+ pObj->iFan1 = 0;
+ p->iNodePrev = pObj->iNode;
+ }
+ else // if ( (iValue & 1) == 0 ) // co
+ {
+ pObj->iNode = 0;
+ pObj->iFan0 = ((p->iNodePrev << 1) | 1) - (iValue >> 1);
+ pObj->iFan1 = 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSimulateRound2( Fsim_Man_t * p )
+{
+ Fsim_Obj_t * pObj;
+ int i, iCis = 0, iCos = 0;
+ if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) )
+ Fsim_ManSimInfoOne( p, Fsim_SimData(p, 1) );
+ Fsim_ManForEachObj( p, pObj, i )
+ {
+ if ( pObj->iFan0 == 0 )
+ Fsim_ManSimulateCi( p, pObj->iNode, iCis++ );
+ else if ( pObj->iFan1 == 0 )
+ Fsim_ManSimulateCo( p, iCos++, pObj->iFan0 );
+ else
+ Fsim_ManSimulateNode( p, pObj->iNode, pObj->iFan0, pObj->iFan1 );
+ }
+ assert( iCis == p->nCis );
+ assert( iCos == p->nCos );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSimulateRound( Fsim_Man_t * p )
+{
+ int * pCur, * pEnd;
+ int iCis = 0, iCos = 0;
+ if ( p->pDataAig2 == NULL )
+ {
+ Fsim_ManSimulateRound2( p );
+ return;
+ }
+ if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) )
+ Fsim_ManSimInfoOne( p, Fsim_SimData(p, 1) );
+ pCur = p->pDataAig2 + 6;
+ pEnd = p->pDataAig2 + 3 * p->nObjs;
+ while ( pCur < pEnd )
+ {
+ if ( pCur[1] == 0 )
+ Fsim_ManSimulateCi( p, pCur[0], iCis++ );
+ else if ( pCur[2] == 0 )
+ Fsim_ManSimulateCo( p, iCos++, pCur[1] );
+ else
+ Fsim_ManSimulateNode( p, pCur[0], pCur[1], pCur[2] );
+ pCur += 3;
+ }
+ assert( iCis == p->nCis );
+ assert( iCos == p->nCos );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fsim_ManSimulateRoundTest( Fsim_Man_t * p )
+{
+ Fsim_Obj_t * pObj;
+ int i, clk = clock();
+ Fsim_ManForEachObj( p, pObj, i )
+ {
+ }
+// PRT( "Unpacking time", p->pPars->nIters * (clock() - clk) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns index of the PO and pattern that failed it.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Fsim_ManCheckPos( Fsim_Man_t * p, int * piPo, int * piPat )
+{
+ int i, iPat;
+ for ( i = 0; i < p->nPos; i++ )
+ {
+ iPat = Fsim_ManSimInfoIsZero( p, Fsim_SimDataCo(p, i) );
+ if ( iPat >= 0 )
+ {
+ *piPo = i;
+ *piPat = iPat;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Cex_t * Fsim_ManGenerateCounter( Aig_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids )
+{
+ Ssw_Cex_t * p;
+ unsigned * pData;
+ int f, i, w, iPioId, Counter;
+ p = Ssw_SmlAllocCounterExample( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), iFrame+1 );
+ p->iFrame = iFrame;
+ p->iPo = iOut;
+ // fill in the binary data
+ Aig_ManRandom( 1 );
+ Counter = p->nRegs;
+ pData = ALLOC( unsigned, nWords );
+ for ( f = 0; f <= iFrame; f++, Counter += p->nPis )
+ for ( i = 0; i < Aig_ManPiNum(pAig); i++ )
+ {
+ iPioId = Vec_IntEntry( vCis2Ids, i );
+ if ( iPioId >= p->nPis )
+ continue;
+ for ( w = nWords-1; w >= 0; w-- )
+ pData[w] = Aig_ManRandom( 0 );
+ if ( Aig_InfoHasBit( pData, iPat ) )
+ Aig_InfoSetBit( p->pData, Counter + iPioId );
+ }
+ free( pData );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fsim_ManSimulate( Aig_Man_t * pAig, Fsim_ParSim_t * pPars )
+{
+ Fsim_Man_t * p;
+ Sec_MtrStatus_t Status;
+ int i, iOut, iPat, clk, clkTotal = clock(), clk2, clk2Total = 0;
+ assert( Aig_ManRegNum(pAig) > 0 );
+ Status = Sec_MiterStatus( pAig );
+ if ( Status.nSat > 0 )
+ {
+ printf( "Miter is trivially satisfiable (output %d).\n", Status.iOut );
+ return 1;
+ }
+ if ( Status.nUndec == 0 )
+ {
+ printf( "Miter is trivially unsatisfiable.\n" );
+ return 0;
+ }
+ // create manager
+ clk = clock();
+ p = Fsim_ManCreate( pAig );
+ p->nWords = pPars->nWords;
+ if ( pPars->fVerbose )
+ {
+ printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d. FrtMem = %7.2f Mb. ",
+ p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront,
+ 4.0*p->nWords*(p->nFront)/(1<<20) );
+ PRT( "Time", clock() - clk );
+ }
+ // create simulation frontier
+ clk = clock();
+ Fsim_ManFront( p, pPars->fCompressAig );
+ if ( pPars->fVerbose )
+ {
+ printf( "Max ID = %8d. Log max ID = %2d. AigMem = %7.2f Mb (%5.2f byte/obj). ",
+ p->iNumber, Aig_Base2Log(p->iNumber),
+ 1.0*(p->pDataCur-p->pDataAig)/(1<<20),
+ 1.0*(p->pDataCur-p->pDataAig)/p->nObjs );
+ PRT( "Time", clock() - clk );
+ }
+ // perform simulation
+ Aig_ManRandom( 1 );
+ assert( p->pDataSim == NULL );
+ p->pDataSim = ALLOC( unsigned, p->nWords * p->nFront * sizeof(unsigned) );
+ p->pDataSimCis = ALLOC( unsigned, p->nWords * p->nCis * sizeof(unsigned) );
+ p->pDataSimCos = ALLOC( unsigned, p->nWords * p->nCos * sizeof(unsigned) );
+ Fsim_ManSimInfoInit( p );
+ for ( i = 0; i < pPars->nIters; i++ )
+ {
+ Fsim_ManSimulateRound( p );
+ if ( pPars->fVerbose )
+ {
+ printf( "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit );
+ printf( "Time = %7.2f sec\r", (1.0*clock()-clkTotal)/CLOCKS_PER_SEC );
+ }
+ if ( pPars->fCheckMiter && Fsim_ManCheckPos( p, &iOut, &iPat ) )
+ {
+ assert( pAig->pSeqModel == NULL );
+ pAig->pSeqModel = Fsim_ManGenerateCounter( pAig, i, iOut, p->nWords, iPat, p->vCis2Ids );
+ if ( pPars->fVerbose )
+ printf( "Miter is satisfiable after simulation (output %d).\n", iOut );
+ break;
+ }
+ if ( (clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit )
+ {
+ printf( "No bug detected after %d frames with time limit %d seconds.\n", i+1, pPars->TimeLimit );
+ break;
+ }
+ clk2 = clock();
+ if ( i < pPars->nIters - 1 )
+ Fsim_ManSimInfoTransfer( p );
+ clk2Total += clock() - clk2;
+ }
+ if ( pPars->fVerbose )
+ {
+ printf( "Maxcut = %8d. AigMem = %7.2f Mb. SimMem = %7.2f Mb. ",
+ p->nCrossCutMax,
+ p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20),
+ 4.0*p->nWords*(p->nFront+p->nCis+p->nCos)/(1<<20) );
+ PRT( "Sim time", clock() - clkTotal );
+
+// PRT( "Additional time", clk2Total );
+// Fsim_ManSimulateRoundTest( p );
+// Fsim_ManSimulateRoundTest2( p );
+ }
+ Fsim_ManDelete( p );
+ return pAig->pSeqModel != NULL;
+
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/fsim/fsimSwitch.c b/src/aig/fsim/fsimSwitch.c
new file mode 100644
index 00000000..00046af6
--- /dev/null
+++ b/src/aig/fsim/fsimSwitch.c
@@ -0,0 +1,588 @@
+/**CFile****************************************************************
+
+ FileName [fsimSwitch.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast sequential AIG simulator.]
+
+ Synopsis [Computing switching activity.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: fsimSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fsimInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimInfoRandom( Fsim_Man_t * p, unsigned * pInfo, int nProbNum )
+{
+ unsigned Mask;
+ int w, i;
+ if ( nProbNum )
+ {
+ Mask = Aig_ManRandom( 0 );
+ for ( i = 0; i < nProbNum; i++ )
+ Mask &= Aig_ManRandom( 0 );
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] ^= Mask;
+ }
+ else
+ {
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = Aig_ManRandom( 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimInfoRandomShift( Fsim_Man_t * p, unsigned * pInfo, int nProbNum )
+{
+ unsigned Mask;
+ int w, i;
+ Mask = Aig_ManRandom( 0 );
+ for ( i = 0; i < nProbNum; i++ )
+ Mask &= Aig_ManRandom( 0 );
+ if ( p->nWords == 1 )
+ pInfo[0] = (pInfo[0] << 16) | ((pInfo[0] ^ Mask) & 0xffff);
+ else
+ {
+ assert( (p->nWords & 1) == 0 ); // should be even number
+ for ( w = p->nWords-1; w >= 0; w-- )
+ if ( w >= p->nWords/2 )
+ pInfo[w] = pInfo[w - p->nWords/2];
+ else
+ pInfo[w] ^= Mask;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimInfoZero( Fsim_Man_t * p, unsigned * pInfo )
+{
+ int w;
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimInfoOne( Fsim_Man_t * p, unsigned * pInfo )
+{
+ int w;
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = ~0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimInfoCopy( Fsim_Man_t * p, unsigned * pInfo, unsigned * pInfo0 )
+{
+ int w;
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimInfoCopyShift( Fsim_Man_t * p, unsigned * pInfo, unsigned * pInfo0 )
+{
+ int w;
+ if ( p->nWords == 1 )
+ pInfo[0] = (pInfo[0] << 16) | (pInfo0[0] & 0xffff);
+ else
+ {
+ assert( (p->nWords & 1) == 0 ); // should be even number
+ for ( w = p->nWords-1; w >= 0; w-- )
+ {
+ if ( w >= p->nWords/2 )
+ pInfo[w] = pInfo[w - p->nWords/2];
+ else
+ pInfo[w] = pInfo0[w];
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimulateCi( Fsim_Man_t * p, int iNode, int iCi )
+{
+ unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront );
+ unsigned * pInfo0 = Fsim_SimDataCi( p, iCi );
+ int w;
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 )
+{
+ unsigned * pInfo = Fsim_SimDataCo( p, iCo );
+ unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront );
+ int w;
+ if ( Fsim_LitIsCompl(iFan0) )
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = ~pInfo0[w];
+ else //if ( !Fsim_LitIsCompl(iFan0) )
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = pInfo0[w];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 )
+{
+ unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront );
+ unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront );
+ unsigned * pInfo1 = Fsim_SimData( p, Fsim_Lit2Var(iFan1) % p->nFront );
+ int w;
+ if ( Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) )
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
+ else if ( Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) )
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = ~pInfo0[w] & pInfo1[w];
+ else if ( !Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) )
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = pInfo0[w] & ~pInfo1[w];
+ else //if ( !Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) )
+ for ( w = p->nWords-1; w >= 0; w-- )
+ pInfo[w] = pInfo0[w] & pInfo1[w];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimInfoInit( Fsim_Man_t * p )
+{
+ int iPioNum, i;
+ Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+ {
+ if ( iPioNum < p->nPis )
+ Fsim_ManSwitchSimInfoRandom( p, Fsim_SimDataCi(p, i), 0 );
+ else
+ Fsim_ManSwitchSimInfoZero( p, Fsim_SimDataCi(p, i) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimInfoTransfer( Fsim_Man_t * p, int nProbNum )
+{
+ int iPioNum, i;
+ Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+ {
+ if ( iPioNum < p->nPis )
+ Fsim_ManSwitchSimInfoRandom( p, Fsim_SimDataCi(p, i), nProbNum );
+ else
+ Fsim_ManSwitchSimInfoCopy( p, Fsim_SimDataCi(p, i), Fsim_SimDataCo(p, p->nPos+iPioNum-p->nPis) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimInfoTransferShift( Fsim_Man_t * p, int nProbNum )
+{
+ int iPioNum, i;
+ Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+ {
+ if ( iPioNum < p->nPis )
+ Fsim_ManSwitchSimInfoRandomShift( p, Fsim_SimDataCi(p, i), nProbNum );
+ else
+ Fsim_ManSwitchSimInfoCopyShift( p, Fsim_SimDataCi(p, i), Fsim_SimDataCo(p, p->nPos+iPioNum-p->nPis) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Fsim_ManSwitchSimInfoCountOnes( Fsim_Man_t * p, int iNode )
+{
+ unsigned * pInfo;
+ int w, Counter = 0;
+ pInfo = Fsim_SimData( p, iNode % p->nFront );
+ for ( w = p->nWords-1; w >= 0; w-- )
+ Counter += Aig_WordCountOnes( pInfo[w] );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Fsim_ManSwitchSimInfoCountTrans( Fsim_Man_t * p, int iNode )
+{
+ unsigned * pInfo;
+ int w, Counter = 0;
+ assert( iNode % p->nFront );
+ pInfo = Fsim_SimData( p, iNode % p->nFront );
+ if ( p->nWords == 1 )
+ return Aig_WordCountOnes( (pInfo[0] ^ (pInfo[0] >> 16)) & 0xffff );
+ for ( w = p->nWords/2-1; w >= 0; w-- )
+ Counter += Aig_WordCountOnes( pInfo[w] ^ pInfo[w + p->nWords/2] );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManSwitchSimulateRound( Fsim_Man_t * p, int fCount )
+{
+ int * pCur, * pEnd;
+ int i, iCis = 0, iCos = 0;
+ if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) )
+ Fsim_ManSwitchSimInfoOne( p, Fsim_SimData(p, 1) );
+ pCur = p->pDataAig2 + 6;
+ pEnd = p->pDataAig2 + 3 * p->nObjs;
+ for ( i = 2; pCur < pEnd; i++ )
+ {
+ if ( pCur[1] == 0 )
+ Fsim_ManSwitchSimulateCi( p, pCur[0], iCis++ );
+ else if ( pCur[2] == 0 )
+ Fsim_ManSwitchSimulateCo( p, iCos++, pCur[1] );
+ else
+ Fsim_ManSwitchSimulateNode( p, pCur[0], pCur[1], pCur[2] );
+ if ( fCount && pCur[0] )
+ {
+ if ( p->pData1 )
+ p->pData1[i] += Fsim_ManSwitchSimInfoCountOnes( p, pCur[0] );
+ if ( p->pData2 )
+ p->pData2[i] += Fsim_ManSwitchSimInfoCountTrans( p, pCur[0] );
+ }
+ pCur += 3;
+ }
+ assert( iCis == p->nCis );
+ assert( iCos == p->nCos );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes switching activity of one node.]
+
+ Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Fsim_ManSwitchComputeSwitching( int nOnes, int nSimWords )
+{
+ int nTotal = 32 * nSimWords;
+ return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes switching activity of one node.]
+
+ Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Fsim_ManSwitchComputeProbOne( int nOnes, int nSimWords )
+{
+ int nTotal = 32 * nSimWords;
+ return (float)nOnes / nTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Fsim_ManSwitchSimulate( Aig_Man_t * pAig, Fsim_ParSwitch_t * pPars )
+{
+ Vec_Int_t * vSwitching;
+ float * pSwitching;
+ Aig_Obj_t * pObj;
+ Fsim_Man_t * p;
+ int i, clk, clkTotal = clock();
+ // create manager
+ clk = clock();
+ p = Fsim_ManCreate( pAig );
+ p->nWords = pPars->nWords;
+ // if the number of words is larger then 1, it should be even
+ if ( p->nWords > 1 && (p->nWords & 1) )
+ p->nWords++;
+ // print stats
+ if ( pPars->fVerbose )
+ {
+ printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d. FrtMem = %7.2f Mb. ",
+ p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront,
+ 4.0*pPars->nWords*(p->nFront)/(1<<20) );
+ PRT( "Time", clock() - clk );
+ }
+ // create simulation frontier
+ clk = clock();
+ Fsim_ManFront( p, 0 );
+ if ( pPars->fVerbose )
+ {
+ printf( "Max ID = %8d. Log max ID = %2d. AigMem = %7.2f Mb (%5.2f byte/obj). ",
+ p->iNumber, Aig_Base2Log(p->iNumber),
+ 1.0*(p->pDataCur-p->pDataAig)/(1<<20),
+ 1.0*(p->pDataCur-p->pDataAig)/p->nObjs );
+ PRT( "Time", clock() - clk );
+ }
+ // perform simulation
+ Aig_ManRandom( 1 );
+ assert( p->pDataSim == NULL );
+ p->pDataSim = ALLOC( unsigned, pPars->nWords * p->nFront * sizeof(unsigned) );
+ p->pDataSimCis = ALLOC( unsigned, pPars->nWords * p->nCis * sizeof(unsigned) );
+ p->pDataSimCos = ALLOC( unsigned, pPars->nWords * p->nCos * sizeof(unsigned) );
+ if ( pPars->fProbOne )
+ p->pData1 = CALLOC( int, p->nObjs * sizeof(int) );
+ if ( pPars->fProbTrans )
+ p->pData2 = CALLOC( int, p->nObjs * sizeof(int) );
+ Fsim_ManSwitchSimInfoInit( p );
+ for ( i = 0; i < pPars->nIters; i++ )
+ {
+ Fsim_ManSwitchSimulateRound( p, i >= pPars->nPref );
+ if ( i < pPars->nIters - 1 )
+ {
+// if ( pPars->fProbTrans )
+ Fsim_ManSwitchSimInfoTransferShift( p, pPars->nRandPiNum );
+// else
+// Fsim_ManSwitchSimInfoTransfer( p, pPars->nRandPiNum );
+ }
+ }
+ if ( pPars->fVerbose )
+ {
+ printf( "Maxcut = %8d. AigMem = %7.2f Mb. SimMem = %7.2f Mb. ",
+ p->nCrossCutMax,
+ p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20),
+ 4.0*pPars->nWords*(p->nFront+p->nCis+p->nCos)/(1<<20) );
+ PRT( "Sim time", clock() - clkTotal );
+ }
+ // derive the result
+ vSwitching = Vec_IntStart( Aig_ManObjNumMax(pAig) );
+ pSwitching = (float *)vSwitching->pArray;
+/*
+ if ( pPars->fProbOne && pPars->fProbTrans )
+ {
+ Aig_ManForEachObj( pAig, pObj, i )
+// pSwitching[pObj->Id] = Fsim_ManSwitchComputeSwitching( p->pData1[pObj->iData], pPars->nWords*(pPars->nIters-pPars->nPref) );
+ pSwitching[pObj->Id] = Fsim_ManSwitchComputeProbOne( p->pData2[pObj->iData], pPars->nWords*(pPars->nIters-pPars->nPref)/2 );
+ }
+ else if ( !pPars->fProbOne && pPars->fProbTrans )
+ {
+ Aig_ManForEachObj( pAig, pObj, i )
+ pSwitching[pObj->Id] = Fsim_ManSwitchComputeProbOne( p->pData2[pObj->iData], pPars->nWords*(pPars->nIters-pPars->nPref)/2 );
+ }
+ else if ( pPars->fProbOne && !pPars->fProbTrans )
+ {
+ Aig_ManForEachObj( pAig, pObj, i )
+ pSwitching[pObj->Id] = Fsim_ManSwitchComputeProbOne( p->pData1[pObj->iData], pPars->nWords*(pPars->nIters-pPars->nPref) );
+ }
+ else
+ assert( 0 );
+*/
+ if ( pPars->fProbOne && !pPars->fProbTrans )
+ {
+ Aig_ManForEachObj( pAig, pObj, i )
+ pSwitching[pObj->Id] = Fsim_ManSwitchComputeProbOne( p->pData1[pObj->iData], pPars->nWords*(pPars->nIters-pPars->nPref) );
+ }
+ else if ( !pPars->fProbOne && pPars->fProbTrans )
+ {
+ Aig_ManForEachObj( pAig, pObj, i )
+ pSwitching[pObj->Id] = Fsim_ManSwitchComputeProbOne( p->pData2[pObj->iData], pPars->nWords*(pPars->nIters-pPars->nPref)/2 );
+ }
+ else
+ assert( 0 );
+ Fsim_ManDelete( p );
+ return vSwitching;
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes probability of switching (or of being 1).]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManComputeSwitchProbs4( Aig_Man_t * p, int nFrames, int nPref, int fProbOne )
+{
+ Fsim_ParSwitch_t Pars, * pPars = &Pars;
+ Fsim_ManSetDefaultParamsSwitch( pPars );
+ pPars->nWords = 1;
+ pPars->nIters = nFrames;
+ pPars->nPref = nPref;
+ if ( fProbOne )
+ {
+ pPars->fProbOne = 1;
+ pPars->fProbTrans = 0;
+ }
+ else
+ {
+ pPars->fProbOne = 0;
+ pPars->fProbTrans = 1;
+ }
+ pPars->fVerbose = 0;
+ return Fsim_ManSwitchSimulate( p, pPars );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/fsim/fsimTsim.c b/src/aig/fsim/fsimTsim.c
new file mode 100644
index 00000000..963d7581
--- /dev/null
+++ b/src/aig/fsim/fsimTsim.c
@@ -0,0 +1,410 @@
+/**CFile****************************************************************
+
+ FileName [fsimTsim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast sequential AIG simulator.]
+
+ Synopsis [Varius utilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: fsimTsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fsimInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define FSIM_ZER 1
+#define FSIM_ONE 2
+#define FSIM_UND 3
+
+static inline int Aig_XsimNotCond( int Value, int fCompl )
+{
+ if ( Value == FSIM_UND )
+ return FSIM_UND;
+ if ( Value == FSIM_ZER + fCompl )
+ return FSIM_ZER;
+ return FSIM_ONE;
+}
+static inline int Aig_XsimAndCond( int Value0, int Value1, int fCompl0, int fCompl1 )
+{
+ if ( Value0 == FSIM_UND || Value1 == FSIM_UND )
+ return FSIM_UND;
+ if ( Value0 == FSIM_ZER + fCompl0 || Value1 == FSIM_ZER + fCompl1 )
+ return FSIM_ZER;
+ return FSIM_ONE;
+}
+
+static inline int Fsim_ManTerSimInfoGet( unsigned * pInfo, int i )
+{
+ return 3 & (pInfo[i >> 4] >> ((i & 15) << 1));
+}
+static inline void Fsim_ManTerSimInfoSet( unsigned * pInfo, int i, int Value )
+{
+ assert( Value >= FSIM_ZER && Value <= FSIM_UND );
+ Value ^= Fsim_ManTerSimInfoGet( pInfo, i );
+ pInfo[i >> 4] ^= (Value << ((i & 15) << 1));
+}
+
+static inline unsigned * Fsim_ManTerStateNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); }
+static inline void Fsim_ManTerStateSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManTerSimulateCi( Fsim_Man_t * p, int iNode, int iCi )
+{
+ Fsim_ManTerSimInfoSet( p->pDataSim, iNode, Fsim_ManTerSimInfoGet(p->pDataSimCis, iCi) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManTerSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 )
+{
+ int Value = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan0) );
+ Fsim_ManTerSimInfoSet( p->pDataSimCos, iCo, Aig_XsimNotCond( Value, Fsim_LitIsCompl(iFan0) ) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManTerSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 )
+{
+ int Value0 = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan0) );
+ int Value1 = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan1) );
+ Fsim_ManTerSimInfoSet( p->pDataSim, iNode, Aig_XsimAndCond( Value0, Value1, Fsim_LitIsCompl(iFan0), Fsim_LitIsCompl(iFan1) ) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManTerSimInfoInit( Fsim_Man_t * p )
+{
+ int iPioNum, i;
+ Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+ {
+ if ( iPioNum < p->nPis )
+ Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_UND );
+ else
+ Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_ZER );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManTerSimInfoTransfer( Fsim_Man_t * p )
+{
+ int iPioNum, i;
+ Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+ {
+ if ( iPioNum < p->nPis )
+ Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_UND );
+ else
+ Fsim_ManTerSimInfoSet( p->pDataSimCis, i, Fsim_ManTerSimInfoGet( p->pDataSimCos, p->nPos+iPioNum-p->nPis ) );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes hash value of the node using its simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fsim_ManTerStateHash( unsigned * pState, int nWords, int nTableSize )
+{
+ static int s_FPrimes[128] = {
+ 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
+ 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
+ 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
+ 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
+ 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
+ 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
+ 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
+ 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
+ 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
+ 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
+ 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
+ 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
+ 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+ };
+ unsigned uHash;
+ int i;
+ uHash = 0;
+ for ( i = 0; i < nWords; i++ )
+ uHash ^= pState[i] * s_FPrimes[i & 0x7F];
+ return uHash % nTableSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts value into the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fsim_ManTerStateLookup( unsigned * pState, int nWords, unsigned ** pBins, int nBins )
+{
+ unsigned * pEntry;
+ int Hash;
+ Hash = Fsim_ManTerStateHash( pState, nWords, nBins );
+ for ( pEntry = pBins[Hash]; pEntry; pEntry = Fsim_ManTerStateNext(pEntry, nWords) )
+ if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts value into the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fsim_ManTerStateInsert( unsigned * pState, int nWords, unsigned ** pBins, int nBins )
+{
+ int Hash = Fsim_ManTerStateHash( pState, nWords, nBins );
+ assert( !Fsim_ManTerStateLookup( pState, nWords, pBins, nBins ) );
+ Fsim_ManTerStateSetNext( pState, nWords, pBins[Hash] );
+ pBins[Hash] = pState;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts value into the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Fsim_ManTerStateCreate( unsigned * pInfo, int nPis, int nCis, int nWords )
+{
+ unsigned * pRes;
+ int i;
+ pRes = (unsigned *)CALLOC( char, sizeof(unsigned) * nWords + sizeof(unsigned *) );
+ for ( i = nPis; i < nCis; i++ )
+ Fsim_ManTerSimInfoSet( pRes, i-nPis, Fsim_ManTerSimInfoGet(pInfo, i) );
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts value into the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fsim_ManTerStatePrint( unsigned * pState, int nRegs )
+{
+ int i, Value, nZeros = 0, nOnes = 0, nDcs = 0;
+ for ( i = 0; i < nRegs; i++ )
+ {
+ Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i );
+ if ( Value == 1 )
+ printf( "0" ), nZeros++;
+ else if ( Value == 2 )
+ printf( "1" ), nOnes++;
+ else if ( Value == 3 )
+ printf( "x" ), nDcs++;
+ else
+ assert( 0 );
+ }
+ printf( " (0=%5d, 1=%5d, x=%5d)\n", nZeros, nOnes, nDcs );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fsim_ManTerSimulateRound( Fsim_Man_t * p )
+{
+ int * pCur, * pEnd;
+ int iCis = 0, iCos = 0;
+ if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) )
+ Fsim_ManTerSimInfoSet( p->pDataSimCis, 1, FSIM_ONE );
+ pCur = p->pDataAig2 + 6;
+ pEnd = p->pDataAig2 + 3 * p->nObjs;
+ while ( pCur < pEnd )
+ {
+ if ( pCur[1] == 0 )
+ Fsim_ManTerSimulateCi( p, pCur[0], iCis++ );
+ else if ( pCur[2] == 0 )
+ Fsim_ManTerSimulateCo( p, iCos++, pCur[1] );
+ else
+ Fsim_ManTerSimulateNode( p, pCur[0], pCur[1], pCur[2] );
+ pCur += 3;
+ }
+ assert( iCis == p->nCis );
+ assert( iCos == p->nCos );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Fsim_ManTerSimulate( Aig_Man_t * pAig, int fVerbose )
+{
+ Fsim_Man_t * p;
+ Vec_Ptr_t * vStates;
+ unsigned ** pBins, * pState;
+ int i, nWords, nBins, clk, clkTotal = clock();
+ assert( Aig_ManRegNum(pAig) > 0 );
+ // create manager
+ clk = clock();
+ p = Fsim_ManCreate( pAig );
+ if ( fVerbose )
+ {
+ printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d. FrtMem = %7.2f Mb. ",
+ p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront,
+ 4.0*Aig_BitWordNum(2 * p->nFront)/(1<<20) );
+ PRT( "Time", clock() - clk );
+ }
+ // create simulation frontier
+ clk = clock();
+ Fsim_ManFront( p, 0 );
+ if ( fVerbose )
+ {
+ printf( "Max ID = %8d. Log max ID = %2d. AigMem = %7.2f Mb (%5.2f byte/obj). ",
+ p->iNumber, Aig_Base2Log(p->iNumber),
+ 1.0*(p->pDataCur-p->pDataAig)/(1<<20),
+ 1.0*(p->pDataCur-p->pDataAig)/p->nObjs );
+ PRT( "Time", clock() - clk );
+ }
+ // allocate storage for terminary states
+ nWords = Aig_BitWordNum( 2*Aig_ManRegNum(pAig) );
+ vStates = Vec_PtrAlloc( 1000 );
+ nBins = Aig_PrimeCudd( 500 );
+ pBins = ALLOC( unsigned *, nBins );
+ memset( pBins, 0, sizeof(unsigned *) * nBins );
+ // perform simulation
+ assert( p->pDataSim == NULL );
+ p->pDataSim = ALLOC( unsigned, Aig_BitWordNum(2 * p->nFront) * sizeof(unsigned) );
+ p->pDataSimCis = ALLOC( unsigned, Aig_BitWordNum(2 * p->nCis) * sizeof(unsigned) );
+ p->pDataSimCos = ALLOC( unsigned, Aig_BitWordNum(2 * p->nCos) * sizeof(unsigned) );
+ Fsim_ManTerSimInfoInit( p );
+ // hash the first state
+ pState = Fsim_ManTerStateCreate( p->pDataSimCis, p->nPis, p->nCis, nWords );
+ Vec_PtrPush( vStates, pState );
+ Fsim_ManTerStateInsert( pState, nWords, pBins, nBins );
+ // perform simuluation till convergence
+ for ( i = 0; ; i++ )
+ {
+ Fsim_ManTerSimulateRound( p );
+ Fsim_ManTerSimInfoTransfer( p );
+ // hash the first state
+ pState = Fsim_ManTerStateCreate( p->pDataSimCis, p->nPis, p->nCis, nWords );
+ Vec_PtrPush( vStates, pState );
+ if ( Fsim_ManTerStateLookup(pState, nWords, pBins, nBins) )
+ break;
+ Fsim_ManTerStateInsert( pState, nWords, pBins, nBins );
+ }
+ if ( fVerbose )
+ {
+ printf( "Maxcut = %8d. AigMem = %7.2f Mb. SimMem = %7.2f Mb. ",
+ p->nCrossCutMax,
+ p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20),
+ 4.0*(Aig_BitWordNum(2 * p->nFront)+Aig_BitWordNum(2 * p->nCis)+Aig_BitWordNum(2 * p->nCos))/(1<<20) );
+ PRT( "Sim time", clock() - clkTotal );
+ }
+ free( pBins );
+ Fsim_ManDelete( p );
+ return vStates;
+
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/fsim/module.make b/src/aig/fsim/module.make
new file mode 100644
index 00000000..91c733c3
--- /dev/null
+++ b/src/aig/fsim/module.make
@@ -0,0 +1,6 @@
+SRC += src/aig/fsim/fsimCore.c \
+ src/aig/fsim/fsimFront.c \
+ src/aig/fsim/fsimMan.c \
+ src/aig/fsim/fsimSim.c \
+ src/aig/fsim/fsimSwitch.c \
+ src/aig/fsim/fsimTsim.c
diff --git a/src/aig/hop/hop.h b/src/aig/hop/hop.h
index db4799ca..6ffc4eac 100644
--- a/src/aig/hop/hop.h
+++ b/src/aig/hop/hop.h
@@ -64,7 +64,10 @@ typedef enum {
struct Hop_Obj_t_ // 6 words
{
void * pData; // misc
- Hop_Obj_t * pNext; // strashing table
+ union {
+ Hop_Obj_t * pNext; // strashing table
+ int PioNum; // the number of PI/PO
+ };
Hop_Obj_t * pFanin0; // fanin
Hop_Obj_t * pFanin1; // fanin
unsigned int Type : 3; // object type
diff --git a/src/aig/hop/hopObj.c b/src/aig/hop/hopObj.c
index 69f63ee6..f173248f 100644
--- a/src/aig/hop/hopObj.c
+++ b/src/aig/hop/hopObj.c
@@ -44,6 +44,7 @@ Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p )
Hop_Obj_t * pObj;
pObj = Hop_ManFetchMemory( p );
pObj->Type = AIG_PI;
+ pObj->PioNum = Vec_PtrSize( p->vPis );
Vec_PtrPush( p->vPis, pObj );
p->nObjs[AIG_PI]++;
return pObj;
diff --git a/src/aig/hop/hopTruth.c b/src/aig/hop/hopTruth.c
index 47358715..42ded3ed 100644
--- a/src/aig/hop/hopTruth.c
+++ b/src/aig/hop/hopTruth.c
@@ -44,6 +44,12 @@ static inline void Hop_ManTruthFill( unsigned * pOut, int nVars )
for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- )
pOut[w] = ~(unsigned)0;
}
+static inline void Hop_ManTruthNot( unsigned * pOut, unsigned * pIn, int nVars )
+{
+ int w;
+ for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~pIn[w];
+}
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
@@ -155,7 +161,7 @@ unsigned * Hop_ManConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars
vTtElems = NULL;
// clear the data fields and set marks
- nNodes = Hop_ManConvertAigToTruth_rec1( pRoot );
+ nNodes = Hop_ManConvertAigToTruth_rec1( Hop_Regular(pRoot) );
// prepare memory
nWords = Hop_TruthWordNum( nVars );
Vec_IntClear( vTruth );
@@ -199,9 +205,11 @@ unsigned * Hop_ManConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars
}
}
// clear the marks and compute the truth table
- pTruth2 = Hop_ManConvertAigToTruth_rec2( pRoot, vTruth, nWords );
+ pTruth2 = Hop_ManConvertAigToTruth_rec2( Hop_Regular(pRoot), vTruth, nWords );
// copy the result
Hop_ManTruthCopy( pTruth, pTruth2, nVars );
+ if ( Hop_IsComplement(pRoot) )
+ Hop_ManTruthNot( pTruth, pTruth, nVars );
if ( vTtElems )
Vec_PtrFree( vTtElems );
return pTruth;
diff --git a/src/aig/ioa/ioaWriteAig.c b/src/aig/ioa/ioaWriteAig.c
index 12de42ad..ec37b40e 100644
--- a/src/aig/ioa/ioaWriteAig.c
+++ b/src/aig/ioa/ioaWriteAig.c
@@ -258,6 +258,12 @@ void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int
unsigned char * pBuffer;
unsigned uLit0, uLit1, uLit;
+ if ( Aig_ManPoNum(pMan) == 0 )
+ {
+ printf( "AIG cannot be written because it has no POs.\n" );
+ return;
+ }
+
// assert( Aig_ManIsStrash(pMan) );
// start the output stream
pFile = fopen( pFileName, "wb" );
diff --git a/src/aig/kit/kit.h b/src/aig/kit/kit.h
index 101cf2eb..e8dea11a 100644
--- a/src/aig/kit/kit.h
+++ b/src/aig/kit/kit.h
@@ -141,14 +141,14 @@ struct Kit_DsdMan_t_
};
#ifdef WIN32
-#define DLLEXPORT __declspec(dllexport)
-#define DLLIMPORT __declspec(dllimport)
+#define ABC_DLLEXPORT __declspec(dllexport)
+#define ABC_DLLIMPORT __declspec(dllimport)
#else /* defined(WIN32) */
-#define DLLIMPORT
+#define ABC_DLLIMPORT
#endif /* defined(WIN32) */
#ifndef ABC_DLL
-#define ABC_DLL DLLIMPORT
+#define ABC_DLL ABC_DLLIMPORT
#endif
static inline int Kit_DsdVar2Lit( int Var, int fCompl ) { return Var + Var + fCompl; }
@@ -169,7 +169,9 @@ static inline unsigned Kit_DsdLitSupport( Kit_DsdNtk_t * pNtk, int Lit )
#define Kit_DsdNtkForEachObj( pNtk, pObj, i ) \
for ( i = 0; (i < (pNtk)->nNodes) && ((pObj) = (pNtk)->pNodes[i]); i++ )
#define Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) \
- for ( i = 0; (i < (pObj)->nFans) && ((iLit) = (pObj)->pFans[i], 1); i++ )
+ for ( i = 0; (i < (int)(pObj)->nFans) && ((iLit) = (pObj)->pFans[i], 1); i++ )
+#define Kit_DsdObjForEachFaninReverse( pNtk, pObj, iLit, i ) \
+ for ( i = (int)(pObj)->nFans - 1; (i >= 0) && ((iLit) = (pObj)->pFans[i], 1); i-- )
#define Kit_PlaForEachCube( pSop, nFanins, pCube ) \
for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 )
@@ -528,6 +530,7 @@ extern Kit_DsdNtk_t * Kit_DsdDecomposeMux( unsigned * pTruth, int nVars, int nD
extern void Kit_DsdVerify( Kit_DsdNtk_t * pNtk, unsigned * pTruth, int nVars );
extern void Kit_DsdNtkFree( Kit_DsdNtk_t * pNtk );
extern int Kit_DsdNonDsdSizeMax( Kit_DsdNtk_t * pNtk );
+extern Kit_DsdObj_t * Kit_DsdNonDsdPrimeMax( Kit_DsdNtk_t * pNtk );
extern unsigned Kit_DsdNonDsdSupports( Kit_DsdNtk_t * pNtk );
extern unsigned Kit_DsdGetSupports( Kit_DsdNtk_t * p );
extern Kit_DsdNtk_t * Kit_DsdExpand( Kit_DsdNtk_t * p );
@@ -586,6 +589,7 @@ extern void Kit_SopBestLiteralCover( Kit_Sop_t * cResult, Kit_Sop_t *
/*=== kitTruth.c ==========================================================*/
extern void Kit_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start );
extern void Kit_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn );
+extern void Kit_TruthPermute( unsigned * pOut, unsigned * pIn, int nVars, char * pPerm, int fReturnIn );
extern void Kit_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn );
extern int Kit_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar );
extern int Kit_TruthSupportSize( unsigned * pTruth, int nVars );
@@ -608,6 +612,7 @@ extern void Kit_TruthChangePhase( unsigned * pTruth, int nVars, int i
extern int Kit_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin );
extern int Kit_TruthBestCofVar( unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 );
extern void Kit_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore );
+extern void Kit_TruthCountOnesInCofs0( unsigned * pTruth, int nVars, short * pStore );
extern void Kit_TruthCountOnesInCofsSlow( unsigned * pTruth, int nVars, short * pStore, unsigned * pAux );
extern unsigned Kit_TruthHash( unsigned * pIn, int nWords );
extern unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore );
diff --git a/src/aig/kit/kitDsd.c b/src/aig/kit/kitDsd.c
index 8d670419..75358093 100644
--- a/src/aig/kit/kitDsd.c
+++ b/src/aig/kit/kitDsd.c
@@ -139,9 +139,9 @@ Kit_DsdNtk_t * Kit_DsdNtkAlloc( int nVars )
Kit_DsdNtk_t * pNtk;
pNtk = ALLOC( Kit_DsdNtk_t, 1 );
memset( pNtk, 0, sizeof(Kit_DsdNtk_t) );
- pNtk->pNodes = ALLOC( Kit_DsdObj_t *, nVars );
+ pNtk->pNodes = ALLOC( Kit_DsdObj_t *, nVars+1 );
pNtk->nVars = nVars;
- pNtk->nNodesAlloc = nVars;
+ pNtk->nNodesAlloc = nVars+1;
pNtk->pMem = ALLOC( unsigned, 6 * Kit_TruthWordNum(nVars) );
return pNtk;
}
@@ -303,10 +303,13 @@ void Kit_DsdPrintExpanded( Kit_DsdNtk_t * pNtk )
***********************************************************************/
void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars )
{
- Kit_DsdNtk_t * pTemp;
+ Kit_DsdNtk_t * pTemp, * pTemp2;
pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 5 );
- Kit_DsdVerify( pTemp, pTruth, nVars );
- Kit_DsdPrintExpanded( pTemp );
+// Kit_DsdPrintExpanded( pTemp );
+ pTemp2 = Kit_DsdExpand( pTemp );
+ Kit_DsdPrint( stdout, pTemp2 );
+ Kit_DsdVerify( pTemp2, pTruth, nVars );
+ Kit_DsdNtkFree( pTemp2 );
Kit_DsdNtkFree( pTemp );
}
@@ -392,7 +395,6 @@ unsigned * Kit_DsdTruthComputeNode_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, i
pTruthPrime = Kit_DsdObjTruth( pObj );
// get storage for the temporary minterm
pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes);
-
// go through the minterms
nMints = (1 << pObj->nFans);
Kit_TruthClear( pTruthRes, pNtk->nVars );
@@ -406,6 +408,9 @@ unsigned * Kit_DsdTruthComputeNode_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, i
Kit_TruthOr( pTruthRes, pTruthRes, pTruthMint, pNtk->nVars );
}
*/
+ Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+ if ( Kit_DsdLitIsCompl(iLit) )
+ Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->nVars );
pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes );
Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars );
return pTruthRes;
@@ -550,7 +555,6 @@ unsigned * Kit_DsdTruthComputeNodeOne_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk
pTruthPrime = Kit_DsdObjTruth( pObj );
// get storage for the temporary minterm
pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes);
-
// go through the minterms
nMints = (1 << pObj->nFans);
Kit_TruthClear( pTruthRes, pNtk->nVars );
@@ -564,6 +568,9 @@ unsigned * Kit_DsdTruthComputeNodeOne_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk
Kit_TruthOr( pTruthRes, pTruthRes, pTruthMint, pNtk->nVars );
}
*/
+ Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+ if ( Kit_DsdLitIsCompl(iLit) )
+ Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->nVars );
pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes );
Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars );
return pTruthRes;
@@ -747,7 +754,6 @@ unsigned * Kit_DsdTruthComputeNodeTwo_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk
pTruthPrime = Kit_DsdObjTruth( pObj );
// get storage for the temporary minterm
pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes);
-
// go through the minterms
nMints = (1 << pObj->nFans);
Kit_TruthClear( pTruthRes, pNtk->nVars );
@@ -761,8 +767,11 @@ unsigned * Kit_DsdTruthComputeNodeTwo_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk
Kit_TruthOr( pTruthRes, pTruthRes, pTruthMint, pNtk->nVars );
}
*/
+// Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
+// assert( !Kit_DsdLitIsCompl(iLit) );
Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i )
- assert( !Kit_DsdLitIsCompl(iLit) );
+ if ( Kit_DsdLitIsCompl(iLit) )
+ Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->nVars );
pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes );
Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars );
return pTruthRes;
@@ -957,7 +966,7 @@ int Kit_DsdCountLuts( Kit_DsdNtk_t * pNtk, int nLutSize )
/**Function*************************************************************
- Synopsis [Counts the number of blocks of the given number of inputs.]
+ Synopsis [Returns the size of the largest non-DSD block.]
Description []
@@ -982,6 +991,34 @@ int Kit_DsdNonDsdSizeMax( Kit_DsdNtk_t * pNtk )
/**Function*************************************************************
+ Synopsis [Returns the largest non-DSD block.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Kit_DsdObj_t * Kit_DsdNonDsdPrimeMax( Kit_DsdNtk_t * pNtk )
+{
+ Kit_DsdObj_t * pObj, * pObjMax = NULL;
+ unsigned i, nSizeMax = 0;
+ Kit_DsdNtkForEachObj( pNtk, pObj, i )
+ {
+ if ( pObj->Type != KIT_DSD_PRIME )
+ continue;
+ if ( nSizeMax < pObj->nFans )
+ {
+ nSizeMax = pObj->nFans;
+ pObjMax = pObj;
+ }
+ }
+ return pObjMax;
+}
+
+/**Function*************************************************************
+
Synopsis [Finds the union of supports of the non-DSD blocks.]
Description []
@@ -1125,10 +1162,46 @@ int Kit_DsdExpandNode_rec( Kit_DsdNtk_t * pNew, Kit_DsdNtk_t * p, int iLit )
Kit_TruthChangePhase( pTruthNew, pObjNew->nFans, i );
}
}
- // if the incoming phase is complemented, absorb it into the prime node
- if ( Kit_DsdLitIsCompl(iLit) )
- Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans );
- return Kit_DsdVar2Lit( pObjNew->Id, 0 );
+
+ if ( pObj->nFans == 3 &&
+ (pTruthNew[0] == 0xCACACACA || pTruthNew[0] == 0xC5C5C5C5 ||
+ pTruthNew[0] == 0x3A3A3A3A || pTruthNew[0] == 0x35353535) )
+ {
+ // translate into regular MUXes
+ if ( pTruthNew[0] == 0xC5C5C5C5 )
+ pObjNew->pFans[0] = Kit_DsdLitNot(pObjNew->pFans[0]);
+ else if ( pTruthNew[0] == 0x3A3A3A3A )
+ pObjNew->pFans[1] = Kit_DsdLitNot(pObjNew->pFans[1]);
+ else if ( pTruthNew[0] == 0x35353535 )
+ {
+ pObjNew->pFans[0] = Kit_DsdLitNot(pObjNew->pFans[0]);
+ pObjNew->pFans[1] = Kit_DsdLitNot(pObjNew->pFans[1]);
+ }
+ pTruthNew[0] = 0xCACACACA;
+ // resolve the complemented control input
+ if ( Kit_DsdLitIsCompl(pObjNew->pFans[2]) )
+ {
+ unsigned char Temp = pObjNew->pFans[0];
+ pObjNew->pFans[0] = pObjNew->pFans[1];
+ pObjNew->pFans[1] = Temp;
+ pObjNew->pFans[2] = Kit_DsdLitNot(pObjNew->pFans[2]);
+ }
+ // resolve the complemented true input
+ if ( Kit_DsdLitIsCompl(pObjNew->pFans[1]) )
+ {
+ iLit = Kit_DsdLitNot(iLit);
+ pObjNew->pFans[0] = Kit_DsdLitNot(pObjNew->pFans[0]);
+ pObjNew->pFans[1] = Kit_DsdLitNot(pObjNew->pFans[1]);
+ }
+ return Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(iLit) );
+ }
+ else
+ {
+ // if the incoming phase is complemented, absorb it into the prime node
+ if ( Kit_DsdLitIsCompl(iLit) )
+ Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans );
+ return Kit_DsdVar2Lit( pObjNew->Id, 0 );
+ }
}
/**Function*************************************************************
@@ -1834,7 +1907,7 @@ void Kit_DsdDecompose_rec( Kit_DsdNtk_t * pNtk, Kit_DsdObj_t * pObj, unsigned uS
return;
}
}
-/*
+
// if all decomposition methods failed and we are still above the limit, perform MUX-decomposition
if ( nDecMux > 0 && (int)pObj->nFans > nDecMux )
{
@@ -1852,14 +1925,14 @@ void Kit_DsdDecompose_rec( Kit_DsdNtk_t * pNtk, Kit_DsdObj_t * pObj, unsigned uS
assert( pObj->Type == KIT_DSD_PRIME );
pTruth[0] = 0xCACACACA;
pObj->nFans = 3;
+ pObj->pFans[2] = pObj->pFans[iBestVar];
pObj->pFans[0] = 2*pRes0->Id; pRes0->nRefs++;
pObj->pFans[1] = 2*pRes1->Id; pRes1->nRefs++;
- pObj->pFans[2] = pObj->pFans[iBestVar];
// call recursively
Kit_DsdDecompose_rec( pNtk, pRes0, uSupp0, pObj->pFans + 0, nDecMux );
Kit_DsdDecompose_rec( pNtk, pRes1, uSupp1, pObj->pFans + 1, nDecMux );
}
-*/
+
}
/**Function*************************************************************
@@ -1959,6 +2032,27 @@ Kit_DsdNtk_t * Kit_DsdDecomposeExpand( unsigned * pTruth, int nVars )
***********************************************************************/
Kit_DsdNtk_t * Kit_DsdDecomposeMux( unsigned * pTruth, int nVars, int nDecMux )
{
+/*
+ Kit_DsdNtk_t * pNew;
+ Kit_DsdObj_t * pObjNew;
+ assert( nVars <= 16 );
+ // create a new network
+ pNew = Kit_DsdNtkAlloc( nVars );
+ // consider simple special cases
+ if ( nVars == 0 )
+ {
+ pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 );
+ pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, (int)(pTruth[0] == 0) );
+ return pNew;
+ }
+ if ( nVars == 1 )
+ {
+ pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 );
+ pObjNew->pFans[0] = Kit_DsdVar2Lit( 0, 0 );
+ pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, (int)(pTruth[0] != 0xAAAAAAAA) );
+ return pNew;
+ }
+*/
return Kit_DsdDecomposeInt( pTruth, nVars, nDecMux );
}
diff --git a/src/aig/kit/kitTruth.c b/src/aig/kit/kitTruth.c
index 9ddc7562..3f9188c7 100644
--- a/src/aig/kit/kitTruth.c
+++ b/src/aig/kit/kitTruth.c
@@ -155,7 +155,7 @@ void Kit_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int
of variables is nVars. The total number of variables in nVarsAll. The last argument
(Phase) contains shows where the variables should go.]
- SideEffects []
+ SideEffects [The input truth table is modified.]
SeeAlso []
@@ -189,7 +189,7 @@ void Kit_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll,
of variables is nVars. The total number of variables in nVarsAll. The last argument
(Phase) contains shows what variables should remain.]
- SideEffects []
+ SideEffects [The input truth table is modified.]
SeeAlso []
@@ -215,6 +215,43 @@ void Kit_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll,
Kit_TruthCopy( pOut, pIn, nVarsAll );
}
+/**Function*************************************************************
+
+ Synopsis [Implement give permutation.]
+
+ Description [The input and output truth tables are in pIn/pOut.
+ The number of variables is nVars. Permutation is in pPerm.]
+
+ SideEffects [The input truth table is modified.]
+
+ SeeAlso []
+
+***********************************************************************/
+void Kit_TruthPermute( unsigned * pOut, unsigned * pIn, int nVars, char * pPerm, int fReturnIn )
+{
+ int * pTemp;
+ int i, Temp, fChange, Counter = 0;
+ do {
+ fChange = 0;
+ for ( i = 0; i < nVars-1; i++ )
+ {
+ assert( pPerm[i] != pPerm[i+1] );
+ if ( pPerm[i] <= pPerm[i+1] )
+ continue;
+ Counter++;
+ fChange = 1;
+
+ Temp = pPerm[i];
+ pPerm[i] = pPerm[i+1];
+ pPerm[i+1] = Temp;
+
+ Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ }
+ } while ( fChange );
+ if ( fReturnIn ^ !(Counter & 1) )
+ Kit_TruthCopy( pOut, pIn, nVars );
+}
/**Function*************************************************************
@@ -1291,6 +1328,60 @@ void Kit_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore )
/**Function*************************************************************
+ Synopsis [Counts the number of 1's in each negative cofactor.]
+
+ Description [The resulting numbers are stored in the array of shorts,
+ whose length is nVars. The number of 1's is counted in a different
+ space than the original function. For example, if the function depends
+ on k variables, the cofactors are assumed to depend on k-1 variables.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Kit_TruthCountOnesInCofs0( unsigned * pTruth, int nVars, short * pStore )
+{
+ int nWords = Kit_TruthWordNum( nVars );
+ int i, k, Counter;
+ memset( pStore, 0, sizeof(short) * nVars );
+ if ( nVars <= 5 )
+ {
+ if ( nVars > 0 )
+ pStore[0] = Kit_WordCountOnes( pTruth[0] & 0x55555555 );
+ if ( nVars > 1 )
+ pStore[1] = Kit_WordCountOnes( pTruth[0] & 0x33333333 );
+ if ( nVars > 2 )
+ pStore[2] = Kit_WordCountOnes( pTruth[0] & 0x0F0F0F0F );
+ if ( nVars > 3 )
+ pStore[3] = Kit_WordCountOnes( pTruth[0] & 0x00FF00FF );
+ if ( nVars > 4 )
+ pStore[4] = Kit_WordCountOnes( pTruth[0] & 0x0000FFFF );
+ return;
+ }
+ // nVars >= 6
+ // count 1's for all other variables
+ for ( k = 0; k < nWords; k++ )
+ {
+ Counter = Kit_WordCountOnes( pTruth[k] );
+ for ( i = 5; i < nVars; i++ )
+ if ( (k & (1 << (i-5))) == 0 )
+ pStore[i] += Counter;
+ }
+ // count 1's for the first five variables
+ for ( k = 0; k < nWords/2; k++ )
+ {
+ pStore[0] += Kit_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) );
+ pStore[1] += Kit_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) );
+ pStore[2] += Kit_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) );
+ pStore[3] += Kit_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) );
+ pStore[4] += Kit_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) );
+ pTruth += 2;
+ }
+}
+
+/**Function*************************************************************
+
Synopsis [Counts the number of 1's in each cofactor.]
Description [Verifies the above procedure.]
@@ -1440,16 +1531,17 @@ unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars,
*/
// collect the minterm counts
Kit_TruthCountOnesInCofs( pIn, nVars, pStore );
-// Kit_TruthCountOnesInCofsSlow( pIn, nVars, pStore2, pAux );
-// for ( i = 0; i < 2*nVars; i++ )
-// {
-// assert( pStore[i] == pStore2[i] );
-// }
-
+/*
+ Kit_TruthCountOnesInCofsSlow( pIn, nVars, pStore2, pAux );
+ for ( i = 0; i < 2*nVars; i++ )
+ {
+ assert( pStore[i] == pStore2[i] );
+ }
+*/
// canonicize phase
for ( i = 0; i < nVars; i++ )
{
- if ( pStore[2*i+0] >= pStore[2*i+1] )
+ if ( pStore[2*i+0] <= pStore[2*i+1] )
continue;
uCanonPhase |= (1 << i);
Temp = pStore[2*i+0];
@@ -1463,11 +1555,12 @@ unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars,
// permute
Counter = 0;
+
do {
fChange = 0;
for ( i = 0; i < nVars-1; i++ )
{
- if ( pStore[2*i] >= pStore[2*(i+1)] )
+ if ( pStore[2*i] <= pStore[2*(i+1)] )
continue;
Counter++;
fChange = 1;
@@ -1485,17 +1578,18 @@ unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars,
pStore[2*(i+1)+1] = Temp;
// if the polarity of variables is different, swap them
- if ( ((uCanonPhase & (1 << i)) > 0) != ((uCanonPhase & (1 << (i+1))) > 0) )
- {
- uCanonPhase ^= (1 << i);
- uCanonPhase ^= (1 << (i+1));
- }
+// if ( ((uCanonPhase & (1 << i)) > 0) != ((uCanonPhase & (1 << (i+1))) > 0) )
+// {
+// uCanonPhase ^= (1 << i);
+// uCanonPhase ^= (1 << (i+1));
+// }
Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i );
pTemp = pIn; pIn = pOut; pOut = pTemp;
}
} while ( fChange );
+
/*
Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " );
for ( i = 0; i < nVars; i++ )
diff --git a/src/aig/mfx/mfx.h b/src/aig/mfx/mfx.h
index 783de56c..aae9e625 100644
--- a/src/aig/mfx/mfx.h
+++ b/src/aig/mfx/mfx.h
@@ -53,6 +53,7 @@ struct Mfx_Par_t_
int fMoreEffort; // performs high-affort minimization
int fSwapEdge; // performs edge swapping
int fDelay; // performs optimization for delay
+ int fPower; // performs power-aware optimization
int fVerbose; // enable basic stats
int fVeryVerbose; // enable detailed stats
};
diff --git a/src/aig/mfx/mfxCore.c b/src/aig/mfx/mfxCore.c
index d9f73c9d..f67fb520 100644
--- a/src/aig/mfx/mfxCore.c
+++ b/src/aig/mfx/mfxCore.c
@@ -53,6 +53,7 @@ void Mfx_ParsDefault( Mfx_Par_t * pPars )
pPars->fArea = 0;
pPars->fMoreEffort = 0;
pPars->fSwapEdge = 0;
+ pPars->fPower = 0;
pPars->fVerbose = 0;
pPars->fVeryVerbose = 0;
}
@@ -105,7 +106,9 @@ clk = clock();
return 1;
}
// solve the SAT problem
- if ( p->pPars->fSwapEdge )
+ if ( p->pPars->fPower )
+ Mfx_EdgePower( p, pNode );
+ else if ( p->pPars->fSwapEdge )
Mfx_EdgeSwapEval( p, pNode );
else
{
@@ -132,7 +135,7 @@ int Mfx_Node( Mfx_Man_t * p, Nwk_Obj_t * pNode )
{
Hop_Obj_t * pObj;
int RetValue;
-
+ float dProb;
int nGain, clk;
p->nNodesTried++;
// prepare data structure for this node
@@ -170,7 +173,8 @@ p->timeSat += clock() - clk;
}
// minimize the local function of the node using bi-decomposition
assert( p->nFanins == Nwk_ObjFaninNum(pNode) );
- pObj = Nwk_NodeIfNodeResyn( p->pManDec, pNode->pMan->pManHop, pNode->pFunc, p->nFanins, p->vTruth, p->uCare );
+ dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0;
+ pObj = Nwk_NodeIfNodeResyn( p->pManDec, pNode->pMan->pManHop, pNode->pFunc, p->nFanins, p->vTruth, p->uCare, dProb );
nGain = Hop_DagSize(pNode->pFunc) - Hop_DagSize(pObj);
if ( nGain >= 0 )
{
@@ -184,6 +188,45 @@ p->timeSat += clock() - clk;
/**Function*************************************************************
+ Synopsis [Marks nodes for power-optimization.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Nwk_ManPowerEstimate( Nwk_Man_t * pNtk, int fProbOne )
+{
+ extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+ Vec_Int_t * vProbs;
+ Vec_Int_t * vSwitching;
+ float * pProbability;
+ float * pSwitching;
+ Aig_Man_t * pAig;
+ Aig_Obj_t * pObjAig;
+ Nwk_Obj_t * pObjAbc;
+ int i;
+ // start the resulting array
+ vProbs = Vec_IntStart( Nwk_ManObjNumMax(pNtk) );
+ pProbability = (float *)vProbs->pArray;
+ // map network into an AIG
+ pAig = Nwk_ManStrash( pNtk );
+ vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, fProbOne );
+ pSwitching = (float *)vSwitching->pArray;
+ Nwk_ManForEachObj( pNtk, pObjAbc, i )
+ {
+ if ( (pObjAig = Aig_Regular(pObjAbc->pCopy)) )
+ pProbability[pObjAbc->Id] = pSwitching[pObjAig->Id];
+ }
+ Vec_IntFree( vSwitching );
+ Aig_ManStop( pAig );
+ return vProbs;
+}
+
+/**Function*************************************************************
+
Synopsis []
Description []
@@ -253,6 +296,17 @@ int Mfx_Perform( Nwk_Man_t * pNtk, Mfx_Par_t * pPars, If_Lib_t * pLutLib )
p->pManDec = Bdc_ManAlloc( pDecPars );
}
+ // precomputer power-aware metrics
+ if ( pPars->fPower )
+ {
+ extern Vec_Int_t * Nwk_ManPowerEstimate( Nwk_Man_t * pNtk, int fProbOne );
+ if ( pPars->fResub )
+ p->vProbs = Nwk_ManPowerEstimate( pNtk, 0 );
+ else
+ p->vProbs = Nwk_ManPowerEstimate( pNtk, 1 );
+ printf( "Total switching before = %7.2f.\n", Nwl_ManComputeTotalSwitching(pNtk) );
+ }
+
// compute don't-cares for each node
nNodes = 0;
p->nTotalNodesBeg = nTotalNodesBeg;
@@ -276,6 +330,7 @@ int Mfx_Perform( Nwk_Man_t * pNtk, Mfx_Par_t * pPars, If_Lib_t * pLutLib )
{
pProgress = Bar_ProgressStart( stdout, Nwk_ManNodeNum(pNtk) );
vLevels = Nwk_ManLevelize( pNtk );
+
Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 )
{
if ( !p->pPars->fVeryVerbose )
@@ -303,6 +358,7 @@ int Mfx_Perform( Nwk_Man_t * pNtk, Mfx_Par_t * pPars, If_Lib_t * pLutLib )
PRT( "Time", clock() - clk2 );
}
}
+
Bar_ProgressStop( pProgress );
Vec_VecFree( vLevels );
}
@@ -312,6 +368,9 @@ int Mfx_Perform( Nwk_Man_t * pNtk, Mfx_Par_t * pPars, If_Lib_t * pLutLib )
assert( Nwk_ManVerifyLevel( pNtk ) );
assert( Nwk_ManVerifyTiming( pNtk ) );
+ if ( pPars->fPower )
+ printf( "Total switching after = %7.2f.\n", Nwl_ManComputeTotalSwitching(pNtk) );
+
// free the manager
p->timeTotal = clock() - clk;
Mfx_ManStop( p );
diff --git a/src/aig/mfx/mfxInt.h b/src/aig/mfx/mfxInt.h
index 0693200d..9095c8ce 100644
--- a/src/aig/mfx/mfxInt.h
+++ b/src/aig/mfx/mfxInt.h
@@ -81,6 +81,8 @@ struct Mfx_Man_t_
Vec_Ptr_t * vFanins; // the new set of fanins
int nTotConfLim; // total conflict limit
int nTotConfLevel; // total conflicts on this level
+ // switching activity
+ Vec_Int_t * vProbs;
// the result of solving
int nFanins; // the number of fanins
int nWords; // the number of words
@@ -136,6 +138,7 @@ extern void Mfx_ManStop( Mfx_Man_t * p );
extern void Mfx_ManClean( Mfx_Man_t * p );
/*=== mfxResub.c ==========================================================*/
extern void Mfx_PrintResubStats( Mfx_Man_t * p );
+extern int Mfx_EdgePower( Mfx_Man_t * p, Nwk_Obj_t * pNode );
extern int Mfx_EdgeSwapEval( Mfx_Man_t * p, Nwk_Obj_t * pNode );
extern int Mfx_ResubNode( Mfx_Man_t * p, Nwk_Obj_t * pNode );
extern int Mfx_ResubNode2( Mfx_Man_t * p, Nwk_Obj_t * pNode );
diff --git a/src/aig/mfx/mfxMan.c b/src/aig/mfx/mfxMan.c
index 63531770..b8361a20 100644
--- a/src/aig/mfx/mfxMan.c
+++ b/src/aig/mfx/mfxMan.c
@@ -168,6 +168,8 @@ void Mfx_ManStop( Mfx_Man_t * p )
Aig_ManStop( p->pCare );
if ( p->vSuppsInv )
Vec_VecFree( (Vec_Vec_t *)p->vSuppsInv );
+ if ( p->vProbs )
+ Vec_IntFree( p->vProbs );
Mfx_ManClean( p );
Int_ManFree( p->pMan );
Vec_IntFree( p->vMem );
diff --git a/src/aig/mfx/mfxResub.c b/src/aig/mfx/mfxResub.c
index 006656ee..312ae226 100644
--- a/src/aig/mfx/mfxResub.c
+++ b/src/aig/mfx/mfxResub.c
@@ -206,6 +206,8 @@ p->timeInt += clock() - clk;
iVar = -1;
while ( 1 )
{
+ float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL);
+ assert( (pProbab != NULL) == p->pPars->fPower );
if ( fVeryVerbose )
{
printf( "%3d: %2d ", p->nCexes, iVar );
@@ -222,6 +224,13 @@ p->timeInt += clock() - clk;
assert( nWords <= p->nDivWords );
for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Nwk_ObjFaninNum(pNode); iVar++ )
{
+ if ( p->pPars->fPower )
+ {
+ Nwk_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar);
+ // only accept the divisor if it is "cool"
+ if ( pProbab[Nwk_ObjId(pDiv)] >= 0.2 )
+ continue;
+ }
pData = Vec_PtrEntry( p->vDivCexes, iVar );
for ( w = 0; w < nWords; w++ )
if ( pData[w] != ~0 )
@@ -431,6 +440,33 @@ int Mfx_EdgeSwapEval( Mfx_Man_t * p, Nwk_Obj_t * pNode )
/**Function*************************************************************
+ Synopsis [Evaluates the possibility of replacing given edge by another edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mfx_EdgePower( Mfx_Man_t * p, Nwk_Obj_t * pNode )
+{
+ Nwk_Obj_t * pFanin;
+ float * pProbab = (float *)p->vProbs->pArray;
+ int i;
+ // try replacing area critical fanins
+ Nwk_ObjForEachFanin( pNode, pFanin, i )
+ if ( pProbab[pFanin->Id] >= 0.4 )
+ {
+ if ( Mfx_SolveSatResub( p, pNode, i, 0, 0 ) )
+ return 1;
+ }
+ return 0;
+}
+
+
+/**Function*************************************************************
+
Synopsis [Performs resubstitution for the node.]
Description []
diff --git a/src/aig/ntl/ntl.h b/src/aig/ntl/ntl.h
index 54db901f..ac266ca5 100644
--- a/src/aig/ntl/ntl.h
+++ b/src/aig/ntl/ntl.h
@@ -79,6 +79,10 @@ struct Ntl_Man_t_
Aig_Man_t * pAig; // the extracted AIG
Tim_Man_t * pManTime; // the timing manager
int iLastCi; // the last true CI
+ void * pNal; // additional data
+ void (*pNalF)(void *); // additional data
+ void (*pNalD)(void *,void *); // additional data
+ void (*pNalW)(void *,void *); // additional data
// hashing names into models
Ntl_Mod_t ** pModTable; // the hash table of names into models
int nModTableSize; // the allocated table size
@@ -93,6 +97,7 @@ struct Ntl_Mod_t_
Vec_Ptr_t * vObjs; // the array of all objects
Vec_Ptr_t * vPis; // the array of PI objects
Vec_Ptr_t * vPos; // the array of PO objects
+ Vec_Ptr_t * vNets; // the array of nets
int nObjs[NTL_OBJ_VOID]; // counter of objects of each type
// box attributes
unsigned int attrWhite :1; // box has known logic
@@ -104,6 +109,9 @@ struct Ntl_Mod_t_
Ntl_Net_t ** pTable; // the hash table of names into nets
int nTableSize; // the allocated table size
int nEntries; // the number of entries in the hash table
+ // clocks of the model
+ Vec_Ptr_t * vClocks; // the clock signals
+ Vec_Vec_t * vClockFlops; // the flops of each clock
// delay information
Vec_Int_t * vDelays;
Vec_Int_t * vTimeInputs;
@@ -154,6 +162,7 @@ struct Ntl_Net_t_
int iTemp; // other data
};
Ntl_Obj_t * pDriver; // driver of the net
+ int NetId; // unique ID of the net
char nVisits; // the number of times the net is visited
char fMark; // temporary mark
char pName[0]; // the name of this net
@@ -175,18 +184,19 @@ struct Ntl_Lut_t_
////////////////////////////////////////////////////////////////////////
/// INLINED FUNCTIONS ///
////////////////////////////////////////////////////////////////////////
+
#ifdef WIN32
-#define DLLEXPORT __declspec(dllexport)
-#define DLLIMPORT __declspec(dllimport)
+#define ABC_DLLEXPORT __declspec(dllexport)
+#define ABC_DLLIMPORT __declspec(dllimport)
#else /* defined(WIN32) */
-#define DLLIMPORT
+#define ABC_DLLIMPORT
#endif /* defined(WIN32) */
#ifndef ABC_DLL
-#define ABC_DLL DLLIMPORT
+#define ABC_DLL ABC_DLLIMPORT
#endif
-static inline Ntl_Mod_t * Ntl_ManRootModel( Ntl_Man_t * p ) { return (Ntl_Mod_t *)Vec_PtrEntry( p->vModels, 0 ); }
+static inline Ntl_Mod_t * Ntl_ManRootModel( Ntl_Man_t * p ) { return (Ntl_Mod_t *)Vec_PtrEntry( p->vModels, 0 ); }
static inline int Ntl_ModelPiNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PI]; }
static inline int Ntl_ModelPoNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PO]; }
@@ -195,8 +205,10 @@ static inline int Ntl_ModelLut1Num( Ntl_Mod_t * p ) { return p->nO
static inline int Ntl_ModelLatchNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_LATCH]; }
static inline int Ntl_ModelBoxNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_BOX]; }
-static inline Ntl_Obj_t * Ntl_ModelPi( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vPis, i); }
-static inline Ntl_Obj_t * Ntl_ModelPo( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vPos, i); }
+static inline Ntl_Obj_t * Ntl_ModelPi( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vPis, i); }
+static inline Ntl_Obj_t * Ntl_ModelPo( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vPos, i); }
+static inline Ntl_Obj_t * Ntl_ModelObj( Ntl_Mod_t * p, int i ) { return (Ntl_Obj_t *)Vec_PtrEntry(p->vObjs, i); }
+static inline Ntl_Net_t * Ntl_ModelNet( Ntl_Mod_t * p, int i ) { return (Ntl_Net_t *)Vec_PtrEntry(p->vNets, i); }
static inline char * Ntl_ModelPiName( Ntl_Mod_t * p, int i ) { return Ntl_ModelPi(p, i)->pFanio[0]->pName; }
static inline char * Ntl_ModelPoName( Ntl_Mod_t * p, int i ) { return Ntl_ModelPo(p, i)->pFanio[0]->pName; }
@@ -253,8 +265,8 @@ static inline int Ntl_ObjIsSeqRoot( Ntl_Obj_t * p ) { return Ntl_O
#define Ntl_ModelForEachPo( pNwk, pObj, i ) \
for ( i = 0; (i < Vec_PtrSize(pNwk->vPos)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vPos, i)), 1); i++ )
#define Ntl_ModelForEachNet( pNwk, pNet, i ) \
- for ( i = 0; i < pNwk->nTableSize; i++ ) \
- for ( pNet = pNwk->pTable[i]; pNet; pNet = pNet->pNext )
+ Vec_PtrForEachEntry( pNwk->vNets, pNet, i ) \
+ if ( pNet == NULL ) {} else
#define Ntl_ModelForEachObj( pNwk, pObj, i ) \
for ( i = 0; (i < Vec_PtrSize(pNwk->vObjs)) && (((pObj) = (Ntl_Obj_t*)Vec_PtrEntry(pNwk->vObjs, i)), 1); i++ ) \
if ( pObj == NULL ) {} else
@@ -359,6 +371,7 @@ extern ABC_DLL int Ntl_ModelFindPioNumber( Ntl_Mod_t * p, int fPiOnl
extern ABC_DLL int Ntl_ModelSetNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet );
extern ABC_DLL int Ntl_ModelClearNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet );
extern ABC_DLL void Ntl_ModelDeleteNet( Ntl_Mod_t * p, Ntl_Net_t * pNet );
+extern ABC_DLL void Ntl_ModelInsertNet( Ntl_Mod_t * p, Ntl_Net_t * pNet );
extern ABC_DLL int Ntl_ModelCountNets( Ntl_Mod_t * p );
extern ABC_DLL int Ntl_ManAddModel( Ntl_Man_t * p, Ntl_Mod_t * pModel );
extern ABC_DLL Ntl_Mod_t * Ntl_ManFindModel( Ntl_Man_t * p, const char * pName );
diff --git a/src/aig/ntl/ntlCheck.c b/src/aig/ntl/ntlCheck.c
index 47f14525..82ef388b 100644
--- a/src/aig/ntl/ntlCheck.c
+++ b/src/aig/ntl/ntlCheck.c
@@ -206,11 +206,13 @@ checkobjs:
printf( "Net in bin %d does not have a name\n", i );
fStatus = 0;
}
+/*
if ( pNet->pDriver == NULL )
{
printf( "Net %s does not have a driver\n", pNet->pName );
fStatus = 0;
}
+*/
}
// check objects
diff --git a/src/aig/ntl/ntlCore.c b/src/aig/ntl/ntlCore.c
index 6bff57d9..b170cdad 100644
--- a/src/aig/ntl/ntlCore.c
+++ b/src/aig/ntl/ntlCore.c
@@ -43,14 +43,14 @@
Aig_Man_t * Ntl_ManPerformChoicing( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose )
{
extern Aig_Man_t * Dar_ManBalance( Aig_Man_t * pAig, int fUpdateLevel );
- extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose );
+ extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose );
extern Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose );
Aig_Man_t * pTemp;
// perform synthesis
//printf( "Pre-synthesis AIG: " );
//Aig_ManPrintStats( pAig );
// pTemp = Dar_ManBalance( pAig, 1 );
-// pTemp = Dar_ManCompress( pAig, 1, 1, 0 );
+// pTemp = Dar_ManCompress( pAig, 1, 1, 0, 0 );
pTemp = Dar_ManChoice( pAig, fBalance, fUpdateLevel, fConstruct, nConfMax, nLevelMax, fVerbose );
//printf( "Post-synthesis AIG: " );
//Aig_ManPrintStats( pTemp );
diff --git a/src/aig/ntl/ntlExtract.c b/src/aig/ntl/ntlExtract.c
index 56710a25..6923ac7a 100644
--- a/src/aig/ntl/ntlExtract.c
+++ b/src/aig/ntl/ntlExtract.c
@@ -175,7 +175,7 @@ int Ntl_ManExtract_rec( Ntl_Man_t * p, Ntl_Net_t * pNet )
if ( !Ntl_ManExtract_rec( p, pNetFanin ) )
return 0;
// add box inputs/outputs to COs/CIs
- if ( Ntl_ObjIsBox(pObj) )
+ if ( Ntl_ObjIsBox(pObj) )
{
int LevelCur, LevelMax = -TIM_ETERNITY;
assert( Ntl_BoxIsComb(pObj) );
@@ -370,7 +370,7 @@ int Ntl_ManCollapseBoxSeq1_rec( Ntl_Man_t * p, Ntl_Obj_t * pBox, int fSeq )
pNet->pCopy = Aig_Not(pNet->pCopy);
pNet->nVisits = 2;
// remember the class of this register
- Vec_IntPush( p->vRegClasses, pObj->LatchId.regClass );
+ Vec_IntPush( p->vRegClasses, p->pNal ? pBox->iTemp : pObj->LatchId.regClass );
}
// compute AIG for the internal nodes
Ntl_ModelForEachPo( pModel, pObj, i )
diff --git a/src/aig/ntl/ntlFraig.c b/src/aig/ntl/ntlFraig.c
index 27d863af..d2ae4204 100644
--- a/src/aig/ntl/ntlFraig.c
+++ b/src/aig/ntl/ntlFraig.c
@@ -215,9 +215,9 @@ Aig_Obj_t ** Ntl_ManFraigDeriveClasses( Aig_Man_t * pAig, Ntl_Man_t * pNew, Aig_
void Ntl_ManReduce( Ntl_Man_t * p, Aig_Man_t * pAig )
{
Aig_Obj_t * pObj, * pObjRepr;
- Ntl_Net_t * pNet, * pNetRepr;
+ Ntl_Net_t * pNet, * pNetRepr, * pNetNew;
Ntl_Mod_t * pRoot;
- Ntl_Obj_t * pNode;
+ Ntl_Obj_t * pNode, * pNodeOld;
int i, fCompl, Counter = 0;
assert( pAig->pReprs );
pRoot = Ntl_ManRootModel( p );
@@ -271,10 +271,23 @@ void Ntl_ManReduce( Ntl_Man_t * p, Aig_Man_t * pAig )
pNode->pSop = fCompl? Ntl_ManStoreSop( p->pMemSops, "0 1\n" ) : Ntl_ManStoreSop( p->pMemSops, "1 1\n" );
Ntl_ObjSetFanin( pNode, pNetRepr, 0 );
// make the new node drive the equivalent net (pNet)
+ pNodeOld = pNet->pDriver;
if ( !Ntl_ModelClearNetDriver( pNet->pDriver, pNet ) )
printf( "Ntl_ManReduce(): Internal error! Net already has no driver.\n" );
if ( !Ntl_ModelSetNetDriver( pNode, pNet ) )
printf( "Ntl_ManReduce(): Internal error! Net already has a driver.\n" );
+
+ // remove this net from the hash table (but do not remove from the array)
+ Ntl_ModelDeleteNet( pRoot, pNet );
+ // create new net with the same name
+ pNetNew = Ntl_ModelFindOrCreateNet( pRoot, pNet->pName );
+ // clean the name
+ pNet->pName[0] = 0;
+
+ // make the old node drive the new net without fanouts
+ if ( !Ntl_ModelSetNetDriver( pNodeOld, pNetNew ) )
+ printf( "Ntl_ManReduce(): Internal error! Net already has a driver.\n" );
+
Counter++;
}
}
@@ -372,6 +385,11 @@ Ntl_Man_t * Ntl_ManFraig( Ntl_Man_t * p, int nPartSize, int nConfLimit, int nLev
pAig = Ntl_ManExtract( p );
pNew = Ntl_ManInsertAig( p, pAig );
pAigCol = Ntl_ManCollapseComb( pNew );
+ if ( pAigCol == NULL )
+ {
+ Aig_ManStop( pAig );
+ return pNew;
+ }
// perform fraiging for the given design
nPartSize = nPartSize? nPartSize : Aig_ManPoNum(pAigCol);
@@ -406,13 +424,15 @@ Ntl_Man_t * Ntl_ManScl( Ntl_Man_t * p, int fLatchConst, int fLatchEqual, int fVe
pAig = Ntl_ManExtract( p );
pNew = Ntl_ManInsertAig( p, pAig );
pAigCol = Ntl_ManCollapseSeq( pNew, 0 );
-//Saig_ManDumpBlif( pAigCol, "1s.blif" );
+ if ( pAigCol == NULL )
+ {
+ Aig_ManStop( pAig );
+ return pNew;
+ }
// perform SCL for the given design
pTemp = Aig_ManScl( pAigCol, fLatchConst, fLatchEqual, fVerbose );
Aig_ManStop( pTemp );
- if ( pNew->vRegClasses && Vec_IntSize(pNew->vRegClasses) && pAigCol->pReprs )
- Ntl_ManFilterRegisterClasses( pAigCol, pNew->vRegClasses, fVerbose );
// finalize the transformation
pNew = Ntl_ManFinalize( pAux = pNew, pAig, pAigCol, fVerbose );
@@ -435,25 +455,26 @@ Ntl_Man_t * Ntl_ManScl( Ntl_Man_t * p, int fLatchConst, int fLatchEqual, int fVe
***********************************************************************/
Ntl_Man_t * Ntl_ManLcorr( Ntl_Man_t * p, int nConfMax, int fVerbose )
{
- Ssw_Pars_t Pars, * pPars = &Pars;
Ntl_Man_t * pNew, * pAux;
Aig_Man_t * pAig, * pAigCol, * pTemp;
+ Ssw_Pars_t Pars, * pPars = &Pars;
+ Ssw_ManSetDefaultParamsLcorr( pPars );
+ pPars->nBTLimit = nConfMax;
+ pPars->fVerbose = fVerbose;
// collapse the AIG
pAig = Ntl_ManExtract( p );
pNew = Ntl_ManInsertAig( p, pAig );
- pAigCol = Ntl_ManCollapseSeq( pNew, 0 );
+ pAigCol = Ntl_ManCollapseSeq( pNew, pPars->nMinDomSize );
+ if ( pAigCol == NULL )
+ {
+ Aig_ManStop( pAig );
+ return pNew;
+ }
- // perform SCL for the given design
-// pTemp = Fra_FraigLatchCorrespondence( pAigCol, 0, nConfMax, 0, fVerbose, NULL, 0 );
- Ssw_ManSetDefaultParamsLcorr( pPars );
- pPars->nBTLimit = nConfMax;
- pPars->fVerbose = fVerbose;
+ // perform LCORR for the given design
pTemp = Ssw_LatchCorrespondence( pAigCol, pPars );
-
Aig_ManStop( pTemp );
- if ( p->vRegClasses && Vec_IntSize(p->vRegClasses) && pAigCol->pReprs )
- Ntl_ManFilterRegisterClasses( pAigCol, p->vRegClasses, fVerbose );
// finalize the transformation
pNew = Ntl_ManFinalize( pAux = pNew, pAig, pAigCol, fVerbose );
diff --git a/src/aig/ntl/ntlInsert.c b/src/aig/ntl/ntlInsert.c
index 52f76151..21f2d246 100644
--- a/src/aig/ntl/ntlInsert.c
+++ b/src/aig/ntl/ntlInsert.c
@@ -42,7 +42,7 @@
***********************************************************************/
Ntl_Man_t * Ntl_ManInsertMapping( Ntl_Man_t * p, Vec_Ptr_t * vMapping, Aig_Man_t * pAig )
{
- char Buffer[100];
+ char Buffer[1000];
Vec_Ptr_t * vCopies;
Vec_Int_t * vCover;
Ntl_Mod_t * pRoot;
@@ -141,7 +141,7 @@ Ntl_Man_t * Ntl_ManInsertMapping( Ntl_Man_t * p, Vec_Ptr_t * vMapping, Aig_Man_t
***********************************************************************/
Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig )
{
- char Buffer[100];
+ char Buffer[1000];
Ntl_Mod_t * pRoot;
Ntl_Obj_t * pNode;
Ntl_Net_t * pNet, * pNetCo;
@@ -243,7 +243,6 @@ Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig )
return p;
}
-
/**Function*************************************************************
Synopsis [Inserts the given mapping into the netlist.]
@@ -257,7 +256,7 @@ Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig )
***********************************************************************/
Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk )
{
- char Buffer[100];
+ char Buffer[1000];
Vec_Ptr_t * vObjs;
Vec_Int_t * vTruth;
Vec_Int_t * vCover;
@@ -276,8 +275,8 @@ Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk )
Ntl_ManForEachCiNet( p, pNet, i )
Nwk_ManCi( pNtk, i )->pCopy = pNet;
// create a new node for each LUT
- vTruth = Vec_IntAlloc( 1 << 16 );
- vCover = Vec_IntAlloc( 1 << 16 );
+ vTruth = Vec_IntAlloc( 1 << 16 );
+ vCover = Vec_IntAlloc( 1 << 16 );
nDigits = Aig_Base10Log( Nwk_ManNodeNum(pNtk) );
// go through the nodes in the topological order
vObjs = Nwk_ManDfs( pNtk );
@@ -289,7 +288,6 @@ Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk )
pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 );
if ( Hop_IsComplement(pObj->pFunc) )
Kit_TruthNot( pTruth, pTruth, Nwk_ObjFaninNum(pObj) );
- pNode->pSop = Kit_PlaFromTruth( p->pMemSops, pTruth, Nwk_ObjFaninNum(pObj), vCover );
if ( !Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) && !Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) )
{
Nwk_ObjForEachFanin( pObj, pFanin, k )
@@ -303,8 +301,17 @@ Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk )
Ntl_ObjSetFanin( pNode, pNet, k );
}
}
- else
+ else if ( Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) )
+ {
+ pObj->pFunc = Hop_ManConst0(pNtk->pManHop);
pNode->nFanins = 0;
+ }
+ else if ( Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) )
+ {
+ pObj->pFunc = Hop_ManConst1(pNtk->pManHop);
+ pNode->nFanins = 0;
+ }
+ pNode->pSop = Kit_PlaFromTruth( p->pMemSops, pTruth, Nwk_ObjFaninNum(pObj), vCover );
sprintf( Buffer, "lut%0*d", nDigits, i );
if ( (pNet = Ntl_ModelFindNet( pRoot, Buffer )) )
{
@@ -334,11 +341,29 @@ Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk )
// get the corresponding PO and its driver
pObj = Nwk_ManCo( pNtk, i );
pFanin = Nwk_ObjFanin0( pObj );
- // get the net driving the driver
- pNet = pFanin->pCopy;
- pNode = Ntl_ModelCreateNode( pRoot, 1 );
- pNode->pSop = pObj->fInvert? Ntl_ManStoreSop( p->pMemSops, "0 1\n" ) : Ntl_ManStoreSop( p->pMemSops, "1 1\n" );
- Ntl_ObjSetFanin( pNode, pNet, 0 );
+ // get the net driving this PO
+ pNet = pFanin->pCopy;
+ if ( Nwk_ObjFanoutNum(pFanin) == 1 && Ntl_ObjIsNode(pNet->pDriver) )
+ {
+ pNode = pNet->pDriver;
+ if ( !Ntl_ModelClearNetDriver( pNode, pNet ) )
+ {
+ printf( "Ntl_ManInsertNtk(): Internal error! Net already has no driver.\n" );
+ return NULL;
+ }
+ // remove this net
+ Ntl_ModelDeleteNet( pRoot, pNet );
+ Vec_PtrWriteEntry( pRoot->vNets, pNet->NetId, NULL );
+ // update node's function
+ if ( pObj->fInvert )
+ Kit_PlaComplement( pNode->pSop );
+ }
+ else
+ {
+ pNode = Ntl_ModelCreateNode( pRoot, 1 );
+ pNode->pSop = pObj->fInvert? Ntl_ManStoreSop( p->pMemSops, "0 1\n" ) : Ntl_ManStoreSop( p->pMemSops, "1 1\n" );
+ Ntl_ObjSetFanin( pNode, pNet, 0 );
+ }
// update the CO driver net
assert( pNetCo->pDriver == NULL );
if ( !Ntl_ModelSetNetDriver( pNode, pNetCo ) )
diff --git a/src/aig/ntl/ntlMan.c b/src/aig/ntl/ntlMan.c
index dd481537..8b26e405 100644
--- a/src/aig/ntl/ntlMan.c
+++ b/src/aig/ntl/ntlMan.c
@@ -108,6 +108,7 @@ Ntl_Man_t * Ntl_ManStartFrom( Ntl_Man_t * pOld )
pNew->pName = Ntl_ManStoreFileName( pNew, pOld->pName );
pNew->pSpec = Ntl_ManStoreName( pNew, pOld->pName );
Vec_PtrForEachEntry( pOld->vModels, pModel, i )
+ {
if ( i == 0 )
{
Ntl_ManMarkCiCoNets( pOld );
@@ -116,15 +117,21 @@ Ntl_Man_t * Ntl_ManStartFrom( Ntl_Man_t * pOld )
}
else
pModel->pCopy = Ntl_ModelDup( pNew, pModel );
+ }
Vec_PtrForEachEntry( pOld->vModels, pModel, i )
Ntl_ModelForEachBox( pModel, pBox, k )
+ {
((Ntl_Obj_t *)pBox->pCopy)->pImplem = pBox->pImplem->pCopy;
+ ((Ntl_Obj_t *)pBox->pCopy)->iTemp = pBox->iTemp;
+ }
Ntl_ManForEachCiNet( pOld, pNet, i )
Vec_PtrPush( pNew->vCis, pNet->pCopy );
Ntl_ManForEachCoNet( pOld, pNet, i )
Vec_PtrPush( pNew->vCos, pNet->pCopy );
if ( pOld->pManTime )
pNew->pManTime = Tim_ManDup( pOld->pManTime, 0 );
+ if ( pOld->pNal )
+ pOld->pNalD( pOld, pNew );
return pNew;
}
@@ -195,13 +202,14 @@ void Ntl_ManFree( Ntl_Man_t * p )
if ( p->pMemSops ) Aig_MmFlexStop( p->pMemSops, 0 );
if ( p->pAig ) Aig_ManStop( p->pAig );
if ( p->pManTime ) Tim_ManStop( p->pManTime );
+ if ( p->pNal ) p->pNalF( p->pNal );
FREE( p->pModTable );
free( p );
}
/**Function*************************************************************
- Synopsis [Deallocates the netlist manager.]
+ Synopsis []
Description []
@@ -219,6 +227,7 @@ void Ntl_ManPrintStats( Ntl_Man_t * p )
printf( "po = %5d ", Ntl_ModelPoNum(pRoot) );
printf( "lat = %5d ", Ntl_ModelLatchNum(pRoot) );
printf( "node = %5d ", Ntl_ModelNodeNum(pRoot) );
+ printf( "\n " );
printf( "inv/buf = %5d ", Ntl_ModelLut1Num(pRoot) );
printf( "box = %4d ", Ntl_ModelBoxNum(pRoot) );
printf( "mod = %3d ", Vec_PtrSize(p->vModels) );
@@ -230,6 +239,50 @@ void Ntl_ManPrintStats( Ntl_Man_t * p )
fflush( stdout );
}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Nwk_ManPrintStatsShort( Ntl_Man_t * p, Aig_Man_t * pAig, Nwk_Man_t * pNtk )
+{
+ Ntl_Mod_t * pRoot;
+ Ntl_Obj_t * pObj;
+ int i, Counter = 0;
+ pRoot = Ntl_ManRootModel( p );
+ Ntl_ModelForEachBox( pRoot, pObj, i )
+ if ( strcmp(pObj->pImplem->pName, "dff") == 0 )
+ Counter++;
+ printf( "%-15s : ", p->pName );
+ printf( "pi =%5d ", Ntl_ModelPiNum(pRoot) );
+ printf( "po =%5d ", Ntl_ModelPoNum(pRoot) );
+ printf( "ff =%5d ", Counter );
+ if ( pAig != NULL )
+ {
+ Counter = Aig_ManCountChoices( pAig );
+ if ( Counter )
+ printf( "cho =%7d ", Counter );
+ else
+ printf( "aig =%7d ", Aig_ManNodeNum(pAig) );
+ }
+ if ( pNtk == NULL )
+ printf( "Mapping is not available.\n" );
+ else
+ {
+ printf( "lut =%5d ", Nwk_ManNodeNum(pNtk) );
+ printf( "lev =%3d ", Nwk_ManLevel(pNtk) );
+// printf( "del =%5.2f ", Nwk_ManDelayTraceLut(pNtk) );
+ printf( "\n" );
+ }
+}
+
/**Function*************************************************************
Synopsis [Deallocates the netlist manager.]
@@ -283,6 +336,8 @@ void Ntl_ManSaveBoxType( Ntl_Obj_t * pObj )
***********************************************************************/
void Ntl_ManPrintTypes( Ntl_Man_t * p )
{
+ Vec_Ptr_t * vFlops;
+ Ntl_Net_t * pNet;
Ntl_Mod_t * pModel;
Ntl_Obj_t * pObj;
int i;
@@ -296,7 +351,7 @@ void Ntl_ManPrintTypes( Ntl_Man_t * p )
{
if ( !p->BoxTypes[i] )
continue;
- printf( "%5d :", p->BoxTypes[i] );
+ printf( "Type %2d Num = %7d :", i, p->BoxTypes[i] );
printf( " %s", ((i & 1) > 0)? "white ": "black " );
printf( " %s", ((i & 2) > 0)? "box ": "logic " );
printf( " %s", ((i & 4) > 0)? "comb ": "seq " );
@@ -304,9 +359,22 @@ void Ntl_ManPrintTypes( Ntl_Man_t * p )
printf( " %s", ((i & 16) > 0)? "no_merge": "merge " );
printf( "\n" );
}
- printf( "Total box instances = %6d.\n\n", Ntl_ModelBoxNum(pModel) );
+ printf( "MODEL STATISTICS:\n" );
+ Ntl_ManForEachModel( p, pModel, i )
+ if ( i ) printf( "Model %2d : Name = %10s Used = %6d.\n", i, pModel->pName, pModel->nUsed );
for ( i = 0; i < 32; i++ )
p->BoxTypes[i] = 0;
+ pModel = Ntl_ManRootModel( p );
+ if ( pModel->vClockFlops )
+ {
+ printf( "CLOCK STATISTICS:\n" );
+ Vec_VecForEachLevel( pModel->vClockFlops, vFlops, i )
+ {
+ pNet = Vec_PtrEntry( pModel->vClocks, i );
+ printf( "Clock %2d : Name = %30s Flops = %6d.\n", i+1, pNet->pName, Vec_PtrSize(vFlops) );
+ }
+ }
+ printf( "\n" );
}
/**Function*************************************************************
@@ -336,6 +404,7 @@ Ntl_Mod_t * Ntl_ModelAlloc( Ntl_Man_t * pMan, char * pName )
p->vObjs = Vec_PtrAlloc( 100 );
p->vPis = Vec_PtrAlloc( 10 );
p->vPos = Vec_PtrAlloc( 10 );
+ p->vNets = Vec_PtrAlloc( 100 );
// start the table
p->nTableSize = Aig_PrimeCudd( 100 );
p->pTable = ALLOC( Ntl_Net_t *, p->nTableSize );
@@ -382,7 +451,9 @@ Ntl_Mod_t * Ntl_ModelStartFrom( Ntl_Man_t * pManNew, Ntl_Mod_t * pModelOld )
}
Ntl_ModelForEachNet( pModelOld, pNet, i )
{
- if ( pNet->fMark )
+ if ( pNet->pDriver == NULL )
+ pNet->pCopy = Ntl_ModelFindOrCreateNet( pModelNew, pNet->pName );
+ else if ( pNet->fMark )
{
pNet->pCopy = Ntl_ModelFindOrCreateNet( pModelNew, pNet->pName );
((Ntl_Net_t *)pNet->pCopy)->pDriver = pNet->pDriver->pCopy;
@@ -485,6 +556,9 @@ void Ntl_ModelFree( Ntl_Mod_t * p )
if ( p->vTimeOutputs ) Vec_IntFree( p->vTimeOutputs );
if ( p->vTimeInputs ) Vec_IntFree( p->vTimeInputs );
if ( p->vDelays ) Vec_IntFree( p->vDelays );
+ if ( p->vClocks ) Vec_PtrFree( p->vClocks );
+ if ( p->vClockFlops ) Vec_VecFree( p->vClockFlops );
+ Vec_PtrFree( p->vNets );
Vec_PtrFree( p->vObjs );
Vec_PtrFree( p->vPis );
Vec_PtrFree( p->vPos );
diff --git a/src/aig/ntl/ntlReadBlif.c b/src/aig/ntl/ntlReadBlif.c
index d1a1b99d..3021d556 100644
--- a/src/aig/ntl/ntlReadBlif.c
+++ b/src/aig/ntl/ntlReadBlif.c
@@ -1322,6 +1322,7 @@ static char * Ioa_ReadParseTableBlif( Ioa_ReadMod_t * p, char * pTable, int nFan
char * pProduct, * pOutput;
int i, Polarity = -1;
+
p->pMan->nTablesRead++;
// get the tokens
Ioa_ReadSplitIntoTokens( vTokens, pTable, '.' );
@@ -1330,6 +1331,8 @@ static char * Ioa_ReadParseTableBlif( Ioa_ReadMod_t * p, char * pTable, int nFan
if ( Vec_PtrSize(vTokens) == 1 )
{
pOutput = Vec_PtrEntry( vTokens, 0 );
+ if ( *pOutput == '\"' )
+ return Ntl_ManStoreSop( p->pMan->pDesign->pMemSops, pOutput );
if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
{
sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Ioa_ReadGetLine(p->pMan, pOutput), pOutput );
diff --git a/src/aig/ntl/ntlSweep.c b/src/aig/ntl/ntlSweep.c
index fc95415d..b2c700fb 100644
--- a/src/aig/ntl/ntlSweep.c
+++ b/src/aig/ntl/ntlSweep.c
@@ -139,8 +139,11 @@ int Ntl_ManSweep( Ntl_Man_t * p, int fVerbose )
}
// remove the fanout nets
Ntl_ObjForEachFanout( pObj, pNet, k )
- if ( pNet != NULL )
+ if ( pNet != NULL && pNet->pName[0] != 0 )
+ {
Ntl_ModelDeleteNet( pRoot, pNet );
+ Vec_PtrWriteEntry( pRoot->vNets, pNet->NetId, NULL );
+ }
// remove the object
if ( Ntl_ObjIsNode(pObj) && Ntl_ObjFaninNum(pObj) == 1 )
pRoot->nObjs[NTL_OBJ_LUT1]--;
@@ -150,7 +153,7 @@ int Ntl_ManSweep( Ntl_Man_t * p, int fVerbose )
pObj->Type = NTL_OBJ_NONE;
Counter++;
}
-
+
// print detailed statistics of sweeping
@@ -191,7 +194,7 @@ int Ntl_ManSweep( Ntl_Man_t * p, int fVerbose )
}
}
}
- printf("\nLUTboxType =%d\n", numLutBox);
+// printf("\nLUTboxType =%d\n", numLutBox);
}
}
if ( !Ntl_ManCheck( p ) )
diff --git a/src/aig/ntl/ntlTable.c b/src/aig/ntl/ntlTable.c
index aa122900..62f65d6c 100644
--- a/src/aig/ntl/ntlTable.c
+++ b/src/aig/ntl/ntlTable.c
@@ -58,6 +58,8 @@ Ntl_Net_t * Ntl_ModelCreateNet( Ntl_Mod_t * p, const char * pName )
pNet = (Ntl_Net_t *)Aig_MmFlexEntryFetch( p->pMan->pMemObjs, sizeof(Ntl_Net_t) + strlen(pName) + 1 );
memset( pNet, 0, sizeof(Ntl_Net_t) );
strcpy( pNet->pName, pName );
+ pNet->NetId = Vec_PtrSize( p->vNets );
+ Vec_PtrPush( p->vNets, pNet );
return pNet;
}
@@ -104,7 +106,7 @@ clk = clock();
/**Function*************************************************************
- Synopsis [Finds or creates the net.]
+ Synopsis [Finds net.]
Description []
@@ -125,7 +127,7 @@ Ntl_Net_t * Ntl_ModelFindNet( Ntl_Mod_t * p, const char * pName )
/**Function*************************************************************
- Synopsis [Finds or creates the net.]
+ Synopsis [Deletes net from the hash table.]
Description []
@@ -150,6 +152,26 @@ void Ntl_ModelDeleteNet( Ntl_Mod_t * p, Ntl_Net_t * pNet )
p->pTable[Key] = pEnt->pNext;
else
pPrev->pNext = pEnt->pNext;
+ p->nEntries--;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts net into the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ntl_ModelInsertNet( Ntl_Mod_t * p, Ntl_Net_t * pNet )
+{
+ unsigned Key = Ntl_HashString( pNet->pName, p->nTableSize );
+ assert( Ntl_ModelFindNet( p, pNet->pName ) == NULL );
+ pNet->pNext = p->pTable[Key];
+ p->pTable[Key] = pNet;
}
/**Function*************************************************************
@@ -178,6 +200,17 @@ Ntl_Net_t * Ntl_ModelFindOrCreateNet( Ntl_Mod_t * p, const char * pName )
return pEnt;
}
+/**Function*************************************************************
+
+ Synopsis [Creates new net.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
Ntl_Net_t * Ntl_ModelDontFindCreateNet( Ntl_Mod_t * p, const char * pName )
{
Ntl_Net_t * pEnt;
diff --git a/src/aig/ntl/ntlUtil.c b/src/aig/ntl/ntlUtil.c
index 51f3b818..6e797590 100644
--- a/src/aig/ntl/ntlUtil.c
+++ b/src/aig/ntl/ntlUtil.c
@@ -424,7 +424,7 @@ Vec_Vec_t * Ntl_ManTransformRegClasses( Ntl_Man_t * pMan, int nSizeMax, int fVer
vParts = Vec_PtrAlloc( 100 );
for ( i = 0; i <= ClassMax; i++ )
{
- if ( pClassNums[i] < nSizeMax )
+ if ( pClassNums[i] == 0 || pClassNums[i] < nSizeMax )
continue;
vPart = Vec_IntAlloc( pClassNums[i] );
Vec_IntForEachEntry( pMan->vRegClasses, Class, k )
diff --git a/src/aig/ntl/ntlWriteBlif.c b/src/aig/ntl/ntlWriteBlif.c
index 6b7f0996..3df49270 100644
--- a/src/aig/ntl/ntlWriteBlif.c
+++ b/src/aig/ntl/ntlWriteBlif.c
@@ -140,6 +140,8 @@ void Ioa_WriteBlifModel( FILE * pFile, Ntl_Mod_t * pModel, int fMain )
fprintf( pFile, " %s", pNet->pName );
fprintf( pFile, " %s\n", Ntl_ObjFanout0(pObj)->pName );
fprintf( pFile, "%s", pObj->pSop );
+ if ( *pObj->pSop == '\"' )
+ fprintf( pFile, "\n" );
}
else if ( Ntl_ObjIsLatch(pObj) )
{
@@ -390,6 +392,8 @@ void Ioa_WriteBlifModelGz( gzFile pFile, Ntl_Mod_t * pModel, int fMain )
gzprintf( pFile, " %s", pNet->pName );
gzprintf( pFile, " %s\n", Ntl_ObjFanout0(pObj)->pName );
gzprintf( pFile, "%s", pObj->pSop );
+ if ( *pObj->pSop == '\"' )
+ gzprintf( pFile, "\n" );
}
else if ( Ntl_ObjIsLatch(pObj) )
{
@@ -567,6 +571,8 @@ void Ioa_WriteBlifModelBz2( bz2file * b, Ntl_Mod_t * pModel, int fMain )
fprintfBz2( b, " %s", pNet->pName );
fprintfBz2( b, " %s\n", Ntl_ObjFanout0(pObj)->pName );
fprintfBz2( b, "%s", pObj->pSop );
+ if ( *pObj->pSop == '\"' )
+ fprintfBz2( b, "\n" );
}
else if ( Ntl_ObjIsLatch(pObj) )
{
@@ -625,7 +631,11 @@ void Ioa_WriteBlif( Ntl_Man_t * p, char * pFileName )
Ntl_Mod_t * pModel;
int i, bzError;
bz2file b;
-
+ if ( p->pNal )
+ {
+ p->pNalW( p, pFileName );
+ return;
+ }
// write the GZ file
if (!strncmp(pFileName+strlen(pFileName)-3,".gz",3))
{
diff --git a/src/aig/nwk/nwk.h b/src/aig/nwk/nwk.h
index 603c1fb8..0ea8241b 100644
--- a/src/aig/nwk/nwk.h
+++ b/src/aig/nwk/nwk.h
@@ -123,14 +123,14 @@ struct Nwk_Obj_t_
//#pragma warning( disable : 4273 )
#ifdef WIN32
-#define DLLEXPORT __declspec(dllexport)
-#define DLLIMPORT __declspec(dllimport)
+#define ABC_DLLEXPORT __declspec(dllexport)
+#define ABC_DLLIMPORT __declspec(dllimport)
#else /* defined(WIN32) */
-#define DLLIMPORT
+#define ABC_DLLIMPORT
#endif /* defined(WIN32) */
#ifndef ABC_DLL
-#define ABC_DLL DLLIMPORT
+#define ABC_DLL ABC_DLLIMPORT
#endif
static inline int Nwk_ManCiNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_CI]; }
@@ -234,7 +234,7 @@ static inline int Nwk_ManTimeMore( float f1, float f2, float Eps ) { r
extern ABC_DLL Vec_Ptr_t * Nwk_ManDeriveRetimingCut( Aig_Man_t * p, int fForward, int fVerbose );
/*=== nwkBidec.c ==========================================================*/
extern ABC_DLL void Nwk_ManBidecResyn( Nwk_Man_t * pNtk, int fVerbose );
-extern ABC_DLL Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare );
+extern ABC_DLL Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb );
/*=== nwkCheck.c ==========================================================*/
extern ABC_DLL int Nwk_ManCheck( Nwk_Man_t * p );
/*=== nwkDfs.c ==========================================================*/
@@ -265,7 +265,8 @@ extern ABC_DLL Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int n
/*=== nwkMan.c ============================================================*/
extern ABC_DLL Nwk_Man_t * Nwk_ManAlloc();
extern ABC_DLL void Nwk_ManFree( Nwk_Man_t * p );
-extern ABC_DLL void Nwk_ManPrintStats( Nwk_Man_t * p, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, void * pNtl );
+extern ABC_DLL float Nwl_ManComputeTotalSwitching( Nwk_Man_t * pNtk );
+extern ABC_DLL void Nwk_ManPrintStats( Nwk_Man_t * p, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, void * pNtl );
/*=== nwkMap.c ============================================================*/
extern ABC_DLL Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars );
/*=== nwkObj.c ============================================================*/
diff --git a/src/aig/nwk/nwkBidec.c b/src/aig/nwk/nwkBidec.c
index e30d2c02..2b60d779 100644
--- a/src/aig/nwk/nwkBidec.c
+++ b/src/aig/nwk/nwkBidec.c
@@ -24,6 +24,26 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); }
+static inline void Extra_TruthNot( unsigned * pOut, unsigned * pIn, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = ~pIn[w];
+}
+static inline void Extra_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] | pIn1[w];
+}
+static inline void Extra_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars )
+{
+ int w;
+ for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- )
+ pOut[w] = pIn0[w] & ~pIn1[w];
+}
+
static inline Hop_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) { return Hop_NotCond( Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); }
////////////////////////////////////////////////////////////////////////
@@ -41,7 +61,7 @@ static inline Hop_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) { return Hop_NotCo
SeeAlso []
***********************************************************************/
-Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare )
+Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb )
{
unsigned * pTruth;
Bdc_Fun_t * pFunc;
@@ -52,8 +72,33 @@ Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pR
if ( Hop_IsComplement(pRoot) )
for ( i = Aig_TruthWordNum(nVars)-1; i >= 0; i-- )
pTruth[i] = ~pTruth[i];
- // decompose truth table
- Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 );
+ // perform power-aware decomposition
+ if ( dProb >= 0.0 )
+ {
+ float Prob = (float)2.0 * dProb * (1.0 - dProb);
+ assert( Prob >= 0.0 && Prob <= 0.5 );
+ if ( Prob >= 0.4 )
+ {
+ Extra_TruthNot( puCare, puCare, nVars );
+ if ( dProb > 0.5 ) // more 1s than 0s
+ Extra_TruthOr( pTruth, pTruth, puCare, nVars );
+ else
+ Extra_TruthSharp( pTruth, pTruth, puCare, nVars );
+ Extra_TruthNot( puCare, puCare, nVars );
+ // decompose truth table
+ Bdc_ManDecompose( p, pTruth, NULL, nVars, NULL, 1000 );
+ }
+ else
+ {
+ // decompose truth table
+ Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 );
+ }
+ }
+ else
+ {
+ // decompose truth table
+ Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 );
+ }
// convert back into HOP
Bdc_FuncSetCopy( Bdc_ManFunc( p, 0 ), Hop_ManConst1( pHop ) );
for ( i = 0; i < nVars; i++ )
@@ -106,7 +151,7 @@ void Nwk_ManBidecResyn( Nwk_Man_t * pNtk, int fVerbose )
if ( Nwk_ObjFaninNum(pObj) > 15 )
continue;
nNodes1 = Hop_DagSize(pObj->pFunc);
- pObj->pFunc = Nwk_NodeIfNodeResyn( p, pNtk->pManHop, pObj->pFunc, Nwk_ObjFaninNum(pObj), vTruth, NULL );
+ pObj->pFunc = Nwk_NodeIfNodeResyn( p, pNtk->pManHop, pObj->pFunc, Nwk_ObjFaninNum(pObj), vTruth, NULL, -1.0 );
nNodes2 = Hop_DagSize(pObj->pFunc);
nGainTotal += nNodes1 - nNodes2;
}
diff --git a/src/aig/nwk/nwkMan.c b/src/aig/nwk/nwkMan.c
index 55cdf42b..6b67d3c1 100644
--- a/src/aig/nwk/nwkMan.c
+++ b/src/aig/nwk/nwkMan.c
@@ -183,6 +183,42 @@ char * Nwk_FileNameGeneric( char * FileName )
/**Function*************************************************************
+ Synopsis [Marks nodes for power-optimization.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Nwl_ManComputeTotalSwitching( Nwk_Man_t * pNtk )
+{
+ extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+ Vec_Int_t * vSwitching;
+ float * pSwitching;
+ Aig_Man_t * pAig;
+ Aig_Obj_t * pObjAig;
+ Nwk_Obj_t * pObjAbc;
+ float Result = (float)0;
+ int i;
+ // strash the network
+ // map network into an AIG
+ pAig = Nwk_ManStrash( pNtk );
+ vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 );
+ pSwitching = (float *)vSwitching->pArray;
+ Nwk_ManForEachObj( pNtk, pObjAbc, i )
+ {
+ if ( (pObjAig = Aig_Regular(pObjAbc->pCopy)) )
+ Result += Nwk_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id];
+ }
+ Vec_IntFree( vSwitching );
+ Aig_ManStop( pAig );
+ return Result;
+}
+
+/**Function*************************************************************
+
Synopsis [Prints stats of the manager.]
Description []
@@ -192,7 +228,7 @@ char * Nwk_FileNameGeneric( char * FileName )
SeeAlso []
***********************************************************************/
-void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, void * pNtl )
+void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, void * pNtl )
{
extern int Ntl_ManLatchNum( void * p );
extern void Ioa_WriteBlifLogic( Nwk_Man_t * pNtk, void * pNtl, char * pFileName );
@@ -221,7 +257,9 @@ void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_Lib_t * pLutLib, int fSaveBest, int
printf( "aig = %6d ", Nwk_ManGetAigNodeNum(pNtk) );
printf( "lev = %3d ", Nwk_ManLevel(pNtk) );
// printf( "lev2 = %3d ", Nwk_ManLevelBackup(pNtk) );
- printf( "delay = %5.2f ", Nwk_ManDelayTraceLut(pNtk) );
+ printf( "delay = %5.2f ", Nwk_ManDelayTraceLut(pNtk) );
+ if ( fPower )
+ printf( "power = %7.2f ", Nwl_ManComputeTotalSwitching(pNtk) );
Nwk_ManPrintLutSizes( pNtk, pLutLib );
printf( "\n" );
// Nwk_ManDelayTracePrint( pNtk, pLutLib );
diff --git a/src/aig/nwk/nwkMap.c b/src/aig/nwk/nwkMap.c
index 88e08413..a70bb9b1 100644
--- a/src/aig/nwk/nwkMap.c
+++ b/src/aig/nwk/nwkMap.c
@@ -59,6 +59,7 @@ void Nwk_ManSetIfParsDefault( If_Par_t * pPars )
pPars->fExpRed = 1; ////
pPars->fLatchPaths = 0;
pPars->fEdge = 1;
+ pPars->fPower = 0;
pPars->fCutMin = 0;
pPars->fSeqMap = 0;
pPars->fVerbose = 0;
@@ -98,12 +99,29 @@ void Nwk_ManSetIfParsDefault( If_Par_t * pPars )
***********************************************************************/
If_Man_t * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf )
{
+ extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+ Vec_Int_t * vSwitching = NULL, * vSwitching2 = NULL;
+ float * pSwitching, * pSwitching2;
If_Man_t * pIfMan;
If_Obj_t * pIfObj;
Aig_Obj_t * pNode, * pFanin, * pPrev;
- int i;
+ int i, clk = clock();
+ // set the number of registers (switch activity will be combinational)
+ Aig_ManSetRegNum( p, 0 );
+ if ( pPars->fPower )
+ {
+ vSwitching = Saig_ManComputeSwitchProbs( p, 48, 16, 0 );
+ if ( pPars->fVerbose )
+ {
+ PRT( "Computing switching activity", clock() - clk );
+ }
+ pSwitching = (float *)vSwitching->pArray;
+ vSwitching2 = Vec_IntStart( Aig_ManObjNumMax(p) );
+ pSwitching2 = (float *)vSwitching2->pArray;
+ }
// start the mapping manager and set its parameters
pIfMan = If_ManStart( pPars );
+ pIfMan->vSwitching = vSwitching2;
// load the AIG into the mapper
Aig_ManForEachObj( p, pNode, i )
{
@@ -116,6 +134,8 @@ If_Man_t * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf )
pIfObj = If_ManCreateCi( pIfMan );
If_ObjSetLevel( pIfObj, Aig_ObjLevel(pNode) );
// printf( "pi=%d ", pIfObj->Level );
+ if ( pIfMan->nLevelMax < (int)pIfObj->Level )
+ pIfMan->nLevelMax = (int)pIfObj->Level;
}
else if ( Aig_ObjIsPo(pNode) )
{
@@ -130,6 +150,8 @@ If_Man_t * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf )
assert( Vec_PtrEntry(vAigToIf, i) == NULL );
Vec_PtrWriteEntry( vAigToIf, i, pIfObj );
pNode->pData = pIfObj;
+ if ( vSwitching2 )
+ pSwitching2[pIfObj->Id] = pSwitching[pNode->Id];
// set up the choice node
if ( Aig_ObjIsChoice( p, pNode ) )
{
@@ -140,6 +162,8 @@ If_Man_t * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf )
}
// assert( If_ObjLevel(pIfObj) == Aig_ObjLevel(pNode) );
}
+ if ( vSwitching )
+ Vec_IntFree( vSwitching );
return pIfMan;
}
diff --git a/src/aig/nwk/nwkMerge.c b/src/aig/nwk/nwkMerge.c
index 531bc1c0..3aec4faa 100644
--- a/src/aig/nwk/nwkMerge.c
+++ b/src/aig/nwk/nwkMerge.c
@@ -913,7 +913,7 @@ int Nwk_ManCountTotalFanins( Nwk_Obj_t * pLut, Nwk_Obj_t * pCand )
SeeAlso []
***********************************************************************/
-void Nwl_ManCollectOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
+void Nwk_ManCollectOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
{
Nwk_Obj_t * pFanin, * pObj;
int i, k;
@@ -985,7 +985,7 @@ Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, Nwk_LMPars_t * pPars )
{
if ( Nwk_ObjFaninNum(pLut) > pPars->nMaxLutSize )
continue;
- Nwl_ManCollectOverlapCands( pLut, vCands1, pPars );
+ Nwk_ManCollectOverlapCands( pLut, vCands1, pPars );
if ( pPars->fUseDiffSupp )
Nwk_ManCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars );
if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 )
@@ -1022,9 +1022,11 @@ Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, Nwk_LMPars_t * pPars )
Nwk_ManGraphReportMemoryUsage( p );
}
vResult = p->vPairs; p->vPairs = NULL;
+/*
for ( i = 0; i < vResult->nSize; i += 2 )
printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] );
printf( "\n" );
+*/
Nwk_ManGraphFree( p );
return vResult;
}
diff --git a/src/aig/nwk/nwkStrash.c b/src/aig/nwk/nwkStrash.c
index a4ce5e39..6c2a3677 100644
--- a/src/aig/nwk/nwkStrash.c
+++ b/src/aig/nwk/nwkStrash.c
@@ -133,6 +133,7 @@ Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * pNtk )
}
Vec_PtrFree( vObjs );
Aig_ManCleanup( pMan );
+ Aig_ManSetRegNum( pMan, 0 );
return pMan;
}
diff --git a/src/aig/nwk2/nwk.h b/src/aig/nwk2/nwk.h
index 465bd651..bef16284 100644
--- a/src/aig/nwk2/nwk.h
+++ b/src/aig/nwk2/nwk.h
@@ -242,7 +242,7 @@ extern void Nwk_ObjReplace( Nwk_Obj_t * pNodeOld, Nwk_Obj_t * pNodeNe
/*=== nwkMan.c ============================================================*/
extern Nwk_Man_t * Nwk_ManAlloc();
extern void Nwk_ManFree( Nwk_Man_t * p );
-//extern void Nwk_ManPrintStats( Nwk_Man_t * p, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, void * pNtl );
+//extern void Nwk_ManPrintStats( Nwk_Man_t * p, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, void * pNtl );
/*=== nwkObj.c ============================================================*/
extern Nwk_Obj_t * Nwk_ManCreateCi( Nwk_Man_t * pMan, int nFanouts );
extern Nwk_Obj_t * Nwk_ManCreateCo( Nwk_Man_t * pMan );
diff --git a/src/aig/nwk2/nwkMan.c b/src/aig/nwk2/nwkMan.c
index 962cafd4..cd73f866 100644
--- a/src/aig/nwk2/nwkMan.c
+++ b/src/aig/nwk2/nwkMan.c
@@ -195,7 +195,7 @@ char * Nwk_FileNameGeneric( char * FileName )
***********************************************************************/
/*
-void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, void * pNtl )
+void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_Lib_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, void * pNtl )
{
extern int Ntl_ManLatchNum( void * p );
extern void Ioa_WriteBlifLogic( Nwk_Man_t * pNtk, void * pNtl, char * pFileName );
diff --git a/src/aig/saig/module.make b/src/aig/saig/module.make
index 7063bd2a..e583bcfe 100644
--- a/src/aig/saig/module.make
+++ b/src/aig/saig/module.make
@@ -6,12 +6,18 @@ SRC += src/aig/saig/saigAbs.c \
src/aig/saig/saigHaig.c \
src/aig/saig/saigInd.c \
src/aig/saig/saigIoa.c \
- src/aig/saig/saigLoc.c \
src/aig/saig/saigMiter.c \
src/aig/saig/saigPhase.c \
src/aig/saig/saigRetFwd.c \
src/aig/saig/saigRetMin.c \
src/aig/saig/saigRetStep.c \
src/aig/saig/saigScl.c \
+ src/aig/saig/saigSimExt.c \
+ src/aig/saig/saigSimFast.c \
+ src/aig/saig/saigSimMv.c \
+ src/aig/saig/saigSimSeq.c \
+ src/aig/saig/saigStrSim.c \
+ src/aig/saig/saigSwitch.c \
src/aig/saig/saigSynch.c \
- src/aig/saig/saigTrans.c
+ src/aig/saig/saigTrans.c \
+ src/aig/saig/saigWnd.c
diff --git a/src/aig/saig/saig.h b/src/aig/saig/saig.h
index d96996cf..84ff272a 100644
--- a/src/aig/saig/saig.h
+++ b/src/aig/saig/saig.h
@@ -30,7 +30,6 @@ extern "C" {
////////////////////////////////////////////////////////////////////////
#include "aig.h"
-#include "int.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
@@ -40,6 +39,18 @@ extern "C" {
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
+typedef struct Sec_MtrStatus_t_ Sec_MtrStatus_t;
+struct Sec_MtrStatus_t_
+{
+ int nInputs; // the total number of inputs
+ int nNodes; // the total number of nodes
+ int nOutputs; // the total number of outputs
+ int nUnsat; // the number of UNSAT outputs
+ int nSat; // the number of SAT outputs
+ int nUndec; // the number of undecided outputs
+ int iOut; // the satisfied output
+};
+
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -79,7 +90,7 @@ static inline Aig_Obj_t * Saig_ObjLiToLo( Aig_Man_t * p, Aig_Obj_t * pObj ) {
////////////////////////////////////////////////////////////////////////
/*=== sswAbs.c ==========================================================*/
-extern Aig_Man_t * Saig_ManProofAbstraction( Aig_Man_t * p, int nFrames, int nConfMax, int fDynamic, int fExtend, int fVerbose );
+extern Aig_Man_t * Saig_ManProofAbstraction( Aig_Man_t * p, int nFrames, int nConfMax, int fDynamic, int fExtend, int fSkipProof, int fVerbose );
/*=== saigBmc.c ==========================================================*/
extern int Saig_ManBmcSimple( Aig_Man_t * pAig, int nFrames, int nSizeMax, int nBTLimit, int fRewrite, int fVerbose, int * piFrame );
extern void Saig_BmcPerform( Aig_Man_t * pAig, int nFramesMax, int nNodesMax, int nConfMaxOne, int nConfMaxAll, int fVerbose );
@@ -95,11 +106,11 @@ extern int Saig_ManInduction( Aig_Man_t * p, int nFramesMax, int n
/*=== saigIoa.c ==========================================================*/
extern void Saig_ManDumpBlif( Aig_Man_t * p, char * pFileName );
extern Aig_Man_t * Saig_ManReadBlif( char * pFileName );
-/*=== saigInter.c ==========================================================*/
-extern int Saig_Interpolate( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * pDepth );
/*=== saigMiter.c ==========================================================*/
+extern Sec_MtrStatus_t Sec_MiterStatus( Aig_Man_t * p );
extern Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int Oper );
extern Aig_Man_t * Saig_ManCreateMiterComb( Aig_Man_t * p1, Aig_Man_t * p2, int Oper );
+extern Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter );
extern Aig_Man_t * Saig_ManCreateMiterTwo( Aig_Man_t * pOld, Aig_Man_t * pNew, int nFrames );
extern int Saig_ManDemiterSimple( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 );
extern int Saig_ManDemiterSimpleDiff( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 );
@@ -115,10 +126,23 @@ extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, in
extern int Saig_ManRetimeSteps( Aig_Man_t * p, int nSteps, int fForward, int fAddBugs );
/*=== saigScl.c ==========================================================*/
extern void Saig_ManReportUselessRegisters( Aig_Man_t * pAig );
+/*=== saigSimExt.c ==========================================================*/
+//extern Vec_Int_t * Saig_ManExtendCounterExample( Aig_Man_t * p, int iFirstPi, Ssw_Cex_t * pCex, Vec_Ptr_t * vSimInfo );
+//extern Vec_Int_t * Saig_ManExtendCounterExampleTest( Aig_Man_t * p, int iFirstPi, Ssw_Cex_t * pCex );
+/*=== saigSimMv.c ==========================================================*/
+extern int Saig_MvManSimulate( Aig_Man_t * pAig, int fVerbose );
+/*=== saigStrSim.c ==========================================================*/
+extern Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter );
+/*=== saigSwitch.c ==========================================================*/
+extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
/*=== saigSynch.c ==========================================================*/
extern Aig_Man_t * Saig_ManDupInitZero( Aig_Man_t * p );
/*=== saigTrans.c ==========================================================*/
extern Aig_Man_t * Saig_ManTimeframeSimplify( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit, int fVerbose );
+/*=== saigWnd.c ==========================================================*/
+extern Aig_Man_t * Saig_ManWindowExtract( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist );
+extern Aig_Man_t * Saig_ManWindowInsert( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Aig_Man_t * pWnd );
+extern Aig_Obj_t * Saig_ManFindPivot( Aig_Man_t * p );
#ifdef __cplusplus
}
diff --git a/src/aig/saig/saigAbs.c b/src/aig/saig/saigAbs.c
index 8498f59a..d2a45b4e 100644
--- a/src/aig/saig/saigAbs.c
+++ b/src/aig/saig/saigAbs.c
@@ -23,6 +23,7 @@
#include "cnf.h"
#include "satSolver.h"
#include "satStore.h"
+#include "ssw.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -105,7 +106,11 @@ int Saig_AbsMarkVisited_rec( Aig_Man_t * p, Vec_Str_t * vObj2Visit, Aig_Obj_t *
if ( Saig_ObjIsPi( p, pObj ) )
return 1;
if ( Saig_ObjIsLo( p, pObj ) )
+ {
+ if ( i == 0 )
+ return 1;
return Saig_AbsMarkVisited_rec( p, vObj2Visit, Saig_ObjLoToLi(p, pObj), i-1 );
+ }
if ( Aig_ObjIsPo( pObj ) )
return Saig_AbsMarkVisited_rec( p, vObj2Visit, Aig_ObjFanin0(pObj), i );
Saig_AbsMarkVisited_rec( p, vObj2Visit, Aig_ObjFanin0(pObj), i );
@@ -130,8 +135,8 @@ Vec_Str_t * Saig_AbsMarkVisited( Aig_Man_t * p, int nFramesMax )
Aig_Obj_t * pObj;
int i, f;
vObj2Visit = Vec_StrStart( Aig_ManObjNumMax(p) * nFramesMax );
- Saig_ManForEachLo( p, pObj, i )
- Saig_AbsSetVisited( vObj2Visit, Aig_ManObjNumMax(p), pObj, 0 );
+// Saig_ManForEachLo( p, pObj, i )
+// Saig_AbsSetVisited( vObj2Visit, Aig_ManObjNumMax(p), pObj, 0 );
for ( f = 0; f < nFramesMax; f++ )
{
Saig_AbsSetVisited( vObj2Visit, Aig_ManObjNumMax(p), Aig_ManConst1(p), f );
@@ -193,18 +198,19 @@ Vec_Ptr_t * Saig_AbsCreateFrames( Aig_Man_t * p, int nFramesMax, int fVerbose )
Vec_PtrClear( vLoObjs );
Vec_PtrClear( vLiObjs );
Aig_ManForEachPi( p, pObj, i )
- {
+ {
if ( Saig_AbsVisited( vObj2Visit, Aig_ManObjNumMax(p), pObj, f ) )
{
pObj->pData = Aig_ObjCreatePi(pFrame);
if ( i >= Saig_ManPiNum(p) )
Vec_PtrPush( vLoObjs, pObj );
- }
+ }
}
// remember the number of (implicit) registers in this frame
pFrame->nAsserts = Vec_PtrSize(vLoObjs);
// create POs
Aig_ManForEachPo( p, pObj, i )
+ {
if ( Saig_AbsVisited( vObj2Visit, Aig_ManObjNumMax(p), pObj, f ) )
{
Saig_AbsCreateFrames_rec( pFrame, Aig_ObjFanin0(pObj) );
@@ -212,8 +218,10 @@ Vec_Ptr_t * Saig_AbsCreateFrames( Aig_Man_t * p, int nFramesMax, int fVerbose )
if ( i >= Saig_ManPoNum(p) )
Vec_PtrPush( vLiObjs, pObj );
}
- Vec_PtrPush( vFrames, Cnf_Derive(pFrame, Aig_ManPoNum(pFrame)) );
- // set the new PIs to point to the recorresponding registers
+ }
+// Vec_PtrPush( vFrames, Cnf_Derive(pFrame, Aig_ManPoNum(pFrame)) );
+ Vec_PtrPush( vFrames, Cnf_DeriveSimple(pFrame, Aig_ManPoNum(pFrame)) );
+ // set the new PIs to point to the corresponding registers
Aig_ManCleanData( pFrame );
Vec_PtrForEachEntry( vLoObjs, pObj, i )
((Aig_Obj_t *)pObj->pData)->pData = pObj;
@@ -290,7 +298,10 @@ sat_solver * Saig_AbsCreateSolverDyn( Aig_Man_t * p, Vec_Ptr_t * vFrames )
// add auxiliary clauses (output, connectors, initial)
// add output clause
if ( !sat_solver_addclause( pSat, Vec_IntArray(vPoLits), Vec_IntArray(vPoLits) + Vec_IntSize(vPoLits) ) )
+ {
+ printf( "SAT solver is not created correctly.\n" );
assert( 0 );
+ }
Vec_IntFree( vPoLits );
// add connecting clauses
@@ -627,7 +638,7 @@ void Saig_AbsExtendOneStep( Aig_Man_t * p, Vec_Int_t * vFlops )
/**Function*************************************************************
- Synopsis [Performs proof-based abstraction using BMC of the given depth.]
+ Synopsis [Derive a new counter-example.]
Description []
@@ -636,63 +647,194 @@ void Saig_AbsExtendOneStep( Aig_Man_t * p, Vec_Int_t * vFlops )
SeeAlso []
***********************************************************************/
-Aig_Man_t * Saig_ManProofAbstraction( Aig_Man_t * p, int nFrames, int nConfMax, int fDynamic, int fExtend, int fVerbose )
+Ssw_Cex_t * Saig_ManCexShrink( Aig_Man_t * p, Aig_Man_t * pAbs, Ssw_Cex_t * pCexAbs )
{
- Aig_Man_t * pResult;
- Cnf_Dat_t * pCnf;
- Vec_Ptr_t * vFrames;
- sat_solver * pSat;
- Vec_Int_t * vCore;
- Vec_Int_t * vFlops;
- int clk = clock(), clk2 = clock();
- assert( Aig_ManRegNum(p) > 0 );
- Aig_ManSetPioNumbers( p );
- if ( fVerbose )
- printf( "Performing proof-based abstraction with %d frames and %d max conflicts.\n", nFrames, nConfMax );
- if ( fDynamic )
+ Ssw_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ int i, f;
+ // start the counter-example
+ pCex = Ssw_SmlAllocCounterExample( Aig_ManRegNum(p), Saig_ManPiNum(p), pCexAbs->iFrame+1 );
+ pCex->iFrame = pCexAbs->iFrame;
+ pCex->iPo = pCexAbs->iPo;
+ // copy the bit data
+ for ( f = 0; f <= pCexAbs->iFrame; f++ )
+ {
+ Saig_ManForEachPi( pAbs, pObj, i )
+ {
+ if ( i == Saig_ManPiNum(p) )
+ break;
+ if ( Aig_InfoHasBit( pCexAbs->pData, pCexAbs->nRegs + pCexAbs->nPis * f + i ) )
+ Aig_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * f + i );
+ }
+ }
+ // verify the counter example
+ if ( !Ssw_SmlRunCounterExample( p, pCex ) )
{
- // create CNF for the frames
- vFrames = Saig_AbsCreateFrames( p, nFrames, fVerbose );
- // create dynamic solver
- pSat = Saig_AbsCreateSolverDyn( p, vFrames );
+ printf( "Saig_ManCexShrink(): Counter-example is invalid.\n" );
+ Ssw_SmlFreeCounterExample( pCex );
+ pCex = NULL;
}
else
{
- // create CNF for the AIG
- pCnf = Cnf_DeriveSimple( p, Aig_ManPoNum(p) );
- // create SAT solver for the unrolled AIG
- pSat = Saig_AbsCreateSolver( pCnf, nFrames );
+ printf( "Counter-example verification is successful.\n" );
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). \n", pCex->iPo, pCex->iFrame );
+ }
+ return pCex;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs proof-based abstraction using BMC of the given depth.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManProofRefine( Aig_Man_t * p, Aig_Man_t * pAbs, Vec_Int_t * vFlops, int fVerbose )
+{
+ extern void Saig_BmcPerform( Aig_Man_t * pAig, int nFramesMax, int nNodesMax, int nConfMaxOne, int nConfMaxAll, int fVerbose );
+ extern Vec_Int_t * Saig_ManExtendCounterExampleTest( Aig_Man_t * p, int iFirstPi, void * pCex, int fVerbose );
+
+ Vec_Int_t * vFlopsNew, * vPiToReg;
+ Aig_Obj_t * pObj;
+ int i, Entry, iFlop;
+ Saig_BmcPerform( pAbs, 2000, 2000, 5000, 1000000, fVerbose );
+ if ( pAbs->pSeqModel == NULL )
+ return NULL;
+// Saig_ManExtendCounterExampleTest( p->pAig, 0, p->pAig->pSeqModel );
+ vFlopsNew = Saig_ManExtendCounterExampleTest( pAbs, Saig_ManPiNum(p), pAbs->pSeqModel, fVerbose );
+ if ( Vec_IntSize(vFlopsNew) == 0 )
+ {
+ printf( "Discovered a true counter-example!\n" );
+ p->pSeqModel = Saig_ManCexShrink( p, pAbs, pAbs->pSeqModel );
+ Vec_IntFree( vFlopsNew );
+ return NULL;
}
if ( fVerbose )
+ printf( "Adding %d registers to the abstraction.\n", Vec_IntSize(vFlopsNew) );
+ // vFlopsNew contains PI number that should be kept in pAbs
+
+ // for each additional PI, collect the number of a register it stands for
+ Vec_IntForEachEntry( vFlops, Entry, i )
{
- printf( "SAT solver: Vars = %7d. Clauses = %7d. ", pSat->size, pSat->stats.clauses );
- PRT( "Time", clock() - clk2 );
+ pObj = Saig_ManLo( p, Entry );
+ pObj->fMarkA = 1;
}
- // compute UNSAT core
- vCore = Saig_AbsSolverUnsatCore( pSat, nConfMax, fVerbose );
- sat_solver_delete( pSat );
- if ( vCore == NULL )
+ vPiToReg = Vec_IntAlloc( 1000 );
+ Aig_ManForEachPi( p, pObj, i )
{
- Saig_AbsFreeCnfs( vFrames );
- return NULL;
+ if ( pObj->fMarkA )
+ {
+ pObj->fMarkA = 0;
+ continue;
+ }
+ if ( i < Saig_ManPiNum(p) )
+ Vec_IntPush( vPiToReg, -1 );
+ else
+ Vec_IntPush( vPiToReg, Aig_ObjPioNum(pObj)-Saig_ManPiNum(p) );
}
// collect registers
- if ( fDynamic )
+ Vec_IntForEachEntry( vFlopsNew, Entry, i )
{
- vFlops = Saig_AbsCollectRegistersDyn( p, vFrames, vCore );
- Saig_AbsFreeCnfs( vFrames );
+ iFlop = Vec_IntEntry( vPiToReg, Entry );
+ assert( iFlop >= 0 );
+ assert( iFlop < Aig_ManRegNum(p) );
+ Vec_IntPush( vFlops, iFlop );
}
- else
+ Vec_IntFree( vPiToReg );
+ Vec_IntFree( vFlopsNew );
+
+ Vec_IntSort( vFlops, 0 );
+ Vec_IntForEachEntryStart( vFlops, Entry, i, 1 )
+ assert( Vec_IntEntry(vFlops, i-1) != Entry );
+
+ return Saig_ManAbstraction( p, vFlops );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs proof-based abstraction using BMC of the given depth.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManProofAbstraction( Aig_Man_t * p, int nFrames, int nConfMax, int fDynamic, int fExtend, int fSkipProof, int fVerbose )
+{
+ Aig_Man_t * pResult, * pTemp;
+ Cnf_Dat_t * pCnf;
+ Vec_Ptr_t * vFrames;
+ sat_solver * pSat;
+ Vec_Int_t * vCore;
+ Vec_Int_t * vFlops;
+ int Iter, clk = clock(), clk2 = clock();
+ assert( Aig_ManRegNum(p) > 0 );
+ Aig_ManSetPioNumbers( p );
+
+ if ( fSkipProof )
{
- vFlops = Saig_AbsCollectRegisters( pCnf, nFrames, vCore );
- Cnf_DataFree( pCnf );
+ assert( 0 );
+ if ( fVerbose )
+ printf( "Performing counter-example-based refinement.\n" );
+// vFlops = Vec_IntStartNatural( 100 );
+// Vec_IntPush( vFlops, 0 );
}
- Vec_IntFree( vCore );
- if ( fVerbose )
+ else
{
- printf( "The number of relevant registers is %d (out of %d). ", Vec_IntSize(vFlops), Aig_ManRegNum(p) );
- PRT( "Time", clock() - clk );
+ if ( fVerbose )
+ printf( "Performing proof-based abstraction with %d frames and %d max conflicts.\n", nFrames, nConfMax );
+ if ( fDynamic )
+ {
+ // create CNF for the frames
+ vFrames = Saig_AbsCreateFrames( p, nFrames, fVerbose );
+ // create dynamic solver
+ pSat = Saig_AbsCreateSolverDyn( p, vFrames );
+ }
+ else
+ {
+ // create CNF for the AIG
+ pCnf = Cnf_DeriveSimple( p, Aig_ManPoNum(p) );
+ // create SAT solver for the unrolled AIG
+ pSat = Saig_AbsCreateSolver( pCnf, nFrames );
+ }
+ if ( fVerbose )
+ {
+ printf( "SAT solver: Vars = %7d. Clauses = %7d. ", pSat->size, pSat->stats.clauses );
+ PRT( "Time", clock() - clk2 );
+ }
+ // compute UNSAT core
+ vCore = Saig_AbsSolverUnsatCore( pSat, nConfMax, fVerbose );
+ sat_solver_delete( pSat );
+ if ( vCore == NULL )
+ {
+ Saig_AbsFreeCnfs( vFrames );
+ return NULL;
+ }
+ // collect registers
+ if ( fDynamic )
+ {
+ vFlops = Saig_AbsCollectRegistersDyn( p, vFrames, vCore );
+ Saig_AbsFreeCnfs( vFrames );
+ }
+ else
+ {
+ vFlops = Saig_AbsCollectRegisters( pCnf, nFrames, vCore );
+ Cnf_DataFree( pCnf );
+ }
+ Vec_IntFree( vCore );
+ if ( fVerbose )
+ {
+ printf( "The number of relevant registers is %d (out of %d). ", Vec_IntSize(vFlops), Aig_ManRegNum(p) );
+ PRT( "Time", clock() - clk );
+ }
}
+/*
// extend the abstraction
if ( fExtend )
{
@@ -702,8 +844,33 @@ Aig_Man_t * Saig_ManProofAbstraction( Aig_Man_t * p, int nFrames, int nConfMax,
if ( fVerbose )
printf( " %d flops.\n", Vec_IntSize(vFlops) );
}
+*/
// create the resulting AIG
pResult = Saig_ManAbstraction( p, vFlops );
+
+ if ( fExtend )
+ {
+ if ( !fVerbose )
+ {
+ printf( "Init : " );
+ Aig_ManPrintStats( pResult );
+ }
+ printf( "Refining abstraction...\n" );
+ for ( Iter = 0; ; Iter++ )
+ {
+ pTemp = Saig_ManProofRefine( p, pResult, vFlops, fVerbose );
+ if ( pTemp == NULL )
+ break;
+ Aig_ManStop( pResult );
+ pResult = pTemp;
+ printf( "%4d : ", Iter );
+ if ( !fVerbose )
+ Aig_ManPrintStats( pResult );
+ else
+ printf( " -----------------------------------------------------\n" );
+ }
+ }
+
Vec_IntFree( vFlops );
return pResult;
}
diff --git a/src/aig/saig/saigBmc.c b/src/aig/saig/saigBmc.c
index a5235042..7cccce96 100644
--- a/src/aig/saig/saigBmc.c
+++ b/src/aig/saig/saigBmc.c
@@ -207,7 +207,7 @@ Aig_Obj_t * Saig_BmcIntervalExplore_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i
SeeAlso []
***********************************************************************/
-Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i )
+Aig_Obj_t * Saig_BmcIntervalConstruct_rec_OLD( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i )
{
Aig_Obj_t * pRes;
pRes = Saig_BmcObjFrame( p, pObj, i );
@@ -217,16 +217,16 @@ Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int
if ( Saig_ObjIsPi( p->pAig, pObj ) )
pRes = Aig_ObjCreatePi(p->pFrm);
else if ( Saig_ObjIsLo( p->pAig, pObj ) )
- pRes = Saig_BmcIntervalConstruct_rec( p, Saig_ObjLoToLi(p->pAig, pObj), i-1 );
+ pRes = Saig_BmcIntervalConstruct_rec_OLD( p, Saig_ObjLoToLi(p->pAig, pObj), i-1 );
else if ( Aig_ObjIsPo( pObj ) )
{
- Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i );
+ Saig_BmcIntervalConstruct_rec_OLD( p, Aig_ObjFanin0(pObj), i );
pRes = Saig_BmcObjChild0( p, pObj, i );
}
else
{
- Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i );
- Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin1(pObj), i );
+ Saig_BmcIntervalConstruct_rec_OLD( p, Aig_ObjFanin0(pObj), i );
+ Saig_BmcIntervalConstruct_rec_OLD( p, Aig_ObjFanin1(pObj), i );
pRes = Aig_And( p->pFrm, Saig_BmcObjChild0(p, pObj, i), Saig_BmcObjChild1(p, pObj, i) );
}
assert( pRes != AIG_VISITED );
@@ -236,6 +236,45 @@ Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int
/**Function*************************************************************
+ Synopsis [Performs the actual construction of the output.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i, Vec_Ptr_t * vVisited )
+{
+ Aig_Obj_t * pRes;
+ pRes = Saig_BmcObjFrame( p, pObj, i );
+ if ( pRes != NULL )
+ return pRes;
+ if ( Saig_ObjIsPi( p->pAig, pObj ) )
+ pRes = Aig_ObjCreatePi(p->pFrm);
+ else if ( Saig_ObjIsLo( p->pAig, pObj ) )
+ pRes = Saig_BmcIntervalConstruct_rec( p, Saig_ObjLoToLi(p->pAig, pObj), i-1, vVisited );
+ else if ( Aig_ObjIsPo( pObj ) )
+ {
+ Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i, vVisited );
+ pRes = Saig_BmcObjChild0( p, pObj, i );
+ }
+ else
+ {
+ Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i, vVisited );
+ Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin1(pObj), i, vVisited );
+ pRes = Aig_And( p->pFrm, Saig_BmcObjChild0(p, pObj, i), Saig_BmcObjChild1(p, pObj, i) );
+ }
+ assert( pRes != NULL );
+ Saig_BmcObjSetFrame( p, pObj, i, pRes );
+ Vec_PtrPush( vVisited, pObj );
+ Vec_PtrPush( vVisited, (void *)i );
+ return pRes;
+}
+
+/**Function*************************************************************
+
Synopsis [Adds new AIG nodes to the frames.]
Description []
@@ -248,8 +287,8 @@ Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int
void Saig_BmcInterval( Saig_Bmc_t * p )
{
Aig_Obj_t * pTarget;
-// Aig_Obj_t * pObj;
-// int i;
+ Aig_Obj_t * pObj, * pRes;
+ int i, iFrame;
int nNodes = Aig_ManObjNum( p->pFrm );
Vec_PtrClear( p->vTargets );
p->iFramePrev = p->iFrameLast;
@@ -258,21 +297,25 @@ void Saig_BmcInterval( Saig_Bmc_t * p )
if ( p->iOutputLast == 0 )
{
Saig_BmcObjSetFrame( p, Aig_ManConst1(p->pAig), p->iFrameLast, Aig_ManConst1(p->pFrm) );
-// Saig_ManForEachPi( p->pAig, pObj, i )
-// Saig_BmcObjSetFrame( p, pObj, p->iFrameLast, Aig_ObjCreatePi(p->pFrm) );
}
for ( ; p->iOutputLast < Saig_ManPoNum(p->pAig); p->iOutputLast++ )
{
if ( Aig_ManObjNum(p->pFrm) >= nNodes + p->nNodesMax )
return;
- Saig_BmcIntervalExplore_rec( p, Aig_ManPo(p->pAig, p->iOutputLast), p->iFrameLast );
- pTarget = Saig_BmcIntervalConstruct_rec( p, Aig_ManPo(p->pAig, p->iOutputLast), p->iFrameLast );
-
- /////////
-// if ( Aig_ObjIsConst1(Aig_Regular(pTarget)) )
-// continue;
-
+// Saig_BmcIntervalExplore_rec( p, Aig_ManPo(p->pAig, p->iOutputLast), p->iFrameLast );
+ Vec_PtrClear( p->vVisited );
+ pTarget = Saig_BmcIntervalConstruct_rec( p, Aig_ManPo(p->pAig, p->iOutputLast), p->iFrameLast, p->vVisited );
Vec_PtrPush( p->vTargets, pTarget );
+ Aig_ObjCreatePo( p->pFrm, pTarget );
+ Aig_ManCleanup( p->pFrm );
+ // check if the node is gone
+ Vec_PtrForEachEntry( p->vVisited, pObj, i )
+ {
+ iFrame = (int)(PORT_PTRINT_T)Vec_PtrEntry( p->vVisited, 1+i++ );
+ pRes = Saig_BmcObjFrame( p, pObj, iFrame );
+ if ( Aig_ObjIsNone( Aig_Regular(pRes) ) )
+ Saig_BmcObjSetFrame( p, pObj, iFrame, NULL );
+ }
}
}
}
@@ -489,6 +532,11 @@ int Saig_BmcSolveTargets( Saig_Bmc_t * p )
// generate counter-example
Saig_BmcDeriveFailed( p, i );
p->pAig->pSeqModel = Saig_BmcGenerateCounterExample( p );
+
+ {
+// extern Vec_Int_t * Saig_ManExtendCounterExampleTest( Aig_Man_t * p, int iFirstPi, void * pCex );
+// Saig_ManExtendCounterExampleTest( p->pAig, 0, p->pAig->pSeqModel );
+ }
return l_True;
}
return l_False;
@@ -564,7 +612,7 @@ void Saig_BmcPerform( Aig_Man_t * pAig, int nFramesMax, int nNodesMax, int nConf
RetValue = Saig_BmcSolveTargets( p );
if ( fVerbose )
{
- printf( "%3d : F = %3d. O = %3d. And = %7d. Var = %7d. Conf = %7d. ",
+ printf( "%3d : F = %3d. O =%4d. And = %7d. Var = %7d. Conf = %7d. ",
Iter, p->iFrameLast, p->iOutputLast, Aig_ManNodeNum(p->pFrm), p->nSatVars, (int)p->pSat->stats.conflicts );
PRT( "Time", clock() - clk2 );
}
diff --git a/src/aig/saig/saigDup.c b/src/aig/saig/saigDup.c
index 61ea6ca0..e6534a1f 100644
--- a/src/aig/saig/saigDup.c
+++ b/src/aig/saig/saigDup.c
@@ -46,6 +46,7 @@ Aig_Man_t * Said_ManDupOrpos( Aig_Man_t * pAig )
int i;
// start the new manager
pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+ pAigNew->pName = Aig_UtilStrsav( pAig->pName );
// map the constant node
Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
// create variables for PIs
@@ -80,11 +81,12 @@ Aig_Man_t * Said_ManDupOrpos( Aig_Man_t * pAig )
***********************************************************************/
Aig_Man_t * Saig_ManAbstraction( Aig_Man_t * pAig, Vec_Int_t * vFlops )
{
- Aig_Man_t * pAigNew;
+ Aig_Man_t * pAigNew;//, * pTemp;
Aig_Obj_t * pObj, * pObjLi, * pObjLo;
int i, Entry;
// start the new manager
pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
+ pAigNew->pName = Aig_UtilStrsav( pAig->pName );
// map the constant node
Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
// label included flops
@@ -123,6 +125,8 @@ Aig_Man_t * Saig_ManAbstraction( Aig_Man_t * pAig, Vec_Int_t * vFlops )
}
Aig_ManSetRegNum( pAigNew, Vec_IntSize(vFlops) );
Aig_ManSeqCleanup( pAigNew );
+// pAigNew = Aig_ManDupSimpleDfs( pTemp = pAigNew );
+// Aig_ManStop( pTemp );
return pAigNew;
}
diff --git a/src/aig/saig/saigMiter.c b/src/aig/saig/saigMiter.c
index 84c8a4fe..6c4b3af0 100644
--- a/src/aig/saig/saigMiter.c
+++ b/src/aig/saig/saigMiter.c
@@ -30,6 +30,60 @@
/**Function*************************************************************
+ Synopsis [Checks the status of the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Sec_MtrStatus_t Sec_MiterStatus( Aig_Man_t * p )
+{
+ Sec_MtrStatus_t Status;
+ Aig_Obj_t * pObj, * pChild;
+ int i;
+ memset( &Status, 0, sizeof(Sec_MtrStatus_t) );
+ Status.iOut = -1;
+ Status.nInputs = Saig_ManPiNum( p );
+ Status.nNodes = Aig_ManNodeNum( p );
+ Status.nOutputs = Saig_ManPoNum(p);
+ Saig_ManForEachPo( p, pObj, i )
+ {
+ pChild = Aig_ObjChild0(pObj);
+ // check if the output is constant 0
+ if ( pChild == Aig_ManConst0(p) )
+ Status.nUnsat++;
+ // check if the output is constant 1
+ else if ( pChild == Aig_ManConst1(p) )
+ {
+ Status.nSat++;
+ if ( Status.iOut == -1 )
+ Status.iOut = i;
+ }
+ // check if the output is a primary input
+ else if ( Saig_ObjIsPi(p, Aig_Regular(pChild)) )
+ {
+ Status.nSat++;
+ if ( Status.iOut == -1 )
+ Status.iOut = i;
+ }
+ // check if the output is 1 for the 0000 pattern
+ else if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) )
+ {
+ Status.nSat++;
+ if ( Status.iOut == -1 )
+ Status.iOut = i;
+ }
+ else
+ Status.nUndec++;
+ }
+ return Status;
+}
+
+/**Function*************************************************************
+
Synopsis [Creates sequential miter.]
Description []
@@ -143,6 +197,116 @@ Aig_Man_t * Saig_ManCreateMiterComb( Aig_Man_t * p0, Aig_Man_t * p1, int Oper )
/**Function*************************************************************
+ Synopsis [Derives dual-rail AIG.]
+
+ Description [Orders nodes as follows: PIs, ANDs, POs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_AndDualRail( Aig_Man_t * pNew, Aig_Obj_t * pObj, Aig_Obj_t ** ppData, Aig_Obj_t ** ppNext )
+{
+ Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj);
+ Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj);
+ Aig_Obj_t * p0Data = Aig_ObjFaninC0(pObj)? pFanin0->pNext : pFanin0->pData;
+ Aig_Obj_t * p0Next = Aig_ObjFaninC0(pObj)? pFanin0->pData : pFanin0->pNext;
+ Aig_Obj_t * p1Data = Aig_ObjFaninC1(pObj)? pFanin1->pNext : pFanin1->pData;
+ Aig_Obj_t * p1Next = Aig_ObjFaninC1(pObj)? pFanin1->pData : pFanin1->pNext;
+ *ppData = Aig_Or( pNew,
+ Aig_And(pNew, p0Data, Aig_Not(p0Next)),
+ Aig_And(pNew, p1Data, Aig_Not(p1Next)) );
+ *ppNext = Aig_And( pNew,
+ Aig_And(pNew, Aig_Not(p0Data), p0Next),
+ Aig_And(pNew, Aig_Not(p1Data), p1Next) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives dual-rail AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter )
+{
+ Aig_Man_t * pNew;
+ Aig_Obj_t * pObj, * pMiter;
+ int i;
+ Aig_ManCleanData( p );
+ Aig_ManCleanNext( p );
+ // create the new manager
+ pNew = Aig_ManStart( 4*Aig_ManObjNumMax(p) );
+ pNew->pName = Aig_UtilStrsav( p->pName );
+ pNew->pSpec = Aig_UtilStrsav( p->pSpec );
+ // create the PIs
+ Aig_ManConst1(p)->pData = Aig_ManConst0(pNew);
+ Aig_ManConst1(p)->pNext = Aig_ManConst1(pNew);
+ Aig_ManForEachPi( p, pObj, i )
+ {
+ pObj->pData = Aig_ObjCreatePi( pNew );
+ pObj->pNext = Aig_ObjCreatePi( pNew );
+ }
+ // duplicate internal nodes
+ Aig_ManForEachNode( p, pObj, i )
+ Saig_AndDualRail( pNew, pObj, (Aig_Obj_t **)&pObj->pData, &pObj->pNext );
+ // add the POs
+ if ( fMiter )
+ {
+ pMiter = Aig_ManConst1(pNew);
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ pMiter = Aig_And( pNew, pMiter,
+ Aig_Or(pNew, pObj->pData, pObj->pNext) );
+ }
+ Aig_ObjCreatePo( pNew, pMiter );
+ Saig_ManForEachLi( p, pObj, i )
+ {
+ if ( !Aig_ObjFaninC0(pObj) )
+ {
+ Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pData );
+ Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pNext );
+ }
+ else
+ {
+ Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pNext );
+ Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pData );
+ }
+ }
+ }
+ else
+ {
+ Aig_ManForEachPo( p, pObj, i )
+ {
+ if ( !Aig_ObjFaninC0(pObj) )
+ {
+ Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pData );
+ Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pNext );
+ }
+ else
+ {
+ Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pNext );
+ Aig_ObjCreatePo( pNew, Aig_ObjFanin0(pObj)->pData );
+ }
+ }
+ }
+ Aig_ManSetRegNum( pNew, 2*Aig_ManRegNum(p) );
+ Aig_ManCleanData( p );
+ Aig_ManCleanNext( p );
+ Aig_ManCleanup( pNew );
+ // check the resulting network
+ if ( !Aig_ManCheck(pNew) )
+ printf( "Aig_ManDupSimple(): The check has failed.\n" );
+ return pNew;
+}
+
+/**Function*************************************************************
+
Synopsis [Create combinational timeframes by unrolling sequential circuits.]
Description []
@@ -392,7 +556,7 @@ int Saig_ManDemiterSimpleDiff( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t **
Vec_Ptr_t * vSet0, * vSet1;
Aig_Obj_t * pObj, * pFanin, * pObj0, * pObj1;
int i, Counter = 0;
- assert( Saig_ManRegNum(p) % 2 == 0 );
+// assert( Saig_ManRegNum(p) % 2 == 0 );
vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) );
vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) );
Saig_ManForEachPo( p, pObj, i )
@@ -773,27 +937,47 @@ PRT( "Time", clock() - clkTotal );
SeeAlso []
***********************************************************************/
-int Ssw_SecSpecialMiter( Aig_Man_t * pMiter, int fVerbose )
+int Ssw_SecSpecialMiter( Aig_Man_t * p0, Aig_Man_t * p1, int nFrames, int fVerbose )
{
- int nFrames = 2; // modify to enable comparison over any number of frames
Aig_Man_t * pPart0, * pPart1;
int RetValue;
if ( fVerbose )
- Aig_ManPrintStats( pMiter );
- // demiter the miter
- if ( !Saig_ManDemiterSimple( pMiter, &pPart0, &pPart1 ) )
+ printf( "Performing sequential verification combinational A/B miter.\n" );
+ // consider the case when a miter is given
+ if ( p1 == NULL )
{
- printf( "Demitering has failed.\n" );
- return -1;
+ if ( fVerbose )
+ {
+ Aig_ManPrintStats( p0 );
+ }
+ // demiter the miter
+ if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) )
+ {
+ printf( "Demitering has failed.\n" );
+ return -1;
+ }
+ }
+ else
+ {
+ pPart0 = Aig_ManDupSimple( p0 );
+ pPart1 = Aig_ManDupSimple( p1 );
}
if ( fVerbose )
{
- Aig_ManPrintStats( pPart0 );
- Aig_ManPrintStats( pPart1 );
- Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL );
- Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL );
- printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" );
+// Aig_ManPrintStats( pPart0 );
+// Aig_ManPrintStats( pPart1 );
+ if ( p1 == NULL )
+ {
+// Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL );
+// Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL );
+// printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" );
+ }
}
+ assert( Aig_ManRegNum(pPart0) > 0 );
+ assert( Aig_ManRegNum(pPart1) > 0 );
+ assert( Saig_ManPiNum(pPart0) == Saig_ManPiNum(pPart1) );
+ assert( Saig_ManPoNum(pPart0) == Saig_ManPoNum(pPart1) );
+ assert( Aig_ManRegNum(pPart0) == Aig_ManRegNum(pPart1) );
RetValue = Ssw_SecSpecial( pPart0, pPart1, nFrames, fVerbose );
Aig_ManStop( pPart0 );
Aig_ManStop( pPart1 );
diff --git a/src/aig/saig/saigPhase.c b/src/aig/saig/saigPhase.c
index 0f0b1c06..c6d84066 100644
--- a/src/aig/saig/saigPhase.c
+++ b/src/aig/saig/saigPhase.c
@@ -468,7 +468,7 @@ void Saig_TsiStateOrAll( Saig_Tsim_t * pTsi, unsigned * pState )
SeeAlso []
***********************************************************************/
-Saig_Tsim_t * Saig_ManReachableTernary( Aig_Man_t * p, Vec_Int_t * vInits )
+Saig_Tsim_t * Saig_ManReachableTernary( Aig_Man_t * p, Vec_Int_t * vInits, int fVerbose )
{
Saig_Tsim_t * pTsi;
Aig_Obj_t * pObj, * pObjLi, * pObjLo;
@@ -507,7 +507,11 @@ Saig_Tsim_t * Saig_ManReachableTernary( Aig_Man_t * p, Vec_Int_t * vInits )
// Saig_TsiStatePrint( pTsi, pState );
// check if this state exists
if ( Saig_TsiStateLookup( pTsi, pState, pTsi->nWords ) )
+ {
+ if ( fVerbose )
+ printf( "Ternary simulation converged after %d iterations.\n", f );
return pTsi;
+ }
// insert this state
Saig_TsiStateInsert( pTsi, pState, pTsi->nWords );
// simulate internal nodes
@@ -781,7 +785,7 @@ Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrame
assert( Saig_ManPiNum(p) );
assert( Saig_ManPoNum(p) );
// perform terminary simulation
- pTsi = Saig_ManReachableTernary( p, vInits );
+ pTsi = Saig_ManReachableTernary( p, vInits, fVerbose );
if ( pTsi == NULL )
return NULL;
// derive information
@@ -837,7 +841,7 @@ Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose )
assert( Saig_ManPiNum(p) );
assert( Saig_ManPoNum(p) );
// perform terminary simulation
- pTsi = Saig_ManReachableTernary( p, NULL );
+ pTsi = Saig_ManReachableTernary( p, NULL, fVerbose );
if ( pTsi == NULL )
return NULL;
// derive information
diff --git a/src/aig/saig/saigSimExt.c b/src/aig/saig/saigSimExt.c
new file mode 100644
index 00000000..49c85ff4
--- /dev/null
+++ b/src/aig/saig/saigSimExt.c
@@ -0,0 +1,325 @@
+/**CFile****************************************************************
+
+ FileName [saigSimExt.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Sequential AIG package.]
+
+ Synopsis [Extending simulation trace to contain ternary values.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: saigSimExt.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "ssw.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define SAIG_ZER 1
+#define SAIG_ONE 2
+#define SAIG_UND 3
+
+static inline int Saig_ManSimInfoNot( int Value )
+{
+ if ( Value == SAIG_ZER )
+ return SAIG_ONE;
+ if ( Value == SAIG_ONE )
+ return SAIG_ZER;
+ return SAIG_UND;
+}
+
+static inline int Saig_ManSimInfoAnd( int Value0, int Value1 )
+{
+ if ( Value0 == SAIG_ZER || Value1 == SAIG_ZER )
+ return SAIG_ZER;
+ if ( Value0 == SAIG_ONE && Value1 == SAIG_ONE )
+ return SAIG_ONE;
+ return SAIG_UND;
+}
+
+static inline int Saig_ManSimInfoGet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame )
+{
+ unsigned * pInfo = Vec_PtrEntry( vSimInfo, Aig_ObjId(pObj) );
+ return 3 & (pInfo[iFrame >> 4] >> ((iFrame & 15) << 1));
+}
+
+static inline void Saig_ManSimInfoSet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame, int Value )
+{
+ unsigned * pInfo = Vec_PtrEntry( vSimInfo, Aig_ObjId(pObj) );
+ assert( Value >= SAIG_ZER && Value <= SAIG_UND );
+ Value ^= Saig_ManSimInfoGet( vSimInfo, pObj, iFrame );
+ pInfo[iFrame >> 4] ^= (Value << ((iFrame & 15) << 1));
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs ternary simulation for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Saig_ManExtendOneEval( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame )
+{
+ int Value0, Value1, Value;
+ Value0 = Saig_ManSimInfoGet( vSimInfo, Aig_ObjFanin0(pObj), iFrame );
+ if ( Aig_ObjFaninC0(pObj) )
+ Value0 = Saig_ManSimInfoNot( Value0 );
+ if ( Aig_ObjIsPo(pObj) )
+ {
+ Saig_ManSimInfoSet( vSimInfo, pObj, iFrame, Value0 );
+ return Value0;
+ }
+ assert( Aig_ObjIsNode(pObj) );
+ Value1 = Saig_ManSimInfoGet( vSimInfo, Aig_ObjFanin1(pObj), iFrame );
+ if ( Aig_ObjFaninC1(pObj) )
+ Value1 = Saig_ManSimInfoNot( Value1 );
+ Value = Saig_ManSimInfoAnd( Value0, Value1 );
+ Saig_ManSimInfoSet( vSimInfo, pObj, iFrame, Value );
+ return Value;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs ternary simulation for one design.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Saig_ManSimDataInit( Aig_Man_t * p, Ssw_Cex_t * pCex, Vec_Ptr_t * vSimInfo, Vec_Int_t * vRes )
+{
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+ int i, f, Entry, iBit = 0;
+ Saig_ManForEachLo( p, pObj, i )
+ Saig_ManSimInfoSet( vSimInfo, pObj, 0, Aig_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE:SAIG_ZER );
+ for ( f = 0; f <= pCex->iFrame; f++ )
+ {
+ Saig_ManSimInfoSet( vSimInfo, Aig_ManConst1(p), f, SAIG_ONE );
+ Saig_ManForEachPi( p, pObj, i )
+ Saig_ManSimInfoSet( vSimInfo, pObj, f, Aig_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE:SAIG_ZER );
+ if ( vRes )
+ Vec_IntForEachEntry( vRes, Entry, i )
+ Saig_ManSimInfoSet( vSimInfo, Aig_ManPi(p, Entry), f, SAIG_UND );
+ Aig_ManForEachNode( p, pObj, i )
+ Saig_ManExtendOneEval( vSimInfo, pObj, f );
+ Aig_ManForEachPo( p, pObj, i )
+ Saig_ManExtendOneEval( vSimInfo, pObj, f );
+ if ( f == pCex->iFrame )
+ break;
+ Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+ Saig_ManSimInfoSet( vSimInfo, pObjLo, f+1, Saig_ManSimInfoGet(vSimInfo, pObjLi, f) );
+ }
+ // make sure the output of the property failed
+ pObj = Aig_ManPo( p, pCex->iPo );
+ return Saig_ManSimInfoGet( vSimInfo, pObj, pCex->iFrame );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to assign ternary value to one of the primary inputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Saig_ManExtendOne( Aig_Man_t * p, Ssw_Cex_t * pCex, Vec_Ptr_t * vSimInfo,
+ int iPi, int iFrame, Vec_Int_t * vUndo, Vec_Int_t * vVis, Vec_Int_t * vVis2 )
+{
+ Aig_Obj_t * pFanout, * pObj = Aig_ManPi(p, iPi);
+ int i, k, f, iFanout, Value, Value2, Entry;
+ // save original value
+ Value = Saig_ManSimInfoGet( vSimInfo, pObj, iFrame );
+ assert( Value == SAIG_ZER || Value == SAIG_ONE );
+ Vec_IntPush( vUndo, Aig_ObjId(pObj) );
+ Vec_IntPush( vUndo, iFrame );
+ Vec_IntPush( vUndo, Value );
+ // update original value
+ Saig_ManSimInfoSet( vSimInfo, pObj, iFrame, SAIG_UND );
+ // traverse
+ Vec_IntClear( vVis );
+ Vec_IntPush( vVis, Aig_ObjId(pObj) );
+ for ( f = iFrame; f <= pCex->iFrame; f++ )
+ {
+ Vec_IntClear( vVis2 );
+ Vec_IntForEachEntry( vVis, Entry, i )
+ {
+ pObj = Aig_ManObj( p, Entry );
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k )
+ {
+ assert( Aig_ObjId(pObj) < Aig_ObjId(pFanout) );
+ Value = Saig_ManSimInfoGet( vSimInfo, pFanout, f );
+ if ( Value == SAIG_UND )
+ continue;
+ Value2 = Saig_ManExtendOneEval( vSimInfo, pFanout, f );
+ if ( Value2 == Value )
+ continue;
+ assert( Value2 == SAIG_UND );
+// assert( Vec_IntFind(vVis, Aig_ObjId(pFanout)) == -1 );
+ if ( Aig_ObjIsNode(pFanout) )
+ Vec_IntPushOrder( vVis, Aig_ObjId(pFanout) );
+ else if ( Saig_ObjIsLi(p, pFanout) )
+ Vec_IntPush( vVis2, Aig_ObjId(pFanout) );
+ Vec_IntPush( vUndo, Aig_ObjId(pFanout) );
+ Vec_IntPush( vUndo, f );
+ Vec_IntPush( vUndo, Value );
+ }
+ }
+ if ( Vec_IntSize(vVis2) == 0 )
+ break;
+ if ( f == pCex->iFrame )
+ break;
+ // transfer
+ Vec_IntClear( vVis );
+ Vec_IntForEachEntry( vVis2, Entry, i )
+ {
+ pObj = Aig_ManObj( p, Entry );
+ assert( Saig_ObjIsLi(p, pObj) );
+ pFanout = Saig_ObjLiToLo( p, pObj );
+ Vec_IntPushOrder( vVis, Aig_ObjId(pFanout) );
+ Value = Saig_ManSimInfoGet( vSimInfo, pObj, f );
+ Saig_ManSimInfoSet( vSimInfo, pFanout, f+1, Value );
+ }
+ }
+ // check the output
+ pObj = Aig_ManPo( p, pCex->iPo );
+ Value = Saig_ManSimInfoGet( vSimInfo, pObj, pCex->iFrame );
+ assert( Value == SAIG_ONE || Value == SAIG_UND );
+ return (int)(Value == SAIG_ONE);
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_ManExtendUndo( Aig_Man_t * p, Vec_Ptr_t * vSimInfo, Vec_Int_t * vUndo )
+{
+ Aig_Obj_t * pObj;
+ int i, iFrame, Value;
+ for ( i = 0; i < Vec_IntSize(vUndo); i += 3 )
+ {
+ pObj = Aig_ManObj( p, Vec_IntEntry(vUndo, i) );
+ iFrame = Vec_IntEntry(vUndo, i+1);
+ Value = Vec_IntEntry(vUndo, i+2);
+ assert( Saig_ManSimInfoGet(vSimInfo, pObj, iFrame) == SAIG_UND );
+ Saig_ManSimInfoSet( vSimInfo, pObj, iFrame, Value );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of PIs for flops that should not be absracted.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManExtendCounterExample( Aig_Man_t * p, int iFirstPi, Ssw_Cex_t * pCex, Vec_Ptr_t * vSimInfo, int fVerbose )
+{
+ Vec_Int_t * vRes, * vResInv, * vUndo, * vVis, * vVis2;
+ int i, f, Value;
+ assert( Aig_ManRegNum(p) > 0 );
+ assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Aig_BitWordNum(2*(pCex->iFrame+1)) );
+ // start simulation data
+ Value = Saig_ManSimDataInit( p, pCex, vSimInfo, NULL );
+ assert( Value == SAIG_ONE );
+ // select the result
+ vRes = Vec_IntAlloc( 1000 );
+ vResInv = Vec_IntAlloc( 1000 );
+ vVis = Vec_IntAlloc( 1000 );
+ vVis2 = Vec_IntAlloc( 1000 );
+ vUndo = Vec_IntAlloc( 1000 );
+ for ( i = iFirstPi; i < Saig_ManPiNum(p); i++ )
+ {
+ Vec_IntClear( vUndo );
+ for ( f = pCex->iFrame; f >= 0; f-- )
+ if ( !Saig_ManExtendOne( p, pCex, vSimInfo, i, f, vUndo, vVis, vVis2 ) )
+ {
+ Saig_ManExtendUndo( p, vSimInfo, vUndo );
+ break;
+ }
+ if ( f >= 0 )
+ Vec_IntPush( vRes, i );
+ else
+ Vec_IntPush( vResInv, i );
+ }
+ Vec_IntFree( vVis );
+ Vec_IntFree( vVis2 );
+ Vec_IntFree( vUndo );
+ // resimulate to make sure it is valid
+ Value = Saig_ManSimDataInit( p, pCex, vSimInfo, vResInv );
+ assert( Value == SAIG_ONE );
+ Vec_IntFree( vResInv );
+ return vRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of PIs for flops that should not be absracted.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManExtendCounterExampleTest( Aig_Man_t * p, int iFirstPi, Ssw_Cex_t * pCex, int fVerbose )
+{
+ Vec_Int_t * vRes;
+ Vec_Ptr_t * vSimInfo;
+ int clk;
+ Aig_ManFanoutStart( p );
+ vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), Aig_BitWordNum(2*(pCex->iFrame+1)) );
+clk = clock();
+ vRes = Saig_ManExtendCounterExample( p, iFirstPi, pCex, vSimInfo, fVerbose );
+ if ( fVerbose )
+ {
+ printf( "Total new PIs = %3d. Non-removable PIs = %3d. ", Saig_ManPiNum(p)-iFirstPi, Vec_IntSize(vRes) );
+PRT( "Time", clock() - clk );
+ }
+ Vec_PtrFree( vSimInfo );
+ Aig_ManFanoutStop( p );
+ return vRes;
+// Vec_IntFree( vRes );
+// return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/saig/saigSimFast.c b/src/aig/saig/saigSimFast.c
new file mode 100644
index 00000000..09bb6a06
--- /dev/null
+++ b/src/aig/saig/saigSimFast.c
@@ -0,0 +1,443 @@
+/**CFile****************************************************************
+
+ FileName [saigSimFast.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Sequential AIG package.]
+
+ Synopsis [Fast sequential AIG simulator.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: saigSimFast.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// the AIG manager
+typedef struct Faig_Man_t_ Faig_Man_t;
+struct Faig_Man_t_
+{
+ // parameters
+ int nPis;
+ int nPos;
+ int nCis;
+ int nCos;
+ int nFfs;
+ int nNos;
+ // offsets
+ int nPis1;
+ int nCis1;
+ int nCisNos1;
+ int nCisNosPos1;
+ int nObjs;
+ // allocated data
+ int nWords;
+ int pObjs[0];
+};
+
+static inline int Faig_CheckIdPi( Faig_Man_t * p, int i ) { return i >= 1 && i < p->nPis1; }
+static inline int Faig_CheckIdLo( Faig_Man_t * p, int i ) { return i >= p->nPis1 && i < p->nCis1; }
+static inline int Faig_CheckIdNo( Faig_Man_t * p, int i ) { return i >= p->nCis1 && i < p->nCisNos1; }
+static inline int Faig_CheckIdPo( Faig_Man_t * p, int i ) { return i >= p->nCisNos1 && i < p->nCisNosPos1; }
+static inline int Faig_CheckIdLi( Faig_Man_t * p, int i ) { return i >= p->nCisNosPos1 && i < p->nObjs; }
+static inline int Faig_CheckIdCo( Faig_Man_t * p, int i ) { return i >= p->nCisNos1 && i < p->nObjs; }
+static inline int Faig_CheckIdObj( Faig_Man_t * p, int i ) { return i >= 0 && i < p->nObjs; }
+
+static inline int Faig_ObjIdToNumPi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdPi(p,i) ); return i - 1; }
+static inline int Faig_ObjIdToNumLo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLo(p,i) ); return i - p->nPis1; }
+static inline int Faig_ObjIdToNumNo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdNo(p,i) ); return i - p->nCis1; }
+static inline int Faig_ObjIdToNumPo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdPo(p,i) ); return i - p->nCisNos1; }
+static inline int Faig_ObjIdToNumLi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLi(p,i) ); return i - p->nCisNosPos1; }
+static inline int Faig_ObjIdToNumCo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdCo(p,i) ); return i - p->nCisNos1; }
+
+static inline int Faig_ObjLoToLi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLo(p,i) ); return p->nObjs - (p->nCis1 - i); }
+static inline int Faig_ObjLiToLo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLi(p,i) ); return p->nCis1 - (p->nObjs - i); }
+
+static inline int Faig_NodeChild0( Faig_Man_t * p, int n ) { return p->pObjs[n<<1]; }
+static inline int Faig_NodeChild1( Faig_Man_t * p, int n ) { return p->pObjs[(n<<1)+1]; }
+static inline int Faig_CoChild0( Faig_Man_t * p, int n ) { return p->pObjs[(p->nNos<<1)+n]; }
+static inline int Faig_ObjFaninC( int iFan ) { return iFan & 1; }
+static inline int Faig_ObjFanin( int iFan ) { return iFan >> 1; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the manager is correct.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Faig_ManIsCorrect( Aig_Man_t * pAig )
+{
+ return Aig_ManObjNumMax(pAig) ==
+ 1 + Aig_ManPiNum(pAig) + Aig_ManNodeNum(pAig) + Aig_ManPoNum(pAig);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates fast simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Faig_Man_t * Faig_ManAlloc( Aig_Man_t * pAig )
+{
+ Faig_Man_t * p;
+ int nWords;
+// assert( Faig_ManIsCorrect(pAig) );
+ nWords = 2 * Aig_ManNodeNum(pAig) + Aig_ManPoNum(pAig);
+ p = (Faig_Man_t *)ALLOC( char, sizeof(Faig_Man_t) + sizeof(int) * nWords );
+//printf( "Allocating %7.2f Mb.\n", 1.0 * (sizeof(Faig_Man_t) + sizeof(int) * nWords)/(1<<20) );
+ memset( p, 0, sizeof(Faig_Man_t) );
+ p->nPis = Aig_ManPiNum(pAig) - Aig_ManRegNum(pAig);
+ p->nPos = Aig_ManPoNum(pAig) - Aig_ManRegNum(pAig);
+ p->nCis = Aig_ManPiNum(pAig);
+ p->nCos = Aig_ManPoNum(pAig);
+ p->nFfs = Aig_ManRegNum(pAig);
+ p->nNos = Aig_ManNodeNum(pAig);
+ // offsets
+ p->nPis1 = p->nPis + 1;
+ p->nCis1 = p->nCis + 1;
+ p->nCisNos1 = p->nCis + p->nNos + 1;
+ p->nCisNosPos1 = p->nCis + p->nNos + p->nPos + 1;
+ p->nObjs = p->nCis + p->nNos + p->nCos + 1;
+ p->nWords = nWords;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates fast simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Faig_Man_t * Faig_ManCreate( Aig_Man_t * pAig )
+{
+ Faig_Man_t * p;
+ Aig_Obj_t * pObj;
+ int i, iWord = 0;
+ p = Faig_ManAlloc( pAig );
+ Aig_ManForEachNode( pAig, pObj, i )
+ {
+ p->pObjs[iWord++] = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj);
+ p->pObjs[iWord++] = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj);
+ }
+ Aig_ManForEachPo( pAig, pObj, i )
+ p->pObjs[iWord++] = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj);
+ assert( iWord == p->nWords );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Faig_SimulateNode( Faig_Man_t * p, int Id, unsigned * pSimInfo )
+{
+ int n = Faig_ObjIdToNumNo( p, Id );
+ int iFan0 = Faig_NodeChild0( p, n );
+ int iFan1 = Faig_NodeChild1( p, n );
+ if ( Faig_ObjFaninC(iFan0) && Faig_ObjFaninC(iFan1) )
+ return ~(pSimInfo[Faig_ObjFanin(iFan0)] | pSimInfo[Faig_ObjFanin(iFan1)]);
+ if ( Faig_ObjFaninC(iFan0) && !Faig_ObjFaninC(iFan1) )
+ return (~pSimInfo[Faig_ObjFanin(iFan0)] & pSimInfo[Faig_ObjFanin(iFan1)]);
+ if ( !Faig_ObjFaninC(iFan0) && Faig_ObjFaninC(iFan1) )
+ return (pSimInfo[Faig_ObjFanin(iFan0)] & ~pSimInfo[Faig_ObjFanin(iFan1)]);
+ // if ( !Faig_ObjFaninC(iFan0) && !Faig_ObjFaninC(iFan1) )
+ return (pSimInfo[Faig_ObjFanin(iFan0)] & pSimInfo[Faig_ObjFanin(iFan1)]);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Faig_SimulateCo( Faig_Man_t * p, int Id, unsigned * pSimInfo )
+{
+ int n = Faig_ObjIdToNumCo( p, Id );
+ int iFan0 = Faig_CoChild0( p, n );
+ if ( Faig_ObjFaninC(iFan0) )
+ return ~pSimInfo[Faig_ObjFanin(iFan0)];
+ // if ( !Faig_ObjFaninC(iFan0) )
+ return pSimInfo[Faig_ObjFanin(iFan0)];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Faig_SimulateRandomShift( unsigned uOld )
+{
+ return (uOld << 16) | ((uOld ^ Aig_ManRandom(0)) & 0xffff);
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline unsigned Faig_SimulateTransferShift( unsigned uOld, unsigned uNew )
+{
+ return (uOld << 16) | (uNew & 0xffff);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates the timeframes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Faig_ManSimulateFrames( Faig_Man_t * p, int nFrames, int nPref, int fTrans )
+{
+ int * pNumOnes = CALLOC( unsigned, p->nObjs );
+ unsigned * pSimInfo = ALLOC( unsigned, p->nObjs );
+ int f, i;
+//printf( "Allocating %7.2f Mb.\n", 1.0 * 4 * p->nObjs/(1<<20) );
+//printf( "Allocating %7.2f Mb.\n", 1.0 * 4 * p->nObjs/(1<<20) );
+ // set constant 1
+ pSimInfo[0] = ~0;
+ for ( f = 0; f < nFrames; f++ )
+ {
+ if ( fTrans )
+ {
+ for ( i = 1; i < p->nPis1; i++ )
+ pSimInfo[i] = f? Faig_SimulateRandomShift( pSimInfo[i] ) : Aig_ManRandom( 0 );
+ for ( ; i < p->nCis1; i++ )
+ pSimInfo[i] = f? Faig_SimulateTransferShift( pSimInfo[i], pSimInfo[Faig_ObjLoToLi(p,i)] ) : 0;
+ }
+ else
+ {
+ for ( i = 1; i < p->nPis1; i++ )
+ pSimInfo[i] = Aig_ManRandom( 0 );
+ for ( ; i < p->nCis1; i++ )
+ pSimInfo[i] = f? pSimInfo[Faig_ObjLoToLi(p,i)] : 0;
+ }
+ for ( ; i < p->nCisNos1; i++ )
+ pSimInfo[i] = Faig_SimulateNode( p, i, pSimInfo );
+ for ( ; i < p->nObjs; i++ )
+ pSimInfo[i] = Faig_SimulateCo( p, i, pSimInfo );
+ if ( f < nPref )
+ continue;
+ if ( fTrans )
+ {
+ for ( i = 0; i < p->nObjs; i++ )
+ pNumOnes[i] += Aig_WordCountOnes( (pSimInfo[i] ^ (pSimInfo[i] >> 16)) & 0xffff );
+ }
+ else
+ {
+ for ( i = 0; i < p->nObjs; i++ )
+ pNumOnes[i] += Aig_WordCountOnes( pSimInfo[i] );
+ }
+ }
+ free( pSimInfo );
+ return pNumOnes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes switching activity of one node.]
+
+ Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Faig_ManComputeSwitching( int nOnes, int nSimWords )
+{
+ int nTotal = 32 * nSimWords;
+ return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes switching activity of one node.]
+
+ Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Faig_ManComputeProbOne( int nOnes, int nSimWords )
+{
+ int nTotal = 32 * nSimWords;
+ return (float)nOnes / nTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Faig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne )
+{
+ extern char * Abc_FrameReadFlag( char * pFlag );
+ int fTrans = 1;
+ Faig_Man_t * pAig;
+ Vec_Int_t * vSwitching;
+ int * pProbs;
+ float * pSwitching;
+ int nFramesReal, clk, clkTotal = clock();
+ if ( fProbOne )
+ fTrans = 0;
+ vSwitching = Vec_IntStart( Aig_ManObjNumMax(p) );
+ pSwitching = (float *)vSwitching->pArray;
+clk = clock();
+ pAig = Faig_ManCreate( p );
+//PRT( "\nCreation ", clock() - clk );
+ Aig_ManRandom( 1 );
+ // get the number of frames to simulate
+ // if the parameter "seqsimframes" is defined, use it
+ // otherwise, use the given number of frames "nFrames"
+ nFramesReal = nFrames;
+ if ( Abc_FrameReadFlag("seqsimframes") )
+ nFramesReal = atoi( Abc_FrameReadFlag("seqsimframes") );
+ if ( nFramesReal <= nPref )
+ {
+ printf( "The total number of frames (%d) should exceed prefix (%d).\n", nFramesReal, nPref );
+ printf( "Setting the total number of frames to be %d.\n", nFrames );
+ nFramesReal = nFrames;
+ }
+//printf( "Simulating %d frames.\n", nFramesReal );
+clk = clock();
+ pProbs = Faig_ManSimulateFrames( pAig, nFramesReal, nPref, fTrans );
+//PRT( "Simulation", clock() - clk );
+clk = clock();
+ if ( fTrans )
+ {
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ pObj = Aig_ManConst1(p);
+ pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 );
+ Aig_ManForEachPi( p, pObj, i )
+ pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 );
+ Aig_ManForEachNode( p, pObj, i )
+ pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 );
+ Aig_ManForEachPo( p, pObj, i )
+ pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 );
+ assert( Counter == pAig->nObjs );
+ }
+ else if ( fProbOne )
+ {
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ pObj = Aig_ManConst1(p);
+ pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref );
+ Aig_ManForEachPi( p, pObj, i )
+ pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref );
+ Aig_ManForEachNode( p, pObj, i )
+ pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref );
+ Aig_ManForEachPo( p, pObj, i )
+ pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref );
+ assert( Counter == pAig->nObjs );
+ }
+ else
+ {
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ pObj = Aig_ManConst1(p);
+ pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref );
+ Aig_ManForEachPi( p, pObj, i )
+ pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref );
+ Aig_ManForEachNode( p, pObj, i )
+ pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref );
+ Aig_ManForEachPo( p, pObj, i )
+ pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref );
+ assert( Counter == pAig->nObjs );
+ }
+ free( pProbs );
+ free( pAig );
+//PRT( "Switch ", clock() - clk );
+//PRT( "TOTAL ", clock() - clkTotal );
+ return vSwitching;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes probability of switching (or of being 1).]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne )
+{
+ return Faig_ManComputeSwitchProbs( p, nFrames, nPref, fProbOne );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/saig/saigSimMv.c b/src/aig/saig/saigSimMv.c
new file mode 100644
index 00000000..0e250a74
--- /dev/null
+++ b/src/aig/saig/saigSimMv.c
@@ -0,0 +1,726 @@
+/**CFile****************************************************************
+
+ FileName [saigSimMv.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Sequential AIG package.]
+
+ Synopsis [Multi-valued simulation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: saigSimMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define SAIG_DIFF_VALUES 8
+#define SAIG_UNDEF_VALUE 0x1ffffffe //536870910
+
+// old AIG
+typedef struct Saig_MvObj_t_ Saig_MvObj_t;
+struct Saig_MvObj_t_
+{
+ int iFan0;
+ int iFan1;
+ unsigned Type : 3;
+ unsigned Value : 29;
+};
+
+// new AIG
+typedef struct Saig_MvAnd_t_ Saig_MvAnd_t;
+struct Saig_MvAnd_t_
+{
+ int iFan0;
+ int iFan1;
+ int iNext;
+};
+
+// simulation manager
+typedef struct Saig_MvMan_t_ Saig_MvMan_t;
+struct Saig_MvMan_t_
+{
+ // user data
+ Aig_Man_t * pAig; // original AIG
+ // parameters
+ int nStatesMax; // maximum number of states
+ int nLevelsMax; // maximum number of levels
+ int nValuesMax; // maximum number of values
+ int nFlops; // number of flops
+ // compacted AIG
+ Saig_MvObj_t * pAigOld; // AIG objects
+ Vec_Ptr_t * vFlops; // collected flops
+ Vec_Ptr_t * vTired; // collected flops
+ int * pTStates; // hash table for states
+ int nTStatesSize; // hash table size
+ Aig_MmFixed_t * pMemStates; // memory for states
+ Vec_Ptr_t * vStates; // reached states
+ int * pRegsUndef; // count the number of undef values
+ int ** pRegsValues; // write the first different values
+ int * nRegsValues; // count the number of different values
+ int nRUndefs; // the number of undef registers
+ int nRValues[SAIG_DIFF_VALUES+1]; // the number of registers with given values
+ // internal AIG
+ Saig_MvAnd_t * pAigNew; // AIG nodes
+ int nObjsAlloc; // the number of objects allocated
+ int nObjs; // the number of objects
+ int nPis; // the number of primary inputs
+ int * pTNodes; // hash table
+ int nTNodesSize; // hash table size
+ unsigned char * pLevels; // levels of AIG nodes
+};
+
+static inline int Saig_MvObjFaninC0( Saig_MvObj_t * pObj ) { return pObj->iFan0 & 1; }
+static inline int Saig_MvObjFaninC1( Saig_MvObj_t * pObj ) { return pObj->iFan1 & 1; }
+static inline int Saig_MvObjFanin0( Saig_MvObj_t * pObj ) { return pObj->iFan0 >> 1; }
+static inline int Saig_MvObjFanin1( Saig_MvObj_t * pObj ) { return pObj->iFan1 >> 1; }
+
+static inline int Saig_MvConst0() { return 1; }
+static inline int Saig_MvConst1() { return 0; }
+static inline int Saig_MvConst( int c ) { return !c; }
+static inline int Saig_MvUndef() { return SAIG_UNDEF_VALUE; }
+
+static inline int Saig_MvIsConst0( int iNode ) { return iNode == 1; }
+static inline int Saig_MvIsConst1( int iNode ) { return iNode == 0; }
+static inline int Saig_MvIsConst( int iNode ) { return iNode < 2; }
+static inline int Saig_MvIsUndef( int iNode ) { return iNode == SAIG_UNDEF_VALUE;}
+
+static inline int Saig_MvRegular( int iNode ) { return (iNode & ~01); }
+static inline int Saig_MvNot( int iNode ) { return (iNode ^ 01); }
+static inline int Saig_MvNotCond( int iNode, int c ) { return (iNode ^ (c)); }
+static inline int Saig_MvIsComplement( int iNode ) { return (int)(iNode & 01); }
+
+static inline int Saig_MvLit2Var( int iNode ) { return (iNode >> 1); }
+static inline int Saig_MvVar2Lit( int iVar ) { return (iVar << 1); }
+static inline int Saig_MvLev( Saig_MvMan_t * p, int iNode ) { return p->pLevels[iNode >> 1]; }
+
+// iterator over compacted objects
+#define Saig_MvManForEachObj( pAig, pEntry ) \
+ for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates reduced manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Saig_MvObj_t * Saig_ManCreateReducedAig( Aig_Man_t * p, Vec_Ptr_t ** pvFlops )
+{
+ Saig_MvObj_t * pAig, * pEntry;
+ Aig_Obj_t * pObj;
+ int i;
+ *pvFlops = Vec_PtrAlloc( Aig_ManRegNum(p) );
+ pAig = CALLOC( Saig_MvObj_t, Aig_ManObjNumMax(p)+1 );
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ pEntry = pAig + i;
+ pEntry->Type = pObj->Type;
+ if ( Aig_ObjIsPi(pObj) || i == 0 )
+ {
+ if ( Saig_ObjIsLo(p, pObj) )
+ {
+ pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1);
+ pEntry->iFan1 = -1;
+ Vec_PtrPush( *pvFlops, pEntry );
+ }
+ continue;
+ }
+ pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj);
+ if ( Aig_ObjIsPo(pObj) )
+ continue;
+ assert( Aig_ObjIsNode(pObj) );
+ pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj);
+ }
+ pEntry = pAig + Aig_ManObjNumMax(p);
+ pEntry->Type = AIG_OBJ_VOID;
+ return pAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Saig_MvCreateObj( Saig_MvMan_t * p, int iFan0, int iFan1 )
+{
+ Saig_MvAnd_t * pNode;
+ if ( p->nObjs == p->nObjsAlloc )
+ {
+ p->pAigNew = REALLOC( Saig_MvAnd_t, p->pAigNew, 2*p->nObjsAlloc );
+ p->pLevels = REALLOC( unsigned char, p->pLevels, 2*p->nObjsAlloc );
+ p->nObjsAlloc *= 2;
+ }
+ pNode = p->pAigNew + p->nObjs;
+ pNode->iFan0 = iFan0;
+ pNode->iFan1 = iFan1;
+ pNode->iNext = 0;
+ if ( iFan0 || iFan1 )
+ p->pLevels[p->nObjs] = 1 + AIG_MAX( Saig_MvLev(p, iFan0), Saig_MvLev(p, iFan1) );
+ else
+ p->pLevels[p->nObjs] = 0, p->nPis++;
+ return p->nObjs++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates multi-valued simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Saig_MvMan_t * Saig_MvManStart( Aig_Man_t * pAig )
+{
+ Saig_MvMan_t * p;
+ int i;
+ assert( Aig_ManRegNum(pAig) > 0 );
+ p = (Saig_MvMan_t *)ALLOC( Saig_MvMan_t, 1 );
+ memset( p, 0, sizeof(Saig_MvMan_t) );
+ // set parameters
+ p->pAig = pAig;
+ p->nStatesMax = 200;
+ p->nLevelsMax = 4;
+ p->nValuesMax = SAIG_DIFF_VALUES;
+ p->nFlops = Aig_ManRegNum(pAig);
+ // compacted AIG
+ p->pAigOld = Saig_ManCreateReducedAig( pAig, &p->vFlops );
+ p->nTStatesSize = Aig_PrimeCudd( p->nStatesMax );
+ p->pTStates = CALLOC( int, p->nTStatesSize );
+ p->pMemStates = Aig_MmFixedStart( sizeof(int) * (p->nFlops+1), p->nStatesMax );
+ p->vStates = Vec_PtrAlloc( p->nStatesMax );
+ Vec_PtrPush( p->vStates, NULL );
+ p->pRegsUndef = CALLOC( int, p->nFlops );
+ p->pRegsValues = ALLOC( int *, p->nFlops );
+ p->pRegsValues[0] = ALLOC( int, p->nValuesMax * p->nFlops );
+ for ( i = 1; i < p->nFlops; i++ )
+ p->pRegsValues[i] = p->pRegsValues[i-1] + p->nValuesMax;
+ p->nRegsValues = CALLOC( int, p->nFlops );
+ p->vTired = Vec_PtrAlloc( 100 );
+ // internal AIG
+ p->nObjsAlloc = 1000000;
+ p->pAigNew = ALLOC( Saig_MvAnd_t, p->nObjsAlloc );
+ p->nTNodesSize = Aig_PrimeCudd( p->nObjsAlloc / 3 );
+ p->pTNodes = CALLOC( int, p->nTNodesSize );
+ p->pLevels = ALLOC( unsigned char, p->nObjsAlloc );
+ Saig_MvCreateObj( p, 0, 0 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Destroys multi-valued simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_MvManStop( Saig_MvMan_t * p )
+{
+ Aig_MmFixedStop( p->pMemStates, 0 );
+ Vec_PtrFree( p->vStates );
+ Vec_PtrFree( p->vFlops );
+ Vec_PtrFree( p->vTired );
+ free( p->pRegsValues[0] );
+ free( p->pRegsValues );
+ free( p->nRegsValues );
+ free( p->pRegsUndef );
+ free( p->pAigOld );
+ free( p->pTStates );
+ free( p->pAigNew );
+ free( p->pTNodes );
+ free( p->pLevels );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Hashing the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Saig_MvHash( int iFan0, int iFan1, int TableSize )
+{
+ unsigned Key = 0;
+ assert( iFan0 < iFan1 );
+ Key ^= Saig_MvLit2Var(iFan0) * 7937;
+ Key ^= Saig_MvLit2Var(iFan1) * 2971;
+ Key ^= Saig_MvIsComplement(iFan0) * 911;
+ Key ^= Saig_MvIsComplement(iFan1) * 353;
+ return (int)(Key % TableSize);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the place where this node is stored (or should be stored).]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int * Saig_MvTableFind( Saig_MvMan_t * p, int iFan0, int iFan1 )
+{
+ Saig_MvAnd_t * pEntry;
+ int * pPlace = p->pTNodes + Saig_MvHash( iFan0, iFan1, p->nTNodesSize );
+ for ( pEntry = (*pPlace)? p->pAigNew + *pPlace : NULL; pEntry;
+ pPlace = &pEntry->iNext, pEntry = (*pPlace)? p->pAigNew + *pPlace : NULL )
+ if ( pEntry->iFan0 == iFan0 && pEntry->iFan1 == iFan1 )
+ break;
+ return pPlace;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs an AND-operation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Saig_MvAnd( Saig_MvMan_t * p, int iFan0, int iFan1 )
+{
+ if ( iFan0 == iFan1 )
+ return iFan0;
+ if ( iFan0 == Saig_MvNot(iFan1) )
+ return Saig_MvConst0();
+ if ( Saig_MvIsConst(iFan0) )
+ return Saig_MvIsConst1(iFan0) ? iFan1 : Saig_MvConst0();
+ if ( Saig_MvIsConst(iFan1) )
+ return Saig_MvIsConst1(iFan1) ? iFan0 : Saig_MvConst0();
+ if ( Saig_MvIsUndef(iFan0) || Saig_MvIsUndef(iFan1) )
+ return Saig_MvUndef();
+ if ( Saig_MvLev(p, iFan0) >= p->nLevelsMax || Saig_MvLev(p, iFan1) >= p->nLevelsMax )
+ return Saig_MvUndef();
+
+// return Saig_MvUndef();
+
+ if ( iFan0 > iFan1 )
+ {
+ int Temp = iFan0;
+ iFan0 = iFan1;
+ iFan1 = Temp;
+ }
+ {
+ int * pPlace;
+ pPlace = Saig_MvTableFind( p, iFan0, iFan1 );
+ if ( *pPlace == 0 )
+ *pPlace = Saig_MvCreateObj( p, iFan0, iFan1 );
+ return Saig_MvVar2Lit( *pPlace );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Propagates one edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Saig_MvSimulateValue0( Saig_MvObj_t * pAig, Saig_MvObj_t * pObj )
+{
+ Saig_MvObj_t * pObj0 = pAig + Saig_MvObjFanin0(pObj);
+ if ( Saig_MvIsUndef( pObj0->Value ) )
+ return Saig_MvUndef();
+ return Saig_MvNotCond( pObj0->Value, Saig_MvObjFaninC0(pObj) );
+}
+static inline int Saig_MvSimulateValue1( Saig_MvObj_t * pAig, Saig_MvObj_t * pObj )
+{
+ Saig_MvObj_t * pObj1 = pAig + Saig_MvObjFanin1(pObj);
+ if ( Saig_MvIsUndef( pObj1->Value ) )
+ return Saig_MvUndef();
+ return Saig_MvNotCond( pObj1->Value, Saig_MvObjFaninC1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one iteration of simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_MvSimulateFrame( Saig_MvMan_t * p, int fFirst )
+{
+ int fPrintState = 0;
+ Saig_MvObj_t * pEntry;
+ int i, NewValue;
+ Saig_MvManForEachObj( p->pAigOld, pEntry )
+ {
+ if ( pEntry->Type == AIG_OBJ_AND )
+ {
+ pEntry->Value = Saig_MvAnd( p,
+ Saig_MvSimulateValue0(p->pAigOld, pEntry),
+ Saig_MvSimulateValue1(p->pAigOld, pEntry) );
+/*
+printf( "%d = %d%s * %d%s --> %d\n", pEntry - p->pAigOld,
+ Saig_MvObjFanin0(pEntry), Saig_MvObjFaninC0(pEntry)? "-":"+",
+ Saig_MvObjFanin1(pEntry), Saig_MvObjFaninC1(pEntry)? "-":"+", pEntry->Value );
+*/
+ }
+ else if ( pEntry->Type == AIG_OBJ_PO )
+ pEntry->Value = Saig_MvSimulateValue0(p->pAigOld, pEntry);
+ else if ( pEntry->Type == AIG_OBJ_PI )
+ {
+ if ( pEntry->iFan1 == 0 ) // true PI
+ pEntry->Value = Saig_MvVar2Lit( Saig_MvCreateObj( p, 0, 0 ) );
+// else if ( fFirst ) // register output
+// pEntry->Value = Saig_MvConst0();
+// else
+// pEntry->Value = Saig_MvSimulateValue0(p->pAigOld, pEntry);
+ }
+ else if ( pEntry->Type == AIG_OBJ_CONST1 )
+ pEntry->Value = Saig_MvConst1();
+ else if ( pEntry->Type != AIG_OBJ_NONE )
+ assert( 0 );
+ }
+ Vec_PtrClear( p->vTired );
+ Vec_PtrForEachEntry( p->vFlops, pEntry, i )
+ {
+ NewValue = Saig_MvSimulateValue0(p->pAigOld, pEntry);
+ if ( NewValue != (int)pEntry->Value )
+ Vec_PtrPush( p->vTired, pEntry );
+ pEntry->Value = NewValue;
+ if ( !fPrintState )
+ continue;
+ if ( pEntry->Value == 536870910 )
+ printf( "* " );
+ else
+ printf( "%d ", pEntry->Value );
+ }
+if ( fPrintState )
+printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes hash value of the node using its simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Saig_MvSimHash( int * pState, int nFlops, int TableSize )
+{
+ static int s_SPrimes[128] = {
+ 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
+ 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
+ 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
+ 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
+ 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
+ 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
+ 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
+ 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
+ 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
+ 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
+ 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
+ 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
+ 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+ };
+ unsigned uHash = 0;
+ int i;
+ for ( i = 0; i < nFlops; i++ )
+ uHash ^= pState[i] * s_SPrimes[i & 0x7F];
+ return (int)(uHash % TableSize);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the place where this state is stored (or should be stored).]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int * Saig_MvSimTableFind( Saig_MvMan_t * p, int * pState )
+{
+ int * pEntry;
+ int * pPlace = p->pTStates + Saig_MvSimHash( pState+1, p->nFlops, p->nTStatesSize );
+ for ( pEntry = (*pPlace)? Vec_PtrEntry(p->vStates, *pPlace) : NULL; pEntry;
+ pPlace = pEntry, pEntry = (*pPlace)? Vec_PtrEntry(p->vStates, *pPlace) : NULL )
+ if ( memcmp( pEntry+1, pState+1, sizeof(int)*p->nFlops ) == 0 )
+ break;
+ return pPlace;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Saves current state.]
+
+ Description [Returns -1 if there is no fixed point.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Saig_MvSaveState( Saig_MvMan_t * p, int * piReg )
+{
+ Saig_MvObj_t * pEntry;
+ int i, k, * pState, * pPlace, nMaxUndefs = 0;
+ int iTimesOld, iTimesNew;
+ *piReg = -1;
+ pState = (int *)Aig_MmFixedEntryFetch( p->pMemStates );
+ pState[0] = 0;
+ Vec_PtrForEachEntry( p->vFlops, pEntry, i )
+ {
+ iTimesOld = p->nRegsValues[i];
+ // count the number of different def values
+ if ( !Saig_MvIsUndef( pEntry->Value ) && p->nRegsValues[i] < p->nValuesMax )
+ {
+ for ( k = 0; k < p->nRegsValues[i]; k++ )
+ if ( p->pRegsValues[i][k] == (int)pEntry->Value )
+ break;
+ if ( k == p->nRegsValues[i] )
+ p->pRegsValues[i][ p->nRegsValues[i]++ ] = pEntry->Value;
+ }
+ else // retire this register (consider moving this up!)
+ {
+ pEntry->Value = Saig_MvUndef();
+ p->nRegsValues[i] = SAIG_DIFF_VALUES+1;
+ }
+ iTimesNew = p->nRegsValues[i];
+ // count the number of times
+ if ( iTimesOld != iTimesNew )
+ {
+ if ( iTimesOld > 0 )
+ p->nRValues[iTimesOld]--;
+ if ( iTimesNew <= SAIG_DIFF_VALUES )
+ p->nRValues[iTimesNew]++;
+ }
+ // count the number of undef values
+ if ( Saig_MvIsUndef( pEntry->Value ) )
+ {
+ if ( p->pRegsUndef[i]++ == 0 )
+ p->nRUndefs++;
+ }
+ // find def reg with the max number of undef values
+ if ( nMaxUndefs < p->pRegsUndef[i] )
+ {
+ nMaxUndefs = p->pRegsUndef[i];
+ *piReg = i;
+ }
+ // remember state
+ pState[i+1] = pEntry->Value;
+
+// if ( pEntry->Value == 536870910 )
+// printf( "* " );
+// else
+// printf( "%d ", pEntry->Value );
+ }
+//printf( "\n" );
+ pPlace = Saig_MvSimTableFind( p, pState );
+ if ( *pPlace )
+ return *pPlace;
+ *pPlace = Vec_PtrSize( p->vStates );
+ Vec_PtrPush( p->vStates, pState );
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs multi-valued simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_MvManPostProcess( Saig_MvMan_t * p, int iState )
+{
+ Saig_MvObj_t * pEntry;
+ int i, k, j, nTotal = 0, * pState, Counter = 0, iFlop;
+ Vec_Int_t * vUniques = Vec_IntAlloc( 100 );
+ Vec_Int_t * vCounter = Vec_IntAlloc( 100 );
+ // count registers that never became undef
+ Vec_PtrForEachEntry( p->vFlops, pEntry, i )
+ if ( p->pRegsUndef[i] == 0 )
+ nTotal++;
+ printf( "The number of registers that never became undef = %d. (Total = %d.)\n", nTotal, p->nFlops );
+ Vec_PtrForEachEntry( p->vFlops, pEntry, i )
+ {
+ if ( p->pRegsUndef[i] )
+ continue;
+ Vec_IntForEachEntry( vUniques, iFlop, k )
+ {
+ Vec_PtrForEachEntryStart( p->vStates, pState, j, 1 )
+ if ( pState[iFlop+1] != pState[i+1] )
+ break;
+ if ( j == Vec_PtrSize(p->vStates) )
+ {
+ Vec_IntAddToEntry( vCounter, k, 1 );
+ break;
+ }
+ }
+ if ( k == Vec_IntSize(vUniques) )
+ {
+ Vec_IntPush( vUniques, i );
+ Vec_IntPush( vCounter, 1 );
+ }
+ }
+ Vec_IntForEachEntry( vUniques, iFlop, i )
+ {
+ printf( "FLOP %5d : (%3d) ", iFlop, Vec_IntEntry(vCounter,i) );
+/*
+ for ( k = 0; k < p->nRegsValues[iFlop]; k++ )
+ if ( p->pRegsValues[iFlop][k] == 536870910 )
+ printf( "* " );
+ else
+ printf( "%d ", p->pRegsValues[iFlop][k] );
+ printf( "\n" );
+*/
+ Vec_PtrForEachEntryStart( p->vStates, pState, k, 1 )
+ {
+ if ( k == iState+1 )
+ printf( " # " );
+ if ( pState[iFlop+1] == 536870910 )
+ printf( "*" );
+ else
+ printf( "%d", pState[iFlop+1] );
+ }
+ printf( "\n" );
+// if ( ++Counter == 10 )
+// break;
+ }
+
+ Vec_IntFree( vUniques );
+ Vec_IntFree( vCounter );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs multi-valued simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Saig_MvManSimulate( Aig_Man_t * pAig, int fVerbose )
+{
+ Saig_MvMan_t * p;
+ Saig_MvObj_t * pEntry;
+ int f, i, k, iRegMax, iState, clk = clock();
+ // start the manager
+ p = Saig_MvManStart( pAig );
+PRT( "Constructing the problem", clock() - clk );
+ clk = clock();
+ // initiliaze registers
+ Vec_PtrForEachEntry( p->vFlops, pEntry, i )
+ {
+ pEntry->Value = Saig_MvConst0();
+ if ( pEntry->iFan0 == 1 )
+ printf( "Constant value %d\n", i );
+ }
+
+ Saig_MvSaveState( p, &iRegMax );
+ // simulate until convergence
+ for ( f = 0; ; f++ )
+ {
+/*
+ if ( fVerbose )
+ {
+ printf( "%3d : ", f+1 );
+ printf( "*=%6d ", p->nRUndefs );
+ for ( k = 1; k < SAIG_DIFF_VALUES; k++ )
+ if ( p->nRValues[k] == 0 )
+ printf( " " );
+ else
+ printf( "%d=%6d ", k, p->nRValues[k] );
+ printf( "aig=%6d", p->nObjs );
+ printf( "\n" );
+ }
+*/
+ Saig_MvSimulateFrame( p, f==0 );
+ iState = Saig_MvSaveState( p, &iRegMax );
+ if ( iState >= 0 )
+ {
+ printf( "Converged after %d frames with lasso in state %d. Cycle = %d.\n", f+1, iState-1, f+2-iState );
+ printf( "Total number of PIs = %d. AND nodes = %d.\n", p->nPis, p->nObjs - p->nPis );
+ break;
+ }
+ if ( f >= p->nStatesMax && iRegMax >= 0 )
+ {
+/*
+ pEntry = Vec_PtrEntry( p->vFlops, iRegMax );
+ assert( pEntry->Value != (unsigned)Saig_MvUndef() );
+ pEntry->Value = Saig_MvUndef();
+ printf( "Retiring flop %d.\n", iRegMax );
+*/
+// printf( "Retiring %d flops.\n", Vec_PtrSize(p->vTired) );
+ Vec_PtrForEachEntry( p->vTired, pEntry, k )
+ pEntry->Value = Saig_MvUndef();
+ }
+ }
+PRT( "Multi-value simulation", clock() - clk );
+ // implement equivalences
+ Saig_MvManPostProcess( p, iState-1 );
+ Saig_MvManStop( p );
+ return 1;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/saig/saigSimSeq.c b/src/aig/saig/saigSimSeq.c
new file mode 100644
index 00000000..26783346
--- /dev/null
+++ b/src/aig/saig/saigSimSeq.c
@@ -0,0 +1,513 @@
+/**CFile****************************************************************
+
+ FileName [saigSimSeq.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Sequential AIG package.]
+
+ Synopsis [Fast sequential AIG simulator.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: saigSimSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "ssw.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// combinational simulation manager
+typedef struct Raig_Man_t_ Raig_Man_t;
+struct Raig_Man_t_
+{
+ // parameters
+ Aig_Man_t * pAig; // the AIG to be used for simulation
+ int nWords; // the number of words to simulate
+ // AIG representation
+ int nPis; // the number of primary inputs
+ int nPos; // the number of primary outputs
+ int nCis; // the number of combinational inputs
+ int nCos; // the number of combinational outputs
+ int nNodes; // the number of internal nodes
+ int nObjs; // nCis + nNodes + nCos + 2
+ int * pFans0; // fanin0 for all objects
+ int * pFans1; // fanin1 for all objects
+ Vec_Int_t * vCis2Ids; // mapping of CIs into their PI ids
+ Vec_Int_t * vLos; // register outputs
+ Vec_Int_t * vLis; // register inputs
+ // simulation info
+ int * pRefs; // reference counter for each node
+ unsigned * pSims; // simlulation information for each node
+ // recycable memory
+ unsigned * pMems; // allocated simulaton memory
+ int nWordsAlloc; // the number of allocated entries
+ int nMems; // the number of used entries
+ int nMemsMax; // the max number of used entries
+ int MemFree; // next free entry
+};
+
+static inline int Raig_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; }
+static inline int Raig_Lit2Var( int Lit ) { return Lit >> 1; }
+static inline int Raig_LitIsCompl( int Lit ) { return Lit & 1; }
+static inline int Raig_LitNot( int Lit ) { return Lit ^ 1; }
+static inline int Raig_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); }
+static inline int Raig_LitRegular( int Lit ) { return Lit & ~01; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Find the PO corresponding to the PO driver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Raig_ManFindPo( Aig_Man_t * pAig, int iNode )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Saig_ManForEachPo( pAig, pObj, i )
+ if ( pObj->iData == iNode )
+ return i;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates fast simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Raig_ManCreate_rec( Raig_Man_t * p, Aig_Obj_t * pObj )
+{
+ int iFan0, iFan1;
+ assert( !Aig_IsComplement(pObj) );
+ if ( pObj->iData )
+ return pObj->iData;
+ assert( !Aig_ObjIsConst1(pObj) );
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ iFan0 = Raig_ManCreate_rec( p, Aig_ObjFanin0(pObj) );
+ iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj);
+ iFan1 = Raig_ManCreate_rec( p, Aig_ObjFanin1(pObj) );
+ iFan1 = (iFan1 << 1) | Aig_ObjFaninC1(pObj);
+ }
+ else if ( Aig_ObjIsPo(pObj) )
+ {
+ iFan0 = Raig_ManCreate_rec( p, Aig_ObjFanin0(pObj) );
+ iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj);
+ iFan1 = 0;
+ }
+ else
+ {
+ iFan0 = iFan1 = 0;
+ Vec_IntPush( p->vCis2Ids, Aig_ObjPioNum(pObj) );
+ }
+ p->pFans0[p->nObjs] = iFan0;
+ p->pFans1[p->nObjs] = iFan1;
+ p->pRefs[p->nObjs] = Aig_ObjRefs(pObj);
+ return pObj->iData = p->nObjs++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates fast simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Raig_Man_t * Raig_ManCreate( Aig_Man_t * pAig )
+{
+ Raig_Man_t * p;
+ Aig_Obj_t * pObj;
+ int i, nObjs;
+ Aig_ManCleanData( pAig );
+ p = (Raig_Man_t *)ALLOC( Raig_Man_t, 1 );
+ memset( p, 0, sizeof(Raig_Man_t) );
+ p->pAig = pAig;
+ p->nPis = Saig_ManPiNum(pAig);
+ p->nPos = Saig_ManPoNum(pAig);
+ p->nCis = Aig_ManPiNum(pAig);
+ p->nCos = Aig_ManPoNum(pAig);
+ p->nNodes = Aig_ManNodeNum(pAig);
+ nObjs = p->nCis + p->nCos + p->nNodes + 2;
+ p->pFans0 = ALLOC( int, nObjs );
+ p->pFans1 = ALLOC( int, nObjs );
+ p->pRefs = ALLOC( int, nObjs );
+ p->pSims = CALLOC( unsigned, nObjs );
+ p->vCis2Ids = Vec_IntAlloc( Aig_ManPiNum(pAig) );
+ // add objects (0=unused; 1=const1)
+ p->nObjs = 2;
+ pObj = Aig_ManConst1( pAig );
+ pObj->iData = 1;
+ Aig_ManForEachPi( pAig, pObj, i )
+ if ( Aig_ObjRefs(pObj) == 0 )
+ Raig_ManCreate_rec( p, pObj );
+ Aig_ManForEachPo( pAig, pObj, i )
+ Raig_ManCreate_rec( p, pObj );
+ assert( Vec_IntSize(p->vCis2Ids) == Aig_ManPiNum(pAig) );
+ assert( p->nObjs == nObjs );
+ // collect flop outputs
+ p->vLos = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+ Saig_ManForEachLo( pAig, pObj, i )
+ Vec_IntPush( p->vLos, pObj->iData );
+ // collect flop inputs
+ p->vLis = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+ Saig_ManForEachLi( pAig, pObj, i )
+ {
+ Vec_IntPush( p->vLis, pObj->iData );
+ assert( p->pRefs[ pObj->iData ] == 0 );
+ p->pRefs[ pObj->iData ]++;
+ }
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates fast simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Raig_ManDelete( Raig_Man_t * p )
+{
+ Vec_IntFree( p->vCis2Ids );
+ Vec_IntFree( p->vLos );
+ Vec_IntFree( p->vLis );
+ FREE( p->pFans0 );
+ FREE( p->pFans1 );
+ FREE( p->pRefs );
+ FREE( p->pSims );
+ FREE( p->pMems );
+ FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [References simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Raig_ManSimRef( Raig_Man_t * p, int i )
+{
+ unsigned * pSim;
+ assert( i > 1 );
+ assert( p->pSims[i] == 0 );
+ if ( p->MemFree == 0 )
+ {
+ int * pPlace, Ent;
+ if ( p->nWordsAlloc == 0 )
+ {
+ assert( p->pMems == NULL );
+ p->nWordsAlloc = (1<<17); // -> 1Mb
+ p->nMems = 1;
+ }
+ p->nWordsAlloc *= 2;
+ p->pMems = REALLOC( unsigned, p->pMems, p->nWordsAlloc );
+ memset( p->pMems, 0xff, sizeof(unsigned) * (p->nWords + 1) );
+ pPlace = &p->MemFree;
+ for ( Ent = p->nMems * (p->nWords + 1);
+ Ent + p->nWords + 1 < p->nWordsAlloc;
+ Ent += p->nWords + 1 )
+ {
+ *pPlace = Ent;
+ pPlace = p->pMems + Ent;
+ }
+ *pPlace = 0;
+ }
+ p->pSims[i] = p->MemFree;
+ pSim = p->pMems + p->MemFree;
+ p->MemFree = pSim[0];
+ pSim[0] = p->pRefs[i];
+ p->nMems++;
+ if ( p->nMemsMax < p->nMems )
+ p->nMemsMax = p->nMems;
+ return pSim;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dereference simulaton info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Raig_ManSimDeref( Raig_Man_t * p, int i )
+{
+ unsigned * pSim;
+ assert( i );
+ if ( i == 1 ) // const 1
+ return p->pMems;
+ assert( p->pSims[i] > 0 );
+ pSim = p->pMems + p->pSims[i];
+ if ( --pSim[0] == 0 )
+ {
+ pSim[0] = p->MemFree;
+ p->MemFree = p->pSims[i];
+ p->pSims[i] = 0;
+ p->nMems--;
+ }
+ return pSim;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one round.]
+
+ Description [Returns the number of PO entry if failed; 0 otherwise.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Raig_ManSimulateRound( Raig_Man_t * p, int fMiter, int fFirst, int * piPat )
+{
+ unsigned * pRes0, * pRes1, * pRes;
+ int i, w, nCis, nCos, iFan0, iFan1, iPioNum;
+ // nove the values to the register outputs
+ Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i )
+ {
+ if ( iPioNum < p->nPis )
+ continue;
+ pRes = Raig_ManSimRef( p, Vec_IntEntry(p->vLos, iPioNum-p->nPis) );
+ if ( fFirst )
+ memset( pRes + 1, 0, sizeof(unsigned) * p->nWords );
+ else
+ {
+ pRes0 = Raig_ManSimDeref( p, Vec_IntEntry(p->vLis, iPioNum-p->nPis) );
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = pRes0[w];
+ }
+ // handle unused PIs
+ if ( pRes[0] == 0 )
+ {
+ pRes[0] = 1;
+ Raig_ManSimDeref( p, Vec_IntEntry(p->vLos, iPioNum-p->nPis) );
+ }
+ }
+ // simulate the logic
+ nCis = nCos = 0;
+ for ( i = 2; i < p->nObjs; i++ )
+ {
+ if ( p->pFans0[i] == 0 ) // ci always has zero first fanin
+ {
+ iPioNum = Vec_IntEntry( p->vCis2Ids, nCis );
+ if ( iPioNum < p->nPis )
+ {
+ pRes = Raig_ManSimRef( p, i );
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = Aig_ManRandom( 0 );
+ // handle unused PIs
+ if ( pRes[0] == 0 )
+ {
+ pRes[0] = 1;
+ Raig_ManSimDeref( p, i );
+ }
+ }
+ else
+ assert( Vec_IntEntry(p->vLos, iPioNum-p->nPis) == i );
+ nCis++;
+ continue;
+ }
+ if ( p->pFans1[i] == 0 ) // co always has non-zero 1st fanin and zero 2nd fanin
+ {
+ pRes0 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans0[i]) );
+ if ( nCos < p->nPos && fMiter )
+ {
+ unsigned Const = Raig_LitIsCompl(p->pFans0[i])? ~0 : 0;
+ for ( w = 1; w <= p->nWords; w++ )
+ if ( pRes0[w] != Const )
+ {
+ *piPat = 32*(w-1) + Aig_WordFindFirstBit( pRes0[w] ^ Const );
+ return i;
+ }
+ }
+ else
+ {
+ pRes = Raig_ManSimRef( p, i );
+ assert( pRes[0] == 1 );
+ if ( Raig_LitIsCompl(p->pFans0[i]) )
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = ~pRes0[w];
+ else
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = pRes0[w];
+ }
+ nCos++;
+ continue;
+ }
+ pRes = Raig_ManSimRef( p, i );
+ assert( pRes[0] > 0 );
+ iFan0 = p->pFans0[i];
+ iFan1 = p->pFans1[i];
+ pRes0 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans0[i]) );
+ pRes1 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans1[i]) );
+ if ( Raig_LitIsCompl(iFan0) && Raig_LitIsCompl(iFan1) )
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = ~(pRes0[w] | pRes1[w]);
+ else if ( Raig_LitIsCompl(iFan0) && !Raig_LitIsCompl(iFan1) )
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = ~pRes0[w] & pRes1[w];
+ else if ( !Raig_LitIsCompl(iFan0) && Raig_LitIsCompl(iFan1) )
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = pRes0[w] & ~pRes1[w];
+ else if ( !Raig_LitIsCompl(iFan0) && !Raig_LitIsCompl(iFan1) )
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = pRes0[w] & pRes1[w];
+ }
+ assert( nCis == p->nCis );
+ assert( nCos == p->nCos );
+ assert( p->nMems == 1 + Vec_IntSize(p->vLis) );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Cex_t * Raig_ManGenerateCounter( Aig_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids )
+{
+ Ssw_Cex_t * p;
+ unsigned * pData;
+ int f, i, w, iPioId, Counter;
+ p = Ssw_SmlAllocCounterExample( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), iFrame+1 );
+ p->iFrame = iFrame;
+ p->iPo = iOut;
+ // fill in the binary data
+ Aig_ManRandom( 1 );
+ Counter = p->nRegs;
+ pData = ALLOC( unsigned, nWords );
+ for ( f = 0; f <= iFrame; f++, Counter += p->nPis )
+ for ( i = 0; i < Aig_ManPiNum(pAig); i++ )
+ {
+ iPioId = Vec_IntEntry( vCis2Ids, i );
+ if ( iPioId >= p->nPis )
+ continue;
+ for ( w = 0; w < nWords; w++ )
+ pData[w] = Aig_ManRandom( 0 );
+ if ( Aig_InfoHasBit( pData, iPat ) )
+ Aig_InfoSetBit( p->pData, Counter + iPioId );
+ }
+ free( pData );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the bug is detected, 0 otherwise.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Raig_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose )
+{
+ Raig_Man_t * p;
+ Sec_MtrStatus_t Status;
+ int i, iPat, RetValue = 0;
+ int clk, clkTotal = clock();
+ assert( Aig_ManRegNum(pAig) > 0 );
+ Status = Sec_MiterStatus( pAig );
+ if ( Status.nSat > 0 )
+ {
+ printf( "Miter is trivially satisfiable (output %d).\n", Status.iOut );
+ return 1;
+ }
+ if ( Status.nUndec == 0 )
+ {
+ printf( "Miter is trivially unsatisfiable.\n" );
+ return 0;
+ }
+ Aig_ManRandom( 1 );
+ p = Raig_ManCreate( pAig );
+ p->nWords = nWords;
+ // iterate through objects
+ for ( i = 0; i < nIters; i++ )
+ {
+ clk = clock();
+ RetValue = Raig_ManSimulateRound( p, fMiter, i==0, &iPat );
+ if ( fVerbose )
+ {
+ printf( "Frame %4d out of %4d and timeout %3d sec. ", i+1, nIters, TimeLimit );
+ printf("Time = %7.2f sec\r", (1.0*clock()-clkTotal)/CLOCKS_PER_SEC);
+ }
+ if ( RetValue > 0 )
+ {
+ int iOut = Raig_ManFindPo(p->pAig, RetValue);
+ assert( pAig->pSeqModel == NULL );
+ pAig->pSeqModel = Raig_ManGenerateCounter( pAig, i, iOut, nWords, iPat, p->vCis2Ids );
+ if ( fVerbose )
+ printf( "Miter is satisfiable after simulation (output %d).\n", iOut );
+ break;
+ }
+ if ( (clock() - clk)/CLOCKS_PER_SEC >= TimeLimit )
+ {
+ printf( "No bug detected after %d frames with time limit %d seconds.\n", i+1, TimeLimit );
+ break;
+ }
+ }
+ if ( fVerbose )
+ {
+ printf( "Maxcut = %8d. AigMem = %7.2f Mb. SimMem = %7.2f Mb. ",
+ p->nMemsMax,
+ 1.0*(p->nObjs * 16)/(1<<20),
+ 1.0*(p->nMemsMax * 4 * (nWords+1))/(1<<20) );
+ PRT( "Total time", clock() - clkTotal );
+ }
+ Raig_ManDelete( p );
+ return RetValue > 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/saig/saigStrSim.c b/src/aig/saig/saigStrSim.c
new file mode 100644
index 00000000..ce4b8e05
--- /dev/null
+++ b/src/aig/saig/saigStrSim.c
@@ -0,0 +1,971 @@
+/**CFile****************************************************************
+
+ FileName [saigStrSim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Sequential AIG package.]
+
+ Synopsis [Structural matching using simulation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: saigStrSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+#include "ssw.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define SAIG_WORDS 16
+
+static inline Aig_Obj_t * Saig_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; }
+static inline void Saig_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes hash value of the node using its simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Saig_StrSimHash( Aig_Obj_t * pObj )
+{
+ static int s_SPrimes[128] = {
+ 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
+ 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
+ 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
+ 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
+ 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
+ 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
+ 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
+ 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
+ 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
+ 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
+ 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
+ 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
+ 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+ };
+ unsigned * pSims;
+ unsigned uHash = 0;
+ int i;
+ assert( SAIG_WORDS <= 128 );
+ pSims = pObj->pData;
+ for ( i = 0; i < SAIG_WORDS; i++ )
+ uHash ^= pSims[i] * s_SPrimes[i & 0x7F];
+ return uHash;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes hash value of the node using its simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Saig_StrSimIsEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+ unsigned * pSims0 = pObj0->pData;
+ unsigned * pSims1 = pObj1->pData;
+ int i;
+ for ( i = 0; i < SAIG_WORDS; i++ )
+ if ( pSims0[i] != pSims1[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is zero.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Saig_StrSimIsZero( Aig_Obj_t * pObj )
+{
+ unsigned * pSims = pObj->pData;
+ int i;
+ for ( i = 0; i < SAIG_WORDS; i++ )
+ if ( pSims[i] != 0 )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is one.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Saig_StrSimIsOne( Aig_Obj_t * pObj )
+{
+ unsigned * pSims = pObj->pData;
+ int i;
+ for ( i = 0; i < SAIG_WORDS; i++ )
+ if ( pSims[i] != ~0 )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns random simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimAssignRandom( Aig_Obj_t * pObj )
+{
+ unsigned * pSims = pObj->pData;
+ int i;
+ for ( i = 0; i < SAIG_WORDS; i++ )
+ pSims[i] = Aig_ManRandom(0);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns constant 0 simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimAssignOne( Aig_Obj_t * pObj )
+{
+ unsigned * pSims = pObj->pData;
+ int i;
+ for ( i = 0; i < SAIG_WORDS; i++ )
+ pSims[i] = ~0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns constant 0 simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimAssignZeroInit( Aig_Obj_t * pObj )
+{
+ unsigned * pSims = pObj->pData;
+ pSims[0] = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulated one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimulateNode( Aig_Obj_t * pObj, int i )
+{
+ unsigned * pSims = pObj->pData;
+ unsigned * pSims0 = Aig_ObjFanin0(pObj)->pData;
+ unsigned * pSims1 = Aig_ObjFanin1(pObj)->pData;
+ if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) )
+ pSims[i] = ~(pSims0[i] | pSims1[i]);
+ else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) )
+ pSims[i] = (~pSims0[i] & pSims1[i]);
+ else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) )
+ pSims[i] = (pSims0[i] & ~pSims1[i]);
+ else // if ( !Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) )
+ pSims[i] = (pSims0[i] & pSims1[i]);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Saves output of one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimSaveOutput( Aig_Obj_t * pObj, int i )
+{
+ unsigned * pSims = pObj->pData;
+ unsigned * pSims0 = Aig_ObjFanin0(pObj)->pData;
+ if ( Aig_ObjFaninC0(pObj) )
+ pSims[i] = ~pSims0[i];
+ else
+ pSims[i] = pSims0[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers simulation output to another node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimTransfer( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+ unsigned * pSims0 = pObj0->pData;
+ unsigned * pSims1 = pObj1->pData;
+ int i;
+ for ( i = 0; i < SAIG_WORDS; i++ )
+ pSims1[i] = pSims0[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers simulation output to another node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimTransferNext( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int i )
+{
+ unsigned * pSims0 = pObj0->pData;
+ unsigned * pSims1 = pObj1->pData;
+ assert( i < SAIG_WORDS - 1 );
+ pSims1[i+1] = pSims0[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform one round of simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimulateRound( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Aig_Obj_t * pObj0, * pObj1;
+ int f, i;
+ // simulate the nodes
+ Aig_ManForEachObj( p0, pObj0, i )
+ {
+ if ( !Aig_ObjIsPi(pObj0) && !Aig_ObjIsNode(pObj0) )
+ continue;
+ pObj1 = Aig_ObjRepr(p0, pObj0);
+ if ( pObj1 == NULL )
+ continue;
+ assert( Aig_ObjRepr(p1, pObj1) == pObj0 );
+ Saig_StrSimAssignRandom( pObj0 );
+ Saig_StrSimTransfer( pObj0, pObj1 );
+ }
+ // simulate the timeframes
+ for ( f = 0; f < SAIG_WORDS; f++ )
+ {
+ // simulate the first AIG
+ Aig_ManForEachNode( p0, pObj0, i )
+ if ( Aig_ObjRepr(p0, pObj0) == NULL )
+ Saig_StrSimulateNode( pObj0, f );
+ Saig_ManForEachLi( p0, pObj0, i )
+ Saig_StrSimSaveOutput( pObj0, f );
+ if ( f < SAIG_WORDS - 1 )
+ Saig_ManForEachLiLo( p0, pObj0, pObj1, i )
+ Saig_StrSimTransferNext( pObj0, pObj1, f );
+ // simulate the second AIG
+ Aig_ManForEachNode( p1, pObj1, i )
+ if ( Aig_ObjRepr(p1, pObj1) == NULL )
+ Saig_StrSimulateNode( pObj1, f );
+ Saig_ManForEachLi( p1, pObj1, i )
+ Saig_StrSimSaveOutput( pObj1, f );
+ if ( f < SAIG_WORDS - 1 )
+ Saig_ManForEachLiLo( p1, pObj1, pObj0, i )
+ Saig_StrSimTransferNext( pObj1, pObj0, f );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the entry exists in the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Saig_StrSimTableLookup( Aig_Obj_t ** ppTable, Aig_Obj_t ** ppNexts, int nTableSize, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pEntry;
+ int iEntry;
+ // find the hash entry
+ iEntry = Saig_StrSimHash( pObj ) % nTableSize;
+ // check if there are nodes with this signatures
+ for ( pEntry = ppTable[iEntry]; pEntry; pEntry = Saig_ObjNext(ppNexts,pEntry) )
+ if ( Saig_StrSimIsEqual( pEntry, pObj ) )
+ return pEntry;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the entry into the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimTableInsert( Aig_Obj_t ** ppTable, Aig_Obj_t ** ppNexts, int nTableSize, Aig_Obj_t * pObj )
+{
+ // find the hash entry
+ int iEntry = Saig_StrSimHash( pObj ) % nTableSize;
+ // check if there are nodes with this signatures
+ if ( ppTable[iEntry] == NULL )
+ ppTable[iEntry] = pObj;
+ else
+ {
+ Saig_ObjSetNext( ppNexts, pObj, Saig_ObjNext(ppNexts, ppTable[iEntry]) );
+ Saig_ObjSetNext( ppNexts, ppTable[iEntry], pObj );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform one round of matching.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Saig_StrSimDetectUnique( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Aig_Obj_t ** ppTable, ** ppNexts, ** ppCands;
+ Aig_Obj_t * pObj, * pEntry;
+ int i, nTableSize, Counter;
+
+ // allocate the hash table hashing simulation info into nodes
+ nTableSize = Aig_PrimeCudd( Aig_ManObjNum(p0)/2 );
+ ppTable = CALLOC( Aig_Obj_t *, nTableSize );
+ ppNexts = CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) );
+ ppCands = CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) );
+
+ // hash nodes of the first AIG
+ Aig_ManForEachObj( p0, pObj, i )
+ {
+ if ( !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) )
+ continue;
+ if ( Aig_ObjRepr(p0, pObj) )
+ continue;
+ if ( Saig_StrSimIsZero(pObj) || Saig_StrSimIsOne(pObj) )
+ continue;
+ // check if the entry exists
+ pEntry = Saig_StrSimTableLookup( ppTable, ppNexts, nTableSize, pObj );
+ if ( pEntry == NULL ) // insert
+ Saig_StrSimTableInsert( ppTable, ppNexts, nTableSize, pObj );
+ else // mark the entry as not unique
+ pEntry->fMarkA = 1;
+ }
+
+ // hash nodes from the second AIG
+ Aig_ManForEachObj( p1, pObj, i )
+ {
+ if ( !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) )
+ continue;
+ if ( Aig_ObjRepr(p1, pObj) )
+ continue;
+ if ( Saig_StrSimIsZero(pObj) || Saig_StrSimIsOne(pObj) )
+ continue;
+ // check if the entry exists
+ pEntry = Saig_StrSimTableLookup( ppTable, ppNexts, nTableSize, pObj );
+ if ( pEntry == NULL ) // skip
+ continue;
+ // if there is no candidate, label it
+ if ( Saig_ObjNext( ppCands, pEntry ) == NULL )
+ Saig_ObjSetNext( ppCands, pEntry, pObj );
+ else // mark the entry as not unique
+ pEntry->fMarkA = 1;
+ }
+
+ // create representatives for the unique entries
+ Counter = 0;
+ for ( i = 0; i < nTableSize; i++ )
+ for ( pEntry = ppTable[i]; pEntry; pEntry = Saig_ObjNext(ppNexts,pEntry) )
+ if ( !pEntry->fMarkA && (pObj = Saig_ObjNext( ppCands, pEntry )) )
+ {
+// assert( Aig_ObjIsNode(pEntry) == Aig_ObjIsNode(pObj) );
+ if ( Aig_ObjType(pEntry) != Aig_ObjType(pObj) )
+ continue;
+ Aig_ObjSetRepr( p0, pEntry, pObj );
+ Aig_ObjSetRepr( p1, pObj, pEntry );
+ Counter++;
+ }
+
+ // cleanup
+ Aig_ManCleanMarkA( p0 );
+ free( ppTable );
+ free( ppNexts );
+ free( ppCands );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of matched flops.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Saig_StrSimCountMatchedFlops( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Saig_ManForEachLo( p, pObj, i )
+ if ( Aig_ObjRepr(p, pObj) )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of matched nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Saig_StrSimCountMatchedNodes( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Aig_ManForEachNode( p, pObj, i )
+ if ( Aig_ObjRepr(p, pObj) )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs structural matching of two AIGs using simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimPrepareAig( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManReprStart( p, Aig_ManObjNumMax(p) );
+ // allocate simulation info
+ p->pData2 = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), SAIG_WORDS );
+ Aig_ManForEachObj( p, pObj, i )
+ pObj->pData = Vec_PtrEntry( p->pData2, i );
+ // set simulation info for constant1 and register outputs
+ Saig_StrSimAssignOne( Aig_ManConst1(p) );
+ Saig_ManForEachLo( p, pObj, i )
+ Saig_StrSimAssignZeroInit( pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs structural matching of two AIGs using simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimSetInitMatching( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Aig_Obj_t * pObj0, * pObj1;
+ int i;
+ pObj0 = Aig_ManConst1( p0 );
+ pObj1 = Aig_ManConst1( p1 );
+ Aig_ObjSetRepr( p0, pObj0, pObj1 );
+ Aig_ObjSetRepr( p1, pObj1, pObj0 );
+ Saig_ManForEachPi( p0, pObj0, i )
+ {
+ pObj1 = Aig_ManPi( p1, i );
+ Aig_ObjSetRepr( p0, pObj0, pObj1 );
+ Aig_ObjSetRepr( p1, pObj1, pObj0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs structural matching of two AIGs using simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimSetFinalMatching( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Aig_Obj_t * pObj0, * pObj1;
+ Aig_Obj_t * pFanin00, * pFanin01;
+ Aig_Obj_t * pFanin10, * pFanin11;
+ int i, CountAll = 0, CountNot = 0;
+ Aig_ManIncrementTravId( p0 );
+ Aig_ManForEachObj( p0, pObj0, i )
+ {
+ pObj1 = Aig_ObjRepr( p0, pObj0 );
+ if ( pObj1 == NULL )
+ continue;
+ CountAll++;
+ assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );
+ if ( Aig_ObjIsNode(pObj0) )
+ {
+ assert( Aig_ObjIsNode(pObj1) );
+ pFanin00 = Aig_ObjFanin0(pObj0);
+ pFanin01 = Aig_ObjFanin1(pObj0);
+ pFanin10 = Aig_ObjFanin0(pObj1);
+ pFanin11 = Aig_ObjFanin1(pObj1);
+ if ( Aig_ObjRepr(p0, pFanin00) != pFanin10 ||
+ Aig_ObjRepr(p0, pFanin01) != pFanin11 )
+ {
+ Aig_ObjSetTravIdCurrent(p0, pObj0);
+ CountNot++;
+ }
+ }
+ else if ( Saig_ObjIsLo(p0, pObj0) )
+ {
+ assert( Saig_ObjIsLo(p1, pObj1) );
+ pFanin00 = Aig_ObjFanin0( Saig_ObjLoToLi(p0, pObj0) );
+ pFanin10 = Aig_ObjFanin0( Saig_ObjLoToLi(p1, pObj1) );
+ if ( Aig_ObjRepr(p0, pFanin00) != pFanin10 )
+ {
+ Aig_ObjSetTravIdCurrent(p0, pObj0);
+ CountNot++;
+ }
+ }
+ }
+ // remove irrelevant matches
+ Aig_ManForEachObj( p0, pObj0, i )
+ {
+ pObj1 = Aig_ObjRepr( p0, pObj0 );
+ if ( pObj1 == NULL )
+ continue;
+ assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );
+ if ( Aig_ObjIsTravIdCurrent( p0, pObj0 ) )
+ {
+ Aig_ObjSetRepr( p0, pObj0, NULL );
+ Aig_ObjSetRepr( p1, pObj1, NULL );
+ }
+ }
+ printf( "Total matches = %6d. Wrong matches = %6d. Ratio = %5.2f %%\n",
+ CountAll, CountNot, 100.0*CountNot/CountAll );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of dangling nodes removed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimSetContiguousMatching_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pFanout;
+ int i, iFanout = -1;
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ if ( Saig_ObjIsPo( p, pObj ) )
+ return;
+ if ( Saig_ObjIsLi( p, pObj ) )
+ {
+ Saig_StrSimSetContiguousMatching_rec( p, Saig_ObjLiToLo(p, pObj) );
+ return;
+ }
+ assert( Aig_ObjIsPi(pObj) || Aig_ObjIsNode(pObj) );
+ if ( Aig_ObjRepr(p, pObj) == NULL )
+ return;
+ // go through the fanouts
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+ Saig_StrSimSetContiguousMatching_rec( p, pFanout );
+ // go through the fanins
+ if ( !Aig_ObjIsPi( pObj ) )
+ {
+ Saig_StrSimSetContiguousMatching_rec( p, Aig_ObjFanin0(pObj) );
+ Saig_StrSimSetContiguousMatching_rec( p, Aig_ObjFanin1(pObj) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs structural matching of two AIGs using simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_StrSimSetContiguousMatching( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Aig_Obj_t * pObj0, * pObj1;
+ int i, CountAll = 0, CountNot = 0;
+ // mark nodes reachable through the PIs
+ Aig_ManIncrementTravId( p0 );
+ Aig_ObjSetTravIdCurrent( p0, Aig_ManConst1(p0) );
+ Saig_ManForEachPi( p0, pObj0, i )
+ Saig_StrSimSetContiguousMatching_rec( p0, pObj0 );
+ // remove irrelevant matches
+ Aig_ManForEachObj( p0, pObj0, i )
+ {
+ pObj1 = Aig_ObjRepr( p0, pObj0 );
+ if ( pObj1 == NULL )
+ continue;
+ CountAll++;
+ assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );
+ if ( !Aig_ObjIsTravIdCurrent( p0, pObj0 ) )
+ {
+ Aig_ObjSetRepr( p0, pObj0, NULL );
+ Aig_ObjSetRepr( p1, pObj1, NULL );
+ CountNot++;
+ }
+ }
+ printf( "Total matches = %6d. Wrong matches = %6d. Ratio = %5.2f %%\n",
+ CountAll, CountNot, 100.0*CountNot/CountAll );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Establishes relationship between nodes using pairing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_StrSimMatchingExtendOne( Aig_Man_t * p, Vec_Ptr_t * vNodes )
+{
+ Aig_Obj_t * pNext, * pObj;
+ int i, k, iFan;
+ Vec_PtrClear( vNodes );
+ Aig_ManIncrementTravId( p );
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ if ( Aig_ObjRepr( p, pObj ) != NULL )
+ continue;
+ if ( Saig_ObjIsLo(p, pObj) )
+ {
+ pNext = Saig_ObjLoToLi(p, pObj);
+ pNext = Aig_ObjFanin0(pNext);
+ if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pNext);
+ Vec_PtrPush( vNodes, pNext );
+ }
+ }
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ pNext = Aig_ObjFanin0(pObj);
+ if ( Aig_ObjRepr( p, pNext )&& !Aig_ObjIsTravIdCurrent(p, pNext) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pNext);
+ Vec_PtrPush( vNodes, pNext );
+ }
+ pNext = Aig_ObjFanin1(pObj);
+ if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pNext);
+ Vec_PtrPush( vNodes, pNext );
+ }
+ }
+ Aig_ObjForEachFanout( p, pObj, pNext, iFan, k )
+ {
+ if ( Saig_ObjIsPo(p, pNext) )
+ continue;
+ if ( Saig_ObjIsLi(p, pNext) )
+ pNext = Saig_ObjLiToLo(p, pNext);
+ if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pNext);
+ Vec_PtrPush( vNodes, pNext );
+ }
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Establishes relationship between nodes using pairing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_StrSimMatchingCountUnmached( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ if ( Aig_ObjRepr( p, pObj ) != NULL )
+ continue;
+ Counter++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Establishes relationship between nodes using pairing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_StrSimMatchingExtend( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose )
+{
+ Vec_Ptr_t * vNodes0, * vNodes1;
+ Aig_Obj_t * pNext0, * pNext1;
+ int d, k;
+ vNodes0 = Vec_PtrAlloc( 1000 );
+ vNodes1 = Vec_PtrAlloc( 1000 );
+ if ( fVerbose )
+ {
+ int nUnmached = Ssw_StrSimMatchingCountUnmached(p0);
+ printf( "Extending islands by %d steps:\n", nDist );
+ printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n",
+ 0, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0),
+ nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) );
+ }
+ for ( d = 0; d < nDist; d++ )
+ {
+ Ssw_StrSimMatchingExtendOne( p0, vNodes0 );
+ Ssw_StrSimMatchingExtendOne( p1, vNodes1 );
+ Vec_PtrForEachEntry( vNodes0, pNext0, k )
+ {
+ pNext1 = Aig_ObjRepr( p0, pNext0 );
+ if ( pNext1 == NULL )
+ continue;
+ assert( pNext0 == Aig_ObjRepr( p1, pNext1 ) );
+ if ( Saig_ObjIsPi(p1, pNext1) )
+ continue;
+ Aig_ObjSetRepr( p0, pNext0, NULL );
+ Aig_ObjSetRepr( p1, pNext1, NULL );
+ }
+ Vec_PtrForEachEntry( vNodes1, pNext1, k )
+ {
+ pNext0 = Aig_ObjRepr( p1, pNext1 );
+ if ( pNext0 == NULL )
+ continue;
+ assert( pNext1 == Aig_ObjRepr( p0, pNext0 ) );
+ if ( Saig_ObjIsPi(p0, pNext0) )
+ continue;
+ Aig_ObjSetRepr( p0, pNext0, NULL );
+ Aig_ObjSetRepr( p1, pNext1, NULL );
+ }
+ if ( fVerbose )
+ {
+ int nUnmached = Ssw_StrSimMatchingCountUnmached(p0);
+ printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n",
+ d+1, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0),
+ nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) );
+ }
+ }
+ Vec_PtrFree( vNodes0 );
+ Vec_PtrFree( vNodes1 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs structural matching of two AIGs using simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter )
+{
+ extern Aig_Man_t * Saig_ManWindowExtractMiter( Aig_Man_t * p0, Aig_Man_t * p1 );
+
+ Vec_Int_t * vPairs;
+ Aig_Man_t * pPart0, * pPart1;
+ Aig_Obj_t * pObj0, * pObj1;
+ int i, nMatches, clk, clkTotal = clock();
+ Aig_ManRandom( 1 );
+ // consider the case when a miter is given
+ if ( p1 == NULL )
+ {
+ if ( fVerbose )
+ {
+ Aig_ManPrintStats( p0 );
+ }
+ // demiter the miter
+ if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) )
+ {
+ printf( "Demitering has failed.\n" );
+ return NULL;
+ }
+ }
+ else
+ {
+ pPart0 = Aig_ManDupSimple( p0 );
+ pPart1 = Aig_ManDupSimple( p1 );
+ }
+ if ( fVerbose )
+ {
+ Aig_ManPrintStats( pPart0 );
+ Aig_ManPrintStats( pPart1 );
+ }
+ // start simulation
+ Saig_StrSimPrepareAig( pPart0 );
+ Saig_StrSimPrepareAig( pPart1 );
+ Saig_StrSimSetInitMatching( pPart0, pPart1 );
+ if ( fVerbose )
+ {
+ printf( "Allocated %6.2f Mb to simulate the first AIG.\n",
+ 1.0 * Aig_ManObjNumMax(pPart0) * SAIG_WORDS * sizeof(unsigned) / (1<<20) );
+ printf( "Allocated %6.2f Mb to simulate the second AIG.\n",
+ 1.0 * Aig_ManObjNumMax(pPart1) * SAIG_WORDS * sizeof(unsigned) / (1<<20) );
+ }
+ // iterate matching
+ nMatches = 1;
+ for ( i = 0; nMatches > 0; i++ )
+ {
+ clk = clock();
+ Saig_StrSimulateRound( pPart0, pPart1 );
+ nMatches = Saig_StrSimDetectUnique( pPart0, pPart1 );
+ if ( fVerbose )
+ {
+ int nFlops = Saig_StrSimCountMatchedFlops(pPart0);
+ int nNodes = Saig_StrSimCountMatchedNodes(pPart0);
+ printf( "%3d : Match =%6d. FF =%6d. (%6.2f %%) Node =%6d. (%6.2f %%) ",
+ i, nMatches,
+ nFlops, 100.0*nFlops/Aig_ManRegNum(pPart0),
+ nNodes, 100.0*nNodes/Aig_ManNodeNum(pPart0) );
+ PRT( "Time", clock() - clk );
+ }
+ if ( i == 20 )
+ break;
+ }
+ // cleanup
+ Vec_PtrFree( pPart0->pData2 ); pPart0->pData2 = NULL;
+ Vec_PtrFree( pPart1->pData2 ); pPart1->pData2 = NULL;
+ // extend the islands
+ Aig_ManFanoutStart( pPart0 );
+ Aig_ManFanoutStart( pPart1 );
+ if ( nDist )
+ Ssw_StrSimMatchingExtend( pPart0, pPart1, nDist, fVerbose );
+ Saig_StrSimSetFinalMatching( pPart0, pPart1 );
+// Saig_StrSimSetContiguousMatching( pPart0, pPart1 );
+ // copy the results into array
+ vPairs = Vec_IntAlloc( 2*Aig_ManObjNumMax(pPart0) );
+ Aig_ManForEachObj( pPart0, pObj0, i )
+ {
+ pObj1 = Aig_ObjRepr(pPart0, pObj0);
+ if ( pObj1 == NULL )
+ continue;
+ assert( pObj0 == Aig_ObjRepr(pPart1, pObj1) );
+ Vec_IntPush( vPairs, pObj0->Id );
+ Vec_IntPush( vPairs, pObj1->Id );
+ }
+ // this procedure adds matching of PO and LI
+ if ( ppMiter )
+ *ppMiter = Saig_ManWindowExtractMiter( pPart0, pPart1 );
+ Aig_ManFanoutStop( pPart0 );
+ Aig_ManFanoutStop( pPart1 );
+ Aig_ManStop( pPart0 );
+ Aig_ManStop( pPart1 );
+ PRT( "Total runtime", clock() - clkTotal );
+ return vPairs;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/saig/saigSwitch.c b/src/aig/saig/saigSwitch.c
new file mode 100644
index 00000000..684551be
--- /dev/null
+++ b/src/aig/saig/saigSwitch.c
@@ -0,0 +1,582 @@
+/**CFile****************************************************************
+
+ FileName [saigSwitch.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Sequential AIG package.]
+
+ Synopsis [Returns switching propabilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: saigSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Saig_SimObj_t_ Saig_SimObj_t;
+struct Saig_SimObj_t_
+{
+ int iFan0;
+ int iFan1;
+ unsigned Type : 8;
+ unsigned Number : 24;
+ unsigned pData[1];
+};
+
+static inline int Saig_SimObjFaninC0( Saig_SimObj_t * pObj ) { return pObj->iFan0 & 1; }
+static inline int Saig_SimObjFaninC1( Saig_SimObj_t * pObj ) { return pObj->iFan1 & 1; }
+static inline int Saig_SimObjFanin0( Saig_SimObj_t * pObj ) { return pObj->iFan0 >> 1; }
+static inline int Saig_SimObjFanin1( Saig_SimObj_t * pObj ) { return pObj->iFan1 >> 1; }
+
+//typedef struct Aig_CMan_t_ Aig_CMan_t;
+
+//static Aig_CMan_t * Aig_CManCreate( Aig_Man_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates fast simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Saig_SimObj_t * Saig_ManCreateMan( Aig_Man_t * p )
+{
+ Saig_SimObj_t * pAig, * pEntry;
+ Aig_Obj_t * pObj;
+ int i;
+ pAig = CALLOC( Saig_SimObj_t, Aig_ManObjNumMax(p)+1 );
+// printf( "Allocating %7.2f Mb.\n", 1.0 * sizeof(Saig_SimObj_t) * (Aig_ManObjNumMax(p)+1)/(1<<20) );
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ pEntry = pAig + i;
+ pEntry->Type = pObj->Type;
+ if ( Aig_ObjIsPi(pObj) || i == 0 )
+ {
+ if ( Saig_ObjIsLo(p, pObj) )
+ {
+ pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1);
+ pEntry->iFan1 = -1;
+ }
+ continue;
+ }
+ pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj);
+ if ( Aig_ObjIsPo(pObj) )
+ continue;
+ assert( Aig_ObjIsNode(pObj) );
+ pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj);
+ }
+ pEntry = pAig + Aig_ManObjNumMax(p);
+ pEntry->Type = AIG_OBJ_VOID;
+ return pAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulated one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Saig_ManSimulateNode2( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj )
+{
+ Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj );
+ Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pObj );
+ if ( Saig_SimObjFaninC0(pObj) && Saig_SimObjFaninC1(pObj) )
+ pObj->pData[0] = ~(pObj0->pData[0] | pObj1->pData[0]);
+ else if ( Saig_SimObjFaninC0(pObj) && !Saig_SimObjFaninC1(pObj) )
+ pObj->pData[0] = (~pObj0->pData[0] & pObj1->pData[0]);
+ else if ( !Saig_SimObjFaninC0(pObj) && Saig_SimObjFaninC1(pObj) )
+ pObj->pData[0] = (pObj0->pData[0] & ~pObj1->pData[0]);
+ else // if ( !Saig_SimObjFaninC0(pObj) && !Saig_SimObjFaninC1(pObj) )
+ pObj->pData[0] = (pObj0->pData[0] & pObj1->pData[0]);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulated one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Saig_ManSimulateNode( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj )
+{
+ Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj );
+ Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pObj );
+ pObj->pData[0] = (Saig_SimObjFaninC0(pObj)? ~pObj0->pData[0] : pObj0->pData[0])
+ & (Saig_SimObjFaninC1(pObj)? ~pObj1->pData[0] : pObj1->pData[0]);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulated buffer/inverter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Saig_ManSimulateOneInput( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj )
+{
+ Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj );
+ if ( Saig_SimObjFaninC0(pObj) )
+ pObj->pData[0] = ~pObj0->pData[0];
+ else // if ( !Saig_SimObjFaninC0(pObj) )
+ pObj->pData[0] = pObj0->pData[0];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates the timeframes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_ManSimulateFrames( Saig_SimObj_t * pAig, int nFrames, int nPref )
+{
+ Saig_SimObj_t * pEntry;
+ int f;
+ for ( f = 0; f < nFrames; f++ )
+ {
+ for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ )
+ {
+ if ( pEntry->Type == AIG_OBJ_AND )
+ Saig_ManSimulateNode( pAig, pEntry );
+ else if ( pEntry->Type == AIG_OBJ_PO )
+ Saig_ManSimulateOneInput( pAig, pEntry );
+ else if ( pEntry->Type == AIG_OBJ_PI )
+ {
+ if ( pEntry->iFan0 == 0 ) // true PI
+ pEntry->pData[0] = Aig_ManRandom( 0 );
+ else if ( f > 0 ) // register output
+ Saig_ManSimulateOneInput( pAig, pEntry );
+ }
+ else if ( pEntry->Type == AIG_OBJ_CONST1 )
+ pEntry->pData[0] = ~0;
+ else if ( pEntry->Type != AIG_OBJ_NONE )
+ assert( 0 );
+ if ( f >= nPref )
+ pEntry->Number += Aig_WordCountOnes( pEntry->pData[0] );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes switching activity of one node.]
+
+ Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Saig_ManComputeSwitching( int nOnes, int nSimWords )
+{
+ int nTotal = 32 * nSimWords;
+ return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes switching activity of one node.]
+
+ Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Saig_ManComputeProbOne( int nOnes, int nSimWords )
+{
+ int nTotal = 32 * nSimWords;
+ return (float)nOnes / nTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes switching activity of one node.]
+
+ Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Saig_ManComputeProbOnePlus( int nOnes, int nSimWords, int fCompl )
+{
+ int nTotal = 32 * nSimWords;
+ if ( fCompl )
+ return (float)(nTotal-nOnes) / nTotal;
+ else
+ return (float)nOnes / nTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute switching probabilities of all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManComputeSwitchProbs_old( Aig_Man_t * p, int nFrames, int nPref, int fProbOne )
+{
+ extern char * Abc_FrameReadFlag( char * pFlag );
+ Saig_SimObj_t * pAig, * pEntry;
+ Vec_Int_t * vSwitching;
+ float * pSwitching;
+ int nFramesReal, clk, clkTotal = clock();
+ vSwitching = Vec_IntStart( Aig_ManObjNumMax(p) );
+ pSwitching = (float *)vSwitching->pArray;
+clk = clock();
+ pAig = Saig_ManCreateMan( p );
+//PRT( "\nCreation ", clock() - clk );
+
+ Aig_ManRandom( 1 );
+ // get the number of frames to simulate
+ // if the parameter "seqsimframes" is defined, use it
+ // otherwise, use the given number of frames "nFrames"
+ nFramesReal = nFrames;
+ if ( Abc_FrameReadFlag("seqsimframes") )
+ nFramesReal = atoi( Abc_FrameReadFlag("seqsimframes") );
+ if ( nFramesReal <= nPref )
+ {
+ printf( "The total number of frames (%d) should exceed prefix (%d).\n", nFramesReal, nPref );\
+ printf( "Setting the total number of frames to be %d.\n", nFrames );
+ nFramesReal = nFrames;
+ }
+//printf( "Simulating %d frames.\n", nFramesReal );
+clk = clock();
+ Saig_ManSimulateFrames( pAig, nFramesReal, nPref );
+//PRT( "Simulation", clock() - clk );
+clk = clock();
+ for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ )
+ {
+/*
+ if ( pEntry->Type == AIG_OBJ_AND )
+ {
+ Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pEntry );
+ Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pEntry );
+ printf( "%5.2f = %5.2f * %5.2f (%7.4f)\n",
+ Saig_ManComputeProbOnePlus( pEntry->Number, nFrames - nPref, 0 ),
+ Saig_ManComputeProbOnePlus( pObj0->Number, nFrames - nPref, Saig_SimObjFaninC0(pEntry) ),
+ Saig_ManComputeProbOnePlus( pObj1->Number, nFrames - nPref, Saig_SimObjFaninC1(pEntry) ),
+ Saig_ManComputeProbOnePlus( pEntry->Number, nFrames - nPref, 0 ) -
+ Saig_ManComputeProbOnePlus( pObj0->Number, nFrames - nPref, Saig_SimObjFaninC0(pEntry) ) *
+ Saig_ManComputeProbOnePlus( pObj1->Number, nFrames - nPref, Saig_SimObjFaninC1(pEntry) )
+ );
+ }
+*/
+ if ( fProbOne )
+ pSwitching[pEntry-pAig] = Saig_ManComputeProbOne( pEntry->Number, nFramesReal - nPref );
+ else
+ pSwitching[pEntry-pAig] = Saig_ManComputeSwitching( pEntry->Number, nFramesReal - nPref );
+//printf( "%3d : %7.2f\n", pEntry-pAig, pSwitching[pEntry-pAig] );
+ }
+ free( pAig );
+//PRT( "Switch ", clock() - clk );
+//PRT( "TOTAL ", clock() - clkTotal );
+
+// Aig_CManCreate( p );
+ return vSwitching;
+}
+
+
+
+
+typedef struct Aig_CMan_t_ Aig_CMan_t;
+struct Aig_CMan_t_
+{
+ // parameters
+ int nIns;
+ int nNodes;
+ int nOuts;
+ // current state
+ int iNode;
+ int iDiff0;
+ int iDiff1;
+ unsigned char * pCur;
+ // stored data
+ int iPrev;
+ int nBytes;
+ unsigned char Data[0];
+};
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_CMan_t * Aig_CManStart( int nIns, int nNodes, int nOuts )
+{
+ Aig_CMan_t * p;
+ p = (Aig_CMan_t *)ALLOC( char, sizeof(Aig_CMan_t) + 2*(2*nNodes + nOuts) );
+ memset( p, 0, sizeof(Aig_CMan_t) );
+ // set parameters
+ p->nIns = nIns;
+ p->nOuts = nOuts;
+ p->nNodes = nNodes;
+ p->nBytes = 2*(2*nNodes + nOuts);
+ // prepare the manager
+ p->iNode = 1 + p->nIns;
+ p->iPrev = -1;
+ p->pCur = p->Data;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_CManStop( Aig_CMan_t * p )
+{
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_CManRestart( Aig_CMan_t * p )
+{
+ assert( p->iNode == 1 + p->nIns + p->nNodes + p->nOuts );
+ p->iNode = 1 + p->nIns;
+ p->iPrev = -1;
+ p->pCur = p->Data;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_CManStoreNum( Aig_CMan_t * p, unsigned x )
+{
+ while ( x & ~0x7f )
+ {
+ *p->pCur++ = (x & 0x7f) | 0x80;
+ x >>= 7;
+ }
+ *p->pCur++ = x;
+ assert( p->pCur - p->Data < p->nBytes - 10 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_CManRestoreNum( Aig_CMan_t * p )
+{
+ int ch, i, x = 0;
+ for ( i = 0; (ch = *p->pCur++) & 0x80; i++ )
+ x |= (ch & 0x7f) << (7 * i);
+ return x | (ch << (7 * i));
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_CManAddNode( Aig_CMan_t * p, int iFan0, int iFan1 )
+{
+ assert( iFan0 < iFan1 );
+ assert( iFan1 < (p->iNode << 1) );
+ Aig_CManStoreNum( p, (p->iNode++ << 1) - iFan1 );
+ Aig_CManStoreNum( p, iFan1 - iFan0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_CManAddPo( Aig_CMan_t * p, int iFan0 )
+{
+ if ( p->iPrev == -1 )
+ Aig_CManStoreNum( p, p->iNode - iFan0 );
+ else if ( p->iPrev <= iFan0 )
+ Aig_CManStoreNum( p, (iFan0 - p->iPrev) << 1 );
+ else
+ Aig_CManStoreNum( p,((p->iPrev - iFan0) << 1) | 1 );
+ p->iPrev = iFan0;
+ p->iNode++;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_CManGetNode( Aig_CMan_t * p, int * piFan0, int * piFan1 )
+{
+ *piFan1 = (p->iNode++ << 1) - Aig_CManRestoreNum( p );
+ *piFan0 = *piFan1 - Aig_CManRestoreNum( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_CManGetPo( Aig_CMan_t * p )
+{
+ int Num = Aig_CManRestoreNum( p );
+ if ( p->iPrev == -1 )
+ p->iPrev = p->iNode;
+ p->iNode++;
+ if ( Num & 1 )
+ return p->iPrev = p->iPrev + (Num >> 1);
+ return p->iPrev = p->iPrev - (Num >> 1);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute switching probabilities of all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_CMan_t * Aig_CManCreate( Aig_Man_t * p )
+{
+ Aig_CMan_t * pCMan;
+ Aig_Obj_t * pObj;
+ int i;
+ pCMan = Aig_CManStart( Aig_ManPiNum(p), Aig_ManNodeNum(p), Aig_ManPoNum(p) );
+ Aig_ManForEachNode( p, pObj, i )
+ Aig_CManAddNode( pCMan,
+ (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj),
+ (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj) );
+ Aig_ManForEachPo( p, pObj, i )
+ Aig_CManAddPo( pCMan,
+ (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj) );
+ printf( "\nBytes alloc = %5d. Bytes used = %7d. Ave per node = %4.2f. \n",
+ pCMan->nBytes, pCMan->pCur - pCMan->Data,
+ 1.0 * (pCMan->pCur - pCMan->Data) / (pCMan->nNodes + pCMan->nOuts ) );
+// Aig_CManStop( pCMan );
+ return pCMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute switching probabilities of all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Saig_ManComputeSwitchProbs2( Aig_Man_t * p, int nFrames, int nPref, int fProbOne )
+{
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/saig/saigWnd.c b/src/aig/saig/saigWnd.c
new file mode 100644
index 00000000..5524e19f
--- /dev/null
+++ b/src/aig/saig/saigWnd.c
@@ -0,0 +1,809 @@
+/**CFile****************************************************************
+
+ FileName [saigWnd.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Sequential AIG package.]
+
+ Synopsis [Sequential windowing.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: saigWnd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "saig.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of PI/internal nodes.]
+
+ Description [Marks all the visited nodes with the current ID.
+ Does not collect constant node and PO/LI nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_ManWindowOutline_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Vec_Ptr_t * vNodes, int * pDists )
+{
+ Aig_Obj_t * pMatch, * pFanout;
+ int fCollected, iFanout = -1, i;
+ if ( nDist == 0 )
+ return;
+ if ( pDists[pObj->Id] >= nDist )
+ return;
+ pDists[pObj->Id] = nDist;
+ fCollected = Aig_ObjIsTravIdCurrent( p, pObj );
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+ if ( Saig_ObjIsPo(p, pObj) )
+ return;
+ if ( Saig_ObjIsLi(p, pObj) )
+ {
+ pMatch = Saig_ObjLiToLo( p, pObj );
+ if ( !Aig_ObjIsTravIdCurrent( p, pMatch ) )
+ Saig_ManWindowOutline_rec( p, pMatch, nDist, vNodes, pDists );
+ Saig_ManWindowOutline_rec( p, Aig_ObjFanin0(pObj), nDist-1, vNodes, pDists );
+ return;
+ }
+ if ( !fCollected )
+ Vec_PtrPush( vNodes, pObj );
+ if ( Saig_ObjIsPi(p, pObj) )
+ return;
+ if ( Saig_ObjIsLo(p, pObj) )
+ {
+ pMatch = Saig_ObjLoToLi( p, pObj );
+ if ( !Aig_ObjIsTravIdCurrent( p, pMatch ) )
+ Saig_ManWindowOutline_rec( p, pMatch, nDist, vNodes, pDists );
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+ Saig_ManWindowOutline_rec( p, pFanout, nDist-1, vNodes, pDists );
+ return;
+ }
+ assert( Aig_ObjIsNode(pObj) );
+ Saig_ManWindowOutline_rec( p, Aig_ObjFanin0(pObj), nDist-1, vNodes, pDists );
+ Saig_ManWindowOutline_rec( p, Aig_ObjFanin1(pObj), nDist-1, vNodes, pDists );
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+ Saig_ManWindowOutline_rec( p, pFanout, nDist-1, vNodes, pDists );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of PI/internal nodes.]
+
+ Description [Marks all the visited nodes with the current ID.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManWindowOutline( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist )
+{
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObjLi, * pObjLo;
+ int * pDists, i;
+ pDists = CALLOC( int, Aig_ManObjNumMax(p) );
+ vNodes = Vec_PtrAlloc( 1000 );
+ Aig_ManIncrementTravId( p );
+ Saig_ManWindowOutline_rec( p, pObj, nDist, vNodes, pDists );
+ Vec_PtrSort( vNodes, Aig_ObjCompareIdIncrease );
+ // make sure LI/LO are labeled/unlabeled mutually
+ Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+ assert( Aig_ObjIsTravIdCurrent(p, pObjLi) ==
+ Aig_ObjIsTravIdCurrent(p, pObjLo) );
+ free( pDists );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the node has unlabeled fanout.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Saig_ObjHasUnlabeledFanout( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pFanout;
+ int iFanout = -1, i;
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+ if ( Saig_ObjIsPo(p, pFanout) || !Aig_ObjIsTravIdCurrent(p, pFanout) )
+ return pFanout;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects primary inputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManWindowCollectPis( Aig_Man_t * p, Vec_Ptr_t * vNodes )
+{
+ Vec_Ptr_t * vNodesPi;
+ Aig_Obj_t * pObj, * pMatch, * pFanin;
+ int i;
+ vNodesPi = Vec_PtrAlloc( 1000 );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ if ( Saig_ObjIsPi(p, pObj) )
+ {
+ assert( pObj->pData == NULL );
+ Vec_PtrPush( vNodesPi, pObj );
+ }
+ else if ( Saig_ObjIsLo(p, pObj) )
+ {
+ pMatch = Saig_ObjLoToLi( p, pObj );
+ pFanin = Aig_ObjFanin0(pMatch);
+ if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL )
+ Vec_PtrPush( vNodesPi, pFanin );
+ }
+ else
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ pFanin = Aig_ObjFanin0(pObj);
+ if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL )
+ Vec_PtrPush( vNodesPi, pFanin );
+ pFanin = Aig_ObjFanin1(pObj);
+ if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL )
+ Vec_PtrPush( vNodesPi, pFanin );
+ }
+ }
+ return vNodesPi;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects primary outputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManWindowCollectPos( Aig_Man_t * p, Vec_Ptr_t * vNodes, Vec_Ptr_t ** pvPointers )
+{
+ Vec_Ptr_t * vNodesPo;
+ Aig_Obj_t * pObj, * pPointer;
+ int i;
+ vNodesPo = Vec_PtrAlloc( 1000 );
+ if ( pvPointers )
+ *pvPointers = Vec_PtrAlloc( 1000 );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ if ( (pPointer = Saig_ObjHasUnlabeledFanout(p, pObj)) )
+ {
+ Vec_PtrPush( vNodesPo, pObj );
+ if ( pvPointers )
+ Vec_PtrPush( *pvPointers, pPointer );
+ }
+ }
+ return vNodesPo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Extracts the window AIG from the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManWindowExtractNodes( Aig_Man_t * p, Vec_Ptr_t * vNodes )
+{
+ Aig_Man_t * pNew;
+ Aig_Obj_t * pObj, * pMatch;
+ Vec_Ptr_t * vNodesPi, * vNodesPo;
+ int i, nRegCount;
+ Aig_ManCleanData( p );
+ // create the new manager
+ pNew = Aig_ManStart( Vec_PtrSize(vNodes) );
+ pNew->pName = Aig_UtilStrsav( "wnd" );
+ pNew->pSpec = NULL;
+ // map constant nodes
+ pObj = Aig_ManConst1( p );
+ pObj->pData = Aig_ManConst1( pNew );
+ // create real PIs
+ vNodesPi = Saig_ManWindowCollectPis( p, vNodes );
+ Vec_PtrForEachEntry( vNodesPi, pObj, i )
+ pObj->pData = Aig_ObjCreatePi(pNew);
+ Vec_PtrFree( vNodesPi );
+ // create register outputs
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ if ( Saig_ObjIsLo(p, pObj) )
+ pObj->pData = Aig_ObjCreatePi(pNew);
+ }
+ // create internal nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ if ( Aig_ObjIsNode(pObj) )
+ pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ }
+ // create POs
+ vNodesPo = Saig_ManWindowCollectPos( p, vNodes, NULL );
+ Vec_PtrForEachEntry( vNodesPo, pObj, i )
+ Aig_ObjCreatePo( pNew, pObj->pData );
+ Vec_PtrFree( vNodesPo );
+ // create register inputs
+ nRegCount = 0;
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ if ( Saig_ObjIsLo(p, pObj) )
+ {
+ pMatch = Saig_ObjLoToLi( p, pObj );
+ Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) );
+ nRegCount++;
+ }
+ }
+ Aig_ManSetRegNum( pNew, nRegCount );
+ Aig_ManCleanup( pNew );
+ return pNew;
+}
+
+static void Saig_ManWindowInsertSmall_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjSmall,
+ Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode );
+
+/**Function*************************************************************
+
+ Synopsis [Adds nodes for the big manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_ManWindowInsertBig_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjBig,
+ Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode )
+{
+ Aig_Obj_t * pMatch;
+ if ( pObjBig->pData )
+ return;
+ if ( (pMatch = Vec_PtrEntry( vBigNode2SmallPo, pObjBig->Id )) )
+ {
+ Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pMatch), vBigNode2SmallPo, vSmallPi2BigNode );
+ pObjBig->pData = Aig_ObjChild0Copy(pMatch);
+ return;
+ }
+ assert( Aig_ObjIsNode(pObjBig) );
+ Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin0(pObjBig), vBigNode2SmallPo, vSmallPi2BigNode );
+ Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin1(pObjBig), vBigNode2SmallPo, vSmallPi2BigNode );
+ pObjBig->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObjBig), Aig_ObjChild1Copy(pObjBig) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds nodes for the small manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_ManWindowInsertSmall_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjSmall,
+ Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode )
+{
+ Aig_Obj_t * pMatch;
+ if ( pObjSmall->pData )
+ return;
+ if ( (pMatch = Vec_PtrEntry( vSmallPi2BigNode, pObjSmall->Id )) )
+ {
+ Saig_ManWindowInsertBig_rec( pNew, pMatch, vBigNode2SmallPo, vSmallPi2BigNode );
+ pObjSmall->pData = pMatch->pData;
+ return;
+ }
+ assert( Aig_ObjIsNode(pObjSmall) );
+ Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pObjSmall), vBigNode2SmallPo, vSmallPi2BigNode );
+ Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin1(pObjSmall), vBigNode2SmallPo, vSmallPi2BigNode );
+ pObjSmall->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObjSmall), Aig_ObjChild1Copy(pObjSmall) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Extracts the network from the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManWindowInsertNodes( Aig_Man_t * p, Vec_Ptr_t * vNodes, Aig_Man_t * pWnd )
+{
+ Aig_Man_t * pNew;
+ Vec_Ptr_t * vBigNode2SmallPo, * vSmallPi2BigNode;
+ Vec_Ptr_t * vNodesPi, * vNodesPo;
+ Aig_Obj_t * pObj;
+ int i;
+
+ // set mapping of small PIs into big nodes
+ vSmallPi2BigNode = Vec_PtrStart( Aig_ManObjNumMax(pWnd) );
+ vNodesPi = Saig_ManWindowCollectPis( p, vNodes );
+ Vec_PtrForEachEntry( vNodesPi, pObj, i )
+ Vec_PtrWriteEntry( vSmallPi2BigNode, Aig_ManPi(pWnd, i)->Id, pObj );
+ assert( i == Saig_ManPiNum(pWnd) );
+ Vec_PtrFree( vNodesPi );
+
+ // set mapping of big nodes into small POs
+ vBigNode2SmallPo = Vec_PtrStart( Aig_ManObjNumMax(p) );
+ vNodesPo = Saig_ManWindowCollectPos( p, vNodes, NULL );
+ Vec_PtrForEachEntry( vNodesPo, pObj, i )
+ Vec_PtrWriteEntry( vBigNode2SmallPo, pObj->Id, Aig_ManPo(pWnd, i) );
+ assert( i == Saig_ManPoNum(pWnd) );
+ Vec_PtrFree( vNodesPo );
+
+ // create the new manager
+ Aig_ManCleanData( p );
+ Aig_ManCleanData( pWnd );
+ pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+ pNew->pName = Aig_UtilStrsav( p->pName );
+ pNew->pSpec = Aig_UtilStrsav( p->pSpec );
+ // map constant nodes
+ pObj = Aig_ManConst1( p );
+ pObj->pData = Aig_ManConst1( pNew );
+ pObj = Aig_ManConst1( pWnd );
+ pObj->pData = Aig_ManConst1( pNew );
+
+ // create real PIs
+ Aig_ManForEachPi( p, pObj, i )
+ if ( Saig_ObjIsPi(p, pObj) || !Aig_ObjIsTravIdCurrent(p, pObj) )
+ pObj->pData = Aig_ObjCreatePi(pNew);
+ // create additional latch outputs
+ Saig_ManForEachLo( pWnd, pObj, i )
+ pObj->pData = Aig_ObjCreatePi(pNew);
+
+ // create internal nodes starting from the big
+ Aig_ManForEachPo( p, pObj, i )
+ if ( Saig_ObjIsPo(p, pObj) || !Aig_ObjIsTravIdCurrent(p, pObj) )
+ {
+ Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin0(pObj), vBigNode2SmallPo, vSmallPi2BigNode );
+ pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
+ }
+ // create internal nodes starting from the small
+ Saig_ManForEachLi( pWnd, pObj, i )
+ {
+ Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pObj), vBigNode2SmallPo, vSmallPi2BigNode );
+ pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
+ }
+ Vec_PtrFree( vBigNode2SmallPo );
+ Vec_PtrFree( vSmallPi2BigNode );
+ // set the new number of registers
+ assert( Aig_ManPiNum(pNew) - Aig_ManPiNum(p) == Aig_ManPoNum(pNew) - Aig_ManPoNum(p) );
+ Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) + (Aig_ManPiNum(pNew) - Aig_ManPiNum(p)) );
+ Aig_ManCleanup( pNew );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find a good object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Saig_ManFindPivot( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter;
+ if ( Aig_ManRegNum(p) > 0 )
+ {
+ if ( Aig_ManRegNum(p) == 1 )
+ return Saig_ManLo( p, 0 );
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ if ( i == Aig_ManRegNum(p)/2 )
+ return pObj;
+ }
+ }
+ else
+ {
+ Counter = 0;
+ assert( Aig_ManNodeNum(p) > 1 );
+ Aig_ManForEachNode( p, pObj, i )
+ {
+ if ( Counter++ == Aig_ManNodeNum(p)/2 )
+ return pObj;
+ }
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes sequential window of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManWindowExtract( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist )
+{
+ Aig_Man_t * pWnd;
+ Vec_Ptr_t * vNodes;
+ Aig_ManFanoutStart( p );
+ vNodes = Saig_ManWindowOutline( p, pObj, nDist );
+ pWnd = Saig_ManWindowExtractNodes( p, vNodes );
+ Vec_PtrFree( vNodes );
+ Aig_ManFanoutStop( p );
+ return pWnd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes sequential window of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManWindowInsert( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Aig_Man_t * pWnd )
+{
+ Aig_Man_t * pNew, * pWndTest;
+ Vec_Ptr_t * vNodes;
+ Aig_ManFanoutStart( p );
+
+ vNodes = Saig_ManWindowOutline( p, pObj, nDist );
+ pWndTest = Saig_ManWindowExtractNodes( p, vNodes );
+ if ( Saig_ManPiNum(pWndTest) != Saig_ManPiNum(pWnd) ||
+ Saig_ManPoNum(pWndTest) != Saig_ManPoNum(pWnd) )
+ {
+ printf( "The window cannot be reinserted because PI/PO counts do not match.\n" );
+ Aig_ManStop( pWndTest );
+ Vec_PtrFree( vNodes );
+ Aig_ManFanoutStop( p );
+ return NULL;
+ }
+ Aig_ManStop( pWndTest );
+ Vec_PtrFree( vNodes );
+
+ // insert the nodes
+ Aig_ManCleanData( p );
+ vNodes = Saig_ManWindowOutline( p, pObj, nDist );
+ pNew = Saig_ManWindowInsertNodes( p, vNodes, pWnd );
+ Vec_PtrFree( vNodes );
+ Aig_ManFanoutStop( p );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tests the above computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManWindowTest( Aig_Man_t * p )
+{
+ int nDist = 3;
+ Aig_Man_t * pWnd, * pNew;
+ Aig_Obj_t * pPivot;
+ pPivot = Saig_ManFindPivot( p );
+ assert( pPivot != NULL );
+ pWnd = Saig_ManWindowExtract( p, pPivot, nDist );
+ pNew = Saig_ManWindowInsert( p, pPivot, nDist, pWnd );
+ Aig_ManStop( pWnd );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the nodes that are not linked to each other.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Saig_ManCollectedDiffNodes( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj0, * pObj1;
+ int i;
+ // collect nodes that are not linked
+ Aig_ManIncrementTravId( p0 );
+ vNodes = Vec_PtrAlloc( 1000 );
+ Aig_ManForEachObj( p0, pObj0, i )
+ {
+ pObj1 = Aig_ObjRepr( p0, pObj0 );
+ if ( pObj1 != NULL )
+ {
+ assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );
+ continue;
+ }
+ // mark and collect unmatched objects
+ Aig_ObjSetTravIdCurrent( p0, pObj0 );
+ if ( Aig_ObjIsNode(pObj0) || Aig_ObjIsPi(pObj0) )
+ Vec_PtrPush( vNodes, pObj0 );
+ }
+ // make sure LI/LO are labeled/unlabeled mutually
+ Saig_ManForEachLiLo( p0, pObj0, pObj1, i )
+ assert( Aig_ObjIsTravIdCurrent(p0, pObj0) ==
+ Aig_ObjIsTravIdCurrent(p0, pObj1) );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates PIs of the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_ManWindowCreatePis( Aig_Man_t * pNew, Aig_Man_t * p0, Aig_Man_t * p1, Vec_Ptr_t * vNodes0 )
+{
+ Aig_Obj_t * pObj, * pMatch, * pFanin;
+ int i, Counter = 0;
+ Vec_PtrForEachEntry( vNodes0, pObj, i )
+ {
+ if ( Saig_ObjIsLo(p0, pObj) )
+ {
+ pMatch = Saig_ObjLoToLi( p0, pObj );
+ pFanin = Aig_ObjFanin0(pMatch);
+ if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL )
+ {
+ pFanin->pData = Aig_ObjCreatePi(pNew);
+ pMatch = Aig_ObjRepr( p0, pFanin );
+ assert( pFanin == Aig_ObjRepr( p1, pMatch ) );
+ assert( pMatch != NULL );
+ pMatch->pData = pFanin->pData;
+ Counter++;
+ }
+ }
+ else
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ pFanin = Aig_ObjFanin0(pObj);
+ if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL )
+ {
+ pFanin->pData = Aig_ObjCreatePi(pNew);
+ pMatch = Aig_ObjRepr( p0, pFanin );
+ assert( pFanin == Aig_ObjRepr( p1, pMatch ) );
+ assert( pMatch != NULL );
+ pMatch->pData = pFanin->pData;
+ Counter++;
+ }
+ pFanin = Aig_ObjFanin1(pObj);
+ if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL )
+ {
+ pFanin->pData = Aig_ObjCreatePi(pNew);
+ pMatch = Aig_ObjRepr( p0, pFanin );
+ assert( pFanin == Aig_ObjRepr( p1, pMatch ) );
+ assert( pMatch != NULL );
+ pMatch->pData = pFanin->pData;
+ Counter++;
+ }
+ }
+ }
+// printf( "Added %d primary inputs.\n", Counter );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates POs of the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Saig_ManWindowCreatePos( Aig_Man_t * pNew, Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Aig_Obj_t * pObj0, * pObj1, * pMiter;
+ Aig_Obj_t * pFanin0, * pFanin1;
+ int i;
+ Aig_ManForEachObj( p0, pObj0, i )
+ {
+ if ( Aig_ObjIsTravIdCurrent(p0, pObj0) )
+ continue;
+ if ( Aig_ObjIsConst1(pObj0) )
+ continue;
+ if ( Aig_ObjIsPi(pObj0) )
+ continue;
+ pObj1 = Aig_ObjRepr( p0, pObj0 );
+ assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) );
+ if ( Aig_ObjIsPo(pObj0) )
+ {
+ pFanin0 = Aig_ObjFanin0(pObj0);
+ pFanin1 = Aig_ObjFanin0(pObj1);
+ assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) ==
+ Aig_ObjIsTravIdCurrent(p1, pFanin1) );
+ if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) )
+ {
+ pMiter = Aig_Exor( pNew, pFanin0->pData, pFanin1->pData );
+ Aig_ObjCreatePo( pNew, pMiter );
+ }
+ }
+ else
+ {
+ assert( Aig_ObjIsNode(pObj0) );
+
+ pFanin0 = Aig_ObjFanin0(pObj0);
+ pFanin1 = Aig_ObjFanin0(pObj1);
+ assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) ==
+ Aig_ObjIsTravIdCurrent(p1, pFanin1) );
+ if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) )
+ {
+ pMiter = Aig_Exor( pNew, pFanin0->pData, pFanin1->pData );
+ Aig_ObjCreatePo( pNew, pMiter );
+ }
+
+ pFanin0 = Aig_ObjFanin1(pObj0);
+ pFanin1 = Aig_ObjFanin1(pObj1);
+ assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) ==
+ Aig_ObjIsTravIdCurrent(p1, pFanin1) );
+ if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) )
+ {
+ pMiter = Aig_Exor( pNew, pFanin0->pData, pFanin1->pData );
+ Aig_ObjCreatePo( pNew, pMiter );
+ }
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Extracts the window AIG from the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Saig_ManWindowExtractMiter( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Aig_Man_t * pNew;
+ Aig_Obj_t * pObj0, * pObj1, * pMatch0, * pMatch1;
+ Vec_Ptr_t * vNodes0, * vNodes1;
+ int i, nRegCount;
+ // add matching of POs and LIs
+ Saig_ManForEachPo( p0, pObj0, i )
+ {
+ pObj1 = Aig_ManPo( p1, i );
+ Aig_ObjSetRepr( p0, pObj0, pObj1 );
+ Aig_ObjSetRepr( p1, pObj1, pObj0 );
+ }
+ Saig_ManForEachLi( p0, pObj0, i )
+ {
+ pMatch0 = Saig_ObjLiToLo( p0, pObj0 );
+ pMatch1 = Aig_ObjRepr( p0, pMatch0 );
+ if ( pMatch1 == NULL )
+ continue;
+ assert( pMatch0 == Aig_ObjRepr( p1, pMatch1 ) );
+ pObj1 = Saig_ObjLoToLi( p1, pMatch1 );
+ Aig_ObjSetRepr( p0, pObj0, pObj1 );
+ Aig_ObjSetRepr( p1, pObj1, pObj0 );
+ }
+ // clean the markings
+ Aig_ManCleanData( p0 );
+ Aig_ManCleanData( p1 );
+ // collect nodes that are not linked
+ vNodes0 = Saig_ManCollectedDiffNodes( p0, p1 );
+ vNodes1 = Saig_ManCollectedDiffNodes( p1, p0 );
+ // create the new manager
+ pNew = Aig_ManStart( Vec_PtrSize(vNodes0) + Vec_PtrSize(vNodes1) );
+ pNew->pName = Aig_UtilStrsav( "wnd" );
+ pNew->pSpec = NULL;
+ // map constant nodes
+ pObj0 = Aig_ManConst1( p0 );
+ pObj0->pData = Aig_ManConst1( pNew );
+ pObj1 = Aig_ManConst1( p1 );
+ pObj1->pData = Aig_ManConst1( pNew );
+ // create real PIs
+ Saig_ManWindowCreatePis( pNew, p0, p1, vNodes0 );
+ Saig_ManWindowCreatePis( pNew, p1, p0, vNodes1 );
+ // create register outputs
+ Vec_PtrForEachEntry( vNodes0, pObj0, i )
+ {
+ if ( Saig_ObjIsLo(p0, pObj0) )
+ pObj0->pData = Aig_ObjCreatePi(pNew);
+ }
+ Vec_PtrForEachEntry( vNodes1, pObj1, i )
+ {
+ if ( Saig_ObjIsLo(p1, pObj1) )
+ pObj1->pData = Aig_ObjCreatePi(pNew);
+ }
+ // create internal nodes
+ Vec_PtrForEachEntry( vNodes0, pObj0, i )
+ {
+ if ( Aig_ObjIsNode(pObj0) )
+ pObj0->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj0), Aig_ObjChild1Copy(pObj0) );
+ }
+ Vec_PtrForEachEntry( vNodes1, pObj1, i )
+ {
+ if ( Aig_ObjIsNode(pObj1) )
+ pObj1->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj1), Aig_ObjChild1Copy(pObj1) );
+ }
+ // create POs
+ Saig_ManWindowCreatePos( pNew, p0, p1 );
+// Saig_ManWindowCreatePos( pNew, p1, p0 );
+ // create register inputs
+ nRegCount = 0;
+ Vec_PtrForEachEntry( vNodes0, pObj0, i )
+ {
+ if ( Saig_ObjIsLo(p0, pObj0) )
+ {
+ pMatch0 = Saig_ObjLoToLi( p0, pObj0 );
+ Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch0) );
+ nRegCount++;
+ }
+ }
+ Vec_PtrForEachEntry( vNodes1, pObj1, i )
+ {
+ if ( Saig_ObjIsLo(p1, pObj1) )
+ {
+ pMatch1 = Saig_ObjLoToLi( p1, pObj1 );
+ Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch1) );
+ nRegCount++;
+ }
+ }
+ Aig_ManSetRegNum( pNew, nRegCount );
+ Aig_ManCleanup( pNew );
+ return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/aig/ssw/ssw.h b/src/aig/ssw/ssw.h
index 5d70812d..b3222fca 100644
--- a/src/aig/ssw/ssw.h
+++ b/src/aig/ssw/ssw.h
@@ -51,11 +51,16 @@ struct Ssw_Pars_t_
int nBTLimitGlobal;// conflict limit for multiple runs
int nMinDomSize; // min clock domain considered for optimization
int nItersStop; // stop after the given number of iterations
+ int fDumpSRInit; // dumps speculative reduction
+ int nResimDelta; // the number of nodes to resimulate
int fPolarFlip; // uses polarity adjustment
int fLatchCorr; // perform register correspondence
int fSemiFormal; // enable semiformal filtering
int fUniqueness; // enable uniqueness constraints
int fDynamic; // enable dynamic addition of constraints
+ int fLocalSim; // enable local simulation simulation
+ int fPartSigCorr; // uses partial signal correspondence
+ int nIsleDist; // extends islands by the given distance
int fVerbose; // verbose stats
int fFlopVerbose; // verbose printout of redundant flops
// optimized latch correspondence
@@ -82,6 +87,8 @@ struct Ssw_Cex_t_
unsigned pData[0]; // the cex bit data (the number of bits: nRegs + (iFrame+1) * nPis)
};
+typedef struct Ssw_Sml_t_ Ssw_Sml_t; // sequential simulation manager
+
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -97,8 +104,11 @@ extern void Ssw_ManSetDefaultParams( Ssw_Pars_t * p );
extern void Ssw_ManSetDefaultParamsLcorr( Ssw_Pars_t * p );
extern Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars );
extern Aig_Man_t * Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars );
+/*=== sswIslands.c ==========================================================*/
+extern int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars );
+extern int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars );
/*=== sswMiter.c ===================================================*/
-extern int Ssw_SecSpecialMiter( Aig_Man_t * pMiter, int fVerbose );
+extern int Ssw_SecSpecialMiter( Aig_Man_t * p0, Aig_Man_t * p1, int nFrames, int fVerbose );
/*=== sswPart.c ==========================================================*/
extern Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars );
/*=== sswPairs.c ===================================================*/
@@ -107,6 +117,14 @@ extern int Ssw_SecWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec
extern int Ssw_SecGeneral( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Ssw_Pars_t * pPars );
extern int Ssw_SecGeneralMiter( Aig_Man_t * pMiter, Ssw_Pars_t * pPars );
/*=== sswSim.c ===================================================*/
+extern Ssw_Sml_t * Ssw_SmlSimulateComb( Aig_Man_t * pAig, int nWords );
+extern Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords );
+extern void Ssw_SmlUnnormalize( Ssw_Sml_t * p );
+extern void Ssw_SmlStop( Ssw_Sml_t * p );
+extern int Ssw_SmlNumFrames( Ssw_Sml_t * p );
+extern int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p );
+extern unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj );
+extern int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 );
extern Ssw_Cex_t * Ssw_SmlAllocCounterExample( int nRegs, int nRealPis, int nFrames );
extern void Ssw_SmlFreeCounterExample( Ssw_Cex_t * pCex );
extern int Ssw_SmlRunCounterExample( Aig_Man_t * pAig, Ssw_Cex_t * p );
diff --git a/src/aig/ssw/sswAig.c b/src/aig/ssw/sswAig.c
index fda05941..97f0a755 100644
--- a/src/aig/ssw/sswAig.c
+++ b/src/aig/ssw/sswAig.c
@@ -211,6 +211,7 @@ Aig_Man_t * Ssw_SpeculativeReduction( Ssw_Man_t * p )
// start the fraig package
pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFrames );
+ pFrames->pName = Aig_UtilStrsav( p->pAig->pName );
// map constants and PIs
Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), 0, Aig_ManConst1(pFrames) );
Saig_ManForEachPi( p->pAig, pObj, i )
diff --git a/src/aig/ssw/sswClass.c b/src/aig/ssw/sswClass.c
index 771fd530..3528ae27 100644
--- a/src/aig/ssw/sswClass.c
+++ b/src/aig/ssw/sswClass.c
@@ -585,7 +585,7 @@ int Ssw_ClassesPrepareRehash( Ssw_Cla_t * p, Vec_Ptr_t * vCands )
SeeAlso []
***********************************************************************/
-Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs, int fVerbose )
+Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int nMaxLevs, int fVerbose )
{
// int nFrames = 4;
// int nWords = 1;
@@ -595,7 +595,7 @@ Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs,
// int nWords = 4;
// int nIters = 0;
- int nFrames = 4;
+ int nFrames = AIG_MAX( nFramesK, 4 );
int nWords = 2;
int nIters = 16;
Ssw_Cla_t * p;
@@ -836,7 +836,7 @@ Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses )
SeeAlso []
***********************************************************************/
-Ssw_Cla_t * Ssw_ClassesFromIslands( Aig_Man_t * pMiter, Vec_Int_t * vPairs )
+Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs )
{
Ssw_Cla_t * p;
Aig_Obj_t ** ppClassNew;
diff --git a/src/aig/ssw/sswCore.c b/src/aig/ssw/sswCore.c
index 68c00a0e..38a36022 100644
--- a/src/aig/ssw/sswCore.c
+++ b/src/aig/ssw/sswCore.c
@@ -51,10 +51,13 @@ void Ssw_ManSetDefaultParams( Ssw_Pars_t * p )
p->nBTLimitGlobal = 5000000; // conflict limit for all runs
p->nMinDomSize = 100; // min clock domain considered for optimization
p->nItersStop = 0; // stop after the given number of iterations
+ p->nResimDelta = 1000; // the internal of nodes to resimulate
p->fPolarFlip = 0; // uses polarity adjustment
p->fLatchCorr = 0; // performs register correspondence
p->fSemiFormal = 0; // enable semiformal filtering
p->fUniqueness = 0; // enable uniqueness constraints
+ p->fDynamic = 0; // dynamic partitioning
+ p->fLocalSim = 0; // local simulation
p->fVerbose = 0; // verbose stats
// latch correspondence
p->fLatchCorrOpt = 0; // performs optimized register correspondence
@@ -260,6 +263,9 @@ Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars )
if ( pPars->fLatchCorrOpt )
{
pPars->fLatchCorr = 1;
+ pPars->nFramesAddSim = 0;
+ if ( (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0) )
+ return Ssw_SignalCorrespondencePart( pAig, pPars );
}
else
{
@@ -276,7 +282,7 @@ Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars )
if ( p->pPars->nConstrs == 0 )
{
// perform one round of seq simulation and generate candidate equivalence classes
- p->ppClasses = Ssw_ClassesPrepare( pAig, pPars->fLatchCorr, pPars->nMaxLevs, pPars->fVerbose );
+ p->ppClasses = Ssw_ClassesPrepare( pAig, pPars->nFramesK, pPars->fLatchCorr, pPars->nMaxLevs, pPars->fVerbose );
// p->ppClasses = Ssw_ClassesPrepareTargets( pAig );
if ( pPars->fLatchCorrOpt )
p->pSml = Ssw_SmlStart( pAig, 0, 2, 1 );
@@ -292,6 +298,8 @@ Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars )
p->ppClasses = Ssw_ClassesPrepareSimple( pAig, pPars->fLatchCorr, pPars->nMaxLevs );
Ssw_ClassesSetData( p->ppClasses, NULL, NULL, Ssw_SmlObjIsConstBit, Ssw_SmlObjsAreEqualBit );
}
+ if ( p->pPars->fLocalSim )
+ p->pVisited = CALLOC( int, Ssw_SmlNumFrames( p->pSml ) * Aig_ManObjNumMax(p->pAig) );
// perform refinement of classes
pAigNew = Ssw_SignalCorrespondenceRefine( p );
if ( pPars->fUniqueness )
diff --git a/src/aig/ssw/sswDyn.c b/src/aig/ssw/sswDyn.c
index d5559408..d9ac07a9 100644
--- a/src/aig/ssw/sswDyn.c
+++ b/src/aig/ssw/sswDyn.c
@@ -279,6 +279,83 @@ p->timeSimSat += clock() - clk;
/**Function*************************************************************
+ Synopsis [Performs one round of simulation with counter-examples.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepResimulateDynLocal( Ssw_Man_t * p, int f )
+{
+ Aig_Obj_t * pObj, * pRepr, ** ppClass;
+ int i, k, nSize, RetValue1, RetValue2, clk = clock();
+ p->nSimRounds++;
+ // transfer PI simulation information from storage
+// Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords );
+ Ssw_ManSweepTransferDyn( p );
+ // determine const1 cands and classes to be simulated
+ Vec_PtrClear( p->vResimConsts );
+ Vec_PtrClear( p->vResimClasses );
+ Aig_ManIncrementTravId( p->pAig );
+ for ( i = p->iNodeStart; i < p->iNodeLast + p->pPars->nResimDelta; i++ )
+ {
+ if ( i >= Aig_ManObjNumMax( p->pAig ) )
+ break;
+ pObj = Aig_ManObj( p->pAig, i );
+ if ( pObj == NULL )
+ continue;
+ if ( Ssw_ObjIsConst1Cand(p->pAig, pObj) )
+ {
+ Vec_PtrPush( p->vResimConsts, pObj );
+ continue;
+ }
+ pRepr = Aig_ObjRepr(p->pAig, pObj);
+ if ( pRepr == NULL )
+ continue;
+ if ( Aig_ObjIsTravIdCurrent(p->pAig, pRepr) )
+ continue;
+ Aig_ObjSetTravIdCurrent(p->pAig, pRepr);
+ Vec_PtrPush( p->vResimClasses, pRepr );
+ }
+ // simulate internal nodes
+// Ssw_SmlSimulateOneFrame( p->pSml );
+// Ssw_SmlSimulateOne( p->pSml );
+ // resimulate dynamically
+// Aig_ManIncrementTravId( p->pAig );
+// Aig_ObjIsTravIdCurrent( p->pAig, Aig_ManConst1(p->pAig) );
+ p->nVisCounter++;
+ Vec_PtrForEachEntry( p->vResimConsts, pObj, i )
+ Ssw_SmlSimulateOneDyn_rec( p->pSml, pObj, p->nFrames-1, p->pVisited, p->nVisCounter );
+ // resimulate the cone of influence of the cand classes
+ Vec_PtrForEachEntry( p->vResimClasses, pRepr, i )
+ {
+ ppClass = Ssw_ClassesReadClass( p->ppClasses, pRepr, &nSize );
+ for ( k = 0; k < nSize; k++ )
+ Ssw_SmlSimulateOneDyn_rec( p->pSml, ppClass[k], p->nFrames-1, p->pVisited, p->nVisCounter );
+ }
+
+ // check equivalence classes
+// RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 );
+// RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 );
+ // refine these nodes
+ RetValue1 = Ssw_ClassesRefineConst1Group( p->ppClasses, p->vResimConsts, 1 );
+ RetValue2 = 0;
+ Vec_PtrForEachEntry( p->vResimClasses, pRepr, i )
+ RetValue2 += Ssw_ClassesRefineOneClass( p->ppClasses, pRepr, 1 );
+
+ // prepare simulation info for the next round
+ Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 );
+ p->nPatterns = 0;
+ p->nSimRounds++;
+p->timeSimSat += clock() - clk;
+ return RetValue1 > 0 || RetValue2 > 0;
+}
+
+/**Function*************************************************************
+
Synopsis [Performs fraiging for the internal nodes.]
Description []
@@ -321,8 +398,11 @@ p->timeReduce += clock() - clk;
Ssw_ClassesClearRefined( p->ppClasses );
if ( p->pPars->fVerbose )
pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) );
+ p->iNodeStart = 0;
Aig_ManForEachObj( p->pAig, pObj, i )
{
+ if ( p->iNodeStart == 0 )
+ p->iNodeStart = i;
if ( p->pPars->fVerbose )
Bar_ProgressUpdate( pProgress, i, NULL );
if ( Saig_ObjIsLo(p->pAig, pObj) )
@@ -341,7 +421,14 @@ p->timeReduce += clock() - clk;
{
// resimulate
if ( p->nPatterns > 0 )
- Ssw_ManSweepResimulateDyn( p, f );
+ {
+ p->iNodeLast = i;
+ if ( p->pPars->fLocalSim )
+ Ssw_ManSweepResimulateDynLocal( p, f );
+ else
+ Ssw_ManSweepResimulateDyn( p, f );
+ p->iNodeStart = i+1;
+ }
// printf( "Recycling SAT solver with %d vars and %d calls.\n",
// p->pMSat->nSatVars, p->nRecycleCalls );
// Aig_ManCleanMarkAB( p->pAig );
@@ -363,11 +450,24 @@ p->timeReduce += clock() - clk;
}
// resimulate
if ( p->nPatterns == 32 )
- Ssw_ManSweepResimulateDyn( p, f );
+ {
+ p->iNodeLast = i;
+ if ( p->pPars->fLocalSim )
+ Ssw_ManSweepResimulateDynLocal( p, f );
+ else
+ Ssw_ManSweepResimulateDyn( p, f );
+ p->iNodeStart = i+1;
+ }
}
// resimulate
if ( p->nPatterns > 0 )
- Ssw_ManSweepResimulateDyn( p, f );
+ {
+ p->iNodeLast = i;
+ if ( p->pPars->fLocalSim )
+ Ssw_ManSweepResimulateDynLocal( p, f );
+ else
+ Ssw_ManSweepResimulateDyn( p, f );
+ }
// collect stats
if ( p->pPars->fVerbose )
Bar_ProgressStop( pProgress );
diff --git a/src/aig/ssw/sswInt.h b/src/aig/ssw/sswInt.h
index 90c1367f..930796fc 100644
--- a/src/aig/ssw/sswInt.h
+++ b/src/aig/ssw/sswInt.h
@@ -45,7 +45,6 @@ typedef struct Ssw_Man_t_ Ssw_Man_t; // signal correspondence manager
typedef struct Ssw_Frm_t_ Ssw_Frm_t; // unrolled frames manager
typedef struct Ssw_Sat_t_ Ssw_Sat_t; // SAT solver manager
typedef struct Ssw_Cla_t_ Ssw_Cla_t; // equivalence classe manager
-typedef struct Ssw_Sml_t_ Ssw_Sml_t; // sequential simulation manager
struct Ssw_Man_t_
{
@@ -86,8 +85,14 @@ struct Ssw_Man_t_
int nSRMiterMaxId; // max ID after which the last frame begins
Vec_Ptr_t * vNewLos; // new time frame LOs of to constrain
Vec_Int_t * vNewPos; // new time frame POs of to add constraints
- // sequential simulator
- Ssw_Sml_t * pSml;
+ int * pVisited; // flags to label visited nodes in each frame
+ int nVisCounter; // the traversal ID
+ // sequential simulation
+ Ssw_Sml_t * pSml; // the simulator
+ int iNodeStart; // the first node considered
+ int iNodeLast; // the last node considered
+ Vec_Ptr_t * vResimConsts; // resimulation constants
+ Vec_Ptr_t * vResimClasses; // resimulation classes
// counter example storage
int nPatWords; // the number of words in the counter example
unsigned * pPatWords; // the counter example
@@ -201,11 +206,11 @@ extern void Ssw_ClassesCollectClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr,
extern void Ssw_ClassesCheck( Ssw_Cla_t * p );
extern void Ssw_ClassesPrint( Ssw_Cla_t * p, int fVeryVerbose );
extern void Ssw_ClassesRemoveNode( Ssw_Cla_t * p, Aig_Obj_t * pObj );
-extern Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs, int fVerbose );
+extern Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int nMaxLevs, int fVerbose );
extern Ssw_Cla_t * Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs );
extern Ssw_Cla_t * Ssw_ClassesPrepareTargets( Aig_Man_t * pAig );
extern Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses );
-extern Ssw_Cla_t * Ssw_ClassesFromIslands( Aig_Man_t * pMiter, Vec_Int_t * vPairs );
+extern Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs );
extern int Ssw_ClassesRefine( Ssw_Cla_t * p, int fRecursive );
extern int Ssw_ClassesRefineOneClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int fRecursive );
extern int Ssw_ClassesRefineConst1Group( Ssw_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive );
@@ -242,13 +247,12 @@ extern void Ssw_SmlAssignRandomFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj,
extern Ssw_Sml_t * Ssw_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame );
extern void Ssw_SmlClean( Ssw_Sml_t * p );
extern void Ssw_SmlStop( Ssw_Sml_t * p );
-extern int Ssw_SmlNumFrames( Ssw_Sml_t * p );
extern void Ssw_SmlObjAssignConst( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame );
extern void Ssw_SmlObjSetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, unsigned Word, int iWord, int iFrame );
extern void Ssw_SmlAssignDist1Plus( Ssw_Sml_t * p, unsigned * pPat );
extern void Ssw_SmlSimulateOne( Ssw_Sml_t * p );
extern void Ssw_SmlSimulateOneFrame( Ssw_Sml_t * p );
-extern Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords );
+extern void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter );
extern void Ssw_SmlResimulateSeq( Ssw_Sml_t * p );
/*=== sswSimSat.c ===================================================*/
extern void Ssw_ManResimulateBit( Ssw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr );
diff --git a/src/aig/ssw/sswIslands.c b/src/aig/ssw/sswIslands.c
index 5a5783f7..64515f3e 100644
--- a/src/aig/ssw/sswIslands.c
+++ b/src/aig/ssw/sswIslands.c
@@ -24,9 +24,6 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static inline Aig_Obj_t * Aig_ObjChild0Copy2( Aig_Obj_t * pObj ) { return Aig_ObjFanin0(pObj)->pData? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj)) : NULL; }
-static inline Aig_Obj_t * Aig_ObjChild1Copy2( Aig_Obj_t * pObj ) { return Aig_ObjFanin1(pObj)->pData? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj)) : NULL; }
-
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -52,7 +49,7 @@ void Ssw_CreatePair( Vec_Int_t * vPairs, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
/**Function*************************************************************
- Synopsis [Detects islands of common logic and returns them as pairs.]
+ Synopsis [Establishes relationship between nodes using pairing.]
Description []
@@ -61,48 +58,127 @@ void Ssw_CreatePair( Vec_Int_t * vPairs, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
SeeAlso []
***********************************************************************/
-Vec_Int_t * Ssw_DetectIslands( Aig_Man_t * p0, Aig_Man_t * p1, int nCommonFlops, int fVerbose )
+void Ssw_MatchingStart( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs )
{
- Vec_Int_t * vPairs;
- Aig_Obj_t * pObj0, * pObj1, * pFanin0, * pFanin1;
+ Aig_Obj_t * pObj0, * pObj1;
int i;
- assert( Aig_ManRegNum(p0) > 0 );
- assert( Aig_ManRegNum(p1) > 0 );
- assert( Aig_ManRegNum(p0) >= nCommonFlops );
- assert( Aig_ManRegNum(p1) >= nCommonFlops );
- assert( Saig_ManPiNum(p0) == Saig_ManPiNum(p1) );
- assert( Saig_ManPoNum(p0) == Saig_ManPoNum(p1) );
+ // create matching
Aig_ManCleanData( p0 );
Aig_ManCleanData( p1 );
- // start structural equivalence
- vPairs = Vec_IntAlloc( 1000 );
- Ssw_CreatePair( vPairs, Aig_ManConst1(p0), Aig_ManConst1(p1) );
+ for ( i = 0; i < Vec_IntSize(vPairs); i += 2 )
+ {
+ pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairs, i) );
+ pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairs, i+1) );
+ assert( pObj0->pData == NULL );
+ assert( pObj1->pData == NULL );
+ pObj0->pData = pObj1;
+ pObj1->pData = pObj0;
+ }
+ // make sure constants are matched
+ pObj0 = Aig_ManConst1( p0 );
+ pObj1 = Aig_ManConst1( p1 );
+ assert( pObj0->pData == pObj1 );
+ assert( pObj1->pData == pObj0 );
+ // make sure PIs are matched
Saig_ManForEachPi( p0, pObj0, i )
- Ssw_CreatePair( vPairs, pObj0, Aig_ManPi(p1, i) );
+ {
+ pObj1 = Aig_ManPi( p1, i );
+ assert( pObj0->pData == pObj1 );
+ assert( pObj1->pData == pObj0 );
+ }
+ // make sure the POs are not matched
+ Aig_ManForEachPo( p0, pObj0, i )
+ {
+ pObj1 = Aig_ManPo( p1, i );
+ assert( pObj0->pData == NULL );
+ assert( pObj1->pData == NULL );
+ }
+
+ // check that LIs/LOs are matched in sync
Saig_ManForEachLo( p0, pObj0, i )
{
- if ( i == nCommonFlops )
- break;
- Ssw_CreatePair( vPairs, pObj0, Saig_ManLo(p1, i) );
+ if ( pObj0->pData == NULL )
+ continue;
+ pObj1 = pObj0->pData;
+ if ( !Saig_ObjIsLo(p1, pObj1) )
+ printf( "Mismatch between LO pairs.\n" );
}
- // find structurally equivalent nodes
- Aig_ManForEachNode( p0, pObj0, i )
+ Saig_ManForEachLo( p1, pObj1, i )
+ {
+ if ( pObj1->pData == NULL )
+ continue;
+ pObj0 = pObj1->pData;
+ if ( !Saig_ObjIsLo(p0, pObj0) )
+ printf( "Mismatch between LO pairs.\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Establishes relationship between nodes using pairing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_MatchingExtendOne( Aig_Man_t * p, Vec_Ptr_t * vNodes )
+{
+ Aig_Obj_t * pNext, * pObj;
+ int i, k, iFan;
+ Vec_PtrClear( vNodes );
+ Aig_ManIncrementTravId( p );
+ Aig_ManForEachObj( p, pObj, i )
{
- pFanin0 = Aig_ObjChild0Copy2( pObj0 );
- pFanin1 = Aig_ObjChild1Copy2( pObj0 );
- if ( pFanin0 == NULL || pFanin1 == NULL )
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
continue;
- pObj1 = Aig_TableLookupTwo( p1, pFanin0, pFanin1 );
- if ( pObj1 == NULL )
+ if ( pObj->pData != NULL )
continue;
- Ssw_CreatePair( vPairs, pObj0, pObj1 );
+ if ( Saig_ObjIsLo(p, pObj) )
+ {
+ pNext = Saig_ObjLoToLi(p, pObj);
+ pNext = Aig_ObjFanin0(pNext);
+ if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pNext);
+ Vec_PtrPush( vNodes, pNext );
+ }
+ }
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ pNext = Aig_ObjFanin0(pObj);
+ if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pNext);
+ Vec_PtrPush( vNodes, pNext );
+ }
+ pNext = Aig_ObjFanin1(pObj);
+ if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pNext);
+ Vec_PtrPush( vNodes, pNext );
+ }
+ }
+ Aig_ObjForEachFanout( p, pObj, pNext, iFan, k )
+ {
+ if ( Saig_ObjIsPo(p, pNext) )
+ continue;
+ if ( Saig_ObjIsLi(p, pNext) )
+ pNext = Saig_ObjLiToLo(p, pNext);
+ if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pNext);
+ Vec_PtrPush( vNodes, pNext );
+ }
+ }
}
- return vPairs;
}
/**Function*************************************************************
- Synopsis [Collects additional Lis and Los.]
+ Synopsis [Establishes relationship between nodes using pairing.]
Description []
@@ -111,22 +187,24 @@ Vec_Int_t * Ssw_DetectIslands( Aig_Man_t * p0, Aig_Man_t * p1, int nCommonFlops,
SeeAlso []
***********************************************************************/
-void Ssw_CollectExtraLiLo( Aig_Man_t * p, int nCommonFlops, Vec_Ptr_t * vLis, Vec_Ptr_t * vLos )
+int Ssw_MatchingCountUnmached( Aig_Man_t * p )
{
- Aig_Obj_t * pObjLo, * pObjLi;
- int i;
- Saig_ManForEachLiLo( p, pObjLo, pObjLi, i )
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Aig_ManForEachObj( p, pObj, i )
{
- if ( i < nCommonFlops )
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ if ( pObj->pData != NULL )
continue;
- Vec_PtrPush( vLis, pObjLi );
- Vec_PtrPush( vLos, pObjLo );
+ Counter++;
}
+ return Counter;
}
/**Function*************************************************************
- Synopsis [Overlays and extends the pairs.]
+ Synopsis [Establishes relationship between nodes using pairing.]
Description []
@@ -135,80 +213,195 @@ void Ssw_CollectExtraLiLo( Aig_Man_t * p, int nCommonFlops, Vec_Ptr_t * vLis, Ve
SeeAlso []
***********************************************************************/
-void Ssw_OverlayIslands( Aig_Man_t * pTo, Aig_Man_t * pFrom, Vec_Ptr_t * vLisFrom, Vec_Ptr_t * vLosFrom, Vec_Int_t * vPairs, int nCommonFlops, int fToGoesFirst )
+void Ssw_MatchingExtend( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose )
{
- Aig_Obj_t * pObjFrom, * pObjTo, * pFanin0To, * pFanin1To;
- int i;
- // create additional register outputs of From in To
- Vec_PtrForEachEntry( vLosFrom, pObjFrom, i )
+ Vec_Ptr_t * vNodes0, * vNodes1;
+ Aig_Obj_t * pNext0, * pNext1;
+ int d, k;
+ Aig_ManFanoutStart(p0);
+ Aig_ManFanoutStart(p1);
+ vNodes0 = Vec_PtrAlloc( 1000 );
+ vNodes1 = Vec_PtrAlloc( 1000 );
+ if ( fVerbose )
{
- pObjTo = Aig_ObjCreatePi( pTo );
- if( fToGoesFirst )
- Ssw_CreatePair( vPairs, pObjTo, pObjFrom );
- else
- Ssw_CreatePair( vPairs, pObjFrom, pObjTo );
+ int nUnmached = Ssw_MatchingCountUnmached(p0);
+ printf( "Extending islands by %d steps:\n", nDist );
+ printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n",
+ 0, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0),
+ nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) );
}
- // create additional nodes of From in To
- Aig_ManForEachNode( pFrom, pObjFrom, i )
+ for ( d = 0; d < nDist; d++ )
{
- if ( pObjFrom->pData != NULL )
+ Ssw_MatchingExtendOne( p0, vNodes0 );
+ Ssw_MatchingExtendOne( p1, vNodes1 );
+ Vec_PtrForEachEntry( vNodes0, pNext0, k )
+ {
+ pNext1 = pNext0->pData;
+ if ( pNext1 == NULL )
+ continue;
+ assert( pNext1->pData == pNext0 );
+ if ( Saig_ObjIsPi(p0, pNext1) )
+ continue;
+ pNext0->pData = NULL;
+ pNext1->pData = NULL;
+ }
+ Vec_PtrForEachEntry( vNodes1, pNext0, k )
+ {
+ pNext1 = pNext0->pData;
+ if ( pNext1 == NULL )
+ continue;
+ assert( pNext1->pData == pNext0 );
+ if ( Saig_ObjIsPi(p1, pNext1) )
+ continue;
+ pNext0->pData = NULL;
+ pNext1->pData = NULL;
+ }
+ if ( fVerbose )
+ {
+ int nUnmached = Ssw_MatchingCountUnmached(p0);
+ printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n",
+ d+1, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0),
+ nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) );
+ }
+ }
+ Vec_PtrFree( vNodes0 );
+ Vec_PtrFree( vNodes1 );
+ Aig_ManFanoutStop(p0);
+ Aig_ManFanoutStop(p1);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Used differences in p0 to complete p1.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_MatchingComplete( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Vec_Ptr_t * vNewLis;
+ Aig_Obj_t * pObj0, * pObj0Li, * pObj1;
+ int i;
+ // create register outputs in p0 that are absent in p1
+ vNewLis = Vec_PtrAlloc( 100 );
+ Saig_ManForEachLiLo( p0, pObj0Li, pObj0, i )
+ {
+ if ( pObj0->pData != NULL )
continue;
- pFanin0To = Aig_ObjChild0Copy2( pObjFrom );
- pFanin1To = Aig_ObjChild1Copy2( pObjFrom );
- assert( pFanin0To != NULL && pFanin1To != NULL );
- pObjTo = Aig_And( pTo, pFanin0To, pFanin1To );
- if( fToGoesFirst )
- Ssw_CreatePair( vPairs, pObjTo, pObjFrom );
- else
- Ssw_CreatePair( vPairs, pObjFrom, pObjTo );
+ pObj1 = Aig_ObjCreatePi( p1 );
+ pObj0->pData = pObj1;
+ pObj1->pData = pObj0;
+ Vec_PtrPush( vNewLis, pObj0Li );
}
- // finally recreate additional register inputs
- Vec_PtrForEachEntry( vLisFrom, pObjFrom, i )
+ // add missing nodes in the topological order
+ Aig_ManForEachNode( p0, pObj0, i )
{
- pFanin0To = Aig_ObjChild0Copy2( pObjFrom );
- Aig_ObjCreatePo( pTo, pFanin0To );
+ if ( pObj0->pData != NULL )
+ continue;
+ pObj1 = Aig_And( p1, Aig_ObjChild0Copy(pObj0), Aig_ObjChild1Copy(pObj0) );
+ pObj0->pData = pObj1;
+ pObj1->pData = pObj0;
}
- // update the number of registers
- Aig_ManSetRegNum( pTo, Aig_ManRegNum(pTo) + Vec_PtrSize(vLisFrom) );
+ // create register outputs in p0 that are absent in p1
+ Vec_PtrForEachEntry( vNewLis, pObj0Li, i )
+ Aig_ObjCreatePo( p1, Aig_ObjChild0Copy(pObj0Li) );
+ // increment the number of registers
+ Aig_ManSetRegNum( p1, Aig_ManRegNum(p1) + Vec_PtrSize(vNewLis) );
+ Vec_PtrFree( vNewLis );
}
+
/**Function*************************************************************
- Synopsis [Overlays and extends the pairs.]
+ Synopsis [Derives matching for all pairs.]
- Description []
+ Description [Modifies both AIGs.]
SideEffects []
SeeAlso []
***********************************************************************/
-Vec_Int_t * Saig_ManMiterWithIslands( Aig_Man_t * p0, Aig_Man_t * p1, Aig_Man_t ** ppMiter, Vec_Int_t * vPairs )
+Vec_Int_t * Ssw_MatchingPairs( Aig_Man_t * p0, Aig_Man_t * p1 )
{
- Aig_Man_t * pMiter;
Vec_Int_t * vPairsNew;
Aig_Obj_t * pObj0, * pObj1;
int i;
- vPairsNew = Vec_IntAlloc( 1000 );
- pMiter = Saig_ManCreateMiter( p0, p1, 0 );
- for ( i = 0; i < Vec_IntSize(vPairs); i += 2 )
+ // check correctness
+ assert( Aig_ManPiNum(p0) == Aig_ManPiNum(p1) );
+ assert( Aig_ManPoNum(p0) == Aig_ManPoNum(p1) );
+ assert( Aig_ManRegNum(p0) == Aig_ManRegNum(p1) );
+ assert( Aig_ManObjNum(p0) == Aig_ManObjNum(p1) );
+ // create complete pairs
+ vPairsNew = Vec_IntAlloc( 2*Aig_ManObjNum(p0) );
+ Aig_ManForEachObj( p0, pObj0, i )
{
- pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairs, i) );
- pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairs, i+1) );
+ if ( Aig_ObjIsPo(pObj0) )
+ continue;
+ pObj1 = pObj0->pData;
+ Vec_IntPush( vPairsNew, pObj0->Id );
+ Vec_IntPush( vPairsNew, pObj1->Id );
+ }
+ return vPairsNew;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the result of matching to miter.]
+
+ Description [The array of pairs should be complete.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Ssw_MatchingMiter( Aig_Man_t * pMiter, Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairsAll )
+{
+ Vec_Int_t * vPairsMiter;
+ Aig_Obj_t * pObj0, * pObj1;
+ int i;
+ // create matching of nodes in the miter
+ vPairsMiter = Vec_IntAlloc( 2*Aig_ManObjNum(p0) );
+ for ( i = 0; i < Vec_IntSize(vPairsAll); i += 2 )
+ {
+ pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairsAll, i) );
+ pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairsAll, i+1) );
+ assert( pObj0->pData != NULL );
+ assert( pObj1->pData != NULL );
+ if ( pObj0->pData == pObj1->pData )
+ continue;
+ if ( Aig_ObjIsNone(pObj0->pData) || Aig_ObjIsNone(pObj1->pData) )
+ continue;
+ // get the miter nodes
pObj0 = pObj0->pData;
pObj1 = pObj1->pData;
assert( !Aig_IsComplement(pObj0) );
assert( !Aig_IsComplement(pObj1) );
- if ( pObj0 == pObj1 )
+ assert( Aig_ObjType(pObj0) == Aig_ObjType(pObj1) );
+ if ( Aig_ObjIsPo(pObj0) )
continue;
+ assert( Aig_ObjIsNode(pObj0) || Saig_ObjIsLo(pMiter, pObj0) );
+ assert( Aig_ObjIsNode(pObj1) || Saig_ObjIsLo(pMiter, pObj1) );
assert( pObj0->Id < pObj1->Id );
- Vec_IntPush( vPairsNew, pObj0->Id );
- Vec_IntPush( vPairsNew, pObj1->Id );
+ Vec_IntPush( vPairsMiter, pObj0->Id );
+ Vec_IntPush( vPairsMiter, pObj1->Id );
}
- *ppMiter = pMiter;
- return vPairsNew;
+ return vPairsMiter;
}
+
+
+
+
/**Function*************************************************************
Synopsis [Solves SEC using structural similarity.]
@@ -220,72 +413,41 @@ Vec_Int_t * Saig_ManMiterWithIslands( Aig_Man_t * p0, Aig_Man_t * p1, Aig_Man_t
SeeAlso []
***********************************************************************/
-Aig_Man_t * Ssw_SecWithIslandsInternal( Aig_Man_t * p0, Aig_Man_t * p1, int nCommonFlops, int fVerbose, Ssw_Pars_t * pPars )
+Aig_Man_t * Ssw_SecWithSimilaritySweep( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars )
{
Ssw_Man_t * p;
- Ssw_Pars_t Pars;
- Vec_Int_t * vPairs, * vPairsMiter;
+ Vec_Int_t * vPairsAll, * vPairsMiter;
Aig_Man_t * pMiter, * pAigNew;
- Vec_Ptr_t * vLis0, * vLos0, * vLis1, * vLos1;
- int nNodes, nRegs;
- assert( Aig_ManRegNum(p0) > 0 );
- assert( Aig_ManRegNum(p1) > 0 );
- assert( Aig_ManRegNum(p0) >= nCommonFlops );
- assert( Aig_ManRegNum(p1) >= nCommonFlops );
- assert( Saig_ManPiNum(p0) == Saig_ManPiNum(p1) );
- assert( Saig_ManPoNum(p0) == Saig_ManPoNum(p1) );
- // derive pairs
- vPairs = Ssw_DetectIslands( p0, p1, nCommonFlops, fVerbose );
- if ( fVerbose )
- {
- printf( "Original managers:\n" );
- Aig_ManPrintStats( p0 );
- Aig_ManPrintStats( p1 );
- printf( "Detected %d PI pairs, %d LO pairs, and %d node pairs.\n",
- Saig_ManPiNum(p0), nCommonFlops, Vec_IntSize(vPairs)/2 - Saig_ManPiNum(p0) - nCommonFlops - 1 );
- }
- // complete the manager with islands
- vLis0 = Vec_PtrAlloc( 100 );
- vLos0 = Vec_PtrAlloc( 100 );
- vLis1 = Vec_PtrAlloc( 100 );
- vLos1 = Vec_PtrAlloc( 100 );
- Ssw_CollectExtraLiLo( p0, nCommonFlops, vLis0, vLos0 );
- Ssw_CollectExtraLiLo( p1, nCommonFlops, vLis1, vLos1 );
-
- nRegs = Saig_ManRegNum(p0);
- nNodes = Aig_ManNodeNum(p0);
- Ssw_OverlayIslands( p0, p1, vLis1, vLos1, vPairs, nCommonFlops, 1 );
- if ( fVerbose )
- printf( "Completed p0 with %d registers and %d nodes.\n",
- Saig_ManRegNum(p0) - nRegs, Aig_ManNodeNum(p0) - nNodes );
-
- nRegs = Saig_ManRegNum(p1);
- nNodes = Aig_ManNodeNum(p1);
- Ssw_OverlayIslands( p1, p0, vLis0, vLos0, vPairs, nCommonFlops, 0 );
- if ( fVerbose )
- printf( "Completed p1 with %d registers and %d nodes.\n",
- Saig_ManRegNum(p1) - nRegs, Aig_ManNodeNum(p1) - nNodes );
- if ( fVerbose )
- {
- printf( "Modified managers:\n" );
- Aig_ManPrintStats( p0 );
- Aig_ManPrintStats( p1 );
- }
-
- Vec_PtrFree( vLis0 );
- Vec_PtrFree( vLos0 );
- Vec_PtrFree( vLis1 );
- Vec_PtrFree( vLos1 );
- // create sequential miter
- vPairsMiter = Saig_ManMiterWithIslands( p0, p1, &pMiter, vPairs );
- Vec_IntFree( vPairs );
- // if parameters are not given, create them
- if ( pPars == NULL )
- Ssw_ManSetDefaultParams( pPars = &Pars );
+ // derive full matching
+ Ssw_MatchingStart( p0, p1, vPairs );
+ if ( pPars->nIsleDist )
+ Ssw_MatchingExtend( p0, p1, pPars->nIsleDist, pPars->fVerbose );
+ Ssw_MatchingComplete( p0, p1 );
+ Ssw_MatchingComplete( p1, p0 );
+ vPairsAll = Ssw_MatchingPairs( p0, p1 );
+ // create miter and transfer matching
+ pMiter = Saig_ManCreateMiter( p0, p1, 0 );
+ vPairsMiter = Ssw_MatchingMiter( pMiter, p0, p1, vPairsAll );
+ Vec_IntFree( vPairsAll );
// start the induction manager
p = Ssw_ManCreate( pMiter, pPars );
// create equivalence classes using these IDs
- p->ppClasses = Ssw_ClassesFromIslands( pMiter, vPairsMiter );
+ if ( p->pPars->fPartSigCorr )
+ p->ppClasses = Ssw_ClassesPreparePairsSimple( pMiter, vPairsMiter );
+ else
+ p->ppClasses = Ssw_ClassesPrepare( pMiter, pPars->nFramesK, pPars->fLatchCorr, pPars->nMaxLevs, pPars->fVerbose );
+ if ( p->pPars->fDumpSRInit )
+ {
+ if ( p->pPars->fPartSigCorr )
+ {
+ Aig_Man_t * pSRed = Ssw_SpeculativeReduction( p );
+ Aig_ManDumpBlif( pSRed, "srm_part.blif", NULL, NULL );
+ Aig_ManStop( pSRed );
+ printf( "Speculatively reduced miter is saved in file \"%s\".\n", "srm_part.blif" );
+ }
+ else
+ printf( "Dumping speculative miter is possible only for partial signal correspondence (switch \"-c\").\n" );
+ }
p->pSml = Ssw_SmlStart( pMiter, 0, 1 + p->pPars->nFramesAddSim, 1 );
Ssw_ClassesSetData( p->ppClasses, p->pSml, Ssw_SmlObjHashWord, Ssw_SmlObjIsConstWord, Ssw_SmlObjsAreEqualWord );
// perform refinement of classes
@@ -299,28 +461,28 @@ Aig_Man_t * Ssw_SecWithIslandsInternal( Aig_Man_t * p0, Aig_Man_t * p1, int nCom
/**Function*************************************************************
- Synopsis [Solves SEC using structural similarity.]
+ Synopsis [Solves SEC with structural similarity.]
- Description []
+ Description [The first two arguments are pointers to the AIG managers.
+ The third argument is the array of pairs of IDs of structurally equivalent
+ nodes from the first and second managers, respectively.]
- SideEffects []
+ SideEffects [The managers will be updated by adding "islands of difference".]
SeeAlso []
***********************************************************************/
-int Ssw_SecWithIslands( Aig_Man_t * p0, Aig_Man_t * p1, int nCommonFlops, int fVerbose, Ssw_Pars_t * pPars )
+int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars )
{
+ Ssw_Pars_t Pars;
Aig_Man_t * pAigRes;
- Aig_Man_t * p0New, * p1New;
int RetValue, clk = clock();
- // try the new AIGs
-// printf( "Performing verification using structural similarity.\n" );
- p0New = Aig_ManDupSimple( p0 );
- p1New = Aig_ManDupSimple( p1 );
- pAigRes = Ssw_SecWithIslandsInternal( p0New, p1New, nCommonFlops, fVerbose, pPars );
- Aig_ManStop( p0New );
- Aig_ManStop( p1New );
- // report the results
+ // derive parameters if not given
+ if ( pPars == NULL )
+ Ssw_ManSetDefaultParams( pPars = &Pars );
+ // reduce the AIG with pairs
+ pAigRes = Ssw_SecWithSimilaritySweep( p0, p1, vPairs, pPars );
+ // report the result of verification
RetValue = Ssw_MiterStatus( pAigRes, 1 );
if ( RetValue == 1 )
printf( "Verification successful. " );
@@ -328,17 +490,43 @@ int Ssw_SecWithIslands( Aig_Man_t * p0, Aig_Man_t * p1, int nCommonFlops, int fV
printf( "Verification failed with a counter-example. " );
else
printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ",
- Aig_ManRegNum(pAigRes), Aig_ManRegNum(p0New)+Aig_ManRegNum(p1New) );
+ Aig_ManRegNum(pAigRes), Aig_ManRegNum(p0)+Aig_ManRegNum(p1) );
PRT( "Time", clock() - clk );
- // cleanup
Aig_ManStop( pAigRes );
return RetValue;
}
+/**Function*************************************************************
+
+ Synopsis [Dummy procedure to detect structural similarity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Saig_StrSimPerformMatching_hack( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Vec_Int_t * vPairs;
+ Aig_Obj_t * pObj;
+ int i;
+ // create array of pairs
+ vPairs = Vec_IntAlloc( 100 );
+ Aig_ManForEachObj( p0, pObj, i )
+ {
+ if ( !Aig_ObjIsConst1(pObj) && !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) )
+ continue;
+ Vec_IntPush( vPairs, i );
+ Vec_IntPush( vPairs, i );
+ }
+ return vPairs;
+}
/**Function*************************************************************
- Synopsis [Solves SEC using structural similarity for the miter.]
+ Synopsis [Solves SEC with structural similarity.]
Description []
@@ -347,34 +535,57 @@ int Ssw_SecWithIslands( Aig_Man_t * p0, Aig_Man_t * p1, int nCommonFlops, int fV
SeeAlso []
***********************************************************************/
-int Ssw_SecWithIslandsMiter( Aig_Man_t * pMiter, int nCommonFlops, int fVerbose )
+int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars )
{
+ Vec_Int_t * vPairs;
Aig_Man_t * pPart0, * pPart1;
int RetValue;
- if ( fVerbose )
- Aig_ManPrintStats( pMiter );
- // demiter the miter
- if ( !Saig_ManDemiterSimpleDiff( pMiter, &pPart0, &pPart1 ) )
+ if ( pPars->fVerbose )
+ printf( "Performing sequential verification using structural similarity.\n" );
+ // consider the case when a miter is given
+ if ( p1 == NULL )
{
- printf( "Demitering has failed.\n" );
- return -1;
+ if ( pPars->fVerbose )
+ {
+ Aig_ManPrintStats( p0 );
+ }
+ // demiter the miter
+ if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) )
+ {
+ printf( "Demitering has failed.\n" );
+ return -1;
+ }
}
- if ( fVerbose )
+ else
+ {
+ pPart0 = Aig_ManDupSimple( p0 );
+ pPart1 = Aig_ManDupSimple( p1 );
+ }
+ if ( pPars->fVerbose )
{
// Aig_ManPrintStats( pPart0 );
// Aig_ManPrintStats( pPart1 );
+ if ( p1 == NULL )
+ {
// Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL );
// Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL );
// printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" );
+ }
}
- RetValue = Ssw_SecWithIslands( pPart0, pPart1, nCommonFlops, fVerbose, NULL );
+ assert( Aig_ManRegNum(pPart0) > 0 );
+ assert( Aig_ManRegNum(pPart1) > 0 );
+ assert( Saig_ManPiNum(pPart0) == Saig_ManPiNum(pPart1) );
+ assert( Saig_ManPoNum(pPart0) == Saig_ManPoNum(pPart1) );
+ // derive pairs
+// vPairs = Saig_StrSimPerformMatching_hack( pPart0, pPart1 );
+ vPairs = Saig_StrSimPerformMatching( pPart0, pPart1, 0, pPars->fVerbose, NULL );
+ RetValue = Ssw_SecWithSimilarityPairs( pPart0, pPart1, vPairs, pPars );
Aig_ManStop( pPart0 );
Aig_ManStop( pPart1 );
+ Vec_IntFree( vPairs );
return RetValue;
}
-
-
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/aig/ssw/sswMan.c b/src/aig/ssw/sswMan.c
index 913f7518..7e6e4473 100644
--- a/src/aig/ssw/sswMan.c
+++ b/src/aig/ssw/sswMan.c
@@ -61,6 +61,8 @@ Ssw_Man_t * Ssw_ManCreate( Aig_Man_t * pAig, Ssw_Pars_t * pPars )
// other
p->vNewLos = Vec_PtrAlloc( 100 );
p->vNewPos = Vec_IntAlloc( 100 );
+ p->vResimConsts = Vec_PtrAlloc( 100 );
+ p->vResimClasses = Vec_PtrAlloc( 100 );
// p->pPars->fVerbose = 1;
return p;
@@ -171,6 +173,7 @@ void Ssw_ManCleanup( Ssw_Man_t * p )
***********************************************************************/
void Ssw_ManStop( Ssw_Man_t * p )
{
+ FREE( p->pVisited );
if ( p->pPars->fVerbose )
Ssw_ManPrintStats( p );
if ( p->ppClasses )
@@ -179,6 +182,8 @@ void Ssw_ManStop( Ssw_Man_t * p )
Ssw_SmlStop( p->pSml );
if ( p->vDiffPairs )
Vec_IntFree( p->vDiffPairs );
+ Vec_PtrFree( p->vResimConsts );
+ Vec_PtrFree( p->vResimClasses );
Vec_PtrFree( p->vNewLos );
Vec_IntFree( p->vNewPos );
Vec_PtrFree( p->vCommon );
diff --git a/src/aig/ssw/sswPart.c b/src/aig/ssw/sswPart.c
index 983a2022..9d2ec34e 100644
--- a/src/aig/ssw/sswPart.c
+++ b/src/aig/ssw/sswPart.c
@@ -30,7 +30,7 @@
/**Function*************************************************************
- Synopsis [Performs partitioned sequential SAT sweepingG.]
+ Synopsis [Performs partitioned sequential SAT sweeping.]
Description []
diff --git a/src/aig/ssw/sswSim.c b/src/aig/ssw/sswSim.c
index 836b75e3..a860199e 100644
--- a/src/aig/ssw/sswSim.c
+++ b/src/aig/ssw/sswSim.c
@@ -200,19 +200,21 @@ int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * p
{
unsigned * pSimLi, * pSimLo, * pSimCand;
int k;
+ assert( pObjLo->fPhase == 0 );
+ // pObjLi->fPhase may be 1, but the LI simulation data is not complemented!
pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id );
pSimLi = Ssw_ObjSim( p, pObjLi->Id );
pSimLo = Ssw_ObjSim( p, pObjLo->Id );
- if ( !Aig_IsComplement(pCand) )
+ if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) )
{
for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
- if ( pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) )
+ if ( ~pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) )
return 0;
}
else
{
for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
- if ( ~pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) )
+ if ( pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) )
return 0;
}
return 1;
@@ -233,24 +235,50 @@ int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * p
{
unsigned * pSimLi, * pSimLo, * pSimCand;
int k, Counter = 0;
+ assert( pObjLo->fPhase == 0 );
+ // pObjLi->fPhase may be 1, but the LI simulation data is not complemented!
pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id );
pSimLi = Ssw_ObjSim( p, pObjLi->Id );
pSimLo = Ssw_ObjSim( p, pObjLo->Id );
- if ( !Aig_IsComplement(pCand) )
+ if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) )
{
for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
- Counter += Aig_WordCountOnes(pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k]));
+ Counter += Aig_WordCountOnes(~pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k]));
}
else
{
for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
- Counter += Aig_WordCountOnes(~pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k]));
+ Counter += Aig_WordCountOnes(pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k]));
}
return Counter;
}
/**Function*************************************************************
+ Synopsis [Counts the number of 1s in the implication.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo )
+{
+ unsigned * pSimLi, * pSimLo;
+ int k, Counter = 0;
+ assert( pObjLo->fPhase == 0 );
+ // pObjLi->fPhase may be 1, but the LI simulation data is not complemented!
+ pSimLi = Ssw_ObjSim( p, pObjLi->Id );
+ pSimLo = Ssw_ObjSim( p, pObjLo->Id );
+ for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+ Counter += Aig_WordCountOnes( ~(pSimLi[k] ^ pSimLo[k]) );
+ return Counter;
+}
+
+/**Function*************************************************************
+
Synopsis [Returns 1 if simulation info is composed of all zeros.]
Description []
@@ -273,7 +301,7 @@ int Ssw_SmlNodeIsZero( Ssw_Sml_t * p, Aig_Obj_t * pObj )
/**Function*************************************************************
- Synopsis [Counts the number of one's in the patten of the output.]
+ Synopsis [Counts the number of one's in the patten the object.]
Description []
@@ -282,13 +310,55 @@ int Ssw_SmlNodeIsZero( Ssw_Sml_t * p, Aig_Obj_t * pObj )
SeeAlso []
***********************************************************************/
-int Ssw_SmlNodeCountOnes( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj )
{
unsigned * pSims;
int i, Counter = 0;
- pSims = Ssw_ObjSim(p, pObj->Id);
+ pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id);
+ if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) )
+ {
+ for ( i = 0; i < p->nWordsTotal; i++ )
+ Counter += Aig_WordCountOnes( ~pSims[i] );
+ }
+ else
+ {
+ for ( i = 0; i < p->nWordsTotal; i++ )
+ Counter += Aig_WordCountOnes( pSims[i] );
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of one's in the patten the object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs )
+{
+ Aig_Obj_t * pObj;
+ unsigned * pSims, uWord;
+ int i, k, Counter = 0;
+ if ( Vec_PtrSize(vObjs) == 0 )
+ return 0;
for ( i = 0; i < p->nWordsTotal; i++ )
- Counter += Aig_WordCountOnes( pSims[i] );
+ {
+ uWord = 0;
+ Vec_PtrForEachEntry( vObjs, pObj, k )
+ {
+ pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id);
+ if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) )
+ uWord |= ~pSims[i];
+ else
+ uWord |= pSims[i];
+ }
+ Counter += Aig_WordCountOnes( uWord );
+ }
return Counter;
}
@@ -889,6 +959,79 @@ p->nSimRounds++;
/**Function*************************************************************
+ Synopsis [Converts simulation information to be not normallized.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlUnnormalize( Ssw_Sml_t * p )
+{
+ Aig_Obj_t * pObj;
+ unsigned * pSims;
+ int i, k;
+ // convert constant 1
+ pSims = Ssw_ObjSim( p, 0 );
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = ~pSims[i];
+ // convert internal nodes
+ Aig_ManForEachNode( p->pAig, pObj, k )
+ {
+ if ( pObj->fPhase == 0 )
+ continue;
+ pSims = Ssw_ObjSim( p, pObj->Id );
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = ~pSims[i];
+ }
+ // PIs/POs are always stored in their natural state
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates AIG manager.]
+
+ Description [Assumes that the PI simulation info is attached.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter )
+{
+// if ( Aig_ObjIsTravIdCurrent(p->pAig, pObj) )
+// return;
+// Aig_ObjSetTravIdCurrent(p->pAig, pObj);
+ if ( pVisited[p->nFrames*pObj->Id+f] == nVisCounter )
+ return;
+ pVisited[p->nFrames*pObj->Id+f] = nVisCounter;
+ if ( Saig_ObjIsPi( p->pAig, pObj ) || Aig_ObjIsConst1(pObj) )
+ return;
+ if ( Saig_ObjIsLo( p->pAig, pObj ) )
+ {
+ if ( f == 0 )
+ return;
+ Ssw_SmlSimulateOneDyn_rec( p, Saig_ObjLoToLi(p->pAig, pObj), f-1, pVisited, nVisCounter );
+ Ssw_SmlNodeTransferNext( p, Saig_ObjLoToLi(p->pAig, pObj), pObj, f-1 );
+ return;
+ }
+ if ( Saig_ObjIsLi( p->pAig, pObj ) )
+ {
+ Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter );
+ Ssw_SmlNodeCopyFanin( p, pObj, f );
+ return;
+ }
+ assert( Aig_ObjIsNode(pObj) );
+ Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter );
+ Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin1(pObj), f, pVisited, nVisCounter );
+ Ssw_SmlNodeSimulate( p, pObj, f );
+}
+
+/**Function*************************************************************
+
Synopsis [Simulates AIG manager.]
Description [Assumes that the PI simulation info is attached.]
@@ -974,22 +1117,6 @@ void Ssw_SmlStop( Ssw_Sml_t * p )
free( p );
}
-/**Function*************************************************************
-
- Synopsis [Deallocates simulation manager.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Ssw_SmlNumFrames( Ssw_Sml_t * p )
-{
- return p->nFrames;
-}
-
/**Function*************************************************************
@@ -1051,6 +1178,56 @@ void Ssw_SmlResimulateSeq( Ssw_Sml_t * p )
}
+/**Function*************************************************************
+
+ Synopsis [Returns the number of frames simulated in the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlNumFrames( Ssw_Sml_t * p )
+{
+ return p->nFrames;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the total number of simulation words.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p )
+{
+ return p->nWordsTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the simulation info of the node.]
+
+ Description [The simulation info is normalized unless procedure
+ Ssw_SmlUnnormalize() is called in advance.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+ assert( !Aig_IsComplement(pObj) );
+ return Ssw_ObjSim( p, pObj->Id );
+}
+
/**Function*************************************************************
diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h
index e4b0ad69..987adaad 100644
--- a/src/base/abc/abc.h
+++ b/src/base/abc/abc.h
@@ -154,7 +154,12 @@ struct Abc_Obj_t_ // 12 words
// miscellaneous
void * pData; // the network specific data (SOP, BDD, gate, equiv class, etc)
Abc_Obj_t * pNext; // the next pointer in the hash table
- Abc_Obj_t * pCopy; // the copy of this object
+ union { // temporary store for user's data
+ Abc_Obj_t * pCopy; // the copy of this object
+ void * pTemp;
+ int iTemp;
+ float dTemp;
+ };
Hop_Obj_t * pEquiv; // pointer to the HAIG node
};
@@ -227,14 +232,14 @@ struct Abc_Lib_t_
//#pragma warning( disable : 4273 )
#ifdef WIN32
-#define DLLEXPORT __declspec(dllexport)
-#define DLLIMPORT __declspec(dllimport)
+#define ABC_DLLEXPORT __declspec(dllexport)
+#define ABC_DLLIMPORT __declspec(dllimport)
#else /* defined(WIN32) */
-#define DLLIMPORT
+#define ABC_DLLIMPORT
#endif /* defined(WIN32) */
#ifndef ABC_DLL
-#define ABC_DLL DLLIMPORT
+#define ABC_DLL ABC_DLLIMPORT
#endif
// maximum/minimum operators
@@ -748,7 +753,8 @@ extern ABC_DLL bool Abc_NodeIsBuf( Abc_Obj_t * pNode );
extern ABC_DLL bool Abc_NodeIsInv( Abc_Obj_t * pNode );
extern ABC_DLL void Abc_NodeComplement( Abc_Obj_t * pNode );
/*=== abcPrint.c ==========================================================*/
-extern ABC_DLL void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes );
+extern ABC_DLL float Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk );
+extern ABC_DLL void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower );
extern ABC_DLL void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk );
extern ABC_DLL void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk );
extern ABC_DLL void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk );
diff --git a/src/base/abc/abcHie.c b/src/base/abc/abcHie.c
index 56333a36..19bdc47e 100644
--- a/src/base/abc/abcHie.c
+++ b/src/base/abc/abcHie.c
@@ -472,9 +472,6 @@ Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL )
Vec_PtrWriteEntry( pDesign->vModules, 0, pNtkNew );
pNtkNew->pDesign = pDesign;
-//Abc_NtkPrintStats( stdout, pNtkH, 0 );
-//Abc_NtkPrintStats( stdout, pNtkNew, 0 );
-
// check integrity
if ( !Abc_NtkCheck( pNtkNew ) )
{
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index 2ad8dc75..7aad2eb2 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -38,6 +38,8 @@
#include "dch.h"
#include "ssw.h"
#include "cgt.h"
+#include "amap.h"
+#include "cec.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -82,6 +84,8 @@ static int Abc_CommandImfs ( Abc_Frame_t * pAbc, int argc, char ** arg
static int Abc_CommandMfs ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandTrace ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandSpeedup ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandPowerdown ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMerge ( 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 );
@@ -136,7 +140,7 @@ static int Abc_CommandICut ( Abc_Frame_t * pAbc, int argc, char ** arg
static int Abc_CommandIRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandDRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandDRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
-static int Abc_CommandDCompress2 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandDC2 ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandDChoice ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandDch ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandDrwsat ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -147,6 +151,9 @@ static int Abc_CommandIFraig ( Abc_Frame_t * pAbc, int argc, char ** arg
static int Abc_CommandDFraig ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandCSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandDProve ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandSimSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandMatch ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandHaig ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandMini ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandQbf ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -170,6 +177,7 @@ static int Abc_CommandRecPs ( Abc_Frame_t * pAbc, int argc, char ** arg
static int Abc_CommandRecUse ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandMap ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAmap ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandUnmap ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAttach ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandSuperChoice ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -202,8 +210,11 @@ static int Abc_CommandSim ( Abc_Frame_t * pAbc, int argc, char ** arg
static int Abc_CommandDarPhase ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandSynch ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandClockGate ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandExtWin ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandInsWin ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandCec2 ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandDCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -314,8 +325,9 @@ void Abc_FrameClearDesign()
***********************************************************************/
void Abc_Init( Abc_Frame_t * pAbc )
{
-// Abc_NtkBddImplicationTest();
-// Ply_LutPairTest();
+// Amap_LibParseTest( "at\\syn\\libraries\\LIBS\\BRDCM\\tsmc13_5.ff.genlib" );
+// Amap_LibParseTest( "at\\syn\\libraries\\LIBS\\GS60\\GS60_W_30_1.7_CORE.genlib" );
+// Amap_LibParseTest( "at\\syn\\libraries\\LIBS\\TYPICAL\\typical.genlib" );
Cmd_CommandAdd( pAbc, "Printing", "print_stats", Abc_CommandPrintStats, 0 );
Cmd_CommandAdd( pAbc, "Printing", "print_exdc", Abc_CommandPrintExdc, 0 );
@@ -356,6 +368,8 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Synthesis", "mfs", Abc_CommandMfs, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "trace", Abc_CommandTrace, 0 );
Cmd_CommandAdd( pAbc, "Synthesis", "speedup", Abc_CommandSpeedup, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "powerdown", Abc_CommandPowerdown, 1 );
+ Cmd_CommandAdd( pAbc, "Synthesis", "merge", Abc_CommandMerge, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 );
@@ -410,7 +424,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "New AIG", "irw", Abc_CommandIRewrite, 1 );
Cmd_CommandAdd( pAbc, "New AIG", "drw", Abc_CommandDRewrite, 1 );
Cmd_CommandAdd( pAbc, "New AIG", "drf", Abc_CommandDRefactor, 1 );
- Cmd_CommandAdd( pAbc, "New AIG", "dcompress2", Abc_CommandDCompress2, 1 );
+ Cmd_CommandAdd( pAbc, "New AIG", "dc2", Abc_CommandDC2, 1 );
Cmd_CommandAdd( pAbc, "New AIG", "dchoice", Abc_CommandDChoice, 1 );
Cmd_CommandAdd( pAbc, "New AIG", "dch", Abc_CommandDch, 1 );
Cmd_CommandAdd( pAbc, "New AIG", "drwsat", Abc_CommandDrwsat, 1 );
@@ -443,6 +457,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Choicing", "rec_use", Abc_CommandRecUse, 1 );
Cmd_CommandAdd( pAbc, "SC mapping", "map", Abc_CommandMap, 1 );
+ Cmd_CommandAdd( pAbc, "SC mapping", "amap", Abc_CommandAmap, 1 );
Cmd_CommandAdd( pAbc, "SC mapping", "unmap", Abc_CommandUnmap, 1 );
Cmd_CommandAdd( pAbc, "SC mapping", "attach", Abc_CommandAttach, 1 );
Cmd_CommandAdd( pAbc, "SC mapping", "sc", Abc_CommandSuperChoice, 1 );
@@ -473,12 +488,18 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Sequential", "phase", Abc_CommandDarPhase, 1 );
Cmd_CommandAdd( pAbc, "Sequential", "synch", Abc_CommandSynch, 1 );
Cmd_CommandAdd( pAbc, "Sequential", "clockgate", Abc_CommandClockGate, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "extwin", Abc_CommandExtWin, 1 );
+ Cmd_CommandAdd( pAbc, "Sequential", "inswin", Abc_CommandInsWin, 1 );
Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "cec2", Abc_CommandCec2, 0 );
Cmd_CommandAdd( pAbc, "Verification", "dcec", Abc_CommandDCec, 0 );
Cmd_CommandAdd( pAbc, "Verification", "sec", Abc_CommandSec, 0 );
Cmd_CommandAdd( pAbc, "Verification", "dsec", Abc_CommandDSec, 0 );
Cmd_CommandAdd( pAbc, "Verification", "dprove", Abc_CommandDProve, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "absec", Abc_CommandAbSec, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "simsec", Abc_CommandSimSec, 0 );
+ Cmd_CommandAdd( pAbc, "Verification", "match", Abc_CommandMatch, 0 );
Cmd_CommandAdd( pAbc, "Verification", "sat", Abc_CommandSat, 0 );
Cmd_CommandAdd( pAbc, "Verification", "dsat", Abc_CommandDSat, 0 );
Cmd_CommandAdd( pAbc, "Verification", "psat", Abc_CommandPSat, 0 );
@@ -553,6 +574,12 @@ void Abc_Init( Abc_Frame_t * pAbc )
// extern void Aig_ManRandomTest1();
// Aig_ManRandomTest1();
}
+// malloc(1001);
+ {
+ extern void Extra_MemTest();
+// Extra_MemTest();
+ }
+
}
/**Function*************************************************************
@@ -589,6 +616,10 @@ void Abc_End()
extern void Dar_LibStop();
Dar_LibStop();
}
+ {
+ extern void Aig_RManQuit();
+ Aig_RManQuit();
+ }
Abc_NtkFraigStoreClean();
// Rwt_Man4ExplorePrint();
@@ -616,6 +647,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
int fUseLutLib;
int fPrintTime;
int fPrintMuxes;
+ int fPower;
int c;
pNtk = Abc_FrameReadNtk(pAbc);
@@ -629,8 +661,9 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
fUseLutLib = 0;
fPrintTime = 0;
fPrintMuxes = 0;
+ fPower = 0;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmph" ) ) != EOF )
{
switch ( c )
{
@@ -652,6 +685,9 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'm':
fPrintMuxes ^= 1;
break;
+ case 'p':
+ fPower ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -669,7 +705,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( Abc_FrameReadErr(pAbc), "Cannot print LUT delay for a non-logic network.\n" );
return 1;
}
- Abc_NtkPrintStats( pOut, pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes );
+ Abc_NtkPrintStats( pOut, pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower );
if ( fPrintTime )
{
pAbc->TimeTotal += pAbc->TimeCommand;
@@ -680,7 +716,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: print_stats [-fbdltmh]\n" );
+ fprintf( pErr, "usage: print_stats [-fbdltmph]\n" );
fprintf( pErr, "\t prints the network statistics\n" );
fprintf( pErr, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" );
fprintf( pErr, "\t-b : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" );
@@ -688,6 +724,7 @@ usage:
fprintf( pErr, "\t-l : toggles printing delay of LUT mapping using LUT library [default = %s]\n", fSaveBest? "yes": "no" );
fprintf( pErr, "\t-t : toggles printing runtime statistics [default = %s]\n", fPrintTime? "yes": "no" );
fprintf( pErr, "\t-m : toggles printing MUX statistics [default = %s]\n", fPrintMuxes? "yes": "no" );
+ fprintf( pErr, "\t-p : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
@@ -773,7 +810,7 @@ int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv )
}
else
printf( "EXDC network statistics: \n" );
- Abc_NtkPrintStats( pOut, pNtk->pExdc, 0, 0, 0, 0, 0 );
+ Abc_NtkPrintStats( pOut, pNtk->pExdc, 0, 0, 0, 0, 0, 0 );
return 0;
usage:
@@ -3683,7 +3720,7 @@ int Abc_CommandMfs( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
Abc_NtkMfsParsDefault( pPars );
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCraestvwh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCraestpvwh" ) ) != EOF )
{
switch ( c )
{
@@ -3768,6 +3805,9 @@ int Abc_CommandMfs( Abc_Frame_t * pAbc, int argc, char ** argv )
case 't':
pPars->fOneHotness ^= 1;
break;
+ case 'p':
+ pPars->fPower ^= 1;
+ break;
case 'v':
pPars->fVerbose ^= 1;
break;
@@ -3801,7 +3841,7 @@ int Abc_CommandMfs( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: mfs [-WFDMLC <num>] [-raestvh]\n" );
+ fprintf( pErr, "usage: mfs [-WFDMLC <num>] [-raestpvh]\n" );
fprintf( pErr, "\t performs don't-care-based optimization of logic networks\n" );
fprintf( pErr, "\t-W <num> : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nWinTfoLevs );
fprintf( pErr, "\t-F <num> : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutsMax );
@@ -3814,6 +3854,7 @@ usage:
fprintf( pErr, "\t-e : toggle high-effort resubstitution [default = %s]\n", pPars->fMoreEffort? "yes": "no" );
fprintf( pErr, "\t-s : toggle evaluation of edge swapping [default = %s]\n", pPars->fSwapEdge? "yes": "no" );
fprintf( pErr, "\t-t : toggle using artificial one-hotness conditions [default = %s]\n", pPars->fOneHotness? "yes": "no" );
+ fprintf( pErr, "\t-p : toggle power-aware optimization [default = %s]\n", pPars->fPower? "yes": "no" );
fprintf( pErr, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" );
fprintf( pErr, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
@@ -4001,6 +4042,252 @@ usage:
return 1;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandPowerdown( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int c;
+ int fUseLutLib;
+ int Percentage;
+ int Degree;
+ int fVerbose;
+ int fVeryVerbose;
+ extern Abc_Ntk_t * Abc_NtkPowerdown( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fUseLutLib = 0;
+ Percentage =10;
+ Degree = 2;
+ fVerbose = 0;
+ fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "PNlvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'P':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ Percentage = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( Percentage < 1 || Percentage > 100 )
+ goto usage;
+ break;
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ Degree = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( Degree < 1 || Degree > 5 )
+ goto usage;
+ break;
+ case 'l':
+ fUseLutLib ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'w':
+ fVeryVerbose ^= 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, "This command can only be applied to a logic network.\n" );
+ return 1;
+ }
+
+ // modify the current network
+ pNtkRes = Abc_NtkPowerdown( pNtk, fUseLutLib, Percentage, Degree, fVerbose, fVeryVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "The command has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: powerdown [-P num] [-N num] [-vwh]\n" );
+ fprintf( pErr, "\t transforms LUT-mapped network into an AIG with choices;\n" );
+ fprintf( pErr, "\t the choices are added to power down the next round of mapping\n" );
+ fprintf( pErr, "\t-P <num> : switching propability delta defining power critical edges [default = %d%%]\n", Percentage );
+ fprintf( pErr, "\t (e.g. 5% means hot wires switch with probability: 0.45 <= p <= 0.50 (max)\n" );
+ fprintf( pErr, "\t-N <num> : the max critical path degree for resynthesis (0 < num < 6) [default = %d]\n", Degree );
+// fprintf( pErr, "\t-l : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib" : "unit" );
+ fprintf( pErr, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle printing detailed stats for each node [default = %s]\n", fVeryVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandMerge( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Abc_Ntk_t * pNtk;
+ Nwk_LMPars_t Pars, * pPars = &Pars;
+ Vec_Int_t * vResult;
+ int c;
+ extern Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars );
+ pNtk = Abc_FrameReadNtk(pAbc);
+
+ // set defaults
+ memset( pPars, 0, sizeof(Nwk_LMPars_t) );
+ pPars->nMaxLutSize = 5; // the max LUT size for merging (N=5)
+ pPars->nMaxSuppSize = 5; // the max total support size after merging (S=5)
+ pPars->nMaxDistance = 3; // the max number of nodes separating LUTs
+ pPars->nMaxLevelDiff = 2; // the max difference in levels
+ pPars->nMaxFanout = 100; // the max number of fanouts to traverse
+ pPars->fUseDiffSupp = 0; // enables the use of nodes with different support
+ pPars->fUseTfiTfo = 0; // enables the use of TFO/TFO nodes as candidates
+ pPars->fVeryVerbose = 0; // enables additional verbose output
+ pPars->fVerbose = 1; // enables verbose output
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NSDLFscvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( stdout, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nMaxLutSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nMaxLutSize < 2 )
+ goto usage;
+ break;
+ case 'S':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( stdout, "Command line switch \"-S\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nMaxSuppSize = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nMaxSuppSize < 2 )
+ goto usage;
+ break;
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( stdout, "Command line switch \"-D\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nMaxDistance = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nMaxDistance < 2 )
+ goto usage;
+ break;
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( stdout, "Command line switch \"-L\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nMaxLevelDiff = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nMaxLevelDiff < 2 )
+ goto usage;
+ break;
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( stdout, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nMaxFanout = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nMaxFanout < 2 )
+ goto usage;
+ break;
+ case 's':
+ pPars->fUseDiffSupp ^= 1;
+ break;
+ case 'c':
+ pPars->fUseTfiTfo ^= 1;
+ break;
+ case 'w':
+ pPars->fVeryVerbose ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL || !Abc_NtkIsLogic(pNtk) )
+ {
+ printf( "Abc_CommandSpeedup(): There is no mapped network to merge LUTs.\n" );
+ return 1;
+ }
+
+ vResult = Abc_NtkLutMerge( pNtk, pPars );
+ Vec_IntFree( vResult );
+ return 0;
+
+usage:
+ fprintf( stdout, "usage: merge [-NSDLF num] [-scwvh]\n" );
+ fprintf( stdout, "\t creates pairs of topologically-related LUTs\n" );
+ fprintf( stdout, "\t-N <num> : the max LUT size for merging (1 < num) [default = %d]\n", pPars->nMaxLutSize );
+ fprintf( stdout, "\t-S <num> : the max total support size after merging (1 < num) [default = %d]\n", pPars->nMaxSuppSize );
+ fprintf( stdout, "\t-D <num> : the max distance in terms of LUTs (0 < num) [default = %d]\n", pPars->nMaxDistance );
+ fprintf( stdout, "\t-L <num> : the max difference in levels (0 <= num) [default = %d]\n", pPars->nMaxLevelDiff );
+ fprintf( stdout, "\t-F <num> : the max number of fanouts to stop traversal (0 < num) [default = %d]\n", pPars->nMaxFanout );
+ fprintf( stdout, "\t-s : toggle the use of nodes without support overlap [default = %s]\n", pPars->fUseDiffSupp? "yes" : "no" );
+ fprintf( stdout, "\t-c : toggle the use of TFI/TFO nodes as candidates [default = %s]\n", pPars->fUseTfiTfo? "yes" : "no" );
+ fprintf( stdout, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+ fprintf( stdout, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( stdout, "\t-h : print the command usage\n");
+ return 1;
+}
/**Function*************************************************************
@@ -4905,7 +5192,7 @@ usage:
fprintf( pErr, "\t-P num : output partition size [default = %s]\n", Buffer );
fprintf( pErr, "\t-c : toggles deriving combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" );
fprintf( pErr, "\t-i : toggles deriving implication miter (file1 => file2) [default = %s]\n", fImplic? "yes": "no" );
- fprintf( pErr, "\t-m : toggles creating multi-output miters [default = %s]\n", fMulti? "yes": "no" );
+ fprintf( pErr, "\t-m : toggles creating multi-output miter [default = %s]\n", fMulti? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
fprintf( pErr, "\tfile1 : (optional) the file with the first network\n");
fprintf( pErr, "\tfile2 : (optional) the file with the second network\n");
@@ -6943,18 +7230,20 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv )
memset( pParams, 0, sizeof(Cut_Params_t) );
pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts)
pParams->nKeepMax = 1000; // the max number of cuts kept at a node
- pParams->fTruth = 0; // compute truth tables
+ pParams->fTruth = 1; // compute truth tables
pParams->fFilter = 1; // filter dominated cuts
pParams->fDrop = 0; // drop cuts on the fly
- pParams->fDag = 0; // compute DAG cuts
+ pParams->fDag = 1; // compute DAG cuts
pParams->fTree = 0; // compute tree cuts
pParams->fGlobal = 0; // compute global cuts
pParams->fLocal = 0; // compute local cuts
pParams->fFancy = 0; // compute something fancy
+ pParams->fRecordAig= 1; // compute something fancy
pParams->fMap = 0; // compute mapping delay
+ pParams->fAdjust = 1; // removes useless fanouts
pParams->fVerbose = 0; // the verbosiness flag
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzmvoh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzamjvoh" ) ) != EOF )
{
switch ( c )
{
@@ -7004,9 +7293,15 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'z':
pParams->fFancy ^= 1;
break;
+ case 'a':
+ pParams->fRecordAig ^= 1;
+ break;
case 'm':
pParams->fMap ^= 1;
break;
+ case 'j':
+ pParams->fAdjust ^= 1;
+ break;
case 'v':
pParams->fVerbose ^= 1;
break;
@@ -7056,7 +7351,7 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: cut [-K num] [-M num] [-tfdxyzmvh]\n" );
+ fprintf( pErr, "usage: cut [-K num] [-M num] [-tfdxyzamjvh]\n" );
fprintf( pErr, "\t computes k-feasible cuts for the AIG\n" );
fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax );
fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax );
@@ -7068,7 +7363,9 @@ usage:
fprintf( pErr, "\t-g : toggle computing only global cuts [default = %s]\n", pParams->fGlobal? "yes": "no" );
fprintf( pErr, "\t-l : toggle computing only local cuts [default = %s]\n", pParams->fLocal? "yes": "no" );
fprintf( pErr, "\t-z : toggle fancy computations [default = %s]\n", pParams->fFancy? "yes": "no" );
+ fprintf( pErr, "\t-a : toggle recording cut functions [default = %s]\n", pParams->fRecordAig?"yes": "no" );
fprintf( pErr, "\t-m : toggle delay-oriented FPGA mapping [default = %s]\n", pParams->fMap? "yes": "no" );
+ fprintf( pErr, "\t-j : toggle removing fanouts due to XOR/MUX [default = %s]\n", pParams->fAdjust? "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;
@@ -7742,7 +8039,6 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
// extern void Aig_ProcedureTest();
extern void Abc_NtkDarTest( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkDarTestNtk( Abc_Ntk_t * pNtk );
- extern int Ssw_SecSpecialMiter( Aig_Man_t * pMiter, int fVerbose );
pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
@@ -8804,13 +9100,13 @@ usage:
SeeAlso []
***********************************************************************/
-int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv )
+int Abc_CommandDC2( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
- int fBalance, fVerbose, fUpdateLevel, fFanout, c;
+ int fBalance, fVerbose, fUpdateLevel, fFanout, fPower, c;
- extern Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fVerbose );
+ extern Abc_Ntk_t * Abc_NtkDC2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose );
pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
@@ -8821,8 +9117,9 @@ int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv )
fVerbose = 0;
fUpdateLevel = 0;
fFanout = 1;
+ fPower = 0;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "blfvh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "blfpvh" ) ) != EOF )
{
switch ( c )
{
@@ -8835,6 +9132,9 @@ int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'f':
fFanout ^= 1;
break;
+ case 'p':
+ fPower ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -8854,7 +9154,7 @@ int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "This command works only for strashed networks.\n" );
return 1;
}
- pNtkRes = Abc_NtkDCompress2( pNtk, fBalance, fUpdateLevel, fFanout, fVerbose );
+ pNtkRes = Abc_NtkDC2( pNtk, fBalance, fUpdateLevel, fFanout, fPower, fVerbose );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Command has failed.\n" );
@@ -8865,11 +9165,12 @@ int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: dcompress2 [-blfvh]\n" );
+ fprintf( pErr, "usage: dc2 [-blfpvh]\n" );
fprintf( pErr, "\t performs combinational AIG optimization\n" );
fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" );
fprintf( pErr, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" );
fprintf( pErr, "\t-f : toggle representing fanouts [default = %s]\n", fFanout? "yes": "no" );
+ fprintf( pErr, "\t-p : toggle power-aware rewriting [default = %s]\n", fPower? "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;
@@ -9053,7 +9354,7 @@ int Abc_CommandDch( Abc_Frame_t * pAbc, int argc, char ** argv )
pPars->fSynthesis ^= 1;
break;
case 'p':
- pPars->fPolarFlip ^= 1;
+ pPars->fPower ^= 1;
break;
case 't':
pPars->fSimulateTfo ^= 1;
@@ -9094,7 +9395,7 @@ usage:
fprintf( pErr, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
fprintf( pErr, "\t-S num : the max number of SAT variables [default = %d]\n", pPars->nSatVarMax );
fprintf( pErr, "\t-s : toggle synthesizing three snapshots [default = %s]\n", pPars->fSynthesis? "yes": "no" );
- fprintf( pErr, "\t-p : toggle alighning polarity of SAT variables [default = %s]\n", pPars->fPolarFlip? "yes": "no" );
+ fprintf( pErr, "\t-p : toggle power-aware rewriting [default = %s]\n", pPars->fPower? "yes": "no" );
fprintf( pErr, "\t-t : toggle simulation of the TFO classes [default = %s]\n", pPars->fSimulateTfo? "yes": "no" );
fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
@@ -11166,6 +11467,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk, * pNtkRes;
char Buffer[100];
double DelayTarget;
+ int fAreaOnly;
int fRecovery;
int fSweep;
int fSwitching;
@@ -11180,12 +11482,13 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
DelayTarget =-1;
+ fAreaOnly = 0;
fRecovery = 1;
fSweep = 1;
fSwitching = 0;
fVerbose = 0;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "Daspvh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Darspvh" ) ) != EOF )
{
switch ( c )
{
@@ -11201,6 +11504,9 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
goto usage;
break;
case 'a':
+ fAreaOnly ^= 1;
+ break;
+ case 'r':
fRecovery ^= 1;
break;
case 's':
@@ -11225,6 +11531,9 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
+ if ( fAreaOnly )
+ DelayTarget = 100000.0;
+
if ( !Abc_NtkIsStrash(pNtk) )
{
pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
@@ -11274,10 +11583,11 @@ usage:
sprintf( Buffer, "not used" );
else
sprintf( Buffer, "%.3f", DelayTarget );
- fprintf( pErr, "usage: map [-D float] [-aspvh]\n" );
+ fprintf( pErr, "usage: map [-D float] [-arspvh]\n" );
fprintf( pErr, "\t performs standard cell mapping of the current network\n" );
fprintf( pErr, "\t-D float : sets the global required times [default = %s]\n", Buffer );
- fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
+ fprintf( pErr, "\t-a : toggles area-only mapping [default = %s]\n", fAreaOnly? "yes": "no" );
+ fprintf( pErr, "\t-r : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" );
fprintf( pErr, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" );
fprintf( pErr, "\t-p : optimizes power by minimizing switching [default = %s]\n", fSwitching? "yes": "no" );
fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
@@ -11285,6 +11595,159 @@ usage:
return 1;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandAmap( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Amap_Par_t Pars, * pPars = &Pars;
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkRes;
+ int fSweep;
+ int c;
+ extern Abc_Ntk_t * Abc_NtkDarAmap( Abc_Ntk_t * pNtk, Amap_Par_t * pPars );
+ extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fSweep = 0;
+ Amap_ManSetDefaultParams( pPars );
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FAEmxisvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by a floating point number.\n" );
+ goto usage;
+ }
+ pPars->nIterFlow = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nIterFlow < 0 )
+ goto usage;
+ break;
+ case 'A':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-A\" should be followed by a floating point number.\n" );
+ goto usage;
+ }
+ pPars->nIterArea = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nIterArea < 0 )
+ goto usage;
+ break;
+ case 'E':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-E\" should be followed by a floating point number.\n" );
+ goto usage;
+ }
+ pPars->fEpsilon = (float)atof(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->fEpsilon < 0.0 || pPars->fEpsilon > 1.0 )
+ goto usage;
+ break;
+ case 'm':
+ pPars->fUseMuxes ^= 1;
+ break;
+ case 'x':
+ pPars->fUseXors ^= 1;
+ break;
+ case 'i':
+ pPars->fFreeInvs ^= 1;
+ break;
+ case 's':
+ fSweep ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Strashing before mapping has failed.\n" );
+ return 1;
+ }
+ pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 );
+ Abc_NtkDelete( pNtkRes );
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Balancing before mapping has failed.\n" );
+ return 1;
+ }
+ fprintf( pOut, "The network was strashed and balanced before mapping.\n" );
+ // get the new network
+ pNtkRes = Abc_NtkDarAmap( pNtk, pPars );
+ if ( pNtkRes == NULL )
+ {
+ Abc_NtkDelete( pNtk );
+ fprintf( pErr, "Mapping has failed.\n" );
+ return 1;
+ }
+ Abc_NtkDelete( pNtk );
+ }
+ else
+ {
+ // get the new network
+ pNtkRes = Abc_NtkDarAmap( pNtk, pPars );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Mapping has failed.\n" );
+ return 1;
+ }
+ }
+
+ if ( fSweep )
+ Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 );
+
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: amap [-FA <num>] [-E <float>] [-mxisvh]\n" );
+ fprintf( pErr, "\t performs standard cell mapping of the current network\n" );
+ fprintf( pErr, "\t-F num : the number of iterations of area flow [default = %d]\n", pPars->nIterFlow );
+ fprintf( pErr, "\t-A num : the number of iterations of exact area [default = %d]\n", pPars->nIterArea );
+ fprintf( pErr, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->fEpsilon );
+ fprintf( pErr, "\t-m : toggles using MUX matching [default = %s]\n", pPars->fUseMuxes? "yes": "no" );
+ fprintf( pErr, "\t-x : toggles using XOR matching [default = %s]\n", pPars->fUseXors? "yes": "no" );
+ fprintf( pErr, "\t-i : toggles assuming inverters are free [default = %s]\n", pPars->fFreeInvs? "yes": "no" );
+ fprintf( pErr, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
/**Function*************************************************************
@@ -11916,6 +12379,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
pPars->fExpRed = 1;
pPars->fLatchPaths = 0;
pPars->fEdge = 1;
+ pPars->fPower = 0;
pPars->fCutMin = 0;
pPars->fSeqMap = 0;
pPars->fBidec = 0;
@@ -11930,7 +12394,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
pPars->pFuncCost = NULL;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADEpaflemrstbvh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADEqaflepmrstbvh" ) ) != EOF )
{
switch ( c )
{
@@ -12001,7 +12465,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( pPars->Epsilon < 0.0 || pPars->Epsilon > 1.0 )
goto usage;
break;
- case 'p':
+ case 'q':
pPars->fPreprocess ^= 1;
break;
case 'a':
@@ -12019,6 +12483,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'e':
pPars->fEdge ^= 1;
break;
+ case 'p':
+ pPars->fPower ^= 1;
+ break;
case 'm':
pPars->fCutMin ^= 1;
break;
@@ -12159,7 +12626,7 @@ usage:
sprintf( LutSize, "library" );
else
sprintf( LutSize, "%d", pPars->nLutSize );
- fprintf( pErr, "usage: if [-KCFA num] [-DE float] [-parlemsbvh]\n" );
+ fprintf( pErr, "usage: if [-KCFA num] [-DE float] [-qarlepmsbvh]\n" );
fprintf( pErr, "\t performs FPGA technology mapping of the network\n" );
fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize );
fprintf( pErr, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
@@ -12167,12 +12634,13 @@ usage:
fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters );
fprintf( pErr, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer );
fprintf( pErr, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon );
- fprintf( pErr, "\t-p : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" );
+ fprintf( pErr, "\t-q : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" );
fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" );
// fprintf( pErr, "\t-f : toggles one fancy feature [default = %s]\n", pPars->fFancy? "yes": "no" );
fprintf( pErr, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" );
fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" );
fprintf( pErr, "\t-e : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" );
+ fprintf( pErr, "\t-p : uses power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" );
fprintf( pErr, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" );
fprintf( pErr, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" );
// fprintf( pErr, "\t-t : toggles the use of true sequential cuts [default = %s]\n", pPars->fLiftLeaves? "yes": "no" );
@@ -12957,10 +13425,12 @@ int Abc_CommandFlowRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
int fFastButConservative;
int maxDelay;
- extern Abc_Ntk_t* Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose,
- int fComputeInit, int fGuaranteeInit, int fBlockConst,
- int fForward, int fBackward, int nMaxIters,
- int maxDelay, int fFastButConservative);
+ printf( "This command is temporarily disabled.\n" );
+ return 0;
+// extern Abc_Ntk_t* Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose,
+// int fComputeInit, int fGuaranteeInit, int fBlockConst,
+// int fForward, int fBackward, int nMaxIters,
+// int maxDelay, int fFastButConservative);
pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
@@ -13042,7 +13512,7 @@ int Abc_CommandFlowRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" );
return 1;
}
-
+
if ( fGuaranteeInit && !fComputeInit )
{
fprintf( pErr, "Initial state guarantee (-g) requires initial state computation (-i).\n" );
@@ -13062,10 +13532,10 @@ int Abc_CommandFlowRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// perform the retiming
- pNtkRes = Abc_FlowRetime_MinReg( pNtk, fVerbose, fComputeInit,
- fGuaranteeInit, fBlockConst,
- fForward, fBackward,
- nMaxIters, maxDelay, fFastButConservative );
+// pNtkRes = Abc_FlowRetime_MinReg( pNtk, fVerbose, fComputeInit,
+// fGuaranteeInit, fBlockConst,
+// fForward, fBackward,
+// nMaxIters, maxDelay, fFastButConservative );
if (pNtkRes != pNtk)
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
@@ -13567,7 +14037,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
Ssw_ManSetDefaultParams( pPars );
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLNSIVMplfudvwh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLNSIVMplfudsvwh" ) ) != EOF )
{
switch ( c )
{
@@ -13696,6 +14166,9 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'd':
pPars->fDynamic ^= 1;
break;
+ case 's':
+ pPars->fLocalSim ^= 1;
+ break;
case 'v':
pPars->fVerbose ^= 1;
break;
@@ -13739,7 +14212,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: scorr [-PQFCLNSIVM <num>] [-pludvwh]\n" );
+ fprintf( pErr, "usage: scorr [-PQFCLNSIVM <num>] [-pludsvwh]\n" );
fprintf( pErr, "\t performs sequential sweep using K-step induction\n" );
fprintf( pErr, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize );
fprintf( pErr, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize );
@@ -13756,6 +14229,7 @@ usage:
// fprintf( pErr, "\t-f : toggle filtering using iterative BMC [default = %s]\n", pPars->fSemiFormal? "yes": "no" );
fprintf( pErr, "\t-u : toggle using uniqueness constraints [default = %s]\n", pPars->fUniqueness? "yes": "no" );
fprintf( pErr, "\t-d : toggle dynamic addition of constraints [default = %s]\n", pPars->fDynamic? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle local simulation in the cone of influence [default = %s]\n", pPars->fLocalSim? "yes": "no" );
fprintf( pErr, "\t-w : toggle printout of flop equivalences [default = %s]\n", pPars->fFlopVerbose? "yes": "no" );
fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
@@ -14336,21 +14810,29 @@ int Abc_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv )
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
+ int fNew;
+ int fComb;
int nFrames;
int nWords;
+ int TimeOut;
+ int fMiter;
int fVerbose;
- extern int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int fVerbose );
+ extern int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int TimeOut, int fNew, int fComb, int fMiter, int fVerbose );
pNtk = Abc_FrameReadNtk(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
+ fNew = 1;
+ fComb = 0;
nFrames = 32;
nWords = 8;
+ TimeOut = 30;
+ fMiter = 0;
fVerbose = 0;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "FWvh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FWTncmvh" ) ) != EOF )
{
switch ( c )
{
@@ -14376,6 +14858,26 @@ int Abc_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( nWords < 0 )
goto usage;
break;
+ case 'T':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ TimeOut = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( TimeOut < 0 )
+ goto usage;
+ break;
+ case 'n':
+ fNew ^= 1;
+ break;
+ case 'c':
+ fComb ^= 1;
+ break;
+ case 'm':
+ fMiter ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -14390,27 +14892,24 @@ int Abc_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Empty network.\n" );
return 1;
}
-
if ( !Abc_NtkIsStrash(pNtk) )
{
fprintf( pErr, "Only works for strashed networks.\n" );
return 1;
}
- if ( !Abc_NtkLatchNum(pNtk) )
- {
- fprintf( pErr, "The network is combinational.\n" );
- return 0;
- }
-
FREE( pNtk->pSeqModel );
- Abc_NtkDarSeqSim( pNtk, nFrames, nWords, fVerbose );
+ Abc_NtkDarSeqSim( pNtk, nFrames, nWords, TimeOut, fNew, fComb, fMiter, fVerbose );
return 0;
usage:
- fprintf( pErr, "usage: sim [-F num] [-W num] [-vh]\n" );
+ fprintf( pErr, "usage: sim [-FWT num] [-ncmvh]\n" );
fprintf( pErr, "\t performs random simulation of the sequentail miter\n" );
fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames );
fprintf( pErr, "\t-W num : the number of words to simulate [default = %d]\n", nWords );
+ fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", TimeOut );
+ fprintf( pErr, "\t-n : toggle new vs. old implementation [default = %s]\n", fNew? "new": "old" );
+ fprintf( pErr, "\t-c : toggle comb vs. seq simulaton [default = %s]\n", fComb? "comb": "seq" );
+ fprintf( pErr, "\t-m : toggle miter vs. any circuit [default = %s]\n", fMiter? "miter": "not miter" );
fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
@@ -14664,7 +15163,7 @@ int Abc_CommandClockGate( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
Cgt_SetDefaultParams( pPars );
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "LNDCVKvh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "LNDCVKavwh" ) ) != EOF )
{
switch ( c )
{
@@ -14734,9 +15233,15 @@ int Abc_CommandClockGate( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( pPars->nFlopsMin <= 0 )
goto usage;
break;
+ case 'a':
+ pPars->fAreaOnly ^= 1;
+ break;
case 'v':
pPars->fVerbose ^= 1;
break;
+ case 'w':
+ pPars->fVeryVerbose ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -14780,7 +15285,7 @@ int Abc_CommandClockGate( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( pErr, "usage: clockgate [-LNDCVK <num>] [-vh] <file>\n" );
+ fprintf( pErr, "usage: clockgate [-LNDCVK <num>] [-avwh] <file>\n" );
fprintf( pErr, "\t sequential clock gating with observability don't-cares\n" );
fprintf( pErr, "\t-L num : max level number of a clock gate [default = %d]\n", pPars->nLevelMax );
fprintf( pErr, "\t-N num : max number of candidates for a flop [default = %d]\n", pPars->nCandMax );
@@ -14788,7 +15293,9 @@ usage:
fprintf( pErr, "\t-C num : max number of conflicts at a node [default = %d]\n", pPars->nConfMax );
fprintf( pErr, "\t-V num : min number of vars to recycle SAT solver [default = %d]\n", pPars->nVarsMin );
fprintf( pErr, "\t-K num : min number of flops to recycle SAT solver [default = %d]\n", pPars->nFlopsMin );
+ fprintf( pErr, "\t-a : toggle minimizing area-only [default = %s]\n", pPars->fAreaOnly? "yes": "no" );
fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle even more detailed output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
fprintf( pErr, "\tfile : (optional) constraints for primary inputs and register outputs\n");
return 1;
@@ -14805,6 +15312,226 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandExtWin( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtkRes, * pNtk;
+ int c;
+ int nObjId;
+ int nDist;
+ int fVerbose;
+
+ extern Abc_Ntk_t * Abc_NtkDarExtWin( Abc_Ntk_t * pNtk, int nObjId, int nDist, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nObjId = -1;
+ nDist = 5;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NDvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nObjId = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nObjId <= 0 )
+ goto usage;
+ break;
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nDist = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nDist <= 0 )
+ goto usage;
+ 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_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Only works for structrally hashed networks.\n" );
+ return 1;
+ }
+
+ if ( argc != globalUtilOptind )
+ {
+ fprintf( pErr, "Not enough command-line arguments.\n" );
+ return 1;
+ }
+ // modify the current network
+ pNtkRes = Abc_NtkDarExtWin( pNtk, nObjId, nDist, fVerbose );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Extracting sequential window has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: extwin [-ND <num>] [-vh]\n" );
+ fprintf( pErr, "\t extracts sequential window from the AIG\n" );
+ fprintf( pErr, "\t-N num : the ID of the object to use as the center [default = %d]\n", nObjId );
+ fprintf( pErr, "\t-D num : the \"radius\" of the window [default = %d]\n", nDist );
+ fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandInsWin( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtkRes, * pNtk, * pNtkCare;
+ int c;
+ int nObjId;
+ int nDist;
+ int fVerbose;
+
+ extern Abc_Ntk_t * Abc_NtkDarInsWin( Abc_Ntk_t * pNtk, Abc_Ntk_t * pWnd, int nObjId, int nDist, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ nObjId = -1;
+ nDist = 5;
+ fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NDvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nObjId = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nObjId <= 0 )
+ goto usage;
+ break;
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nDist = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nDist <= 0 )
+ goto usage;
+ 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_NtkIsStrash(pNtk) )
+ {
+ fprintf( pErr, "Only works for structrally hashed networks.\n" );
+ return 1;
+ }
+
+ if ( argc != globalUtilOptind + 1 )
+ {
+ fprintf( pErr, "Not enough command-line arguments.\n" );
+ return 1;
+ }
+ pNtkCare = Io_Read( argv[globalUtilOptind], Io_ReadFileType(argv[globalUtilOptind]), 1 );
+ if ( pNtkCare == NULL )
+ {
+ printf( "Reading care network has failed.\n" );
+ return 1;
+ }
+ if ( !Abc_NtkIsStrash(pNtkCare) )
+ {
+ Abc_Ntk_t * pNtkTemp;
+ pNtkCare = Abc_NtkStrash( pNtkTemp = pNtkCare, 0, 1, 0 );
+ Abc_NtkDelete( pNtkTemp );
+ }
+ // modify the current network
+ pNtkRes = Abc_NtkDarInsWin( pNtk, pNtkCare, nObjId, nDist, fVerbose );
+ Abc_NtkDelete( pNtkCare );
+ if ( pNtkRes == NULL )
+ {
+ fprintf( pErr, "Inserting sequential window has failed.\n" );
+ return 0;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: inswin [-ND <num>] [-vh] <file>\n" );
+ fprintf( pErr, "\t inserts sequential window into the AIG\n" );
+ fprintf( pErr, "\t-N num : the ID of the object to use as the center [default = %d]\n", nObjId );
+ fprintf( pErr, "\t-D num : the \"radius\" of the window [default = %d]\n", nDist );
+ fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ fprintf( pErr, "\tfile : file with the AIG to be inserted\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
{
char Buffer[16];
@@ -15108,6 +15835,149 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandCec2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Cec_ParCec_t Pars, * pPars = &Pars;
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+ int fDelete1, fDelete2;
+ char ** pArgvNew;
+ int nArgcNew;
+ int fMiter;
+ int c;
+
+ extern int Abc_NtkDarCec2( Abc_Ntk_t * pNtk0, Abc_Ntk_t * pNtk1, Cec_ParCec_t * pPars );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fMiter = 0;
+ Cec_ManCecSetDefaultParams( pPars );
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "BMImfrsvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'B':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nBTLimitBeg = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nBTLimitBeg < 0 )
+ goto usage;
+ break;
+ case 'M':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nBTlimitMulti = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nBTlimitMulti < 0 )
+ goto usage;
+ break;
+ case 'I':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nIters = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nIters < 0 )
+ goto usage;
+ break;
+ case 'm':
+ fMiter ^= 1;
+ break;
+ case 'f':
+ pPars->fFirstStop ^= 1;
+ break;
+ case 'r':
+ pPars->fRewriting ^= 1;
+ break;
+ case 's':
+ pPars->fSatSweeping ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( fMiter )
+ {
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if ( Abc_NtkIsStrash(pNtk) )
+ {
+ pNtk1 = pNtk;
+ fDelete1 = 0;
+ }
+ else
+ {
+ pNtk1 = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ fDelete1 = 1;
+ }
+ pNtk2 = NULL;
+ fDelete2 = 0;
+ }
+ else
+ {
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+ }
+
+ // perform equivalence checking
+ Abc_NtkDarCec2( pNtk1, pNtk2, pPars );
+
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: cec2 [-BMI num] [-frsvh] <file1> <file2>\n" );
+ fprintf( pErr, "\t performs combinational equivalence checking\n" );
+ fprintf( pErr, "\t-B num : staring limit on the number of conflicts [default = %d]\n", pPars->nBTLimitBeg );
+ fprintf( pErr, "\t-M num : multiple of the above limit [default = %d]\n", pPars->nBTlimitMulti );
+ fprintf( pErr, "\t-I num : the number of iterations [default = %d]\n", pPars->nIters );
+ fprintf( pErr, "\t-m : toggle working on two networks or a miter [default = %s]\n", fMiter? "miter": "two networks" );
+ fprintf( pErr, "\t-f : toggle stopping after first mismatch [default = %s]\n", pPars->fFirstStop? "yes": "no" );
+ fprintf( pErr, "\t-r : toggle AIG rewriting [default = %s]\n", pPars->fRewriting? "yes": "no" );
+ fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", pPars->fSatSweeping? "SAT only": "FRAIG + SAT" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ 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");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
@@ -15558,6 +16428,351 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandAbSec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+ int fDelete1, fDelete2;
+ char ** pArgvNew;
+ int nArgcNew;
+ int fMiter, nFrames, fVerbose, c;
+
+ extern int Abc_NtkDarAbSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fMiter = 1;
+ nFrames = 2;
+ fVerbose = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Fmvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nFrames = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nFrames < 0 )
+ goto usage;
+ break;
+ case 'm':
+ fMiter ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( fMiter )
+ {
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ printf( "This command works only for structrally hashed networks. Run \"st\".\n" );
+ return 0;
+ }
+ Abc_NtkDarAbSec( pNtk, NULL, nFrames, fVerbose );
+ }
+ else
+ {
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+ if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 )
+ {
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ printf( "The network has no latches. Used combinational command \"cec\".\n" );
+ return 0;
+ }
+ // perform verification
+ Abc_NtkDarAbSec( pNtk1, pNtk2, nFrames, fVerbose );
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: absec [-F num] [-mv] <file1> <file2>\n" );
+ fprintf( pErr, "\t performs SEC by applying CEC to several timeframes\n" );
+ fprintf( pErr, "\t-F num : the total number of timeframes to use [default = %d]\n", nFrames );
+ fprintf( pErr, "\t-m : toggles miter vs. two networks [default = %s]\n", fMiter? "miter": "two networks" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ 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");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandSimSec( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Ssw_Pars_t Pars, * pPars = &Pars;
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk1, * pNtk2;
+ int fDelete1, fDelete2;
+ char ** pArgvNew;
+ int nArgcNew, c;
+ int fMiter;
+
+ extern int Abc_NtkDarSimSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Ssw_Pars_t * pPars );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fMiter = 1;
+ Ssw_ManSetDefaultParams( pPars );
+ pPars->fPartSigCorr = 1;
+ pPars->fVerbose = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FDcymvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nFramesK = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nFramesK < 0 )
+ goto usage;
+ break;
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nIsleDist = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nIsleDist < 0 )
+ goto usage;
+ break;
+ case 'm':
+ fMiter ^= 1;
+ break;
+ case 'c':
+ pPars->fPartSigCorr ^= 1;
+ break;
+ case 'y':
+ pPars->fDumpSRInit ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( fMiter )
+ {
+// Abc_Ntk_t * pNtkA, * pNtkB;
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ printf( "This command works only for structrally hashed networks. Run \"st\".\n" );
+ return 0;
+ }
+ Abc_NtkDarSimSec( pNtk, NULL, pPars );
+/*
+ pNtkA = Abc_NtkDup( pNtk );
+ pNtkB = Abc_NtkDup( pNtk );
+ Abc_NtkDarSimSec( pNtkA, pNtkB, pPars );
+ Abc_NtkDelete( pNtkA );
+ Abc_NtkDelete( pNtkB );
+*/
+ }
+ else
+ {
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+ if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 )
+ {
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ printf( "The network has no latches. Used combinational command \"cec\".\n" );
+ return 0;
+ }
+ // perform verification
+ Abc_NtkDarSimSec( pNtk1, pNtk2, pPars );
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ }
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: simsec [-FD num] [-mcyv] <file1> <file2>\n" );
+ fprintf( pErr, "\t performs SEC using structural similarity\n" );
+ fprintf( pErr, "\t-F num : the limit on the depth of induction [default = %d]\n", pPars->nFramesK );
+ fprintf( pErr, "\t-D num : the distance for extending islands [default = %d]\n", pPars->nIsleDist );
+ fprintf( pErr, "\t-m : toggles miter vs. two networks [default = %s]\n", fMiter? "miter": "two networks" );
+ fprintf( pErr, "\t-c : uses partial vs. full signal correspondence [default = %s]\n", pPars->fPartSigCorr? "partial": "full" );
+ fprintf( pErr, "\t-y : dumps speculatively reduced miter of the classes [default = %s]\n", pPars->fDumpSRInit? "yes": "no" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ 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");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandMatch( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes;
+ int fDelete1, fDelete2;
+ char ** pArgvNew;
+ int nArgcNew, c;
+ int fMiter;
+ int nDist;
+ int fVerbose;
+
+ extern Abc_Ntk_t * Abc_NtkDarMatch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nDist, int fVerbose );
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set defaults
+ fMiter = 0;
+ nDist = 0;
+ fVerbose = 1;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "Dmvh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'D':
+ if ( globalUtilOptind >= argc )
+ {
+ fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ nDist = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( nDist < 0 )
+ goto usage;
+ break;
+ case 'm':
+ fMiter ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+ if ( fMiter )
+ {
+// Abc_Ntk_t * pNtkA, * pNtkB;
+ if ( !Abc_NtkIsStrash(pNtk) )
+ {
+ printf( "This command works only for structrally hashed networks. Run \"st\".\n" );
+ return 0;
+ }
+ pNtkRes = Abc_NtkDarMatch( pNtk, NULL, nDist, fVerbose );
+/*
+ pNtkA = Abc_NtkDup( pNtk );
+ pNtkB = Abc_NtkDup( pNtk );
+ Abc_NtkDarSimSec( pNtkA, pNtkB, pPars );
+ Abc_NtkDelete( pNtkA );
+ Abc_NtkDelete( pNtkB );
+*/
+ }
+ else
+ {
+ pArgvNew = argv + globalUtilOptind;
+ nArgcNew = argc - globalUtilOptind;
+ if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) )
+ return 1;
+ if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 )
+ {
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ printf( "The network has no latches. Used combinational command \"cec\".\n" );
+ return 0;
+ }
+ // perform verification
+ pNtkRes = Abc_NtkDarMatch( pNtk1, pNtk2, nDist, fVerbose );
+ if ( fDelete1 ) Abc_NtkDelete( pNtk1 );
+ if ( fDelete2 ) Abc_NtkDelete( pNtk2 );
+ }
+ if ( pNtkRes == NULL )
+ {
+ printf( "Matching has failed.\n" );
+ return 1;
+ }
+ // replace the current network
+ Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: match [-D num] [-mv] <file1> <file2>\n" );
+ fprintf( pErr, "\t detects structural similarity using simulation\n" );
+ fprintf( pErr, "\t replaces the current network by the miter of differences\n" );
+ fprintf( pErr, "\t-D num : the distance for extending differences [default = %d]\n", nDist );
+ fprintf( pErr, "\t-m : toggles miter vs. two networks [default = %s]\n", fMiter? "miter": "two networks" );
+ fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
+ 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");
+ fprintf( pErr, "\t if one file is given, uses the current network and the file\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
@@ -17133,8 +18348,9 @@ int Abc_CommandPBAbstraction( Abc_Frame_t * pAbc, int argc, char ** argv )
pNtkRes = Abc_NtkDarPBAbstraction( pNtk, nFramesMax, nConfMax, fDynamic, fExtend, fVerbose );
if ( pNtkRes == NULL )
{
- fprintf( pErr, "Target enlargement has failed.\n" );
- return 1;
+ if ( pNtk->pSeqModel == NULL )
+ printf( "Proof-based abstraction has failed.\n" );
+ return 0;
}
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
@@ -17297,16 +18513,19 @@ int Abc_CommandAbc8Read( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fMapped;
int fTest;
+ int fAlter;
extern void * Ioa_ReadBlif( char * pFileName, int fCheck );
extern void Ioa_WriteBlif( void * p, char * pFileName );
extern Aig_Man_t * Ntl_ManExtract( void * p );
extern void * Ntl_ManExtractNwk( void * p, Aig_Man_t * pAig, Tim_Man_t * pManTime );
+ extern void Ntl_ManPrintStats( void * p );
// set defaults
fMapped = 0;
fTest = 0;
+ fAlter = 0;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "mth" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "mtah" ) ) != EOF )
{
switch ( c )
{
@@ -17316,6 +18535,9 @@ int Abc_CommandAbc8Read( Abc_Frame_t * pAbc, int argc, char ** argv )
case 't':
fTest ^= 1;
break;
+ case 'a':
+ fAlter ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -17334,11 +18556,9 @@ int Abc_CommandAbc8Read( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
fclose( pFile );
-
if ( fTest )
{
extern void Ntl_ManFree( void * p );
- extern void Ntl_ManPrintStats( void * p );
void * pTemp = Ioa_ReadBlif( pFileName, 1 );
if ( pTemp )
{
@@ -17350,11 +18570,26 @@ int Abc_CommandAbc8Read( Abc_Frame_t * pAbc, int argc, char ** argv )
}
Abc_FrameClearDesign();
- pAbc->pAbc8Ntl = Ioa_ReadBlif( pFileName, 1 );
- if ( pAbc->pAbc8Ntl == NULL )
+ if ( !fAlter )
{
- printf( "Abc_CommandAbc8Read(): Reading BLIF has failed.\n" );
- return 1;
+ pAbc->pAbc8Ntl = Ioa_ReadBlif( pFileName, 1 );
+ if ( pAbc->pAbc8Ntl == NULL )
+ {
+ printf( "Abc_CommandAbc8Read(): Reading BLIF has failed.\n" );
+ return 1;
+ }
+ }
+ else
+ {
+ extern void * Nal_ManRead( char * pFileName );
+ pAbc->pAbc8Ntl = NULL;
+// pAbc->pAbc8Ntl = Nal_ManRead( pFileName );
+// Ioa_WriteBlif( pAbc->pAbc8Ntl, "test_boxes.blif" );
+ if ( pAbc->pAbc8Ntl == NULL )
+ {
+ printf( "Abc_CommandAbc8Read(): Reading design has failed.\n" );
+ return 1;
+ }
}
pAbc->pAbc8Aig = Ntl_ManExtract( pAbc->pAbc8Ntl );
if ( pAbc->pAbc8Aig == NULL )
@@ -17371,10 +18606,11 @@ int Abc_CommandAbc8Read( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( stdout, "usage: *r [-mth]\n" );
+ fprintf( stdout, "usage: *r [-mtah]\n" );
fprintf( stdout, "\t reads the design with whiteboxes\n" );
fprintf( stdout, "\t-m : toggle extracting mapped network [default = %s]\n", fMapped? "yes": "no" );
fprintf( stdout, "\t-t : toggle reading in the test mode [default = %s]\n", fTest? "yes": "no" );
+ fprintf( stdout, "\t-a : toggle reading another file type [default = %s]\n", fAlter? "yes": "no" );
fprintf( stdout, "\t-h : print the command usage\n");
return 1;
}
@@ -17468,6 +18704,7 @@ int Abc_CommandAbc8Write( Abc_Frame_t * pAbc, int argc, char ** argv )
char * pFileName;
void * pTemp;
int fAig;
+ int fBlif;
int fCollapsed;
int c;
extern void Ioa_WriteBlif( void * p, char * pFileName );
@@ -17479,15 +18716,19 @@ int Abc_CommandAbc8Write( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
fAig = 0;
+ fBlif = 1;
fCollapsed = 0;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "ach" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "abch" ) ) != EOF )
{
switch ( c )
{
case 'a':
fAig ^= 1;
break;
+ case 'b':
+ fBlif ^= 1;
+ break;
case 'c':
fCollapsed ^= 1;
break;
@@ -17501,29 +18742,38 @@ int Abc_CommandAbc8Write( Abc_Frame_t * pAbc, int argc, char ** argv )
{
printf( "Abc_CommandAbc8Write(): There is no design to write.\n" );
return 1;
- }
+ }
// create the design to write
pFileName = argv[globalUtilOptind];
if ( fAig )
{
if ( fCollapsed )
{
+ extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
pTemp = Ntl_ManCollapseSeq( pAbc->pAbc8Ntl, 0 );
- Saig_ManDumpBlif( pTemp, pFileName );
+ if ( fBlif )
+ Saig_ManDumpBlif( pTemp, pFileName );
+ else
+ Ioa_WriteAiger( pTemp, pFileName, 0, 0 );
Aig_ManStop( pTemp );
}
else
{
if ( pAbc->pAbc8Aig != NULL )
{
- pTemp = Ntl_ManInsertAig( pAbc->pAbc8Ntl, pAbc->pAbc8Aig );
- if ( pTemp == NULL )
+ if ( fBlif )
{
- printf( "Abc_CommandAbc8Write(): Inserting AIG has failed.\n" );
- return 1;
+ pTemp = Ntl_ManInsertAig( pAbc->pAbc8Ntl, pAbc->pAbc8Aig );
+ if ( pTemp == NULL )
+ {
+ printf( "Abc_CommandAbc8Write(): Inserting AIG has failed.\n" );
+ return 1;
+ }
+ Ioa_WriteBlif( pTemp, pFileName );
+ Ntl_ManFree( pTemp );
}
- Ioa_WriteBlif( pTemp, pFileName );
- Ntl_ManFree( pTemp );
+ else
+ Ioa_WriteAiger( pAbc->pAbc8Aig, pFileName, 0, 0 );
}
else
{
@@ -17547,17 +18797,18 @@ int Abc_CommandAbc8Write( Abc_Frame_t * pAbc, int argc, char ** argv )
}
else
{
- pTemp = pAbc->pAbc8Ntl;
printf( "Writing the unmapped netlist.\n" );
+ pTemp = pAbc->pAbc8Ntl;
Ioa_WriteBlif( pTemp, pFileName );
}
}
return 0;
usage:
- fprintf( stdout, "usage: *w [-ach]\n" );
+ fprintf( stdout, "usage: *w [-abch]\n" );
fprintf( stdout, "\t write the design with whiteboxes\n" );
fprintf( stdout, "\t-a : toggle writing mapped network or AIG [default = %s]\n", fAig? "AIG": "mapped" );
+ fprintf( stdout, "\t-b : toggle writing AIG as BLIF or AIGER [default = %s]\n", fBlif? "BLIF": "AIGER" );
fprintf( stdout, "\t-c : toggle writing collapsed sequential AIG [default = %s]\n", fCollapsed? "yes": "no" );
fprintf( stdout, "\t-h : print the command usage\n");
return 1;
@@ -17841,14 +19092,19 @@ int Abc_CommandAbc8Ps( Abc_Frame_t * pAbc, int argc, char ** argv )
int c;
int fSaveBest;
int fDumpResult;
+ int fPower;
+ int fShort;
extern void Ntl_ManPrintStats( void * p );
- extern void Nwk_ManPrintStats( void * p, void * pLutLib, int fSaveBest, int fDumpResult, void * pNtl );
+ extern void Nwk_ManPrintStats( void * p, void * pLutLib, int fSaveBest, int fDumpResult, int fPower, void * pNtl );
+ extern void Nwk_ManPrintStatsShort( void * p, void * pAig, void * pNtk );
// set defaults
fSaveBest = 0;
fDumpResult = 0;
+ fPower = 0;
+ fShort = 1;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "bdh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "bdpsh" ) ) != EOF )
{
switch ( c )
{
@@ -17858,6 +19114,12 @@ int Abc_CommandAbc8Ps( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'd':
fDumpResult ^= 1;
break;
+ case 'p':
+ fPower ^= 1;
+ break;
+ case 's':
+ fShort ^= 1;
+ break;
case 'h':
goto usage;
default:
@@ -17870,6 +19132,11 @@ int Abc_CommandAbc8Ps( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
+ if ( fShort )
+ {
+ Nwk_ManPrintStatsShort( pAbc->pAbc8Ntl, pAbc->pAbc8Aig, pAbc->pAbc8Nwk );
+ return 0;
+ }
// get the input file name
if ( pAbc->pAbc8Ntl )
{
@@ -17889,15 +19156,17 @@ int Abc_CommandAbc8Ps( Abc_Frame_t * pAbc, int argc, char ** argv )
pAbc->pAbc8Lib = If_SetSimpleLutLib( 6 );
}
printf( "MAPPED: " );
- Nwk_ManPrintStats( pAbc->pAbc8Nwk, pAbc->pAbc8Lib, fSaveBest, fDumpResult, pAbc->pAbc8Ntl );
+ Nwk_ManPrintStats( pAbc->pAbc8Nwk, pAbc->pAbc8Lib, fSaveBest, fDumpResult, fPower, pAbc->pAbc8Ntl );
}
return 0;
usage:
- fprintf( stdout, "usage: *ps [-bdh]\n" );
+ fprintf( stdout, "usage: *ps [-bdpsh]\n" );
fprintf( stdout, "\t prints design statistics\n" );
fprintf( stdout, "\t-b : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" );
fprintf( stdout, "\t-d : toggles dumping network into file \"<input_file_name>_dump.blif\" [default = %s]\n", fDumpResult? "yes": "no" );
+ fprintf( stdout, "\t-p : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" );
+ fprintf( stdout, "\t-s : toggles short printing mode [default = %s]\n", fShort? "yes": "no" );
fprintf( stdout, "\t-h : print the command usage\n");
return 1;
}
@@ -17979,7 +19248,7 @@ int Abc_CommandAbc8If( Abc_Frame_t * pAbc, int argc, char ** argv )
Nwk_ManSetIfParsDefault( pPars );
pPars->pLutLib = pAbc->pAbc8Lib;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADEpaflemrstbvh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADEqaflepmrstbvh" ) ) != EOF )
{
switch ( c )
{
@@ -18039,6 +19308,7 @@ int Abc_CommandAbc8If( Abc_Frame_t * pAbc, int argc, char ** argv )
globalUtilOptind++;
if ( pPars->DelayTarget <= 0.0 )
goto usage;
+ break;
case 'E':
if ( globalUtilOptind >= argc )
{
@@ -18050,7 +19320,7 @@ int Abc_CommandAbc8If( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( pPars->Epsilon < 0.0 || pPars->Epsilon > 1.0 )
goto usage;
break;
- case 'p':
+ case 'q':
pPars->fPreprocess ^= 1;
break;
case 'a':
@@ -18068,6 +19338,9 @@ int Abc_CommandAbc8If( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'e':
pPars->fEdge ^= 1;
break;
+ case 'p':
+ pPars->fPower ^= 1;
+ break;
case 'm':
pPars->fCutMin ^= 1;
break;
@@ -18146,7 +19419,7 @@ usage:
sprintf( LutSize, "library" );
else
sprintf( LutSize, "%d", pPars->nLutSize );
- fprintf( stdout, "usage: *if [-KCFA num] [-DE float] [-parlembvh]\n" );
+ fprintf( stdout, "usage: *if [-KCFA num] [-DE float] [-qarlepmbvh]\n" );
fprintf( stdout, "\t performs FPGA technology mapping of the network\n" );
fprintf( stdout, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize );
fprintf( stdout, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
@@ -18154,12 +19427,13 @@ usage:
fprintf( stdout, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters );
fprintf( stdout, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer );
fprintf( stdout, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon );
- fprintf( stdout, "\t-p : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" );
+ fprintf( stdout, "\t-q : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" );
fprintf( stdout, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" );
// fprintf( stdout, "\t-f : toggles one fancy feature [default = %s]\n", pPars->fFancy? "yes": "no" );
fprintf( stdout, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" );
fprintf( stdout, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" );
fprintf( stdout, "\t-e : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" );
+ fprintf( stdout, "\t-p : uses power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" );
fprintf( stdout, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" );
// fprintf( stdout, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" );
// fprintf( stdout, "\t-t : toggles the use of true sequential cuts [default = %s]\n", pPars->fLiftLeaves? "yes": "no" );
@@ -18332,7 +19606,7 @@ int Abc_CommandAbc8Dch( Abc_Frame_t * pAbc, int argc, char ** argv )
pPars->fSynthesis ^= 1;
break;
case 'p':
- pPars->fPolarFlip ^= 1;
+ pPars->fPower ^= 1;
break;
case 't':
pPars->fSimulateTfo ^= 1;
@@ -18370,7 +19644,7 @@ usage:
fprintf( stdout, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit );
fprintf( stdout, "\t-S num : the max number of SAT variables [default = %d]\n", pPars->nSatVarMax );
fprintf( stdout, "\t-s : toggle synthesizing three snapshots [default = %s]\n", pPars->fSynthesis? "yes": "no" );
- fprintf( stdout, "\t-p : toggle alighning polarity of SAT variables [default = %s]\n", pPars->fPolarFlip? "yes": "no" );
+ fprintf( stdout, "\t-p : toggle power-aware rewriting [default = %s]\n", pPars->fPower? "yes": "no" );
fprintf( stdout, "\t-t : toggle simulation of the TFO classes [default = %s]\n", pPars->fSimulateTfo? "yes": "no" );
fprintf( stdout, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" );
fprintf( stdout, "\t-h : print the command usage\n");
@@ -18395,15 +19669,17 @@ int Abc_CommandAbc8DC2( Abc_Frame_t * pAbc, int argc, char ** argv )
int fBalance;
int fUpdateLevel;
int fVerbose;
+ int fPower;
- extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fVerbose );
+ extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose );
// set defaults
fBalance = 1;
fUpdateLevel = 1;
+ fPower = 0;
fVerbose = 0;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "blh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "blpvh" ) ) != EOF )
{
switch ( c )
{
@@ -18413,6 +19689,9 @@ int Abc_CommandAbc8DC2( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'l':
fUpdateLevel ^= 1;
break;
+ case 'p':
+ fPower ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -18429,7 +19708,7 @@ int Abc_CommandAbc8DC2( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// get the input file name
- pAigNew = Dar_ManCompress2( pAbc->pAbc8Aig, fBalance, fUpdateLevel, 1, fVerbose );
+ pAigNew = Dar_ManCompress2( pAbc->pAbc8Aig, fBalance, fUpdateLevel, 1, fPower, fVerbose );
if ( pAigNew == NULL )
{
printf( "Abc_CommandAbc8DC2(): Tranformation of the AIG has failed.\n" );
@@ -18440,10 +19719,11 @@ int Abc_CommandAbc8DC2( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( stdout, "usage: *dc2 [-blvh]\n" );
+ fprintf( stdout, "usage: *dc2 [-blpvh]\n" );
fprintf( stdout, "\t performs AIG-based synthesis without deriving choices\n" );
fprintf( stdout, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" );
fprintf( stdout, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" );
+ fprintf( stdout, "\t-p : toggle power-aware rewriting [default = %s]\n", fPower? "yes": "no" );
fprintf( stdout, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
fprintf( stdout, "\t-h : print the command usage\n");
return 1;
@@ -18526,7 +19806,7 @@ int Abc_CommandAbc8Strash( Abc_Frame_t * pAbc, int argc, char ** argv )
{
printf( "Abc_CommandAbc8Strash(): There is no mapped network to strash.\n" );
return 1;
- }
+ }
pAigNew = Nwk_ManStrash( pAbc->pAbc8Nwk );
if ( pAigNew == NULL )
@@ -18566,7 +19846,7 @@ int Abc_CommandAbc8Mfs( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
Mfx_ParsDefault( pPars );
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCraesvwh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCraespvwh" ) ) != EOF )
{
switch ( c )
{
@@ -18648,6 +19928,9 @@ int Abc_CommandAbc8Mfs( Abc_Frame_t * pAbc, int argc, char ** argv )
case 's':
pPars->fSwapEdge ^= 1;
break;
+ case 'p':
+ pPars->fPower ^= 1;
+ break;
case 'v':
pPars->fVerbose ^= 1;
break;
@@ -18687,7 +19970,7 @@ int Abc_CommandAbc8Mfs( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( stdout, "usage: *mfs [-WFDMLC <num>] [-raesvh]\n" );
+ fprintf( stdout, "usage: *mfs [-WFDMLC <num>] [-raespvh]\n" );
fprintf( stdout, "\t performs don't-care-based optimization of logic networks\n" );
fprintf( stdout, "\t-W <num> : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nWinTfoLevs );
fprintf( stdout, "\t-F <num> : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutsMax );
@@ -18699,6 +19982,7 @@ usage:
fprintf( stdout, "\t-a : toggle minimizing area or area+edges [default = %s]\n", pPars->fArea? "area": "area+edges" );
fprintf( stdout, "\t-e : toggle high-effort resubstitution [default = %s]\n", pPars->fMoreEffort? "yes": "no" );
fprintf( stdout, "\t-s : toggle evaluation of edge swapping [default = %s]\n", pPars->fSwapEdge? "yes": "no" );
+ fprintf( stdout, "\t-p : toggle power-aware optimization [default = %s]\n", pPars->fPower? "yes": "no" );
fprintf( stdout, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" );
fprintf( stdout, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
fprintf( stdout, "\t-h : print the command usage\n");
@@ -19624,7 +20908,7 @@ int Abc_CommandAbc8Scorr( Abc_Frame_t * pAbc, int argc, char ** argv )
// set defaults
Ssw_ManSetDefaultParams( pPars );
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLNSDVMpldvh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLNSDVMpldsvh" ) ) != EOF )
{
switch ( c )
{
@@ -19747,6 +21031,9 @@ int Abc_CommandAbc8Scorr( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'd':
pPars->fDynamic ^= 1;
break;
+ case 's':
+ pPars->fLocalSim ^= 1;
+ break;
case 'v':
pPars->fVerbose ^= 1;
break;
@@ -19800,7 +21087,7 @@ int Abc_CommandAbc8Scorr( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- fprintf( stdout, "usage: *scorr [-PQFCLNSDVM <num>] [-pldvh]\n" );
+ fprintf( stdout, "usage: *scorr [-PQFCLNSDVM <num>] [-pldsvh]\n" );
fprintf( stdout, "\t performs sequential sweep using K-step induction\n" );
fprintf( stdout, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize );
fprintf( stdout, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize );
@@ -19815,6 +21102,7 @@ usage:
fprintf( stdout, "\t-p : toggle alighning polarity of SAT variables [default = %s]\n", pPars->fPolarFlip? "yes": "no" );
fprintf( stdout, "\t-l : toggle latch correspondence only [default = %s]\n", pPars->fLatchCorr? "yes": "no" );
fprintf( stdout, "\t-d : toggle dynamic addition of constraints [default = %s]\n", pPars->fDynamic? "yes": "no" );
+ fprintf( stdout, "\t-s : toggle local simulation in the cone of influence [default = %s]\n", pPars->fLocalSim? "yes": "no" );
fprintf( stdout, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
fprintf( stdout, "\t-h : print the command usage\n");
return 1;
diff --git a/src/base/abci/abc.zip b/src/base/abci/abc.zip
deleted file mode 100644
index 34df9a63..00000000
--- a/src/base/abci/abc.zip
+++ /dev/null
Binary files differ
diff --git a/src/base/abci/abcBidec.c b/src/base/abci/abcBidec.c
index bb114578..01146014 100644
--- a/src/base/abci/abcBidec.c
+++ b/src/base/abci/abcBidec.c
@@ -42,7 +42,7 @@ static inline Hop_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) { return Hop_NotCo
SeeAlso []
***********************************************************************/
-Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare )
+Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb )
{
unsigned * pTruth;
Bdc_Fun_t * pFunc;
@@ -52,8 +52,33 @@ Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pR
pTruth = Hop_ManConvertAigToTruth( pHop, Hop_Regular(pRoot), nVars, vTruth, 0 );
if ( Hop_IsComplement(pRoot) )
Extra_TruthNot( pTruth, pTruth, nVars );
- // decompose truth table
- Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 );
+ // perform power-aware decomposition
+ if ( dProb >= 0.0 )
+ {
+ float Prob = (float)2.0 * dProb * (1.0 - dProb);
+ assert( Prob >= 0.0 && Prob <= 0.5 );
+ if ( Prob >= 0.4 )
+ {
+ Extra_TruthNot( puCare, puCare, nVars );
+ if ( dProb > 0.5 ) // more 1s than 0s
+ Extra_TruthOr( pTruth, pTruth, puCare, nVars );
+ else
+ Extra_TruthSharp( pTruth, pTruth, puCare, nVars );
+ Extra_TruthNot( puCare, puCare, nVars );
+ // decompose truth table
+ Bdc_ManDecompose( p, pTruth, NULL, nVars, NULL, 1000 );
+ }
+ else
+ {
+ // decompose truth table
+ Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 );
+ }
+ }
+ else
+ {
+ // decompose truth table
+ Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 );
+ }
// convert back into HOP
Bdc_FuncSetCopy( Bdc_ManFunc( p, 0 ), Hop_ManConst1( pHop ) );
for ( i = 0; i < nVars; i++ )
@@ -104,7 +129,7 @@ void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose )
if ( Abc_ObjFaninNum(pObj) > 15 )
continue;
nNodes1 = Hop_DagSize(pObj->pData);
- pObj->pData = Abc_NodeIfNodeResyn( p, pNtk->pManFunc, pObj->pData, Abc_ObjFaninNum(pObj), vTruth, NULL );
+ pObj->pData = Abc_NodeIfNodeResyn( p, pNtk->pManFunc, pObj->pData, Abc_ObjFaninNum(pObj), vTruth, NULL, -1.0 );
nNodes2 = Hop_DagSize(pObj->pData);
nGainTotal += nNodes1 - nNodes2;
}
diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c
index d38f62d0..1c7459eb 100644
--- a/src/base/abci/abcCut.c
+++ b/src/base/abci/abcCut.c
@@ -39,6 +39,74 @@ static int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p );
/**Function*************************************************************
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCutsSubtractFanunt( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj, * pFan0, * pFan1, * pFanC;
+ int i, Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( !Abc_NodeIsMuxType(pObj) )
+ continue;
+ pFanC = Abc_NodeRecognizeMux( pObj, &pFan1, &pFan0 );
+ pFanC = Abc_ObjRegular(pFanC);
+ pFan0 = Abc_ObjRegular(pFan0);
+ assert( pFanC->vFanouts.nSize > 1 );
+ pFanC->vFanouts.nSize--;
+ Counter++;
+ if ( Abc_NodeIsExorType(pObj) )
+ {
+ assert( pFan0->vFanouts.nSize > 1 );
+ pFan0->vFanouts.nSize--;
+ Counter++;
+ }
+ }
+ printf("Substracted %d fanouts\n", Counter );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCutsAddFanunt( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj, * pFan0, * pFan1, * pFanC;
+ int i, Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( !Abc_NodeIsMuxType(pObj) )
+ continue;
+ pFanC = Abc_NodeRecognizeMux( pObj, &pFan1, &pFan0 );
+ pFanC = Abc_ObjRegular(pFanC);
+ pFan0 = Abc_ObjRegular(pFan0);
+ pFanC->vFanouts.nSize++;
+ Counter++;
+ if ( Abc_NodeIsExorType(pObj) )
+ {
+ pFan0->vFanouts.nSize++;
+ Counter++;
+ }
+ }
+ printf("Added %d fanouts\n", Counter );
+}
+
+/**Function*************************************************************
+
Synopsis [Computes the cuts for the network.]
Description []
@@ -61,6 +129,9 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk );
extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk );
+ if ( pParams->fAdjust )
+ Abc_NtkCutsSubtractFanunt( pNtk );
+
nTotal = nGood = nEqual = 0;
assert( Abc_NtkIsStrash(pNtk) );
@@ -118,7 +189,7 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
Vec_PtrFree( vNodes );
Vec_IntFree( vChoices );
Cut_ManPrintStats( p );
-PRT( "TOTAL ", clock() - clk );
+PRT( "TOTAL", clock() - clk );
printf( "Area = %d.\n", Abc_NtkComputeArea( pNtk, p ) );
//Abc_NtkPrintCuts( p, pNtk, 0 );
// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk );
@@ -126,6 +197,8 @@ PRT( "TOTAL ", clock() - clk );
// temporary printout of stats
if ( nTotal )
printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal );
+ if ( pParams->fAdjust )
+ Abc_NtkCutsAddFanunt( pNtk );
return p;
}
diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c
index dcc7f4c1..9dc10d84 100644
--- a/src/base/abci/abcDar.c
+++ b/src/base/abci/abcDar.c
@@ -29,6 +29,8 @@
#include "dch.h"
#include "ssw.h"
#include "cgt.h"
+#include "cec.h"
+#include "fsim.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -126,7 +128,7 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters )
if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) )
pObjNew->pFanin0 = Aig_Not(pObjNew->pFanin0);
// remove dangling nodes
- nNodes = Aig_ManCleanup( pMan );
+ nNodes = (Abc_NtkGetChoiceNum(pNtk) == 0)? Aig_ManCleanup( pMan ) : 0;
if ( !fExors && nNodes )
printf( "Abc_NtkToDar(): Unexpected %d dangling nodes when converting to AIG!\n", nNodes );
//Aig_ManDumpVerilog( pMan, "test.v" );
@@ -153,6 +155,63 @@ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters )
Synopsis [Converts the network from the AIG manager into ABC.]
+ Description [Assumes that registers are ordered after PIs/POs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Abc_NtkToDarChoices( Abc_Ntk_t * pNtk )
+{
+ Aig_Man_t * pMan;
+ Abc_Obj_t * pObj, * pPrev, * pFanin;
+ Vec_Ptr_t * vNodes;
+ int i;
+ vNodes = Abc_AigDfs( pNtk, 0, 0 );
+ // create the manager
+ pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 );
+ pMan->pName = Extra_UtilStrsav( pNtk->pName );
+ if ( Abc_NtkGetChoiceNum(pNtk) )
+ {
+ pMan->pEquivs = ALLOC( Aig_Obj_t *, Abc_NtkObjNum(pNtk) );
+ memset( pMan->pEquivs, 0, sizeof(Aig_Obj_t *) * Abc_NtkObjNum(pNtk) );
+ }
+ // transfer the pointers to the basic nodes
+ Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan);
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreatePi(pMan);
+ // perform the conversion of the internal nodes (assumes DFS ordering)
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) );
+// printf( "%d->%d ", pObj->Id, ((Aig_Obj_t *)pObj->pCopy)->Id );
+ if ( Abc_AigNodeIsChoice( pObj ) )
+ {
+ for ( pPrev = pObj, pFanin = pObj->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData )
+ Aig_ObjSetEquiv( pMan, (Aig_Obj_t *)pPrev->pCopy, (Aig_Obj_t *)pFanin->pCopy );
+// Aig_ManCreateChoice( pIfMan, (Aig_Obj_t *)pNode->pCopy );
+ }
+ }
+ Vec_PtrFree( vNodes );
+ // create the POs
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ Aig_ObjCreatePo( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj) );
+ // complement the 1-valued registers
+ Aig_ManSetRegNum( pMan, 0 );
+ if ( !Aig_ManCheck( pMan ) )
+ {
+ printf( "Abc_NtkToDar: AIG check has failed.\n" );
+ Aig_ManStop( pMan );
+ return NULL;
+ }
+ return pMan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the network from the AIG manager into ABC.]
+
Description []
SideEffects []
@@ -351,6 +410,9 @@ Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan )
assert( pMan->nAsserts == 0 );
// perform strashing
pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ // duplicate the name and the spec
+// pNtkNew->pName = Extra_UtilStrsav(pMan->pName);
+// pNtkNew->pSpec = Extra_UtilStrsav(pMan->pSpec);
Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew);
// create PIs
Aig_ManForEachPiSeq( pMan, pObj, i )
@@ -771,7 +833,7 @@ clk = clock();
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fVerbose )
+Abc_Ntk_t * Abc_NtkDC2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose )
{
Aig_Man_t * pMan, * pTemp;
Abc_Ntk_t * pNtkAig;
@@ -783,7 +845,7 @@ Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel,
// Aig_ManPrintStats( pMan );
clk = clock();
- pMan = Dar_ManCompress2( pTemp = pMan, fBalance, fUpdateLevel, fFanout, fVerbose );
+ pMan = Dar_ManCompress2( pTemp = pMan, fBalance, fUpdateLevel, fFanout, fPower, fVerbose );
Aig_ManStop( pTemp );
//PRT( "time", clock() - clk );
@@ -832,7 +894,7 @@ Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, in
***********************************************************************/
Abc_Ntk_t * Abc_NtkDch( Abc_Ntk_t * pNtk, Dch_Pars_t * pPars )
{
- extern Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose );
+ extern Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose );
Vec_Ptr_t * vAigs;
Aig_Man_t * pMan, * pTemp;
@@ -845,8 +907,8 @@ Abc_Ntk_t * Abc_NtkDch( Abc_Ntk_t * pNtk, Dch_Pars_t * pPars )
clk = clock();
if ( pPars->fSynthesis )
{
-// vAigs = Dar_ManChoiceSynthesis( pMan, 1, 1, pPars->fVerbose );
- vAigs = Dar_ManChoiceSynthesis( pMan, 1, 1, 0 );
+// vAigs = Dar_ManChoiceSynthesis( pMan, 1, 1, pPars->fPower, pPars->fVerbose );
+ vAigs = Dar_ManChoiceSynthesis( pMan, 1, 1, pPars->fPower, 0 );
Aig_ManStop( pMan );
}
else
@@ -1191,6 +1253,81 @@ PRT( "Time", clock() - clkTotal );
SeeAlso []
***********************************************************************/
+int Abc_NtkDarCec2( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Cec_ParCec_t * pPars )
+{
+ Aig_Man_t * pMan1, * pMan2 = NULL;
+ int RetValue, clkTotal = clock();
+ if ( pNtk2 )
+ {
+ if ( Abc_NtkPiNum(pNtk1) != Abc_NtkPiNum(pNtk2) )
+ {
+ printf( "Networks have different number of PIs.\n" );
+ return -1;
+ }
+ if ( Abc_NtkPoNum(pNtk1) != Abc_NtkPoNum(pNtk2) )
+ {
+ printf( "Networks have different number of POs.\n" );
+ return -1;
+ }
+ }
+ if ( pNtk1 )
+ {
+ pMan1 = Abc_NtkToDar( pNtk1, 0, 0 );
+ if ( pMan1 == NULL )
+ {
+ printf( "Converting into AIG has failed.\n" );
+ return -1;
+ }
+ }
+ if ( pNtk2 )
+ {
+ pMan2 = Abc_NtkToDar( pNtk2, 0, 0 );
+ if ( pMan2 == NULL )
+ {
+ Aig_ManStop( pMan1 );
+ printf( "Converting into AIG has failed.\n" );
+ return -1;
+ }
+ }
+ // perform verification
+ RetValue = Cec_Solve( pMan1, pMan2, pPars );
+ // transfer model if given
+ pNtk1->pModel = pMan1->pData, pMan1->pData = NULL;
+ Aig_ManStop( pMan1 );
+ if ( pMan2 )
+ Aig_ManStop( pMan2 );
+
+ // report the miter
+ if ( RetValue == 1 )
+ {
+ printf( "Networks are equivalent. " );
+PRT( "Time", clock() - clkTotal );
+ }
+ else if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT. " );
+PRT( "Time", clock() - clkTotal );
+ }
+ else
+ {
+ printf( "Networks are UNDECIDED. " );
+PRT( "Time", clock() - clkTotal );
+ }
+ fflush( stdout );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, Fra_Ssw_t * pPars )
{
Fraig_Params_t Params;
@@ -1282,7 +1419,7 @@ void Abc_NtkPrintLatchEquivClasses( Abc_Ntk_t * pNtk, Aig_Man_t * pAig )
if ( pRepr == NULL )
{
// printf("Nothing equivalent to flop %s\n", pFlopName);
- p_irrelevant[i] = true;
+// p_irrelevant[i] = true;
continue;
}
@@ -1600,7 +1737,7 @@ PRT( "Time", clock() - clk );
***********************************************************************/
int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk )
{
- Aig_Man_t * pMan, * pPart0, * pPart1, * pMiter;
+ Aig_Man_t * pMan, * pPart0, * pPart1;//, * pMiter;
// derive the AIG manager
pMan = Abc_NtkToDar( pNtk, 0, 1 );
if ( pMan == NULL )
@@ -1608,7 +1745,8 @@ int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk )
printf( "Converting network into AIG has failed.\n" );
return 0;
}
- if ( !Saig_ManDemiterSimple( pMan, &pPart0, &pPart1 ) )
+// if ( !Saig_ManDemiterSimple( pMan, &pPart0, &pPart1 ) )
+ if ( !Saig_ManDemiterSimpleDiff( pMan, &pPart0, &pPart1 ) )
{
printf( "Demitering has failed.\n" );
return 0;
@@ -1617,10 +1755,10 @@ int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk )
Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL );
printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" );
// create two-level miter
- pMiter = Saig_ManCreateMiterTwo( pPart0, pPart1, 2 );
- Aig_ManDumpBlif( pMiter, "miter01.blif", NULL, NULL );
- Aig_ManStop( pMiter );
- printf( "The new miter is written into file \"%s\".\n", "miter01.blif" );
+// pMiter = Saig_ManCreateMiterTwo( pPart0, pPart1, 2 );
+// Aig_ManDumpBlif( pMiter, "miter01.blif", NULL, NULL );
+// Aig_ManStop( pMiter );
+// printf( "The new miter is written into file \"%s\".\n", "miter01.blif" );
Aig_ManStop( pPart0 );
Aig_ManStop( pPart1 );
@@ -1761,7 +1899,7 @@ int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Fra_Sec_t * pSecPar )
return 1;
}
- // commented out because something became non-inductive
+ // commented out because sometimes the problem became non-inductive
/*
// preprocess the miter by fraiging it
// (note that for each functional class, fraiging leaves one representative;
@@ -1805,6 +1943,146 @@ int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Fra_Sec_t * pSecPar )
return RetValue;
}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD-based reachability analysis.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarAbSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fVerbose )
+{
+ Aig_Man_t * pMan1, * pMan2 = NULL;
+ int RetValue;
+ // derive AIG manager
+ pMan1 = Abc_NtkToDar( pNtk1, 0, 1 );
+ if ( pMan1 == NULL )
+ {
+ printf( "Converting miter into AIG has failed.\n" );
+ return -1;
+ }
+ assert( Aig_ManRegNum(pMan1) > 0 );
+ // derive AIG manager
+ if ( pNtk2 )
+ {
+ pMan2 = Abc_NtkToDar( pNtk2, 0, 1 );
+ if ( pMan2 == NULL )
+ {
+ printf( "Converting miter into AIG has failed.\n" );
+ return -1;
+ }
+ assert( Aig_ManRegNum(pMan2) > 0 );
+ }
+
+ // perform verification
+ RetValue = Ssw_SecSpecialMiter( pMan1, pMan2, nFrames, fVerbose );
+ Aig_ManStop( pMan1 );
+ if ( pMan2 )
+ Aig_ManStop( pMan2 );
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkDarSimSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Ssw_Pars_t * pPars )
+{
+ Aig_Man_t * pMan1, * pMan2 = NULL;
+ int RetValue;
+ // derive AIG manager
+ pMan1 = Abc_NtkToDar( pNtk1, 0, 1 );
+ if ( pMan1 == NULL )
+ {
+ printf( "Converting miter into AIG has failed.\n" );
+ return -1;
+ }
+ assert( Aig_ManRegNum(pMan1) > 0 );
+ // derive AIG manager
+ if ( pNtk2 )
+ {
+ pMan2 = Abc_NtkToDar( pNtk2, 0, 1 );
+ if ( pMan2 == NULL )
+ {
+ printf( "Converting miter into AIG has failed.\n" );
+ return -1;
+ }
+ assert( Aig_ManRegNum(pMan2) > 0 );
+ }
+
+ // perform verification
+ RetValue = Ssw_SecWithSimilarity( pMan1, pMan2, pPars );
+ Aig_ManStop( pMan1 );
+ if ( pMan2 )
+ Aig_ManStop( pMan2 );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarMatch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nDist, int fVerbose )
+{
+ extern Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter );
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan1, * pMan2 = NULL, * pManRes;
+ Vec_Int_t * vPairs;
+ assert( Abc_NtkIsStrash(pNtk1) );
+ // derive AIG manager
+ pMan1 = Abc_NtkToDar( pNtk1, 0, 1 );
+ if ( pMan1 == NULL )
+ {
+ printf( "Converting miter into AIG has failed.\n" );
+ return NULL;
+ }
+ assert( Aig_ManRegNum(pMan1) > 0 );
+ // derive AIG manager
+ if ( pNtk2 )
+ {
+ pMan2 = Abc_NtkToDar( pNtk2, 0, 1 );
+ if ( pMan2 == NULL )
+ {
+ printf( "Converting miter into AIG has failed.\n" );
+ return NULL;
+ }
+ assert( Aig_ManRegNum(pMan2) > 0 );
+ }
+
+ // perform verification
+ vPairs = Saig_StrSimPerformMatching( pMan1, pMan2, nDist, 1, &pManRes );
+ pNtkAig = Abc_NtkFromAigPhase( pManRes );
+ if ( vPairs )
+ Vec_IntFree( vPairs );
+ if ( pManRes )
+ Aig_ManStop( pManRes );
+ Aig_ManStop( pMan1 );
+ if ( pMan2 )
+ Aig_ManStop( pMan2 );
+ return pNtkAig;
+}
+
+
/**Function*************************************************************
Synopsis [Gives the current ABC network to AIG manager for processing.]
@@ -2049,33 +2327,140 @@ Abc_Ntk_t * Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk, int nIters, int nSteps, int
SeeAlso []
***********************************************************************/
-int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int fVerbose )
+int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int TimeOut, int fNew, int fComb, int fMiter, int fVerbose )
{
+ extern int Cec_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose );
+ extern int Raig_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose );
Aig_Man_t * pMan;
- Fra_Sml_t * pSml;
Fra_Cex_t * pCex;
- int RetValue, clk = clock();
+ int status, RetValue, clk = clock();
pMan = Abc_NtkToDar( pNtk, 0, 1 );
- pSml = Fra_SmlSimulateSeq( pMan, 0, nFrames, nWords );
- if ( pSml->fNonConstOut )
+ if ( fComb || Abc_NtkLatchNum(pNtk) == 0 )
{
- pCex = Fra_SmlGetCounterExample( pSml );
- if ( pCex )
- printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ",
+ if ( Cec_ManSimulate( pMan, nWords, nFrames, TimeOut, fMiter, fVerbose ) )
+ {
+ pCex = pMan->pSeqModel;
+ if ( pCex )
+ {
+ printf( "Simulation iterated %d times with %d words asserted output %d in frame %d. ",
nFrames, nWords, pCex->iPo, pCex->iFrame );
- FREE( pNtk->pModel );
- FREE( pNtk->pSeqModel );
- pNtk->pSeqModel = pCex;
- RetValue = 1;
+ status = Ssw_SmlRunCounterExample( pMan, (Ssw_Cex_t *)pCex );
+ if ( status == 0 )
+ printf( "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" );
+ }
+ FREE( pNtk->pModel );
+ FREE( pNtk->pSeqModel );
+ pNtk->pSeqModel = pCex;
+ RetValue = 1;
+ }
+ else
+ {
+ RetValue = 0;
+ printf( "Simulation iterated %d times with %d words did not assert the outputs. ",
+ nFrames, nWords );
+ }
+ }
+ else if ( fNew )
+ {
+/*
+ if ( Raig_ManSimulate( pMan, nWords, nFrames, TimeOut, fVerbose ) )
+ {
+ if ( (pCex = pMan->pSeqModel) )
+ {
+ printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ",
+ nFrames, nWords, pCex->iPo, pCex->iFrame );
+ status = Ssw_SmlRunCounterExample( pMan, (Ssw_Cex_t *)pCex );
+ if ( status == 0 )
+ printf( "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" );
+ }
+ FREE( pNtk->pModel );
+ FREE( pNtk->pSeqModel );
+ pNtk->pSeqModel = pCex; pMan->pSeqModel = NULL;
+ RetValue = 1;
+ }
+ else
+ {
+ RetValue = 0;
+ printf( "Simulation of %d frames with %d words did not assert the outputs. ",
+ nFrames, nWords );
+ }
+*/
+ Fsim_ParSim_t Pars, * pPars = &Pars;
+ Fsim_ManSetDefaultParamsSim( pPars );
+ pPars->nWords = nWords;
+ pPars->nIters = nFrames;
+ pPars->TimeLimit = TimeOut;
+ pPars->fCheckMiter = fMiter;
+ pPars->fVerbose = fVerbose;
+ if ( Fsim_ManSimulate( pMan, pPars ) )
+ {
+ if ( (pCex = pMan->pSeqModel) )
+ {
+ printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ",
+ nFrames, nWords, pCex->iPo, pCex->iFrame );
+ status = Ssw_SmlRunCounterExample( pMan, (Ssw_Cex_t *)pCex );
+ if ( status == 0 )
+ printf( "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" );
+ }
+ FREE( pNtk->pModel );
+ FREE( pNtk->pSeqModel );
+ pNtk->pSeqModel = pCex; pMan->pSeqModel = NULL;
+ RetValue = 1;
+ }
+ else
+ {
+ RetValue = 0;
+ printf( "Simulation of %d frames with %d words did not assert the outputs. ",
+ nFrames, nWords );
+ }
}
else
{
- RetValue = 0;
- printf( "Simulation of %d frames with %d words did not assert the outputs. ",
- nFrames, nWords );
+/*
+ Fra_Sml_t * pSml;
+ pSml = Fra_SmlSimulateSeq( pMan, 0, nFrames, nWords );
+ if ( pSml->fNonConstOut )
+ {
+ pCex = Fra_SmlGetCounterExample( pSml );
+ if ( pCex )
+ printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ",
+ nFrames, nWords, pCex->iPo, pCex->iFrame );
+ FREE( pNtk->pModel );
+ FREE( pNtk->pSeqModel );
+ pNtk->pSeqModel = pCex;
+ RetValue = 1;
+ }
+ else
+ {
+ RetValue = 0;
+ printf( "Simulation of %d frames with %d words did not assert the outputs. ",
+ nFrames, nWords );
+ }
+ Fra_SmlStop( pSml );
+*/
+ if ( Raig_ManSimulate( pMan, nWords, nFrames, TimeOut, fMiter, fVerbose ) )
+ {
+ if ( (pCex = pMan->pSeqModel) )
+ {
+ printf( "Simulation of %d frames with %d words asserted output %d in frame %d. ",
+ nFrames, nWords, pCex->iPo, pCex->iFrame );
+ status = Ssw_SmlRunCounterExample( pMan, (Ssw_Cex_t *)pCex );
+ if ( status == 0 )
+ printf( "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" );
+ }
+ FREE( pNtk->pModel );
+ FREE( pNtk->pSeqModel );
+ pNtk->pSeqModel = pCex; pMan->pSeqModel = NULL;
+ RetValue = 1;
+ }
+ else
+ {
+ RetValue = 0;
+ printf( "Simulation of %d frames with %d words did not assert the outputs. ",
+ nFrames, nWords );
+ }
}
PRT( "Time", clock() - clk );
- Fra_SmlStop( pSml );
Aig_ManStop( pMan );
return RetValue;
}
@@ -2200,14 +2585,20 @@ Abc_Ntk_t * Abc_NtkDarPBAbstraction( Abc_Ntk_t * pNtk, int nFramesMax, int nConf
return NULL;
Aig_ManSetRegNum( pMan, pMan->nRegs );
- pMan = Saig_ManProofAbstraction( pTemp = pMan, nFramesMax, nConfMax, fDynamic, fExtend, fVerbose );
+ pMan = Saig_ManProofAbstraction( pTemp = pMan, nFramesMax, nConfMax, fDynamic, fExtend, 0, fVerbose );
+ if ( pTemp->pSeqModel )
+ {
+ FREE( pNtk->pModel );
+ FREE( pNtk->pSeqModel );
+ pNtk->pSeqModel = pTemp->pSeqModel; pTemp->pSeqModel = NULL;
+ }
Aig_ManStop( pTemp );
if ( pMan == NULL )
return NULL;
pNtkAig = Abc_NtkFromAigPhase( pMan );
- pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
- pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+// pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
+// pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
Aig_ManStop( pMan );
return pNtkAig;
}
@@ -2480,8 +2871,8 @@ Abc_Ntk_t * Abc_NtkPhaseAbstract( Abc_Ntk_t * pNtk, int nFrames, int fIgnore, in
if ( pMan == NULL )
return NULL;
pNtkAig = Abc_NtkFromAigPhase( pMan );
- pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
- pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+// pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
+// pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
Aig_ManStop( pMan );
return pNtkAig;
}
@@ -2545,8 +2936,8 @@ Abc_Ntk_t * Abc_NtkDarSynch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nWords, i
if ( pMan == NULL )
return NULL;
pNtkAig = Abc_NtkFromAigPhase( pMan );
- pNtkAig->pName = Extra_UtilStrsav("miter");
- pNtkAig->pSpec = NULL;
+// pNtkAig->pName = Extra_UtilStrsav("miter");
+// pNtkAig->pSpec = NULL;
Aig_ManStop( pMan );
return pNtkAig;
}
@@ -2600,6 +2991,129 @@ Abc_Ntk_t * Abc_NtkDarClockGate( Abc_Ntk_t * pNtk, Abc_Ntk_t * pCare, Cgt_Par_t
SeeAlso []
***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarExtWin( Abc_Ntk_t * pNtk, int nObjId, int nDist, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan1, * pMan;
+ Aig_Obj_t * pObj;
+ pMan1 = Abc_NtkToDar( pNtk, 0, 1 );
+ if ( pMan1 == NULL )
+ return NULL;
+ if ( nObjId == -1 )
+ {
+ pObj = Saig_ManFindPivot( pMan1 );
+ printf( "Selected object %d as a window pivot.\n", pObj->Id );
+ }
+ else
+ {
+ if ( nObjId >= Aig_ManObjNumMax(pMan1) )
+ {
+ Aig_ManStop( pMan1 );
+ printf( "The ID is too large.\n" );
+ return NULL;
+ }
+ pObj = Aig_ManObj( pMan1, nObjId );
+ if ( pObj == NULL )
+ {
+ Aig_ManStop( pMan1 );
+ printf( "Object with ID %d does not exist.\n", nObjId );
+ return NULL;
+ }
+ if ( !Saig_ObjIsLo(pMan1, pObj) && !Aig_ObjIsNode(pObj) )
+ {
+ Aig_ManStop( pMan1 );
+ printf( "Object with ID %d is not a node or reg output.\n", nObjId );
+ return NULL;
+ }
+ }
+ pMan = Saig_ManWindowExtract( pMan1, pObj, nDist );
+ Aig_ManStop( pMan1 );
+ if ( pMan == NULL )
+ return NULL;
+ pNtkAig = Abc_NtkFromAigPhase( pMan );
+ pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
+ pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs phase abstraction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarInsWin( Abc_Ntk_t * pNtk, Abc_Ntk_t * pCare, int nObjId, int nDist, int fVerbose )
+{
+ Abc_Ntk_t * pNtkAig;
+ Aig_Man_t * pMan1, * pMan2 = NULL, * pMan;
+ Aig_Obj_t * pObj;
+ pMan1 = Abc_NtkToDar( pNtk, 0, 1 );
+ if ( pMan1 == NULL )
+ return NULL;
+ if ( nObjId == -1 )
+ {
+ pObj = Saig_ManFindPivot( pMan1 );
+ printf( "Selected object %d as a window pivot.\n", pObj->Id );
+ }
+ else
+ {
+ if ( nObjId >= Aig_ManObjNumMax(pMan1) )
+ {
+ Aig_ManStop( pMan1 );
+ printf( "The ID is too large.\n" );
+ return NULL;
+ }
+ pObj = Aig_ManObj( pMan1, nObjId );
+ if ( pObj == NULL )
+ {
+ Aig_ManStop( pMan1 );
+ printf( "Object with ID %d does not exist.\n", nObjId );
+ return NULL;
+ }
+ if ( !Saig_ObjIsLo(pMan1, pObj) && !Aig_ObjIsNode(pObj) )
+ {
+ Aig_ManStop( pMan1 );
+ printf( "Object with ID %d is not a node or reg output.\n", nObjId );
+ return NULL;
+ }
+ }
+ if ( pCare )
+ {
+ pMan2 = Abc_NtkToDar( pCare, 0, 0 );
+ if ( pMan2 == NULL )
+ {
+ Aig_ManStop( pMan1 );
+ return NULL;
+ }
+ }
+ pMan = Saig_ManWindowInsert( pMan1, pObj, nDist, pMan2 );
+ Aig_ManStop( pMan1 );
+ if ( pMan2 )
+ Aig_ManStop( pMan2 );
+ if ( pMan == NULL )
+ return NULL;
+ pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan );
+ Aig_ManStop( pMan );
+ return pNtkAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs phase abstraction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
Abc_Ntk_t * Abc_NtkDarFrames( Abc_Ntk_t * pNtk, int nPrefix, int nFrames, int fInit, int fVerbose )
{
Abc_Ntk_t * pNtkAig;
@@ -2680,6 +3194,112 @@ void Abc_NtkDarReach( Abc_Ntk_t * pNtk, int nBddMax, int nIterMax, int fPartitio
Aig_ManStop( pMan );
}
+#include "amap.h"
+#include "mio.h"
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Amap_ManProduceNetwork( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMapping )
+{
+ extern void * Abc_FrameReadLibGen();
+ Mio_Library_t * pLib = Abc_FrameReadLibGen();
+ Amap_Out_t * pRes;
+ Vec_Ptr_t * vNodesNew;
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pNodeNew, * pFaninNew;
+ int i, k, iPis, iPos, nDupGates;
+ // make sure gates exist in the current library
+ Vec_PtrForEachEntry( vMapping, pRes, i )
+ if ( pRes->pName && Mio_LibraryReadGateByName( pLib, pRes->pName ) == NULL )
+ {
+ printf( "Current library does not contain gate \"%s\".\n", pRes->pName );
+ return NULL;
+ }
+ // create the network
+ pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP );
+ pNtkNew->pManFunc = pLib;
+ iPis = iPos = 0;
+ vNodesNew = Vec_PtrAlloc( Vec_PtrSize(vMapping) );
+ Vec_PtrForEachEntry( vMapping, pRes, i )
+ {
+ if ( pRes->Type == -1 )
+ pNodeNew = Abc_NtkCi( pNtkNew, iPis++ );
+ else if ( pRes->Type == 1 )
+ pNodeNew = Abc_NtkCo( pNtkNew, iPos++ );
+ else
+ {
+ pNodeNew = Abc_NtkCreateNode( pNtkNew );
+ pNodeNew->pData = Mio_LibraryReadGateByName( pLib, pRes->pName );
+ }
+ for ( k = 0; k < pRes->nFans; k++ )
+ {
+ pFaninNew = Vec_PtrEntry( vNodesNew, pRes->pFans[k] );
+ Abc_ObjAddFanin( pNodeNew, pFaninNew );
+ }
+ Vec_PtrPush( vNodesNew, pNodeNew );
+ }
+ Vec_PtrFree( vNodesNew );
+ assert( iPis == Abc_NtkCiNum(pNtkNew) );
+ assert( iPos == Abc_NtkCoNum(pNtkNew) );
+ // decouple the PO driver nodes to reduce the number of levels
+ nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
+// if ( nDupGates && Map_ManReadVerbose(pMan) )
+// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Gives the current ABC network to AIG manager for processing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkDarAmap( Abc_Ntk_t * pNtk, Amap_Par_t * pPars )
+{
+ Vec_Ptr_t * vMapping;
+ Abc_Ntk_t * pNtkAig = NULL;
+ Aig_Man_t * pMan;
+ Aig_MmFlex_t * pMem;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // convert to the AIG manager
+ pMan = Abc_NtkToDarChoices( pNtk );
+ if ( pMan == NULL )
+ return NULL;
+
+ // perform computation
+ vMapping = Amap_ManTest( pMan, pPars );
+ Aig_ManStop( pMan );
+ if ( vMapping == NULL )
+ return NULL;
+ pMem = Vec_PtrPop( vMapping );
+ pNtkAig = Amap_ManProduceNetwork( pNtk, vMapping );
+ Aig_MmFlexStop( pMem, 0 );
+ Vec_PtrFree( vMapping );
+
+ // make sure everything is okay
+ if ( pNtkAig && !Abc_NtkCheck( pNtkAig ) )
+ {
+ printf( "Abc_NtkDar: The network check has failed.\n" );
+ Abc_NtkDelete( pNtkAig );
+ return NULL;
+ }
+ return pNtkAig;
+}
/**Function*************************************************************
@@ -2694,9 +3314,10 @@ void Abc_NtkDarReach( Abc_Ntk_t * pNtk, int nBddMax, int nIterMax, int fPartitio
***********************************************************************/
void Abc_NtkDarTest( Abc_Ntk_t * pNtk )
{
-// extern Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig );
-
- Aig_Man_t * pMan;//, * pTemp;
+ extern void Fsim_ManTest( Aig_Man_t * pAig );
+ extern Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter );
+// Vec_Int_t * vPairs;
+ Aig_Man_t * pMan;//, * pMan2;//, * pTemp;
assert( Abc_NtkIsStrash(pNtk) );
pMan = Abc_NtkToDar( pNtk, 0, 1 );
if ( pMan == NULL )
@@ -2714,9 +3335,21 @@ Aig_ManPrintStats( pMan );
pTemp = Ssw_SignalCorrespondeceTestPairs( pMan );
Aig_ManStop( pTemp );
*/
- Ssw_SecSpecialMiter( pMan, 1 );
+/*
+// Ssw_SecSpecialMiter( pMan, NULL, 2, 1 );
+ pMan2 = Aig_ManDupSimple(pMan);
+ vPairs = Saig_StrSimPerformMatching( pMan, pMan2, 0, 1, NULL );
+ Vec_IntFree( vPairs );
Aig_ManStop( pMan );
+ Aig_ManStop( pMan2 );
+*/
+
+// Saig_MvManSimulate( pMan, 1 );
+
+ Fsim_ManTest( pMan );
+ Aig_ManStop( pMan );
+
}
/**Function*************************************************************
@@ -2732,6 +3365,8 @@ Aig_ManPrintStats( pMan );
***********************************************************************/
Abc_Ntk_t * Abc_NtkDarTestNtk( Abc_Ntk_t * pNtk )
{
+ extern Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter );
+
/*
extern Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig );
@@ -2760,9 +3395,16 @@ Abc_Ntk_t * Abc_NtkDarTestNtk( Abc_Ntk_t * pNtk )
pMan = Abc_NtkToDar( pNtk, 0, 1 );
if ( pMan == NULL )
return NULL;
+/*
+ Aig_ManSetRegNum( pMan, pMan->nRegs );
+ pMan = Saig_ManProofAbstraction( pTemp = pMan, 5, 10000, 0, 0, 0, 1 );
+ Aig_ManStop( pTemp );
+ if ( pMan == NULL )
+ return NULL;
+*/
Aig_ManSetRegNum( pMan, pMan->nRegs );
- pMan = Saig_ManProofAbstraction( pTemp = pMan, 5, 10000, 0, 0, 1 );
+ pMan = Saig_ManDualRail( pTemp = pMan, 1 );
Aig_ManStop( pTemp );
if ( pMan == NULL )
return NULL;
diff --git a/src/base/abci/abcDelay.c b/src/base/abci/abcDelay.c
index 91f175fa..847c7f1b 100644
--- a/src/base/abci/abcDelay.c
+++ b/src/base/abci/abcDelay.c
@@ -20,6 +20,7 @@
#include "abc.h"
#include "if.h"
+#include "aig.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -652,6 +653,302 @@ Abc_Ntk_t * Abc_NtkSpeedup( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, in
return pNtkNew;
}
+/**Function*************************************************************
+
+ Synopsis [Marks nodes for power-optimization.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne )
+{
+ extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+ extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+ Vec_Int_t * vProbs;
+ Vec_Int_t * vSwitching;
+ float * pProbability;
+ float * pSwitching;
+ Abc_Ntk_t * pNtkStr;
+ Aig_Man_t * pAig;
+ Aig_Obj_t * pObjAig;
+ Abc_Obj_t * pObjAbc, * pObjAbc2;
+ int i;
+ // start the resulting array
+ vProbs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
+ pProbability = (float *)vProbs->pArray;
+ // strash the network
+ pNtkStr = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ Abc_NtkForEachObj( pNtk, pObjAbc, i )
+ if ( Abc_ObjRegular(pObjAbc->pTemp)->Type == ABC_FUNC_NONE )
+ pObjAbc->pTemp = NULL;
+ // map network into an AIG
+ pAig = Abc_NtkToDar( pNtkStr, 0, (int)(Abc_NtkLatchNum(pNtk) > 0) );
+ vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, fProbOne );
+ pSwitching = (float *)vSwitching->pArray;
+ Abc_NtkForEachObj( pNtk, pObjAbc, i )
+ {
+ if ( (pObjAbc2 = Abc_ObjRegular(pObjAbc->pTemp)) && (pObjAig = pObjAbc2->pTemp) )
+ pProbability[pObjAbc->Id] = pSwitching[pObjAig->Id];
+ }
+ Vec_IntFree( vSwitching );
+ Aig_ManStop( pAig );
+ Abc_NtkDelete( pNtkStr );
+ return vProbs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks nodes for power-optimization.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPowerPrint( Abc_Ntk_t * pNtk, Vec_Int_t * vProbs )
+{
+ Abc_Obj_t * pObj;
+ float * pProb, TotalProb = 0.0, ProbThis, Probs[5] = {0.0};
+ int i, nNodes = 0, nEdges = 0, Counter[5] = {0};
+ pProb = (float *)vProbs->pArray;
+ assert( Vec_IntSize(vProbs) >= Abc_NtkObjNumMax(pNtk) );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPi(pObj) )
+ continue;
+ nNodes++;
+ nEdges += Abc_ObjFanoutNum(pObj);
+ ProbThis = pProb[i] * Abc_ObjFanoutNum(pObj);
+ TotalProb += ProbThis;
+ assert( pProb[i] >= 0.0 && pProb[i] <= 0.5 );
+ if ( pProb[i] >= 0.4 )
+ {
+ Counter[4]++;
+ Probs[4] += ProbThis;
+ }
+ else if ( pProb[i] >= 0.3 )
+ {
+ Counter[3]++;
+ Probs[3] += ProbThis;
+ }
+ else if ( pProb[i] >= 0.2 )
+ {
+ Counter[2]++;
+ Probs[2] += ProbThis;
+ }
+ else if ( pProb[i] >= 0.1 )
+ {
+ Counter[1]++;
+ Probs[1] += ProbThis;
+ }
+ else
+ {
+ Counter[0]++;
+ Probs[0] += ProbThis;
+ }
+ }
+ printf( "Node distribution: " );
+ for ( i = 0; i < 5; i++ )
+ printf( "n%d%d = %6.2f%% ", i, i+1, 100.0 * Counter[i]/nNodes );
+ printf( "\n" );
+ printf( "Power distribution: " );
+ for ( i = 0; i < 5; i++ )
+ printf( "p%d%d = %6.2f%% ", i, i+1, 100.0 * Probs[i]/TotalProb );
+ printf( "\n" );
+ printf( "Total probs = %7.2f. ", TotalProb );
+ printf( "Total edges = %d. ", nEdges );
+ printf( "Average = %7.2f. ", TotalProb / nEdges );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determines timing-critical edges of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Abc_NtkPowerCriticalEdges( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, float Limit, Vec_Int_t * vProbs )
+{
+ Abc_Obj_t * pFanin;
+ float * pProb = (float *)vProbs->pArray;
+ unsigned uResult = 0;
+ int k;
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ if ( pProb[pFanin->Id] >= Limit )
+ uResult |= (1 << k);
+ return uResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds choices to speed up the network by the given percentage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkPowerdown( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose )
+{
+ Abc_Ntk_t * pNtkNew;
+ Vec_Int_t * vProbs;
+ Vec_Ptr_t * vTimeCries, * vTimeFanins;
+ Abc_Obj_t * pNode, * pFanin, * pFanin2;
+ float * pProb, Limit;
+ int i, k, k2, Counter, CounterRes, nTimeCris;
+ unsigned * puPCEdges;
+ // compute the limit
+ Limit = 0.5 - (1.0 * Percentage / 100);
+ // perform computation of switching probability
+ vProbs = Abc_NtkPowerEstimate( pNtk, 0 );
+ pProb = (float *)vProbs->pArray;
+ // compute percentage of wires of each type
+ if ( fVerbose )
+ Abc_NtkPowerPrint( pNtk, vProbs );
+ // mark the power critical nodes and edges
+ puPCEdges = ALLOC( unsigned, Abc_NtkObjNumMax(pNtk) );
+ memset( puPCEdges, 0, sizeof(unsigned) * Abc_NtkObjNumMax(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ if ( pProb[pNode->Id] < Limit )
+ continue;
+ puPCEdges[pNode->Id] = Abc_NtkPowerCriticalEdges( pNtk, pNode, Limit, vProbs );
+ }
+/*
+ if ( fVerbose )
+ {
+ Counter = CounterRes = 0;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Counter += Abc_ObjFaninNum(pNode);
+ CounterRes += Extra_WordCountOnes( puPCEdges[pNode->Id] );
+ }
+ printf( "Edges: Total = %7d. Critical = %7d. Ratio = %4.2f\n",
+ Counter, CounterRes, 1.0*CounterRes/Counter );
+ }
+*/
+ // start the resulting network
+ pNtkNew = Abc_NtkStrash( pNtk, 0, 1, 0 );
+
+ // collect nodes to be used for resynthesis
+ Counter = CounterRes = 0;
+ vTimeCries = Vec_PtrAlloc( 16 );
+ vTimeFanins = Vec_PtrAlloc( 16 );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+// if ( pProb[pNode->Id] < Limit )
+// continue;
+ // count the number of non-PI power-critical nodes
+ nTimeCris = 0;
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ if ( !Abc_ObjIsCi(pFanin) && (puPCEdges[pNode->Id] & (1<<k)) )
+ nTimeCris++;
+ if ( !fVeryVerbose && nTimeCris == 0 )
+ continue;
+ Counter++;
+ // count the total number of power-critical second-generation nodes
+ Vec_PtrClear( vTimeCries );
+ if ( nTimeCris )
+ {
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ if ( !Abc_ObjIsCi(pFanin) && (puPCEdges[pNode->Id] & (1<<k)) )
+ Abc_ObjForEachFanin( pFanin, pFanin2, k2 )
+ if ( puPCEdges[pFanin->Id] & (1<<k2) )
+ Vec_PtrPushUnique( vTimeCries, pFanin2 );
+ }
+// if ( !fVeryVerbose && (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) )
+ if ( (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) )
+ continue;
+ CounterRes++;
+ // collect second generation nodes
+ Vec_PtrClear( vTimeFanins );
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ {
+ if ( Abc_ObjIsCi(pFanin) )
+ Vec_PtrPushUnique( vTimeFanins, pFanin );
+ else
+ Abc_ObjForEachFanin( pFanin, pFanin2, k2 )
+ Vec_PtrPushUnique( vTimeFanins, pFanin2 );
+ }
+ // print the results
+ if ( fVeryVerbose )
+ {
+ printf( "%5d Node %5d : %d %2d %2d ", Counter, pNode->Id,
+ nTimeCris, Vec_PtrSize(vTimeCries), Vec_PtrSize(vTimeFanins) );
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ printf( "%d(%.2f)%s ", pFanin->Id, pProb[pFanin->Id], (puPCEdges[pNode->Id] & (1<<k))? "*":"" );
+ printf( "\n" );
+ }
+ // add the node to choices
+ if ( Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree )
+ continue;
+ // order the fanins in the increasing order of criticalily
+ if ( Vec_PtrSize(vTimeCries) > 1 )
+ {
+ pFanin = Vec_PtrEntry( vTimeCries, 0 );
+ pFanin2 = Vec_PtrEntry( vTimeCries, 1 );
+// if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) )
+ if ( pProb[pFanin->Id] > pProb[pFanin2->Id] )
+ {
+ Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 );
+ Vec_PtrWriteEntry( vTimeCries, 1, pFanin );
+ }
+ }
+ if ( Vec_PtrSize(vTimeCries) > 2 )
+ {
+ pFanin = Vec_PtrEntry( vTimeCries, 1 );
+ pFanin2 = Vec_PtrEntry( vTimeCries, 2 );
+// if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) )
+ if ( pProb[pFanin->Id] > pProb[pFanin2->Id] )
+ {
+ Vec_PtrWriteEntry( vTimeCries, 1, pFanin2 );
+ Vec_PtrWriteEntry( vTimeCries, 2, pFanin );
+ }
+ pFanin = Vec_PtrEntry( vTimeCries, 0 );
+ pFanin2 = Vec_PtrEntry( vTimeCries, 1 );
+// if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) )
+ if ( pProb[pFanin->Id] > pProb[pFanin2->Id] )
+ {
+ Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 );
+ Vec_PtrWriteEntry( vTimeCries, 1, pFanin );
+ }
+ }
+ // add choice
+ Abc_NtkSpeedupNode( pNtk, pNtkNew, pNode, vTimeFanins, vTimeCries );
+ }
+ Vec_PtrFree( vTimeCries );
+ Vec_PtrFree( vTimeFanins );
+ free( puPCEdges );
+ if ( fVerbose )
+ printf( "Nodes: Total = %7d. Power-critical = %7d. Workable = %7d. Ratio = %4.2f\n",
+ Abc_NtkNodeNum(pNtk), Counter, CounterRes, 1.0*CounterRes/Counter );
+
+ // remove invalid choice nodes
+ Abc_AigForEachAnd( pNtkNew, pNode, i )
+ if ( pNode->pData )
+ {
+ if ( Abc_ObjFanoutNum(pNode->pData) > 0 )
+ pNode->pData = NULL;
+ }
+
+ // return the result
+ Vec_IntFree( vProbs );
+ return pNtkNew;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c
index 751e2b2f..c5d9ada7 100644
--- a/src/base/abci/abcIf.c
+++ b/src/base/abci/abcIf.c
@@ -51,6 +51,59 @@ extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose );
SeeAlso []
***********************************************************************/
+void Abc_NtkIfComputeSwitching( Abc_Ntk_t * pNtk, If_Man_t * pIfMan )
+{
+ extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+ extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+ Vec_Int_t * vSwitching;
+ float * pSwitching;
+ Abc_Obj_t * pObjAbc;
+ Aig_Obj_t * pObjAig;
+ Aig_Man_t * pAig;
+ If_Obj_t * pObjIf;
+ int i, clk = clock();
+ // map IF objects into old network
+ Abc_NtkForEachObj( pNtk, pObjAbc, i )
+ if ( (pObjIf = pObjAbc->pTemp) )
+ pObjIf->pCopy = pObjAbc;
+ // map network into an AIG
+ pAig = Abc_NtkToDar( pNtk, 0, 0 );
+ vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 );
+ pSwitching = (float *)vSwitching->pArray;
+ Abc_NtkForEachObj( pNtk, pObjAbc, i )
+ if ( (pObjAig = pObjAbc->pTemp) )
+ {
+ pObjAbc->dTemp = pSwitching[pObjAig->Id];
+ // J. Anderson and F. N. Najm, “Power-Aware Technology Mapping for LUT-Based FPGAs,”
+ // IEEE Intl. Conf. on Field-Programmable Technology, 2002.
+// pObjAbc->dTemp = (1.55 + 1.05 / (float) Abc_ObjFanoutNum(pObjAbc)) * pSwitching[pObjAig->Id];
+ }
+ Vec_IntFree( vSwitching );
+ Aig_ManStop( pAig );
+ // compute switching for the IF objects
+ assert( pIfMan->vSwitching == NULL );
+ pIfMan->vSwitching = Vec_IntStart( If_ManObjNum(pIfMan) );
+ pSwitching = (float *)pIfMan->vSwitching->pArray;
+ If_ManForEachObj( pIfMan, pObjIf, i )
+ if ( (pObjAbc = pObjIf->pCopy) )
+ pSwitching[i] = pObjAbc->dTemp;
+if ( pIfMan->pPars->fVerbose )
+{
+ PRT( "Computing switching activity", clock() - clk );
+}
+}
+
+/**Function*************************************************************
+
+ Synopsis [Interface with the FPGA mapping package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
{
Abc_Ntk_t * pNtkNew;
@@ -74,6 +127,8 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
pIfMan = Abc_NtkToIf( pNtk, pPars );
if ( pIfMan == NULL )
return NULL;
+ if ( pPars->fPower )
+ Abc_NtkIfComputeSwitching( pNtk, pIfMan );
if ( !If_ManPerformMapping( pIfMan ) )
{
If_ManStop( pIfMan );
@@ -133,6 +188,7 @@ If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30), Abc_NtkObjNum(pNtk) );
// create PIs and remember them in the old nodes
+ Abc_NtkCleanCopy( pNtk );
Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan );
Abc_NtkForEachCi( pNtk, pNode, i )
{
@@ -165,7 +221,7 @@ If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
// set the primary outputs without copying the phase
Abc_NtkForEachCo( pNtk, pNode, i )
- If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) );
+ pNode->pCopy = (Abc_Obj_t *)If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) );
return pIfMan;
}
diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c
index d0bce990..3a454fc0 100644
--- a/src/base/abci/abcMap.c
+++ b/src/base/abci/abcMap.c
@@ -61,7 +61,7 @@ Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int
Map_Man_t * pMan;
Vec_Int_t * vSwitching = NULL;
float * pSwitching = NULL;
- int clk;
+ int clk, clkTotal = clock();
assert( Abc_NtkIsStrash(pNtk) );
@@ -115,6 +115,10 @@ clk = clock();
if ( pNtk->pExdc )
pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
+if ( fVerbose )
+{
+PRT( "Total runtime", clock() - clkTotal );
+}
// make sure that everything is okay
if ( !Abc_NtkCheck( pNtkNew ) )
diff --git a/src/base/abci/abcMerge.c b/src/base/abci/abcMerge.c
new file mode 100644
index 00000000..25a4f02e
--- /dev/null
+++ b/src/base/abci/abcMerge.c
@@ -0,0 +1,352 @@
+/**CFile****************************************************************
+
+ FileName [abcMerge.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [LUT merging algorithm.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "aig.h"
+#include "nwkMerge.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Marks the fanins of the node with the current trav ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMarkFanins_rec( Abc_Obj_t * pLut, int nLevMin )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ if ( !Abc_ObjIsNode(pLut) )
+ return;
+ if ( Abc_NodeIsTravIdCurrent( pLut ) )
+ return;
+ Abc_NodeSetTravIdCurrent( pLut );
+ if ( Abc_ObjLevel(pLut) < nLevMin )
+ return;
+ Abc_ObjForEachFanin( pLut, pNext, i )
+ Abc_NtkMarkFanins_rec( pNext, nLevMin );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the fanouts of the node with the current trav ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMarkFanouts_rec( Abc_Obj_t * pLut, int nLevMax, int nFanMax )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ if ( !Abc_ObjIsNode(pLut) )
+ return;
+ if ( Abc_NodeIsTravIdCurrent( pLut ) )
+ return;
+ Abc_NodeSetTravIdCurrent( pLut );
+ if ( Abc_ObjLevel(pLut) > nLevMax )
+ return;
+ if ( Abc_ObjFanoutNum(pLut) > nFanMax )
+ return;
+ Abc_ObjForEachFanout( pLut, pNext, i )
+ Abc_NtkMarkFanouts_rec( pNext, nLevMax, nFanMax );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the circle of nodes around the given set.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax )
+{
+ Abc_Obj_t * pObj, * pNext;
+ int i, k;
+ Vec_PtrClear( vNext );
+ Vec_PtrForEachEntry( vStart, pObj, i )
+ {
+ Abc_ObjForEachFanin( pObj, pNext, k )
+ {
+ if ( !Abc_ObjIsNode(pNext) )
+ continue;
+ if ( Abc_NodeIsTravIdCurrent( pNext ) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pNext );
+ Vec_PtrPush( vNext, pNext );
+ }
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ {
+ if ( !Abc_ObjIsNode(pNext) )
+ continue;
+ if ( Abc_NodeIsTravIdCurrent( pNext ) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pNext );
+ if ( Abc_ObjFanoutNum(pNext) > nFanMax )
+ continue;
+ Vec_PtrPush( vNext, pNext );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the circle of nodes removes from the given one.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCollectNonOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
+{
+ Vec_Ptr_t * vTemp;
+ Abc_Obj_t * pObj;
+ int i, k;
+ Vec_PtrClear( vCands );
+ if ( pPars->nMaxSuppSize - Abc_ObjFaninNum(pLut) <= 1 )
+ return;
+
+ // collect nodes removed by this distance
+ assert( pPars->nMaxDistance > 0 );
+ Vec_PtrClear( vStart );
+ Vec_PtrPush( vStart, pLut );
+ Abc_NtkIncrementTravId( pLut->pNtk );
+ Abc_NodeSetTravIdCurrent( pLut );
+ for ( i = 1; i <= pPars->nMaxDistance; i++ )
+ {
+ Abc_NtkCollectCircle( vStart, vNext, pPars->nMaxFanout );
+ vTemp = vStart;
+ vStart = vNext;
+ vNext = vTemp;
+ // collect the nodes in vStart
+ Vec_PtrForEachEntry( vStart, pObj, k )
+ Vec_PtrPush( vCands, pObj );
+ }
+
+ // mark the TFI/TFO nodes
+ Abc_NtkIncrementTravId( pLut->pNtk );
+ if ( pPars->fUseTfiTfo )
+ Abc_NodeSetTravIdCurrent( pLut );
+ else
+ {
+ Abc_NodeSetTravIdPrevious( pLut );
+ Abc_NtkMarkFanins_rec( pLut, Abc_ObjLevel(pLut) - pPars->nMaxDistance );
+ Abc_NodeSetTravIdPrevious( pLut );
+ Abc_NtkMarkFanouts_rec( pLut, Abc_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout );
+ }
+
+ // collect nodes satisfying the following conditions:
+ // - they are close enough in terms of distance
+ // - they are not in the TFI/TFO of the LUT
+ // - they have no more than the given number of fanins
+ // - they have no more than the given diff in delay
+ k = 0;
+ Vec_PtrForEachEntry( vCands, pObj, i )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ continue;
+ if ( Abc_ObjFaninNum(pLut) + Abc_ObjFaninNum(pObj) > pPars->nMaxSuppSize )
+ continue;
+ if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff ||
+ Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff )
+ continue;
+ Vec_PtrWriteEntry( vCands, k++, pObj );
+ }
+ Vec_PtrShrink( vCands, k );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Count the total number of fanins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkCountTotalFanins( Abc_Obj_t * pLut, Abc_Obj_t * pCand )
+{
+ Abc_Obj_t * pFanin;
+ int i, nCounter = Abc_ObjFaninNum(pLut);
+ Abc_ObjForEachFanin( pCand, pFanin, i )
+ nCounter += !pFanin->fMarkC;
+ return nCounter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects overlapping candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCollectOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
+{
+ Abc_Obj_t * pFanin, * pObj;
+ int i, k;
+ // mark fanins of pLut
+ Abc_ObjForEachFanin( pLut, pFanin, i )
+ pFanin->fMarkC = 1;
+ // collect the matching fanouts of each fanin of the node
+ Vec_PtrClear( vCands );
+ Abc_NtkIncrementTravId( pLut->pNtk );
+ Abc_NodeSetTravIdCurrent( pLut );
+ Abc_ObjForEachFanin( pLut, pFanin, i )
+ {
+ if ( !Abc_ObjIsNode(pFanin) )
+ continue;
+ if ( Abc_ObjFanoutNum(pFanin) > pPars->nMaxFanout )
+ continue;
+ Abc_ObjForEachFanout( pFanin, pObj, k )
+ {
+ if ( !Abc_ObjIsNode(pObj) )
+ continue;
+ if ( Abc_NodeIsTravIdCurrent( pObj ) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pObj );
+ // check the difference in delay
+ if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff ||
+ Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff )
+ continue;
+ // check the total number of fanins of the node
+ if ( Abc_NtkCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize )
+ continue;
+ Vec_PtrPush( vCands, pObj );
+ }
+ }
+ // unmark fanins of pLut
+ Abc_ObjForEachFanin( pLut, pFanin, i )
+ pFanin->fMarkC = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs LUT merging with parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars )
+{
+ Nwk_Grf_t * p;
+ Vec_Int_t * vResult;
+ Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2;
+ Abc_Obj_t * pLut, * pCand;
+ int i, k, nVertsMax, nCands, clk = clock();
+ // count the number of vertices
+ nVertsMax = 0;
+ Abc_NtkForEachNode( pNtk, pLut, i )
+ nVertsMax += (int)(Abc_ObjFaninNum(pLut) <= pPars->nMaxLutSize);
+ p = Nwk_ManGraphAlloc( nVertsMax );
+ // create graph
+ vStart = Vec_PtrAlloc( 1000 );
+ vNext = Vec_PtrAlloc( 1000 );
+ vCands1 = Vec_PtrAlloc( 1000 );
+ vCands2 = Vec_PtrAlloc( 1000 );
+ nCands = 0;
+ Abc_NtkForEachNode( pNtk, pLut, i )
+ {
+ if ( Abc_ObjFaninNum(pLut) > pPars->nMaxLutSize )
+ continue;
+ Abc_NtkCollectOverlapCands( pLut, vCands1, pPars );
+ if ( pPars->fUseDiffSupp )
+ Abc_NtkCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars );
+ if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 )
+ continue;
+ nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2);
+ // save candidates
+ Vec_PtrForEachEntry( vCands1, pCand, k )
+ Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) );
+ Vec_PtrForEachEntry( vCands2, pCand, k )
+ Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) );
+ // print statistics about this node
+ if ( pPars->fVeryVerbose )
+ printf( "Node %6d : Fanins = %d. Fanouts = %3d. Cand1 = %3d. Cand2 = %3d.\n",
+ Abc_ObjId(pLut), Abc_ObjFaninNum(pLut), Abc_ObjFaninNum(pLut),
+ Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) );
+ }
+ Vec_PtrFree( vStart );
+ Vec_PtrFree( vNext );
+ Vec_PtrFree( vCands1 );
+ Vec_PtrFree( vCands2 );
+ if ( pPars->fVerbose )
+ {
+ printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands );
+ PRT( "Deriving graph", clock() - clk );
+ }
+ // solve the graph problem
+ clk = clock();
+ Nwk_ManGraphSolve( p );
+ if ( pPars->fVerbose )
+ {
+ printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ",
+ p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 );
+ PRT( "Solving", clock() - clk );
+ Nwk_ManGraphReportMemoryUsage( p );
+ }
+ vResult = p->vPairs; p->vPairs = NULL;
+/*
+ for ( i = 0; i < vResult->nSize; i += 2 )
+ printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] );
+ printf( "\n" );
+*/
+ Nwk_ManGraphFree( p );
+ return vResult;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c
index 23a44eb3..0b1d8fc1 100644
--- a/src/base/abci/abcPrint.c
+++ b/src/base/abci/abcPrint.c
@@ -22,7 +22,7 @@
#include "dec.h"
#include "main.h"
#include "mio.h"
-//#include "seq.h"
+#include "aig.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
@@ -102,6 +102,49 @@ int Abc_NtkCompareAndSaveBest( Abc_Ntk_t * pNtk )
/**Function*************************************************************
+ Synopsis [Marks nodes for power-optimization.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk )
+{
+ extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+ extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
+ Vec_Int_t * vSwitching;
+ float * pSwitching;
+ Abc_Ntk_t * pNtkStr;
+ Aig_Man_t * pAig;
+ Aig_Obj_t * pObjAig;
+ Abc_Obj_t * pObjAbc, * pObjAbc2;
+ float Result = (float)0;
+ int i;
+ // strash the network
+ pNtkStr = Abc_NtkStrash( pNtk, 0, 1, 0 );
+ Abc_NtkForEachObj( pNtk, pObjAbc, i )
+ if ( Abc_ObjRegular(pObjAbc->pTemp)->Type == ABC_FUNC_NONE )
+ pObjAbc->pTemp = NULL;
+ // map network into an AIG
+ pAig = Abc_NtkToDar( pNtkStr, 0, (int)(Abc_NtkLatchNum(pNtk) > 0) );
+ vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 );
+ pSwitching = (float *)vSwitching->pArray;
+ Abc_NtkForEachObj( pNtk, pObjAbc, i )
+ {
+ if ( (pObjAbc2 = Abc_ObjRegular(pObjAbc->pTemp)) && (pObjAig = pObjAbc2->pTemp) )
+ Result += Abc_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id];
+ }
+ Vec_IntFree( vSwitching );
+ Aig_ManStop( pAig );
+ Abc_NtkDelete( pNtkStr );
+ return Result;
+}
+
+/**Function*************************************************************
+
Synopsis [Print the vital stats of the network.]
Description []
@@ -111,7 +154,7 @@ int Abc_NtkCompareAndSaveBest( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
-void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes )
+void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower )
{
int Num;
if ( fSaveBest )
@@ -192,6 +235,8 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored, int fSave
fprintf( pFile, " lev = %3d", Abc_NtkLevel(pNtk) );
if ( fUseLutLib && Abc_FrameReadLibLut() )
fprintf( pFile, " delay = %5.2f", Abc_NtkDelayTraceLut(pNtk, 1) );
+ if ( fPower )
+ fprintf( pFile, " power = %7.2f", Abc_NtkMfsTotalSwitching(pNtk) );
fprintf( pFile, "\n" );
// Abc_NtkCrossCut( pNtk );
@@ -898,32 +943,39 @@ void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary )
if ( fUseLibrary && Abc_NtkHasMapping(pNtk) )
{
- stmm_table * tTable;
- stmm_generator * gen;
- char * pName;
- int * pCounter, Counter;
+ Mio_Gate_t ** ppGates;
double Area, AreaTotal;
+ int Counter, nGates, i;
+
+ // clean value of all gates
+ nGates = Mio_LibraryReadGateNum( pNtk->pManFunc );
+ ppGates = Mio_LibraryReadGatesByName( pNtk->pManFunc );
+ for ( i = 0; i < nGates; i++ )
+ Mio_GateSetValue( ppGates[i], 0 );
// count the gates by name
CounterTotal = 0;
- tTable = stmm_init_table(strcmp, stmm_strhash);
Abc_NtkForEachNode( pNtk, pObj, i )
{
if ( i == 0 ) continue;
- if ( !stmm_find_or_add( tTable, Mio_GateReadName(pObj->pData), (char ***)&pCounter ) )
- *pCounter = 0;
- (*pCounter)++;
+ Mio_GateSetValue( pObj->pData, 1 + Mio_GateReadValue(pObj->pData) );
CounterTotal++;
}
// print the gates
AreaTotal = Abc_NtkGetMappedArea(pNtk);
- stmm_foreach_item( tTable, gen, (char **)&pName, (char **)&Counter )
+ for ( i = 0; i < nGates; i++ )
{
- Area = Counter * Mio_GateReadArea(Mio_LibraryReadGateByName(pNtk->pManFunc,pName));
- printf( "%-12s = %8d %10.2f %6.2f %%\n", pName, Counter, Area, 100.0 * Area / AreaTotal );
+ Counter = Mio_GateReadValue( ppGates[i] );
+ if ( Counter == 0 )
+ continue;
+ Area = Counter * Mio_GateReadArea( ppGates[i] );
+ printf( "%-12s Fanin = %2d Instance = %8d Area = %10.2f %6.2f %%\n",
+ Mio_GateReadName( ppGates[i] ),
+ Mio_GateReadInputs( ppGates[i] ),
+ Counter, Area, 100.0 * Area / AreaTotal );
}
- printf( "%-12s = %8d %10.2f %6.2f %%\n", "TOTAL", CounterTotal, AreaTotal, 100.0 );
- stmm_free_table( tTable );
+ printf( "%-12s Instance = %8d Area = %10.2f %6.2f %%\n", "TOTAL",
+ CounterTotal, AreaTotal, 100.0 );
return;
}
diff --git a/src/base/abci/abcStrash.c b/src/base/abci/abcStrash.c
index 463846b9..a7c9f609 100644
--- a/src/base/abci/abcStrash.c
+++ b/src/base/abci/abcStrash.c
@@ -316,7 +316,7 @@ int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos )
***********************************************************************/
void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord )
{
- ProgressBar * pProgress;
+// ProgressBar * pProgress;
Vec_Ptr_t * vNodes;
Abc_Obj_t * pNodeOld;
int i; //, clk = clock();
@@ -326,13 +326,13 @@ void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNod
vNodes = Abc_NtkDfsIter( pNtkOld, fAllNodes );
//printf( "Nodes = %d. ", Vec_PtrSize(vNodes) );
//PRT( "Time", clock() - clk );
- pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
+// pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
Vec_PtrForEachEntry( vNodes, pNodeOld, i )
{
- Extra_ProgressBarUpdate( pProgress, i, NULL );
+// Extra_ProgressBarUpdate( pProgress, i, NULL );
pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord );
}
- Extra_ProgressBarStop( pProgress );
+// Extra_ProgressBarStop( pProgress );
Vec_PtrFree( vNodes );
}
diff --git a/src/base/abci/module.make b/src/base/abci/module.make
index e83785fe..c872d62e 100644
--- a/src/base/abci/module.make
+++ b/src/base/abci/module.make
@@ -25,6 +25,7 @@ SRC += src/base/abci/abc.c \
src/base/abci/abcIvy.c \
src/base/abci/abcLut.c \
src/base/abci/abcMap.c \
+ src/base/abci/abcMerge.c \
src/base/abci/abcMini.c \
src/base/abci/abcMiter.c \
src/base/abci/abcMulti.c \
diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c
index 4e0a4c95..459d82c9 100644
--- a/src/base/cmd/cmd.c
+++ b/src/base/cmd/cmd.c
@@ -662,6 +662,7 @@ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv )
}
}
+ fflush( pAbc->Out );
status = Cmd_CommandExecute( pAbc, line );
}
while ( status == 0 );
diff --git a/src/base/cmd/cmd.h b/src/base/cmd/cmd.h
index 9d0b8703..143f57cd 100644
--- a/src/base/cmd/cmd.h
+++ b/src/base/cmd/cmd.h
@@ -41,14 +41,14 @@ typedef struct MvCommand Abc_Command; // one command
typedef struct MvAlias Abc_Alias; // one alias
#ifdef WIN32
-#define DLLEXPORT __declspec(dllexport)
-#define DLLIMPORT __declspec(dllimport)
+#define ABC_DLLEXPORT __declspec(dllexport)
+#define ABC_DLLIMPORT __declspec(dllimport)
#else /* defined(WIN32) */
-#define DLLIMPORT
+#define ABC_DLLIMPORT
#endif /* defined(WIN32) */
#ifndef ABC_DLL
-#define ABC_DLL DLLIMPORT
+#define ABC_DLL ABC_DLLIMPORT
#endif
////////////////////////////////////////////////////////////////////////
diff --git a/src/base/io/io.c b/src/base/io/io.c
index 6f326a27..a8941868 100644
--- a/src/base/io/io.c
+++ b/src/base/io/io.c
@@ -48,6 +48,7 @@ static int IoCommandWriteBaf ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWriteBlif ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWriteBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWriteBench ( Abc_Frame_t * pAbc, int argc, char **argv );
+static int IoCommandWriteBook ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWriteCnf ( Abc_Frame_t * pAbc, int argc, char **argv );
static int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv );
@@ -102,6 +103,7 @@ void Io_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "I/O", "write_blif", IoCommandWriteBlif, 0 );
Cmd_CommandAdd( pAbc, "I/O", "write_blif_mv", IoCommandWriteBlifMv, 0 );
Cmd_CommandAdd( pAbc, "I/O", "write_bench", IoCommandWriteBench, 0 );
+ Cmd_CommandAdd( pAbc, "I/O", "write_book", IoCommandWriteBook, 0 );
Cmd_CommandAdd( pAbc, "I/O", "write_cellnet", IoCommandWriteCellNet, 0 );
Cmd_CommandAdd( pAbc, "I/O", "write_counter", IoCommandWriteCounter, 0 );
Cmd_CommandAdd( pAbc, "I/O", "write_cnf", IoCommandWriteCnf, 0 );
@@ -1488,6 +1490,49 @@ usage:
SeeAlso []
***********************************************************************/
+int IoCommandWriteBook( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ char * pFileName;
+ int c;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( argc != globalUtilOptind + 1 )
+ goto usage;
+ // get the output file name
+ pFileName = argv[globalUtilOptind];
+ // call the corresponding file writer
+ Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BOOK );
+ return 0;
+
+usage:
+ fprintf( pAbc->Err, "usage: write_book [-h] <file> [-options]\n" );
+ fprintf( pAbc->Err, "\t-h : print the help massage\n" );
+ fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .aux, .nodes, .nets)\n" );
+ fprintf( pAbc->Err, "\t\n" );
+ fprintf( pAbc->Err, "\tThis command is developed by Myungchul Kim (University of Michigan).\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv )
{
Abc_Ntk_t * pNtk;
diff --git a/src/base/io/ioAbc.h b/src/base/io/ioAbc.h
index e62cc168..842d8995 100644
--- a/src/base/io/ioAbc.h
+++ b/src/base/io/ioAbc.h
@@ -47,6 +47,7 @@ typedef enum {
IO_FILE_BLIF,
IO_FILE_BLIFMV,
IO_FILE_BENCH,
+ IO_FILE_BOOK,
IO_FILE_CNF,
IO_FILE_DOT,
IO_FILE_EDIF,
@@ -99,6 +100,8 @@ extern void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName );
/*=== abcWriteBench.c =========================================================*/
extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName );
extern int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * FileName );
+/*=== abcWriteBook.c =========================================================*/
+extern void Io_WriteBook( Abc_Ntk_t * pNtk, char * FileName );
/*=== abcWriteCnf.c ===========================================================*/
extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName, int fAllPrimes );
/*=== abcWriteDot.c ===========================================================*/
diff --git a/src/base/io/ioReadAiger.c b/src/base/io/ioReadAiger.c
index b8555561..3a6ecd19 100644
--- a/src/base/io/ioReadAiger.c
+++ b/src/base/io/ioReadAiger.c
@@ -45,7 +45,7 @@
SeeAlso []
***********************************************************************/
-unsigned Io_ReadAigerDecode( char ** ppPos )
+static inline unsigned Io_ReadAigerDecode( char ** ppPos )
{
unsigned x = 0, i = 0;
unsigned char ch;
diff --git a/src/base/io/ioReadBlifMv.c b/src/base/io/ioReadBlifMv.c
index 880c2b5f..87358ed2 100644
--- a/src/base/io/ioReadBlifMv.c
+++ b/src/base/io/ioReadBlifMv.c
@@ -130,7 +130,7 @@ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
FILE * pFile;
Io_MvMan_t * p;
Abc_Ntk_t * pNtk;
- Abc_Lib_t * pDesign = NULL;
+ Abc_Lib_t * pDesign = NULL;
char * pDesignName;
int RetValue, i;
@@ -951,6 +951,7 @@ static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine )
pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") );
// create latch
pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) );
+// Abc_LatchSetInit0( pObj );
Abc_LatchSetInit0( pObj );
}
return 1;
diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c
index 119b4d75..60e6adc8 100644
--- a/src/base/io/ioUtil.c
+++ b/src/base/io/ioUtil.c
@@ -338,6 +338,8 @@ void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType )
}
else if ( FileType == IO_FILE_BENCH )
Io_WriteBench( pNtkTemp, pFileName );
+ else if ( FileType == IO_FILE_BOOK )
+ Io_WriteBook( pNtkTemp, pFileName );
else if ( FileType == IO_FILE_PLA )
Io_WritePla( pNtkTemp, pFileName );
else if ( FileType == IO_FILE_EQN )
diff --git a/src/base/io/ioWriteBook.c b/src/base/io/ioWriteBook.c
new file mode 100644
index 00000000..95405438
--- /dev/null
+++ b/src/base/io/ioWriteBook.c
@@ -0,0 +1,985 @@
+/**CFile****************************************************************
+
+ FileName [ioWriteBook.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Command processing package.]
+
+ Synopsis [Procedures to write Bookshelf files.]
+
+ Author [Myungchul Kim]
+
+ Affiliation [U of Michigan]
+
+ Date [Ver. 1.0. Started - October 25, 2008.]
+
+ Revision [$Id: ioWriteBook.c,v 1.00 2005/11/10 00:00:00 mckima Exp $]
+
+***********************************************************************/
+
+#include "ioAbc.h"
+#include "main.h"
+#include "mio.h"
+#define NODES 0
+#define PL 1
+#define coreHeight 1
+#define termWidth 1
+#define termHeight 1
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned Io_NtkWriteNodes( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWritePiPoNodes( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteLatchNode( FILE * pFile, Abc_Obj_t * pLatch, bool NodesOrPl );
+static unsigned Io_NtkWriteIntNode( FILE * pFile, Abc_Obj_t * pNode, bool NodesOrPl );
+static unsigned Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkWriteNets( FILE * pFile, Abc_Ntk_t * pNtk );
+static void Io_NtkWriteIntNet( FILE * pFile, Abc_Obj_t * pNode );
+static void Io_NtkBuildLayout( FILE * pFile1, FILE *pFile2, Abc_Ntk_t * pNtk, double aspectRatio, double whiteSpace, unsigned coreCellArea );
+static void Io_NtkWriteScl( FILE * pFile, unsigned numCoreRows, double layoutWidth );
+static void Io_NtkWritePl( FILE * pFile, Abc_Ntk_t * pNtk, unsigned numTerms, double layoutHeight, double layoutWidth );
+static Vec_Ptr_t * Io_NtkOrderingPads( Abc_Ntk_t * pNtk, Vec_Ptr_t * vTerms );
+static Abc_Obj_t * Io_NtkBfsPads( Abc_Ntk_t * pNtk, Abc_Obj_t * pCurrEntry, unsigned numTerms, bool * pOrdered );
+static bool Abc_NodeIsNand2( Abc_Obj_t * pNode );
+static bool Abc_NodeIsNor2( Abc_Obj_t * pNode );
+static bool Abc_NodeIsAnd2( Abc_Obj_t * pNode );
+static bool Abc_NodeIsOr2( Abc_Obj_t * pNode );
+static bool Abc_NodeIsXor2( Abc_Obj_t * pNode );
+static bool Abc_NodeIsXnor2( Abc_Obj_t * pNode );
+
+static inline double Abc_Rint( double x ) { return (double)(int)x; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Write the network into a Bookshelf file with the given name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteBookLogic( Abc_Ntk_t * pNtk, char * FileName )
+{
+ Abc_Ntk_t * pNtkTemp;
+ // derive the netlist
+ pNtkTemp = Abc_NtkToNetlist(pNtk);
+ if ( pNtkTemp == NULL )
+ {
+ fprintf( stdout, "Writing BOOK has failed.\n" );
+ return;
+ }
+ Io_WriteBook( pNtkTemp, FileName );
+ Abc_NtkDelete( pNtkTemp );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the network into a BOOK file with the given name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_WriteBook( Abc_Ntk_t * pNtk, char * FileName )
+{
+
+ FILE * pFileNodes, * pFileNets, * pFileAux;
+ FILE * pFileScl, * pFilePl, * pFileWts;
+ char * FileExt = (char *)calloc(strlen(FileName)+7, sizeof(char));
+ unsigned coreCellArea=0;
+ Abc_Ntk_t * pExdc, * pNtkTemp;
+ int i;
+
+ assert( Abc_NtkIsNetlist(pNtk) );
+ // start writing the files
+ strcpy(FileExt, FileName);
+ pFileNodes = fopen( strcat(FileExt,".nodes"), "w" );
+ strcpy(FileExt, FileName);
+ pFileNets = fopen( strcat(FileExt,".nets"), "w" );
+ strcpy(FileExt, FileName);
+ pFileAux = fopen( strcat(FileExt,".aux"), "w" );
+
+ // write the aux file
+ if ( (pFileNodes == NULL) || (pFileNets == NULL) || (pFileAux == NULL) )
+ {
+ fprintf( stdout, "Io_WriteBook(): Cannot open the output files.\n" );
+ return;
+ }
+ fprintf( pFileAux, "RowBasedPlacement : %s.nodes %s.nets %s.scl %s.pl %s.wts",
+ FileName, FileName, FileName, FileName, FileName );
+ fclose( pFileAux );
+
+ // write the master network
+ coreCellArea+=Io_NtkWriteNodes( pFileNodes, pNtk );
+ Io_NtkWriteNets( pFileNets, pNtk );
+
+ // write EXDC network if it exists
+ pExdc = Abc_NtkExdc( pNtk );
+ if ( pExdc )
+ {
+ coreCellArea+=Io_NtkWriteNodes( pFileNodes, pNtk );
+ Io_NtkWriteNets( pFileNets, pNtk );
+ }
+
+ // make sure there is no logic hierarchy
+ assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
+
+ // write the hierarchy if present
+ if ( Abc_NtkBlackboxNum(pNtk) > 0 )
+ {
+ Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i )
+ {
+ if ( pNtkTemp == pNtk )
+ continue;
+ coreCellArea+=Io_NtkWriteNodes( pFileNodes, pNtkTemp );
+ Io_NtkWriteNets( pFileNets, pNtkTemp );
+ }
+ }
+ fclose( pFileNodes );
+ fclose( pFileNets );
+
+ strcpy(FileExt, FileName);
+ pFileScl = fopen( strcat(FileExt,".scl"), "w" );
+ strcpy(FileExt, FileName);
+ pFilePl = fopen( strcat(FileExt,".pl"), "w" );
+ strcpy(FileExt, FileName);
+ pFileWts = fopen( strcat(FileExt,".wts"), "w" );
+ free(FileExt);
+
+ Io_NtkBuildLayout( pFileScl, pFilePl, pNtk, 1.0, 10, coreCellArea );
+ fclose( pFileScl );
+ fclose( pFilePl );
+ fclose( pFileWts );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the network into a BOOK file with the given name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Io_NtkWriteNodes( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ ProgressBar * pProgress;
+ Abc_Obj_t * pLatch, * pNode;
+ unsigned numTerms, numNodes, coreCellArea=0;
+ int i;
+
+ assert( Abc_NtkIsNetlist(pNtk) );
+ // write the forehead
+ numTerms=Abc_NtkPiNum(pNtk)+Abc_NtkPoNum(pNtk);
+ numNodes=numTerms+Abc_NtkNodeNum(pNtk)+Abc_NtkLatchNum(pNtk);
+ printf("NumNodes : %d\t", numNodes );
+ printf("NumTerminals : %d\n", numTerms );
+ fprintf( pFile, "UCLA nodes 1.0\n");
+ fprintf( pFile, "NumNodes : %d\n", numNodes );
+ fprintf( pFile, "NumTerminals : %d\n", numTerms );
+ // write the PI/POs
+ Io_NtkWritePiPoNodes( pFile, pNtk );
+ // write the latches
+ if ( !Abc_NtkIsComb(pNtk) )
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ Io_NtkWriteLatchNode( pFile, pLatch, NODES );
+ coreCellArea+=6*coreHeight;
+ }
+ // write each internal node
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ coreCellArea+=Io_NtkWriteIntNode( pFile, pNode, NODES );
+ }
+ Extra_ProgressBarStop( pProgress );
+ return coreCellArea;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the primary input nodes into a file]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWritePiPoNodes( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pTerm, * pNet;
+ int i;
+
+ Abc_NtkForEachPi( pNtk, pTerm, i )
+ {
+ pNet = Abc_ObjFanout0(pTerm);
+ fprintf( pFile, "i%s_input\t", Abc_ObjName(pNet) );
+ fprintf( pFile, "terminal ");
+ fprintf( pFile, " %d %d\n", termWidth, termHeight );
+ }
+
+ Abc_NtkForEachPo( pNtk, pTerm, i )
+ {
+ pNet = Abc_ObjFanin0(pTerm);
+ fprintf( pFile, "o%s_output\t", Abc_ObjName(pNet) );
+ fprintf( pFile, "terminal ");
+ fprintf( pFile, " %d %d\n", termWidth, termHeight );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the latch nodes into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteLatchNode( FILE * pFile, Abc_Obj_t * pLatch, bool NodesOrPl )
+{
+ Abc_Obj_t * pNetLi, * pNetLo;
+
+ pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) );
+ pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) );
+ /// write the latch line
+ fprintf( pFile, "%s_%s_latch\t", Abc_ObjName(pNetLi), Abc_ObjName(pNetLo) );
+ if (NodesOrPl == NODES)
+ fprintf( pFile, " %d %d\n", 6, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the internal node into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Io_NtkWriteIntNode( FILE * pFile, Abc_Obj_t * pNode, bool NodesOrPl )
+{
+ unsigned sizex=0, sizey=coreHeight, isize=0;
+ //double nx, ny, xstep, ystep;
+ Abc_Obj_t * pNeti, *pNeto;
+ int i;
+
+ // write the network after mapping
+ if ( Abc_NtkHasMapping(pNode->pNtk) )
+ sizex=Io_NtkWriteNodeGate( pFile, pNode );
+ else
+ {
+ Abc_ObjForEachFanin( pNode, pNeti, i )
+ fprintf( pFile, "%s_", Abc_ObjName(pNeti) );
+ Abc_ObjForEachFanout( pNode, pNeto, i )
+ fprintf( pFile, "%s_", Abc_ObjName(pNeto) );
+ fprintf( pFile, "name\t" );
+
+ if(NodesOrPl == NODES)
+ {
+ isize=Abc_ObjFaninNum(pNode);
+ if ( Abc_NodeIsConst0(pNode) || Abc_NodeIsConst1(pNode) )
+ sizex=0;
+ else if ( Abc_NodeIsInv(pNode) )
+ sizex=1;
+ else if ( Abc_NodeIsBuf(pNode) )
+ sizex=2;
+ else
+ {
+ assert( Abc_NtkHasSop(pNode->pNtk) );
+ if ( Abc_NodeIsNand2(pNode) || Abc_NodeIsNor2(pNode) )
+ sizex=2;
+ else if ( Abc_NodeIsAnd2(pNode) || Abc_NodeIsOr2(pNode) )
+ sizex=3;
+ else if ( Abc_NodeIsXor2(pNode) || Abc_NodeIsXnor2(pNode) )
+ sizex=5;
+ else
+ {
+ assert( isize > 2 );
+ sizex=isize+Abc_SopGetCubeNum(pNode->pData);
+ }
+ }
+ }
+ }
+ if(NodesOrPl == NODES)
+ {
+ fprintf( pFile, " %d %d\n", sizex, sizey );
+
+ // Equally place pins. Size pins needs / isize+#output+1
+ isize= isize + Abc_ObjFanoutNum(pNode) + 1;
+ }
+ return sizex*sizey;
+ /*
+ xstep = sizex / isize;
+ ystep = sizey / isize;
+ nx= -0.5 * sizex;
+ ny= -0.5 * sizey;
+
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ nx+= xstep;
+ ny+= ystep;
+ if (fabs(nx) < 0.001)
+ nx= 0;
+ if (fabs(ny) < 0.001)
+ ny= 0;
+ }
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ {
+ nx+= xstep;
+ ny+= ystep;
+ if (fabs(nx) < 0.001)
+ nx= 0;
+ if (fabs(ny) < 0.001)
+ ny= 0;
+ }
+ */
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the internal node after tech mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode )
+{
+ Mio_Gate_t * pGate = pNode->pData;
+ Mio_Pin_t * pGatePin;
+ int i;
+ // write the node gate
+ for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ )
+ fprintf( pFile, "%s_", Abc_ObjName( Abc_ObjFanin(pNode,i) ) );
+ assert ( i == Abc_ObjFaninNum(pNode) );
+ fprintf( pFile, "%s_%s\t", Abc_ObjName( Abc_ObjFanout0(pNode) ), Mio_GateReadName(pGate) );
+ return Mio_GateReadArea(pGate);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the nets into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteNets( FILE * pFile, Abc_Ntk_t * pNtk )
+{
+ ProgressBar * pProgress;
+ Abc_Obj_t * pNet;
+ unsigned numPin=0;
+ int i;
+
+ assert( Abc_NtkIsNetlist(pNtk) );
+ // write the head
+ Abc_NtkForEachNet( pNtk, pNet, i )
+ numPin+=Abc_ObjFaninNum(pNet)+Abc_ObjFanoutNum(pNet);
+ printf( "NumNets : %d\t", Abc_NtkNetNum(pNtk) );
+ printf( "NumPins : %d\n\n", numPin );
+ fprintf( pFile, "UCLA nets 1.0\n");
+ fprintf( pFile, "NumNets : %d\n", Abc_NtkNetNum(pNtk) );
+ fprintf( pFile, "NumPins : %d\n", numPin );
+
+ // write nets
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNetNum(pNtk) );
+ Abc_NtkForEachNet( pNtk, pNet, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ Io_NtkWriteIntNet( pFile, pNet );
+ }
+ Extra_ProgressBarStop( pProgress );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the nets into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteIntNet( FILE * pFile, Abc_Obj_t * pNet )
+{
+ Abc_Obj_t * pFanin, * pFanout;
+ Abc_Obj_t * pNeti, * pNeto;
+ Abc_Obj_t * pNetLi, * pNetLo, * pLatch;
+ int i, j;
+ int NetDegree=Abc_ObjFaninNum(pNet)+Abc_ObjFanoutNum(pNet);
+
+ fprintf( pFile, "NetDegree\t:\t\t%d\t\t%s\n", NetDegree, Abc_ObjName(Abc_ObjFanin0(pNet)) );
+
+ pFanin=Abc_ObjFanin0(pNet);
+ if ( Abc_ObjIsPi(pFanin) )
+ fprintf( pFile, "i%s_input I\n", Abc_ObjName(pNet) );
+ else
+ {
+ if(!Abc_NtkIsComb(pNet->pNtk) && Abc_ObjFaninNum(pFanin) && Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) )
+ {
+ pLatch=Abc_ObjFanin0(pFanin);
+ pNetLi=Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+ pNetLo=Abc_ObjFanout0(Abc_ObjFanout0(pLatch));
+ fprintf( pFile, "%s_%s_latch I : ", Abc_ObjName(pNetLi), Abc_ObjName(pNetLo) );
+ }
+ else
+ {
+ Abc_ObjForEachFanin( pFanin, pNeti, j )
+ fprintf( pFile, "%s_", Abc_ObjName(pNeti) );
+ Abc_ObjForEachFanout( pFanin, pNeto, j )
+ fprintf( pFile, "%s_", Abc_ObjName(pNeto) );
+ if ( Abc_NtkHasMapping(pNet->pNtk) )
+ fprintf( pFile, "%s : ", Mio_GateReadName(pFanin->pData) );
+ else
+ fprintf( pFile, "name I : " );
+ }
+ // offsets are simlply 0.00 0.00 at the moment
+ fprintf( pFile, "%.2f %.2f\n", .0, .0 );
+ }
+
+ Abc_ObjForEachFanout( pNet, pFanout, i )
+ {
+ if ( Abc_ObjIsPo(pFanout) )
+ fprintf( pFile, "o%s_output O\n", Abc_ObjName(pNet) );
+ else
+ {
+ if(!Abc_NtkIsComb(pNet->pNtk) && Abc_ObjFanoutNum(pFanout) && Abc_ObjIsLatch( Abc_ObjFanout0(pFanout) ) )
+ {
+ pLatch=Abc_ObjFanout0(pFanout);
+ pNetLi=Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
+ pNetLo=Abc_ObjFanout0(Abc_ObjFanout0(pLatch));
+ fprintf( pFile, "%s_%s_latch O : ", Abc_ObjName(pNetLi), Abc_ObjName(pNetLo) );
+ }
+ else
+ {
+ Abc_ObjForEachFanin( pFanout, pNeti, j )
+ fprintf( pFile, "%s_", Abc_ObjName(pNeti) );
+ Abc_ObjForEachFanout( pFanout, pNeto, j )
+ fprintf( pFile, "%s_", Abc_ObjName(pNeto) );
+ if ( Abc_NtkHasMapping(pNet->pNtk) )
+ fprintf( pFile, "%s : ", Mio_GateReadName(pFanout->pData) );
+ else
+ fprintf( pFile, "name O : " );
+ }
+ // offsets are simlply 0.00 0.00 at the moment
+ fprintf( pFile, "%.2f %.2f\n", .0, .0 );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the network into a BOOK file with the given name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkBuildLayout( FILE * pFileScl, FILE * pFilePl, Abc_Ntk_t * pNtk, double aspectRatio, double whiteSpace, unsigned coreCellArea )
+{
+ unsigned numCoreCells=Abc_NtkNodeNum(pNtk)+Abc_NtkLatchNum(pNtk);
+ double targetLayoutArea = coreCellArea/(1.0-(whiteSpace/100.0));
+ unsigned numCoreRows=(aspectRatio>0.0) ? (Abc_Rint(sqrt(targetLayoutArea/aspectRatio)/coreHeight)) : 0;
+ unsigned numTerms=Abc_NtkPiNum(pNtk)+Abc_NtkPoNum(pNtk);
+ unsigned totalWidth=coreCellArea/coreHeight;
+ double layoutHeight = numCoreRows * coreHeight;
+ double layoutWidth = Abc_Rint(targetLayoutArea/layoutHeight);
+ double actualLayoutArea = layoutWidth * layoutHeight;
+
+ printf( "Core cell height(==site height) is %d\n", coreHeight );
+ printf( "Total core cell width is %d giving an ave width of %f\n", totalWidth, (double)(totalWidth/numCoreCells));
+ printf( "Target Dimensions:\n" );
+ printf( " Area : %f\n", targetLayoutArea );
+ printf( " WS%% : %f\n", whiteSpace );
+ printf( " AR : %f\n", aspectRatio );
+ printf( "Actual Dimensions:\n" );
+ printf( " Width : %f\n", layoutWidth );
+ printf( " Height: %f (%d rows)\n", layoutHeight, numCoreRows);
+ printf( " Area : %f\n", actualLayoutArea );
+ printf( " WS%% : %f\n", 100*(actualLayoutArea-coreCellArea)/actualLayoutArea );
+ printf( " AR : %f\n\n", layoutWidth/layoutHeight );
+
+ Io_NtkWriteScl( pFileScl, numCoreRows, layoutWidth );
+ Io_NtkWritePl( pFilePl, pNtk, numTerms, layoutHeight, layoutWidth );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the network into a BOOK file with the given name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWriteScl( FILE * pFile, unsigned numCoreRows, double layoutWidth )
+{
+ int origin_y=0;
+ char * rowOrients[2] = {"N", "FS"};
+ char symmetry='Y';
+ double sitewidth=1.0;
+ double spacing=1.0;
+
+ int rowId;
+ // write the forehead
+ fprintf( pFile, "UCLA scl 1.0\n\n" );
+ fprintf( pFile, "Numrows : %d\n\n", numCoreRows );
+
+ for( rowId=0 ; rowId<numCoreRows ; rowId++, origin_y += coreHeight )
+ {
+ fprintf( pFile, "CoreRow Horizontal\n" );
+ fprintf( pFile, " Coordinate : \t%d\n", origin_y);
+ fprintf( pFile, " Height : \t%d\n", coreHeight);
+ fprintf( pFile, " Sitewidth : \t%d\n", (unsigned)sitewidth );
+ fprintf( pFile, " Sitespacing : \t%d\n", (unsigned)spacing );
+ fprintf( pFile, " Siteorient : \t%s\n", rowOrients[rowId%2] );
+ //if( coreRow[i].site.symmetry.rot90 || coreRow[i].site.symmetry.y || coreRow[i].site.symmetry.x )
+ fprintf( pFile, " Sitesymmetry : \t%c\n", symmetry );
+ //else fprintf( pFile, "Sitesymmetry : \t\t\t1\n" );
+ fprintf( pFile, " SubrowOrigin : \t%d Numsites : \t%d\n", 0, (unsigned)layoutWidth );
+ fprintf( pFile, "End\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Write the network into a BOOK file with the given name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Io_NtkWritePl( FILE * pFile, Abc_Ntk_t * pNtk, unsigned numTerms, double layoutWidth, double layoutHeight )
+{
+ Abc_Obj_t * pTerm, * pLatch, * pNode;
+ Vec_Ptr_t * vTerms = Vec_PtrAlloc ( numTerms );
+ Vec_Ptr_t * vOrderedTerms = Vec_PtrAlloc ( numTerms );
+ double layoutPerim = 2*layoutWidth + 2*layoutHeight;
+ double nextLoc_x, nextLoc_y;
+ double delta;
+ unsigned termsOnTop, termsOnBottom, termsOnLeft, termsOnRight;
+ int i, t;
+
+ termsOnTop = termsOnBottom = (unsigned)(Abc_Rint(numTerms*(layoutWidth/layoutPerim)));
+ termsOnLeft = numTerms - (termsOnTop+termsOnBottom);
+ termsOnRight = (unsigned)(ceil(termsOnLeft/2.0));
+ termsOnLeft -= termsOnRight;
+
+ Abc_NtkForEachPi( pNtk, pTerm, i )
+ Vec_PtrPush( vTerms, pTerm );
+ Abc_NtkForEachPo( pNtk, pTerm, i )
+ Vec_PtrPush( vTerms, pTerm );
+ // Ordering Pads
+ vOrderedTerms=Io_NtkOrderingPads( pNtk, vTerms );
+ assert( termsOnTop+termsOnBottom+termsOnLeft+termsOnRight == Vec_PtrSize(vOrderedTerms) );
+
+ printf( "Done constructing layout region\n" );
+ printf( "Terminals: %d\n", numTerms );
+ printf( " Top: %d\n", termsOnTop );
+ printf( " Bottom: %d\n", termsOnBottom );
+ printf( " Left: %d\n", termsOnLeft );
+ printf( " Right: %d\n", termsOnRight );
+
+ fprintf( pFile, "UCLA pl 1.0\n\n" );
+
+ nextLoc_x = floor(.0);
+ nextLoc_y = ceil(layoutHeight + 2*coreHeight);
+ delta = layoutWidth / termsOnTop;
+ for(t = 0; t < termsOnTop; t++)
+ {
+ pTerm = Vec_PtrEntry( vOrderedTerms, t );
+ if( Abc_ObjIsPi(pTerm) )
+ fprintf( pFile, "i%s_input\t\t", Abc_ObjName(Abc_ObjFanout0(pTerm)) );
+ else
+ fprintf( pFile, "o%s_output\t\t", Abc_ObjName(Abc_ObjFanin0(pTerm)) );
+ if( t && Abc_Rint(nextLoc_x) < Abc_Rint(nextLoc_x-delta)+termWidth )
+ nextLoc_x++;
+ fprintf( pFile, "%d\t\t%d\t: %s /FIXED\n", (int)Abc_Rint(nextLoc_x), (int)Abc_Rint(nextLoc_y), "FS" );
+ nextLoc_x += delta;
+ }
+
+ nextLoc_x = floor(.0);
+ nextLoc_y = floor(.0 - 2*coreHeight - termHeight);
+ delta = layoutWidth / termsOnBottom;
+ for(;t < termsOnTop+termsOnBottom; t++)
+ {
+ pTerm = Vec_PtrEntry( vOrderedTerms, t );
+ if( Abc_ObjIsPi(pTerm) )
+ fprintf( pFile, "i%s_input\t\t", Abc_ObjName(Abc_ObjFanout0(pTerm)) );
+ else
+ fprintf( pFile, "o%s_output\t\t", Abc_ObjName(Abc_ObjFanin0(pTerm)) );
+ if( t!=termsOnTop && Abc_Rint(nextLoc_x) < Abc_Rint(nextLoc_x-delta)+termWidth )
+ nextLoc_x++;
+ fprintf( pFile, "%d\t\t%d\t: %s /FIXED\n", (int)Abc_Rint(nextLoc_x), (int)Abc_Rint(nextLoc_y), "N" );
+ nextLoc_x += delta;
+ }
+
+ nextLoc_x = floor(.0-2*coreHeight-termWidth);
+ nextLoc_y = floor(.0);
+ delta = layoutHeight / termsOnLeft;
+ for(;t < termsOnTop+termsOnBottom+termsOnLeft; t++)
+ {
+ pTerm = Vec_PtrEntry( vOrderedTerms, t );
+ if( Abc_ObjIsPi(pTerm) )
+ fprintf( pFile, "i%s_input\t\t", Abc_ObjName(Abc_ObjFanout0(pTerm)) );
+ else
+ fprintf( pFile, "o%s_output\t\t", Abc_ObjName(Abc_ObjFanin0(pTerm)) );
+ if( Abc_Rint(nextLoc_y) < Abc_Rint(nextLoc_y-delta)+termHeight )
+ nextLoc_y++;
+ fprintf( pFile, "%d\t\t%d\t: %s /FIXED\n", (int)Abc_Rint(nextLoc_x), (int)Abc_Rint(nextLoc_y), "E" );
+ nextLoc_y += delta;
+ }
+
+ nextLoc_x = ceil(layoutWidth+2*coreHeight);
+ nextLoc_y = floor(.0);
+ delta = layoutHeight / termsOnRight;
+ for(;t < termsOnTop+termsOnBottom+termsOnLeft+termsOnRight; t++)
+ {
+ pTerm = Vec_PtrEntry( vOrderedTerms, t );
+ if( Abc_ObjIsPi(pTerm) )
+ fprintf( pFile, "i%s_input\t\t", Abc_ObjName(Abc_ObjFanout0(pTerm)) );
+ else
+ fprintf( pFile, "o%s_output\t\t", Abc_ObjName(Abc_ObjFanin0(pTerm)) );
+ if( Abc_Rint(nextLoc_y) < Abc_Rint(nextLoc_y-delta)+termHeight )
+ nextLoc_y++;
+ fprintf( pFile, "%d\t\t%d\t: %s /FIXED\n", (int)Abc_Rint(nextLoc_x), (int)Abc_Rint(nextLoc_y), "FW" );
+ nextLoc_y += delta;
+ }
+
+ if( !Abc_NtkIsComb(pNtk) )
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ Io_NtkWriteLatchNode( pFile, pLatch, PL );
+ fprintf( pFile, "\t%d\t\t%d\t: %s\n", 0, 0, "N" );
+ }
+
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ Io_NtkWriteIntNode( pFile, pNode, PL );
+ fprintf( pFile, "\t%d\t\t%d\t: %s\n", 0, 0, "N" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the closest I/O to a given I/O.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Io_NtkOrderingPads( Abc_Ntk_t * pNtk, Vec_Ptr_t * vTerms )
+{
+ ProgressBar * pProgress;
+ unsigned numTerms=Vec_PtrSize(vTerms);
+ unsigned termIdx=0, termCount=0;
+ bool * pOrdered = (bool *)malloc(sizeof(bool)*numTerms);
+ bool newNeighbor=1;
+ Vec_Ptr_t * vOrderedTerms = Vec_PtrAlloc ( numTerms );
+ Abc_Obj_t * pNeighbor, * pNextTerm;
+ int i;
+
+ for( i=0 ; i<numTerms ; i++ )
+ pOrdered[i]=0;
+
+ pNextTerm = Vec_PtrEntry(vTerms, termIdx++);
+ pProgress = Extra_ProgressBarStart( stdout, numTerms );
+ while( termCount < numTerms && termIdx < numTerms )
+ {
+ if( pOrdered[Abc_ObjId(pNextTerm)] && !newNeighbor )
+ {
+ pNextTerm = Vec_PtrEntry( vTerms, termIdx++ );
+ continue;
+ }
+ if(!Vec_PtrPushUnique( vOrderedTerms, pNextTerm ))
+ {
+ pOrdered[Abc_ObjId(pNextTerm)]=1;
+ termCount++;
+ }
+ pNeighbor=Io_NtkBfsPads( pNtk, pNextTerm, numTerms, pOrdered );
+ if( (newNeighbor=!Vec_PtrPushUnique( vOrderedTerms, pNeighbor )) )
+ {
+ pOrdered[Abc_ObjId(pNeighbor)]=1;
+ termCount++;
+ pNextTerm=pNeighbor;
+ }
+ else if(termIdx < numTerms)
+ pNextTerm = Vec_PtrEntry( vTerms, termIdx++ );
+
+ Extra_ProgressBarUpdate( pProgress, termCount, NULL );
+ }
+ Extra_ProgressBarStop( pProgress );
+ assert(termCount==numTerms);
+ return vOrderedTerms;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the closest I/O to a given I/O.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Io_NtkBfsPads( Abc_Ntk_t * pNtk, Abc_Obj_t * pTerm, unsigned numTerms, bool * pOrdered )
+{
+ Vec_Ptr_t * vNeighbors = Vec_PtrAlloc ( numTerms );
+ Abc_Obj_t * pNet, * pNode, * pNeighbor;
+ bool foundNeighbor=0;
+ int i;
+
+ assert(Abc_ObjIsPi(pTerm) || Abc_ObjIsPo(pTerm) );
+ Abc_NtkIncrementTravId ( pNtk );
+ Abc_NodeSetTravIdCurrent( pTerm );
+ if(Abc_ObjIsPi(pTerm))
+ {
+ pNet = Abc_ObjFanout0(pTerm);
+ Abc_ObjForEachFanout( pNet, pNode, i )
+ Vec_PtrPush( vNeighbors, pNode );
+ }
+ else
+ {
+ pNet = Abc_ObjFanin0(pTerm);
+ Abc_ObjForEachFanin( pNet, pNode, i )
+ Vec_PtrPush( vNeighbors, pNode );
+ }
+
+ while ( Vec_PtrSize(vNeighbors) >0 )
+ {
+ pNeighbor = Vec_PtrEntry( vNeighbors, 0 );
+ assert( Abc_ObjIsNode(pNeighbor) || Abc_ObjIsTerm(pNeighbor) );
+ Vec_PtrRemove( vNeighbors, pNeighbor );
+
+ if( Abc_NodeIsTravIdCurrent( pNeighbor ) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pNeighbor );
+
+ if( ((Abc_ObjIsPi(pNeighbor) || Abc_ObjIsPo(pNeighbor))) && !pOrdered[Abc_ObjId(pNeighbor)] )
+ {
+ foundNeighbor=1;
+ break;
+ }
+ if( Abc_ObjFanoutNum( pNeighbor ) )
+ {
+ pNet=Abc_ObjFanout0( pNeighbor );
+ if( !Abc_NtkIsComb(pNtk) && Abc_ObjIsLatch(pNet) )
+ pNet=Abc_ObjFanout0( Abc_ObjFanout0(pNet) );
+ Abc_ObjForEachFanout( pNet, pNode, i )
+ if( !Abc_NodeIsTravIdCurrent(pNode) )
+ Vec_PtrPush( vNeighbors, pNode );
+ }
+ if( Abc_ObjFaninNum( pNeighbor ) )
+ {
+ if( !Abc_NtkIsComb(pNtk) && Abc_ObjIsLatch(Abc_ObjFanin0(pNeighbor)) )
+ pNeighbor=Abc_ObjFanin0( Abc_ObjFanin0(pNeighbor) );
+ Abc_ObjForEachFanin( pNeighbor, pNet, i )
+ if( !Abc_NodeIsTravIdCurrent(pNode=Abc_ObjFanin0(pNet)) )
+ Vec_PtrPush( vNeighbors, pNode );
+ }
+ }
+ return ( foundNeighbor ) ? pNeighbor : pTerm;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Test is the node is nand2.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NodeIsNand2( Abc_Obj_t * pNode )
+{
+ Abc_Ntk_t * pNtk = pNode->pNtk;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
+ if ( Abc_ObjFaninNum(pNode) != 2 )
+ return 0;
+ if ( Abc_NtkHasSop(pNtk) )
+ return ( !strcmp((pNode->pData), "-0 1\n0- 1\n") ||
+ !strcmp((pNode->pData), "0- 1\n-0 1\n") ||
+ !strcmp((pNode->pData), "11 0\n") );
+ if ( Abc_NtkHasMapping(pNtk) )
+ return pNode->pData == Mio_LibraryReadNand2(Abc_FrameReadLibGen());
+ assert( 0 );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Test is the node is nand2.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NodeIsNor2( Abc_Obj_t * pNode )
+{
+ Abc_Ntk_t * pNtk = pNode->pNtk;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
+ if ( Abc_ObjFaninNum(pNode) != 2 )
+ return 0;
+ if ( Abc_NtkHasSop(pNtk) )
+ return ( !strcmp((pNode->pData), "00 1\n") );
+ assert( 0 );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Test is the node is and2.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NodeIsAnd2( Abc_Obj_t * pNode )
+{
+ Abc_Ntk_t * pNtk = pNode->pNtk;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
+ if ( Abc_ObjFaninNum(pNode) != 2 )
+ return 0;
+ if ( Abc_NtkHasSop(pNtk) )
+ return Abc_SopIsAndType((pNode->pData));
+ if ( Abc_NtkHasMapping(pNtk) )
+ return pNode->pData == Mio_LibraryReadAnd2(Abc_FrameReadLibGen());
+ assert( 0 );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Test is the node is or2.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NodeIsOr2( Abc_Obj_t * pNode )
+{
+ Abc_Ntk_t * pNtk = pNode->pNtk;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
+ if ( Abc_ObjFaninNum(pNode) != 2 )
+ return 0;
+ if ( Abc_NtkHasSop(pNtk) )
+ return ( Abc_SopIsOrType((pNode->pData)) ||
+ !strcmp((pNode->pData), "01 0\n") ||
+ !strcmp((pNode->pData), "10 0\n") ||
+ !strcmp((pNode->pData), "00 0\n") );
+ //off-sets, too
+ assert( 0 );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Test is the node is xor2.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NodeIsXor2( Abc_Obj_t * pNode )
+{
+ Abc_Ntk_t * pNtk = pNode->pNtk;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
+ if ( Abc_ObjFaninNum(pNode) != 2 )
+ return 0;
+ if ( Abc_NtkHasSop(pNtk) )
+ return ( !strcmp((pNode->pData), "01 1\n10 1\n") || !strcmp((pNode->pData), "10 1\n01 1\n") );
+ assert( 0 );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Test is the node is xnor2.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_NodeIsXnor2( Abc_Obj_t * pNode )
+{
+ Abc_Ntk_t * pNtk = pNode->pNtk;
+ assert( Abc_NtkIsNetlist(pNtk) );
+ assert( Abc_ObjIsNode(pNode) );
+ if ( Abc_ObjFaninNum(pNode) != 2 )
+ return 0;
+ if ( Abc_NtkHasSop(pNtk) )
+ return ( !strcmp((pNode->pData), "11 1\n00 1\n") || !strcmp((pNode->pData), "00 1\n11 1\n") );
+ assert( 0 );
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/base/io/io_.c b/src/base/io/io_.c
deleted file mode 100644
index b24d1299..00000000
--- a/src/base/io/io_.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/**CFile****************************************************************
-
- FileName [io_.c]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [Command processing package.]
-
- Synopsis [Procedure to read network from file.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: io_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#include "ioAbc.h"
-
-////////////////////////////////////////////////////////////////////////
-/// DECLARATIONS ///
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFINITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
-
-
diff --git a/src/base/io/module.make b/src/base/io/module.make
index bb35a7fc..6f4e2539 100644
--- a/src/base/io/module.make
+++ b/src/base/io/module.make
@@ -16,6 +16,7 @@ SRC += src/base/io/io.c \
src/base/io/ioWriteBench.c \
src/base/io/ioWriteBlif.c \
src/base/io/ioWriteBlifMv.c \
+ src/base/io/ioWriteBook.c \
src/base/io/ioWriteCnf.c \
src/base/io/ioWriteDot.c \
src/base/io/ioWriteEqn.c \
diff --git a/src/base/main/main.c b/src/base/main/main.c
index bfa91ddc..a9d610fd 100644
--- a/src/base/main/main.c
+++ b/src/base/main/main.c
@@ -216,14 +216,14 @@ int main( int argc, char * argv[] )
if ( fStatus == -1 || fStatus == -2 )
break;
}
- }
+ }
// if the memory should be freed, quit packages
if ( fStatus < 0 )
{
Abc_Stop();
- }
- return 0;
+ }
+ return 0;
usage:
Abc_UtilsPrintHello( pAbc );
diff --git a/src/base/main/main.h b/src/base/main/main.h
index af0ed24d..159122d2 100644
--- a/src/base/main/main.h
+++ b/src/base/main/main.h
@@ -65,15 +65,16 @@ typedef struct Abc_Frame_t_ Abc_Frame_t;
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
+
#ifdef WIN32
-#define DLLEXPORT __declspec(dllexport)
-#define DLLIMPORT __declspec(dllimport)
+#define ABC_DLLEXPORT __declspec(dllexport)
+#define ABC_DLLIMPORT __declspec(dllimport)
#else /* defined(WIN32) */
-#define DLLIMPORT
+#define ABC_DLLIMPORT
#endif /* defined(WIN32) */
#ifndef ABC_DLL
-#define ABC_DLL DLLIMPORT
+#define ABC_DLL ABC_DLLIMPORT
#endif
/*=== main.c ===========================================================*/
@@ -103,6 +104,7 @@ extern ABC_DLL Vec_Ptr_t * Abc_FrameReadStore();
extern ABC_DLL int Abc_FrameReadStoreSize();
extern ABC_DLL void * Abc_FrameReadLibLut();
extern ABC_DLL void * Abc_FrameReadLibGen();
+extern ABC_DLL void * Abc_FrameReadLibGen2();
extern ABC_DLL void * Abc_FrameReadLibSuper();
extern ABC_DLL void * Abc_FrameReadLibVer();
extern ABC_DLL void * Abc_FrameReadManDd();
@@ -114,6 +116,7 @@ extern ABC_DLL void Abc_FrameSetNtkStore( Abc_Ntk_t * pNtk );
extern ABC_DLL void Abc_FrameSetNtkStoreSize( int nStored );
extern ABC_DLL void Abc_FrameSetLibLut( void * pLib );
extern ABC_DLL void Abc_FrameSetLibGen( void * pLib );
+extern ABC_DLL void Abc_FrameSetLibGen2( void * pLib );
extern ABC_DLL void Abc_FrameSetLibSuper( void * pLib );
extern ABC_DLL void Abc_FrameSetLibVer( void * pLib );
extern ABC_DLL void Abc_FrameSetFlag( char * pFlag, char * pValue );
diff --git a/src/base/main/mainFrame.c b/src/base/main/mainFrame.c
index f02ade1c..23e9184e 100644
--- a/src/base/main/mainFrame.c
+++ b/src/base/main/mainFrame.c
@@ -47,6 +47,7 @@ Vec_Ptr_t * Abc_FrameReadStore() { return s_GlobalFrame->vSt
int Abc_FrameReadStoreSize() { return Vec_PtrSize(s_GlobalFrame->vStore); }
void * Abc_FrameReadLibLut() { return s_GlobalFrame->pLibLut; }
void * Abc_FrameReadLibGen() { return s_GlobalFrame->pLibGen; }
+void * Abc_FrameReadLibGen2() { return s_GlobalFrame->pLibGen2; }
void * Abc_FrameReadLibSuper() { return s_GlobalFrame->pLibSuper; }
void * Abc_FrameReadLibVer() { return s_GlobalFrame->pLibVer; }
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; }
@@ -55,6 +56,7 @@ char * Abc_FrameReadFlag( char * pFlag ) { return Cmd_FlagReadByName
void Abc_FrameSetLibLut( void * pLib ) { s_GlobalFrame->pLibLut = pLib; }
void Abc_FrameSetLibGen( void * pLib ) { s_GlobalFrame->pLibGen = pLib; }
+void Abc_FrameSetLibGen2( void * pLib ) { s_GlobalFrame->pLibGen2 = pLib; }
void Abc_FrameSetLibSuper( void * pLib ) { s_GlobalFrame->pLibSuper = pLib; }
void Abc_FrameSetLibVer( void * pLib ) { s_GlobalFrame->pLibVer = pLib; }
void Abc_FrameSetFlag( char * pFlag, char * pValue ) { Cmd_FlagUpdateValue( s_GlobalFrame, pFlag, pValue ); }
diff --git a/src/base/main/mainInt.h b/src/base/main/mainInt.h
index becbfd6b..cfd945b7 100644
--- a/src/base/main/mainInt.h
+++ b/src/base/main/mainInt.h
@@ -71,6 +71,7 @@ struct Abc_Frame_t_
// libraries for mapping
void * pLibLut; // the current LUT library
void * pLibGen; // the current genlib
+ void * pLibGen2; // the current genlib
void * pLibSuper; // the current supergate library
void * pLibVer; // the current Verilog library
@@ -97,15 +98,16 @@ struct Abc_Frame_t_
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
+
#ifdef WIN32
-#define DLLEXPORT __declspec(dllexport)
-#define DLLIMPORT __declspec(dllimport)
+#define ABC_DLLEXPORT __declspec(dllexport)
+#define ABC_DLLIMPORT __declspec(dllimport)
#else /* defined(WIN32) */
-#define DLLIMPORT
+#define ABC_DLLIMPORT
#endif /* defined(WIN32) */
#ifndef ABC_DLL
-#define ABC_DLL DLLIMPORT
+#define ABC_DLL ABC_DLLIMPORT
#endif
/*=== mvMain.c ===========================================================*/
diff --git a/src/map/amap/amap.h b/src/map/amap/amap.h
new file mode 100644
index 00000000..ee845e7f
--- /dev/null
+++ b/src/map/amap/amap.h
@@ -0,0 +1,83 @@
+/**CFile****************************************************************
+
+ FileName [amap.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amap.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __AMAP_H__
+#define __AMAP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+
+typedef struct Amap_Par_t_ Amap_Par_t;
+struct Amap_Par_t_
+{
+ int nIterFlow; // iterations of area flow
+ int nIterArea; // iteratoins of exact area
+ int fUseMuxes; // enables the use of MUXes
+ int fUseXors; // enables the use of XORs
+ int fFreeInvs; // assume inverters are free (area = 0)
+ float fEpsilon; // used to compare floating point numbers
+ int fVerbose; // verbosity flag
+};
+
+typedef struct Amap_Out_t_ Amap_Out_t;
+struct Amap_Out_t_
+{
+ char * pName; // gate name
+ short Type; // node type (-1=input; 0=internal; 1=output)
+ short nFans; // number of fanins
+ int pFans[0]; // fanin
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== amapCore.c ==========================================================*/
+extern void Amap_ManSetDefaultParams( Amap_Par_t * pPars );
+extern Vec_Ptr_t * Amap_ManTest( Aig_Man_t * pAig, Amap_Par_t * pPars );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/map/amap/amapCore.c b/src/map/amap/amapCore.c
new file mode 100644
index 00000000..f1554862
--- /dev/null
+++ b/src/map/amap/amapCore.c
@@ -0,0 +1,103 @@
+/**CFile****************************************************************
+
+ FileName [amapCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis [Core mapping procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManSetDefaultParams( Amap_Par_t * p )
+{
+ memset( p, 0, sizeof(Amap_Par_t) );
+ p->nIterFlow = 1; // iterations of area flow
+ p->nIterArea = 4; // iteratoins of exact area
+ p->fUseMuxes = 0; // enables the use of MUXes
+ p->fUseXors = 1; // enables the use of XORs
+ p->fFreeInvs = 0; // assume inverters are free (area = 0)
+ p->fEpsilon = (float)0.001; // used to compare floating point numbers
+ p->fVerbose = 0; // verbosity flag
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Amap_ManTest( Aig_Man_t * pAig, Amap_Par_t * pPars )
+{
+ extern void * Abc_FrameReadLibGen2();
+ Vec_Ptr_t * vRes;
+ Amap_Man_t * p;
+ Amap_Lib_t * pLib;
+ int clkTotal = clock();
+ pLib = Abc_FrameReadLibGen2();
+ if ( pLib == NULL )
+ {
+ printf( "Library is not available.\n" );
+ return NULL;
+ }
+ p = Amap_ManStart( Aig_ManNodeNum(pAig) );
+ p->pPars = pPars;
+ p->pLib = pLib;
+ p->fAreaInv = pPars->fFreeInvs? 0.0 : pLib->pGateInv->dArea;
+ p->fUseMux = pPars->fUseMuxes && pLib->fHasMux;
+ p->fUseXor = pPars->fUseXors && pLib->fHasXor;
+ p->ppCutsTemp = CALLOC( Amap_Cut_t *, 2 * pLib->nNodes );
+ p->pMatsTemp = CALLOC( int, 2 * pLib->nNodes );
+ Amap_ManCreate( p, pAig );
+ Amap_ManMap( p );
+ vRes = NULL;
+ vRes = Amap_ManProduceMapped( p );
+ Amap_ManStop( p );
+if ( pPars->fVerbose )
+{
+PRT( "Total runtime", clock() - clkTotal );
+}
+ return vRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/amap/amapGraph.c b/src/map/amap/amapGraph.c
new file mode 100644
index 00000000..83cadc2c
--- /dev/null
+++ b/src/map/amap/amapGraph.c
@@ -0,0 +1,389 @@
+/**CFile****************************************************************
+
+ FileName [amapGraph.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis [Internal AIG manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapGraph.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManSetupObj( Amap_Man_t * p )
+{
+ Amap_Obj_t * pObj;
+ pObj = (Amap_Obj_t *)Aig_MmFixedEntryFetch( p->pMemObj );
+ memset( pObj, 0, sizeof(Amap_Obj_t) );
+ pObj->nFouts[0] = 1; // needed for flow to work in the first pass
+ pObj->Id = Vec_PtrSize(p->vObjs);
+ Vec_PtrPush( p->vObjs, pObj );
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates constant 1 node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManCreateConst1( Amap_Man_t * p )
+{
+ Amap_Obj_t * pObj;
+ pObj = Amap_ManSetupObj( p );
+ pObj->Type = AMAP_OBJ_CONST1;
+ pObj->fPhase = 1;
+ p->nObjs[AMAP_OBJ_CONST1]++;
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates primary input.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManCreatePi( Amap_Man_t * p )
+{
+ Amap_Obj_t * pObj;
+ pObj = Amap_ManSetupObj( p );
+ pObj->Type = AMAP_OBJ_PI;
+ pObj->IdPio = Vec_PtrSize( p->vPis );
+ Vec_PtrPush( p->vPis, pObj );
+ p->nObjs[AMAP_OBJ_PI]++;
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates primary output with the given driver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManCreatePo( Amap_Man_t * p, Amap_Obj_t * pFan0 )
+{
+ Amap_Obj_t * pObj;
+ pObj = Amap_ManSetupObj( p );
+ pObj->IdPio = Vec_PtrSize( p->vPos );
+ Vec_PtrPush( p->vPos, pObj );
+ pObj->Type = AMAP_OBJ_PO;
+ pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++;
+ pObj->Level = Amap_Regular(pFan0)->Level;
+ if ( p->nLevelMax < (int)pObj->Level )
+ p->nLevelMax = (int)pObj->Level;
+ p->nObjs[AMAP_OBJ_PO]++;
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the new node assuming it does not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManCreateAnd( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 )
+{
+ Amap_Obj_t * pObj;
+ pObj = Amap_ManSetupObj( p );
+ pObj->Type = AMAP_OBJ_AND;
+ pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++;
+ pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++;
+ assert( Amap_Lit2Var(pObj->Fan[0]) != Amap_Lit2Var(pObj->Fan[1]) );
+ pObj->fPhase = Amap_ObjPhaseReal(pFan0) & Amap_ObjPhaseReal(pFan1);
+ pObj->Level = 1 + AIG_MAX( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level );
+ if ( p->nLevelMax < (int)pObj->Level )
+ p->nLevelMax = (int)pObj->Level;
+ p->nObjs[AMAP_OBJ_AND]++;
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the new node assuming it does not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManCreateXor( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 )
+{
+ Amap_Obj_t * pObj;
+ pObj = Amap_ManSetupObj( p );
+ pObj->Type = AMAP_OBJ_XOR;
+ pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++;
+ pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++;
+ pObj->fPhase = Amap_ObjPhaseReal(pFan0) ^ Amap_ObjPhaseReal(pFan1);
+ pObj->Level = 2 + AIG_MAX( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level );
+ if ( p->nLevelMax < (int)pObj->Level )
+ p->nLevelMax = (int)pObj->Level;
+ p->nObjs[AMAP_OBJ_XOR]++;
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the new node assuming it does not exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManCreateMux( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pFanC )
+{
+ Amap_Obj_t * pObj;
+ pObj = Amap_ManSetupObj( p );
+ pObj->Type = AMAP_OBJ_MUX;
+ pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++;
+ pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++;
+ pObj->Fan[2] = Amap_ObjToLit(pFanC); Amap_Regular(pFanC)->nRefs++;
+ pObj->fPhase = (Amap_ObjPhaseReal(pFan1) & Amap_ObjPhaseReal(pFanC)) |
+ (Amap_ObjPhaseReal(pFan0) & ~Amap_ObjPhaseReal(pFanC));
+ pObj->Level = AIG_MAX( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level );
+ pObj->Level = 2 + AIG_MAX( pObj->Level, Amap_Regular(pFanC)->Level );
+ if ( p->nLevelMax < (int)pObj->Level )
+ p->nLevelMax = (int)pObj->Level;
+ p->nObjs[AMAP_OBJ_MUX]++;
+ return pObj;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the choice node.]
+
+ Description [Should be called after the equivalence class nodes are linked.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManCreateChoice( Amap_Man_t * p, Amap_Obj_t * pObj )
+{
+ Amap_Obj_t * pTemp;
+ // mark the node as a representative if its class
+// assert( pObj->fRepr == 0 );
+ pObj->fRepr = 1;
+ // update the level of this node (needed for correct required time computation)
+ for ( pTemp = pObj; pTemp; pTemp = Amap_ObjChoice(p, pTemp) )
+ {
+ pObj->Level = AIG_MAX( pObj->Level, pTemp->Level );
+// pTemp->nVisits++; pTemp->nVisitsCopy++;
+ }
+ // mark the largest level
+ if ( p->nLevelMax < (int)pObj->Level )
+ p->nLevelMax = (int)pObj->Level;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates XOR/MUX choices for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManCreateXorChoices( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pChoices[] )
+{
+ pChoices[0] = Amap_ManCreateXor( p, pFan0, pFan1 );
+ pChoices[1] = Amap_ManCreateXor( p, Amap_Not(pFan0), pFan1 );
+ pChoices[2] = Amap_ManCreateXor( p, pFan0, Amap_Not(pFan1) );
+ pChoices[3] = Amap_ManCreateXor( p, Amap_Not(pFan0), Amap_Not(pFan1) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates XOR/MUX choices for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManCreateMuxChoices( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pFanC, Amap_Obj_t * pChoices[] )
+{
+ pChoices[0] = Amap_ManCreateMux( p, pFan0, pFan1, pFanC );
+ pChoices[1] = Amap_ManCreateMux( p, Amap_Not(pFan0), Amap_Not(pFan1), pFanC );
+ pChoices[2] = Amap_ManCreateMux( p, pFan1, pFan0, Amap_Not(pFanC) );
+ pChoices[3] = Amap_ManCreateMux( p, Amap_Not(pFan1), Amap_Not(pFan0), Amap_Not(pFanC) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Drags pointer out through the copy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Amap_Obj_t * Amap_AndToObj( Aig_Obj_t * pObj )
+{
+ return Amap_NotCond( (Amap_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Obj_t * Amap_ManGetLast_rec( Amap_Man_t * p, Amap_Obj_t * pObj )
+{
+ if ( pObj->Equiv == 0 )
+ return pObj;
+ return Amap_ManGetLast_rec( p, Amap_ObjChoice(p, pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManCreate( Amap_Man_t * p, Aig_Man_t * pAig )
+{
+ Vec_Ptr_t * vNodes;
+ Amap_Obj_t * pChoices[4];
+ Aig_Obj_t * pObj, * pFanin, * pPrev, * pFan0, * pFan1, * pFanC;
+ int i, fChoices;
+ if ( pAig->pEquivs )
+ vNodes = Aig_ManDfsChoices( pAig );
+ else
+ vNodes = Aig_ManDfs( pAig, 1 );
+ p->pConst1 = Amap_ManCreateConst1( p );
+ // print warning about excessive memory usage
+ if ( p->pPars->fVerbose )
+ {
+ if ( 1.0 * Aig_ManObjNum(pAig) * sizeof(Amap_Obj_t) / (1<<30) > 0.1 )
+ printf( "Warning: Mapper allocates %.3f Gb for subject graph with %d objects.\n",
+ 1.0 * Aig_ManObjNum(pAig) * sizeof(Amap_Obj_t) / (1<<30), Aig_ManObjNum(pAig) );
+ }
+ // create PIs and remember them in the old nodes
+ Aig_ManCleanData(pAig);
+ Aig_ManConst1(pAig)->pData = Amap_ManConst1( p );
+ Aig_ManForEachPi( pAig, pObj, i )
+ pObj->pData = Amap_ManCreatePi( p );
+ // load the AIG into the mapper
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ fChoices = 0;
+ if ( p->fUseXor && Aig_ObjRecognizeExor(pObj, &pFan0, &pFan1 ) )
+ {
+ Amap_ManCreateXorChoices( p, Amap_AndToObj(pFan0), Amap_AndToObj(pFan1), pChoices );
+ fChoices = 1;
+ }
+ else if ( p->fUseMux && Aig_ObjIsMuxType(pObj) )
+ {
+ pFanC = Aig_ObjRecognizeMux( pObj, &pFan1, &pFan0 );
+ Amap_ManCreateMuxChoices( p, Amap_AndToObj(pFan0), Amap_AndToObj(pFan1), Amap_AndToObj(pFanC), pChoices );
+ fChoices = 1;
+ }
+ pObj->pData = Amap_ManCreateAnd( p, (Amap_Obj_t *)Aig_ObjChild0Copy(pObj), (Amap_Obj_t *)Aig_ObjChild1Copy(pObj) );
+ if ( fChoices )
+ {
+ p->nChoicesAdded++;
+ Amap_ObjSetChoice( (Amap_Obj_t *)pObj->pData, pChoices[0] );
+ Amap_ObjSetChoice( pChoices[0], pChoices[1] );
+ Amap_ObjSetChoice( pChoices[1], pChoices[2] );
+ Amap_ObjSetChoice( pChoices[2], pChoices[3] );
+ Amap_ManCreateChoice( p, (Amap_Obj_t *)pObj->pData );
+ }
+ if ( Aig_ObjIsChoice( pAig, pObj ) )
+ {
+// assert( !fChoices );
+ p->nChoicesGiven++;
+ for ( pPrev = pObj, pFanin = Aig_ObjEquiv(pAig, pObj); pFanin; pPrev = pFanin, pFanin = Aig_ObjEquiv(pAig, pFanin) )
+ {
+ ((Amap_Obj_t *)pFanin->pData)->fRepr = 0;
+ Amap_ObjSetChoice( Amap_ManGetLast_rec(p, (Amap_Obj_t *)pPrev->pData),
+ (Amap_Obj_t *)pFanin->pData );
+ }
+ Amap_ManCreateChoice( p, (Amap_Obj_t *)pObj->pData );
+ }
+ }
+ Vec_PtrFree( vNodes );
+ // set the primary outputs without copying the phase
+ Aig_ManForEachPo( pAig, pObj, i )
+ pObj->pData = Amap_ManCreatePo( p, (Amap_Obj_t *)Aig_ObjChild0Copy(pObj) );
+ if ( p->pPars->fVerbose )
+ printf( "Performing mapping with %d given and %d created choices.\n",
+ p->nChoicesGiven, p->nChoicesAdded );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/amap/amapInt.h b/src/map/amap/amapInt.h
new file mode 100644
index 00000000..954790c9
--- /dev/null
+++ b/src/map/amap/amapInt.h
@@ -0,0 +1,380 @@
+/**CFile****************************************************************
+
+ FileName [amapInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __AMAP_INT_H__
+#define __AMAP_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "aig.h"
+#include "amap.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+// the largest gate size in the library
+// (gates above this size will be ignored)
+#define AMAP_MAXINS 15
+
+#define AMAP_STRING_CONST0 "CONST0"
+#define AMAP_STRING_CONST1 "CONST1"
+
+// object types
+typedef enum {
+ AMAP_OBJ_NONE, // 0: non-existent object
+ AMAP_OBJ_CONST1, // 1: constant 1
+ AMAP_OBJ_PI, // 2: primary input
+ AMAP_OBJ_PO, // 3: primary output
+ AMAP_OBJ_AND, // 4: AND node
+ AMAP_OBJ_XOR, // 5: XOR node
+ AMAP_OBJ_MUX, // 6: MUX node
+ AMAP_OBJ_VOID // 7: unused object
+} Amap_Type_t;
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Amap_Lib_t_ Amap_Lib_t;
+typedef struct Amap_Pin_t_ Amap_Pin_t;
+typedef struct Amap_Gat_t_ Amap_Gat_t;
+typedef struct Amap_Nod_t_ Amap_Nod_t;
+typedef struct Amap_Set_t_ Amap_Set_t;
+
+typedef struct Amap_Man_t_ Amap_Man_t;
+typedef struct Amap_Obj_t_ Amap_Obj_t;
+typedef struct Amap_Cut_t_ Amap_Cut_t;
+typedef struct Amap_Mat_t_ Amap_Mat_t;
+
+struct Amap_Man_t_
+{
+ // user data
+ Amap_Par_t * pPars;
+ Amap_Lib_t * pLib;
+ // internal parameters
+ float fEpsilonInternal;
+ float fAreaInv;
+ int fUseXor;
+ int fUseMux;
+ // internal AIG with choices
+ Vec_Ptr_t * vPis;
+ Vec_Ptr_t * vPos;
+ Vec_Ptr_t * vObjs;
+ Aig_MmFixed_t * pMemObj;
+ Aig_MmFlex_t * pMemCuts;
+ Aig_MmFlex_t * pMemCutBest;
+ Aig_MmFlex_t * pMemTemp;
+ Amap_Obj_t * pConst1;
+ int nObjs[AMAP_OBJ_VOID];
+ int nLevelMax;
+ int nChoicesGiven;
+ int nChoicesAdded;
+ // mapping data-structures
+ Vec_Int_t * vTemp;
+ int * pMatsTemp;
+ Amap_Cut_t ** ppCutsTemp;
+ Amap_Cut_t * pCutsPi;
+ Vec_Ptr_t * vCuts0;
+ Vec_Ptr_t * vCuts1;
+ Vec_Ptr_t * vCuts2;
+ // statistics
+ int nCutsUsed;
+ int nCutsTried;
+ int nCutsTried3;
+ int nBytesUsed;
+};
+struct Amap_Lib_t_
+{
+ char * pName; // library name
+ Vec_Ptr_t * vGates; // represenation of gates
+ Vec_Ptr_t * vSorted; // gates sorted for area-only mapping
+ Vec_Ptr_t * vSelect; // gates selected for area-only mapping
+ Amap_Gat_t * pGate0; // the constant zero gate
+ Amap_Gat_t * pGate1; // the constant one gate
+ Amap_Gat_t * pGateBuf; // the buffer
+ Amap_Gat_t * pGateInv; // the inverter
+ Aig_MmFlex_t * pMemGates; // memory manager for objects
+ int fHasXor; // XOR/NXOR gates are present
+ int fHasMux; // MUX/NMUX gates are present
+ // structural representation
+ int fVerbose; // enable detailed statistics
+ Amap_Nod_t * pNodes; // representation nodes
+ int nNodes; // the number of nodes used
+ int nNodesAlloc; // the number of nodes allocated
+ Vec_Ptr_t * vRules; // the rule of AND gate
+ Vec_Ptr_t * vRulesX; // the rule of XOR gate
+ Vec_Int_t * vRules3; // the rule of MUX gate
+ int ** pRules; // simplified representation
+ int ** pRulesX; // simplified representation
+ Aig_MmFlex_t * pMemSet; // memory manager for sets
+ int nSets; // the number of sets created
+};
+struct Amap_Pin_t_
+{
+ char * pName;
+ int Phase;
+ double dLoadInput;
+ double dLoadMax;
+ double dDelayBlockRise;
+ double dDelayFanoutRise;
+ double dDelayBlockFall;
+ double dDelayFanoutFall;
+ double dDelayBlockMax;
+};
+struct Amap_Gat_t_
+{
+ Amap_Lib_t * pLib; // library
+ char * pName; // the name of the gate
+ char * pOutName; // name of the output
+ double dArea; // the area of the gate
+ char * pForm; // the formula describing functionality
+ unsigned * pFunc; // truth table
+ unsigned Id : 23; // unique number of the gate
+ unsigned fMux : 1; // denotes MUX-gates
+ unsigned nPins : 8; // number of inputs
+ Amap_Pin_t Pins[0]; // description of inputs
+};
+struct Amap_Set_t_
+{
+ Amap_Set_t * pNext;
+ unsigned iGate : 16;
+ unsigned fInv : 1;
+ unsigned nIns : 15;
+ char Ins[AMAP_MAXINS];// mapping from gate inputs into fanins
+};
+struct Amap_Nod_t_
+{
+ unsigned Id : 16; // ID of the node
+ unsigned nSuppSize: 8; // support size
+ unsigned Type : 8; // the type of node
+ short iFan0; // fanin0
+ short iFan1; // fanin1
+ short iFan2; // fanin2
+ short Unused; //
+ Amap_Set_t * pSets; // implementable gates
+};
+struct Amap_Cut_t_
+{
+ unsigned iMat : 16;
+ unsigned fInv : 1;
+ unsigned nFans : 15;
+ int Fans[0];
+};
+struct Amap_Mat_t_
+{
+ Amap_Cut_t * pCut; // the cut
+ Amap_Set_t * pSet; // the set
+ float Area; // area flow / exact area of the node
+ float AveFan; // edge flow of the node
+ float Delay; // delay of the node
+};
+struct Amap_Obj_t_
+{
+ unsigned Type : 3;
+ unsigned Id : 29;
+ unsigned IdPio : 29;
+ unsigned fPhase : 1;
+ unsigned fRepr : 1;
+ unsigned fPolar : 1; // pCutBest->fInv ^ pSetBest->fInv
+ unsigned Level : 20;
+ unsigned nCuts : 12;
+ int nRefs;
+ int Equiv;
+ int Fan[3];
+ union {
+ void * pData;
+ int iData;
+ };
+ // match of the node
+ float EstRefs; // the number of estimated fanouts
+ int nFouts[2]; // the number of refs in each polarity
+ Amap_Mat_t Best; // the best match of the node
+};
+
+static inline int Amap_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; }
+static inline int Amap_Lit2Var( int Lit ) { return Lit >> 1; }
+static inline int Amap_LitIsCompl( int Lit ) { return Lit & 1; }
+static inline int Amap_LitNot( int Lit ) { return Lit ^ 1; }
+static inline int Amap_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); }
+static inline int Amap_LitRegular( int Lit ) { return Lit & ~01; }
+
+static inline Amap_Obj_t * Amap_Regular( Amap_Obj_t * p ) { return (Amap_Obj_t *)((PORT_PTRUINT_T)(p) & ~01); }
+static inline Amap_Obj_t * Amap_Not( Amap_Obj_t * p ) { return (Amap_Obj_t *)((PORT_PTRUINT_T)(p) ^ 01); }
+static inline Amap_Obj_t * Amap_NotCond( Amap_Obj_t * p, int c ) { return (Amap_Obj_t *)((PORT_PTRUINT_T)(p) ^ (c)); }
+static inline int Amap_IsComplement( Amap_Obj_t * p ) { return (int )(((PORT_PTRUINT_T)p) & 01); }
+
+static inline int Amap_ManPiNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_PI]; }
+static inline int Amap_ManPoNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_PO]; }
+static inline int Amap_ManAndNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_AND]; }
+static inline int Amap_ManXorNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_XOR]; }
+static inline int Amap_ManMuxNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_MUX]; }
+static inline int Amap_ManObjNum( Amap_Man_t * p ) { return Vec_PtrSize(p->vObjs); }
+static inline int Amap_ManNodeNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_AND] + p->nObjs[AMAP_OBJ_XOR] + p->nObjs[AMAP_OBJ_MUX]; }
+
+static inline Amap_Obj_t * Amap_ManConst1( Amap_Man_t * p ) { return p->pConst1; }
+static inline Amap_Obj_t * Amap_ManPi( Amap_Man_t * p, int i ) { return (Amap_Obj_t *)Vec_PtrEntry( p->vPis, i ); }
+static inline Amap_Obj_t * Amap_ManPo( Amap_Man_t * p, int i ) { return (Amap_Obj_t *)Vec_PtrEntry( p->vPos, i ); }
+static inline Amap_Obj_t * Amap_ManObj( Amap_Man_t * p, int i ) { return (Amap_Obj_t *)Vec_PtrEntry( p->vObjs, i ); }
+
+static inline int Amap_ObjIsConst1( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_CONST1; }
+static inline int Amap_ObjIsPi( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_PI; }
+static inline int Amap_ObjIsPo( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_PO; }
+static inline int Amap_ObjIsAnd( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_AND; }
+static inline int Amap_ObjIsXor( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_XOR; }
+static inline int Amap_ObjIsMux( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_MUX; }
+static inline int Amap_ObjIsNode( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_AND || pObj->Type == AMAP_OBJ_XOR || pObj->Type == AMAP_OBJ_MUX; }
+
+static inline int Amap_ObjToLit( Amap_Obj_t * pObj ) { return Amap_Var2Lit( Amap_Regular(pObj)->Id, Amap_IsComplement(pObj) ); }
+static inline Amap_Obj_t * Amap_ObjFanin0( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Amap_Lit2Var(pObj->Fan[0])); }
+static inline Amap_Obj_t * Amap_ObjFanin1( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Amap_Lit2Var(pObj->Fan[1])); }
+static inline Amap_Obj_t * Amap_ObjFanin2( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Amap_Lit2Var(pObj->Fan[2])); }
+static inline int Amap_ObjFaninC0( Amap_Obj_t * pObj ) { return Amap_LitIsCompl(pObj->Fan[0]); }
+static inline int Amap_ObjFaninC1( Amap_Obj_t * pObj ) { return Amap_LitIsCompl(pObj->Fan[1]); }
+static inline int Amap_ObjFaninC2( Amap_Obj_t * pObj ) { return Amap_LitIsCompl(pObj->Fan[2]); }
+static inline void * Amap_ObjCopy( Amap_Obj_t * pObj ) { return pObj->pData; }
+static inline int Amap_ObjLevel( Amap_Obj_t * pObj ) { return pObj->Level; }
+static inline void Amap_ObjSetLevel( Amap_Obj_t * pObj, int Level ) { pObj->Level = Level; }
+static inline void Amap_ObjSetCopy( Amap_Obj_t * pObj, void * pCopy ) { pObj->pData = pCopy; }
+static inline Amap_Obj_t * Amap_ObjChoice( Amap_Man_t * p, Amap_Obj_t * pObj ) { return pObj->Equiv? Amap_ManObj(p, pObj->Equiv) : NULL; }
+static inline void Amap_ObjSetChoice( Amap_Obj_t * pObj, Amap_Obj_t * pEqu){ assert(pObj->Equiv==0); pObj->Equiv = pEqu->Id; }
+static inline int Amap_ObjPhaseReal( Amap_Obj_t * pObj ) { return Amap_Regular(pObj)->fPhase ^ Amap_IsComplement(pObj); }
+static inline int Amap_ObjRefsTotal( Amap_Obj_t * pObj ) { return pObj->nFouts[0] + pObj->nFouts[1]; }
+
+static inline Amap_Gat_t * Amap_LibGate( Amap_Lib_t * p, int i ) { return Vec_PtrEntry(p->vGates, i); }
+static inline Amap_Nod_t * Amap_LibNod( Amap_Lib_t * p, int i ) { return p->pNodes + i; }
+
+// returns pointer to the next cut (internal cuts only)
+static inline Amap_Cut_t * Amap_ManCutNext( Amap_Cut_t * pCut )
+{ return (Amap_Cut_t *)(((int *)pCut)+pCut->nFans+1); }
+// returns pointer to the place of the next cut (temporary cuts only)
+static inline Amap_Cut_t ** Amap_ManCutNextP( Amap_Cut_t * pCut )
+{ return (Amap_Cut_t **)(((int *)pCut)+pCut->nFans+1); }
+
+extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars );
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// iterator over the primary inputs
+#define Amap_ManForEachPi( p, pObj, i ) \
+ Vec_PtrForEachEntry( p->vPis, pObj, i )
+// iterator over the primary outputs
+#define Amap_ManForEachPo( p, pObj, i ) \
+ Vec_PtrForEachEntry( p->vPos, pObj, i )
+// iterator over all objects, including those currently not used
+#define Amap_ManForEachObj( p, pObj, i ) \
+ Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else
+// iterator over all nodes
+#define Amap_ManForEachNode( p, pObj, i ) \
+ Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL || !Amap_ObjIsNode(pObj) ) {} else
+
+// iterator through all gates of the library
+#define Amap_LibForEachGate( pLib, pGate, i ) \
+ Vec_PtrForEachEntry( pLib->vGates, pGate, i )
+// iterator through all pins of the gate
+#define Amap_GateForEachPin( pGate, pPin ) \
+ for ( pPin = pGate->Pins; pPin < pGate->Pins + pGate->nPins; pPin++ )
+
+// iterator through all cuts of the node
+#define Amap_NodeForEachCut( pNode, pCut, i ) \
+ for ( i = 0, pCut = (Amap_Cut_t *)pNode->pData; i < (int)pNode->nCuts; \
+ i++, pCut = Amap_ManCutNext(pCut) )
+
+// iterator through all sets of one library node
+#define Amap_LibNodeForEachSet( pNod, pSet ) \
+ for ( pSet = pNod->pSets; pSet; pSet = pSet->pNext )
+
+// iterates through each fanin of the match
+#define Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i ) \
+ for ( i = 0; i < (int)(pM)->pCut->nFans && \
+ ((pFanin = Amap_ManObj((p), Amap_Lit2Var((pM)->pCut->Fans[Amap_Lit2Var((pM)->pSet->Ins[i])]))), 1) && \
+ ((fCompl = Amap_LitIsCompl((pM)->pSet->Ins[i]) ^ Amap_LitIsCompl((pM)->pCut->Fans[Amap_Lit2Var((pM)->pSet->Ins[i])])), 1); \
+ i++ )
+
+// iterates through each fanin of the match
+#define Amap_MatchForEachFanin( p, pM, pFanin, i ) \
+ for ( i = 0; i < (int)(pM)->pCut->nFans && \
+ ((pFanin = Amap_ManObj((p), Amap_Lit2Var((pM)->pCut->Fans[Amap_Lit2Var((pM)->pSet->Ins[i])]))), 1); \
+ i++ )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== amapCore.c ==========================================================*/
+/*=== amapGraph.c ==========================================================*/
+extern Amap_Obj_t * Amap_ManCreatePi( Amap_Man_t * p );
+extern Amap_Obj_t * Amap_ManCreatePo( Amap_Man_t * p, Amap_Obj_t * pFan0 );
+extern Amap_Obj_t * Amap_ManCreateAnd( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 );
+extern Amap_Obj_t * Amap_ManCreateXor( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 );
+extern Amap_Obj_t * Amap_ManCreateMux( Amap_Man_t * p, Amap_Obj_t * pFanC, Amap_Obj_t * pFan1, Amap_Obj_t * pFan0 );
+extern void Amap_ManCreateChoice( Amap_Man_t * p, Amap_Obj_t * pObj );
+extern void Amap_ManCreate( Amap_Man_t * p, Aig_Man_t * pAig );
+/*=== amapLib.c ==========================================================*/
+extern Amap_Lib_t * Amap_LibAlloc();
+extern void Amap_LibFree( Amap_Lib_t * p );
+extern int Amap_LibNumPinsMax( Amap_Lib_t * p );
+extern void Amap_LibWrite( FILE * pFile, Amap_Lib_t * pLib, int fPrintDsd );
+extern Vec_Ptr_t * Amap_LibSelectGates( Amap_Lib_t * p, int fVerbose );
+extern void Amap_LibPrintSelectedGates( Amap_Lib_t * p, int fAllGates );
+extern Amap_Lib_t * Amap_LibReadAndPrepare( char * pFileName, int fVerbose, int fVeryVerbose );
+/*=== amapMan.c ==========================================================*/
+extern Amap_Man_t * Amap_ManStart( int nNodes );
+extern void Amap_ManStop( Amap_Man_t * p );
+/*=== amapMatch.c ==========================================================*/
+extern void Amap_ManMap( Amap_Man_t * p );
+/*=== amapMerge.c ==========================================================*/
+extern void Amap_ManMerge( Amap_Man_t * p );
+/*=== amapOutput.c ==========================================================*/
+extern Vec_Ptr_t * Amap_ManProduceMapped( Amap_Man_t * p );
+/*=== amapParse.c ==========================================================*/
+extern int Amap_LibParseEquations( Amap_Lib_t * p, int fVerbose );
+/*=== amapPerm.c ==========================================================*/
+/*=== amapRead.c ==========================================================*/
+extern Amap_Lib_t * Amap_LibReadFile( char * pFileName, int fVerbose );
+/*=== amapRule.c ==========================================================*/
+extern short * Amap_LibTableFindNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor );
+extern void Amap_LibCreateRules( Amap_Lib_t * p, int fVeryVerbose );
+/*=== amapUniq.c ==========================================================*/
+extern int Amap_LibFindNode( Amap_Lib_t * pLib, int iFan0, int iFan1, int fXor );
+extern int Amap_LibFindMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 );
+extern int Amap_LibCreateVar( Amap_Lib_t * p );
+extern int Amap_LibCreateNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor );
+extern int Amap_LibCreateMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 );
+extern int ** Amap_LibLookupTableAlloc( Vec_Ptr_t * vVec, int fVerbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/map/amap/amapLib.c b/src/map/amap/amapLib.c
new file mode 100644
index 00000000..816f0703
--- /dev/null
+++ b/src/map/amap/amapLib.c
@@ -0,0 +1,361 @@
+/**CFile****************************************************************
+
+ FileName [amapLib.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis [Standard-cell library.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocs a library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Lib_t * Amap_LibAlloc()
+{
+ Amap_Lib_t * p;
+ p = (Amap_Lib_t *)ALLOC( Amap_Lib_t, 1 );
+ memset( p, 0, sizeof(Amap_Lib_t) );
+ p->vGates = Vec_PtrAlloc( 100 );
+ p->pMemGates = Aig_MmFlexStart();
+ p->pMemSet = Aig_MmFlexStart();
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocs a library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_LibFree( Amap_Lib_t * p )
+{
+ if ( p == NULL )
+ return;
+ if ( p->vSelect )
+ Vec_PtrFree( p->vSelect );
+ if ( p->vSorted )
+ Vec_PtrFree( p->vSorted );
+ if ( p->vGates )
+ Vec_PtrFree( p->vGates );
+ if ( p->vRules )
+ Vec_VecFree( (Vec_Vec_t *)p->vRules );
+ if ( p->vRulesX )
+ Vec_VecFree( (Vec_Vec_t *)p->vRulesX );
+ if ( p->vRules3 )
+ Vec_IntFree( p->vRules3 );
+ Aig_MmFlexStop( p->pMemGates, 0 );
+ Aig_MmFlexStop( p->pMemSet, 0 );
+ FREE( p->pRules );
+ FREE( p->pRulesX );
+ FREE( p->pNodes );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the largest gate size.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_LibNumPinsMax( Amap_Lib_t * p )
+{
+ Amap_Gat_t * pGate;
+ int i, Counter = 0;
+ Amap_LibForEachGate( p, pGate, i )
+ if ( Counter < (int)pGate->nPins )
+ Counter = pGate->nPins;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes one pin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_LibWritePin( FILE * pFile, Amap_Pin_t * pPin )
+{
+ char * pPhaseNames[10] = { "UNKNOWN", "INV", "NONINV" };
+ fprintf( pFile, " PIN " );
+ fprintf( pFile, "%9s ", pPin->pName );
+ fprintf( pFile, "%10s ", pPhaseNames[pPin->Phase] );
+ fprintf( pFile, "%6d ", (int)pPin->dLoadInput );
+ fprintf( pFile, "%6d ", (int)pPin->dLoadMax );
+ fprintf( pFile, "%6.2f ", pPin->dDelayBlockRise );
+ fprintf( pFile, "%6.2f ", pPin->dDelayFanoutRise );
+ fprintf( pFile, "%6.2f ", pPin->dDelayBlockFall );
+ fprintf( pFile, "%6.2f", pPin->dDelayFanoutFall );
+ fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes one gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_LibWriteGate( FILE * pFile, Amap_Gat_t * pGate, int fPrintDsd )
+{
+ Amap_Pin_t * pPin;
+ fprintf( pFile, "GATE " );
+ fprintf( pFile, "%12s ", pGate->pName );
+ fprintf( pFile, "%10.2f ", pGate->dArea );
+ fprintf( pFile, "%s=%s;\n", pGate->pOutName, pGate->pForm );
+ if ( fPrintDsd )
+ {
+ if ( pGate->pFunc == NULL )
+ printf( "Truth table is not available.\n" );
+ else
+ Kit_DsdPrintFromTruth( pGate->pFunc, pGate->nPins );
+ }
+ Amap_GateForEachPin( pGate, pPin )
+ Amap_LibWritePin( pFile, pPin );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_LibWrite( FILE * pFile, Amap_Lib_t * pLib, int fPrintDsd )
+{
+ Amap_Gat_t * pGate;
+ int i;
+ fprintf( pFile, "# The genlib library \"%s\".\n", pLib->pName );
+ Amap_LibForEachGate( pLib, pGate, i )
+ Amap_LibWriteGate( pFile, pGate, fPrintDsd );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares two gates by area.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_LibCompareGatesByArea( Amap_Gat_t ** pp1, Amap_Gat_t ** pp2 )
+{
+ double Diff = (*pp1)->dArea - (*pp2)->dArea;
+ if ( Diff < 0.0 )
+ return -1;
+ if ( Diff > 0.0 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares gates by area.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Amap_LibSortGatesByArea( Amap_Lib_t * pLib )
+{
+ Vec_Ptr_t * vSorted;
+ vSorted = Vec_PtrDup( pLib->vGates );
+ qsort( (void *)Vec_PtrArray(vSorted), Vec_PtrSize(vSorted), sizeof(void *),
+ (int (*)(const void *, const void *)) Amap_LibCompareGatesByArea );
+ return vSorted;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds min-area gate with the given function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Gat_t * Amap_LibFindGate( Amap_Lib_t * p, unsigned uTruth )
+{
+ Amap_Gat_t * pGate;
+ int i;
+ Vec_PtrForEachEntry( p->vSorted, pGate, i )
+ if ( pGate->nPins <= 5 && pGate->pFunc[0] == uTruth )
+ return pGate;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Selects gates useful for area-only mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Amap_LibSelectGates( Amap_Lib_t * p, int fVerbose )
+{
+ Vec_Ptr_t * vSelect;
+ Amap_Gat_t * pGate, * pGate2;
+ int i, k, clk = clock();
+ p->pGate0 = Amap_LibFindGate( p, 0 );
+ p->pGate1 = Amap_LibFindGate( p, ~0 );
+ p->pGateBuf = Amap_LibFindGate( p, 0xAAAAAAAA );
+ p->pGateInv = Amap_LibFindGate( p, ~0xAAAAAAAA );
+ vSelect = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( p->vSorted, pGate, i )
+ {
+ if ( pGate->pFunc == NULL )
+ continue;
+ Vec_PtrForEachEntryStop( p->vSorted, pGate2, k, i )
+ {
+ if ( pGate2->pFunc == NULL )
+ continue;
+ if ( pGate2->nPins != pGate->nPins )
+ continue;
+ if ( !memcmp( pGate2->pFunc, pGate->pFunc, sizeof(unsigned) * Aig_TruthWordNum(pGate->nPins) ) )
+ break;
+ }
+ if ( k < i )
+ continue;
+ Vec_PtrPush( vSelect, pGate );
+ }
+ return vSelect;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Selects gates useful for area-only mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_LibPrintSelectedGates( Amap_Lib_t * p, int fAllGates )
+{
+ Vec_Ptr_t * vArray;
+ Amap_Gat_t * pGate;
+ int i;
+ vArray = fAllGates? p->vGates : p->vSelect;
+ Vec_PtrForEachEntry( vArray, pGate, i )
+ {
+ printf( "Gate %4d : %15s Area = %9.2f\n", pGate->Id, pGate->pName, pGate->dArea );
+ printf( " Formula: %s=%s\n", pGate->pOutName, pGate->pForm );
+ printf( " DSD: " );
+ Kit_DsdPrintFromTruth( pGate->pFunc, pGate->nPins );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses equations for the gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Lib_t * Amap_LibReadAndPrepare( char * pFileName, int fVerbose, int fVeryVerbose )
+{
+ Amap_Lib_t * p;
+ int clk = clock();
+ p = Amap_LibReadFile( pFileName, fVerbose );
+ if ( fVerbose )
+ printf( "Read %d gates from file \"%s\".\n", Vec_PtrSize(p->vGates), pFileName );
+ if ( p == NULL )
+ return NULL;
+ if ( !Amap_LibParseEquations( p, fVerbose ) )
+ {
+ Amap_LibFree( p );
+ return NULL;
+ }
+ p->vSorted = Amap_LibSortGatesByArea( p );
+ p->vSelect = Amap_LibSelectGates( p, fVerbose );
+ if ( fVerbose )
+ {
+ printf( "Selected %d functionally unique gates. ",
+ Vec_PtrSize(p->vSelect), Vec_PtrSize(p->vSorted) );
+ PRT( "Time", clock() - clk );
+ }
+ clk = clock();
+ Amap_LibCreateRules( p, fVeryVerbose );
+ if ( fVerbose )
+ {
+ printf( "Created %d rules and %d matches. ",
+ p->nNodes, p->nSets );
+ PRT( "Time", clock() - clk );
+ }
+ return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/amap/amapMan.c b/src/map/amap/amapMan.c
new file mode 100644
index 00000000..521b4ffd
--- /dev/null
+++ b/src/map/amap/amapMan.c
@@ -0,0 +1,99 @@
+/**CFile****************************************************************
+
+ FileName [amapMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis [Mapping manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Man_t * Amap_ManStart( int nNodes )
+{
+ Amap_Man_t * p;
+ // start the manager
+ p = ALLOC( Amap_Man_t, 1 );
+ memset( p, 0, sizeof(Amap_Man_t) );
+ p->fEpsilonInternal = (float)0.01;
+ // allocate arrays for nodes
+ p->vPis = Vec_PtrAlloc( 100 );
+ p->vPos = Vec_PtrAlloc( 100 );
+ p->vObjs = Vec_PtrAlloc( 100 );
+ p->vTemp = Vec_IntAlloc( 100 );
+ p->vCuts0 = Vec_PtrAlloc( 100 );
+ p->vCuts1 = Vec_PtrAlloc( 100 );
+ p->vCuts2 = Vec_PtrAlloc( 100 );
+ // prepare the memory manager
+ p->pMemObj = Aig_MmFixedStart( sizeof(Amap_Obj_t), nNodes );
+ p->pMemCuts = Aig_MmFlexStart();
+ p->pMemCutBest = Aig_MmFlexStart();
+ p->pMemTemp = Aig_MmFlexStart();
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManStop( Amap_Man_t * p )
+{
+ Vec_PtrFree( p->vPis );
+ Vec_PtrFree( p->vPos );
+ Vec_PtrFree( p->vObjs );
+ Vec_PtrFree( p->vCuts0 );
+ Vec_PtrFree( p->vCuts1 );
+ Vec_PtrFree( p->vCuts2 );
+ Vec_IntFree( p->vTemp );
+ Aig_MmFixedStop( p->pMemObj, 0 );
+ Aig_MmFlexStop( p->pMemCuts, 0 );
+ Aig_MmFlexStop( p->pMemCutBest, 0 );
+ Aig_MmFlexStop( p->pMemTemp, 0 );
+ FREE( p->pMatsTemp );
+ FREE( p->ppCutsTemp );
+ FREE( p->pCutsPi );
+ free( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/amap/amapMatch.c b/src/map/amap/amapMatch.c
new file mode 100644
index 00000000..0b15a931
--- /dev/null
+++ b/src/map/amap/amapMatch.c
@@ -0,0 +1,538 @@
+/**CFile****************************************************************
+
+ FileName [amapMatch.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapMatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the cut using new memory manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Cut_t * Amap_ManDupCut( Amap_Man_t * p, Amap_Cut_t * pCut )
+{
+ Amap_Cut_t * pNew;
+ int nBytes = sizeof(Amap_Cut_t) + sizeof(int) * pCut->nFans;
+ pNew = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemCutBest, nBytes );
+ memcpy( pNew, pCut, nBytes );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the match with cut and set.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Amap_ManMatchStart( Amap_Mat_t * p, Amap_Cut_t * pCut, Amap_Set_t * pSet )
+{
+ memset( p, 0, sizeof(Amap_Mat_t) );
+ p->pCut = pCut;
+ p->pSet = pSet;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans reference counters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManCleanRefs( Amap_Man_t * p )
+{
+ Amap_Obj_t * pObj;
+ int i;
+ Amap_ManForEachObj( p, pObj, i )
+ pObj->nFouts[0] = pObj->nFouts[1] = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes delay.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Amap_ManMaxDelay( Amap_Man_t * p )
+{
+ Amap_Obj_t * pObj;
+ float Delay = 0.0;
+ int i;
+ Amap_ManForEachPo( p, pObj, i )
+ Delay = AIG_MAX( Delay, Amap_ObjFanin0(p,pObj)->Best.Delay );
+ return Delay;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans reference counters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManCleanData( Amap_Man_t * p )
+{
+ Amap_Obj_t * pObj;
+ int i;
+// Amap_ManForEachNode( p, pObj, i )
+// FREE( pObj->pData );
+ Amap_ManForEachObj( p, pObj, i )
+ pObj->pData = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute nodes used in the mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Amap_ManComputeMapping_rec( Amap_Man_t * p, Amap_Obj_t * pObj, int fCompl )
+{
+ Amap_Mat_t * pM = &pObj->Best;
+ Amap_Obj_t * pFanin;
+ Amap_Gat_t * pGate;
+ int i, iFanin, fComplFanin;
+ float Area;
+ if ( pObj->nFouts[fCompl]++ + pObj->nFouts[!fCompl] > 0 )
+ return 0.0;
+ if ( Amap_ObjIsPi(pObj) || Amap_ObjIsConst1(pObj) )
+ return 0.0;
+ pGate = Amap_LibGate( p->pLib, pM->pSet->iGate );
+ assert( pGate->nPins == pM->pCut->nFans );
+ Area = pGate->dArea;
+ for ( i = 0; i < (int)pGate->nPins; i++ )
+ {
+ iFanin = Amap_Lit2Var( pM->pSet->Ins[i] );
+ pFanin = Amap_ManObj( p, Amap_Lit2Var(pM->pCut->Fans[iFanin]) );
+ fComplFanin = Amap_LitIsCompl( pM->pSet->Ins[i] ) ^ Amap_LitIsCompl( pM->pCut->Fans[iFanin] );
+ Area += Amap_ManComputeMapping_rec( p, pFanin, fComplFanin );
+ }
+ return Area;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute nodes used in the mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Amap_ManComputeMapping( Amap_Man_t * p )
+{
+ Amap_Obj_t * pObj;
+ float Area = 0.0;
+ int i;
+ Amap_ManCleanRefs( p );
+ Amap_ManForEachPo( p, pObj, i )
+ Area += Amap_ManComputeMapping_rec( p, Amap_ObjFanin0(p, pObj), Amap_ObjFaninC0(pObj) );
+ return Area;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of inverters to be added.]
+
+ Description [Should be called after mapping has been set.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_ManCountInverters( Amap_Man_t * p )
+{
+ Amap_Obj_t * pObj;
+ int i, Counter = 0;
+ Amap_ManForEachObj( p, pObj, i )
+ Counter += (int)(pObj->nFouts[!pObj->fPolar] > 0);
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compare two matches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Amap_CutCompare( Amap_Man_t * p, Amap_Mat_t * pM0, Amap_Mat_t * pM1 )
+{
+ // compare area flows
+ if ( pM0->Area < pM1->Area - p->pPars->fEpsilon )
+ return -1;
+ if ( pM0->Area > pM1->Area + p->pPars->fEpsilon )
+ return 1;
+
+ // compare average fanouts
+ if ( pM0->AveFan > pM1->AveFan - p->pPars->fEpsilon )
+ return -1;
+ if ( pM0->AveFan < pM1->AveFan + p->pPars->fEpsilon )
+ return 1;
+
+ // compare delay
+ if ( pM0->Delay < pM1->Delay - p->pPars->fEpsilon )
+ return -1;
+ if ( pM0->Delay > pM1->Delay + p->pPars->fEpsilon )
+ return 1;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts area while dereferencing the match.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float Amap_CutAreaDeref( Amap_Man_t * p, Amap_Mat_t * pM )
+{
+ Amap_Obj_t * pFanin;
+ int i, fCompl;
+ float Area = Amap_LibGate( p->pLib, pM->pSet->iGate )->dArea;
+ Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i )
+ {
+ assert( Amap_ObjRefsTotal(pFanin) > 0 );
+ if ( (int)pFanin->fPolar != fCompl && pFanin->nFouts[fCompl] == 1 )
+ Area += p->fAreaInv;
+ if ( --pFanin->nFouts[fCompl] + pFanin->nFouts[!fCompl] == 0 && Amap_ObjIsNode(pFanin) )
+ Area += Amap_CutAreaDeref( p, &pFanin->Best );
+ }
+ return Area;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts area while referencing the match.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float Amap_CutAreaRef( Amap_Man_t * p, Amap_Mat_t * pM )
+{
+ Amap_Obj_t * pFanin;
+ int i, fCompl;
+ float Area = Amap_LibGate( p->pLib, pM->pSet->iGate )->dArea;
+ Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i )
+ {
+ assert( Amap_ObjRefsTotal(pFanin) >= 0 );
+ if ( (int)pFanin->fPolar != fCompl && pFanin->nFouts[fCompl] == 0 )
+ Area += p->fAreaInv;
+ if ( pFanin->nFouts[fCompl]++ + pFanin->nFouts[!fCompl] == 0 && Amap_ObjIsNode(pFanin) )
+ Area += Amap_CutAreaRef( p, &pFanin->Best );
+ }
+ return Area;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives area of the match for a non-referenced node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline float Amap_CutAreaDerefed( Amap_Man_t * p, Amap_Obj_t * pNode, Amap_Mat_t * pM )
+{
+ float aResult, aResult2;
+ int fComplNew;
+ aResult2 = Amap_CutAreaRef( p, pM );
+ aResult = Amap_CutAreaDeref( p, pM );
+ assert( aResult > aResult2 - p->fEpsilonInternal );
+ assert( aResult < aResult2 + p->fEpsilonInternal );
+ // if node is needed in another polarity, add inverter
+ fComplNew = pM->pCut->fInv ^ pM->pSet->fInv;
+ if ( pNode->nFouts[fComplNew] == 0 && pNode->nFouts[!fComplNew] > 0 )
+ aResult += p->fAreaInv;
+ return aResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Amap_CutAreaTest( Amap_Man_t * p, Amap_Obj_t * pNode )
+{
+ float aResult, aResult2;
+ if ( Amap_ObjRefsTotal(pNode) == 0 )
+ {
+ aResult2 = Amap_CutAreaRef( p, &pNode->Best );
+ aResult = Amap_CutAreaDeref( p, &pNode->Best );
+ assert( aResult > aResult2 - p->fEpsilonInternal );
+ assert( aResult < aResult2 + p->fEpsilonInternal );
+ }
+ else
+ {
+ aResult = Amap_CutAreaDeref( p, &pNode->Best );
+ aResult2 = Amap_CutAreaRef( p, &pNode->Best );
+ assert( aResult > aResult2 - p->fEpsilonInternal );
+ assert( aResult < aResult2 + p->fEpsilonInternal );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives parameters for the match.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Amap_ManMatchGetFlows( Amap_Man_t * p, Amap_Mat_t * pM )
+{
+ Amap_Mat_t * pMFanin;
+ Amap_Obj_t * pFanin;
+ Amap_Gat_t * pGate;
+ int i;
+ pGate = Amap_LibGate( p->pLib, pM->pSet->iGate );
+ assert( pGate->nPins == pM->pCut->nFans );
+ assert( pM->Area == 0.0 );
+ pM->Area = pGate->dArea;
+ pM->AveFan = 0.0;
+ pM->Delay = 0.0;
+ Amap_MatchForEachFanin( p, pM, pFanin, i )
+ {
+ pMFanin = &pFanin->Best;
+ pM->Delay = AIG_MAX( pM->Delay, pMFanin->Delay );
+ pM->AveFan += Amap_ObjRefsTotal(pFanin);
+ if ( Amap_ObjRefsTotal(pFanin) == 0 )
+ pM->Area += pMFanin->Area;
+ else
+ pM->Area += pMFanin->Area / pFanin->EstRefs;
+ }
+ pM->AveFan /= pGate->nPins;
+ pM->Delay += 1.0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives parameters for the match.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Amap_ManMatchGetExacts( Amap_Man_t * p, Amap_Obj_t * pNode, Amap_Mat_t * pM )
+{
+ Amap_Mat_t * pMFanin;
+ Amap_Obj_t * pFanin;
+ Amap_Gat_t * pGate;
+ int i;
+ pGate = Amap_LibGate( p->pLib, pM->pSet->iGate );
+ assert( pGate->nPins == pM->pCut->nFans );
+ assert( pM->Area == 0.0 );
+ pM->AveFan = 0.0;
+ pM->Delay = 0.0;
+ Amap_MatchForEachFanin( p, pM, pFanin, i )
+ {
+ pMFanin = &pFanin->Best;
+ pM->Delay = AIG_MAX( pM->Delay, pMFanin->Delay );
+ pM->AveFan += Amap_ObjRefsTotal(pFanin);
+ }
+ pM->AveFan /= pGate->nPins;
+ pM->Delay += 1.0;
+ pM->Area = Amap_CutAreaDerefed( p, pNode, pM );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the best match at each node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManMatchNode( Amap_Man_t * p, Amap_Obj_t * pNode, int fFlow, int fRefs )
+{
+ Amap_Mat_t M1, M2, * pMBest = &M1, * pMThis = &M2;
+ Amap_Cut_t * pCut;
+ Amap_Set_t * pSet;
+ Amap_Nod_t * pNod;
+ int i;
+ if ( fRefs )
+ pNode->EstRefs = (float)((2.0 * pNode->EstRefs + Amap_ObjRefsTotal(pNode)) / 3.0);
+ else
+ pNode->EstRefs = (float)pNode->nRefs;
+ if ( fRefs && Amap_ObjRefsTotal(pNode) > 0 )
+ Amap_CutAreaDeref( p, &pNode->Best );
+ pMBest->pCut = NULL;
+ Amap_NodeForEachCut( pNode, pCut, i )
+ {
+ if ( pCut->iMat == 0 )
+ continue;
+ pNod = Amap_LibNod( p->pLib, pCut->iMat );
+ Amap_LibNodeForEachSet( pNod, pSet )
+ {
+ Amap_ManMatchStart( pMThis, pCut, pSet );
+ if ( fFlow )
+ Amap_ManMatchGetFlows( p, pMThis );
+ else
+ Amap_ManMatchGetExacts( p, pNode, pMThis );
+ if ( pMBest->pCut == NULL || Amap_CutCompare(p, pMBest, pMThis) == 1 )
+ *pMBest = *pMThis;
+ }
+ }
+ pNode->fPolar = pMBest->pCut->fInv ^ pMBest->pSet->fInv;
+ pNode->Best = *pMBest;
+ pNode->Best.pCut = Amap_ManDupCut( p, pNode->Best.pCut );
+ if ( fRefs && Amap_ObjRefsTotal(pNode) > 0 )
+ Amap_CutAreaRef( p, &pNode->Best );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one round of mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManMatch( Amap_Man_t * p, int fFlow, int fRefs )
+{
+ Aig_MmFlex_t * pMemOld;
+ Amap_Obj_t * pObj;
+ float Area;
+ int i, nInvs, clk = clock();
+ pMemOld = p->pMemCutBest;
+ p->pMemCutBest = Aig_MmFlexStart();
+ Amap_ManForEachNode( p, pObj, i )
+ if ( pObj->pData )
+ Amap_ManMatchNode( p, pObj, fFlow, fRefs );
+ Aig_MmFlexStop( pMemOld, 0 );
+ Area = Amap_ManComputeMapping( p );
+ nInvs = Amap_ManCountInverters( p );
+if ( p->pPars->fVerbose )
+{
+ printf( "Area =%9.2f. Gate =%9.2f. Inv =%9.2f. (%6d.) Delay =%6.2f. ",
+ Area + nInvs * p->fAreaInv,
+ Area, nInvs * p->fAreaInv, nInvs,
+ Amap_ManMaxDelay(p) );
+PRT( "Time ", clock() - clk );
+}
+ // test procedures
+// Amap_ManForEachNode( p, pObj, i )
+// Amap_CutAreaTest( p, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManMap( Amap_Man_t * p )
+{
+ int i;
+ Amap_ManMerge( p );
+ for ( i = 0; i < p->pPars->nIterFlow; i++ )
+ Amap_ManMatch( p, 1, i>0 );
+ for ( i = 0; i < p->pPars->nIterArea; i++ )
+ Amap_ManMatch( p, 0, p->pPars->nIterFlow>0||i>0 );
+/*
+ for ( i = 0; i < p->pPars->nIterFlow; i++ )
+ Amap_ManMatch( p, 1, 1 );
+ for ( i = 0; i < p->pPars->nIterArea; i++ )
+ Amap_ManMatch( p, 0, 1 );
+*/
+ Amap_ManCleanData( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/amap/amapMerge.c b/src/map/amap/amapMerge.c
new file mode 100644
index 00000000..b024616e
--- /dev/null
+++ b/src/map/amap/amapMerge.c
@@ -0,0 +1,521 @@
+/**CFile****************************************************************
+
+ FileName [amapMerge.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis [Computing cuts for the node.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates new cut and adds it to storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Cut_t * Amap_ManSetupPis( Amap_Man_t * p )
+{
+ Amap_Obj_t * pObj;
+ Amap_Cut_t * pCut;
+ int i, nBytes = sizeof(Amap_Cut_t) + sizeof(int);
+ char * pBuffer = ALLOC( char, Amap_ManPiNum(p) * nBytes );
+ Amap_ManForEachPi( p, pObj, i )
+ {
+ pCut = (Amap_Cut_t *)( pBuffer + i*nBytes );
+ pCut->iMat = 0;
+ pCut->fInv = 0;
+ pCut->nFans = 1;
+ pCut->Fans[0] = Amap_Var2Lit( pObj->Id, 0 );
+ pObj->pData = pCut;
+ pObj->nCuts = 1;
+ pObj->EstRefs = (float)1.0;
+ }
+ return (Amap_Cut_t *)pBuffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates new cut and adds it to storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Cut_t * Amap_ManCutStore( Amap_Man_t * p, Amap_Cut_t * pCut, int fCompl )
+{
+ Amap_Cut_t * pNew;
+ int iFan, nBytes = sizeof(Amap_Cut_t) + sizeof(int) * pCut->nFans + sizeof(Amap_Cut_t *);
+ pNew = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemTemp, nBytes );
+ pNew->iMat = pCut->iMat;
+ pNew->fInv = pCut->fInv ^ fCompl;
+ pNew->nFans = pCut->nFans;
+ memcpy( pNew->Fans, pCut->Fans, sizeof(int) * pCut->nFans );
+ // add it to storage
+ iFan = Amap_Var2Lit( pNew->iMat, pNew->fInv );
+ if ( p->ppCutsTemp[ iFan ] == NULL )
+ Vec_IntPushOrder( p->vTemp, iFan );
+ *Amap_ManCutNextP( pNew ) = p->ppCutsTemp[ iFan ];
+ p->ppCutsTemp[ iFan ] = pNew;
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates new cut and adds it to storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Cut_t * Amap_ManCutCreate( Amap_Man_t * p,
+ Amap_Cut_t * pCut0, Amap_Cut_t * pCut1, int iMat )
+{
+ Amap_Cut_t * pCut;
+ int i, nSize = pCut0->nFans + pCut1->nFans;
+ int nBytes = sizeof(Amap_Cut_t) + sizeof(int) * nSize + sizeof(Amap_Cut_t *);
+ assert( pCut0->iMat >= pCut1->iMat );
+ pCut = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemTemp, nBytes );
+ pCut->iMat = iMat;
+ pCut->fInv = 0;
+ pCut->nFans = nSize;
+ for ( i = 0; i < (int)pCut0->nFans; i++ )
+ pCut->Fans[i] = pCut0->Fans[i];
+ for ( i = 0; i < (int)pCut1->nFans; i++ )
+ pCut->Fans[pCut0->nFans+i] = pCut1->Fans[i];
+ // add it to storage
+ if ( p->ppCutsTemp[ pCut->iMat ] == NULL )
+ Vec_IntPushOrder( p->vTemp, pCut->iMat );
+ *Amap_ManCutNextP( pCut ) = p->ppCutsTemp[ pCut->iMat ];
+ p->ppCutsTemp[ pCut->iMat ] = pCut;
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates new cut and adds it to storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Cut_t * Amap_ManCutCreate3( Amap_Man_t * p,
+ Amap_Cut_t * pCut0, Amap_Cut_t * pCut1, Amap_Cut_t * pCut2, int iMat )
+{
+ Amap_Cut_t * pCut;
+ int i, nSize = pCut0->nFans + pCut1->nFans + pCut2->nFans;
+ int nBytes = sizeof(Amap_Cut_t) + sizeof(int) * nSize + sizeof(Amap_Cut_t *);
+ pCut = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemTemp, nBytes );
+ pCut->iMat = iMat;
+ pCut->fInv = 0;
+ pCut->nFans = nSize;
+ for ( i = 0; i < (int)pCut0->nFans; i++ )
+ pCut->Fans[i] = pCut0->Fans[i];
+ for ( i = 0; i < (int)pCut1->nFans; i++ )
+ pCut->Fans[pCut0->nFans+i] = pCut1->Fans[i];
+ for ( i = 0; i < (int)pCut2->nFans; i++ )
+ pCut->Fans[pCut0->nFans+pCut1->nFans+i] = pCut2->Fans[i];
+ // add it to storage
+ if ( p->ppCutsTemp[ pCut->iMat ] == NULL )
+ Vec_IntPushOrder( p->vTemp, pCut->iMat );
+ *Amap_ManCutNextP( pCut ) = p->ppCutsTemp[ pCut->iMat ];
+ p->ppCutsTemp[ pCut->iMat ] = pCut;
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes cuts from the temporary storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManCutSaveStored( Amap_Man_t * p, Amap_Obj_t * pNode )
+{
+ int * pBuffer;
+ Amap_Cut_t * pNext, * pCut;
+ int i, nWords, Entry, nCuts;
+ assert( pNode->pData == NULL );
+ // count memory needed
+ nCuts = 1;
+ nWords = 2;
+ Vec_IntForEachEntry( p->vTemp, Entry, i )
+ {
+ for ( pCut = p->ppCutsTemp[Entry]; pCut; pCut = *Amap_ManCutNextP(pCut) )
+ {
+ nCuts++;
+ nWords += pCut->nFans + 1;
+ }
+ }
+ p->nBytesUsed += 4*nWords;
+ // allocate memory
+ pBuffer = (int *)Aig_MmFlexEntryFetch( p->pMemCuts, 4*nWords );
+ pNext = (Amap_Cut_t *)pBuffer;
+ // add the first cut
+ pNext->iMat = 0;
+ pNext->fInv = 0;
+ pNext->nFans = 1;
+ pNext->Fans[0] = Amap_Var2Lit(pNode->Id, 0);
+ pNext = (Amap_Cut_t *)(pBuffer + 2);
+ // add other cuts
+ Vec_IntForEachEntry( p->vTemp, Entry, i )
+ {
+ for ( pCut = p->ppCutsTemp[Entry]; pCut; pCut = *Amap_ManCutNextP(pCut) )
+ {
+ memcpy( pNext, pCut, sizeof(int) * (pCut->nFans + 1) );
+ pNext = (Amap_Cut_t *)((int *)pNext + pCut->nFans + 1);
+ }
+ p->ppCutsTemp[Entry] = NULL;
+ }
+ assert( (int *)pNext - pBuffer == nWords );
+ // restore the storage
+ Vec_IntClear( p->vTemp );
+ Aig_MmFlexRestart( p->pMemTemp );
+ for ( i = 0; i < 2*p->pLib->nNodes; i++ )
+ if ( p->ppCutsTemp[i] != NULL )
+ printf( "Amap_ManCutSaveStored(): Error!\n" );
+ pNode->pData = (Amap_Cut_t *)pBuffer;
+ pNode->nCuts = nCuts;
+// printf("%d ", nCuts );
+ // verify cuts
+ pCut = NULL;
+ Amap_NodeForEachCut( pNode, pNext, i )
+// for ( i = 0, pNext = (Amap_Cut_t *)pNode->pData; i < (int)pNode->nCuts;
+// i++, pNext = Amap_ManCutNext(pNext) )
+ {
+ assert( pCut == NULL || pCut->iMat <= pNext->iMat );
+ pCut = pNext;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of possible new cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_ManMergeCountCuts( Amap_Man_t * p, Amap_Obj_t * pNode )
+{
+ Amap_Obj_t * pFanin0 = Amap_ObjFanin0( p, pNode );
+ Amap_Obj_t * pFanin1 = Amap_ObjFanin1( p, pNode );
+ Amap_Cut_t * pCut0, * pCut1;
+ int Entry, c0, c1, iCompl0, iCompl1, iFan0, iFan1;
+ int Counter = 1;
+ Amap_NodeForEachCut( pFanin0, pCut0, c0 )
+ Amap_NodeForEachCut( pFanin1, pCut1, c1 )
+ {
+ iCompl0 = pCut0->fInv ^ Amap_ObjFaninC0(pNode);
+ iCompl1 = pCut1->fInv ^ Amap_ObjFaninC1(pNode);
+ iFan0 = !pCut0->iMat? 0: Amap_Var2Lit( pCut0->iMat, iCompl0 );
+ iFan1 = !pCut1->iMat? 0: Amap_Var2Lit( pCut1->iMat, iCompl1 );
+ Entry = Amap_LibFindNode( p->pLib, iFan0, iFan1, pNode->Type == AMAP_OBJ_XOR );
+ Counter += ( Entry >=0 );
+// if ( Entry >=0 )
+// printf( "Full: %d + %d = %d\n", iFan0, iFan1, Entry );
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Print cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManPrintCuts( Amap_Obj_t * pNode )
+{
+ Amap_Cut_t * pCut;
+ int c, i;
+ printf( "NODE %5d : Type = ", pNode->Id );
+ if ( pNode->Type == AMAP_OBJ_AND )
+ printf( "AND" );
+ else if ( pNode->Type == AMAP_OBJ_XOR )
+ printf( "XOR" );
+ else if ( pNode->Type == AMAP_OBJ_MUX )
+ printf( "MUX" );
+ printf( " Cuts = %d\n", pNode->nCuts );
+ Amap_NodeForEachCut( pNode, pCut, c )
+ {
+ printf( "%3d : Mat= %3d Inv=%d ", c, pCut->iMat, pCut->fInv );
+ for ( i = 0; i < (int)pCut->nFans; i++ )
+ printf( "%d%c ", Amap_Lit2Var(pCut->Fans[i]), Amap_LitIsCompl(pCut->Fans[i])?'-':'+' );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives cuts for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManMergeNodeChoice( Amap_Man_t * p, Amap_Obj_t * pNode )
+{
+ Amap_Obj_t * pTemp;
+ Amap_Cut_t * pCut;
+ int c;
+ // go through the nodes of the choice node
+ for ( pTemp = pNode; pTemp; pTemp = Amap_ObjChoice(p, pTemp) )
+ {
+ Amap_NodeForEachCut( pTemp, pCut, c )
+ if ( pCut->iMat )
+ Amap_ManCutStore( p, pCut, pNode->fPhase ^ pTemp->fPhase );
+ pTemp->pData = NULL;
+ }
+ Amap_ManCutSaveStored( p, pNode );
+
+// Amap_ManPrintCuts( pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives cuts for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_ManFindCut( Amap_Obj_t * pNode, Amap_Obj_t * pFanin, int fComplFanin, int Val, Vec_Ptr_t * vCuts )
+{
+ Amap_Cut_t * pCut;
+ int c, iCompl, iFan;
+ Vec_PtrClear( vCuts );
+ Amap_NodeForEachCut( pFanin, pCut, c )
+ {
+ iCompl = pCut->fInv ^ fComplFanin;
+ iFan = !pCut->iMat? 0: Amap_Var2Lit( pCut->iMat, iCompl );
+ if ( iFan == Val )
+ Vec_PtrPush( vCuts, pCut );
+ }
+ return Vec_PtrSize(vCuts) == 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives cuts for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManMergeNodeCutsMux( Amap_Man_t * p, Amap_Obj_t * pNode )
+{
+ Vec_Int_t * vRules = p->pLib->vRules3;
+ Amap_Obj_t * pFanin0 = Amap_ObjFanin0( p, pNode );
+ Amap_Obj_t * pFanin1 = Amap_ObjFanin1( p, pNode );
+ Amap_Obj_t * pFanin2 = Amap_ObjFanin2( p, pNode );
+ int fComplFanin0 = Amap_ObjFaninC0( pNode );
+ int fComplFanin1 = Amap_ObjFaninC1( pNode );
+ int fComplFanin2 = Amap_ObjFaninC2( pNode );
+ Amap_Cut_t * pCut0, * pCut1, * pCut2;
+ int x, c0, c1, c2;
+ assert( pNode->pData == NULL );
+ assert( pNode->Type == AMAP_OBJ_MUX );
+ assert( pNode->fRepr == 0 );
+ // go through the rules
+ for ( x = 0; x < Vec_IntSize(vRules); x += 4 )
+ {
+ if ( Amap_ManFindCut( pNode, pFanin0, fComplFanin0, Vec_IntEntry(vRules, x), p->vCuts0 ) )
+ continue;
+ if ( Amap_ManFindCut( pNode, pFanin1, fComplFanin1, Vec_IntEntry(vRules, x+1), p->vCuts1 ) )
+ continue;
+ if ( Amap_ManFindCut( pNode, pFanin2, fComplFanin2, Vec_IntEntry(vRules, x+2), p->vCuts2 ) )
+ continue;
+ Vec_PtrForEachEntry( p->vCuts0, pCut0, c0 )
+ Vec_PtrForEachEntry( p->vCuts1, pCut1, c1 )
+ Vec_PtrForEachEntry( p->vCuts2, pCut2, c2 )
+ {
+ Amap_Nod_t * pNod = Amap_LibNod( p->pLib, Vec_IntEntry(vRules, x+3) );
+ if ( pNod->pSets == NULL )
+ continue;
+ // complement literals
+ if ( pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0) )
+ pCut0->Fans[0] = Amap_LitNot(pCut0->Fans[0]);
+ if ( pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1) )
+ pCut1->Fans[0] = Amap_LitNot(pCut1->Fans[0]);
+ if ( pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) )
+ pCut2->Fans[0] = Amap_LitNot(pCut2->Fans[0]);
+ // create new cut
+ Amap_ManCutCreate3( p, pCut0, pCut1, pCut2, Vec_IntEntry(vRules, x+3) );
+ // uncomplement literals
+ if ( pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0) )
+ pCut0->Fans[0] = Amap_LitNot(pCut0->Fans[0]);
+ if ( pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1) )
+ pCut1->Fans[0] = Amap_LitNot(pCut1->Fans[0]);
+ if ( pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) )
+ pCut2->Fans[0] = Amap_LitNot(pCut2->Fans[0]);
+ }
+ }
+ Amap_ManCutSaveStored( p, pNode );
+ p->nCutsUsed += pNode->nCuts;
+ p->nCutsTried3 += pFanin0->nCuts * pFanin1->nCuts * pFanin2->nCuts;
+
+// Amap_ManPrintCuts( pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives cuts for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManMergeNodeCuts( Amap_Man_t * p, Amap_Obj_t * pNode )
+{
+ Amap_Obj_t * pFanin0 = Amap_ObjFanin0( p, pNode );
+ Amap_Obj_t * pFanin1 = Amap_ObjFanin1( p, pNode );
+ Amap_Cut_t * pCut0, * pCut1;
+ int ** pRules, Entry, i, k, c, iCompl0, iCompl1, iFan0, iFan1;
+ assert( pNode->pData == NULL );
+ if ( pNode->Type == AMAP_OBJ_MUX )
+ {
+ Amap_ManMergeNodeCutsMux( p, pNode );
+ return;
+ }
+ assert( pNode->Type != AMAP_OBJ_MUX );
+ pRules = (pNode->Type == AMAP_OBJ_AND)? p->pLib->pRules: p->pLib->pRulesX;
+ Amap_NodeForEachCut( pFanin0, pCut0, c )
+ {
+ iCompl0 = pCut0->fInv ^ Amap_ObjFaninC0(pNode);
+ iFan0 = !pCut0->iMat? 0: Amap_Var2Lit( pCut0->iMat, iCompl0 );
+ // complement literals
+ if ( pCut0->nFans == 1 && iCompl0 )
+ pCut0->Fans[0] = Amap_LitNot(pCut0->Fans[0]);
+ // label resulting sets
+ for ( i = 0; (Entry = pRules[iFan0][i]); i++ )
+ p->pMatsTemp[Entry & 0xffff] = (Entry >> 16);
+ // iterate through the cuts
+ Amap_NodeForEachCut( pFanin1, pCut1, k )
+ {
+ iCompl1 = pCut1->fInv ^ Amap_ObjFaninC1(pNode);
+ iFan1 = !pCut1->iMat? 0: Amap_Var2Lit( pCut1->iMat, iCompl1 );
+ if ( p->pMatsTemp[iFan1] == 0 )
+ continue;
+ // complement literals
+ if ( pCut1->nFans == 1 && iCompl1 )
+ pCut1->Fans[0] = Amap_LitNot(pCut1->Fans[0]);
+ // create new cut
+ if ( iFan0 >= iFan1 )
+ Amap_ManCutCreate( p, pCut0, pCut1, p->pMatsTemp[iFan1] );
+ else
+ Amap_ManCutCreate( p, pCut1, pCut0, p->pMatsTemp[iFan1] );
+ // uncomplement literals
+ if ( pCut1->nFans == 1 && iCompl1 )
+ pCut1->Fans[0] = Amap_LitNot(pCut1->Fans[0]);
+ }
+ // uncomplement literals
+ if ( pCut0->nFans == 1 && iCompl0 )
+ pCut0->Fans[0] = Amap_LitNot(pCut0->Fans[0]);
+ // label resulting sets
+ for ( i = 0; (Entry = pRules[iFan0][i]); i++ )
+ p->pMatsTemp[Entry & 0xffff] = 0;
+ }
+ Amap_ManCutSaveStored( p, pNode );
+ p->nCutsUsed += pNode->nCuts;
+ p->nCutsTried += pFanin0->nCuts * pFanin1->nCuts;
+// assert( (int)pNode->nCuts == Amap_ManMergeCountCuts(p, pNode) );
+ if ( pNode->fRepr )
+ Amap_ManMergeNodeChoice( p, pNode );
+
+// Amap_ManPrintCuts( pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives cuts for all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_ManMerge( Amap_Man_t * p )
+{
+ Amap_Obj_t * pObj;
+ int i, clk = clock();
+ p->pCutsPi = Amap_ManSetupPis( p );
+ Amap_ManForEachNode( p, pObj, i )
+ Amap_ManMergeNodeCuts( p, pObj );
+ if ( p->pPars->fVerbose )
+ {
+ printf( "AIG object is %d bytes. ", sizeof(Amap_Obj_t) );
+ printf( "Internal AIG = %5.2f Mb. Cuts = %5.2f Mb.\n",
+ 1.0*Amap_ManObjNum(p)*sizeof(Amap_Obj_t)/(1<<20), 1.0*p->nBytesUsed/(1<<20) );
+ printf( "Node =%6d. Try =%9d. Try3 =%10d. Used =%7d. R =%6.2f. ",
+ Amap_ManNodeNum(p), p->nCutsTried, p->nCutsTried3, p->nCutsUsed,
+ 1.0*p->nCutsUsed/Amap_ManNodeNum(p) );
+PRT( "Time ", clock() - clk );
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/amap/amapOutput.c b/src/map/amap/amapOutput.c
new file mode 100644
index 00000000..1decc52e
--- /dev/null
+++ b/src/map/amap/amapOutput.c
@@ -0,0 +1,181 @@
+/**CFile****************************************************************
+
+ FileName [amapOutput.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis [Core mapping procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapOutput.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline char * Amap_OuputStrsav( Aig_MmFlex_t * p, char * pStr )
+{ return pStr ? strcpy(Aig_MmFlexEntryFetch(p, strlen(pStr)+1), pStr) : NULL; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates structure for storing one gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Out_t * Amap_OutputStructAlloc( Aig_MmFlex_t * pMem, Amap_Gat_t * pGate )
+{
+ Amap_Out_t * pRes;
+ int nFans = pGate? pGate->nPins : 1;
+ pRes = (Amap_Out_t *)Aig_MmFlexEntryFetch( pMem, sizeof(Amap_Out_t)+sizeof(int)*nFans );
+ memset( pRes, 0, sizeof(Amap_Out_t) );
+ memset( pRes->pFans, 0xff, sizeof(int)*nFans );
+ pRes->pName = pGate? Amap_OuputStrsav( pMem, pGate->pName ) : NULL;
+ pRes->nFans = nFans;
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns mapped network as an array of structures.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Amap_ManProduceMapped( Amap_Man_t * p )
+{
+ Vec_Ptr_t * vNodes;
+ Aig_MmFlex_t * pMem;
+ Amap_Obj_t * pObj, * pFanin;
+ Amap_Gat_t * pGate;
+ Amap_Out_t * pRes;
+ int i, k, iFanin, fCompl;
+ float TotalArea = 0.0;
+ pMem = Aig_MmFlexStart();
+ // create mapping object for each node used in the mapping
+ vNodes = Vec_PtrAlloc( 10 );
+ Amap_ManForEachObj( p, pObj, i )
+ {
+ if ( Amap_ObjIsPi(pObj) )
+ {
+ assert( pObj->fPolar == 0 );
+ pRes = Amap_OutputStructAlloc( pMem, NULL );
+ pRes->Type = -1;
+ pRes->nFans = 0;
+ // save this structure
+ pObj->iData = Vec_PtrSize( vNodes );
+ Vec_PtrPush( vNodes, pRes );
+ // create invertor if needed
+ if ( pObj->nFouts[1] ) // this PI is used in the neg polarity
+ {
+ pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGateInv );
+ pRes->pFans[0] = pObj->iData;
+ // save this structure
+ Vec_PtrPush( vNodes, pRes );
+ TotalArea += p->pLib->pGateInv->dArea;
+ }
+ continue;
+ }
+ if ( Amap_ObjIsNode(pObj) )
+ {
+ // skip the node that is not used in the mapping
+ if ( Amap_ObjRefsTotal(pObj) == 0 )
+ continue;
+ // get the gate
+ pGate = Amap_LibGate( p->pLib, pObj->Best.pSet->iGate );
+ assert( pGate->nPins == pObj->Best.pCut->nFans );
+ // allocate structure
+ pRes = Amap_OutputStructAlloc( pMem, pGate );
+ Amap_MatchForEachFaninCompl( p, &pObj->Best, pFanin, fCompl, k )
+ {
+ assert( Amap_ObjRefsTotal(pFanin) );
+ if ( (int)pFanin->fPolar == fCompl )
+ pRes->pFans[k] = pFanin->iData;
+ else
+ pRes->pFans[k] = pFanin->iData + 1;
+ }
+ // save this structure
+ pObj->iData = Vec_PtrSize( vNodes );
+ Vec_PtrPush( vNodes, pRes );
+ TotalArea += pGate->dArea;
+ // create invertor if needed
+ if ( pObj->nFouts[!pObj->fPolar] ) // needed in the opposite polarity
+ {
+ pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGateInv );
+ pRes->pFans[0] = pObj->iData;
+ // save this structure
+ Vec_PtrPush( vNodes, pRes );
+ TotalArea += p->pLib->pGateInv->dArea;
+ }
+ continue;
+ }
+ if ( Amap_ObjIsPo(pObj) )
+ {
+ assert( pObj->fPolar == 0 );
+ pFanin = Amap_ObjFanin0(p, pObj);
+ assert( Amap_ObjRefsTotal(pFanin) );
+ if ( Amap_ObjIsConst1(pFanin) )
+ { // create constant node
+ if ( Amap_ObjFaninC0(pObj) )
+ {
+ pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGate0 );
+ TotalArea += p->pLib->pGate0->dArea;
+ }
+ else
+ {
+ pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGate1 );
+ TotalArea += p->pLib->pGate1->dArea;
+ }
+ // save this structure
+ iFanin = Vec_PtrSize( vNodes );
+ Vec_PtrPush( vNodes, pRes );
+ }
+ else
+ {
+ if ( (int)pFanin->fPolar == Amap_ObjFaninC0(pObj) )
+ iFanin = pFanin->iData;
+ else
+ iFanin = pFanin->iData + 1;
+ }
+ // create PO node
+ pRes = Amap_OutputStructAlloc( pMem, NULL );
+ pRes->Type = 1;
+ pRes->pFans[0] = iFanin;
+ // save this structure
+ Vec_PtrPush( vNodes, pRes );
+ }
+ }
+ // return memory manager in the last entry of the array
+ Vec_PtrPush( vNodes, pMem );
+ return vNodes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/amap/amapParse.c b/src/map/amap/amapParse.c
new file mode 100644
index 00000000..262fbd5a
--- /dev/null
+++ b/src/map/amap/amapParse.c
@@ -0,0 +1,457 @@
+/**CFile****************************************************************
+
+ FileName [amapParse.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis [Parses representations of gates.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapParse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+#include "hop.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// the list of operation symbols to be used in expressions
+#define AMAP_EQN_SYM_OPEN '(' // opening paranthesis
+#define AMAP_EQN_SYM_CLOSE ')' // closing paranthesis
+#define AMAP_EQN_SYM_CONST0 '0' // constant 0
+#define AMAP_EQN_SYM_CONST1 '1' // constant 1
+#define AMAP_EQN_SYM_NEG '!' // negation before the variable
+#define AMAP_EQN_SYM_NEGAFT '\'' // negation after the variable
+#define AMAP_EQN_SYM_AND '*' // logic AND
+#define AMAP_EQN_SYM_XOR '^' // logic XOR
+#define AMAP_EQN_SYM_OR '+' // logic OR
+
+// the list of opcodes (also specifying operation precedence)
+#define AMAP_EQN_OPER_NEG 10 // negation
+#define AMAP_EQN_OPER_AND 9 // logic AND
+#define AMAP_EQN_OPER_XOR 8 // logic XOR
+#define AMAP_EQN_OPER_OR 7 // logic OR
+#define AMAP_EQN_OPER_MARK 1 // OpStack token standing for an opening paranthesis
+
+// these are values of the internal Flag
+#define AMAP_EQN_FLAG_START 1 // after the opening parenthesis
+#define AMAP_EQN_FLAG_VAR 2 // after operation is received
+#define AMAP_EQN_FLAG_OPER 3 // after operation symbol is received
+#define AMAP_EQN_FLAG_ERROR 4 // when error is detected
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs the operation on the top entries in the stack.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Amap_ParseFormulaOper( Hop_Man_t * pMan, Vec_Ptr_t * pStackFn, int Oper )
+{
+ Hop_Obj_t * gArg1, * gArg2, * gFunc;
+ // perform the given operation
+ gArg2 = Vec_PtrPop( pStackFn );
+ gArg1 = Vec_PtrPop( pStackFn );
+ if ( Oper == AMAP_EQN_OPER_AND )
+ gFunc = Hop_And( pMan, gArg1, gArg2 );
+ else if ( Oper == AMAP_EQN_OPER_OR )
+ gFunc = Hop_Or( pMan, gArg1, gArg2 );
+ else if ( Oper == AMAP_EQN_OPER_XOR )
+ gFunc = Hop_Exor( pMan, gArg1, gArg2 );
+ else
+ return NULL;
+// Cudd_Ref( gFunc );
+// Cudd_RecursiveDeref( dd, gArg1 );
+// Cudd_RecursiveDeref( dd, gArg2 );
+ Vec_PtrPush( pStackFn, gFunc );
+ return gFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the AIG corresponding to the equation.]
+
+ Description [Takes the stream to output messages, the formula, the vector
+ of variable names and the AIG manager.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Amap_ParseFormula( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan )
+{
+ char * pFormula;
+ Vec_Ptr_t * pStackFn;
+ Vec_Int_t * pStackOp;
+ Hop_Obj_t * gFunc;
+ char * pTemp, * pName;
+ int nParans, fFound, Flag;
+ int Oper, Oper1, Oper2;
+ int i, v;
+
+ // make sure that the number of opening and closing parantheses is the same
+ nParans = 0;
+ for ( pTemp = pFormInit; *pTemp; pTemp++ )
+ if ( *pTemp == '(' )
+ nParans++;
+ else if ( *pTemp == ')' )
+ nParans--;
+ if ( nParans != 0 )
+ {
+ fprintf( pOutput, "Amap_ParseFormula(): Different number of opening and closing parantheses ().\n" );
+ return NULL;
+ }
+
+ // copy the formula
+ pFormula = ALLOC( char, strlen(pFormInit) + 3 );
+ sprintf( pFormula, "(%s)", pFormInit );
+
+ // start the stacks
+ pStackFn = Vec_PtrAlloc( 100 );
+ pStackOp = Vec_IntAlloc( 100 );
+
+ Flag = AMAP_EQN_FLAG_START;
+ for ( pTemp = pFormula; *pTemp; pTemp++ )
+ {
+ switch ( *pTemp )
+ {
+ // skip all spaces, tabs, and end-of-lines
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ continue;
+ case AMAP_EQN_SYM_CONST0:
+ Vec_PtrPush( pStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( b0 );
+ if ( Flag == AMAP_EQN_FLAG_VAR )
+ {
+ fprintf( pOutput, "Amap_ParseFormula(): No operation symbol before constant 0.\n" );
+ Flag = AMAP_EQN_FLAG_ERROR;
+ break;
+ }
+ Flag = AMAP_EQN_FLAG_VAR;
+ break;
+ case AMAP_EQN_SYM_CONST1:
+ Vec_PtrPush( pStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( b1 );
+ if ( Flag == AMAP_EQN_FLAG_VAR )
+ {
+ fprintf( pOutput, "Amap_ParseFormula(): No operation symbol before constant 1.\n" );
+ Flag = AMAP_EQN_FLAG_ERROR;
+ break;
+ }
+ Flag = AMAP_EQN_FLAG_VAR;
+ break;
+ case AMAP_EQN_SYM_NEG:
+ if ( Flag == AMAP_EQN_FLAG_VAR )
+ {// if NEGBEF follows a variable, AND is assumed
+ Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND );
+ Flag = AMAP_EQN_FLAG_OPER;
+ }
+ Vec_IntPush( pStackOp, AMAP_EQN_OPER_NEG );
+ break;
+ case AMAP_EQN_SYM_NEGAFT:
+ if ( Flag != AMAP_EQN_FLAG_VAR )
+ {// if there is no variable before NEGAFT, it is an error
+ fprintf( pOutput, "Amap_ParseFormula(): No variable is specified before the negation suffix.\n" );
+ Flag = AMAP_EQN_FLAG_ERROR;
+ break;
+ }
+ else // if ( Flag == PARSE_FLAG_VAR )
+ Vec_PtrPush( pStackFn, Hop_Not( Vec_PtrPop(pStackFn) ) );
+ break;
+ case AMAP_EQN_SYM_AND:
+ case AMAP_EQN_SYM_OR:
+ case AMAP_EQN_SYM_XOR:
+ if ( Flag != AMAP_EQN_FLAG_VAR )
+ {
+ fprintf( pOutput, "Amap_ParseFormula(): There is no variable before AND, EXOR, or OR.\n" );
+ Flag = AMAP_EQN_FLAG_ERROR;
+ break;
+ }
+ if ( *pTemp == AMAP_EQN_SYM_AND )
+ Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND );
+ else if ( *pTemp == AMAP_EQN_SYM_OR )
+ Vec_IntPush( pStackOp, AMAP_EQN_OPER_OR );
+ else //if ( *pTemp == AMAP_EQN_SYM_XOR )
+ Vec_IntPush( pStackOp, AMAP_EQN_OPER_XOR );
+ Flag = AMAP_EQN_FLAG_OPER;
+ break;
+ case AMAP_EQN_SYM_OPEN:
+ if ( Flag == AMAP_EQN_FLAG_VAR )
+ {
+// Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND );
+ fprintf( pOutput, "Amap_ParseFormula(): An opening paranthesis follows a var without operation sign.\n" );
+ Flag = AMAP_EQN_FLAG_ERROR;
+ break;
+ }
+ Vec_IntPush( pStackOp, AMAP_EQN_OPER_MARK );
+ // after an opening bracket, it feels like starting over again
+ Flag = AMAP_EQN_FLAG_START;
+ break;
+ case AMAP_EQN_SYM_CLOSE:
+ if ( Vec_IntSize( pStackOp ) != 0 )
+ {
+ while ( 1 )
+ {
+ if ( Vec_IntSize( pStackOp ) == 0 )
+ {
+ fprintf( pOutput, "Amap_ParseFormula(): There is no opening paranthesis\n" );
+ Flag = AMAP_EQN_FLAG_ERROR;
+ break;
+ }
+ Oper = Vec_IntPop( pStackOp );
+ if ( Oper == AMAP_EQN_OPER_MARK )
+ break;
+
+ // perform the given operation
+ if ( Amap_ParseFormulaOper( pMan, pStackFn, Oper ) == NULL )
+ {
+ fprintf( pOutput, "Amap_ParseFormula(): Unknown operation\n" );
+ free( pFormula );
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ fprintf( pOutput, "Amap_ParseFormula(): There is no opening paranthesis\n" );
+ Flag = AMAP_EQN_FLAG_ERROR;
+ break;
+ }
+ if ( Flag != AMAP_EQN_FLAG_ERROR )
+ Flag = AMAP_EQN_FLAG_VAR;
+ break;
+
+
+ default:
+ // scan the next name
+ for ( i = 0; pTemp[i] &&
+ pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' &&
+ pTemp[i] != AMAP_EQN_SYM_AND && pTemp[i] != AMAP_EQN_SYM_OR &&
+ pTemp[i] != AMAP_EQN_SYM_XOR && pTemp[i] != AMAP_EQN_SYM_CLOSE; i++ )
+ {
+ if ( pTemp[i] == AMAP_EQN_SYM_NEG || pTemp[i] == AMAP_EQN_SYM_OPEN )
+ {
+ fprintf( pOutput, "Amap_ParseFormula(): The negation sign or an opening paranthesis inside the variable name.\n" );
+ Flag = AMAP_EQN_FLAG_ERROR;
+ break;
+ }
+ }
+ // variable name is found
+ fFound = 0;
+ Vec_PtrForEachEntry( vVarNames, pName, v )
+ if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i )
+ {
+ pTemp += i-1;
+ fFound = 1;
+ break;
+ }
+ if ( !fFound )
+ {
+ fprintf( pOutput, "Amap_ParseFormula(): The parser cannot find var \"%s\" in the input var list.\n", pTemp );
+ Flag = AMAP_EQN_FLAG_ERROR;
+ break;
+ }
+ if ( Flag == AMAP_EQN_FLAG_VAR )
+ {
+ fprintf( pOutput, "Amap_ParseFormula(): The variable name \"%s\" follows another var without operation sign.\n", pTemp );
+ Flag = AMAP_EQN_FLAG_ERROR;
+ break;
+ }
+ Vec_PtrPush( pStackFn, Hop_IthVar( pMan, v ) ); // Cudd_Ref( pbVars[v] );
+ Flag = AMAP_EQN_FLAG_VAR;
+ break;
+ }
+
+ if ( Flag == AMAP_EQN_FLAG_ERROR )
+ break; // error exit
+ else if ( Flag == AMAP_EQN_FLAG_START )
+ continue; // go on parsing
+ else if ( Flag == AMAP_EQN_FLAG_VAR )
+ while ( 1 )
+ { // check if there are negations in the OpStack
+ if ( Vec_IntSize( pStackOp ) == 0 )
+ break;
+ Oper = Vec_IntPop( pStackOp );
+ if ( Oper != AMAP_EQN_OPER_NEG )
+ {
+ Vec_IntPush( pStackOp, Oper );
+ break;
+ }
+ else
+ {
+ Vec_PtrPush( pStackFn, Hop_Not(Vec_PtrPop(pStackFn)) );
+ }
+ }
+ else // if ( Flag == AMAP_EQN_FLAG_OPER )
+ while ( 1 )
+ { // execute all the operations in the OpStack
+ // with precedence higher or equal than the last one
+ Oper1 = Vec_IntPop( pStackOp ); // the last operation
+ if ( Vec_IntSize( pStackOp ) == 0 )
+ { // if it is the only operation, push it back
+ Vec_IntPush( pStackOp, Oper1 );
+ break;
+ }
+ Oper2 = Vec_IntPop( pStackOp ); // the operation before the last one
+ if ( Oper2 >= Oper1 )
+ { // if Oper2 precedence is higher or equal, execute it
+ if ( Amap_ParseFormulaOper( pMan, pStackFn, Oper2 ) == NULL )
+ {
+ fprintf( pOutput, "Amap_ParseFormula(): Unknown operation\n" );
+ free( pFormula );
+ return NULL;
+ }
+ Vec_IntPush( pStackOp, Oper1 ); // push the last operation back
+ }
+ else
+ { // if Oper2 precedence is lower, push them back and done
+ Vec_IntPush( pStackOp, Oper2 );
+ Vec_IntPush( pStackOp, Oper1 );
+ break;
+ }
+ }
+ }
+
+ if ( Flag != AMAP_EQN_FLAG_ERROR )
+ {
+ if ( Vec_PtrSize(pStackFn) != 0 )
+ {
+ gFunc = Vec_PtrPop(pStackFn);
+ if ( Vec_PtrSize(pStackFn) == 0 )
+ if ( Vec_IntSize( pStackOp ) == 0 )
+ {
+ Vec_PtrFree(pStackFn);
+ Vec_IntFree(pStackOp);
+// Cudd_Deref( gFunc );
+ free( pFormula );
+ return gFunc;
+ }
+ else
+ fprintf( pOutput, "Amap_ParseFormula(): Something is left in the operation stack\n" );
+ else
+ fprintf( pOutput, "Amap_ParseFormula(): Something is left in the function stack\n" );
+ }
+ else
+ fprintf( pOutput, "Amap_ParseFormula(): The input string is empty\n" );
+ }
+ free( pFormula );
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses equations for the gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_LibParseEquations( Amap_Lib_t * p, int fVerbose )
+{
+ extern int Kit_TruthSupportSize( unsigned * pTruth, int nVars );
+ Hop_Man_t * pMan;
+ Hop_Obj_t * pObj;
+ Vec_Ptr_t * vNames;
+ Vec_Int_t * vTruth;
+ Amap_Gat_t * pGate;
+ Amap_Pin_t * pPin;
+ unsigned * pTruth;
+ int i, nPinMax;
+ nPinMax = Amap_LibNumPinsMax(p);
+ if ( nPinMax > AMAP_MAXINS )
+ printf( "Gates with more than %d inputs will be ignored.\n", AMAP_MAXINS );
+ vTruth = Vec_IntAlloc( 1 << 16 );
+ vNames = Vec_PtrAlloc( 100 );
+ pMan = Hop_ManStart();
+ Hop_IthVar( pMan, nPinMax - 1 );
+ Vec_PtrForEachEntry( p->vGates, pGate, i )
+ {
+ if ( pGate->nPins == 0 )
+ {
+ pGate->pFunc = (unsigned *)Aig_MmFlexEntryFetch( p->pMemGates, 4 );
+ if ( strcmp( pGate->pForm, AMAP_STRING_CONST0 ) == 0 )
+ pGate->pFunc[0] = 0;
+ else if ( strcmp( pGate->pForm, AMAP_STRING_CONST1 ) == 0 )
+ pGate->pFunc[0] = ~0;
+ else
+ {
+ printf( "Cannot parse formula \"%s\" of gate \"%s\" with no pins.\n", pGate->pForm, pGate->pName );
+ break;
+ }
+ continue;
+ }
+ if ( pGate->nPins > AMAP_MAXINS )
+ continue;
+ Vec_PtrClear( vNames );
+ Amap_GateForEachPin( pGate, pPin )
+ Vec_PtrPush( vNames, pPin->pName );
+ pObj = Amap_ParseFormula( stdout, pGate->pForm, vNames, pMan );
+ if ( pObj == NULL )
+ break;
+ pTruth = Hop_ManConvertAigToTruth( pMan, pObj, pGate->nPins, vTruth, 0 );
+ if ( Kit_TruthSupportSize(pTruth, pGate->nPins) < (int)pGate->nPins )
+ {
+ printf( "Skipping gate \"%s\" because its formula \"%s\" does not depend on some pin variables.\n", pGate->pName, pGate->pForm );
+ continue;
+ }
+ pGate->pFunc = (unsigned *)Aig_MmFlexEntryFetch( p->pMemGates, sizeof(unsigned)*Aig_TruthWordNum(pGate->nPins) );
+ memcpy( pGate->pFunc, pTruth, sizeof(unsigned)*Aig_TruthWordNum(pGate->nPins) );
+ }
+ Vec_PtrFree( vNames );
+ Vec_IntFree( vTruth );
+ Hop_ManStop( pMan );
+ return i == Vec_PtrSize(p->vGates);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses equations for the gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_LibParseTest( char * pFileName )
+{
+ int fVerbose = 1;
+ Amap_Lib_t * p;
+ int clk = clock();
+ p = Amap_LibReadFile( pFileName, fVerbose );
+ if ( p == NULL )
+ return;
+ Amap_LibParseEquations( p, fVerbose );
+ Amap_LibFree( p );
+ PRT( "Total time", clock() - clk );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/amap/amapPerm.c b/src/map/amap/amapPerm.c
new file mode 100644
index 00000000..17fb57e2
--- /dev/null
+++ b/src/map/amap/amapPerm.c
@@ -0,0 +1,344 @@
+/**CFile****************************************************************
+
+ FileName [amapPerm.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis [Deriving permutation for the gate.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapPerm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+#include "kit.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Collects fanins of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_LibCollectFanins_rec( Amap_Lib_t * pLib, Amap_Nod_t * pNod, Vec_Int_t * vFanins )
+{
+ Amap_Nod_t * pFan0, * pFan1;
+ if ( pNod->Id == 0 )
+ {
+ Vec_IntPush( vFanins, 0 );
+ return;
+ }
+ pFan0 = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan0) );
+ if ( Amap_LitIsCompl(pNod->iFan0) || pFan0->Type != pNod->Type )
+ Vec_IntPush( vFanins, pNod->iFan0 );
+ else
+ Amap_LibCollectFanins_rec( pLib, pFan0, vFanins );
+ pFan1 = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan1) );
+ if ( Amap_LitIsCompl(pNod->iFan1) || pFan1->Type != pNod->Type )
+ Vec_IntPush( vFanins, pNod->iFan1 );
+ else
+ Amap_LibCollectFanins_rec( pLib, pFan1, vFanins );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects fanins of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Amap_LibCollectFanins( Amap_Lib_t * pLib, Amap_Nod_t * pNod )
+{
+ Vec_Int_t * vFanins = Vec_IntAlloc( 10 );
+ Amap_LibCollectFanins_rec( pLib, pNod, vFanins );
+ return vFanins;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Matches the node with the DSD node.]
+
+ Description [Returns perm if the node can be matched.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Amap_LibDeriveGatePerm_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * pNtk, int iLit, Amap_Nod_t * pNod )
+{
+ Vec_Int_t * vPerm, * vPermFanin, * vNodFanin, * vDsdLits;
+ Kit_DsdObj_t * pDsdObj, * pDsdFanin;
+ Amap_Nod_t * pNodFanin;
+ int iDsdFanin, iNodFanin, Value, iDsdLit, i, k, j;
+ assert( !Kit_DsdLitIsCompl(iLit) );
+ pDsdObj = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iLit) );
+ if ( pDsdObj == NULL )
+ {
+ vPerm = Vec_IntAlloc( 1 );
+ Vec_IntPush( vPerm, iLit );
+ return vPerm;
+ }
+ if ( pDsdObj->Type == KIT_DSD_PRIME && pNod->Type == AMAP_OBJ_MUX )
+ {
+ vPerm = Vec_IntAlloc( 10 );
+
+ iDsdFanin = Kit_DsdLitRegular(pDsdObj->pFans[0]);
+ pNodFanin = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan0) );
+ vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin );
+ Vec_IntForEachEntry( vPermFanin, Value, k )
+ Vec_IntPush( vPerm, Value );
+ Vec_IntFree( vPermFanin );
+
+ iDsdFanin = Kit_DsdLitRegular(pDsdObj->pFans[1]);
+ pNodFanin = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan1) );
+ vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin );
+ Vec_IntForEachEntry( vPermFanin, Value, k )
+ Vec_IntPush( vPerm, Value );
+ Vec_IntFree( vPermFanin );
+
+ iDsdFanin = Kit_DsdLitRegular(pDsdObj->pFans[2]);
+ pNodFanin = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan2) );
+ vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin );
+ Vec_IntForEachEntry( vPermFanin, Value, k )
+ Vec_IntPush( vPerm, Value );
+ Vec_IntFree( vPermFanin );
+
+ return vPerm;
+ }
+ // return if wrong types
+ if ( pDsdObj->Type == KIT_DSD_PRIME || pNod->Type == AMAP_OBJ_MUX )
+ return NULL;
+ // return if sizes do not agree
+ vNodFanin = Amap_LibCollectFanins( pLib, pNod );
+ if ( Vec_IntSize(vNodFanin) != (int)pDsdObj->nFans )
+ {
+ Vec_IntFree( vNodFanin );
+ return NULL;
+ }
+ // match fanins of DSD with fanins of nodes
+ // clean the mark and save variable literals
+ vPerm = Vec_IntAlloc( 10 );
+ vDsdLits = Vec_IntAlloc( 10 );
+ Kit_DsdObjForEachFaninReverse( pNtk, pDsdObj, iDsdFanin, i )
+ {
+ pDsdFanin = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iDsdFanin) );
+ if ( pDsdFanin )
+ pDsdFanin->fMark = 0;
+ else
+ Vec_IntPush( vDsdLits, iDsdFanin );
+ }
+ // match each fanins of the node
+ iDsdLit = 0;
+ Vec_IntForEachEntry( vNodFanin, iNodFanin, k )
+ {
+ if ( iNodFanin == 0 )
+ {
+ iDsdFanin = Vec_IntEntry( vDsdLits, iDsdLit++ );
+ Vec_IntPush( vPerm, iDsdFanin );
+ continue;
+ }
+ // find a matching component
+ pNodFanin = Amap_LibNod( pLib, Amap_Lit2Var(iNodFanin) );
+ Kit_DsdObjForEachFaninReverse( pNtk, pDsdObj, iDsdFanin, i )
+ {
+ pDsdFanin = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iDsdFanin) );
+ if ( pDsdFanin == NULL )
+ continue;
+ if ( pDsdFanin->fMark == 1 )
+ continue;
+ if ( !((pDsdFanin->Type == KIT_DSD_AND && pNodFanin->Type == AMAP_OBJ_AND) ||
+ (pDsdFanin->Type == KIT_DSD_XOR && pNodFanin->Type == AMAP_OBJ_XOR) ||
+ (pDsdFanin->Type == KIT_DSD_PRIME && pNodFanin->Type == AMAP_OBJ_MUX)) )
+ continue;
+ vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Kit_DsdLitRegular(iDsdFanin), pNodFanin );
+ if ( vPermFanin == NULL )
+ continue;
+ pDsdFanin->fMark = 1;
+ Vec_IntForEachEntry( vPermFanin, Value, j )
+ Vec_IntPush( vPerm, Value );
+ Vec_IntFree( vPermFanin );
+ break;
+ }
+ }
+ assert( iDsdLit == Vec_IntSize(vDsdLits) );
+ Vec_IntFree( vNodFanin );
+ Vec_IntFree( vDsdLits );
+ return vPerm;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs verification of one gate and one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Amap_LibVerifyPerm_rec( Amap_Lib_t * pLib, Amap_Nod_t * pNod,
+ Vec_Ptr_t * vTtElems, Vec_Int_t * vTruth, int nWords, int * piInput )
+{
+ Amap_Nod_t * pFan0, * pFan1;
+ unsigned * pTruth0, * pTruth1, * pTruth;
+ int i;
+ assert( pNod->Type != AMAP_OBJ_MUX );
+ if ( pNod->Id == 0 )
+ return Vec_PtrEntry( vTtElems, (*piInput)++ );
+ pFan0 = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan0) );
+ pTruth0 = Amap_LibVerifyPerm_rec( pLib, pFan0, vTtElems, vTruth, nWords, piInput );
+ pFan1 = Amap_LibNod( pLib, Amap_Lit2Var(pNod->iFan1) );
+ pTruth1 = Amap_LibVerifyPerm_rec( pLib, pFan1, vTtElems, vTruth, nWords, piInput );
+ pTruth = Vec_IntFetch( vTruth, nWords );
+ if ( pNod->Type == AMAP_OBJ_XOR )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = pTruth0[i] ^ pTruth1[i];
+ else if ( !Amap_LitIsCompl(pNod->iFan0) && !Amap_LitIsCompl(pNod->iFan1) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = pTruth0[i] & pTruth1[i];
+ else if ( !Amap_LitIsCompl(pNod->iFan0) && Amap_LitIsCompl(pNod->iFan1) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = pTruth0[i] & ~pTruth1[i];
+ else if ( Amap_LitIsCompl(pNod->iFan0) && !Amap_LitIsCompl(pNod->iFan1) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ~pTruth0[i] & pTruth1[i];
+ else // if ( Amap_LitIsCompl(pNod->iFan0) && Hop_ObjFaninC1(pObj) )
+ for ( i = 0; i < nWords; i++ )
+ pTruth[i] = ~pTruth0[i] & ~pTruth1[i];
+ return pTruth;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs verification of one gate and one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_LibVerifyPerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, int * pArray )
+{
+ Vec_Ptr_t * vTtElems;
+ Vec_Ptr_t * vTtElemsPol;
+ Vec_Int_t * vTruth;
+ unsigned * pTruth;
+ int i, nWords;
+ int iInput = 0;
+
+ // allocate storage for truth tables
+ assert( pGate->nPins > 1 );
+ nWords = Kit_TruthWordNum( pGate->nPins );
+ vTruth = Vec_IntAlloc( nWords * AMAP_MAXINS );
+ vTtElems = Vec_PtrAllocTruthTables( pGate->nPins );
+ vTtElemsPol = Vec_PtrAlloc( pGate->nPins );
+ for ( i = 0; i < (int)pGate->nPins; i++ )
+ {
+ pTruth = Vec_PtrEntry( vTtElems, Amap_Lit2Var(pArray[i]) );
+ if ( Amap_LitIsCompl( pArray[i] ) )
+ Kit_TruthNot( pTruth, pTruth, pGate->nPins );
+ Vec_PtrPush( vTtElemsPol, pTruth );
+ }
+//Extra_PrintBinary( stdout, Vec_PtrEntry(vTtElemsPol, 0), 4 ); printf("\n" );
+//Extra_PrintBinary( stdout, Vec_PtrEntry(vTtElemsPol, 1), 4 ); printf("\n" );
+ // compute the truth table recursively
+ pTruth = Amap_LibVerifyPerm_rec( pLib, pNod, vTtElemsPol, vTruth, nWords, &iInput );
+ assert( iInput == (int)pGate->nPins );
+ if ( Kit_DsdLitIsCompl(pNtk->Root) )
+ Kit_TruthNot( pTruth, pTruth, pGate->nPins );
+//Extra_PrintBinary( stdout, pTruth, 4 ); printf("\n" );
+//Extra_PrintBinary( stdout, pGate->pFunc, 4 ); printf("\n" );
+ // compare
+ if ( !Kit_TruthIsEqual(pGate->pFunc, pTruth, pGate->nPins) )
+ printf( "Verification failed for gate %d (%s) and node %d.\n",
+ pGate->Id, pGate->pForm, pNod->Id );
+ Vec_IntFree( vTruth );
+ Vec_PtrFree( vTtElems );
+ Vec_PtrFree( vTtElemsPol );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Matches the node with the DSD of a gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, char * pArray )
+{
+ int fVerbose = 0;
+ Vec_Int_t * vPerm;
+ int Entry, Entry2, i, k;
+ vPerm = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Kit_DsdLitRegular(pNtk->Root), pNod );
+ if ( vPerm == NULL )
+ return 0;
+ // check that the permutation is valid
+ assert( Vec_IntSize(vPerm) == (int)pNod->nSuppSize );
+ Vec_IntForEachEntry( vPerm, Entry, i )
+ Vec_IntForEachEntryStart( vPerm, Entry2, k, i+1 )
+ if ( Amap_Lit2Var(Entry) == Amap_Lit2Var(Entry2) )
+ {
+ Vec_IntFree( vPerm );
+ return 0;
+ }
+
+ // reverse the permutation
+ Vec_IntForEachEntry( vPerm, Entry, i )
+ {
+ assert( Entry < 2 * (int)pNod->nSuppSize );
+ pArray[Kit_DsdLit2Var(Entry)] = Amap_Var2Lit( i, Kit_DsdLitIsCompl(Entry) );
+// pArray[i] = Entry;
+//printf( "%d=%d%c ", Kit_DsdLit2Var(Entry), i, Kit_DsdLitIsCompl(Entry)?'-':'+' );
+ }
+//printf( "\n" );
+// if ( Kit_DsdNonDsdSizeMax(pNtk) < 3 )
+// Amap_LibVerifyPerm( pLib, pGate, pNtk, pNod, Vec_IntArray(vPerm) );
+ Vec_IntFree( vPerm );
+ // print the result
+ if ( fVerbose )
+ {
+ printf( "node %4d : ", pNod->Id );
+ for ( i = 0; i < (int)pNod->nSuppSize; i++ )
+ printf( "%d=%d%c ", i, Amap_Lit2Var(pArray[i]), Amap_LitIsCompl(pArray[i])?'-':'+' );
+ printf( "\n" );
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/amap/amapRead.c b/src/map/amap/amapRead.c
new file mode 100644
index 00000000..182de5d1
--- /dev/null
+++ b/src/map/amap/amapRead.c
@@ -0,0 +1,412 @@
+/**CFile****************************************************************
+
+ FileName [amapRead.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapRead.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define AMAP_STRING_GATE "GATE"
+#define AMAP_STRING_PIN "PIN"
+#define AMAP_STRING_NONINV "NONINV"
+#define AMAP_STRING_INV "INV"
+#define AMAP_STRING_UNKNOWN "UNKNOWN"
+
+// these symbols (and no other) can appear in the formulas
+#define AMAP_SYMB_AND '*'
+#define AMAP_SYMB_OR1 '+'
+#define AMAP_SYMB_OR2 '|'
+#define AMAP_SYMB_XOR '^'
+#define AMAP_SYMB_NOT '!'
+#define AMAP_SYMB_AFTNOT '\''
+#define AMAP_SYMB_OPEN '('
+#define AMAP_SYMB_CLOSE ')'
+
+typedef enum {
+ AMAP_PHASE_UNKNOWN,
+ AMAP_PHASE_INV,
+ AMAP_PHASE_NONINV
+} Amap_PinPhase_t;
+
+static inline Amap_Gat_t * Amap_ParseGateAlloc( Aig_MmFlex_t * p, int nPins )
+{ return (Amap_Gat_t *)Aig_MmFlexEntryFetch( p, sizeof(Amap_Gat_t)+sizeof(Amap_Pin_t)*nPins ); }
+static inline char * Amap_ParseStrsav( Aig_MmFlex_t * p, char * pStr )
+{ return pStr ? strcpy(Aig_MmFlexEntryFetch(p, strlen(pStr)+1), pStr) : NULL; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Loads the file into temporary buffer.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Amap_LoadFile( char * pFileName )
+{
+ extern FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose );
+ FILE * pFile;
+ char * pBuffer;
+ int nFileSize;
+ // open the BLIF file for binary reading
+ pFile = Io_FileOpen( pFileName, "open_path", "rb", 1 );
+// pFile = fopen( FileName, "rb" );
+ // if we got this far, file should be okay otherwise would
+ // have been detected by caller
+ if ( pFile == NULL )
+ {
+ printf( "Cannot open file \"%s\".\n", pFileName );
+ return NULL;
+ }
+ assert ( pFile != NULL );
+ // get the file size, in bytes
+ fseek( pFile, 0, SEEK_END );
+ nFileSize = ftell( pFile );
+ // move the file current reading position to the beginning
+ rewind( pFile );
+ // load the contents of the file into memory
+ pBuffer = ALLOC( char, nFileSize + 10 );
+ fread( pBuffer, nFileSize, 1, pFile );
+ // terminate the string with '\0'
+ pBuffer[ nFileSize ] = '\0';
+ strcat( pBuffer, "\n.end\n" );
+ // close file
+ fclose( pFile );
+ return pBuffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Eliminates comments from the input file.]
+
+ Description [As a byproduct, this procedure also counts the number
+ lines and dot-statements in the input file. This also joins non-comment
+ lines that are joined with a backspace '\']
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_RemoveComments( char * pBuffer, int * pnDots, int * pnLines )
+{
+ char * pCur;
+ int nDots, nLines;
+ // scan through the buffer and eliminate comments
+ // (in the BLIF file, comments are lines starting with "#")
+ nDots = nLines = 0;
+ for ( pCur = pBuffer; *pCur; pCur++ )
+ {
+ // if this is the beginning of comment
+ // clean it with spaces until the new line statement
+ if ( *pCur == '#' )
+ while ( *pCur != '\n' )
+ *pCur++ = ' ';
+
+ // count the number of new lines and dots
+ if ( *pCur == '\n' ) {
+ if (*(pCur-1)=='\r') {
+ // DOS(R) file support
+ if (*(pCur-2)!='\\') nLines++;
+ else {
+ // rewind to backslash and overwrite with a space
+ *(pCur-2) = ' ';
+ *(pCur-1) = ' ';
+ *pCur = ' ';
+ }
+ } else {
+ // UNIX(TM) file support
+ if (*(pCur-1)!='\\') nLines++;
+ else {
+ // rewind to backslash and overwrite with a space
+ *(pCur-1) = ' ';
+ *pCur = ' ';
+ }
+ }
+ }
+ else if ( *pCur == '.' )
+ nDots++;
+ }
+ if ( pnDots )
+ *pnDots = nDots;
+ if ( pnLines )
+ *pnLines = nLines;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Splits the stream into tokens.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Amap_DeriveTokens( char * pBuffer )
+{
+ Vec_Ptr_t * vTokens;
+ char * pToken;
+ vTokens = Vec_PtrAlloc( 1000 );
+ pToken = strtok( pBuffer, " ;=\t\r\n" );
+ while ( pToken )
+ {
+ Vec_PtrPush( vTokens, pToken );
+ pToken = strtok( NULL, " ;=\t\r\n" );
+ }
+ return vTokens;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds the number of pins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_ParseCountPins( Vec_Ptr_t * vTokens, int iPos )
+{
+ char * pToken;
+ int i, Counter = 0;
+ Vec_PtrForEachEntryStart( vTokens, pToken, i, iPos )
+ if ( !strcmp( pToken, AMAP_STRING_PIN ) )
+ Counter++;
+ else if ( !strcmp( pToken, AMAP_STRING_GATE ) )
+ return Counter;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect the pin names used in the formula.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_GateCollectNames( Aig_MmFlex_t * pMem, char * pForm, char * pPinNames[] )
+{
+ char Buffer[1000];
+ char * pTemp;
+ int nPins, i;
+ // save the formula as it was
+ strcpy( Buffer, pForm );
+ // remove the non-name symbols
+ for ( pTemp = Buffer; *pTemp; pTemp++ )
+ if ( *pTemp == AMAP_SYMB_AND || *pTemp == AMAP_SYMB_OR1 || *pTemp == AMAP_SYMB_OR2
+ || *pTemp == AMAP_SYMB_XOR || *pTemp == AMAP_SYMB_NOT || *pTemp == AMAP_SYMB_OPEN
+ || *pTemp == AMAP_SYMB_CLOSE || *pTemp == AMAP_SYMB_AFTNOT )
+ *pTemp = ' ';
+ // save the names
+ nPins = 0;
+ pTemp = strtok( Buffer, " " );
+ while ( pTemp )
+ {
+ for ( i = 0; i < nPins; i++ )
+ if ( strcmp( pTemp, pPinNames[i] ) == 0 )
+ break;
+ if ( i == nPins )
+ { // cannot find this name; save it
+ pPinNames[nPins++] = Amap_ParseStrsav( pMem, pTemp );
+ }
+ // get the next name
+ pTemp = strtok( NULL, " " );
+ }
+ return nPins;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a duplicate gate with pins specified.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Gat_t * Amap_ParseGateWithSamePins( Amap_Gat_t * p )
+{
+ Amap_Gat_t * pGate;
+ Amap_Pin_t * pPin;
+ char * pPinNames[128];
+ int nPinNames;
+ assert( p->nPins == 1 && !strcmp( p->Pins->pName, "*" ) );
+ nPinNames = Amap_GateCollectNames( p->pLib->pMemGates, p->pForm, pPinNames );
+ pGate = Amap_ParseGateAlloc( p->pLib->pMemGates, nPinNames );
+ *pGate = *p;
+ pGate->nPins = nPinNames;
+ Amap_GateForEachPin( pGate, pPin )
+ {
+ *pPin = *p->Pins;
+ pPin->pName = pPinNames[pPin - pGate->Pins];
+ }
+ return pGate;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Lib_t * Amap_ParseTokens( Vec_Ptr_t * vTokens, int fVerbose )
+{
+ Amap_Lib_t * p;
+ Amap_Gat_t * pGate;
+ Amap_Pin_t * pPin;
+ char * pToken;
+ int nPins, iPos = 0;
+ p = Amap_LibAlloc();
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ do
+ {
+ if ( strcmp( pToken, AMAP_STRING_GATE ) )
+ {
+ printf( "The first line should begin with %s.\n", AMAP_STRING_GATE );
+ return NULL;
+ }
+ // start gate
+ nPins = Amap_ParseCountPins( vTokens, iPos );
+ pGate = Amap_ParseGateAlloc( p->pMemGates, nPins );
+ memset( pGate, 0, sizeof(Amap_Gat_t) );
+ pGate->Id = Vec_PtrSize( p->vGates );
+ Vec_PtrPush( p->vGates, pGate );
+ pGate->pLib = p;
+ pGate->nPins = nPins;
+ // read gate
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ pGate->pName = Amap_ParseStrsav( p->pMemGates, pToken );
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ pGate->dArea = atof( pToken );
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ pGate->pOutName = Amap_ParseStrsav( p->pMemGates, pToken );
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ pGate->pForm = Amap_ParseStrsav( p->pMemGates, pToken );
+ // read pins
+ Amap_GateForEachPin( pGate, pPin )
+ {
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ if ( strcmp( pToken, AMAP_STRING_PIN ) )
+ {
+ printf( "Cannot parse gate %s.\n", pGate->pName );
+ return NULL;
+ }
+ // read pin
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ pPin->pName = Amap_ParseStrsav( p->pMemGates, pToken );
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ if ( strcmp( pToken, AMAP_STRING_UNKNOWN ) == 0 )
+ pPin->Phase = AMAP_PHASE_UNKNOWN;
+ else if ( strcmp( pToken, AMAP_STRING_INV ) == 0 )
+ pPin->Phase = AMAP_PHASE_INV;
+ else if ( strcmp( pToken, AMAP_STRING_NONINV ) == 0 )
+ pPin->Phase = AMAP_PHASE_NONINV;
+ else
+ {
+ printf( "Cannot read phase of pin %s of gate %s\n", pPin->pName, pGate->pName );
+ return NULL;
+ }
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ pPin->dLoadInput = atof( pToken );
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ pPin->dLoadMax = atof( pToken );
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ pPin->dDelayBlockRise = atof( pToken );
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ pPin->dDelayFanoutRise = atof( pToken );
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ pPin->dDelayBlockFall = atof( pToken );
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ pPin->dDelayFanoutFall = atof( pToken );
+ if ( pPin->dDelayBlockRise > pPin->dDelayBlockFall )
+ pPin->dDelayBlockMax = pPin->dDelayBlockRise;
+ else
+ pPin->dDelayBlockMax = pPin->dDelayBlockFall;
+ }
+ // fix the situation when all pins are represented as one
+ if ( pGate->nPins == 1 && !strcmp( pGate->Pins->pName, "*" ) )
+ {
+ pGate = Amap_ParseGateWithSamePins( pGate );
+ Vec_PtrPop( p->vGates );
+ Vec_PtrPush( p->vGates, pGate );
+ }
+ pToken = Vec_PtrEntry(vTokens, iPos++);
+ }
+ while ( strcmp( pToken, ".end" ) );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the library from the input file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Lib_t * Amap_LibReadFile( char * pFileName, int fVerbose )
+{
+ Amap_Lib_t * pLib;
+ Vec_Ptr_t * vTokens;
+ char * pBuffer;
+ pBuffer = Amap_LoadFile( pFileName );
+ if ( pBuffer == NULL )
+ return NULL;
+ Amap_RemoveComments( pBuffer, NULL, NULL );
+ vTokens = Amap_DeriveTokens( pBuffer );
+ pLib = Amap_ParseTokens( vTokens, fVerbose );
+ if ( pLib == NULL )
+ return NULL;
+ pLib->pName = Amap_ParseStrsav( pLib->pMemGates, pFileName );
+ Vec_PtrFree( vTokens );
+ free( pBuffer );
+ return pLib;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/amap/amapRule.c b/src/map/amap/amapRule.c
new file mode 100644
index 00000000..212f7631
--- /dev/null
+++ b/src/map/amap/amapRule.c
@@ -0,0 +1,368 @@
+/**CFile****************************************************************
+
+ FileName [amapRule.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis [Matching rules.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapRule.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+#include "kit.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, char * pArray );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the three-argument rule exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Amap_CreateRulesPrime( Amap_Lib_t * p, Vec_Int_t * vNods0, Vec_Int_t * vNods1, Vec_Int_t * vNods2 )
+{
+ Vec_Int_t * vRes;
+ int i, k, j, iNod, iNod0, iNod1, iNod2;
+ if ( p->vRules3 == NULL )
+ p->vRules3 = Vec_IntAlloc( 100 );
+ vRes = Vec_IntAlloc( 10 );
+ Vec_IntForEachEntry( vNods0, iNod0, i )
+ Vec_IntForEachEntry( vNods1, iNod1, k )
+ Vec_IntForEachEntry( vNods2, iNod2, j )
+ {
+ iNod = Amap_LibFindMux( p, iNod0, iNod1, iNod2 );
+ if ( iNod == -1 )
+ iNod = Amap_LibCreateMux( p, iNod0, iNod1, iNod2 );
+ Vec_IntPush( vRes, Amap_Var2Lit(iNod, 0) );
+ }
+ return vRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_CreateRulesTwo( Amap_Lib_t * p, Vec_Int_t * vNods, Vec_Int_t * vNods0, Vec_Int_t * vNods1, int fXor )
+{
+ int i, k, iNod, iNod0, iNod1;
+ Vec_IntForEachEntry( vNods0, iNod0, i )
+ Vec_IntForEachEntry( vNods1, iNod1, k )
+ {
+ iNod = Amap_LibFindNode( p, iNod0, iNod1, fXor );
+ if ( iNod == -1 )
+ iNod = Amap_LibCreateNode( p, iNod0, iNod1, fXor );
+ Vec_IntPushUnique( vNods, Amap_Var2Lit(iNod, 0) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_CreateCheckAllZero( Vec_Ptr_t * vVecNods )
+{
+ Vec_Int_t * vNods;
+ int i;
+ Vec_PtrForEachEntryReverse( vVecNods, vNods, i )
+ if ( Vec_IntSize(vNods) != 1 || Vec_IntEntry(vNods,0) != 0 )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Amap_CreateRulesVector_rec( Amap_Lib_t * p, Vec_Ptr_t * vVecNods, int fXor )
+{
+ Vec_Ptr_t * vVecNods0, * vVecNods1;
+ Vec_Int_t * vRes, * vNods, * vNods0, * vNods1;
+ int i, k;
+ if ( Vec_PtrSize(vVecNods) == 1 )
+ return Vec_IntDup( Vec_PtrEntry(vVecNods, 0) );
+ vRes = Vec_IntAlloc( 10 );
+ vVecNods0 = Vec_PtrAlloc( Vec_PtrSize(vVecNods) );
+ vVecNods1 = Vec_PtrAlloc( Vec_PtrSize(vVecNods) );
+ if ( Amap_CreateCheckAllZero(vVecNods) )
+ {
+ for ( i = Vec_PtrSize(vVecNods)-1; i > 0; i-- )
+ {
+ Vec_PtrClear( vVecNods0 );
+ Vec_PtrClear( vVecNods1 );
+ Vec_PtrForEachEntryStop( vVecNods, vNods, k, i )
+ Vec_PtrPush( vVecNods0, vNods );
+ Vec_PtrForEachEntryStart( vVecNods, vNods, k, i )
+ Vec_PtrPush( vVecNods1, vNods );
+ vNods0 = Amap_CreateRulesVector_rec( p, vVecNods0, fXor );
+ vNods1 = Amap_CreateRulesVector_rec( p, vVecNods1, fXor );
+ Amap_CreateRulesTwo( p, vRes, vNods0, vNods1, fXor );
+ Vec_IntFree( vNods0 );
+ Vec_IntFree( vNods1 );
+ }
+ }
+ else
+ {
+ int Limit = (1 << Vec_PtrSize(vVecNods))-2;
+ for ( i = 1; i < Limit; i++ )
+ {
+ Vec_PtrClear( vVecNods0 );
+ Vec_PtrClear( vVecNods1 );
+ Vec_PtrForEachEntryReverse( vVecNods, vNods, k )
+ {
+ if ( i & (1 << k) )
+ Vec_PtrPush( vVecNods1, vNods );
+ else
+ Vec_PtrPush( vVecNods0, vNods );
+ }
+ assert( Vec_PtrSize(vVecNods0) > 0 );
+ assert( Vec_PtrSize(vVecNods1) > 0 );
+ assert( Vec_PtrSize(vVecNods0) < Vec_PtrSize(vVecNods) );
+ assert( Vec_PtrSize(vVecNods1) < Vec_PtrSize(vVecNods) );
+ vNods0 = Amap_CreateRulesVector_rec( p, vVecNods0, fXor );
+ vNods1 = Amap_CreateRulesVector_rec( p, vVecNods1, fXor );
+ Amap_CreateRulesTwo( p, vRes, vNods0, vNods1, fXor );
+ Vec_IntFree( vNods0 );
+ Vec_IntFree( vNods1 );
+ }
+ }
+ Vec_PtrFree( vVecNods0 );
+ Vec_PtrFree( vVecNods1 );
+ return vRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Amap_CreateRulesFromDsd_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * p, int iLit )
+{
+ Vec_Int_t * vRes;
+ Vec_Ptr_t * vVecNods;
+ Vec_Int_t * vNodsFanin;
+ Kit_DsdObj_t * pObj;
+ unsigned i;
+ int iFanin, iNod, k;
+ assert( !Kit_DsdLitIsCompl(iLit) );
+ pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) );
+ if ( pObj == NULL )
+ return Vec_IntStartNatural( 1 );
+ // solve for the inputs
+ vVecNods = Vec_PtrAlloc( pObj->nFans );
+ Kit_DsdObjForEachFanin( p, pObj, iFanin, i )
+ {
+ vNodsFanin = Amap_CreateRulesFromDsd_rec( pLib, p, Kit_DsdLitRegular(iFanin) );
+ if ( Kit_DsdLitIsCompl(iFanin) )
+ {
+ Vec_IntForEachEntry( vNodsFanin, iNod, k )
+ if ( iNod > 0 )
+ Vec_IntWriteEntry( vNodsFanin, k, Amap_LitNot(iNod) );
+ }
+ Vec_PtrPush( vVecNods, vNodsFanin );
+ }
+ if ( pObj->Type == KIT_DSD_AND )
+ vRes = Amap_CreateRulesVector_rec( pLib, vVecNods, 0 );
+ else if ( pObj->Type == KIT_DSD_XOR )
+ vRes = Amap_CreateRulesVector_rec( pLib, vVecNods, 1 );
+ else if ( pObj->Type == KIT_DSD_PRIME )
+ {
+ assert( pObj->nFans == 3 );
+ assert( Kit_DsdObjTruth(pObj)[0] == 0xCACACACA );
+ vRes = Amap_CreateRulesPrime( pLib, Vec_PtrEntry(vVecNods, 0),
+ Vec_PtrEntry(vVecNods, 1), Vec_PtrEntry(vVecNods, 2) );
+ }
+ else assert( 0 );
+ Vec_PtrForEachEntry( vVecNods, vNodsFanin, k )
+ Vec_IntFree( vNodsFanin );
+ Vec_PtrFree( vVecNods );
+ return vRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Amap_CreateRulesFromDsd( Amap_Lib_t * pLib, Kit_DsdNtk_t * p )
+{
+ Vec_Int_t * vNods;
+ int iNod, i;
+ assert( p->nVars >= 2 );
+ vNods = Amap_CreateRulesFromDsd_rec( pLib, p, Kit_DsdLitRegular(p->Root) );
+ if ( vNods == NULL )
+ return NULL;
+ if ( Kit_DsdLitIsCompl(p->Root) )
+ {
+ Vec_IntForEachEntry( vNods, iNod, i )
+ Vec_IntWriteEntry( vNods, i, Amap_LitNot(iNod) );
+ }
+ return vNods;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates rules for the given gate]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_CreateRulesForGate( Amap_Lib_t * pLib, Amap_Gat_t * pGate )
+{
+ Kit_DsdNtk_t * pNtk, * pTemp;
+ Vec_Int_t * vNods;
+ Amap_Nod_t * pNod;
+ Amap_Set_t * pSet;
+ int iNod, i;
+// if ( pGate->nPins > 4 )
+// return;
+ pNtk = Kit_DsdDecomposeMux( pGate->pFunc, pGate->nPins, 2 );
+ if ( pGate->nPins == 2 && (pGate->pFunc[0] == 0x66666666 || pGate->pFunc[0] == ~0x66666666) )
+ pLib->fHasXor = 1;
+ if ( Kit_DsdNonDsdSizeMax(pNtk) == 3 )
+ pLib->fHasMux = pGate->fMux = 1;
+ pNtk = Kit_DsdExpand( pTemp = pNtk );
+ Kit_DsdNtkFree( pTemp );
+ Kit_DsdVerify( pNtk, pGate->pFunc, pGate->nPins );
+if ( pLib->fVerbose )
+//if ( pGate->fMux )
+{
+printf( "\nProcessing library gate %4d: %10s ", pGate->Id, pGate->pName );
+Kit_DsdPrint( stdout, pNtk );
+}
+ vNods = Amap_CreateRulesFromDsd( pLib, pNtk );
+ if ( vNods )
+ {
+ Vec_IntForEachEntry( vNods, iNod, i )
+ {
+ assert( iNod > 1 );
+ pNod = Amap_LibNod( pLib, Amap_Lit2Var(iNod) );
+ assert( pNod->Type == AMAP_OBJ_MUX || pNod->nSuppSize == pGate->nPins );
+ pSet = (Amap_Set_t *)Aig_MmFlexEntryFetch( pLib->pMemSet, sizeof(Amap_Set_t) );
+ memset( pSet, 0, sizeof(Amap_Set_t) );
+ pSet->iGate = pGate->Id;
+ pSet->fInv = Amap_LitIsCompl(iNod);
+ pSet->nIns = pGate->nPins;
+ if ( Amap_LibDeriveGatePerm( pLib, pGate, pNtk, pNod, pSet->Ins ) == 0 )
+ {
+if ( pLib->fVerbose )
+{
+ printf( "Cound not prepare gate \"%s\": ", pGate->pName );
+ Kit_DsdPrint( stdout, pNtk );
+}
+ continue;
+ }
+ pSet->pNext = pNod->pSets;
+ pNod->pSets = pSet;
+ pLib->nSets++;
+ }
+ Vec_IntFree( vNods );
+ }
+ Kit_DsdNtkFree( pNtk );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates rules for the given gate]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Amap_LibCreateRules( Amap_Lib_t * pLib, int fVeryVerbose )
+{
+ Amap_Gat_t * pGate;
+ int i, nGates = 0;
+ int clk = clock();
+ pLib->fVerbose = fVeryVerbose;
+ pLib->vRules = Vec_PtrAlloc( 100 );
+ pLib->vRulesX = Vec_PtrAlloc( 100 );
+ pLib->vRules3 = Vec_IntAlloc( 100 );
+ Amap_LibCreateVar( pLib );
+ Vec_PtrForEachEntry( pLib->vSelect, pGate, i )
+ {
+ if ( pGate->nPins < 2 )
+ continue;
+ if ( pGate->pFunc == NULL )
+ {
+ printf( "Amap_LibCreateRules(): Skipping gate %s (%s).\n", pGate->pName, pGate->pForm );
+ continue;
+ }
+ Amap_CreateRulesForGate( pLib, pGate );
+ nGates++;
+ }
+ assert( Vec_PtrSize(pLib->vRules) == 2*pLib->nNodes );
+ assert( Vec_PtrSize(pLib->vRulesX) == 2*pLib->nNodes );
+ pLib->pRules = Amap_LibLookupTableAlloc( pLib->vRules, 0 );
+ pLib->pRulesX = Amap_LibLookupTableAlloc( pLib->vRulesX, 0 );
+ Vec_VecFree( (Vec_Vec_t *)pLib->vRules ); pLib->vRules = NULL;
+ Vec_VecFree( (Vec_Vec_t *)pLib->vRulesX ); pLib->vRulesX = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/amap/amapUniq.c b/src/map/amap/amapUniq.c
new file mode 100644
index 00000000..83fce6a2
--- /dev/null
+++ b/src/map/amap/amapUniq.c
@@ -0,0 +1,312 @@
+/**CFile****************************************************************
+
+ FileName [amapUniq.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Technology mapper for standard cells.]
+
+ Synopsis [Checks if the structural node already exists.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: amapUniq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "amapInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the entry exists and returns value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Vec_IntCheckWithMask( Vec_Int_t * p, int Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( (0xffff & p->pArray[i]) == (0xffff & Entry) )
+ return p->pArray[i] >> 16;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Pushes entry in the natural order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Vec_IntPushOrderWithMask( Vec_Int_t * p, int Entry )
+{
+ int i;
+ if ( p->nSize == p->nCap )
+ Vec_IntGrow( p, 2 * p->nCap );
+ p->nSize++;
+ for ( i = p->nSize-2; i >= 0; i-- )
+ if ( (0xffff & p->pArray[i]) > (0xffff & Entry) )
+ p->pArray[i+1] = p->pArray[i];
+ else
+ break;
+ p->pArray[i+1] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_LibFindNode( Amap_Lib_t * pLib, int iFan0, int iFan1, int fXor )
+{
+ if ( fXor )
+ return Vec_IntCheckWithMask( Vec_PtrEntry(pLib->vRulesX, iFan0), iFan1 );
+ else
+ return Vec_IntCheckWithMask( Vec_PtrEntry(pLib->vRules, iFan0), iFan1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the three-argument rule exist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_LibFindMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 )
+{
+ int x;
+ for ( x = 0; x < Vec_IntSize(p->vRules3); x += 4 )
+ {
+ if ( Vec_IntEntry(p->vRules3, x) == iFan0 &&
+ Vec_IntEntry(p->vRules3, x+1) == iFan1 &&
+ Vec_IntEntry(p->vRules3, x+2) == iFan2 )
+ {
+ return Vec_IntEntry(p->vRules3, x+3);
+ }
+ }
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Amap_Nod_t * Amap_LibCreateObj( Amap_Lib_t * p )
+{
+ Amap_Nod_t * pNode;
+ if ( p->nNodes == p->nNodesAlloc )
+ {
+ p->pNodes = REALLOC( Amap_Nod_t, p->pNodes, 2*p->nNodesAlloc );
+ p->nNodesAlloc *= 2;
+ }
+ pNode = Amap_LibNod( p, p->nNodes );
+ memset( pNode, 0, sizeof(Amap_Nod_t) );
+ pNode->Id = p->nNodes++;
+ Vec_PtrPush( p->vRules, Vec_IntAlloc(8) );
+ Vec_PtrPush( p->vRules, Vec_IntAlloc(8) );
+ Vec_PtrPush( p->vRulesX, Vec_IntAlloc(8) );
+ Vec_PtrPush( p->vRulesX, Vec_IntAlloc(8) );
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_LibCreateVar( Amap_Lib_t * p )
+{
+ Amap_Nod_t * pNode;
+ // start the manager
+ assert( p->pNodes == NULL );
+ p->nNodesAlloc = 256;
+ p->pNodes = ALLOC( Amap_Nod_t, p->nNodesAlloc );
+ // create the first node
+ pNode = Amap_LibCreateObj( p );
+ p->pNodes->Type = AMAP_OBJ_PI;
+ p->pNodes->nSuppSize = 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_LibCreateNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor )
+{
+ Amap_Nod_t * pNode;
+ int iFan;
+ if ( iFan0 < iFan1 )
+ {
+ iFan = iFan0;
+ iFan0 = iFan1;
+ iFan1 = iFan;
+ }
+ pNode = Amap_LibCreateObj( p );
+ pNode->Type = fXor? AMAP_OBJ_XOR : AMAP_OBJ_AND;
+ pNode->nSuppSize = p->pNodes[Amap_Lit2Var(iFan0)].nSuppSize + p->pNodes[Amap_Lit2Var(iFan1)].nSuppSize;
+ pNode->iFan0 = iFan0;
+ pNode->iFan1 = iFan1;
+if ( p->fVerbose )
+printf( "Creating node %5d %c : iFan0 = %5d%c iFan1 = %5d%c\n",
+pNode->Id, (fXor?'x':' '),
+Amap_Lit2Var(iFan0), (Amap_LitIsCompl(iFan0)?'-':'+'),
+Amap_Lit2Var(iFan1), (Amap_LitIsCompl(iFan1)?'-':'+') );
+
+ if ( fXor )
+ {
+ if ( iFan0 == iFan1 )
+ Vec_IntPushOrderWithMask( Vec_PtrEntry(p->vRulesX, iFan0), (pNode->Id << 16) | iFan1 );
+ else
+ {
+ Vec_IntPushOrderWithMask( Vec_PtrEntry(p->vRulesX, iFan0), (pNode->Id << 16) | iFan1 );
+ Vec_IntPushOrderWithMask( Vec_PtrEntry(p->vRulesX, iFan1), (pNode->Id << 16) | iFan0 );
+ }
+ }
+ else
+ {
+ if ( iFan0 == iFan1 )
+ Vec_IntPushOrderWithMask( Vec_PtrEntry(p->vRules, iFan0), (pNode->Id << 16) | iFan1 );
+ else
+ {
+ Vec_IntPushOrderWithMask( Vec_PtrEntry(p->vRules, iFan0), (pNode->Id << 16) | iFan1 );
+ Vec_IntPushOrderWithMask( Vec_PtrEntry(p->vRules, iFan1), (pNode->Id << 16) | iFan0 );
+ }
+ }
+ return pNode->Id;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Amap_LibCreateMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 )
+{
+ Amap_Nod_t * pNode;
+ pNode = Amap_LibCreateObj( p );
+ pNode->Type = AMAP_OBJ_MUX;
+ pNode->nSuppSize = p->pNodes[Amap_Lit2Var(iFan0)].nSuppSize + p->pNodes[Amap_Lit2Var(iFan1)].nSuppSize + p->pNodes[Amap_Lit2Var(iFan2)].nSuppSize;
+ pNode->iFan0 = iFan0;
+ pNode->iFan1 = iFan1;
+ pNode->iFan2 = iFan2;
+if ( p->fVerbose )
+printf( "Creating node %5d %c : iFan0 = %5d%c iFan1 = %5d%c iFan2 = %5d%c\n",
+pNode->Id, 'm',
+Amap_Lit2Var(iFan0), (Amap_LitIsCompl(iFan0)?'-':'+'),
+Amap_Lit2Var(iFan1), (Amap_LitIsCompl(iFan1)?'-':'+'),
+Amap_Lit2Var(iFan2), (Amap_LitIsCompl(iFan2)?'-':'+') );
+
+ Vec_IntPush( p->vRules3, iFan0 );
+ Vec_IntPush( p->vRules3, iFan1 );
+ Vec_IntPush( p->vRules3, iFan2 );
+ Vec_IntPush( p->vRules3, pNode->Id );
+ return pNode->Id;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates triangular lookup table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int ** Amap_LibLookupTableAlloc( Vec_Ptr_t * vVec, int fVerbose )
+{
+ Vec_Int_t * vOne;
+ int ** pRes, * pBuffer;
+ int i, k, nTotal, nSize, nEntries, Value;
+ // count the total size
+ nEntries = nSize = Vec_PtrSize( vVec );
+ Vec_PtrForEachEntry( vVec, vOne, i )
+ nEntries += Vec_IntSize(vOne);
+ pBuffer = ALLOC( int, nSize * sizeof(void *) + nEntries );
+ pRes = (int **)pBuffer;
+ pRes[0] = pBuffer + nSize * sizeof(void *);
+ nTotal = 0;
+ Vec_PtrForEachEntry( vVec, vOne, i )
+ {
+ pRes[i] = pRes[0] + nTotal;
+ nTotal += Vec_IntSize(vOne) + 1;
+ if ( fVerbose )
+ printf( "%d : ", i );
+ Vec_IntForEachEntry( vOne, Value, k )
+ {
+ pRes[i][k] = Value;
+ if ( fVerbose )
+ printf( "%d(%d) ", Value&0xffff, Value>>16 );
+ }
+ if ( fVerbose )
+ printf( "\n" );
+ pRes[i][k] = 0;
+ }
+ assert( nTotal == nEntries );
+ return pRes;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/map/amap/module.make b/src/map/amap/module.make
new file mode 100644
index 00000000..d5edadb9
--- /dev/null
+++ b/src/map/amap/module.make
@@ -0,0 +1,12 @@
+SRC += src/map/amap/amapCore.c \
+ src/map/amap/amapGraph.c \
+ src/map/amap/amapLib.c \
+ src/map/amap/amapMan.c \
+ src/map/amap/amapMatch.c \
+ src/map/amap/amapMerge.c \
+ src/map/amap/amapOutput.c \
+ src/map/amap/amapParse.c \
+ src/map/amap/amapPerm.c \
+ src/map/amap/amapRead.c \
+ src/map/amap/amapRule.c \
+ src/map/amap/amapUniq.c
diff --git a/src/map/if/if.h b/src/map/if/if.h
index 24046f06..ce2cb483 100644
--- a/src/map/if/if.h
+++ b/src/map/if/if.h
@@ -88,6 +88,7 @@ struct If_Par_t_
int fExpRed; // expand/reduce of the best cuts
int fLatchPaths; // reset timing on latch paths
int fEdge; // uses edge-based cut selection heuristics
+ int fPower; // uses power-aware cut selection heuristics
int fCutMin; // performs cut minimization by removing functionally reducdant variables
int fSeqMap; // sequential mapping
int fBidec; // use bi-decomposition
@@ -141,12 +142,14 @@ struct If_Man_t_
float RequiredGlo2; // global required times
float AreaGlo; // global area
int nNets; // the sum total of fanins of all LUTs in the mapping
+ float dPower; // the sum total of switching activities of all LUTs in the mapping
int nCutsUsed; // the number of cuts currently used
int nCutsMerged; // the total number of cuts merged
unsigned * puTemp[4]; // used for the truth table computation
int SortMode; // one of the three sorting modes
int fNextRound; // set to 1 after the first round
int nChoices; // the number of choice nodes
+ Vec_Int_t * vSwitching; // switching activity of each node
// sequential mapping
Vec_Ptr_t * vLatchOrder; // topological ordering of latches
Vec_Int_t * vLags; // sequentail lags of all nodes
@@ -177,6 +180,7 @@ struct If_Cut_t_
float Area; // area (or area-flow) of the cut
float AveRefs; // the average number of leaf references
float Edge; // the edge flow
+ float Power; // the power flow
float Delay; // delay of the cut
unsigned uSign; // cut signature
unsigned Cost : 14; // the user's cost of the cut
@@ -351,6 +355,7 @@ extern void If_CutLift( If_Cut_t * pCut );
extern void If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc );
extern float If_CutAreaFlow( If_Man_t * p, If_Cut_t * pCut );
extern float If_CutEdgeFlow( If_Man_t * p, If_Cut_t * pCut );
+extern float If_CutPowerFlow( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot );
extern float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut );
extern float If_CutAreaDeref( If_Man_t * p, If_Cut_t * pCut );
extern float If_CutAreaRef( If_Man_t * p, If_Cut_t * pCut );
@@ -360,6 +365,10 @@ extern float If_CutEdgeDeref( If_Man_t * p, If_Cut_t * pCut );
extern float If_CutEdgeRef( If_Man_t * p, If_Cut_t * pCut );
extern float If_CutEdgeDerefed( If_Man_t * p, If_Cut_t * pCut );
extern float If_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut );
+extern float If_CutPowerDeref( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot );
+extern float If_CutPowerRef( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot );
+extern float If_CutPowerDerefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot );
+extern float If_CutPowerRefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot );
/*=== ifLib.c =============================================================*/
extern If_Lib_t * If_LutLibRead( char * FileName );
extern If_Lib_t * If_LutLibDup( If_Lib_t * p );
diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c
index afaae239..af1f5213 100644
--- a/src/map/if/ifCut.c
+++ b/src/map/if/ifCut.c
@@ -432,40 +432,144 @@ void If_ManSortCuts( If_Man_t * p, int Mode )
***********************************************************************/
static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 )
{
- if ( p->SortMode == 1 ) // area
+ if ( p->pPars->fPower )
{
- if ( pC0->Area < pC1->Area - p->fEpsilon )
+ if ( p->SortMode == 1 ) // area flow
+ {
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ //printf("area(%.2f, %.2f), power(%.2f, %.2f), edge(%.2f, %.2f)\n",
+ // pC0->Area, pC1->Area, pC0->Power, pC1->Power, pC0->Edge, pC1->Edge);
+ if ( pC0->Power < pC1->Power - p->fEpsilon )
+ return -1;
+ if ( pC0->Power > pC1->Power + p->fEpsilon )
+ return 1;
+ if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+ return -1;
+ if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+ return 1;
+ if ( pC0->AveRefs > pC1->AveRefs )
+ return -1;
+ if ( pC0->AveRefs < pC1->AveRefs )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ return 0;
+ }
+ if ( p->SortMode == 0 ) // delay
+ {
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ if ( pC0->Power < pC1->Power - p->fEpsilon )
+ return -1;
+ if ( pC0->Power > pC1->Power + p->fEpsilon )
+ return 1;
+ if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+ return -1;
+ if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+ return 1;
+ return 0;
+ }
+ assert( p->SortMode == 2 ); // delay old, exact area
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
return -1;
- if ( pC0->Area > pC1->Area + p->fEpsilon )
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ if ( pC0->Power < pC1->Power - p->fEpsilon )
+ return -1;
+ if ( pC0->Power > pC1->Power + p->fEpsilon )
return 1;
if ( pC0->Edge < pC1->Edge - p->fEpsilon )
return -1;
if ( pC0->Edge > pC1->Edge + p->fEpsilon )
return 1;
- if ( pC0->AveRefs > pC1->AveRefs )
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
return -1;
- if ( pC0->AveRefs < pC1->AveRefs )
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
return 1;
if ( pC0->nLeaves < pC1->nLeaves )
return -1;
if ( pC0->nLeaves > pC1->nLeaves )
return 1;
- if ( pC0->Delay < pC1->Delay - p->fEpsilon )
- return -1;
- if ( pC0->Delay > pC1->Delay + p->fEpsilon )
- return 1;
return 0;
- }
- if ( p->SortMode == 0 ) // delay
+ }
+ else // reglar
{
+ if ( p->SortMode == 1 ) // area
+ {
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+ return -1;
+ if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+ return 1;
+ if ( pC0->Power < pC1->Power - p->fEpsilon )
+ return -1;
+ if ( pC0->Power > pC1->Power + p->fEpsilon )
+ return 1;
+ if ( pC0->AveRefs > pC1->AveRefs )
+ return -1;
+ if ( pC0->AveRefs < pC1->AveRefs )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ return 0;
+ }
+ if ( p->SortMode == 0 ) // delay
+ {
+ if ( pC0->Delay < pC1->Delay - p->fEpsilon )
+ return -1;
+ if ( pC0->Delay > pC1->Delay + p->fEpsilon )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
+ if ( pC0->Area < pC1->Area - p->fEpsilon )
+ return -1;
+ if ( pC0->Area > pC1->Area + p->fEpsilon )
+ return 1;
+ if ( pC0->Edge < pC1->Edge - p->fEpsilon )
+ return -1;
+ if ( pC0->Edge > pC1->Edge + p->fEpsilon )
+ return 1;
+ if ( pC0->Power < pC1->Power - p->fEpsilon )
+ return -1;
+ if ( pC0->Power > pC1->Power + p->fEpsilon )
+ return 1;
+ return 0;
+ }
+ assert( p->SortMode == 2 ); // delay old
if ( pC0->Delay < pC1->Delay - p->fEpsilon )
return -1;
if ( pC0->Delay > pC1->Delay + p->fEpsilon )
return 1;
- if ( pC0->nLeaves < pC1->nLeaves )
- return -1;
- if ( pC0->nLeaves > pC1->nLeaves )
- return 1;
if ( pC0->Area < pC1->Area - p->fEpsilon )
return -1;
if ( pC0->Area > pC1->Area + p->fEpsilon )
@@ -474,26 +578,16 @@ static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC
return -1;
if ( pC0->Edge > pC1->Edge + p->fEpsilon )
return 1;
+ if ( pC0->Power < pC1->Power - p->fEpsilon )
+ return -1;
+ if ( pC0->Power > pC1->Power + p->fEpsilon )
+ return 1;
+ if ( pC0->nLeaves < pC1->nLeaves )
+ return -1;
+ if ( pC0->nLeaves > pC1->nLeaves )
+ return 1;
return 0;
}
- assert( p->SortMode == 2 ); // delay old
- if ( pC0->Delay < pC1->Delay - p->fEpsilon )
- return -1;
- if ( pC0->Delay > pC1->Delay + p->fEpsilon )
- return 1;
- if ( pC0->Area < pC1->Area - p->fEpsilon )
- return -1;
- if ( pC0->Area > pC1->Area + p->fEpsilon )
- return 1;
- if ( pC0->Edge < pC1->Edge - p->fEpsilon )
- return -1;
- if ( pC0->Edge > pC1->Edge + p->fEpsilon )
- return 1;
- if ( pC0->nLeaves < pC1->nLeaves )
- return -1;
- if ( pC0->nLeaves > pC1->nLeaves )
- return 1;
- return 0;
}
/**Function*************************************************************
@@ -820,6 +914,40 @@ float If_CutEdgeFlow( If_Man_t * p, If_Cut_t * pCut )
/**Function*************************************************************
+ Synopsis [Computes area flow.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutPowerFlow( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot )
+{
+ If_Obj_t * pLeaf;
+ float * pSwitching = (float *)p->vSwitching->pArray;
+ float Power = 0;
+ int i;
+ assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ Power += pSwitching[pLeaf->Id];
+ if ( pLeaf->nRefs == 0 )
+ Power += If_ObjCutBest(pLeaf)->Power;
+ else if ( p->pPars->fSeqMap ) // seq
+ Power += If_ObjCutBest(pLeaf)->Power / pLeaf->nRefs;
+ else
+ {
+ assert( pLeaf->EstRefs > p->fEpsilon );
+ Power += If_ObjCutBest(pLeaf)->Power / pLeaf->EstRefs;
+ }
+ }
+ return Power;
+}
+
+/**Function*************************************************************
+
Synopsis [Average number of references of the leaves.]
Description []
@@ -1038,6 +1166,107 @@ float If_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut )
return aResult;
}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutPowerDeref( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot )
+{
+ If_Obj_t * pLeaf;
+ float * pSwitching = (float *)p->vSwitching->pArray;
+ float Power = 0;
+ int i;
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ Power += pSwitching[pLeaf->Id];
+ assert( pLeaf->nRefs > 0 );
+ if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) )
+ continue;
+ Power += If_CutPowerDeref( p, If_ObjCutBest(pLeaf), pRoot );
+ }
+ return Power;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutPowerRef( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot )
+{
+ If_Obj_t * pLeaf;
+ float * pSwitching = (float *)p->vSwitching->pArray;
+ float Power = 0;
+ int i;
+ If_CutForEachLeaf( p, pCut, pLeaf, i )
+ {
+ Power += pSwitching[pLeaf->Id];
+ assert( pLeaf->nRefs >= 0 );
+ if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) )
+ continue;
+ Power += If_CutPowerRef( p, If_ObjCutBest(pLeaf), pRoot );
+ }
+ return Power;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes Power of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutPowerDerefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot )
+{
+ float aResult, aResult2;
+ assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+ aResult2 = If_CutPowerRef( p, pCut, pRoot );
+ aResult = If_CutPowerDeref( p, pCut, pRoot );
+ assert( aResult > aResult2 - p->fEpsilon );
+ assert( aResult < aResult2 + p->fEpsilon );
+ return aResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes area of the first level.]
+
+ Description [The cut need to be derefed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float If_CutPowerRefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot )
+{
+ float aResult, aResult2;
+ assert( p->pPars->fSeqMap || pCut->nLeaves > 1 );
+ aResult2 = If_CutPowerDeref( p, pCut, pRoot );
+ aResult = If_CutPowerRef( p, pCut, pRoot );
+ assert( aResult > aResult2 - p->fEpsilon );
+ assert( aResult < aResult2 + p->fEpsilon );
+ return aResult;
+}
+
/**Function*************************************************************
Synopsis [Computes the cone of the cut in AIG with choices.]
diff --git a/src/map/if/ifMan.c b/src/map/if/ifMan.c
index 35b0cccc..82ee6728 100644
--- a/src/map/if/ifMan.c
+++ b/src/map/if/ifMan.c
@@ -145,6 +145,8 @@ void If_ManStop( If_Man_t * p )
FREE( p->pPars->pTimesReq );
if ( p->pManTim )
Tim_ManStop( p->pManTim );
+ if ( p->vSwitching )
+ Vec_IntFree( p->vSwitching );
free( p );
}
diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c
index 75370dff..fc3d7cd3 100644
--- a/src/map/if/ifMap.c
+++ b/src/map/if/ifMap.c
@@ -95,6 +95,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut );
if ( p->pPars->fEdge )
pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut );
+ if ( p->pPars->fPower )
+ pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj );
// save the best cut from the previous iteration
if ( !fPreprocess )
If_CutCopy( p, pCutSet->ppCuts[pCutSet->nCuts++], pCut );
@@ -141,6 +143,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut );
if ( p->pPars->fEdge )
pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut );
+ if ( p->pPars->fPower )
+ pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj );
pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut );
// insert the cut into storage
If_CutSort( p, pCutSet, pCut );
@@ -227,6 +231,8 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP
pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut );
if ( p->pPars->fEdge )
pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut );
+ if ( p->pPars->fPower )
+ pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj );
pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut );
// insert the cut into storage
If_CutSort( p, pCutSet, pCut );
@@ -334,8 +340,8 @@ int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPrepr
if ( p->pPars->fVerbose )
{
char Symb = fPreprocess? 'P' : ((Mode == 0)? 'D' : ((Mode == 1)? 'F' : 'A'));
- printf( "%c: Del = %7.2f. Ar = %9.1f. Edge = %8d. Cut = %8d. ",
- Symb, p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged );
+ printf( "%c: Del = %7.2f. Ar = %9.1f. Edge = %8d. Switch = %7.2f. Cut = %8d. ",
+ Symb, p->RequiredGlo, p->AreaGlo, p->nNets, p->dPower, p->nCutsMerged );
PRT( "T", clock() - clk );
// printf( "Max number of cuts = %d. Average number of cuts = %5.2f.\n",
// p->nCutsMax, 1.0 * p->nCutsMerged / If_ManAndNum(p) );
diff --git a/src/map/if/ifReduce.c b/src/map/if/ifReduce.c
index fd1af0d7..a5fa7d86 100644
--- a/src/map/if/ifReduce.c
+++ b/src/map/if/ifReduce.c
@@ -55,8 +55,8 @@ void If_ManImproveMapping( If_Man_t * p )
If_ManComputeRequired( p );
if ( p->pPars->fVerbose )
{
- printf( "E: Del = %7.2f. Ar = %9.1f. Edge = %8d. Cut = %8d. ",
- p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged );
+ printf( "E: Del = %7.2f. Ar = %9.1f. Edge = %8d. Switch = %7.2f. Cut = %8d. ",
+ p->RequiredGlo, p->AreaGlo, p->nNets, p->dPower, p->nCutsMerged );
PRT( "T", clock() - clk );
}
diff --git a/src/map/if/ifUtil.c b/src/map/if/ifUtil.c
index 57e1ad13..06015b06 100644
--- a/src/map/if/ifUtil.c
+++ b/src/map/if/ifUtil.c
@@ -585,6 +585,7 @@ float If_ManMarkMapping_rec( If_Man_t * p, If_Obj_t * pObj )
{
If_Obj_t * pLeaf;
If_Cut_t * pCutBest;
+ float * pSwitching = p->vSwitching? (float*)p->vSwitching->pArray : NULL;
float aArea;
int i;
if ( pObj->nRefs++ || If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) )
@@ -596,7 +597,10 @@ float If_ManMarkMapping_rec( If_Man_t * p, If_Obj_t * pObj )
p->nNets += pCutBest->nLeaves;
aArea = If_CutLutArea( p, pCutBest );
If_CutForEachLeaf( p, pCutBest, pLeaf, i )
+ {
+ p->dPower += pSwitching? pSwitching[pLeaf->Id] : 0.0;
aArea += If_ManMarkMapping_rec( p, pLeaf );
+ }
return aArea;
}
@@ -622,6 +626,7 @@ void If_ManMarkMapping( If_Man_t * p )
pObj->nRefs = 0;
}
p->nNets = 0;
+ p->dPower = 0.0;
p->AreaGlo = 0.0;
If_ManForEachCo( p, pObj, i )
p->AreaGlo += If_ManMarkMapping_rec( p, If_ObjFanin0(pObj) );
diff --git a/src/map/mapper/mapperTime.c b/src/map/mapper/mapperTime.c
index cc4173cf..309863fd 100644
--- a/src/map/mapper/mapperTime.c
+++ b/src/map/mapper/mapperTime.c
@@ -206,7 +206,7 @@ void Map_TimeComputeRequiredGlobal( Map_Man_t * p )
}
else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon )
{
- if ( p->fMappingMode == 1 )
+ if ( p->fMappingMode == 1 && p->fVerbose )
printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget );
p->fRequiredGlo = p->DelayTarget;
}
diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c
index 37ba82c2..1326dbbf 100644
--- a/src/map/mio/mio.c
+++ b/src/map/mio/mio.c
@@ -28,6 +28,10 @@
#include "mioInt.h"
#include "mapper.h"
+extern void Amap_LibFree( void * p );
+extern void Amap_LibPrintSelectedGates( void * p, int fAllGates );
+extern void * Amap_LibReadAndPrepare( char * pFileName, int fVerbose, int fVeryVerbose );
+
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
@@ -35,6 +39,9 @@
static int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv );
static int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv );
+static int Mio_CommandReadLibrary2( Abc_Frame_t * pAbc, int argc, char **argv );
+static int Mio_CommandPrintLibrary2( Abc_Frame_t * pAbc, int argc, char **argv );
+
// internal version of GENLIB library
static char * pMcncGenlib[25] = {
"GATE inv1 1 O=!a; PIN * INV 1 999 0.9 0.0 0.9 0.0\n",
@@ -78,7 +85,7 @@ static char * pMcncGenlib[25] = {
void Mio_Init( Abc_Frame_t * pAbc )
{
char * pFileTemp = "mcnc_temp.genlib";
- Mio_Library_t * pLibGen;
+ void * pLibGen;
FILE * pFile;
int i;
@@ -90,6 +97,9 @@ void Mio_Init( Abc_Frame_t * pAbc )
// read genlib from file
pLibGen = Mio_LibraryRead( pAbc, pFileTemp, NULL, 0 );
Abc_FrameSetLibGen( pLibGen );
+ pLibGen = Amap_LibReadAndPrepare( pFileTemp, 0, 0 );
+ Abc_FrameSetLibGen2( pLibGen );
+
#ifdef WIN32
_unlink( pFileTemp );
#else
@@ -98,6 +108,9 @@ void Mio_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "SC mapping", "read_library", Mio_CommandReadLibrary, 0 );
Cmd_CommandAdd( pAbc, "SC mapping", "print_library", Mio_CommandPrintLibrary, 0 );
+
+ Cmd_CommandAdd( pAbc, "SC mapping", "read_library2", Mio_CommandReadLibrary2, 0 );
+ Cmd_CommandAdd( pAbc, "SC mapping", "print_library2", Mio_CommandPrintLibrary2, 0 );
}
/**Function*************************************************************
@@ -115,6 +128,7 @@ void Mio_End()
{
// Mio_LibraryDelete( s_pLib );
Mio_LibraryDelete( Abc_FrameReadLibGen() );
+ Amap_LibFree( Abc_FrameReadLibGen2() );
}
@@ -190,25 +204,124 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv )
if ( Abc_FrameReadLibSuper() )
{
extern void Map_SuperLibFree( Map_SuperLib_t * p );
-// Map_SuperLibFree( s_pSuperLib );
-// s_pSuperLib = NULL;
Map_SuperLibFree( Abc_FrameReadLibSuper() );
Abc_FrameSetLibSuper( NULL );
}
// replace the current library
-// Mio_LibraryDelete( s_pLib );
-// s_pLib = pLib;
Mio_LibraryDelete( Abc_FrameReadLibGen() );
Abc_FrameSetLibGen( pLib );
+
+ // set the new network
+ pLib = Amap_LibReadAndPrepare( FileName, 1, 0 );
+ if ( pLib == NULL )
+ {
+ fprintf( pErr, "Reading GENLIB library has failed.\n" );
+ return 1;
+ }
+ // replace the current library
+ Amap_LibFree( Abc_FrameReadLibGen2() );
+ Abc_FrameSetLibGen2( pLib );
return 0;
usage:
fprintf( pErr, "usage: read_library [-vh]\n");
fprintf( pErr, "\t read the library from a genlib file\n" );
fprintf( pErr, "\t (if the library contains more than one gate\n" );
- fprintf( pErr, "\t with the same Boolean function, only the first gate\n" );
- fprintf( pErr, "\t in the order of their appearance in the file is used)\n" );
+ fprintf( pErr, "\t with the same Boolean function, only the gate\n" );
+ fprintf( pErr, "\t with the smallest area will be used)\n" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-h : enable verbose output\n");
+ return 1; /* error exit */
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mio_CommandReadLibrary2( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ FILE * pFile;
+ FILE * pOut, * pErr;
+ Mio_Library_t * pLib;
+ Abc_Ntk_t * pNet;
+ char * FileName;
+ int fVerbose;
+ int fVeryVerbose;
+ int c;
+
+ pNet = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ fVerbose = 1;
+ fVeryVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "vwh")) != EOF )
+ {
+ switch (c)
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'w':
+ fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+
+ if ( argc != globalUtilOptind + 1 )
+ {
+ goto usage;
+ }
+
+ // get the input file name
+ FileName = argv[globalUtilOptind];
+ if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL )
+ {
+ fprintf( pErr, "Cannot open input file \"%s\". ", FileName );
+ if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) )
+ fprintf( pErr, "Did you mean \"%s\"?", FileName );
+ fprintf( pErr, "\n" );
+ return 1;
+ }
+ fclose( pFile );
+
+ // set the new network
+ pLib = Amap_LibReadAndPrepare( FileName, fVerbose, fVeryVerbose );
+ if ( pLib == NULL )
+ {
+ fprintf( pErr, "Reading GENLIB library has failed.\n" );
+ return 1;
+ }
+
+ // replace the current library
+ Amap_LibFree( Abc_FrameReadLibGen2() );
+ Abc_FrameSetLibGen2( pLib );
+ return 0;
+
+usage:
+ fprintf( pErr, "usage: read_library2 [-vh]\n");
+ fprintf( pErr, "\t read the library from a genlib file\n" );
+ fprintf( pErr, "\t (if the library contains more than one gate\n" );
+ fprintf( pErr, "\t with the same Boolean function, only the gate\n" );
+ fprintf( pErr, "\t with the smallest area will be used)\n" );
+ fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
+ fprintf( pErr, "\t-w : toggle detailed printout [default = %s]\n", fVeryVerbose? "yes": "no" );
fprintf( pErr, "\t-h : enable verbose output\n");
return 1; /* error exit */
}
@@ -271,6 +384,72 @@ usage:
fprintf( pErr, "\t-h : print the command usage\n");
return 1; /* error exit */
}
+
+
+/**Function*************************************************************
+
+ Synopsis [Command procedure to read LUT libraries.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mio_CommandPrintLibrary2( Abc_Frame_t * pAbc, int argc, char **argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNet;
+ int fPrintAll;
+ int fVerbose;
+ int c;
+
+ pNet = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ // set the defaults
+ fPrintAll = 0;
+ fVerbose = 1;
+ Extra_UtilGetoptReset();
+ while ( (c = Extra_UtilGetopt(argc, argv, "avh")) != EOF )
+ {
+ switch (c)
+ {
+ case 'a':
+ fPrintAll ^= 1;
+ break;
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ break;
+ default:
+ goto usage;
+ }
+ }
+
+
+ if ( argc != globalUtilOptind )
+ {
+ goto usage;
+ }
+
+ // set the new network
+ Amap_LibPrintSelectedGates( Abc_FrameReadLibGen2(), fPrintAll );
+ return 0;
+
+usage:
+ fprintf( pErr, "\nusage: print_library2 [-avh]\n");
+ fprintf( pErr, "\t print gates used for area-oriented tech-mapping\n" );
+ fprintf( pErr, "\t-a : toggles printing all gates [default = %s]\n", (fPrintAll? "yes" : "no") );
+ fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") );
+ fprintf( pErr, "\t-h : print the command usage\n");
+ return 1; /* error exit */
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/map/mio/mio.h b/src/map/mio/mio.h
index dbe2420b..0e5a39d3 100644
--- a/src/map/mio/mio.h
+++ b/src/map/mio/mio.h
@@ -79,6 +79,7 @@ typedef struct Mio_PinStruct_t_ Mio_Pin_t;
extern char * Mio_LibraryReadName ( Mio_Library_t * pLib );
extern int Mio_LibraryReadGateNum ( Mio_Library_t * pLib );
extern Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib );
+extern Mio_Gate_t ** Mio_LibraryReadGatesByName( Mio_Library_t * pLib );
extern DdManager * Mio_LibraryReadDd ( Mio_Library_t * pLib );
extern Mio_Gate_t * Mio_LibraryReadGateByName ( Mio_Library_t * pLib, char * pName );
extern char * Mio_LibraryReadSopByName ( Mio_Library_t * pLib, char * pName );
@@ -110,6 +111,8 @@ extern int Mio_GateReadInputs ( Mio_Gate_t * pGate );
extern double Mio_GateReadDelayMax ( Mio_Gate_t * pGate );
extern char * Mio_GateReadSop ( Mio_Gate_t * pGate );
extern DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate );
+extern int Mio_GateReadValue ( Mio_Gate_t * pGate );
+extern void Mio_GateSetValue ( Mio_Gate_t * pGate, int Value );
extern char * Mio_PinReadName ( Mio_Pin_t * pPin );
extern Mio_PinPhase_t Mio_PinReadPhase ( Mio_Pin_t * pPin );
extern double Mio_PinReadInputLoad ( Mio_Pin_t * pPin );
diff --git a/src/map/mio/mio81214.zip b/src/map/mio/mio81214.zip
new file mode 100644
index 00000000..12f766a9
--- /dev/null
+++ b/src/map/mio/mio81214.zip
Binary files differ
diff --git a/src/map/mio/mioApi.c b/src/map/mio/mioApi.c
index 73473f8b..61cc2509 100644
--- a/src/map/mio/mioApi.c
+++ b/src/map/mio/mioApi.c
@@ -40,6 +40,7 @@
char * Mio_LibraryReadName ( Mio_Library_t * pLib ) { return pLib->pName; }
int Mio_LibraryReadGateNum ( Mio_Library_t * pLib ) { return pLib->nGates; }
Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ) { return pLib->pGates; }
+Mio_Gate_t ** Mio_LibraryReadGatesByName ( Mio_Library_t * pLib ) { return pLib->ppGatesName;}
DdManager * Mio_LibraryReadDd ( Mio_Library_t * pLib ) { return pLib->dd; }
Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib ) { return pLib->pGateBuf; }
Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib ) { return pLib->pGateInv; }
@@ -131,17 +132,19 @@ char * Mio_LibraryReadSopByName( Mio_Library_t * pLib, char * pName )
SeeAlso []
***********************************************************************/
-char * Mio_GateReadName ( Mio_Gate_t * pGate ) { return pGate->pName; }
-char * Mio_GateReadOutName ( Mio_Gate_t * pGate ) { return pGate->pOutName; }
-double Mio_GateReadArea ( Mio_Gate_t * pGate ) { return pGate->dArea; }
-char * Mio_GateReadForm ( Mio_Gate_t * pGate ) { return pGate->pForm; }
-Mio_Pin_t * Mio_GateReadPins ( Mio_Gate_t * pGate ) { return pGate->pPins; }
-Mio_Library_t * Mio_GateReadLib ( Mio_Gate_t * pGate ) { return pGate->pLib; }
-Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate ) { return pGate->pNext; }
-int Mio_GateReadInputs ( Mio_Gate_t * pGate ) { return pGate->nInputs; }
-double Mio_GateReadDelayMax( Mio_Gate_t * pGate ) { return pGate->dDelayMax; }
-char * Mio_GateReadSop ( Mio_Gate_t * pGate ) { return pGate->pSop; }
-DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate ) { return pGate->bFunc; }
+char * Mio_GateReadName ( Mio_Gate_t * pGate ) { return pGate->pName; }
+char * Mio_GateReadOutName ( Mio_Gate_t * pGate ) { return pGate->pOutName; }
+double Mio_GateReadArea ( Mio_Gate_t * pGate ) { return pGate->dArea; }
+char * Mio_GateReadForm ( Mio_Gate_t * pGate ) { return pGate->pForm; }
+Mio_Pin_t * Mio_GateReadPins ( Mio_Gate_t * pGate ) { return pGate->pPins; }
+Mio_Library_t * Mio_GateReadLib ( Mio_Gate_t * pGate ) { return pGate->pLib; }
+Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate ) { return pGate->pNext; }
+int Mio_GateReadInputs ( Mio_Gate_t * pGate ) { return pGate->nInputs; }
+double Mio_GateReadDelayMax( Mio_Gate_t * pGate ) { return pGate->dDelayMax; }
+char * Mio_GateReadSop ( Mio_Gate_t * pGate ) { return pGate->pSop; }
+DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate ) { return pGate->bFunc; }
+int Mio_GateReadValue ( Mio_Gate_t * pGate ) { return pGate->Value; }
+void Mio_GateSetValue ( Mio_Gate_t * pGate, int Value ) { pGate->Value = Value; }
/**Function*************************************************************
diff --git a/src/map/mio/mioGENERIC.c b/src/map/mio/mioGENERIC.c
deleted file mode 100644
index 972c4ffc..00000000
--- a/src/map/mio/mioGENERIC.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/**CFile****************************************************************
-
- FileName [mio___.c]
-
- PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
-
- Synopsis [File reading/writing for technology mapping.]
-
- Author [MVSIS Group]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - September 8, 2003.]
-
- Revision [$Id: mio___.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#include "mioInt.h"
-
-////////////////////////////////////////////////////////////////////////
-/// DECLARATIONS ///
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFINITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
-
diff --git a/src/map/mio/mioInt.h b/src/map/mio/mioInt.h
index 3f90b625..654b7e19 100644
--- a/src/map/mio/mioInt.h
+++ b/src/map/mio/mioInt.h
@@ -54,6 +54,8 @@ struct Mio_LibraryStruct_t_
{
char * pName; // the name of the library
int nGates; // the number of the gates
+ Mio_Gate_t ** ppGates0; // the array of gates in the original order
+ Mio_Gate_t ** ppGatesName; // the array of gates sorted by name
Mio_Gate_t * pGates; // the linked list of all gates in no particular order
Mio_Gate_t * pGate0; // the constant zero gate
Mio_Gate_t * pGate1; // the constant one gate
@@ -84,7 +86,8 @@ struct Mio_GateStruct_t_
int nInputs; // the number of inputs
double dDelayMax; // the maximum delay
DdNode * bFunc; // the functionality
- char * pSop;
+ char * pSop; // sum-of-products
+ int Value; // user's information
};
struct Mio_PinStruct_t_
diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c
index 5b92d3e1..ae33c942 100644
--- a/src/map/mio/mioRead.c
+++ b/src/map/mio/mioRead.c
@@ -418,11 +418,92 @@ char * chomp( char *s )
SeeAlso []
***********************************************************************/
+int Mio_LibraryCompareGatesByArea( Mio_Gate_t ** pp1, Mio_Gate_t ** pp2 )
+{
+ double Diff = (*pp1)->dArea - (*pp2)->dArea;
+ if ( Diff < 0.0 )
+ return -1;
+ if ( Diff > 0.0 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Mio_LibraryCompareGatesByName( Mio_Gate_t ** pp1, Mio_Gate_t ** pp2 )
+{
+ int Diff = strcmp( (*pp1)->pName, (*pp2)->pName );
+ if ( Diff < 0.0 )
+ return -1;
+ if ( Diff > 0.0 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Mio_LibrarySortGates( Mio_Library_t * pLib )
+{
+ Mio_Gate_t ** ppGates, * pGate;
+ int i = 0;
+ ppGates = ALLOC( Mio_Gate_t *, pLib->nGates );
+ Mio_LibraryForEachGate( pLib, pGate )
+ ppGates[i++] = pGate;
+ assert( i == pLib->nGates );
+ // sort gates by area
+ pLib->ppGates0 = ALLOC( Mio_Gate_t *, pLib->nGates );
+ for ( i = 0; i < pLib->nGates; i++ )
+ pLib->ppGates0[i] = ppGates[i];
+ qsort( (void *)ppGates, pLib->nGates, sizeof(void *),
+ (int (*)(const void *, const void *)) Mio_LibraryCompareGatesByArea );
+ for ( i = 0; i < pLib->nGates; i++ )
+ ppGates[i]->pNext = (i < pLib->nGates-1)? ppGates[i+1] : NULL;
+ pLib->pGates = ppGates[0];
+ free( ppGates );
+ // sort gates by name
+ pLib->ppGatesName = ALLOC( Mio_Gate_t *, pLib->nGates );
+ for ( i = 0; i < pLib->nGates; i++ )
+ pLib->ppGatesName[i] = pLib->ppGates0[i];
+ qsort( (void *)pLib->ppGatesName, pLib->nGates, sizeof(void *),
+ (int (*)(const void *, const void *)) Mio_LibraryCompareGatesByName );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib )
{
Mio_Gate_t * pGate;
DdNode * bFuncBuf, * bFuncInv, * bFuncNand2, * bFuncAnd2;
+ Mio_LibrarySortGates( pLib );
+
bFuncBuf = pLib->dd->vars[0]; Cudd_Ref( bFuncBuf );
bFuncInv = Cudd_Not( pLib->dd->vars[0] ); Cudd_Ref( bFuncInv );
bFuncNand2 = Cudd_bddNand( pLib->dd, pLib->dd->vars[0], pLib->dd->vars[1] ); Cudd_Ref( bFuncNand2 );
diff --git a/src/map/mio/mioUtils.c b/src/map/mio/mioUtils.c
index bd3d01f7..2a1d1f30 100644
--- a/src/map/mio/mioUtils.c
+++ b/src/map/mio/mioUtils.c
@@ -59,6 +59,8 @@ void Mio_LibraryDelete( Mio_Library_t * pLib )
st_free_table( pLib->tName2Gate );
if ( pLib->dd )
Cudd_Quit( pLib->dd );
+ FREE( pLib->ppGates0 );
+ FREE( pLib->ppGatesName );
free( pLib );
}
@@ -82,7 +84,7 @@ void Mio_GateDelete( Mio_Gate_t * pGate )
if ( pGate->bFunc )
Cudd_RecursiveDeref( pGate->pLib->dd, pGate->bFunc );
Mio_GateForEachPinSafe( pGate, pPin, pPin2 )
- Mio_PinDelete( pPin );
+ Mio_PinDelete( pPin );
free( pGate );
}
@@ -142,11 +144,14 @@ Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin )
***********************************************************************/
void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops )
{
- Mio_Gate_t * pGate;
+// Mio_Gate_t * pGate;
+ int i;
fprintf( pFile, "# The genlib library \"%s\".\n", pLib->pName );
- Mio_LibraryForEachGate( pLib, pGate )
- Mio_WriteGate( pFile, pGate, fPrintSops );
+// Mio_LibraryForEachGate( pLib, pGate )
+// Mio_WriteGate( pFile, pGate, fPrintSops );
+ for ( i = 0; i < pLib->nGates; i++ )
+ Mio_WriteGate( pFile, pLib->ppGates0[i], fPrintSops );
}
/**Function*************************************************************
diff --git a/src/map/super/superGate.c b/src/map/super/superGate.c
index 915ff86d..c8aa02ba 100644
--- a/src/map/super/superGate.c
+++ b/src/map/super/superGate.c
@@ -345,7 +345,12 @@ Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGat
continue;
}
}
-
+/*
+ if ( strcmp(Mio_GateReadName(ppGates[k]), "MUX2IX0") == 0 )
+ {
+ int s = 0;
+ }
+*/
// select the subset of gates to be considered with this root gate
// all the gates past this point will lead to delay larger than the limit
tDelayMio = (float)Mio_GateReadDelayMax(ppGates[k]);
diff --git a/src/misc/avl/avl.c b/src/misc/avl/avl.c
new file mode 100644
index 00000000..2c2dec88
--- /dev/null
+++ b/src/misc/avl/avl.c
@@ -0,0 +1,616 @@
+/*
+ * Revision Control Information
+ *
+ * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/avl/RCS/avl.c,v $
+ * $Author: sis $
+ * $Revision: 1.3 $
+ * $Date: 1994/07/15 23:00:40 $
+ *
+ */
+/* LINTLIBRARY */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "avl.h"
+
+
+
+#define HEIGHT(node) (node == NIL(avl_node) ? -1 : (node)->height)
+#define BALANCE(node) (HEIGHT((node)->right) - HEIGHT((node)->left))
+
+#define compute_height(node) { \
+ int x=HEIGHT(node->left), y=HEIGHT(node->right); \
+ (node)->height = MAX(x,y) + 1; \
+}
+
+#define COMPARE(key, nodekey, compare) \
+ ((compare == avl_numcmp) ? \
+ (int) key - (int) nodekey : \
+ (*compare)(key, nodekey))
+
+
+#define STACK_SIZE 50
+
+static avl_node *new_node ();
+static avl_node *find_rightmost ();
+static void do_rebalance ();
+static rotate_left ();
+static rotate_right ();
+static int do_check_tree ();
+
+avl_tree *
+avl_init_table (compar)
+ int (*compar) ();
+{
+ avl_tree *tree;
+
+ tree = ALLOC (avl_tree, 1);
+ tree->root = NIL (avl_node);
+ tree->compar = compar;
+ tree->num_entries = 0;
+ return tree;
+}
+
+
+
+avl_lookup (tree, key, value_p)
+ avl_tree *tree;
+ register char *key;
+ char **value_p;
+{
+ register avl_node *node;
+ register int (*compare) () = tree->compar, diff;
+
+ node = tree->root;
+ while (node != NIL (avl_node))
+ {
+ diff = COMPARE (key, node->key, compare);
+ if (diff == 0)
+ {
+ /* got a match */
+ if (value_p != NIL (char *))
+ *value_p = node->value;
+ return 1;
+ }
+ node = (diff < 0) ? node->left : node->right;
+ }
+ return 0;
+}
+
+avl_first (tree, key_p, value_p)
+ avl_tree *tree;
+ char **key_p;
+ char **value_p;
+{
+ register avl_node *node;
+
+ if (tree->root == 0)
+ {
+ return 0; /* no entries */
+ }
+ else
+ {
+ /* walk down the tree; stop at leftmost leaf */
+ for (node = tree->root; node->left != 0; node = node->left)
+ {
+ }
+ if (key_p != NIL (char *))
+ *key_p = node->key;
+ if (value_p != NIL (char *))
+ *value_p = node->value;
+ return 1;
+ }
+}
+
+
+avl_last (tree, key_p, value_p)
+ avl_tree *tree;
+ char **key_p;
+ char **value_p;
+{
+ register avl_node *node;
+
+ if (tree->root == 0)
+ {
+ return 0; /* no entries */
+ }
+ else
+ {
+ /* walk down the tree; stop at rightmost leaf */
+ for (node = tree->root; node->right != 0; node = node->right)
+ {
+ }
+ if (key_p != NIL (char *))
+ *key_p = node->key;
+ if (value_p != NIL (char *))
+ *value_p = node->value;
+ return 1;
+ }
+}
+
+avl_insert (tree, key, value)
+ avl_tree *tree;
+ char *key;
+ char *value;
+{
+ register avl_node **node_p, *node;
+ register int stack_n = 0;
+ register int (*compare) () = tree->compar;
+ avl_node **stack_nodep[STACK_SIZE];
+ int diff, status;
+
+ node_p = &tree->root;
+
+ /* walk down the tree (saving the path); stop at insertion point */
+ status = 0;
+ while ((node = *node_p) != NIL (avl_node))
+ {
+ stack_nodep[stack_n++] = node_p;
+ diff = COMPARE (key, node->key, compare);
+ if (diff == 0)
+ status = 1;
+ node_p = (diff < 0) ? &node->left : &node->right;
+ }
+
+ /* insert the item and re-balance the tree */
+ *node_p = new_node (key, value);
+ do_rebalance (stack_nodep, stack_n);
+ tree->num_entries++;
+ tree->modified = 1;
+ return status;
+}
+
+
+
+avl_find_or_add (tree, key, slot_p)
+ avl_tree *tree;
+ char *key;
+ char ***slot_p;
+{
+ register avl_node **node_p, *node;
+ register int stack_n = 0;
+ register int (*compare) () = tree->compar;
+ avl_node **stack_nodep[STACK_SIZE];
+ int diff;
+
+ node_p = &tree->root;
+
+ /* walk down the tree (saving the path); stop at insertion point */
+ while ((node = *node_p) != NIL (avl_node))
+ {
+ stack_nodep[stack_n++] = node_p;
+ diff = COMPARE (key, node->key, compare);
+ if (diff == 0)
+ {
+ if (slot_p != 0)
+ *slot_p = &node->value;
+ return 1; /* found */
+ }
+ node_p = (diff < 0) ? &node->left : &node->right;
+ }
+
+ /* insert the item and re-balance the tree */
+ *node_p = new_node (key, NIL (char));
+ if (slot_p != 0)
+ *slot_p = &(*node_p)->value;
+ do_rebalance (stack_nodep, stack_n);
+ tree->num_entries++;
+ tree->modified = 1;
+ return 0; /* not already in tree */
+}
+
+avl_delete (tree, key_p, value_p)
+ avl_tree *tree;
+ char **key_p;
+ char **value_p;
+{
+ register avl_node **node_p, *node, *rightmost;
+ register int stack_n = 0;
+ char *key = *key_p;
+ int (*compare) () = tree->compar, diff;
+ avl_node **stack_nodep[STACK_SIZE];
+
+ node_p = &tree->root;
+
+ /* Walk down the tree saving the path; return if not found */
+ while ((node = *node_p) != NIL (avl_node))
+ {
+ diff = COMPARE (key, node->key, compare);
+ if (diff == 0)
+ goto delete_item;
+ stack_nodep[stack_n++] = node_p;
+ node_p = (diff < 0) ? &node->left : &node->right;
+ }
+ return 0; /* not found */
+
+ /* prepare to delete node and replace it with rightmost of left tree */
+ delete_item:
+ *key_p = node->key;
+ if (value_p != 0)
+ *value_p = node->value;
+ if (node->left == NIL (avl_node))
+ {
+ *node_p = node->right;
+ }
+ else
+ {
+ rightmost = find_rightmost (&node->left);
+ rightmost->left = node->left;
+ rightmost->right = node->right;
+ rightmost->height = -2; /* mark bogus height for do_rebal */
+ *node_p = rightmost;
+ stack_nodep[stack_n++] = node_p;
+ }
+ FREE (node);
+
+ /* work our way back up, re-balancing the tree */
+ do_rebalance (stack_nodep, stack_n);
+ tree->num_entries--;
+ tree->modified = 1;
+ return 1;
+}
+
+static void
+avl_record_gen_forward (node, gen)
+ avl_node *node;
+ avl_generator *gen;
+{
+ if (node != NIL (avl_node))
+ {
+ avl_record_gen_forward (node->left, gen);
+ gen->nodelist[gen->count++] = node;
+ avl_record_gen_forward (node->right, gen);
+ }
+}
+
+
+static void
+avl_record_gen_backward (node, gen)
+ avl_node *node;
+ avl_generator *gen;
+{
+ if (node != NIL (avl_node))
+ {
+ avl_record_gen_backward (node->right, gen);
+ gen->nodelist[gen->count++] = node;
+ avl_record_gen_backward (node->left, gen);
+ }
+}
+
+
+avl_generator *
+avl_init_gen (tree, dir)
+ avl_tree *tree;
+ int dir;
+{
+ avl_generator *gen;
+
+ /* what a hack */
+ gen = ALLOC (avl_generator, 1);
+ gen->tree = tree;
+ gen->nodelist = ALLOC (avl_node *, avl_count (tree));
+ gen->count = 0;
+ if (dir == AVL_FORWARD)
+ {
+ avl_record_gen_forward (tree->root, gen);
+ }
+ else
+ {
+ avl_record_gen_backward (tree->root, gen);
+ }
+ gen->count = 0;
+
+ /* catch any attempt to modify the tree while we generate */
+ tree->modified = 0;
+ return gen;
+}
+
+
+avl_gen (gen, key_p, value_p)
+ avl_generator *gen;
+ char **key_p;
+ char **value_p;
+{
+ avl_node *node;
+
+ if (gen->count == gen->tree->num_entries)
+ {
+ return 0;
+ }
+ else
+ {
+ node = gen->nodelist[gen->count++];
+ if (key_p != NIL (char *))
+ *key_p = node->key;
+ if (value_p != NIL (char *))
+ *value_p = node->value;
+ return 1;
+ }
+}
+
+
+void
+avl_free_gen (gen)
+ avl_generator *gen;
+{
+ FREE (gen->nodelist);
+ FREE (gen);
+}
+
+static avl_node *
+find_rightmost (node_p)
+ register avl_node **node_p;
+{
+ register avl_node *node;
+ register int stack_n = 0;
+ avl_node **stack_nodep[STACK_SIZE];
+
+ node = *node_p;
+ while (node->right != NIL (avl_node))
+ {
+ stack_nodep[stack_n++] = node_p;
+ node_p = &node->right;
+ node = *node_p;
+ }
+ *node_p = node->left;
+
+ do_rebalance (stack_nodep, stack_n);
+ return node;
+}
+
+
+static void
+do_rebalance (stack_nodep, stack_n)
+ register avl_node ***stack_nodep;
+ register int stack_n;
+{
+ register avl_node **node_p, *node;
+ register int hl, hr;
+ int height;
+
+ /* work our way back up, re-balancing the tree */
+ while (--stack_n >= 0)
+ {
+ node_p = stack_nodep[stack_n];
+ node = *node_p;
+ hl = HEIGHT (node->left); /* watch for NIL */
+ hr = HEIGHT (node->right); /* watch for NIL */
+ if ((hr - hl) < -1)
+ {
+ rotate_right (node_p);
+ }
+ else if ((hr - hl) > 1)
+ {
+ rotate_left (node_p);
+ }
+ else
+ {
+ height = MAX (hl, hr) + 1;
+ if (height == node->height)
+ break;
+ node->height = height;
+ }
+ }
+}
+
+static
+rotate_left (node_p)
+ register avl_node **node_p;
+{
+ register avl_node *old_root = *node_p, *new_root, *new_right;
+
+ if (BALANCE (old_root->right) >= 0)
+ {
+ *node_p = new_root = old_root->right;
+ old_root->right = new_root->left;
+ new_root->left = old_root;
+ }
+ else
+ {
+ new_right = old_root->right;
+ *node_p = new_root = new_right->left;
+ old_root->right = new_root->left;
+ new_right->left = new_root->right;
+ new_root->right = new_right;
+ new_root->left = old_root;
+ compute_height (new_right);
+ }
+ compute_height (old_root);
+ compute_height (new_root);
+}
+
+
+static
+rotate_right (node_p)
+ avl_node **node_p;
+{
+ register avl_node *old_root = *node_p, *new_root, *new_left;
+
+ if (BALANCE (old_root->left) <= 0)
+ {
+ *node_p = new_root = old_root->left;
+ old_root->left = new_root->right;
+ new_root->right = old_root;
+ }
+ else
+ {
+ new_left = old_root->left;
+ *node_p = new_root = new_left->right;
+ old_root->left = new_root->right;
+ new_left->right = new_root->left;
+ new_root->left = new_left;
+ new_root->right = old_root;
+ compute_height (new_left);
+ }
+ compute_height (old_root);
+ compute_height (new_root);
+}
+
+static void
+avl_walk_forward (node, func)
+ avl_node *node;
+ void (*func) ();
+{
+ if (node != NIL (avl_node))
+ {
+ avl_walk_forward (node->left, func);
+ (*func) (node->key, node->value);
+ avl_walk_forward (node->right, func);
+ }
+}
+
+
+static void
+avl_walk_backward (node, func)
+ avl_node *node;
+ void (*func) ();
+{
+ if (node != NIL (avl_node))
+ {
+ avl_walk_backward (node->right, func);
+ (*func) (node->key, node->value);
+ avl_walk_backward (node->left, func);
+ }
+}
+
+
+void
+avl_foreach (tree, func, direction)
+ avl_tree *tree;
+ void (*func) ();
+ int direction;
+{
+ if (direction == AVL_FORWARD)
+ {
+ avl_walk_forward (tree->root, func);
+ }
+ else
+ {
+ avl_walk_backward (tree->root, func);
+ }
+}
+
+
+static void
+free_entry (node, key_free, value_free)
+ avl_node *node;
+ void (*key_free) ();
+ void (*value_free) ();
+{
+ if (node != NIL (avl_node))
+ {
+ free_entry (node->left, key_free, value_free);
+ free_entry (node->right, key_free, value_free);
+ if (key_free != 0)
+ (*key_free) (node->key);
+ if (value_free != 0)
+ (*value_free) (node->value);
+ FREE (node);
+ }
+}
+
+
+void
+avl_free_table (tree, key_free, value_free)
+ avl_tree *tree;
+ void (*key_free) ();
+ void (*value_free) ();
+{
+ free_entry (tree->root, key_free, value_free);
+ FREE (tree);
+}
+
+
+int
+avl_count (tree)
+ avl_tree *tree;
+{
+ return tree->num_entries;
+}
+
+static avl_node *
+new_node (key, value)
+ char *key;
+ char *value;
+{
+ register avl_node *new;
+
+ new = ALLOC (avl_node, 1);
+ new->key = key;
+ new->value = value;
+ new->height = 0;
+ new->left = new->right = NIL (avl_node);
+ return new;
+}
+
+
+int
+avl_numcmp (x, y)
+ char *x, *y;
+{
+ return (int) x - (int) y;
+}
+
+int
+avl_check_tree (tree)
+ avl_tree *tree;
+{
+ int error = 0;
+ (void) do_check_tree (tree->root, tree->compar, &error);
+ return error;
+}
+
+
+static int
+do_check_tree (node, compar, error)
+ avl_node *node;
+ int (*compar) ();
+ int *error;
+{
+ int l_height, r_height, comp_height, bal;
+
+ if (node == NIL (avl_node))
+ {
+ return -1;
+ }
+
+ r_height = do_check_tree (node->right, compar, error);
+ l_height = do_check_tree (node->left, compar, error);
+
+ comp_height = MAX (l_height, r_height) + 1;
+ bal = r_height - l_height;
+
+ if (comp_height != node->height)
+ {
+ (void) printf ("Bad height for 0x%08x: computed=%d stored=%d\n",
+ node, comp_height, node->height);
+ ++*error;
+ }
+
+ if (bal > 1 || bal < -1)
+ {
+ (void) printf ("Out of balance at node 0x%08x, balance = %d\n",
+ node, bal);
+ ++*error;
+ }
+
+ if (node->left != NIL (avl_node) &&
+ (*compar) (node->left->key, node->key) > 0)
+ {
+ (void) printf ("Bad ordering between 0x%08x and 0x%08x",
+ node, node->left);
+ ++*error;
+ }
+
+ if (node->right != NIL (avl_node) &&
+ (*compar) (node->key, node->right->key) > 0)
+ {
+ (void) printf ("Bad ordering between 0x%08x and 0x%08x",
+ node, node->right);
+ ++*error;
+ }
+
+ return comp_height;
+}
diff --git a/src/misc/avl/avl.doc b/src/misc/avl/avl.doc
new file mode 100644
index 00000000..a9753b3a
--- /dev/null
+++ b/src/misc/avl/avl.doc
@@ -0,0 +1,166 @@
+/*
+ * Revision Control Information
+ *
+ * /projects/hsis/CVS/utilities/avl/avl.doc,v
+ * rajeev
+ * 1.3
+ * 1995/08/08 22:36:22
+ *
+ */
+avl_tree *
+avl_init_table(compare)
+int (*compare)();
+ Initialize and return a new avl_tree. Use the function `compare' to
+ compare items in the tree. `compare' should be of the form:
+
+ int
+ compare(a,b)
+ char *a, *b;
+
+ and return a number < 0, == 0, > 0 depending on whether a < b,
+ a == b, or a > b, respectively.
+
+
+void
+avl_free_table(tree, key_delete_func, value_delete_func)
+avl_tree *tree;
+void (*key_delete_func)();
+void (*value_delete_func)();
+
+ Delete all storage associated with `tree'. The functions
+ key_delete_func and value_delete_func, if non-null, are called
+ to free each (key, value) pair. They are declared as:
+
+ void
+ key_delete_func(key)
+ char *key;
+ {}
+
+ void
+ value_delete_func(value)
+ char *value;
+ {}
+
+ The C-library function free is often suitable as a free function.
+
+
+avl_first(tree, key_p, value_p)
+avl_tree *tree;
+char **key_p;
+char **value_p;
+ Retrieves the smallest element in the tree. Returns 0 if there
+ are no elements in the tree.
+
+
+avl_last(tree, key_p, value_p)
+avl_tree *tree;
+char **key_p;
+char **value_p;
+ Retrieves the largest element in the tree. Returns 0 if there
+ are no elements in the tree.
+
+
+avl_lookup(tree, key, value_p)
+avl_tree *tree;
+char *key;
+char **value_p;
+ Search for an entry matching `key'. If found, set `value_p' to
+ the associated value field and return 1. If not found, return
+ 0 and leave `value_p' unchanged.
+
+
+avl_insert(tree, key, value);
+avl_tree *tree;
+char *key;
+char *value;
+ Insert the value `value' under the key `key'. Multiple items
+ are allowed with the same value; all are inserted.
+
+
+avl_delete(tree, key_p, value_p)
+avl_tree *tree;
+char **key_p;
+char **value_p;
+ Search for the item with key `*key_p' in `tree'. If found, set
+ `key_p' and `value_p' to point to the key and value of item,
+ delete the item and return 1. Otherwise return 0 and leave
+ `key_p' and `value_p' unchanged. WARNING: This interface is
+ buggy; in particular, if identical keys are in the table, it is
+ not possible to delete a particular (key, value) pair. This
+ will be fixed either with 'handles' or a separate delete
+ function.
+
+
+avl_find_or_add(tree, key, slot_p)
+avl_tree *tree;
+char *key;
+char ***slot_p;
+ Search for an entry matching key; if not found, insert key and
+ return the address of the value slot for this entry. If found,
+ do not insert key, and return the address of the value slot for
+ the existing entry. slot_p can be used to associate a value with
+ the key.
+
+
+void
+avl_foreach(tree, func, direction)
+avl_tree *tree;
+int (*func)();
+int direction;
+
+ Apply `func' to each item in the tree `tree' in turn. If
+ direction is AVL_FORWARD, the tree is traversed from smallest
+ to largest. Otherwise it is traversed from largest to smallest.
+
+ func should be of the form:
+
+ void
+ func(key, value)
+ char *key;
+ char *value;
+
+ where `key' is the key the item was stored under, and `value'
+ the value of the item.
+
+
+avl_count(tree)
+avl_tree *tree;
+ Returns the number of entries in the avl tree.
+
+
+avl_generator *
+avl_init_gen(tree, direction)
+avl_tree *tree;
+int direction;
+ Start up a generator on an avl-tree. direction is either
+ AVL_FORWARD or AVL_BACKWARD indicating the direction of
+ generation.
+
+
+avl_gen(gen, key_p, value_p)
+avl_generator *gen;
+char **key_p;
+char **value_p;
+ Generate the next item from the avl-tree. Returns 0 if there
+ are no more items in the tree. Deletion of last generated item
+ (via avl_delete) is supported. Insertion of items during
+ generation will result in these items never being generated
+ (until the next avl_init_gen()). Excercise for the interested
+ student: how does one write an avl generator ?
+
+
+void
+avl_free_gen(gen)
+avl_generator *gen;
+ Free a generator.
+
+
+avl_foreach_item(tree, gen, direction, key_p, value_p)
+avl_tree *tree;
+avl_generator *gen;
+int direction;
+char **key_p;
+char **value_p;
+ Generate over all items in an avl-tree. This macro iterator
+ combines avl_init_gen(), avl_gen(), and avl_free_gen() into
+ a single statement iterator.
diff --git a/src/misc/avl/avl.h b/src/misc/avl/avl.h
new file mode 100644
index 00000000..21d811da
--- /dev/null
+++ b/src/misc/avl/avl.h
@@ -0,0 +1,80 @@
+/*
+ * Revision Control Information
+ *
+ * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/avl/RCS/avl.h,v $
+ * $Author: sis $
+ * $Revision: 1.3 $
+ * $Date: 1994/07/15 23:00:40 $
+ *
+ */
+#ifndef AVL_INCLUDED
+#define AVL_INCLUDED
+
+#define EXTERN
+#define ARGS(protos) protos
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+#define NIL(type) \
+ ((type *) 0)
+#define ALLOC(type, num) \
+ ((type *) malloc(sizeof(type) * (num)))
+#define REALLOC(type, obj, num) \
+ ((type *) realloc((char *) obj, sizeof(type) * (num)))
+#define FREE(obj) \
+ free((char *) (obj))
+
+
+
+typedef struct avl_node_struct avl_node;
+struct avl_node_struct {
+ avl_node *left, *right;
+ char *key;
+ char *value;
+ int height;
+};
+
+
+typedef struct avl_tree_struct avl_tree;
+struct avl_tree_struct {
+ avl_node *root;
+ int (*compar)();
+ int num_entries;
+ int modified;
+};
+
+
+typedef struct avl_generator_struct avl_generator;
+struct avl_generator_struct {
+ avl_tree *tree;
+ avl_node **nodelist;
+ int count;
+};
+
+
+#define AVL_FORWARD 0
+#define AVL_BACKWARD 1
+
+
+EXTERN avl_tree *avl_init_table ARGS((int (*)()));
+EXTERN int avl_delete ARGS((avl_tree *, char **, char **));
+EXTERN int avl_insert ARGS((avl_tree *, char *, char *));
+EXTERN int avl_lookup ARGS((avl_tree *, char *, char **));
+EXTERN int avl_first ARGS((avl_tree *, char **, char **));
+EXTERN int avl_last ARGS((avl_tree *, char **, char **));
+EXTERN int avl_find_or_add ARGS((avl_tree *, char *, char ***));
+EXTERN int avl_count ARGS((avl_tree *));
+EXTERN int avl_numcmp ARGS((char *, char *));
+EXTERN int avl_gen ARGS((avl_generator *, char **, char **));
+EXTERN void avl_foreach ARGS((avl_tree *, void (*)(), int));
+EXTERN void avl_free_table ARGS((avl_tree *, void (*)(), void (*)()));
+EXTERN void avl_free_gen ARGS((avl_generator *));
+EXTERN avl_generator *avl_init_gen ARGS((avl_tree *, int));
+
+#define avl_is_member(tree, key) avl_lookup(tree, key, (char **) 0)
+
+#define avl_foreach_item(table, gen, dir, key_p, value_p) \
+ for(gen = avl_init_gen(table, dir); \
+ avl_gen(gen, key_p, value_p) || (avl_free_gen(gen),0);)
+
+#endif
diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h
index beb5a4d0..d7a3e98c 100644
--- a/src/misc/extra/extra.h
+++ b/src/misc/extra/extra.h
@@ -41,12 +41,6 @@ extern "C" {
/* Nested includes */
/*---------------------------------------------------------------------------*/
-// this include should be the first one in the list
-// it is used to catch memory leaks on Windows
-#if defined(_DEBUG) && defined(_MSC_VER) && (_MSC_VER <= 1200) // 1200 = MSVC 6.0
-#include "leaks.h"
-#endif
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -56,6 +50,12 @@ extern "C" {
#include "cuddInt.h"
#include "port_type.h"
+// catch memory leaks in Visual Studio
+#ifdef _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#endif
+
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
@@ -77,17 +77,16 @@ extern "C" {
/*---------------------------------------------------------------------------*/
#ifdef WIN32
-#define DLLEXPORT __declspec(dllexport)
-#define DLLIMPORT __declspec(dllimport)
+#define ABC_DLLEXPORT __declspec(dllexport)
+#define ABC_DLLIMPORT __declspec(dllimport)
#else /* defined(WIN32) */
-#define DLLIMPORT
+#define ABC_DLLIMPORT
#endif /* defined(WIN32) */
#ifndef ABC_DLL
-#define ABC_DLL DLLIMPORT
+#define ABC_DLL ABC_DLLIMPORT
#endif
-
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
diff --git a/src/misc/extra/extraUtilMemory.c b/src/misc/extra/extraUtilMemory.c
index 39c34296..e672afbb 100644
--- a/src/misc/extra/extraUtilMemory.c
+++ b/src/misc/extra/extraUtilMemory.c
@@ -339,7 +339,7 @@ int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p )
***********************************************************************/
Extra_MmFlex_t * Extra_MmFlexStart()
-{
+{
Extra_MmFlex_t * p;
//printf( "allocing flex\n" );
p = ALLOC( Extra_MmFlex_t, 1 );
@@ -349,7 +349,7 @@ Extra_MmFlex_t * Extra_MmFlexStart()
p->pCurrent = NULL;
p->pEnd = NULL;
- p->nChunkSize = (1 << 10);
+ p->nChunkSize = (1 << 12);
p->nChunksAlloc = 64;
p->nChunks = 0;
p->pChunks = ALLOC( char *, p->nChunksAlloc );
diff --git a/src/misc/extra/extraUtilUtil.c b/src/misc/extra/extraUtilUtil.c
index abe08d7a..7165a0cd 100644
--- a/src/misc/extra/extraUtilUtil.c
+++ b/src/misc/extra/extraUtilUtil.c
@@ -377,6 +377,22 @@ double Extra_CpuTimeDouble()
}
#endif
+/**Function*************************************************************
+
+ Synopsis [Testing memory leaks.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Extra_MemTest()
+{
+ malloc( 1002 );
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/misc/util/leaks.h b/src/misc/util/leaks.h
deleted file mode 100644
index 1a32062a..00000000
--- a/src/misc/util/leaks.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//////////////////////////////////////////////////////////////////////////
-// This file is used to detect memory leaks using Visual Studio 6.0
-// 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__
-
-#ifdef _DEBUG
-#define _CRTDBG_MAP_ALLOC // include Microsoft memory leak detection procedures
-//#define _INC_MALLOC // exclude standard memory alloc procedures
-
-#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
-#define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__)
-#define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
-//#define _expand(p, s) _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
-//#define free(p) _free_dbg(p, _NORMAL_BLOCK)
-//#define _msize(p) _msize_dbg(p, _NORMAL_BLOCK)
-
-//#include <stdlib.h>
-#include <stdlib_hack.h>
-#include <crtdbg.h>
-#endif
-
-#endif
-
-//////////////////////////////////////
-
-
diff --git a/src/misc/util/stdlib_hack.h b/src/misc/util/stdlib_hack.h
deleted file mode 100644
index 2ddf73d1..00000000
--- a/src/misc/util/stdlib_hack.h
+++ /dev/null
@@ -1,4 +0,0 @@
-
-#include <stdlib.h>
-
-
diff --git a/src/misc/vec/vec.h b/src/misc/vec/vec.h
index 4c19b5ee..67ec44aa 100644
--- a/src/misc/vec/vec.h
+++ b/src/misc/vec/vec.h
@@ -48,10 +48,10 @@ typedef long long sint64;
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
-// this include should be the first one in the list
-// it is used to catch memory leaks on Windows
-#if defined(_DEBUG) && defined(_MSC_VER) && (_MSC_VER <= 1200) // 1200 = MSVC 6.0
-#include "leaks.h"
+// catch memory leaks in Visual Studio
+#ifdef _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
#endif
////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/cut/cut.h b/src/opt/cut/cut.h
index dee05dfc..faa249f2 100644
--- a/src/opt/cut/cut.h
+++ b/src/opt/cut/cut.h
@@ -64,8 +64,10 @@ struct Cut_ParamsStruct_t_
int fGlobal; // compute only global cuts
int fLocal; // compute only local cuts
int fRecord; // record the cut computation flow
+ int fRecordAig; // record the cut functions
int fFancy; // perform fancy computations
int fMap; // computes delay of FPGA mapping with cuts
+ int fAdjust; // removed useless fanouts of XORs/MUXes
int fVerbose; // the verbosiness flag
};
diff --git a/src/opt/cut/cutNode.c b/src/opt/cut/cutNode.c
index 2d17020b..633219fd 100644
--- a/src/opt/cut/cutNode.c
+++ b/src/opt/cut/cutNode.c
@@ -393,6 +393,13 @@ p->timeMerge += clock() - clk;
Vec_IntPush( p->vCutPairs, ((pCut->Num1 << 16) | pCut->Num0) );
Vec_IntWriteEntry( p->vNodeCuts, Node, Vec_IntSize(p->vCutPairs) - Vec_IntEntry(p->vNodeStarts, Node) );
}
+ if ( p->pParams->fRecordAig )
+ {
+ extern void Aig_RManRecord( unsigned * pTruth, int nVarsInit );
+ Cut_ListForEachCut( pList, pCut )
+ if ( Cut_CutReadLeaveNum(pCut) > 4 )
+ Aig_RManRecord( Cut_CutReadTruth(pCut), Cut_CutReadLeaveNum(pCut) );
+ }
// check if the node is over the list
if ( p->nNodeCuts == p->pParams->nKeepMax )
p->nCutsLimit++;
diff --git a/src/opt/lpk/lpkAbcDsd.c b/src/opt/lpk/lpkAbcDsd.c
index 46d9179a..a1cd9def 100644
--- a/src/opt/lpk/lpkAbcDsd.c
+++ b/src/opt/lpk/lpkAbcDsd.c
@@ -287,7 +287,12 @@ void Lpk_FunCompareBoundSets( Lpk_Fun_t * p, Vec_Int_t * vBSets, int nCofDepth,
if ( (uBoundSet & uLateArrSupp) ) // skip those boundsets that are late arriving
continue;
if ( fVerbose )
-Lpk_PrintSetOne( uBoundSet );
+{
+Lpk_PrintSetOne( uBoundSet & 0xFFFF );
+//printf( "\n" );
+//Lpk_PrintSetOne( uBoundSet >> 16 );
+//printf( "\n" );
+}
assert( (uBoundSet & (uBoundSet >> 16)) == 0 );
nVarsBS = Kit_WordCountOnes( uBoundSet & 0xFFFF );
if ( nVarsBS == 1 )
diff --git a/src/opt/lpk/lpkCore.c b/src/opt/lpk/lpkCore.c
index 78356d81..d8dd15b7 100644
--- a/src/opt/lpk/lpkCore.c
+++ b/src/opt/lpk/lpkCore.c
@@ -387,6 +387,10 @@ p->timeCuts += clock() - clk;
p->nCutsUseful += p->nEvals;
for ( i = 0; i < p->nEvals; i++ )
{
+ if ( p->pObj->Id == 1478 )
+ {
+ int x = 0;
+ }
// get the cut
pCut = p->pCuts + p->pEvals[i];
if ( p->pPars->fFirst && i == 1 )
diff --git a/src/opt/mfs/mfs.h b/src/opt/mfs/mfs.h
index 9550a31b..bddb9328 100644
--- a/src/opt/mfs/mfs.h
+++ b/src/opt/mfs/mfs.h
@@ -54,6 +54,7 @@ struct Mfs_Par_t_
int fSwapEdge; // performs edge swapping
int fOneHotness; // adds one-hotness conditions
int fDelay; // performs optimization for delay
+ int fPower; // performs power-aware optimization
int fVerbose; // enable basic stats
int fVeryVerbose; // enable detailed stats
};
diff --git a/src/opt/mfs/mfsCore.c b/src/opt/mfs/mfsCore.c
index 3444bab1..e8820acd 100644
--- a/src/opt/mfs/mfsCore.c
+++ b/src/opt/mfs/mfsCore.c
@@ -9,7 +9,7 @@
Synopsis [Core procedures of this package.]
Author [Alan Mishchenko]
-
+
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
@@ -24,6 +24,8 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+extern int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate );
+
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -33,7 +35,7 @@
Synopsis []
Description []
-
+
SideEffects []
SeeAlso []
@@ -57,13 +59,176 @@ void Abc_NtkMfsParsDefault( Mfs_Par_t * pPars )
pPars->fVerbose = 0;
pPars->fVeryVerbose = 0;
}
+/*
+int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ float * pProbab = (float *)p->vProbs->pArray;
+ int i;
+ // try replacing area critical fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( pProbab[pFanin->Id] >= 0.4 )
+ {
+ if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+ return 1;
+ } else if ( pProbab[pFanin->Id] >= 0.3 )
+ {
+ if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) )
+ return 1;
+ }
+ }
+ return 0;
+}
+*/
+
+int Abc_WinNode(Mfs_Man_t * p, Abc_Obj_t *pNode)
+{
+// int clk;
+// Abc_Obj_t * pFanin;
+ float * pProbab = (float *)p->vProbs->pArray;
+// int i;
+
+ p->nNodesTried++;
+ // prepare data structure for this node
+ Mfs_ManClean( p );
+ // compute window roots, window support, and window nodes
+ p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax );
+ p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+ p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+ if ( p->pPars->nWinSizeMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinSizeMax )
+ return 1;
+ // compute the divisors of the window
+ p->vDivs = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 );
+ p->nTotalDivs += Vec_PtrSize(p->vDivs);
+ // construct AIG for the window
+ p->pAigWin = Abc_NtkConstructAig( p, pNode );
+ // translate it into CNF
+ p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) );
+ // create the SAT problem
+ p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 );
+ if ( p->pSat == NULL )
+ {
+ p->nNodesBad++;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+int Abc_NtkMfsPowerResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+ int clk;
+ Abc_Obj_t * pFanin;
+ float * pProbab = (float *)p->vProbs->pArray;
+ int i;
+
+ if (Abc_WinNode(p, pNode) // something wrong
+ return 1;
+
+ // solve the SAT problem
+ // Abc_NtkMfsEdgePower( p, pNode );
+ // try replacing area critical fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( pProbab[pFanin->Id] >= 0.37 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+ return 1;
+
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( pProbab[pFanin->Id] >= 0.1 && Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) )
+ return 1;
+
+ if ( Abc_ObjFaninNum(pNode) == p->nFaninMax )
+ return 0;
+
+ // try replacing area critical fanins while adding two new fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( pProbab[pFanin->Id] >= 0.37 && Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) )
+ return 1;
+ }
+ return 0;
+
+ return 1;
+}
+*/
+
+Abc_NtkMfsPowerResub( Mfs_Man_t * p, Mfs_Par_t * pPars)
+{
+ int i, k;
+ Abc_Obj_t *pFanin, *pNode;
+ Abc_Ntk_t *pNtk = p->pNtk;
+ int nFaninMax = Abc_NtkGetFaninMax(p->pNtk);
+ float * pProbab = (float *)p->vProbs->pArray;
+
+ Abc_NtkForEachNode( pNtk, pNode, k )
+ {
+ if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax )
+ continue;
+ if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax )
+ continue;
+ if (Abc_WinNode(p, pNode) ) // something wrong
+ continue;
+
+ // solve the SAT problem
+ // Abc_NtkMfsEdgePower( p, pNode );
+ // try replacing area critical fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( pProbab[pFanin->Id] >= 0.35 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+ continue;
+ }
+
+ Abc_NtkForEachNode( pNtk, pNode, k )
+ {
+ if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax )
+ continue;
+ if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax )
+ continue;
+ if (Abc_WinNode(p, pNode) ) // something wrong
+ continue;
+
+ // solve the SAT problem
+ // Abc_NtkMfsEdgePower( p, pNode );
+ // try replacing area critical fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( pProbab[pFanin->Id] >= 0.35 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+ continue;
+ }
+
+ Abc_NtkForEachNode( pNtk, pNode, k )
+ {
+ if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax )
+ continue;
+ if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax )
+ continue;
+ if (Abc_WinNode(p, pNode) ) // something wrong
+ continue;
+
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( pProbab[pFanin->Id] >= 0.2 && Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) )
+ continue;
+ }
+/*
+ Abc_NtkForEachNode( pNtk, pNode, k )
+ {
+ if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax )
+ continue;
+ if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax - 2)
+ continue;
+ if (Abc_WinNode(p, pNode) ) // something wrong
+ continue;
+
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( pProbab[pFanin->Id] >= 0.37 && Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) )
+ continue;
+ }
+*/
+}
/**Function*************************************************************
Synopsis []
Description []
-
+
SideEffects []
SeeAlso []
@@ -74,7 +239,7 @@ int Abc_NtkMfsResub( Mfs_Man_t * p, Abc_Obj_t * pNode )
int clk;
p->nNodesTried++;
// prepare data structure for this node
- Mfs_ManClean( p );
+ Mfs_ManClean( p );
// compute window roots, window support, and window nodes
clk = clock();
p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax );
@@ -105,7 +270,9 @@ clk = clock();
return 1;
}
// solve the SAT problem
- if ( p->pPars->fSwapEdge )
+ if ( p->pPars->fPower )
+ Abc_NtkMfsEdgePower( p, pNode );
+ else if ( p->pPars->fSwapEdge )
Abc_NtkMfsEdgeSwapEval( p, pNode );
else
{
@@ -122,7 +289,7 @@ p->timeSat += clock() - clk;
Synopsis []
Description []
-
+
SideEffects []
SeeAlso []
@@ -132,7 +299,8 @@ int Abc_NtkMfsNode( Mfs_Man_t * p, Abc_Obj_t * pNode )
{
Hop_Obj_t * pObj;
int RetValue;
- extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare );
+ float dProb;
+ extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb );
int nGain, clk;
p->nNodesTried++;
@@ -173,14 +341,15 @@ p->timeSat += clock() - clk;
}
// minimize the local function of the node using bi-decomposition
assert( p->nFanins == Abc_ObjFaninNum(pNode) );
- pObj = Abc_NodeIfNodeResyn( p->pManDec, pNode->pNtk->pManFunc, pNode->pData, p->nFanins, p->vTruth, p->uCare );
+ dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0;
+ pObj = Abc_NodeIfNodeResyn( p->pManDec, pNode->pNtk->pManFunc, pNode->pData, p->nFanins, p->vTruth, p->uCare, dProb );
nGain = Hop_DagSize(pNode->pData) - Hop_DagSize(pObj);
if ( nGain >= 0 )
{
p->nNodesDec++;
p->nNodesGained += nGain;
p->nNodesGainedLevel += nGain;
- pNode->pData = pObj;
+ pNode->pData = pObj;
}
return 1;
}
@@ -190,7 +359,7 @@ p->timeSat += clock() - clk;
Synopsis []
Description []
-
+
SideEffects []
SeeAlso []
@@ -198,7 +367,7 @@ p->timeSat += clock() - clk;
***********************************************************************/
int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars )
{
- extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters );
+ extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
Bdc_Par_t Pars = {0}, * pDecPars = &Pars;
ProgressBar * pProgress;
@@ -242,16 +411,32 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars )
p = Mfs_ManAlloc( pPars );
p->pNtk = pNtk;
p->nFaninMax = nFaninMax;
+
+ // precomputer power-aware metrics
+ if ( pPars->fPower )
+ {
+ extern Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne );
+ if ( pPars->fResub )
+ p->vProbs = Abc_NtkPowerEstimate( pNtk, 0 );
+ else
+ p->vProbs = Abc_NtkPowerEstimate( pNtk, 1 );
+#if 0
+ printf( "Total switching before = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) );
+#else
+ p->TotalSwitchingBeg = Abc_NtkMfsTotalSwitching(pNtk);
+#endif
+ }
+
if ( pNtk->pExcare )
{
Abc_Ntk_t * pTemp;
if ( Abc_NtkPiNum(pNtk->pExcare) != Abc_NtkCiNum(pNtk) )
- printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n",
+ printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n",
Abc_NtkPiNum(pNtk->pExcare), Abc_NtkCiNum(pNtk) );
else
{
pTemp = Abc_NtkStrash( pNtk->pExcare, 0, 0, 0 );
- p->pCare = Abc_NtkToDar( pTemp, 0 );
+ p->pCare = Abc_NtkToDar( pTemp, 0, 0 );
Abc_NtkDelete( pTemp );
p->vSuppsInv = Aig_ManSupportsInverse( p->pCare );
}
@@ -273,7 +458,7 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars )
Abc_NtkForEachCi( pNtk, pObj, i )
pObj->pData = (void *)(PORT_PTRUINT_T)i;
}
-
+
// compute levels
Abc_NtkLevel( pNtk );
Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel );
@@ -284,6 +469,14 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars )
p->nTotalEdgesBeg = nTotalEdgesBeg;
if ( pPars->fResub )
{
+#if 0
+ printf( "TotalSwitching (%7.2f --> ", Abc_NtkMfsTotalSwitching(pNtk) );
+#endif
+ if (pPars->fPower)
+ {
+ Abc_NtkMfsPowerResub( p, pPars);
+ } else
+ {
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
Abc_NtkForEachNode( pNtk, pObj, i )
{
@@ -299,9 +492,15 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars )
Abc_NtkMfsNode( p, pObj );
}
Extra_ProgressBarStop( pProgress );
+#if 0
+ printf( " %7.2f )\n", Abc_NtkMfsTotalSwitching(pNtk) );
+#endif
}
- else
+ } else
{
+#if 0
+ printf( "Total switching before = %7.2f, ----> ", Abc_NtkMfsTotalSwitching(pNtk) );
+#endif
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) );
vLevels = Abc_NtkLevelize( pNtk );
Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 )
@@ -320,22 +519,27 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars )
continue;
if ( pPars->fResub )
Abc_NtkMfsResub( p, pObj );
- else
+ else
Abc_NtkMfsNode( p, pObj );
}
nNodes += Vec_PtrSize(vNodes);
if ( pPars->fVerbose )
{
- printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ",
+ /*
+ printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ",
k, Vec_PtrSize(vNodes),
1.0*p->nNodesGainedLevel/Vec_PtrSize(vNodes),
1.0*p->nTotConfLevel/Vec_PtrSize(vNodes),
100.0*p->nTimeOutsLevel/Vec_PtrSize(vNodes) );
PRT( "Time", clock() - clk2 );
+ */
}
}
Extra_ProgressBarStop( pProgress );
Vec_VecFree( vLevels );
+#if 0
+ printf( " %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) );
+#endif
}
Abc_NtkStopReverseLevels( pNtk );
@@ -357,6 +561,16 @@ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars )
pObj->pData = NULL;
}
+ if ( pPars->fPower )
+ {
+#if 1
+ p->TotalSwitchingEnd = Abc_NtkMfsTotalSwitching(pNtk);
+// printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) );
+#else
+ printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) );
+#endif
+ }
+
// free the manager
p->timeTotal = clock() - clk;
Mfs_ManStop( p );
diff --git a/src/opt/mfs/mfsCore_.c b/src/opt/mfs/mfsCore_.c
new file mode 100644
index 00000000..66b497f6
--- /dev/null
+++ b/src/opt/mfs/mfsCore_.c
@@ -0,0 +1,388 @@
+/**CFile****************************************************************
+
+ FileName [mfsCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [The good old minimization with complete don't-cares.]
+
+ Synopsis [Core procedures of this package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: mfsCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMfsParsDefault( Mfs_Par_t * pPars )
+{
+ memset( pPars, 0, sizeof(Mfs_Par_t) );
+ pPars->nWinTfoLevs = 2;
+ pPars->nFanoutsMax = 10;
+ pPars->nDepthMax = 20;
+ pPars->nDivMax = 250;
+ pPars->nWinSizeMax = 300;
+ pPars->nGrowthLevel = 0;
+ pPars->nBTLimit = 5000;
+ pPars->fResub = 1;
+ pPars->fArea = 0;
+ pPars->fMoreEffort = 0;
+ pPars->fSwapEdge = 0;
+ pPars->fOneHotness = 0;
+ pPars->fVerbose = 0;
+ pPars->fVeryVerbose = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMfsResub( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+ int clk;
+ p->nNodesTried++;
+ // prepare data structure for this node
+ Mfs_ManClean( p );
+ // compute window roots, window support, and window nodes
+clk = clock();
+ p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax );
+ p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+ p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+p->timeWin += clock() - clk;
+ if ( p->pPars->nWinSizeMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinSizeMax )
+ return 1;
+ // compute the divisors of the window
+clk = clock();
+ p->vDivs = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 );
+ p->nTotalDivs += Vec_PtrSize(p->vDivs);
+p->timeDiv += clock() - clk;
+ // construct AIG for the window
+clk = clock();
+ p->pAigWin = Abc_NtkConstructAig( p, pNode );
+p->timeAig += clock() - clk;
+ // translate it into CNF
+clk = clock();
+ p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) );
+p->timeCnf += clock() - clk;
+ // create the SAT problem
+clk = clock();
+ p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 );
+ if ( p->pSat == NULL )
+ {
+ p->nNodesBad++;
+ return 1;
+ }
+ // solve the SAT problem
+ if ( p->pPars->fPower )
+ Abc_NtkMfsEdgePower( p, pNode );
+ else if ( p->pPars->fSwapEdge )
+ Abc_NtkMfsEdgeSwapEval( p, pNode );
+ else
+ {
+ Abc_NtkMfsResubNode( p, pNode );
+ if ( p->pPars->fMoreEffort )
+ Abc_NtkMfsResubNode2( p, pNode );
+ }
+p->timeSat += clock() - clk;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMfsNode( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+ Hop_Obj_t * pObj;
+ int RetValue;
+ float dProb;
+ extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb );
+
+ int nGain, clk;
+ p->nNodesTried++;
+ // prepare data structure for this node
+ Mfs_ManClean( p );
+ // compute window roots, window support, and window nodes
+clk = clock();
+ p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax );
+ p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+ p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) );
+p->timeWin += clock() - clk;
+ // count the number of patterns
+// p->dTotalRatios += Abc_NtkConstraintRatio( p, pNode );
+ // construct AIG for the window
+clk = clock();
+ p->pAigWin = Abc_NtkConstructAig( p, pNode );
+p->timeAig += clock() - clk;
+ // translate it into CNF
+clk = clock();
+ p->pCnf = Cnf_DeriveSimple( p->pAigWin, Abc_ObjFaninNum(pNode) );
+p->timeCnf += clock() - clk;
+ // create the SAT problem
+clk = clock();
+ p->pSat = Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 );
+ if ( p->pSat && p->pPars->fOneHotness )
+ Abc_NtkAddOneHotness( p );
+ if ( p->pSat == NULL )
+ return 0;
+ // solve the SAT problem
+ RetValue = Abc_NtkMfsSolveSat( p, pNode );
+ p->nTotConfLevel += p->pSat->stats.conflicts;
+p->timeSat += clock() - clk;
+ if ( RetValue == 0 )
+ {
+ p->nTimeOutsLevel++;
+ p->nTimeOuts++;
+ return 0;
+ }
+ // minimize the local function of the node using bi-decomposition
+ assert( p->nFanins == Abc_ObjFaninNum(pNode) );
+ dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0;
+ pObj = Abc_NodeIfNodeResyn( p->pManDec, pNode->pNtk->pManFunc, pNode->pData, p->nFanins, p->vTruth, p->uCare, dProb );
+ nGain = Hop_DagSize(pNode->pData) - Hop_DagSize(pObj);
+ if ( nGain >= 0 )
+ {
+ p->nNodesDec++;
+ p->nNodesGained += nGain;
+ p->nNodesGainedLevel += nGain;
+ pNode->pData = pObj;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars )
+{
+ extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+
+ Bdc_Par_t Pars = {0}, * pDecPars = &Pars;
+ ProgressBar * pProgress;
+ Mfs_Man_t * p;
+ Abc_Obj_t * pObj;
+ Vec_Vec_t * vLevels;
+ Vec_Ptr_t * vNodes;
+ int i, k, nNodes, nFaninMax, clk = clock(), clk2;
+ int nTotalNodesBeg = Abc_NtkNodeNum(pNtk);
+ int nTotalEdgesBeg = Abc_NtkGetTotalFanins(pNtk);
+
+ assert( Abc_NtkIsLogic(pNtk) );
+ nFaninMax = Abc_NtkGetFaninMax(pNtk);
+ if ( pPars->fResub )
+ {
+ if ( nFaninMax > 8 )
+ {
+ printf( "Nodes with more than %d fanins will node be processed.\n", 8 );
+ nFaninMax = 8;
+ }
+ }
+ else
+ {
+ if ( nFaninMax > MFS_FANIN_MAX )
+ {
+ printf( "Nodes with more than %d fanins will node be processed.\n", MFS_FANIN_MAX );
+ nFaninMax = MFS_FANIN_MAX;
+ }
+ }
+ // perform the network sweep
+ Abc_NtkSweep( pNtk, 0 );
+ // convert into the AIG
+ if ( !Abc_NtkToAig(pNtk) )
+ {
+ fprintf( stdout, "Converting to AIGs has failed.\n" );
+ return 0;
+ }
+ assert( Abc_NtkHasAig(pNtk) );
+
+ // start the manager
+ p = Mfs_ManAlloc( pPars );
+ p->pNtk = pNtk;
+ p->nFaninMax = nFaninMax;
+
+ // precomputer power-aware metrics
+ if ( pPars->fPower )
+ {
+ extern Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne );
+ if ( pPars->fResub )
+ p->vProbs = Abc_NtkPowerEstimate( pNtk, 0 );
+ else
+ p->vProbs = Abc_NtkPowerEstimate( pNtk, 1 );
+ printf( "Total switching before = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) );
+ }
+
+ if ( pNtk->pExcare )
+ {
+ Abc_Ntk_t * pTemp;
+ if ( Abc_NtkPiNum(pNtk->pExcare) != Abc_NtkCiNum(pNtk) )
+ printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n",
+ Abc_NtkPiNum(pNtk->pExcare), Abc_NtkCiNum(pNtk) );
+ else
+ {
+ pTemp = Abc_NtkStrash( pNtk->pExcare, 0, 0, 0 );
+ p->pCare = Abc_NtkToDar( pTemp, 0, 0 );
+ Abc_NtkDelete( pTemp );
+ p->vSuppsInv = Aig_ManSupportsInverse( p->pCare );
+ }
+ }
+ if ( p->pCare != NULL )
+ printf( "Performing optimization with %d external care clauses.\n", Aig_ManPoNum(p->pCare) );
+ // prepare the BDC manager
+ if ( !pPars->fResub )
+ {
+ pDecPars->nVarsMax = (nFaninMax < 3) ? 3 : nFaninMax;
+ pDecPars->fVerbose = pPars->fVerbose;
+ p->vTruth = Vec_IntAlloc( 0 );
+ p->pManDec = Bdc_ManAlloc( pDecPars );
+ }
+
+ // label the register outputs
+ if ( p->pCare )
+ {
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pData = (void *)(PORT_PTRUINT_T)i;
+ }
+
+ // compute levels
+ Abc_NtkLevel( pNtk );
+ Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel );
+
+ // compute don't-cares for each node
+ nNodes = 0;
+ p->nTotalNodesBeg = nTotalNodesBeg;
+ p->nTotalEdgesBeg = nTotalEdgesBeg;
+ if ( pPars->fResub )
+ {
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax )
+ continue;
+ if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax )
+ continue;
+ if ( !p->pPars->fVeryVerbose )
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ if ( pPars->fResub )
+ Abc_NtkMfsResub( p, pObj );
+ else
+ Abc_NtkMfsNode( p, pObj );
+ }
+ Extra_ProgressBarStop( pProgress );
+ }
+ else
+ {
+ pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) );
+ vLevels = Abc_NtkLevelize( pNtk );
+ Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 )
+ {
+ if ( !p->pPars->fVeryVerbose )
+ Extra_ProgressBarUpdate( pProgress, nNodes, NULL );
+ p->nNodesGainedLevel = 0;
+ p->nTotConfLevel = 0;
+ p->nTimeOutsLevel = 0;
+ clk2 = clock();
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax )
+ break;
+ if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax )
+ continue;
+ if ( pPars->fResub )
+ Abc_NtkMfsResub( p, pObj );
+ else
+ Abc_NtkMfsNode( p, pObj );
+ }
+ nNodes += Vec_PtrSize(vNodes);
+ if ( pPars->fVerbose )
+ {
+ printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ",
+ k, Vec_PtrSize(vNodes),
+ 1.0*p->nNodesGainedLevel/Vec_PtrSize(vNodes),
+ 1.0*p->nTotConfLevel/Vec_PtrSize(vNodes),
+ 100.0*p->nTimeOutsLevel/Vec_PtrSize(vNodes) );
+ PRT( "Time", clock() - clk2 );
+ }
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_VecFree( vLevels );
+ }
+ Abc_NtkStopReverseLevels( pNtk );
+
+ // perform the sweeping
+ if ( !pPars->fResub )
+ {
+ extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose );
+// Abc_NtkSweep( pNtk, 0 );
+// Abc_NtkBidecResyn( pNtk, 0 );
+ }
+
+ p->nTotalNodesEnd = Abc_NtkNodeNum(pNtk);
+ p->nTotalEdgesEnd = Abc_NtkGetTotalFanins(pNtk);
+
+ // undo labesl
+ if ( p->pCare )
+ {
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ pObj->pData = NULL;
+ }
+ if ( pPars->fPower )
+ printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) );
+
+ // free the manager
+ p->timeTotal = clock() - clk;
+ Mfs_ManStop( p );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/mfs/mfsInt.h b/src/opt/mfs/mfsInt.h
index df8a4848..9eb6e4a4 100644
--- a/src/opt/mfs/mfsInt.h
+++ b/src/opt/mfs/mfsInt.h
@@ -81,6 +81,8 @@ struct Mfs_Man_t_
Vec_Ptr_t * vFanins; // the new set of fanins
int nTotConfLim; // total conflict limit
int nTotConfLevel; // total conflicts on this level
+ // switching activity
+ Vec_Int_t * vProbs;
// the result of solving
int nFanins; // the number of fanins
int nWords; // the number of words
@@ -102,6 +104,8 @@ struct Mfs_Man_t_
int nTotalNodesEnd;
int nTotalEdgesBeg;
int nTotalEdgesEnd;
+ float TotalSwitchingBeg;
+ float TotalSwitchingEnd;
// statistics
int timeWin;
int timeDiv;
@@ -137,6 +141,7 @@ extern void Mfs_ManClean( Mfs_Man_t * p );
/*=== mfsResub.c ==========================================================*/
extern void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p );
extern int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode );
+extern int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode );
extern int Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode );
extern int Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode );
/*=== mfsSat.c ==========================================================*/
diff --git a/src/opt/mfs/mfsMan.c b/src/opt/mfs/mfsMan.c
index d0642368..9a043ed8 100644
--- a/src/opt/mfs/mfsMan.c
+++ b/src/opt/mfs/mfsMan.c
@@ -108,6 +108,7 @@ void Mfs_ManPrint( Mfs_Man_t * p )
{
if ( p->pPars->fResub )
{
+/*
printf( "Reduction in nodes = %5d. (%.2f %%) ",
p->nTotalNodesBeg-p->nTotalNodesEnd,
100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/p->nTotalNodesBeg );
@@ -123,6 +124,28 @@ void Mfs_ManPrint( Mfs_Man_t * p )
else
Abc_NtkMfsPrintResubStats( p );
// printf( "Average ratio of DCs in the resubed nodes = %.2f.\n", 1.0*p->nDcMints/(64 * p->nNodesResub) );
+*/
+ printf( "@@@------- Node( %4d, %4.2f%% ), ",
+ p->nTotalNodesBeg-p->nTotalNodesEnd,
+ 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/p->nTotalNodesBeg );
+ printf( "Edge( %4d, %4.2f%% ), ",
+ p->nTotalEdgesBeg-p->nTotalEdgesEnd,
+ 100.0*(p->nTotalEdgesBeg-p->nTotalEdgesEnd)/p->nTotalEdgesBeg );
+ if (p->pPars->fPower)
+ printf( "Power( %5.2f, %4.2f%%) ",
+ p->TotalSwitchingBeg - p->TotalSwitchingEnd,
+ 100.0*(p->TotalSwitchingBeg-p->TotalSwitchingEnd)/p->TotalSwitchingBeg );
+ printf( "\n" );
+#if 0
+ printf( "Nodes = %d. Try = %d. Resub = %d. Div = %d. SAT calls = %d. Timeouts = %d.\n",
+ Abc_NtkNodeNum(p->pNtk), p->nNodesTried, p->nNodesResub, p->nTotalDivs, p->nSatCalls, p->nTimeOuts );
+#endif
+ if ( p->pPars->fSwapEdge )
+ printf( "Swappable edges = %d. Total edges = %d. Ratio = %5.2f.\n",
+ p->nNodesResub, Abc_NtkGetTotalFanins(p->pNtk), 1.00 * p->nNodesResub / Abc_NtkGetTotalFanins(p->pNtk) );
+ else
+ Abc_NtkMfsPrintResubStats( p );
+// printf( "Average ratio of DCs in the resubed nodes = %.2f.\n", 1.0*p->nDcMints/(64 * p->nNodesResub) );
}
else
{
@@ -168,6 +191,8 @@ void Mfs_ManStop( Mfs_Man_t * p )
Aig_ManStop( p->pCare );
if ( p->vSuppsInv )
Vec_VecFree( (Vec_Vec_t *)p->vSuppsInv );
+ if ( p->vProbs )
+ Vec_IntFree( p->vProbs );
Mfs_ManClean( p );
Int_ManFree( p->pMan );
Vec_IntFree( p->vMem );
diff --git a/src/opt/mfs/mfsResub.c b/src/opt/mfs/mfsResub.c
index b6c7299b..e9ea2c40 100644
--- a/src/opt/mfs/mfsResub.c
+++ b/src/opt/mfs/mfsResub.c
@@ -80,8 +80,8 @@ void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p )
nAreaExpanse += (int)(Abc_ObjFaninNum(pNode) < nFaninMax);
}
}
- printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n",
- nAreaCrits, nAreaExpanse );
+// printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n",
+// nAreaCrits, nAreaExpanse );
}
/**Function*************************************************************
@@ -209,6 +209,8 @@ p->timeInt += clock() - clk;
iVar = -1;
while ( 1 )
{
+ float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL);
+ assert( (pProbab != NULL) == p->pPars->fPower );
if ( fVeryVerbose )
{
printf( "%3d: %2d ", p->nCexes, iVar );
@@ -225,6 +227,13 @@ p->timeInt += clock() - clk;
assert( nWords <= p->nDivWords );
for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ )
{
+ if ( p->pPars->fPower )
+ {
+ Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar);
+ // only accept the divisor if it is "cool"
+ if ( pProbab[Abc_ObjId(pDiv)] >= 0.15 )
+ continue;
+ }
pData = Vec_PtrEntry( p->vDivCexes, iVar );
for ( w = 0; w < nWords; w++ )
if ( pData[w] != ~0 )
@@ -345,6 +354,10 @@ p->timeInt += clock() - clk;
iVar = iVar2 = -1;
while ( 1 )
{
+#if 1 // sjang
+ float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL);
+ assert( (pProbab != NULL) == p->pPars->fPower );
+#endif
if ( fVeryVerbose )
{
printf( "%3d: %2d %2d ", p->nCexes, iVar, iVar2 );
@@ -363,9 +376,27 @@ p->timeInt += clock() - clk;
for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ )
{
pData = Vec_PtrEntry( p->vDivCexes, iVar );
+#if 1 // sjang
+ if ( p->pPars->fPower )
+ {
+ Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar);
+ // only accept the divisor if it is "cool"
+ if ( pProbab[Abc_ObjId(pDiv)] >= 0.12 )
+ continue;
+ }
+#endif
for ( iVar2 = 0; iVar2 < iVar; iVar2++ )
{
pData2 = Vec_PtrEntry( p->vDivCexes, iVar2 );
+#if 1 // sjang
+ if ( p->pPars->fPower )
+ {
+ Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar2);
+ // only accept the divisor if it is "cool"
+ if ( pProbab[Abc_ObjId(pDiv)] >= 0.12 )
+ continue;
+ }
+#endif
for ( w = 0; w < nWords; w++ )
if ( (pData[w] | pData2[w]) != ~0 )
break;
@@ -434,6 +465,38 @@ int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode )
/**Function*************************************************************
+ Synopsis [Evaluates the possibility of replacing given edge by another edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ float * pProbab = (float *)p->vProbs->pArray;
+ int i;
+ // try replacing area critical fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( pProbab[pFanin->Id] >= 0.35 )
+ {
+ if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+ return 1;
+ } else if ( pProbab[pFanin->Id] >= 0.25 ) // sjang
+ {
+ if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) )
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
Synopsis [Performs resubstitution for the node.]
Description []
diff --git a/src/opt/mfs/mfsResub_.c b/src/opt/mfs/mfsResub_.c
new file mode 100644
index 00000000..47600b30
--- /dev/null
+++ b/src/opt/mfs/mfsResub_.c
@@ -0,0 +1,560 @@
+/**CFile****************************************************************
+
+ FileName [mfsResub.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [The good old minimization with complete don't-cares.]
+
+ Synopsis [Procedures to perform resubstitution.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: mfsResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "mfsInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Updates the network after resubstitution.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMfsUpdateNetwork( Mfs_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc )
+{
+ Abc_Obj_t * pObjNew, * pFanin;
+ int k;
+ // create the new node
+ pObjNew = Abc_NtkCreateNode( pObj->pNtk );
+ pObjNew->pData = pFunc;
+ Vec_PtrForEachEntry( vFanins, pFanin, k )
+ Abc_ObjAddFanin( pObjNew, pFanin );
+ // replace the old node by the new node
+//printf( "Replacing node " ); Abc_ObjPrint( stdout, pObj );
+//printf( "Inserting node " ); Abc_ObjPrint( stdout, pObjNew );
+ // update the level of the node
+ Abc_NtkUpdate( pObj, pObjNew, p->vLevels );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints resub candidate stats.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p )
+{
+ Abc_Obj_t * pFanin, * pNode;
+ int i, k, nAreaCrits = 0, nAreaExpanse = 0;
+ int nFaninMax = Abc_NtkGetFaninMax(p->pNtk);
+ Abc_NtkForEachNode( p->pNtk, pNode, i )
+ Abc_ObjForEachFanin( pNode, pFanin, k )
+ {
+ if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+ {
+ nAreaCrits++;
+ nAreaExpanse += (int)(Abc_ObjFaninNum(pNode) < nFaninMax);
+ }
+ }
+ printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n",
+ nAreaCrits, nAreaExpanse );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries resubstitution.]
+
+ Description [Returns 1 if it is feasible, or 0 if c-ex is found.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMfsTryResubOnce( Mfs_Man_t * p, int * pCands, int nCands )
+{
+ unsigned * pData;
+ int RetValue, iVar, i;
+ p->nSatCalls++;
+ RetValue = sat_solver_solve( p->pSat, pCands, pCands + nCands, (sint64)p->pPars->nBTLimit, (sint64)0, (sint64)0, (sint64)0 );
+// assert( RetValue == l_False || RetValue == l_True );
+ if ( RetValue == l_False )
+ return 1;
+ if ( RetValue != l_True )
+ {
+ p->nTimeOuts++;
+ return -1;
+ }
+ p->nSatCexes++;
+ // store the counter-example
+ Vec_IntForEachEntry( p->vProjVars, iVar, i )
+ {
+ pData = Vec_PtrEntry( p->vDivCexes, i );
+ if ( !sat_solver_var_value( p->pSat, iVar ) ) // remove 0s!!!
+ {
+ assert( Aig_InfoHasBit(pData, p->nCexes) );
+ Aig_InfoXorBit( pData, p->nCexes );
+ }
+ }
+ p->nCexes++;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs resubstitution for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate )
+{
+ int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80;
+ unsigned * pData;
+ int pCands[MFS_FANIN_MAX];
+ int RetValue, iVar, i, nCands, nWords, w, clk;
+ Abc_Obj_t * pFanin;
+ Hop_Obj_t * pFunc;
+ assert( iFanin >= 0 );
+
+ // clean simulation info
+ Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords );
+ p->nCexes = 0;
+ if ( fVeryVerbose )
+ {
+ printf( "\n" );
+ printf( "Node %5d : Level = %2d. Divs = %3d. Fanin = %d (out of %d). MFFC = %d\n",
+ pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode),
+ iFanin, Abc_ObjFaninNum(pNode),
+ Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 );
+ }
+
+ // try fanins without the critical fanin
+ nCands = 0;
+ Vec_PtrClear( p->vFanins );
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( i == iFanin )
+ continue;
+ Vec_PtrPush( p->vFanins, pFanin );
+ iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i;
+ pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVars, iVar ), 1 );
+ }
+ RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands );
+ if ( RetValue == -1 )
+ return 0;
+ if ( RetValue == 1 )
+ {
+ if ( fVeryVerbose )
+ printf( "Node %d: Fanin %d can be removed.\n", pNode->Id, iFanin );
+ p->nNodesResub++;
+ p->nNodesGainedLevel++;
+ if ( fSkipUpdate )
+ return 1;
+clk = clock();
+ // derive the function
+ pFunc = Abc_NtkMfsInterplate( p, pCands, nCands );
+ if ( pFunc == NULL )
+ return 0;
+ // update the network
+ Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc );
+p->timeInt += clock() - clk;
+ return 1;
+ }
+
+ if ( fOnlyRemove )
+ return 0;
+
+ if ( fVeryVerbose )
+ {
+ for ( i = 0; i < 8; i++ )
+ printf( " " );
+ for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ )
+ printf( "%d", i % 10 );
+ for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+ if ( i == iFanin )
+ printf( "*" );
+ else
+ printf( "%c", 'a' + i );
+ printf( "\n" );
+ }
+ iVar = -1;
+ while ( 1 )
+ {
+ float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL);
+ assert( (pProbab != NULL) == p->pPars->fPower );
+ if ( fVeryVerbose )
+ {
+ printf( "%3d: %2d ", p->nCexes, iVar );
+ for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ )
+ {
+ pData = Vec_PtrEntry( p->vDivCexes, i );
+ printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) );
+ }
+ printf( "\n" );
+ }
+
+ // find the next divisor to try
+ nWords = Aig_BitWordNum(p->nCexes);
+ assert( nWords <= p->nDivWords );
+ for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ )
+ {
+ if ( p->pPars->fPower )
+ {
+ Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar);
+ // only accept the divisor if it is "cool"
+ if ( pProbab[Abc_ObjId(pDiv)] >= 0.2 )
+ continue;
+ }
+ pData = Vec_PtrEntry( p->vDivCexes, iVar );
+ for ( w = 0; w < nWords; w++ )
+ if ( pData[w] != ~0 )
+ break;
+ if ( w == nWords )
+ break;
+ }
+ if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) )
+ return 0;
+
+ pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVars, iVar), 1 );
+ RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+1 );
+ if ( RetValue == -1 )
+ return 0;
+ if ( RetValue == 1 )
+ {
+ if ( fVeryVerbose )
+ printf( "Node %d: Fanin %d can be replaced by divisor %d.\n", pNode->Id, iFanin, iVar );
+ p->nNodesResub++;
+ p->nNodesGainedLevel++;
+ if ( fSkipUpdate )
+ return 1;
+clk = clock();
+ // derive the function
+ pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+1 );
+ if ( pFunc == NULL )
+ return 0;
+ // update the network
+ Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) );
+ Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc );
+p->timeInt += clock() - clk;
+ return 1;
+ }
+ if ( p->nCexes >= p->pPars->nDivMax )
+ break;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs resubstitution for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMfsSolveSatResub2( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int iFanin2 )
+{
+ int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80;
+ unsigned * pData, * pData2;
+ int pCands[MFS_FANIN_MAX];
+ int RetValue, iVar, iVar2, i, w, nCands, clk, nWords, fBreak;
+ Abc_Obj_t * pFanin;
+ Hop_Obj_t * pFunc;
+ assert( iFanin >= 0 );
+ assert( iFanin2 >= 0 || iFanin2 == -1 );
+
+ // clean simulation info
+ Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords );
+ p->nCexes = 0;
+ if ( fVeryVerbose )
+ {
+ printf( "\n" );
+ printf( "Node %5d : Level = %2d. Divs = %3d. Fanins = %d/%d (out of %d). MFFC = %d\n",
+ pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode),
+ iFanin, iFanin2, Abc_ObjFaninNum(pNode),
+ Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 );
+ }
+
+ // try fanins without the critical fanin
+ nCands = 0;
+ Vec_PtrClear( p->vFanins );
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( i == iFanin || i == iFanin2 )
+ continue;
+ Vec_PtrPush( p->vFanins, pFanin );
+ iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i;
+ pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVars, iVar ), 1 );
+ }
+ RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands );
+ if ( RetValue == -1 )
+ return 0;
+ if ( RetValue == 1 )
+ {
+ if ( fVeryVerbose )
+ printf( "Node %d: Fanins %d/%d can be removed.\n", pNode->Id, iFanin, iFanin2 );
+ p->nNodesResub++;
+ p->nNodesGainedLevel++;
+clk = clock();
+ // derive the function
+ pFunc = Abc_NtkMfsInterplate( p, pCands, nCands );
+ if ( pFunc == NULL )
+ return 0;
+ // update the network
+ Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc );
+p->timeInt += clock() - clk;
+ return 1;
+ }
+
+ if ( fVeryVerbose )
+ {
+ for ( i = 0; i < 11; i++ )
+ printf( " " );
+ for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ )
+ printf( "%d", i % 10 );
+ for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
+ if ( i == iFanin || i == iFanin2 )
+ printf( "*" );
+ else
+ printf( "%c", 'a' + i );
+ printf( "\n" );
+ }
+ iVar = iVar2 = -1;
+ while ( 1 )
+ {
+ if ( fVeryVerbose )
+ {
+ printf( "%3d: %2d %2d ", p->nCexes, iVar, iVar2 );
+ for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ )
+ {
+ pData = Vec_PtrEntry( p->vDivCexes, i );
+ printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) );
+ }
+ printf( "\n" );
+ }
+
+ // find the next divisor to try
+ nWords = Aig_BitWordNum(p->nCexes);
+ assert( nWords <= p->nDivWords );
+ fBreak = 0;
+ for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ )
+ {
+ pData = Vec_PtrEntry( p->vDivCexes, iVar );
+ for ( iVar2 = 0; iVar2 < iVar; iVar2++ )
+ {
+ pData2 = Vec_PtrEntry( p->vDivCexes, iVar2 );
+ for ( w = 0; w < nWords; w++ )
+ if ( (pData[w] | pData2[w]) != ~0 )
+ break;
+ if ( w == nWords )
+ {
+ fBreak = 1;
+ break;
+ }
+ }
+ if ( fBreak )
+ break;
+ }
+ if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) )
+ return 0;
+
+ pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVars, iVar2), 1 );
+ pCands[nCands+1] = toLitCond( Vec_IntEntry(p->vProjVars, iVar), 1 );
+ RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+2 );
+ if ( RetValue == -1 )
+ return 0;
+ if ( RetValue == 1 )
+ {
+ if ( fVeryVerbose )
+ printf( "Node %d: Fanins %d/%d can be replaced by divisors %d/%d.\n", pNode->Id, iFanin, iFanin2, iVar, iVar2 );
+ p->nNodesResub++;
+ p->nNodesGainedLevel++;
+clk = clock();
+ // derive the function
+ pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+2 );
+ if ( pFunc == NULL )
+ return 0;
+ // update the network
+ Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar2) );
+ Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) );
+ assert( Vec_PtrSize(p->vFanins) == nCands + 2 );
+ Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc );
+p->timeInt += clock() - clk;
+ return 1;
+ }
+ if ( p->nCexes >= p->pPars->nDivMax )
+ break;
+ }
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Evaluates the possibility of replacing given edge by another edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 1 );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluates the possibility of replacing given edge by another edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ float * pProbab = (float *)p->vProbs->pArray;
+ int i;
+ // try replacing area critical fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( pProbab[pFanin->Id] >= 0.4 )
+ {
+ if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+ return 1;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs resubstitution for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // try replacing area critical fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+ {
+ if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+ return 1;
+ }
+ // try removing redundant edges
+ if ( !p->pPars->fArea )
+ {
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( Abc_ObjIsCi(pFanin) || Abc_ObjFanoutNum(pFanin) != 1 )
+ {
+ if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) )
+ return 1;
+ }
+ }
+ if ( Abc_ObjFaninNum(pNode) == p->nFaninMax )
+ return 0;
+ // try replacing area critical fanins while adding two new fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+ {
+ if ( Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) )
+ return 1;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs resubstitution for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin, * pFanin2;
+ int i, k;
+/*
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+ {
+ if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) )
+ return 1;
+ }
+*/
+ if ( Abc_ObjFaninNum(pNode) < 2 )
+ return 0;
+ // try replacing one area critical fanin and one other fanin while adding two new fanins
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
+ {
+ // consider second fanin to remove at the same time
+ Abc_ObjForEachFanin( pNode, pFanin2, k )
+ {
+ if ( i != k && Abc_NtkMfsSolveSatResub2( p, pNode, i, k ) )
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/sim/simSwitch.c b/src/opt/sim/simSwitch.c
index 218d4d59..baabc320 100644
--- a/src/opt/sim/simSwitch.c
+++ b/src/opt/sim/simSwitch.c
@@ -97,7 +97,7 @@ float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords )
int nOnes, nTotal;
nTotal = 32 * nSimWords;
nOnes = Sim_UtilCountOnes( pSimInfo, nSimWords );
- return (float)2.0 * nOnes * (nTotal - nOnes) / nTotal / nTotal;
+ return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal;
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/sat/bsat/satInterP.c b/src/sat/bsat/satInterP.c
index 686774fa..c944c36d 100644
--- a/src/sat/bsat/satInterP.c
+++ b/src/sat/bsat/satInterP.c
@@ -601,6 +601,27 @@ int Intp_ManProofTraceOne( Intp_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pF
Intp_ManPrintResolvent( p->pResLits, p->nResLits );
Intp_ManPrintClause( p, pFinal );
}
+
+ // if there are literals in the clause that are not in the resolvent
+ // it means that the derived resolvent is stronger than the clause
+ // we can replace the clause with the resolvent by removing these literals
+ if ( p->nResLits != (int)pFinal->nLits )
+ {
+ for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ )
+ {
+ for ( v2 = 0; v2 < p->nResLits; v2++ )
+ if ( pFinal->pLits[v1] == p->pResLits[v2] )
+ break;
+ if ( v2 < p->nResLits )
+ continue;
+ // remove literal v1 from the final clause
+ pFinal->nLits--;
+ for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ )
+ pFinal->pLits[v2] = pFinal->pLits[v2+1];
+ v1--;
+ }
+ assert( p->nResLits == (int)pFinal->nLits );
+ }
}
p->timeTrace += clock() - clk;
@@ -610,6 +631,10 @@ p->timeTrace += clock() - clk;
// Intp_ManPrintInterOne( p, pFinal );
// }
Intp_ManProofSet( p, pFinal, p->Counter );
+ // make sure the same proof ID is not asssigned to two consecutive clauses
+ assert( p->pProofNums[pFinal->Id-1] != p->Counter );
+// if ( p->pProofNums[pFinal->Id] == p->pProofNums[pFinal->Id-1] )
+// p->pProofNums[pFinal->Id] = p->pProofNums[pConflict->Id];
return p->Counter;
}
@@ -634,9 +659,19 @@ int Intp_ManProofRecordOne( Intp_Man_t * p, Sto_Cls_t * pClause )
if ( pClause->nLits == 0 )
printf( "Error: Empty clause is attempted.\n" );
- // add assumptions to the trail
assert( !pClause->fRoot );
assert( p->nTrailSize == p->nRootSize );
+
+ // if any of the clause literals are already assumed
+ // it means that the clause is redundant and can be skipped
+ for ( i = 0; i < (int)pClause->nLits; i++ )
+ if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] )
+ {
+ Vec_IntPush( p->vBreaks, Vec_IntSize(p->vAnties) );
+ return 1;
+ }
+
+ // add assumptions to the trail
for ( i = 0; i < (int)pClause->nLits; i++ )
if ( !Intp_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) )
{
@@ -652,6 +687,28 @@ int Intp_ManProofRecordOne( Intp_Man_t * p, Sto_Cls_t * pClause )
return 0;
}
+ // skip the clause if it is weaker or the same as the conflict clause
+ if ( pClause->nLits >= pConflict->nLits )
+ {
+ // check if every literal of conflict clause can be found in the given clause
+ int j;
+ for ( i = 0; i < (int)pConflict->nLits; i++ )
+ {
+ for ( j = 0; j < (int)pClause->nLits; j++ )
+ if ( pConflict->pLits[i] == pClause->pLits[j] )
+ break;
+ if ( j == (int)pClause->nLits ) // literal pConflict->pLits[i] is not found
+ break;
+ }
+ if ( i == (int)pConflict->nLits ) // all lits are found
+ {
+ // undo to the root level
+ Intp_ManCancelUntil( p, p->nRootSize );
+ Vec_IntPush( p->vBreaks, Vec_IntSize(p->vAnties) );
+ return 1;
+ }
+ }
+
// construct the proof
Intp_ManProofTraceOne( p, pConflict, pClause );
@@ -737,8 +794,12 @@ int Intp_ManProcessRoots( Intp_Man_t * p )
if ( !Intp_ManEnqueue( p, pClause->pLits[0], pClause ) )
{
// detected root level conflict
- printf( "Error in Intp_ManProcessRoots(): Detected a root-level conflict too early!\n" );
- assert( 0 );
+// printf( "Error in Intp_ManProcessRoots(): Detected a root-level conflict too early!\n" );
+// assert( 0 );
+ // detected root level conflict
+ Intp_ManProofTraceOne( p, pClause, p->pCnf->pEmpty );
+ if ( p->fVerbose )
+ printf( "Found root level conflict!\n" );
return 0;
}
}
@@ -762,6 +823,68 @@ int Intp_ManProcessRoots( Intp_Man_t * p )
/**Function*************************************************************
+ Synopsis [Verifies the UNSAT core.]
+
+ Description [Takes the interpolation manager, the CNF derived by the SAT
+ solver, which includes the root clauses and the learned clauses. Returns
+ the array of integers representing the number of root clauses that are in
+ the UNSAT core.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Intp_ManUnsatCoreVerify( Sto_Man_t * pCnf, Vec_Int_t * vCore )
+{
+ int fVerbose = 0;
+ int nConfMax = 1000000;
+ sat_solver * pSat;
+ Sto_Cls_t * pClause;
+ Vec_Ptr_t * vClauses;
+ int i, iClause, RetValue, clk = clock();
+ // collect the clauses
+ vClauses = Vec_PtrAlloc( 1000 );
+ Sto_ManForEachClauseRoot( pCnf, pClause )
+ {
+ assert( Vec_PtrSize(vClauses) == pClause->Id );
+ Vec_PtrPush( vClauses, pClause );
+ }
+ // create new SAT solver
+ pSat = sat_solver_new();
+// sat_solver_setnvars( pSat, nSatVars );
+ Vec_IntForEachEntry( vCore, iClause, i )
+ {
+ pClause = Vec_PtrEntry( vClauses, iClause );
+ if ( !sat_solver_addclause( pSat, pClause->pLits, pClause->pLits+pClause->nLits ) )
+ {
+ printf( "The core verification problem is trivially UNSAT.\n" );
+ break;
+ }
+ }
+ Vec_PtrFree( vClauses );
+ // solve the problem
+ RetValue = sat_solver_solve( pSat, NULL, NULL, (sint64)nConfMax, (sint64)0, (sint64)0, (sint64)0 );
+ sat_solver_delete( pSat );
+ if ( fVerbose )
+ {
+ if ( RetValue == l_Undef )
+ printf( "Conflict limit is reached. " );
+ else if ( RetValue == l_True )
+ printf( "UNSAT core verification FAILED. " );
+ else
+ printf( "UNSAT core verification succeeded. " );
+ PRT( "Time", clock() - clk );
+ }
+ else
+ {
+ if ( RetValue == l_True )
+ printf( "UNSAT core verification FAILED. \n" );
+ }
+}
+
+/**Function*************************************************************
+
Synopsis [Recursively computes the UNSAT core.]
Description []
@@ -771,15 +894,13 @@ int Intp_ManProcessRoots( Intp_Man_t * p )
SeeAlso []
***********************************************************************/
-void Intp_ManUnsatCore_rec( Vec_Int_t * vAnties, Vec_Int_t * vBreaks, int iThis, Vec_Int_t * vCore, int nRoots )
+void Intp_ManUnsatCore_rec( Vec_Int_t * vAnties, Vec_Int_t * vBreaks, int iThis, Vec_Int_t * vCore, int nRoots, Vec_Int_t * vVisited )
{
int i, iStop, iStart;
- // skip of this clause was visited
- iStart = Vec_IntEntry( vBreaks, iThis );
- if ( iStart == -1 )
+ // skip visited clauses
+ if ( Vec_IntEntry( vVisited, iThis ) )
return;
- // mark this clause as visited
- Vec_IntWriteEntry( vBreaks, iThis, -1 );
+ Vec_IntWriteEntry( vVisited, iThis, 1 );
// add a root clause to the core
if ( iThis < nRoots )
{
@@ -787,9 +908,11 @@ void Intp_ManUnsatCore_rec( Vec_Int_t * vAnties, Vec_Int_t * vBreaks, int iThis,
return;
}
// iterate through the clauses
+ iStart = Vec_IntEntry( vBreaks, iThis );
iStop = Vec_IntEntry( vBreaks, iThis+1 );
+ assert( iStop != -1 );
for ( i = iStart; i < iStop; i++ )
- Intp_ManUnsatCore_rec( vAnties, vBreaks, Vec_IntEntry(vAnties, i), vCore, nRoots );
+ Intp_ManUnsatCore_rec( vAnties, vBreaks, Vec_IntEntry(vAnties, i), vCore, nRoots, vVisited );
}
/**Function*************************************************************
@@ -809,6 +932,7 @@ void Intp_ManUnsatCore_rec( Vec_Int_t * vAnties, Vec_Int_t * vBreaks, int iThis,
void * Intp_ManUnsatCore( Intp_Man_t * p, Sto_Man_t * pCnf, int fVerbose )
{
Vec_Int_t * vCore;
+ Vec_Int_t * vVisited;
Sto_Cls_t * pClause;
int RetValue = 1;
int clkTotal = clock();
@@ -859,6 +983,7 @@ void * Intp_ManUnsatCore( Intp_Man_t * p, Sto_Man_t * pCnf, int fVerbose )
if ( p->fProofWrite )
{
fclose( p->pFile );
+// Sat_ProofChecker( "proof.cnf_" );
p->pFile = NULL;
}
@@ -874,10 +999,13 @@ p->timeTotal += clock() - clkTotal;
// derive the UNSAT core
vCore = Vec_IntAlloc( 1000 );
- Intp_ManUnsatCore_rec( p->vAnties, p->vBreaks, p->pCnf->pEmpty->Id, vCore, p->pCnf->nRoots );
+ vVisited = Vec_IntStart( p->pCnf->pEmpty->Id+1 );
+ Intp_ManUnsatCore_rec( p->vAnties, p->vBreaks, p->pCnf->pEmpty->Id, vCore, p->pCnf->nRoots, vVisited );
+ Vec_IntFree( vVisited );
if ( fVerbose )
printf( "Root clauses = %d. Learned clauses = %d. UNSAT core size = %d.\n",
p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, Vec_IntSize(vCore) );
+ Intp_ManUnsatCoreVerify( p->pCnf, vCore );
return vCore;
}
diff --git a/src/sat/bsat/satStore.h b/src/sat/bsat/satStore.h
index ef98ab93..f63703d3 100644
--- a/src/sat/bsat/satStore.h
+++ b/src/sat/bsat/satStore.h
@@ -74,7 +74,7 @@ struct Sto_Cls_t_
{
Sto_Cls_t * pNext; // the next clause
Sto_Cls_t * pNext0; // the next 0-watch
- Sto_Cls_t * pNext1; // the next 0-watch
+ Sto_Cls_t * pNext1; // the next 1-watch
int Id; // the clause ID
unsigned fA : 1; // belongs to A
unsigned fRoot : 1; // original clause