From eb2a5b43a46b90f3c46b388f50ea0ca8918983aa Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 12 Aug 2006 08:01:00 -0700 Subject: [PATCH] Version abc60812 --- abc.dsp | 52 +--- abc.rc | 3 +- src/base/abci/abc.c | 71 +++++ src/base/abci/abcIvy.c | 37 ++- src/base/abci/abcNtbdd.c | 1 - src/base/main/mainFrame.c | 3 +- src/base/main/mainInt.h | 1 - src/bdd/reo/reo.h | 8 +- src/bdd/reo/reoProfile.c | 2 +- src/bdd/reo/reoSwap.c | 26 +- src/bdd/reo/reoTransfer.c | 14 +- src/misc/extra/extra.h | 29 +- src/misc/extra/extraUtil.h | 60 ---- src/misc/extra/extraUtilTruth.c | 20 -- src/opt/cut/cut60720.zip | Bin 31142 -> 0 bytes src/opt/cut/cut60721.zip | Bin 42872 -> 0 bytes src/opt/fxu/fxuCreate.c | 4 +- src/temp/ivy/ivy.h | 101 ++++--- src/temp/ivy/ivyBalance.c | 11 + src/temp/ivy/ivyCut.c | 1 - src/temp/ivy/ivyCutTrav.c | 473 ++++++++++++++++++++++++++++++++ src/temp/ivy/ivyDfs.c | 2 +- src/temp/ivy/ivyHaig.c | 348 +++++++++++++++++++++++ src/temp/ivy/ivyMan.c | 58 ++++ src/temp/ivy/ivyMem.c | 2 +- src/temp/ivy/ivyMulti.c | 39 --- src/temp/ivy/ivyObj.c | 15 +- src/temp/ivy/ivyOper.c | 39 +++ src/temp/ivy/ivySeq.c | 4 - src/temp/player/playerToAbc.c | 11 +- 30 files changed, 1177 insertions(+), 258 deletions(-) delete mode 100644 src/misc/extra/extraUtil.h delete mode 100644 src/opt/cut/cut60720.zip delete mode 100644 src/opt/cut/cut60721.zip create mode 100644 src/temp/ivy/ivyCutTrav.c create mode 100644 src/temp/ivy/ivyHaig.c diff --git a/abc.dsp b/abc.dsp index 121b87e8a..59ff89311 100644 --- a/abc.dsp +++ b/abc.dsp @@ -2102,6 +2102,10 @@ SOURCE=.\src\temp\ivy\ivyCut.c # End Source File # Begin Source File +SOURCE=.\src\temp\ivy\ivyCutTrav.c +# End Source File +# Begin Source File + SOURCE=.\src\temp\ivy\ivyDfs.c # End Source File # Begin Source File @@ -2114,6 +2118,10 @@ SOURCE=.\src\temp\ivy\ivyFanout.c # End Source File # Begin Source File +SOURCE=.\src\temp\ivy\ivyHaig.c +# End Source File +# Begin Source File + SOURCE=.\src\temp\ivy\ivyIsop.c # End Source File # Begin Source File @@ -2205,50 +2213,6 @@ SOURCE=.\src\temp\esop\esopMin.c SOURCE=.\src\temp\esop\esopUtil.c # End Source File # End Group -# Begin Group "xyz" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\temp\xyz\xyz.h -# End Source File -# Begin Source File - -SOURCE=.\src\temp\xyz\xyzBuild.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\xyz\xyzCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\xyz\xyzInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\temp\xyz\xyzMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\xyz\xyzMinEsop.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\xyz\xyzMinMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\xyz\xyzMinSop.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\xyz\xyzMinUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\temp\xyz\xyzTest.c -# End Source File -# End Group # Begin Group "rwt" # PROP Default_Filter "" diff --git a/abc.rc b/abc.rc index 49c9617bd..ea9dc7bc1 100644 --- a/abc.rc +++ b/abc.rc @@ -3,7 +3,8 @@ #set checkfio # prints warnings when fanins/fanouts are duplicated #set checkread # checks new networks after reading from file #set backup # saves backup networks retrived by "undo" and "recall" -#set savesteps 1 # sets the maximum number of backup networks to save +#set savesteps 1 # sets the maximum number of backup networks to save +set progressbar # display the progress bar # program names for internal calls set dotwin dot.exe diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index bb8f56586..f3dbe3572 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -93,6 +93,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_CommandIRewriteSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandIResyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandHaig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraigTrust ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -210,6 +211,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "New AIG", "irw", Abc_CommandIRewrite, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "irws", Abc_CommandIRewriteSeq, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "iresyn", Abc_CommandIResyn, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "haig", Abc_CommandHaig, 1 ); Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 ); Cmd_CommandAdd( pAbc, "Fraiging", "fraig_trust", Abc_CommandFraigTrust, 1 ); @@ -5088,6 +5090,75 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandHaig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fVerbose; + extern Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUpdateLevel = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "zvh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsSeq(pNtk) ) + { + fprintf( pErr, "Only works for non-sequential networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyHaig( pNtk, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: haig [-vh]\n" ); + fprintf( pErr, "\t prints HAIG stats after one round of sequential rewriting\n" ); +// fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* diff --git a/src/base/abci/abcIvy.c b/src/base/abci/abcIvy.c index 380b3f8b4..7d5ed6ece 100644 --- a/src/base/abci/abcIvy.c +++ b/src/base/abci/abcIvy.c @@ -168,6 +168,36 @@ Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk ) return pNtkAig; } +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan; + pMan = Abc_NtkIvyBefore( pNtk, 1, 1 ); + if ( pMan == NULL ) + return NULL; + + Ivy_ManHaigStart( pMan ); + Ivy_ManRewriteSeq( pMan, 0, fVerbose ); + Ivy_ManHaigPrintStats( pMan ); + Ivy_ManHaigStop( pMan ); + +// pNtkAig = Abc_NtkIvyAfterHaig( pNtk, pMan, 1 ); + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] @@ -276,10 +306,10 @@ Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ) ***********************************************************************/ Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk ) { - Abc_Ntk_t * pNtkAig; +// Abc_Ntk_t * pNtkAig; Ivy_Man_t * pMan;//, * pTemp; int fCleanup = 1; - int nNodes; +// int nNodes; int nLatches = Abc_NtkLatchNum(pNtk); int * pInit = Abc_NtkCollectLatchValues( pNtk, 0 ); @@ -329,6 +359,7 @@ Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk ) // Ivy_ManStop( pTemp ); // Ivy_ManTestCutsAll( pMan ); +// Ivy_ManTestCutsTravAll( pMan ); // Ivy_ManPrintStats( pMan ); @@ -344,7 +375,7 @@ Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk ) // Ivy_ManRequiredLevels( pMan ); // Pla_ManFastLutMap( pMan, 8 ); -// Ivy_ManStop( pMan ); + Ivy_ManStop( pMan ); return NULL; diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c index 33f432f42..6cbab1a66 100644 --- a/src/base/abci/abcNtbdd.c +++ b/src/base/abci/abcNtbdd.c @@ -148,7 +148,6 @@ Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ) void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { ProgressBar * pProgress; - DdManager * dd = pNtk->pManFunc; Abc_Obj_t * pNode, * pNodeNew; Vec_Ptr_t * vNodes; int i; diff --git a/src/base/main/mainFrame.c b/src/base/main/mainFrame.c index 5c4a06753..a1011a360 100644 --- a/src/base/main/mainFrame.c +++ b/src/base/main/mainFrame.c @@ -111,7 +111,6 @@ Abc_Frame_t * Abc_FrameAllocate() // set the starting step p->nSteps = 1; p->fBatchMode = 0; - p->fProgress = 1; // initialize decomposition manager define_cube_size(20); set_espresso_flags(); @@ -176,7 +175,7 @@ void Abc_FrameRestart( Abc_Frame_t * p ) ***********************************************************************/ bool Abc_FrameShowProgress( Abc_Frame_t * p ) { - return p->fProgress; + return Abc_FrameIsFlagEnabled( "progressbar" ); } diff --git a/src/base/main/mainInt.h b/src/base/main/mainInt.h index 109e91c83..d2bca1ab0 100644 --- a/src/base/main/mainInt.h +++ b/src/base/main/mainInt.h @@ -55,7 +55,6 @@ struct Abc_Frame_t_ int nSteps; // the counter of different network processed int fAutoexac; // marks the autoexec mode int fBatchMode; // are we invoked in batch mode? - int fProgress; // shows progress bars // output streams FILE * Out; FILE * Err; diff --git a/src/bdd/reo/reo.h b/src/bdd/reo/reo.h index 456677680..9be29f87c 100644 --- a/src/bdd/reo/reo.h +++ b/src/bdd/reo/reo.h @@ -27,6 +27,8 @@ extern "C" { #include #include "extra.h" +//#pragma warning( disable : 4514 ) + //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -91,9 +93,9 @@ struct _reo_plane struct _reo_hash { int Sign; // signature of the current cache operation - unsigned Arg1; // the first argument - unsigned Arg2; // the second argument - unsigned Arg3; // the second argument + reo_unit * Arg1; // the first argument + reo_unit * Arg2; // the second argument + reo_unit * Arg3; // the third argument }; struct _reo_man diff --git a/src/bdd/reo/reoProfile.c b/src/bdd/reo/reoProfile.c index b38575f0c..84a0bc192 100644 --- a/src/bdd/reo/reoProfile.c +++ b/src/bdd/reo/reoProfile.c @@ -330,7 +330,7 @@ void reoProfileWidthPrint( reo_man * p ) WidthMax = p->pPlanes[i].statsWidth; TotalWidth += p->pPlanes[i].statsWidth; } - assert( p->nWidthCur = TotalWidth ); + assert( p->nWidthCur == TotalWidth ); printf( "WIDTH: " ); printf( "Maximum = %5d. ", WidthMax ); printf( "Total = %7d. ", p->nWidthCur ); diff --git a/src/bdd/reo/reoSwap.c b/src/bdd/reo/reoSwap.c index cb730d8e4..4afa650c9 100644 --- a/src/bdd/reo/reoSwap.c +++ b/src/bdd/reo/reoSwap.c @@ -271,9 +271,9 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) HKey = (HKey+1) % p->nTableSize ); assert( p->HTable[HKey].Sign != p->Signature ); p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = (unsigned)pUnitE; - p->HTable[HKey].Arg2 = (unsigned)pUnitT; - p->HTable[HKey].Arg3 = (unsigned)pUnit; + p->HTable[HKey].Arg1 = pUnitE; + p->HTable[HKey].Arg2 = pUnitT; + p->HTable[HKey].Arg3 = pUnit; nNodesUpMovedDown++; @@ -512,10 +512,10 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) for ( HKey = hashKey3(p->Signature, pNew1E, pNew1T, p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) - if ( p->HTable[HKey].Arg1 == (unsigned)pNew1E && p->HTable[HKey].Arg2 == (unsigned)pNew1T ) + if ( p->HTable[HKey].Arg1 == pNew1E && p->HTable[HKey].Arg2 == pNew1T ) { // the entry is present // assign this entry - pNewPlane20 = (reo_unit *)p->HTable[HKey].Arg3; + pNewPlane20 = p->HTable[HKey].Arg3; assert( pNewPlane20->lev == lev1 ); fFound = 1; p->HashSuccess++; @@ -549,9 +549,9 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) // add this entry to cache assert( p->HTable[HKey].Sign != p->Signature ); p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = (unsigned)pNew1E; - p->HTable[HKey].Arg2 = (unsigned)pNew1T; - p->HTable[HKey].Arg3 = (unsigned)pNewPlane20; + p->HTable[HKey].Arg1 = pNew1E; + p->HTable[HKey].Arg2 = pNew1T; + p->HTable[HKey].Arg3 = pNewPlane20; nNodesUnrefAdded++; @@ -637,10 +637,10 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) for ( HKey = hashKey3(p->Signature, pNew2E, pNew2T, p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) - if ( p->HTable[HKey].Arg1 == (unsigned)pNew2E && p->HTable[HKey].Arg2 == (unsigned)pNew2T ) + if ( p->HTable[HKey].Arg1 == pNew2E && p->HTable[HKey].Arg2 == pNew2T ) { // the entry is present // assign this entry - pNewPlane21 = (reo_unit *)p->HTable[HKey].Arg3; + pNewPlane21 = p->HTable[HKey].Arg3; assert( pNewPlane21->lev == lev1 ); fFound = 1; p->HashSuccess++; @@ -675,9 +675,9 @@ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) // add this entry to cache assert( p->HTable[HKey].Sign != p->Signature ); p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = (unsigned)pNew2E; - p->HTable[HKey].Arg2 = (unsigned)pNew2T; - p->HTable[HKey].Arg3 = (unsigned)pNewPlane21; + p->HTable[HKey].Arg1 = pNew2E; + p->HTable[HKey].Arg2 = pNew2T; + p->HTable[HKey].Arg3 = pNewPlane21; nNodesUnrefAdded++; diff --git a/src/bdd/reo/reoTransfer.c b/src/bdd/reo/reoTransfer.c index 752cd3d77..65d31d014 100644 --- a/src/bdd/reo/reoTransfer.c +++ b/src/bdd/reo/reoTransfer.c @@ -51,9 +51,9 @@ reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F ) { // search cache - use linear probing for ( HKey = hashKey2(p->Signature,F,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) - if ( p->HTable[HKey].Arg1 == (unsigned)F ) + if ( p->HTable[HKey].Arg1 == (reo_unit *)F ) { - pUnit = (reo_unit*) p->HTable[HKey].Arg2; + pUnit = p->HTable[HKey].Arg2; assert( pUnit ); // increment the edge counter pUnit->n++; @@ -93,8 +93,8 @@ reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F ) // might have been used. Make sure that its signature is different. for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ); p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = (unsigned)F; - p->HTable[HKey].Arg2 = (unsigned)pUnit; + p->HTable[HKey].Arg1 = (reo_unit *)F; + p->HTable[HKey].Arg2 = pUnit; } // increment the counter of nodes @@ -126,7 +126,7 @@ DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ) if ( pUnit->n != 1 ) { for ( HKey = hashKey2(p->Signature,pUnit,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) - if ( p->HTable[HKey].Arg1 == (unsigned)pUnit ) + if ( p->HTable[HKey].Arg1 == pUnit ) { bRes = (DdNode*) p->HTable[HKey].Arg2; assert( bRes ); @@ -179,8 +179,8 @@ DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ) // might have been used. Make sure that its signature is different. for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ); p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = (unsigned)pUnit; - p->HTable[HKey].Arg2 = (unsigned)bRes; + p->HTable[HKey].Arg1 = pUnit; + p->HTable[HKey].Arg2 = (reo_unit *)bRes; // add the DD to the referenced DD list in order to be able to store it in cache p->pRefNodes[p->nRefNodes++] = bRes; Cudd_Ref( bRes ); diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h index bdbc3d891..8b20daae8 100644 --- a/src/misc/extra/extra.h +++ b/src/misc/extra/extra.h @@ -341,7 +341,7 @@ extern int Extra_MmStepReadMemUsage( Extra_MmStep_t * p ); /*=== extraUtilMisc.c ========================================================*/ -/* finds the smallest integer larger of equal than the logarithm. */ +/* finds the smallest integer larger or equal than the logarithm */ extern int Extra_Base2Log( unsigned Num ); extern int Extra_Base2LogDouble( double Num ); extern int Extra_Base10Log( unsigned Num ); @@ -400,7 +400,15 @@ static inline void Extra_ProgressBarUpdate( ProgressBar * p, int nItemsCur, char /*=== extraUtilTruth.c ================================================================*/ -static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline int Extra_Float2Int( float Val ) { return *((int *)&Val); } +static inline float Extra_Int2Float( int Num ) { return *((float *)&Num); } +static inline int Extra_BitWordNum( int nBits ) { return nBits/(8*sizeof(unsigned)) + ((nBits%(8*sizeof(unsigned))) > 0); } +static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } + +static inline void Extra_TruthSetBit( unsigned * p, int Bit ) { p[Bit>>5] |= (1<<(Bit & 31)); } +static inline void Extra_TruthXorBit( unsigned * p, int Bit ) { p[Bit>>5] ^= (1<<(Bit & 31)); } +static inline int Extra_TruthHasBit( unsigned * p, int Bit ) { return (p[Bit>>5] & (1<<(Bit & 31))) > 0; } + static inline int Extra_WordCountOnes( unsigned uWord ) { uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); @@ -409,6 +417,13 @@ static inline int Extra_WordCountOnes( unsigned uWord ) uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); return (uWord & 0x0000FFFF) + (uWord>>16); } +static inline int Extra_TruthCountOnes( unsigned * pIn, int nVars ) +{ + int w, Counter = 0; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + Counter += Extra_WordCountOnes(pIn[w]); + return Counter; +} static inline int Extra_TruthIsEqual( unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; @@ -504,18 +519,26 @@ extern void Extra_TruthForall( unsigned * pTruth, int nVars, int iVar ); extern void Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ); extern void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ); extern int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ); -extern int Extra_TruthCountOnes( unsigned * pTruth, int nVars ); extern void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ); extern unsigned Extra_TruthHash( unsigned * pIn, int nWords ); extern unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ); /*=== extraUtilUtil.c ================================================================*/ +#ifndef ALLOC #define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#endif + +#ifndef FREE #define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#endif + +#ifndef REALLOC #define REALLOC(type, obj, num) \ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ ((type *) malloc(sizeof(type) * (num)))) +#endif + extern long Extra_CpuTime(); extern int Extra_GetSoftDataLimit(); diff --git a/src/misc/extra/extraUtil.h b/src/misc/extra/extraUtil.h deleted file mode 100644 index d3f432c2e..000000000 --- a/src/misc/extra/extraUtil.h +++ /dev/null @@ -1,60 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraUtil.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [Various reusable software utilities.] - - Description [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extraUtil.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __EXTRA_UTIL_H__ -#define __EXTRA_UTIL_H__ - -/*---------------------------------------------------------------------------*/ -/* Nested includes */ -/*---------------------------------------------------------------------------*/ - -#include -#include - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/*===========================================================================*/ -/* Various Utilities */ -/*===========================================================================*/ - - -/**AutomaticEnd***************************************************************/ - -#endif /* __EXTRA_UTIL_H__ */ diff --git a/src/misc/extra/extraUtilTruth.c b/src/misc/extra/extraUtilTruth.c index 6b10813c2..ab476f6fd 100644 --- a/src/misc/extra/extraUtilTruth.c +++ b/src/misc/extra/extraUtilTruth.c @@ -780,26 +780,6 @@ void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ) } } -/**Function************************************************************* - - Synopsis [Changes phase of the function w.r.t. one variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_TruthCountOnes( unsigned * pTruth, int nVars ) -{ - int nWords = Extra_TruthWordNum( nVars ); - int i, Counter = 0; - for ( i = 0; i < nWords; i++ ) - Counter += Extra_WordCountOnes( pTruth[i] ); - return Counter; -} - /**Function************************************************************* Synopsis [Computes minimum overlap in supports of cofactors.] diff --git a/src/opt/cut/cut60720.zip b/src/opt/cut/cut60720.zip deleted file mode 100644 index 86ad67262c23a35ba5204db31081153d20c351e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31142 zcmY(pV{k4^z@{17w)MoeZQHhWV&}xRZQHi(^n1C^X>lW>fc?}b=^{w0R=+? z0s(>oGOYGz%}1O-7KH=?`XB}Z0tW&DGI4XIx7^XPbJ$`>`XM0t-Jgd~PhyMBZW&VK zz||eo@8On5;@OEp#)=l*&^47Vq2jP#`0XVHOf=GN*dLq>g;2#0cb&$*j*|NNc&yv9 z#1Zg6Z0>IDf+|Y#F_#3a&BvO$Ih#OyJSr|$VB@g=V>J+3BV@rH6rj-KtY zr?^Eb%n|}^Mw*Cf5YYPXhgMdQO8PF?H=N&n!*3eC`}tRmpj5OrjhTM?u{a*c+ttT;gdV-pu*d%;_Wo0oW=N6f0VG> z?X8lXfyb&3L|#IWb67{@i-$y-c+g_il8t-aoVM?}Be^8c;(5i%pN)3w>^6v+svng( z256w;AHUPQ)wAv;l^{RqBj6K8S?sVsdtDzTydqJ1IR3=4*QVI9+YXRvpgvnxh{hsc zjbP(N=XB^W_o)*|y0R~dA3^s_9-^B`AwXpX<0*J?iP-RI;Mp7>wQ%i!mS9hpSMo`)gX zWhgIZ&^p0P10BTV`W-z+$qh=bj4o`cQ6Lpd{>IDeB=*ZIe-$?Z7B{nl{!ecBUH0}` z6NUn)F1Xe>zfw7Gmv<`I=Zg;Sb_MUFIw6)uL=@f$~!&yf4eaAr5w@o_8E5W_pd`(|>rgIDHO^CPY*gXRP7aO)JXI?*JZ2TnKxu-jLih&87;2QAe1FPks_`5ZPiz}|#=fJu` z!n%KWng8v6CNcmvI#X7Y!ozH*nFKL37&5i*4{6F*E*g-y;eCXLdG#zNH*Dez|9slw zcrx)6Us*>EM_KA3`}I3UlHtg%;7&DGs@YDJT)tu%WeQx5&0n)rF** zR)B7jdFPcnfeTvcggX@njf4rF>T4L5^9}=?;wtb7V5g$246nGF?Ju~nNWd}}raQ*r zWjSyQcvn2lkWBFFsGL|S{<@k;-2)*2@q=Q3vC`i_#rehLRFL@tg!yU35nvr%#s_eY zmhr>1Onb`FKrG^EVE+YA3d4PsTcAq33;C*@Ok2!0=KP?^E|L_?HNik6P%x$Ha3-wG zG-)T(^zWfjV}tKK1G;$wcKZkMDpalSKAs=mkP!&?esL-%_tsSU70o3iklI+e=@%#9 zo3aH!x|9|bBZ4*Ch`WUBdU=&#eg9eN>-B3@?VP(o{oHJtQ8|yCg3;BBI z!_IBM&jY3H)WkDu^+XpZc`qI1GMxHiPCcy!)@9ul4Xokp7o4>tVnMNcXFEX}*Jhps z+&3scIT_krS#uN>M+Ay?NkXWo0jAQMeiZMr1QH-z*{Zj4DZESJeCIw1tV1}^5T40J zD#%S#@jA>0&RPs)Xh7aJ*H=AopNQLO!I`LdT=@ldxpmYz z+X22&Qe#KoWQZXWyPsLhDcxAEmHQY;YVoKZi709lRevGJR%)Sh&!wg*_3AfIspYaa zghkhW$YS49r_q85m+A#CUD(K8GTb7VE1ePLA3?s!O6|+`k8JkOj`B#8w7GA;XkUiX zsUc|Z&QoD3^=IbVX#J*=W$mfmkK{oL38O~`_4hr!d#)_>+6rXw-p; zpdL3jmr3srjdqZ4OXMWP)P7MAWhyP2uRlcsW1VZ3$g?rd_!+>1Qa zDr8TN_98&@?5hoPbsEvEH$g=uSsAnfua#bX{OE-!WL6rZ>zZnT zs#QuVdDl(17F|x-E!tQOXf|=h-#y=aKsHvA=1_krSl2|5O_Kbcq7FkBIUlEzX0z^~ zAPypx6k%)2%F{sxP11`@p^HRW24)h~tS}&Ep?WAZ{DLRC#Dhc|<^Vw(Q03`n9WUA$ zX*TMg&IwwNs}(E&s?iQnaBVd0*`Od%NuvImsZevuHI*S(*7M?!A@9;s*T^qzpJotw zDk;s$ui2z1q<{I{qiC3+G4u;i;Bxdz?E7LYmV=t86-<92x@WisjTAXF?i#l}LtIL$ z#j2jG2?>SVGM_tIkT~zv?<(D}1d;GM5RncKqlIp5Am*}5HqFb;?D)*GOFg6ShTj%X zJGp#~H)`M$n!x%B>>2P}#d98i&K=?YC|g;H@Y|90o*83pj>{%1`LFl!jL(c|REcqw zvHNq(1KXo*LAlX)R5SyGDX`Y4>{d4N0EcT7-zuf7;lt>L8J~Kps*Tf_$uv#4NA5;U zFNt6kfGsJllkgl>Xah@J`5(r$ysMG|h?gz(11Krmn-!!!JkAsE!5l$#NK|S~Y>(c) z*Byy|6wbTuBzDu7B+r5^&V7@Y8L3oc=|8rN-B@t3d~JKWB;T&3W^pzhoSJOP4DKuk z0`BSj1WQY-y@;ivfaK1AXE*Thg<8cP!~k(W$USpl-Z8BgD6pE3V4`Li9yr3-eck$Y zklSEWoZn^T%lb%f_IfA!d)j%YRKGQf%aT=u@-YxMjl3_L{7UzBP-_#xoejiaoC>qG zEechWWdcgNjqHTw8Gm<=rtX#dYXgZfFlT#VkMZASJH$M2u(^UA_qpg5fz@l@7U60j zzGO>r)l*3`D_q9EK{PHOD8_)s=zAK0(5zF_;6spb(eV`Q;*_8{*x<{wU+`6zjx!A6 z4UxVzM?+0s5?!qK!>sTvZ5En>@eb(HkXE$6tyKyvF?Gr27~jn<9I{DJw}u8&eh z4XoR(QBzBFMNwphh%`DZ2Aqxms8+ix7}|ElQ{57ZEAlCZeCHgw#Gm}vXi~?1PHjI* zvevF+_LFzRz>Rw?+8hY2*7n_?l`WHF%ze%Eta#NKQ5q%AmcQ_lz!0S^x@l$;p5a*5 zpw5Fz&+zJ*U+pZ^E?odEIj_n+Mws%X;UB>S{i(Y$*SFtb|NkHSA9R?-{}ale6#w@J zi~OgRO;)sZ6mYrF{3H$p@EX9$i34TxtI&y6iOHySB$Ys~MKIKEqD5#aSe7~z8^eEl zduKi9JE{Z98w8QIb{pot@rL|L7SEA!HS{^zIoLUXuuAwd4f9Pb#f^4b?s7e8Fd&zR zhEW@MZS&k?_Xc}NDZo@H@eTvP0`Oo7>J`L?MTwp8JBNw96Z_GbZx?bn4c{u*2dRhz zY~h}W7y&HiB%P$Dlw=jPu*o3h4tEC`C!VLM; zpQt%#8Q`cIA<1dMLMnWB0s5ky9doZ%)c1QlY$1St``{Tt?2;u8=*lU}^vGyPwJmX| zEuHWri!YvdZ&CBZ*Qogqc$P|L*y_L}p{_At$ZU<>E}QAjdbXA=X-=|B^0q}=`gRbF zfzd1f!K$U7YVo>7fxuYzAK)O0!d@vfkxQKanb>Iv-LgZ(27LJPuK_&+mY)e5Dy6D* z@*4f|vh@+$&b;c3WPCMsjA+^zNP?`TSIUhB%gLSs#vyt(x;Z(~^5>=8$03&Vlk+hv zUuS(+l_f8E@lz3BgPWv%(w2?Oaq~r^>~w*9BP*NO6&HHh1r6hF(|D6qVzeF3^coGW z3IzRG$!Qo(tBHE#Pk4fuUAe!DlTs*5&Rs2X!}&CVfi;F;?R`jYfA-LGDZu0evIVRK zWXWs^N2s;y^h3`y_FMwG4(0<~d@9acs(}a=Vks*XtfBHC)c#~0xQ0M^i>86o)%@KK zg{uMGOPf&Oua$`WJkBXKtju{W34GRz*ZLnJ0>2EW$4W)<`;5OFf~474gki%*22zKw za(xM?Fgx4}N02WA_z}H1oR|6cs?w#^WEZ(52C;@ZfI7NdQjAbkF~NJlf>QUlKZM6fB$9MF?j&pU?Vm$EiTjZf7F3q-ZvP;v!$rUp#P*-JGjNk|Y#6f{yL< zC8KY2c$69)yS}LiUtJZ<>_W&*2bg*(vb;8HRz>@x(HlMA++0pqu%`4eIF)q0-#s9W zyI9Fpl2kv(J3M!?&{3Si#CKv_l%oBe$e*C3u0%OYbxG%Q0q9gX?}}}W{OcULZZ1O; z56A+G|5i3NI=s<$g|6CNc&<)`ci-uL<}o$yu#l(NmtN@QqbCHKLNhD3N->>%edr0r zD+y8PUS!!a!2e=%-!wK(XTGE3hyTsvUzdI9zuCn(XZ@ERnU{nw@F_{Uiq>kssX{tF z@)jKU@f^^H^QfEw_xg@RQ`?j8x^F5xn|t>@<#}pr2B&5N&T00)i4_j~Mj)k6%cz8W zfCE&xnc7;7%X7}mWxFymQ#P-YeKFEes)Y->LhH{e{ARhk!O7^Z$YZ7gN;kXFh3Vxnw|c!pUE{X9yz5rJFZ1!9e>eDb?ysbr1Y@v ziY$Zo=-p>8prb$Z=ugPe=*QXMb3#;5^@QexukxC}1$a?P1Sy6#TS25Ao0aA-shGW2 zw6FC^F+>|d!g`>sHE#$XT{BWB*2*_2PKNM}L&#~@17+1Ur3kckI>&{mZg0%!i_E&o zEI&vN{{Iea4(jCZp9B!%{?N^9h&}B=I7!30=84A>HS3zg@n|Pk4+@!(@BG{BT#BwN zoi8&#lG;b}V%kQVy4O|iF750|)__&Opj3CecBm=WE8`j}EU7&1%9Y6G(W-tJbc1OI z4W#O4M*w+a0w4Qsk(WNfH&oi2o?U)a`TKL4T&@1l;PTm%@?Dx$6<=$0sa=`ZG6?zv z$ySjfDxt`7G8oM}tqHO^K7=FFkMK|*Ol}zFxn2-Jo}U)Jo(?cBk{litM#dE*VaJGE zr$T9HP#hLd2#*ORVUHBGr6oS#^v2*z9DBGW8gmj!XY^n6CCUN&t?P8=8`u_;vvP4$ z2V->>G~qHNg|wxG^?0R*6v%GBw|9cn1G#vR|ZR)ru{2$he zB_^`!qr=&d{Kwh{JRl(0|D%@0JRFVeP3cW$v~>Q9rqKKl<9{7D;cIf%WA*YuQ)PhH zB7hw#RLHDfk-)%7mzXTHP(&vq7To)MPveuTv+&Cv8=;wO6L>XprzB1c9qQIF33flj z=5A(h5P+O;8nGdLYIihq_(G-$Tefjod|Top=ca=$Z$AGKXG8uO1n;<836UWN))>l` zFs9Wl72P{TOK7GIj+@SDDfO7u&4M|`31>*?Z&=I343j`_S19S!F=`r~ZRgY;PPV&pP< z>H1#`coWEVjA5pZ0aWm=T)s0T=+2rq>DrZPm3_eE-soPqx~(|wmi)3Ldyia%GA%3f zAd5uCJ=&Nk3GCz?=YNj(13bRTeAc2Q@bnAWK@D0c z7_8n5W#Uf2XmXdD{&~JOUc%A;)u?}w;=>=?StbI?bUPEELH1LER)5#6?b>ut!T-Z-h#$I0|1QvYsKIEbkZ~zLatU1Y4T6w%}$QBXX$?M_J z@FOklLiedM%x&&_lJ+kEVX0vb)6ep1FZ@xI~mfS25wJkBkHou-6Eni17?UaD^l) zX68{o@a}ujWb?4wW;8x zn9*BnIfsYZwfk(ls}8a1Dz3TW`*&LHsU&)l)QDdYzIuu=!w!XfmDQ0Mk&?4mZ=^r- zl95FjL-aHm49g%$V;w41;!Pu^amP0-QU75xei?_7B^fPALUMjgfry(QkRKHSv@&x_ zvCL}67jXowE{KE`$KDGHPg7OYsST;K8K)qvy&^+bvM$g3BzJb?B^_F>tS}yX{l`91 zz3f?H>&kY*yv(%ekt{1`#?GDE)_rwLmnxk-xz)52db0a|C9rez3omXAFCQ~aH=dA= z(`dAG*_vbvjFSKn(<*OK2$bz-?_vJP178!%d6_>${3J`_S{qF@R(skmu>;tPX^;*i ztM*|Rc_4wLZKYABmj<+gS~b;nT$*kE`^fXq6iZ@Ynp;~j8^B8OB7yze>v2y4S-`%* zb_)42;pv*!x^I3e;NH{}k;QTiJ68y?0A=j}ZQG6Na#J_pQhybGR%1??cDey@J$i5x zTP%isu&;^Sc0HfGn)qP4-&YR)Q;y6POS`r#1D3WN9PO}8q>C2VlELe(h%Do%+Fp(g zm1tZf0~YJG*t#a(z_;22b->;$Haerlc&fdryu%e0BHjkUyi`0^Oi~30v z@JGKlw*f&YJNReK3*V|)!~ty7b^Xi$jk;ktQsJ}I(Flo2mUXc4Dt0JDqB~u+!al3* zMmET7+udz$@a9b6FQ2$lSGksG>AqGjsd4RggscerGI$z+7E1(s3p4Dwt=vL`Dh*9! z-f|&#caS`Lwscmv^3X-A%tUfW1X8EwIsC*(`b;$lV;3ft(>UeuA+Vjl^O+{Pe{)_8 z8Jvb?S`l;OCctXp^!?SmEK`Q0>k+h(2XHRlm`2c=K+PMyB1QIPHQ-rimdS-;k9j6O zO}7b>^PmG|g&%sHs~sv_^9~-B*?}r52`LA4W?3C~HHz}it@Fne1uU_)Zh<#=vVJrr zFqdzJOoJ!1iewA1IxWfqx=F#G=#hXO$!*_7izWM_!zTM#$H#1tza}bfIDI54M)b6$ zKpo+cWZOqHVKx=*yjsn4<%MDl32yP~d!(a7+JGYD;J11#jymJ18#)-A_MN z^eOECd`O0l^Bg3l@jPCI+uIb52omm4s|Kp_LQdKh9`&wkW176X*KFQXpQR1w?GybA zee0gvhXoa%B_Y*)? z@wQl9=j>kBoos-C{+HuC`w$qrU${pGB6iD|0v?-3aFe-Md?MDq zoCBTNv2@e?wA2&c@P_m>F|~@DE8G66*-h zd+5@9pv#L0K#I7uv+;p$c#LELp~Ag*e7HTuG^0vmm_cMzT|l4rc-gN3=H8j(q^!;x z5siHZ6DPg2XS8;MEK(>!mOsoEgjFw%i<^CAg+sB$uc=+>t>XBIXE843I~VQh~^mi`%W z9605YL{uqOn}cX~8f5_DwfOP{0=@ZIK?BO=^b0}K>2DEYj<2wYFZj%;8g@+U%FPU( zBFnsWt|&@@NcpQYW*2F}A6xv1pGKxZ3PSvBZOUG({@DAL=0KSM8alROkc%_M3A?lK zSw0dC5V}u^MENL=es$o&ovYf)F~Mt6`xzb#aGvx8OMwgObrhi-8l>muIxdrAe_~qq z@btKkmr$7~CDzM0K$GndMQcP>q5{3Ay4O^&>_?oi8`>pE%_?k<=@JEqyf-b@*edi7 zdwFC8C@mxFq7-LusGufpSe8OZ+^^1`0f=CT31d<@+dvsB*G+_LD$bY4jN+#pT@0wB z6e@xObD^5+gRct&W9x<0W=hMsVl7VRm$|kAE5|le5GDj8v=E?Mhct0q!Z!!exhY|T zx}Ukdr%BJfDs&6$hdb$XdsCt?cy#&9mx)L^lCVZL$V!#Xl8!thEzhP!BOO-CQ-A{T z;9PKrU$Rr*$*R6&Q32x0e@M3I|tMSe_cB;F{MBS6}a z7IY=>)W!*6PuhJ#c$n+6|ia$}XXLKZ<6I zQG2a1etO5*s@`y#=rJmNC22gMce>oWyy9zm*V{Iac7mJtb28n$L7&B&R_x%lId*=G z3|KHIXSXnG$V^T&71Z8HOA~{`@4@?G@iM_N_L+d=!Nz+4w!E0;t z4b}Yv4QMDSbzVQWDw~VD6PnF1F(;BB(GxoyGiW+=@U`Lh4(j?4({X#II^xFmrTZ-eVywQ=T*hNsO~YMY6ja1-P@{~z zW_*38V{>Qnhnxiua*LaR(qkibS#Gg?-zsmcSy}*QS& z?mv8}jzCF23<=^Bi9}})U@~ybKB`eTT+1BVj9h-~q zVlecdhsh;q(%VOC4v7+@`r=c~)=EJ36wHMon5`LQA{| zy7M>vg8UzPGv10)NLH{2kCTr#LzZL?T{|6tj!~W?P^2o#?@sihJ zjuE18XXQ{49u=E~a&Nta_BfkpCE4?J<3I=R;YUf8cj)K}CA&C zKv70MIiH(K$XEr{RB_aQB)MCFIaI4I#oBJB`M1>=U3RkEz)27;^;NBwTMWFlZMBiK zyZpYXgfJIj$6?Y#+6>r1Hzs^oyYTRE9j|w5(c2}_r{$8nw={n_mV<~IEZmo(U>E(n z#sBPlzFauhbCIiuQDSwMtQUGH=_u3GZL8jgZ|2$gm(Ovt11C;Mz1Eo&NZx~jpzRA> zvBtOEAM@1qGVT3TL?8+*|6ZY|XX4;j-!b@SB@`zXH&eec=!gDNOs5;4K`8~gHJouZbTDqHqY!$V&(`zV*Wg(A^Id!( z9~rzZpipb0DCRJ6Mc9vUVJp&_m%n2eV#1K{#h_T@gveV4puj^b1Xp3847%IqYN9>vqak0$WgbDaT$;LG9=XiH1 z5Z&0N=NoC=5TUoPf$KZI!!1Q`eAo65VL80OEX&nF3c}Io0fvq zFH1f^!PIn_v2-QwqKs9&)5`#!-_syt1|4YbiYZ1!IG8-no$rEi2Vl6lKlvONxvmyN zMH6T@KFacl#Y-<3Js7MAd(@`%vW12P2=*977Tx9jk>Cg5)ywg7b0-Si7K%H+|K;Ai zIZwqx^PFKr6LT&Ng3eT6g^i4m(LU&XCFxfxH^a1x`=vqkcU1P% zC7^Rf2+kR01@cyFrv(T@kg@R7c(Bnkp#eB#x7LX0Y}^z~TFxz4=YPuW9efuvv*s-g z<_Z)74-E!^e{i|e(9ab&AyEvH!2%yT`2RGG*g^!>grM(dOY@-&c-IC0Av-Z~hOa~1 zgXZRH+_=KgZ2$NKZD_(SU{Hr~dAga1t3vFc`NaVgVzq&is%O2IPwQ(B-g zK~;r~Zyn`IUBqLAcL*@j7RRT$iJ>ff(Jw3ImSme=P?AL!42)tFp94ZvVda*N?Gdi< z5f&hM!*|0NBf0solv;ul(YR(?0T2)29BarTJhMsSQ`aXOvhm^P;qMp zpxe#dw`i7DQz=ScT)gN7r@)P$VQjGu2K3e12c54l-^7FUIHKoERmF=N$FitT^~&IGmlxa|hXB+9MC%4pF2U8oqPW-_4Le;^@p(uZLzZJJ4Oj*E`qyT~++Pm8R}T>;jwX3=Ur zPr0B;`*j(>`&qo=fcNUQnaC=kFRm=*^V(<6XO7xPxiV5~t*mrKKTpjjwPf&3GkuT5 ztAXVzJz9*9hXydJiQ3F-Q7J-_OyMO6L~9jP!q^XXvP$UG`}Wv2!ChQdRHY``q-5)k ztoAdPb2$c;wCA&{no1;S1QzN^*iMM{IBvlHQ^v{AlT_-13WcPiS*lxjL7S2uc@!b3 zOp&utuVFt{r0KNpEH0g*U*%--@F%63lQle7gptT?=I06)9}B+sj!{6P#q+NjZ-GvE zsnW<%cU#(kkoK;Uv0K;d`?LWz8+)GU5F<11Ct0O-z9nGKyf9&zCK((xN5Qb3xSxP4 zFu}=FnKuoht02I%k_W|p;fne1(!6%UO3tt<`tg#AO5Qg73?bnl*})R6(Q7!t^Tf=- zak|2r{qBs@-%4pf$sZFMT75LmOBIHvfGaUK>}2Y zD{03CN6I?j^fVM1p88^FNO(&^7nXMhzcEXLo8cJ>erQF)I|oA}HpkbeGZ-r=m#s)s zGSB286ux6E)4qn6Ta3V?#ilvY0Jst7eq{ScuC^!7fSjk%nkDBVCf3WLEb4Gz!kGJP zXJqC|f_Ds&OAgbYHRGKv1*Ur}gr=a5*`^>_7iM|B``#2;wHq2AOZ3+UcPb<)UDxN~?5?1hh-&5pfngXH?g9ODauFa|P-9}oXx5M=kQ z=>BC@;D5Y_(tnewjR*Cp%m46gEC&Px^MAaDoSCzQ*?%0@y;RteMEcdQ_#Jw>QN5S! zFMW;22@(ZJZUfh7dl?j-9dYAoay7X4#XAFjKWA<}uJyc8eejwa1fgHN+}%&wn))^% zyL5CUC|!kHZ#?<@U%s$`l3b1Cp!eA7i|(@DG)%_`BFhLJg5zaJ9tZZbiq;%Y^ptRe zbU3;xfZ_X{B^*V3xJz5nmFGqzu2OO|`@N^!t7(*m_Tp~RHG#i*i38XIujMS1sQzU} zIP+Nb)N+^{WT@Zz&QTPNQzCgWntcdyzNUv00sOH-*K!fRaPZ`5F=wqD?F>-Y?*CQ; zF|ZOWL8Cvz^WzWT9`Kk7+nZoJ)Wi$=!2gi_Af)q*BKW}336PPV4c;cm7|xyT)!oY| zKSDZ-fKnv%JTIM}v6+frZ8IW6F!b4cb#_?<7FD~-=Si*tjxAdnSM*^ zd85QYeFaQrcka(VBVN7O%V4H~MP6RtFKq0G4NWcm!6YnrktS;?UJ_}(Jz5$;w!vB7QPzV7%du-0jNsXdrq9g+ADlMe5q0apBlzG2V#> za*OE8z~?Md!8w_nN8l{4!t5Z%=(-cvE%vYn2fiPIU&y}^q6I_vDCFD7nR!AV=7eyn zuL%g?IN7Dd2o@S2auNI`4y2ku9}u7Gglu|Eb&vy1el0tOJY7xG>=X4rOH-xd=P0OF zTOJaP`YkzZfU!BTjhBWzZm_wvQog0;I@6cFEgr+TDth>;y6nJzNNXkKv zK%W!3uZ;}hLde|f0FY^N0$sgvc`SR$?sA!zY(y1;4@b$@GI7Ej>L3KOO*(h#W%!%k zxc!wCq5H4LYf_*sqZEo68g^ykWz32>gVJRPVRDn`WbF7fM>-@X@rljglnxJ9MK3=6 zg)waY?zOzxIr{<%|Xnzb6Hmb#)5^1L(mZcUuu?B zi;4BHMCjP4s!M`?d9Ef=DI#gAE##Ytd|{>DOj0jSq{B>(4ihgBK&S2Q!6$vm$LhrC zrVMuN>oqy4bFq!Q%b3=_=qH9IN)(t1qPz0C1TSMsehGxotc8;D<*bDg^ToOl zQ3MuXduleM4BU=%tP0D-F(;Rm5m^NW6o+G);-t}CXG7H zypy|fe3_!q%xA~W-S^kxEE{vT^kp%S{3!b%2pEsDu#>OK^gfS(6JqEuV=R;=0c)GJE~5U1hlNkaoy)JbdtFr1Ixtpgs7& zrb|pi=u5#Y`;1hiZAcQW1Kn8V1xqAbj=|FV|2`bTXX_?>_%eRq3nsdWE>teu18VYg z6VI!Yn7?EgnkjZ!!sfz4n<IfwEw}0Kom)#p zTQRA0qD4#a*0PFNXo0f^jW8cVA#7=7qKay}Rr_bt6kUzsDtWb2UA6so>Mx4Eh;ZYf z_q%IxJ$mQWm3{rpCD#+`OedKltHGj{a^XB&x6o?Br6O_cLTgg)38}PT7?n&2jG+Ms z{!c=^0qMkC27lE^03(+-WkFH$X$mZ4yjK-Vw`HE&hiPN}+oS~%NWQ}gs$u@>lt&{3 z6>t3#?>i9uUqE5PXs$dvP%7l(o8EM;89PNA*hN)$sGDR(57oxp4`Kx2hcW_#SLQ0g zb2fBFN;lp-aozrCtqps1Cqt;$$i?`7>kXR|xVpcciuEmz|-&zIKnuSmJ3-#=z!YeDcul&Z8RyyZMp8`` zMbn1utxQI=7w%?G`gyM{0!E#4n~G!Y@Z6S__XW67E1(!QsasHK2|m(GxZh>+ihIV& zGgAEmeo5SX?lJ!5^iP~`FtO^^{HB$h&i#P@k0iQP`^P%_20Pe@1O${|{eRDxk%0*?6WH|U7t?vu?X5=>F(_x<~B zJgvlWCYZ5=FC0S~X=jSc%0AcPGL+agG+q(3L^W>TJb$jwfz;CCFdWg9%nF7z@(Tp4Ao#2-Xg59mxy(~HT7 zm=bAiZe|~lw~z83cc{WAa8qLjkz>XtBxw6#;lpT+3r`PwDo2!P`5r{qlPTm^N+yiAGl{Z#2M~hP7?XM$(0{B z1lD;r`8N2xzhB;xS^ZRHWD3uTNB_M2cpyqZ6!H4_esy}rPZ923TO+wFqQhr^>SaSXaZr}_T*;H!#ot~g3EVtMVgkALg zxvIiKYaQZczKO~U=fNKwM>v1pza&2w45V*u{GsMA96+Dh``N^44LI(@s76*BE41JY5t#_T{DrCr2Iymmw zTY@w!rH>BQRh0~j2q(MUi)=8D1CHuMw-tRkBAuL8^EN*@!zaUo)t6nG!AQ{*J(6ac zPj(cRa9V*- z3%dOS=()IjpA)Qy@_;iPS3cuaRq4@o9c1X1t|QtQdy>&-O$jCn#AQ4JC5N`O0)a2{ zfe|DA*JiyygyT;@aV~@uyLW2E2!_P?d3WUaW{8)GYlOtG0gQ0N((~L^VHp7}`Jg|#(nFU>-OAqL z(z>DS6a(praJ))PF~Is{PHsmqK#tm)QyaMD3O}0p!5Z zINC*4i&(fbRtIgzEKy94@>sF5brhc#Q0X{+JHWV4`F2wBIE2< z4HH4*@~eCD~flQt>Pq&N#T|27Bt#INw{I^Aj!B%P~;v#QR9H+&nemLA+fQ9%!}&3RR!#|B#4`Bg>k!gxmq+EzPKqnT0oS|4}D#@vv70+m7B;96nV^G@Y@c zS&ZCd-&~WrBJV0}0P;3MCbcZnHfvFA>>yorLP@oS6bX8qNsLgMq#OPnMb4b!=3%R5 zfmU);kCMjnJ7dQA&HXBu*pmJqV^^U#?MSq=MsHlSVInp%uv)) zaLQJmi>t86kyKfSv$r!!fc}iv*Em@yT10)o#SNe?Aj*^P@9WN zZWOzGjEKH{DlNC0{Iqf5(pfvLWwZ|VfjQ~+Bv9I7Fs!VC)bu6XDd?t5FB{PKgyav` zzVOzpxVY`0GcydcvyhQK5Q9)5fiHr^r z+aT6-)62TQWlyN@FEvI3kZRc{g9;$qu=!HpTM#%mR0I)uyJ*303Q_7!F7pRu_{kk@ zKNlYC=jd_=40Rp{s55>(iwy6K5XP%+H1V~w$Q5L5@vq`Au%9O$+E-bQtEd%cos;l3 zllFy9g(o#(Lhn7M%<#%Evt(LY72N5Pv1*lni*Xut_3)SG=sJUxqukt7^bIw-3OzV8 z|DzRH2_|w)))9+-u??l-+YH}AygIcG6W59eE$VZ$jSO+n0FVZU9cfv-#UI8q)syXN zI>;z2&MC>Vuwlx>y-tSyEI()fen4=cQnw9uP7B)-nak-E)}Jrj5|wEVrzz1Jj%3v6 zX;xF?_yD3v`dm%^>5i2_J>(72f3}91U|%QG=)occ8nVbZw6rR^&yg|)y4J|le&v)F zfG(6Y3qWWrM6+pbG4LVtkrmHhdf2|RHCyXD+o-?zAq(sMPTM<_y!#tRAij@AOmf=- z1XPx3D5+L|=2N+h`)^oF%J=5+hwo7v4v|Pdl7qYSDRaYqN`|?=@Lfop4DtDBC|R+H zpn)i%7_*=Cre1Zb8+X}~h!KjBbAjrSA@IeeIB#5K0-<+VDp+&V6&ixShf&Dv5O@KC z+Oo~ztOzSM1kq(7RYf!P5oLn7huL* ziGE~!`>Ha!C>!qT4zzAn$=e0)y#N3c3k7?QKYRiT|LcQ)`YWX+k9fe_bAnzM&*Bry zJmR8tm;8+x&66zH$6{!uj$Yg;DsJTxx$xPAeOkFtDZ!0DIBWqP_CJA0gm9#n z8>E7a?=!I^=)!*Z1Ew4>MW2hG1CVGFQtM2Kmq$PG(I}ZvZRjFtW$sZj96m9}CJ#Yi zea{Pp)!N)KdjVwZ zfCjT^m7tickRs;65qLG9{5*UVl^(Cc$f7BlSO=qRah#>c;@CisbMS}^&7X)(Hhc)f zEAd(-r@1JoBl!3*f?f{1mx>H>MlXgVZK*z!YV9j>Eiv#qy8M6YI>#W%)^6Pvx@_CF zZQHhO+f`k*-DTUh?JnCkx^U~;-??Y+xUp|WMn*=i7%TEeu3T@-ch2#M`OZ;hkj{cS z84<21!LJ#v7$S=Gv!xGFqluJQFv8H@_C_|F{^|IF|79#)y4;8|>APqbos6x}hL~pS zCdtuf#wum&<#8jn3G`1ZE0XQktE&TxE^*QQLLj?VS zzW^XV+`sm2ilIup>vA;`XsQ%G;Fk!ifGO7W;0oZbMCej zzqk^nu#)0&!4T9->rL$H=zl?p(lZEERj$Z z&#iCa60&?^gB*s<7$5um?i$6K2RF)PpFO6749vzBW6Fmqz3dZ++g656QaQA!qIbr( z=VxM)LoG??aqJ5DqepN26;GY42-8c5g%^d}15l}QiC53!2`ec{LVc{v6c9!5spen8 zi7wp*rzLMLM3}`z97i-KQ*opoXdmf_Y@dtah@vKh8wY0GV9g~2OuRK@k(NZ$U?>Qw zvXyUVC&*4JF?N|EE04Qf!i9OO#=UABwz9iBJQx*-4<5^?)UfUJy)cB%_pKP1W1;*` z`SZR0gjfNGM)GA@x-`el81f1(2J#DC3I$;~)JZNIRy5}I#5lz@O_VRMy}Xz9)(NOb zc*J9~wzxbVXKti;Wm}2! z^R|vxfi$y-;L4&j0|Yr2A@#q;l#JjW!aJk*(%5P;rjY&E?b?%2amhgS%1rKOsq$uB ztJ-XaFP$fl?6u8au;A|`As@AwF-HGk#pQ2?_&Uu`gtD)$$S|ju!M^^(Ki$O27b#i& z3jTw+30$r333Heb5@t;)(h4P|iqToe9buo8(dxKx$(fpyWTOQ4&ZYO2%tUEnySxc zhul%+wxPVDPLEApU*23O8iD3+#5jr?t_ADGPxmyF9TC+4m+qj-YjGh6H~U-wZOZ}4A$^No@4c6GT?eY|M$3bD1_-e1~C~hOUpY+aSyR8f_NGioa097 zbLFc2QKltaHwy`MoBnfFiJEb%2;mYH21<|Vz2``sj-%+iMGe}EPC5y8!KK~6$3es`W!}=ma)ZEyG?CDWlf)GvjwR!OxQtYd$Vc4 z^q)w$Fb|EK*Yo^~KG}X20#82Kp%!zGG9pJgj`eaJt0h?%O0rKQqhq|QJ!F5LvoE&q zE-@@@=5i2k*&qcX+PtvFhtcvx<}YmoYzfaymU@>O0+SODd2th1wDDw*>eJ~ z2@tP$W=NEI_J&~h52=qBww`L%)h1y7j1>-1^+zQ(>1lOy_{OUZZ|~_`(6Yh1-wm;Y z*kO3NtWEXFI|b2Kor{w{4CYI@o2 zw<3J`1$cwGdcjzaNL12zs#necI?4hSPC;c}=*}_2G%_ZGr;r2`-nR;M|Czdxk#Mcw zH1-k*@fjsHW5@nvr?YHW!MZl#xb)d?xHCP3As9U+&rtxH@nA$7p_X-QkJm1}TJWMh zk%nR4{`7bcz)n)r5Pb0=sHT`<508Xs%cGWRAV$^D;73caHU}khV2rL=L_Ypfm$R5` zpyME+N0AuUU_py0SKMd4=oHZ)@IpQhPKL;y#5fdA%8+#2A*R6ymr#%;Prt8hCB#Re zSi)qkxNK|vsc^@!J-r`@ZTimHRy@?$*$e0>pJD1zEX?u6Ov{~EVw+jeGEc!4eIm4^^%$XO4K#R?kHT2_e6#lRf;+wlH~i6;R`UPE`=Njtr4rG0rbdZ8sr5W=1C652rI7x#XK~Zj;HzQ^8UL|1hw>!b<4$GWi}Vjk z7_#p4rX8LrC=dj90v#*YbNG8$nFP5p@K2gV3o!vmFT-hyJ7L~)t+khGJCt0bVYq#+ zdKN-Il8OqbKYp0;w6N$Um*Pteix z7+NYTFQ3#oylBBfY#cY{N`it6Mui5Lck*C(Et*+8(ATdg3_b$L#OP)3YpJTyL0slQ zaFyhOa1qU$p4X=Vm2l)L0AfGFg~iw&65;WWadIVkqRZ(*>Kjd8elZyR*wyh-ZnRI* zArxUFH87T_G6S}R)0>BN8`C5&3hcNRzYrunD#xldLThf0yD>C}%g1r#;pQeR5Tb=^foQ8CGGCfj;W-i&y;|2=MMTxR8OFWEN@O9GUHZqJe>l!HM}(#A9|#Twb_{K{(&Z8y{*tLjG@A|Ir&f? z=_m92k@IeVNRgbC=m7z<*&2YGN=bZ}0_Fp(R#<+KumTrCd+L=S;i?u{g9HKM+2m-v zN7pivy5f0iM`6g~Bdpd*Bi&W=Li$z;3nknJXTf<>{qiIdF0ENNK4ra9VFc7W={$c| zX}BlPQ5YmYKL;A*51aI~TwV>^ z%9INvCl9K-Z>Gof`A`>&U;S?0Kg&$YMhHoD%%Yd>4C2=`^Um?&W5kwVvcfioc_HK={1+kWS(q%JCtRIWv#55(zL4Hifjhc6e5Xc zq&sQ3eL^(U0jQ&Y!RM;@tiYLj3$?9{ke`$*ue|O6RY21ps+ozKKLZhyuWG0FdE51rR@) zu*n|CsqCbLCiNGPfU1G@eC(e^_Nk?&9(!z0Y$lGDS~AAn{FPiC((I8hrfTqs1hjGO zQHqn-3rg&s(8ym5GrcJiEvAS{NOjcMb@FiV*mQbG@%D~)M&f9*@Fhv-a;W>OsDhze zT~)<9@56Gu=@Hw}C$c-IRe6uRc)6D^IQ~J9xw@KGK)V9WrS)xE_6MCYq)%RrkeM0W z*KZ7k%?ffpM%C@cUrxHHfNd=SUeSwI5!`nHUq*Qo9HXtX&*VPyK|jx^r)z~Xu(;Wx87U3|Q-L6ZTMAddutSxJk8;2EB;Yy!7tt%pDz(u4wQYED}RITDp1ElTY2- zY8QsZDhW?<39z7TQBvYw*5|JsqCvp}4Fd_@(!G==#Ba4*WXkk9EMSR!797+2=+s+s z5-nh?%KAMOPCA|8gx~|>3bppGN#?XRjVhs8?3#_(7Do|rLzQ@BPrf#dj7MS7X3~3l z_n(9#iEahMER|sFpFy(3w%y1BvjW=$5|Te`hSO%3eLPDQw}a{fSi*OP39CrqC=ls7 zjj1>MLa=8-S?tbKMr8pFxOM5v9#1Ln{*wYc@^GQ>v_Rj+@Fdr*; zxKb(XRYf<0HFls2 zr~&^Ds#1?!&rpU2Q=9v#W|pIrIFdGPmBuyy@|@P9AnawWZhL>d(7tC=Oi+klh=_V; zqX+e@Ix72v)ow4>b_?&7rWKo1M5)JiNwZttF?+Pq8p9p?L(jbivsEZO+tz^PKxC<` zBM#I2dGl*M8PU@alsEh}kTrUGt)d@x0KlZNzJuJ&c`8Q<$6=Ot8yNpqH!gQh-5;E; z(i(pfR+O{As1>26;lr|rcTf9@*!lr0bQWrwThy{mjG7v*;du=%lop(}_MYYZMF-Wy zlItJ#`hQ@zt*&t|||Ox_JHean>sw&xVYl5f(8PVxZ6yJW$7mP+AuMk*~gbOq_|lwN!Tkwm#EA z%XYbMnU*DwH8v?1+t!$2TSvwBqr9TLL+ZSu!VB#4x0cV&@o}#2XE=PY^My1wP%e{O zN@r}Rt=kljSrM6=!=8-#>*`fzmyIK`?kjEhb>P8T|Q7!vOyvX z>`vEyOcvGhz-nFUM(|u%Gem!YSaGGZ%oA#`(vOH%076^#^l3yoQVC|MYKcAVm|X*O z(I1>-o9ndc?6$~=D_F50Q97j%C@06(ZWlievhnmfR&?nhXX=2en6clCa(BI+9AZ0f z^W)i`uGphmWcLt0IsQyVE{AoQR>da{h9lbXa~|}V0Y2C@?dCR7cz*8qJQ)RtReid$ z|0bp2SkFZW7CEocnpx>Ut*f+o!*c)_3zvJcD><-3UOaQ;JqJJUdGE!U@n59!pEQW8 z)T!B-IhT5q7cbnoclEnAe;&9x-K`lRD|{frr-2|tf9l10qZjkSlcRfjijAS&`e^MWe$wVb?0*cJf0 z>*%kJ71<<v8v za{!kXEfA$=whgVoWZ=NC*@V`1hg|k`h?TrX%PPChO!~Ua91D$t6=E6y{zF@XYW@OK z8iFg}pp4z3d9%D^66hXgn<_BB4#)vG@)+p}Y}ug@$3$(}owdz1x$hg4v~Q;`)M_v> zFQ!eAdLsj72$2O`T;5+x{$z<7a!OeeW0OC?Owj5`EC3cv+DARvC62bavvJ(mbpay1 zopRaD9|w!mnwu%2!6#(x!F?FoH~@hHgo*upc=FIA1UbL{A-XT@w&tiOoj(8&6{H^O zuFKE33YA9sYyHg45%Te}!L|k4USZ;@pT-NSiTeiFjN7i_)Y{EeOQZ#zgg}K73-7|BpCg_p8n#LLj)$${-%EP0j;npGp87?rkJDJw;dBhb0I2aJlP z^zS@m8~_4P6qlF*VP&H`I40Nk?){i-_Ma#SNp|f?eL{5Eg7YW&pG6Djj8$!tdy)Ik zNq}RpyP8HJ>OEjomyAfT)SBfUd5OX5tBeV zvy{CAjkqDM7L?~lzcf^4S#P8U+N^mif=vl*RSABA+a&Hil|R1KW47Go5jGwV0^wcH zvm`y<%~nF1)4hmqPRi#=3!dW3x|RU21lNmPP&i}}g#6X4+ z8faymUC2rL9N^fW8j9My9AoCGW1~TRsdG>gAZI=lLq}*a6E0Ux#nH!%UM0Xtq74>m zfPbGP;>7UzhYopK5~GOI;+O-1;3|IRC|i|O%VBF_aC?dhW4_E?mZRQ;hwJO4k1D`7 z0V(#NZI1&+G@OKmfETgE5PbsTAut%0gJHIY_^wE=0&Ws%-4~Wa0M8Hd85=7ZYREu7 zTqa1K<;FtKPU%uibALd-)=NkipchA2H4(^RXnbj3%yPz+sgxQpb~7=rN(7BRv`RA8 z`n$5RVaQdX&VXk&f=((D22;x_TdlADccl_jZ-b;FYGzaJ7H7$_ah-qlOK&W@8EQh8otWavIhtTsZEszrGJBGM1W%=!+ou18w8!2+lav6p4#p ziD|{w^P&%oG=v-b0>v=hXLs!NY-xWXh>*uh#4CHY?BvH>|7w@}pq{U-GKFn3s&O;b zg04BXsRwZ{Y52b=)Bdn@~b@s#GCrFSe?O>N>0{p6>BDS_$QO+u#%+LSB!@n?sf zO>x9F85^|2=Hpf7$V1L6=aW-v&DokcaHuL;fikUhFe{jO^AG z9yTssO6X!Lu8f|Z4$lr_eJ~E0O=>74a3oU12W~SBlLOH4c;w*GxE7r&k>9wh^>q5O z3NLas-_28~&rQgwab%-qNcYzfL zm_niWTkmcWkiQt9OK`zs2P{gTbtO3K!@>kP{7pD*a8t`-Aa? z83$Q=YPiGw^fU@s%{g5GvH9XtCkYWG+e-Y@d&8MPkAK84?PRJIZfs!>5ToyTvaN)P z2SL|#65HB)?w#ptV3!mdh({UD>SPHU{erVAF{Ca2sdDLT&r_S^D9H&379mWx2Yh6) z2gW340aOr|No0*BbQ*J3j59B9)?PMb`5Z*t&UJ(MjCoXfj~UdASw*%*{FDF+EOH6H zaR3ntIa<8zuX@pGs)fbHP5(X|-gTwmzNBxYwMpO9TZLtA@O+vu!B@$n)BMzbsw1>$ zdTW~o^O^cs5@f+!Y^0YcQ_G16Mb7wq+RZQQ+&RDGIJe=)z>5)T< zU1PkROoD}$J=isLtH15XRu9~aU+9a0lBf^bgy4IqC%3l#z^|oI;@AItX{H1+;9rD>)G;=Zn^} zhV|eD*W*@2`nnI-PZbbJVZ|dywTd-W%o#z~4o~6v9F5njm{Pt`()K94(m|uO&}p1m zX%1B$U!7c$Ta2Fz?V1C@1YT-V6Ba_6xX{WR?j`#wpteM zTwg(M@wCXL`#m%*XZCr*8zW~YPXQg{10y@rYV|luaaa&j9T*V<%B!)qWZk6Jw`8Pl zaUTsuGq^%TOHD~f$L3+$DGS0<7$aY_7>H^Pxm+O#3kuyaV@$qr|WVN!y>{_V`fe` zjJu^{a@paN9B!R@);M zV%$lsH&xh1^+e=67@-nR4+WjB4{~JPM?Jf0n`=XQj;z&+pL_<)>^U;^eL5f0{d5kF z0Y3*t&~^O#B&+ySN{E|)>xf<(+t<7$<4M;P+Et!1JFgSnPBo$x)wbYK^&|7oe2a>I zGHBY+H<3e!(1$XpAVyavs(DXWrC)~RqBcJcOumB_h%NDm3+-&)j6yyao#K;FsHYcZ zd18fh!1)q#hcWNM&v3DT_KgCM=!fC*%uQM$oKR5C==X_P@C44kz;WzrdxpzKu=gO4 z4W-$RElsck_reA>ciNe=qsUx>wF7x6WZo#cJipC5h_T5s$F2X4Fsj)o6Y(RuBi%KF z`-C>_>xFOx=^Sx`PrP`;KSJ;nf0`WAIsSgudfB4wHcjv(WB2H9!f z5zLzkqn%xT{q&&$&H2pB6K0k(J-JfPQ}Rz}evQL@oA!cMQTf*IL0X#xBbH^Eu7cO2 zVb`uM#Wz{^m232z(_7 zlS|K}rXH?w&227|j@ZeDC%2J?GLJGQ{#rDG#Y88V*MBI)kK+|izWUgO0ma~N#YXyKZdUhw6`?5Uw0ch-(#$i z$IVLcTbj5YSlHWqXM0)+BFe-F$zxB*NqV%2!yJW~EbOi1Ruod2Ym!a?<(^xb&82g6 z$x+%l1j!`ghv-%(YZF2(3}{5DWJV@!>ROBn`4Nt8ubuBT?c}M(z9`{($p_Jt%UyPT z(_iId(?w&Z8r7>Q(o|)JA2*LQEu8_-N9-XV&0L|F)H2=^cU#R#(rIUDtf{=DKKObj zr)nDSO-H{Z?`|TPJ2gLLU9@LXdkrFED`CMQhDsJyw}+otF3|9Tg*!79}}#U8tWFAEmqIl1R7;8S?NjSf>mM>L1z;Em{X%>z{y- zlz1f&4tK#8h5gII8J40S-oPjST+PkZc%22Lu}TPq-;E1iwF6aUJJg7Nx2%L3;VOB~1++dN&ah1X<`6M%QB*A?W3nyujBmBIX6 z$e{_LlUe6liuITF6E>Z2lB41ZL>m~rX9uS2EDN0^X_<5K*gNpSR2M@Z59sm71#k&i%{I}q)2;0^LV)cD^bko%9bfEAvkKImTS-2J;V`EFlrV(cqS~SAib82jlpDX+~jUQGBKKt zx5}Kg@$DX+P4qSp{JqWyX0nwel72E?5pXgGN*$%~%6qoF_Ytx;nRSg`$8wzJ1uLY5 z{A>ooHyAk_HSO!ir1d^E4ZTv4&Tl6-20y&b*FR}JiMkSGPJwH)0w`MrXi_MofH@!! zdto*(%lvv1K#KyJdD33g+y1G%5viLdSCJ*Cr?TM^mh%a6p1|HMNOsxWU*LgI0b{RIl+gxEn8-}(1f_?CB1MHDT;lP_#9LH>kI|$KnEONG-i(-y0K+TSARzDB^L)02 zGQJ?T!Y2y5^5JSnt;oDuVVe{=ShyVPK#pgU* z79zM->-0*^_tD-+N$0o0CZ6+V6W+T^M3O8 z*zT5Y2a#a+bI^ZXsuE{)5MbVK0@k#zJySbtRXWp+yGSi-e7-Bbz?8HtaNrQ

1IA&v!OgBVg<=2#Ha^LOQg`^(P#EC;x%Z9PWK!lRH( z*@@-8nABu$GIfz?VU&Kt?Erknkc6)20)KV!DNdoi%bF*MYxiWsZ1H3E4dX!EP(S89 zAMaYhabHJ&0RJSF{gLIH-EXHlyXBfAl<-&)Cx8ye-YKXwU1$-bH}|lcf=dOF!cA6k zd38HtPe#Rp=!Cs59hGq-tQ2Vps!Ix1y0V6kuOY z>^p$RN2OXPU+l9{0=o(OS!Hq{ct+%~tqyVMUpSe5o+n9=>cz7(`?6b;b#$Y#WZYkg@hPJpXP|RMn4gjkok%Y`VXk1HE5%iT?k#q0~xxP z6*pDcDM;JxJm@dq`_^9+qlmEsR>o6*ssmf$Ur_tLgRnG~=g^BElhIyWmlz%kqYcX8 zxaesQe8xu$R3uEN8{}S#d6+xYs}hv!!r$%ue7U`uJl$-D0cO%n#SCx09ar=&&4&Qb zFi{-M1fGX1ibT6lp$1bw7(>tC*Ak=(k`h)lat&n<*}r~36SNe@C4WdVYD>(t%FC%Z z?uLb<$s>u=L0%j*oGO6ccUBiI>Mr zFVbCcV^FeL8&kaiSP?27S_c6KvIu6ju8&&j`|pf)TpI21(^sLEHGWT)^pHCEBx4$g zzN^rr=2~Y!p{OU0{lWwmt@WLfb|Y6s`_og$7iC3LCx+_Y3tmo$)Ap{hmve?9jut)% zJPjp6Q4m)jE)KXDG{ihnKBC^~;Lr1XaIUQTtF#DCbr}6;?x0etfw^aTq569{P*>Kf zUjIeS$_3rhe_qj8_>ht8ble(NfQB{|vV(?wd*M+n)*HO^BcT>kpY|0WFeyCFEfC)i z5#MEqU(#Vd6G>i3AW+C-lF%W-H^+*Yn#jIam4af7VlwN~4#7*9waK+9_5_v7{#DkS z!4(RIIA;YmP01IF{YTGYcs4Mc2(8k zwrFiyr8yF-Z99F`;IE)4PCP+h?4VzDm`4=^J~#6BAlo^Lo3P_Ur)4Cz$!TJXZ9$HC zUY2#4NJ?k;V*=AE?IHJ>ODTA?+o;n*A^c2LZRPBfb6r8QPU-&bGDC8kSN%Vc*3n3? zeQEHJF|as3Syx|8KovZuWK*%ehc`x-L=R9h%GTd8gW@}mdwW2$;9h?1)xHCZY2}lx zRi}X)#pciWxHN#sl+cVUReBi=YY641e@&>su+6^RgW%NKc#i4VthT@;{TN*#-$~uDtm0@HLjU7+2MHVin(3Y)6xpW~!BL?ME5OuUSm@l z2GmE{qFG9bh>9HLu0`TNU! z#$&bxB@}=nLfirTW&P~=yxsvI9+6~z=sjn0XOC?q4fNX%4bK%#>ZWiBGpix2nfIQP zo1GhgUK|Ngsn_bL#FJ8~>*S@S`uRw~0<+^&sJH?KDR$gGPN=9 zoV5J~BVji5PQ;6p<1zDOHy3hdySl@ z&WY>xZ$5l;<4OIOxZW1j@}}JLLH&<#2R=z)NV?fHgq7?es0Hu&dTs#e73=aS*(`$n zUudH~&7}OqAQDItDAj;ZNFYwdvB@b>+Z3UNjd5+ITATjnfm4i+E|eBvpk=D~g3f7T zI~Lp}^V|$MX-^;;bCaY*db)>RKU=!KsH0_#2wvc1R!JP$@AsNxI+EFqPJb-TBR$1SMLg1JAb2IW? zaw19N{G!J|kBO_fpEGXEtnOlRnYYX?*2EhS3h`Iq=g1kG+}81i1U-+k-^l|qq?vWk7D<3DMu-c z@pMVdE*$-+Gl|M|WX?S5FqYL#I~{`cqT$uTTp*C`vI-S0BNU9UjRS?g3}ps;_5r=d z*hbwnmZ10!lpedbG3e$A8I!%#0zdYvZv^@NXa7?HQIMUnujc)*V3O!qLsOI*_~HJ& z6)nZsBWk~_%pS4n1?rL+xySmQE7B;MHdD?#BC0}!qz-Us@zPE*G1Je_P^Ful2W0g& zClBW&o{x*qyzL_Nby@HZ-_PvL&j?BFe03j7wQBaKMOzxh7v^3cK=1yxS$eT+#S_G5 zs7f(=!tS_$aD0MrJOyCJ65c+7Uit`i}TA=~R$5SU<7ckU}E0(yXwW6^)&^c1c}d zSWq#NA&Y(+MzTwlM%}YRr7O21)_LSLXs~m5Qj>%{DKhVA5nNfV$E#oqij-DC^D|lr^I|Q`Dm<`wX{%do!GDb;Lhp%xI3`9 zJy^OuxQr*O=}%OfNvyDjmU>ys7F}BuB*}+tnQUFF151L`U`x%Ad|hRtcrbIaNYdUh zvB;US43H!ed9HqkShAY(BfdQ*aY*f>19uy1`|u)tkTaQH({4ieKr$%T@eY+NVV1Su z--<`d9euGH*{BQ^zI$ogA!)^OW0e=ZATUJP?oWoSnyPG$$CmOEZxp+4o-#l2c)qH&I_$Z9*Z1>?^|KOn< zr@Edyn+uRDn@`1F7)GigT3VULQ}PZH``PLrXa7}qhXKGuS;G8FAbiv=N<>XKL7gD? zShaYtgzKSn{pv0;$8LJ3hKu+@N^yKMGqqW)^c=}V$4&6+V8fw;Cy2tI_DxN#V9X0$ zrZ{yLPcC%D$K7Wm==ShCuVgER4s3h7vMGUlTy`yTA3nO09;xgoIL-mJ#NpLjYmlM7 zkuZTH^6uUh0Z|XC4AL5v^FSK)+P)QN!?KL$VF{{#SEYkJ?cvrzHXwP6OUYyt6D$ow z_^D%t8}YMV*m-P-79B6_hEyhD0wozi!j*kPbVG(WY9uX4c4lYh(53!(x#I;#I@IWd z=RuzyJC<*(B7YHG=7!XCq?;>VfO2vxdxlR~jJ(@WSde;wczp)y0o3pp*aBGb<@qVg zRE@KVoChTrsOKHI^X^k5e2l|gA{ny6(Pwd|Wn15r7 z#D8Ib=`jCE{hM&>Zz_ZOztn&ATmR(#%}Vh%SHOqjQ-{j gT>$|8aZ$-jfqa){0KS7$VF7@?BO+tI4+8-FAMK?BCIA2c diff --git a/src/opt/cut/cut60721.zip b/src/opt/cut/cut60721.zip deleted file mode 100644 index d55ccfd07b50f99387f0147be28e0da1f7b6ab4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42872 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 10000000 ) { printf( "The problem is too large to be solved by \"fxu\" (%d cubes and %d cube pairs)\n", nCubesTotal, nPairsStore ); return NULL; } - +*/ // start the matrix p = Fxu_MatrixAllocate(); // create the column labels diff --git a/src/temp/ivy/ivy.h b/src/temp/ivy/ivy.h index a36c795b4..2409284ee 100644 --- a/src/temp/ivy/ivy.h +++ b/src/temp/ivy/ivy.h @@ -110,14 +110,17 @@ struct Ivy_Man_t_ int nTravIds; // the traversal ID int nLevelMax; // the maximum level Vec_Int_t * vRequired; // required times -// Vec_Ptr_t * vFanouts; // representation of the fanouts int fFanout; // fanout is allocated void * pData; // the temporary data void * pCopy; // the temporary data + Ivy_Man_t * pHaig; // history AIG if present // memory management Vec_Ptr_t * vChunks; // allocated memory pieces Vec_Ptr_t * vPages; // memory pages used by nodes Ivy_Obj_t * pListFree; // the list of free nodes + // timing statistics + int time1; + int time2; }; @@ -197,51 +200,54 @@ static inline int Ivy_ManNodeNum( Ivy_Man_t * p ) { return p->nO static inline int Ivy_ManHashObjNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR]+p->nObjs[IVY_LATCH]; } static inline int Ivy_ManGetCost( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+3*p->nObjs[IVY_EXOR]+8*p->nObjs[IVY_LATCH]; } -static inline Ivy_Type_t Ivy_ObjType( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type; } -static inline Ivy_Init_t Ivy_ObjInit( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Init; } -static inline int Ivy_ObjIsConst1( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Id == 0; } -static inline int Ivy_ObjIsGhost( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Id < 0; } -static inline int Ivy_ObjIsNone( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_NONE; } -static inline int Ivy_ObjIsPi( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_PI; } -static inline int Ivy_ObjIsPo( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_PO; } -static inline int Ivy_ObjIsCi( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_PI || pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsCo( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_PO || pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsAssert( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_ASSERT; } -static inline int Ivy_ObjIsLatch( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsAnd( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_AND; } -static inline int Ivy_ObjIsExor( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_EXOR; } -static inline int Ivy_ObjIsBuf( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_BUF; } -static inline int Ivy_ObjIsNode( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR; } -static inline int Ivy_ObjIsTerm( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_PI || pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT; } -static inline int Ivy_ObjIsHash( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR || pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsOneFanin( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT || pObj->Type == IVY_BUF || pObj->Type == IVY_LATCH; } +static inline Ivy_Type_t Ivy_ObjType( Ivy_Obj_t * pObj ) { return pObj->Type; } +static inline Ivy_Init_t Ivy_ObjInit( Ivy_Obj_t * pObj ) { return pObj->Init; } +static inline int Ivy_ObjIsConst1( Ivy_Obj_t * pObj ) { return pObj->Id == 0; } +static inline int Ivy_ObjIsGhost( Ivy_Obj_t * pObj ) { return pObj->Id < 0; } +static inline int Ivy_ObjIsNone( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_NONE; } +static inline int Ivy_ObjIsPi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI; } +static inline int Ivy_ObjIsPo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO; } +static inline int Ivy_ObjIsCi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsCo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsAssert( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_ASSERT; } +static inline int Ivy_ObjIsLatch( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsAnd( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND; } +static inline int Ivy_ObjIsExor( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_EXOR; } +static inline int Ivy_ObjIsBuf( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_BUF; } +static inline int Ivy_ObjIsNode( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR; } +static inline int Ivy_ObjIsTerm( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT; } +static inline int Ivy_ObjIsHash( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR || pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsOneFanin( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT || pObj->Type == IVY_BUF || pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsMarkA( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->fMarkA; } -static inline void Ivy_ObjSetMarkA( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); pObj->fMarkA = 1; } -static inline void Ivy_ObjClearMarkA( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); pObj->fMarkA = 0; } +static inline int Ivy_ObjIsMarkA( Ivy_Obj_t * pObj ) { return pObj->fMarkA; } +static inline void Ivy_ObjSetMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 1; } +static inline void Ivy_ObjClearMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 0; } -static inline void Ivy_ObjSetTravId( Ivy_Obj_t * pObj, int TravId ) { assert( !Ivy_IsComplement(pObj) ); pObj->TravId = TravId; } -static inline void Ivy_ObjSetTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); pObj->TravId = p->nTravIds; } -static inline void Ivy_ObjSetTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); pObj->TravId = p->nTravIds - 1; } -static inline int Ivy_ObjIsTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return (int )((int)pObj->TravId == p->nTravIds); } -static inline int Ivy_ObjIsTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return (int )((int)pObj->TravId == p->nTravIds - 1); } +static inline void Ivy_ObjSetTravId( Ivy_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } +static inline void Ivy_ObjSetTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } +static inline void Ivy_ObjSetTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } +static inline int Ivy_ObjIsTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); } +static inline int Ivy_ObjIsTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds - 1); } -static inline int Ivy_ObjId( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Id; } -static inline int Ivy_ObjPhase( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->fPhase; } -static inline int Ivy_ObjExorFanout( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->fExFan; } -static inline int Ivy_ObjRefs( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->nRefs; } -static inline void Ivy_ObjRefsInc( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); pObj->nRefs++; } -static inline void Ivy_ObjRefsDec( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); assert( pObj->nRefs > 0 ); pObj->nRefs--; } -static inline int Ivy_ObjFaninId0( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->pFanin0? Ivy_ObjId(Ivy_Regular(pObj->pFanin0)) : 0; } -static inline int Ivy_ObjFaninId1( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->pFanin1? Ivy_ObjId(Ivy_Regular(pObj->pFanin1)) : 0; } -static inline int Ivy_ObjFaninC0( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_IsComplement(pObj->pFanin0); } -static inline int Ivy_ObjFaninC1( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_IsComplement(pObj->pFanin1); } -static inline Ivy_Obj_t * Ivy_ObjFanin0( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_Regular(pObj->pFanin0); } -static inline Ivy_Obj_t * Ivy_ObjFanin1( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_Regular(pObj->pFanin1); } -static inline Ivy_Obj_t * Ivy_ObjChild0( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->pFanin0; } -static inline Ivy_Obj_t * Ivy_ObjChild1( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->pFanin1; } -static inline int Ivy_ObjLevel( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return pObj->Level; } -static inline int Ivy_ObjLevelNew( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return 1 + Ivy_ObjIsExor(pObj) + IVY_MAX(Ivy_ObjFanin0(pObj)->Level, Ivy_ObjFanin1(pObj)->Level); } +static inline int Ivy_ObjId( Ivy_Obj_t * pObj ) { return pObj->Id; } +static inline int Ivy_ObjTravId( Ivy_Obj_t * pObj ) { return pObj->TravId; } +static inline int Ivy_ObjPhase( Ivy_Obj_t * pObj ) { return pObj->fPhase; } +static inline int Ivy_ObjExorFanout( Ivy_Obj_t * pObj ) { return pObj->fExFan; } +static inline int Ivy_ObjRefs( Ivy_Obj_t * pObj ) { return pObj->nRefs; } +static inline void Ivy_ObjRefsInc( Ivy_Obj_t * pObj ) { pObj->nRefs++; } +static inline void Ivy_ObjRefsDec( Ivy_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } +static inline int Ivy_ObjFaninId0( Ivy_Obj_t * pObj ) { return pObj->pFanin0? Ivy_ObjId(Ivy_Regular(pObj->pFanin0)) : 0; } +static inline int Ivy_ObjFaninId1( Ivy_Obj_t * pObj ) { return pObj->pFanin1? Ivy_ObjId(Ivy_Regular(pObj->pFanin1)) : 0; } +static inline int Ivy_ObjFaninC0( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin0); } +static inline int Ivy_ObjFaninC1( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin1); } +static inline Ivy_Obj_t * Ivy_ObjFanin0( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin0); } +static inline Ivy_Obj_t * Ivy_ObjFanin1( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin1); } +static inline Ivy_Obj_t * Ivy_ObjChild0( Ivy_Obj_t * pObj ) { return pObj->pFanin0; } +static inline Ivy_Obj_t * Ivy_ObjChild1( Ivy_Obj_t * pObj ) { return pObj->pFanin1; } +static inline Ivy_Obj_t * Ivy_ObjChild0Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin0(pObj)? Ivy_NotCond(Ivy_ObjFanin0(pObj)->pEquiv, Ivy_ObjFaninC0(pObj)) : NULL; } +static inline Ivy_Obj_t * Ivy_ObjChild1Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin1(pObj)? Ivy_NotCond(Ivy_ObjFanin1(pObj)->pEquiv, Ivy_ObjFaninC1(pObj)) : NULL; } +static inline int Ivy_ObjLevel( Ivy_Obj_t * pObj ) { return pObj->Level; } +static inline int Ivy_ObjLevelNew( Ivy_Obj_t * pObj ) { return 1 + Ivy_ObjIsExor(pObj) + IVY_MAX(Ivy_ObjFanin0(pObj)->Level, Ivy_ObjFanin1(pObj)->Level); } static inline void Ivy_ObjClean( Ivy_Obj_t * pObj ) { int IdSaved = pObj->Id; @@ -415,10 +421,19 @@ extern void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_ extern void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ); extern Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ); extern int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +/*=== ivyHaig.c ==========================================================*/ +extern void Ivy_ManHaigStart( Ivy_Man_t * p ); +extern void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ); +extern void Ivy_ManHaigStop( Ivy_Man_t * p ); +extern void Ivy_ManHaigPrintStats( Ivy_Man_t * p ); +extern void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ); +extern void Ivy_ManHaigSimulate( Ivy_Man_t * p ); /*=== ivyIsop.c ==========================================================*/ extern int Ivy_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vCover, int fTryBoth ); /*=== ivyMan.c ==========================================================*/ extern Ivy_Man_t * Ivy_ManStart(); +extern Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ); extern void Ivy_ManStop( Ivy_Man_t * p ); extern int Ivy_ManCleanup( Ivy_Man_t * p ); extern int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ); diff --git a/src/temp/ivy/ivyBalance.c b/src/temp/ivy/ivyBalance.c index 0303485a9..3e8bd6d22 100644 --- a/src/temp/ivy/ivyBalance.c +++ b/src/temp/ivy/ivyBalance.c @@ -59,6 +59,9 @@ Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ) Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) ); Ivy_ManForEachPi( p, pObj, i ) pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) ); + // if HAIG is defined, trasfer the pointers to the PIs/latches +// if ( p->pHaig ) +// Ivy_ManHaigTrasfer( p, pNew ); // balance the AIG vStore = Vec_VecAlloc( 50 ); Ivy_ManForEachPo( p, pObj, i ) @@ -327,10 +330,18 @@ void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, i // get the two last nodes pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 ); pObj2 = Vec_PtrEntry( vSuper, RightBound ); + if ( Ivy_Regular(pObj1) == p->pConst1 || Ivy_Regular(pObj2) == p->pConst1 ) + return; // find the first node that can be shared for ( i = RightBound; i >= LeftBound; i-- ) { pObj3 = Vec_PtrEntry( vSuper, i ); + if ( Ivy_Regular(pObj3) == p->pConst1 ) + { + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } pGhost = Ivy_ObjCreateGhost( p, pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE ); if ( Ivy_TableLookup( p, pGhost ) ) { diff --git a/src/temp/ivy/ivyCut.c b/src/temp/ivy/ivyCut.c index 65ba4aacb..d918c96c0 100644 --- a/src/temp/ivy/ivyCut.c +++ b/src/temp/ivy/ivyCut.c @@ -889,7 +889,6 @@ Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves { static Ivy_Store_t CutStore, * pCutStore = &CutStore; Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; - Ivy_Man_t * pMan = p; Ivy_Obj_t * pLeaf; int i, k, iLeaf0, iLeaf1; diff --git a/src/temp/ivy/ivyCutTrav.c b/src/temp/ivy/ivyCutTrav.c new file mode 100644 index 000000000..ea57c9f59 --- /dev/null +++ b/src/temp/ivy/ivyCutTrav.c @@ -0,0 +1,473 @@ +/**CFile**************************************************************** + + FileName [ivyCutTrav.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCutTrav.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ); +static void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ); +static void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, int nLeaves, int nWords, Vec_Int_t * vStore ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes cuts for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Store_t * Ivy_NodeFindCutsTravAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves, int nNodeLimit, + Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront, Vec_Int_t * vStore, Vec_Vec_t * vBitCuts ) +{ + static Ivy_Store_t CutStore, * pCutStore = &CutStore; + Vec_Ptr_t * vCuts, * vCuts0, * vCuts1; + unsigned * pBitCut; + Ivy_Obj_t * pLeaf; + Ivy_Cut_t * pCut; + int i, k, nWords, nNodes; + + assert( nLeaves <= IVY_CUT_INPUT ); + + // find the given number of nodes in the TFI + Ivy_NodeComputeVolume( pObj, nNodeLimit - 1, vNodes, vFront ); + nNodes = Vec_PtrSize(vNodes); +// assert( nNodes <= nNodeLimit ); + + // make sure vBitCuts has enough room + Vec_VecExpand( vBitCuts, nNodes-1 ); + Vec_VecClear( vBitCuts ); + + // prepare the memory manager + Vec_IntClear( vStore ); + Vec_IntGrow( vStore, 64000 ); + + // set elementary cuts for the leaves + nWords = Extra_BitWordNum( nNodes ); + Vec_PtrForEachEntry( vFront, pLeaf, i ) + { + assert( Ivy_ObjTravId(pLeaf) < nNodes ); + // get the new bitcut + pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); + // set it as the cut of this leaf + Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); + } + + // compute the cuts for each node + Vec_PtrForEachEntry( vNodes, pLeaf, i ) + { + // skip the leaves + vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pLeaf) ); + if ( Vec_PtrSize(vCuts) > 0 ) + continue; + // add elementary cut + pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); + // set it as the cut of this leaf + Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); + // get the fanin cuts + vCuts0 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin0(pLeaf) ) ); + vCuts1 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin1(pLeaf) ) ); + assert( Vec_PtrSize(vCuts0) > 0 ); + assert( Vec_PtrSize(vCuts1) > 0 ); + // merge the cuts + Ivy_NodeFindCutsMerge( vCuts0, vCuts1, vCuts, nLeaves, nWords, vStore ); + } + + // start the structure + pCutStore->nCuts = 0; + pCutStore->nCutsMax = IVY_CUT_LIMIT; + // collect the cuts of the root node + vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pObj) ); + Vec_PtrForEachEntry( vCuts, pBitCut, i ) + { + pCut = pCutStore->pCuts + pCutStore->nCuts++; + pCut->nSize = 0; + pCut->nSizeMax = nLeaves; + pCut->uHash = 0; + for ( k = 0; k < nNodes; k++ ) + if ( Extra_TruthHasBit(pBitCut, k) ) + pCut->pArray[ pCut->nSize++ ] = Ivy_ObjId( Vec_PtrEntry(vNodes, k) ); + assert( pCut->nSize <= nLeaves ); + if ( pCutStore->nCuts == pCutStore->nCutsMax ) + break; + } + + // clean the travIds + Vec_PtrForEachEntry( vNodes, pLeaf, i ) + pLeaf->TravId = 0; + return pCutStore; +} + +/**Function************************************************************* + + Synopsis [Creates elementary bit-cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ) +{ + unsigned * pBitCut; + pBitCut = Vec_IntFetch( vStore, nWords ); + memset( pBitCut, 0, 4 * nWords ); + Extra_TruthSetBit( pBitCut, NodeId ); + return pBitCut; +} + +/**Function************************************************************* + + Synopsis [Compares the node by level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_CompareNodesByLevel( Ivy_Obj_t ** ppObj1, Ivy_Obj_t ** ppObj2 ) +{ + Ivy_Obj_t * pObj1 = *ppObj1; + Ivy_Obj_t * pObj2 = *ppObj2; + if ( pObj1->Level < pObj2->Level ) + return -1; + if ( pObj1->Level > pObj2->Level ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Mark all nodes up to the given depth.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolumeTrav1_rec( Ivy_Obj_t * pObj, int Depth ) +{ + if ( Ivy_ObjIsCi(pObj) || Depth == 0 ) + return; + Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin0(pObj), Depth - 1 ); + Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin1(pObj), Depth - 1 ); + pObj->fMarkA = 1; +} + +/**Function************************************************************* + + Synopsis [Collect the marked nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolumeTrav2_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( !pObj->fMarkA ) + return; + Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin0(pObj), vNodes ); + Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin1(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pTemp, * pFanin; + int i, nNodes; + // mark nodes up to the given depth + Ivy_NodeComputeVolumeTrav1_rec( pObj, 6 ); + // collect the marked nodes + Vec_PtrClear( vFront ); + Ivy_NodeComputeVolumeTrav2_rec( pObj, vFront ); + // find the fanins that are not marked + Vec_PtrClear( vNodes ); + Vec_PtrForEachEntry( vFront, pTemp, i ) + { + pFanin = Ivy_ObjFanin0(pTemp); + if ( !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + } + pFanin = Ivy_ObjFanin1(pTemp); + if ( !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + } + } + // remember the number of nodes in the frontier + nNodes = Vec_PtrSize( vNodes ); + // add the remaining nodes + Vec_PtrForEachEntry( vFront, pTemp, i ) + Vec_PtrPush( vNodes, pTemp ); + // unmark the nodes + Vec_PtrForEachEntry( vNodes, pTemp, i ) + { + pTemp->fMarkA = 0; + pTemp->TravId = i; + } + // collect the frontier nodes + Vec_PtrClear( vFront ); + Vec_PtrForEachEntryStop( vNodes, pTemp, i, nNodes ) + Vec_PtrPush( vFront, pTemp ); +// printf( "%d ", Vec_PtrSize(vNodes) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolume2( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pLeaf, * pPivot, * pFanin; + int LevelMax, i; + assert( Ivy_ObjIsNode(pObj) ); + // clear arrays + Vec_PtrClear( vNodes ); + Vec_PtrClear( vFront ); + // add the root + pObj->fMarkA = 1; + Vec_PtrPush( vNodes, pObj ); + Vec_PtrPush( vFront, pObj ); + // expand node with maximum level + LevelMax = pObj->Level; + do { + // get the node to expand + pPivot = NULL; + Vec_PtrForEachEntryReverse( vFront, pLeaf, i ) + { + if ( (int)pLeaf->Level == LevelMax ) + { + pPivot = pLeaf; + break; + } + } + // decrease level if we did not find the node + if ( pPivot == NULL ) + { + if ( --LevelMax == 0 ) + break; + continue; + } + // the node to expand is found + // remove it from frontier + Vec_PtrRemove( vFront, pPivot ); + // add fanins + pFanin = Ivy_ObjFanin0(pPivot); + if ( !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + Vec_PtrPush( vFront, pFanin ); + } + pFanin = Ivy_ObjFanin1(pPivot); + if ( pFanin && !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + Vec_PtrPush( vFront, pFanin ); + } + // quit if we collected enough nodes + } while ( Vec_PtrSize(vNodes) < nNodeLimit ); + + // sort nodes by level + Vec_PtrSort( vNodes, Ivy_CompareNodesByLevel ); + // make sure the nodes are ordered in the increasing number of levels + pFanin = Vec_PtrEntry( vNodes, 0 ); + pPivot = Vec_PtrEntryLast( vNodes ); + assert( pFanin->Level <= pPivot->Level ); + + // clean the marks and remember node numbers in the TravId + Vec_PtrForEachEntry( vNodes, pFanin, i ) + { + pFanin->fMarkA = 0; + pFanin->TravId = i; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Extra_TruthOrWords( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nWords ) +{ + int w; + for ( w = nWords-1; w >= 0; w-- ) + pOut[w] = pIn0[w] | pIn1[w]; +} +static inline int Extra_TruthIsImplyWords( unsigned * pIn1, unsigned * pIn2, int nWords ) +{ + int w; + for ( w = nWords-1; w >= 0; w-- ) + if ( pIn1[w] & ~pIn2[w] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Merges two sets of bit-cuts at a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, + int nLeaves, int nWords, Vec_Int_t * vStore ) +{ + unsigned * pBitCut, * pBitCut0, * pBitCut1, * pBitCutTest; + int i, k, c, w, Counter; + // iterate through the cut pairs + Vec_PtrForEachEntry( vCuts0, pBitCut0, i ) + Vec_PtrForEachEntry( vCuts1, pBitCut1, k ) + { + // skip infeasible cuts + Counter = 0; + for ( w = 0; w < nWords; w++ ) + { + Counter += Extra_WordCountOnes( pBitCut0[w] | pBitCut1[w] ); + if ( Counter > nLeaves ) + break; + } + if ( Counter > nLeaves ) + continue; + // the new cut is feasible - create it + pBitCutTest = Vec_IntFetch( vStore, nWords ); + Extra_TruthOrWords( pBitCutTest, pBitCut0, pBitCut1, nWords ); + // filter contained cuts; try to find containing cut + w = 0; + Vec_PtrForEachEntry( vCuts, pBitCut, c ) + { + if ( Extra_TruthIsImplyWords( pBitCut, pBitCutTest, nWords ) ) + break; + if ( Extra_TruthIsImplyWords( pBitCutTest, pBitCut, nWords ) ) + continue; + Vec_PtrWriteEntry( vCuts, w++, pBitCut ); + } + if ( c != Vec_PtrSize(vCuts) ) + continue; + Vec_PtrShrink( vCuts, w ); + // add the cut + Vec_PtrPush( vCuts, pBitCutTest ); + } +} + +/**Function************************************************************* + + Synopsis [Compute the set of all cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManTestCutsTravAll( Ivy_Man_t * p ) +{ + Ivy_Store_t * pStore; + Ivy_Obj_t * pObj; + Vec_Ptr_t * vNodes, * vFront; + Vec_Int_t * vStore; + Vec_Vec_t * vBitCuts; + int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; + int clk = clock(); + + vNodes = Vec_PtrAlloc( 100 ); + vFront = Vec_PtrAlloc( 100 ); + vStore = Vec_IntAlloc( 100 ); + vBitCuts = Vec_VecAlloc( 100 ); + + nNodeTotal = nNodeOver = 0; + nCutsTotal = -Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + pStore = Ivy_NodeFindCutsTravAll( p, pObj, 4, 60, vNodes, vFront, vStore, vBitCuts ); + nCutsCut = pStore->nCuts; + nCutsTotal += nCutsCut; + nNodeOver += (nCutsCut == IVY_CUT_LIMIT); + nNodeTotal++; + } + printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", + nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); + PRT( "Time", clock() - clk ); + + Vec_PtrFree( vNodes ); + Vec_PtrFree( vFront ); + Vec_IntFree( vStore ); + Vec_VecFree( vBitCuts ); + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/temp/ivy/ivyDfs.c b/src/temp/ivy/ivyDfs.c index 7246ec252..314bed8d5 100644 --- a/src/temp/ivy/ivyDfs.c +++ b/src/temp/ivy/ivyDfs.c @@ -119,7 +119,7 @@ Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ) Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) Ivy_ObjClearMarkA(pObj); // make sure network does not have dangling nodes - assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); +// assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); *pvLatches = vLatches; return vNodes; } diff --git a/src/temp/ivy/ivyHaig.c b/src/temp/ivy/ivyHaig.c new file mode 100644 index 000000000..7ce71a60c --- /dev/null +++ b/src/temp/ivy/ivyHaig.c @@ -0,0 +1,348 @@ +/**CFile**************************************************************** + + FileName [ivyHaig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [HAIG management procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyHaig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + HAIGing rules in working AIG: + - The node points to the representative of its class + - The pointer can be complemented if they have different polarity + + Choice node rules in HAIG: + - Equivalent nodes are linked into a ring + - Exactly one node in the ring has fanouts (this node is called representative) + - Pointer going from a node to the next node in the ring is complemented + if the first node is complemented, compared to the representative node + - The representative node always has non-complemented pointer to the next node + - New nodes are inserted into the ring before the representative node +*/ + +// returns the representative node of the given HAIG node +static inline Ivy_Obj_t * Ivy_HaigObjRepr( Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj) ); + // if the node has no equivalent or has fanout, it is representative + if ( pObj->pEquiv == NULL || Ivy_ObjRefs(pObj) > 0 ) + return pObj; + // the node belongs to a class and is not a representative + // complemented edge (pObj->pEquiv) tells if it is complemented w.r.t. the repr + for ( pTemp = Ivy_Regular(pObj->pEquiv); pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + if ( Ivy_ObjRefs(pTemp) > 0 ) + break; + // return the representative node + assert( pTemp != pObj ); + return Ivy_NotCond( pTemp, Ivy_IsComplement(pObj->pEquiv) ); +} + +// counts the number of nodes in the equivalence class +static inline int Ivy_HaigObjCountClass( Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pTemp; + int Counter; + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjRefs(pObj) > 0 ); + if ( pObj->pEquiv == NULL ) + return 1; + Counter = 1; + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + Counter++; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts HAIG for the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigStart( Ivy_Man_t * p ) +{ + assert( p->pHaig == NULL ); + p->pHaig = Ivy_ManDup( p ); +} + +/**Function************************************************************* + + Synopsis [Transfers the HAIG to the newly created manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ) +{ + Ivy_Obj_t * pObj; + int i; + assert( p->pHaig != NULL ); + Ivy_ManConst1(pNew)->pEquiv = Ivy_ManConst1(p)->pEquiv; + Ivy_ManForEachPi( pNew, pObj, i ) + pObj->pEquiv = Ivy_ManPi( p, i )->pEquiv; + pNew->pHaig = p->pHaig; +} + +/**Function************************************************************* + + Synopsis [Stops HAIG for the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigStop( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + assert( p->pHaig != NULL ); + Ivy_ManStop( p->pHaig ); + p->pHaig = NULL; + // remove dangling pointers to the HAIG objects + Ivy_ManForEachObj( p, pObj, i ) + pObj->pEquiv = NULL; +} + +/**Function************************************************************* + + Synopsis [Creates a new node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + assert( p->pHaig != NULL ); + assert( !Ivy_IsComplement(pObj) ); + if ( Ivy_ObjType(pObj) == IVY_BUF ) + pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); + else if ( Ivy_ObjType(pObj) == IVY_LATCH ) + pObj->pEquiv = Ivy_Latch( p->pHaig, Ivy_ObjChild0Equiv(pObj), pObj->Init ); + else if ( Ivy_ObjType(pObj) == IVY_AND ) + pObj->pEquiv = Ivy_And( p->pHaig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + else assert( 0 ); + // make sure the node points to the representative + pObj->pEquiv = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObj->pEquiv)), Ivy_IsComplement(pObj->pEquiv) ); +} + +/**Function************************************************************* + + Synopsis [Sets the pair of equivalent nodes in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ) +{ + Ivy_Obj_t * pObjOldHaig, * pObjNewHaig; + Ivy_Obj_t * pObjOldHaigR, * pObjNewHaigR; + int fCompl; + assert( p->pHaig != NULL ); + // get pointers to the classes + pObjOldHaig = pObjOld->pEquiv; + pObjNewHaig = Ivy_NotCond( Ivy_Regular(pObjNew)->pEquiv, Ivy_IsComplement(pObjNew) ); + // get regular pointers + pObjOldHaigR = Ivy_Regular(pObjOldHaig); + pObjNewHaigR = Ivy_Regular(pObjNewHaig); + // check if there is phase difference between them + fCompl = (Ivy_IsComplement(pObjOldHaig) != Ivy_IsComplement(pObjNewHaig)); + // if the class is the same, nothing to do + if ( pObjOldHaigR == pObjNewHaigR ) + return; + // combine classes + // assume the second node does not belong to a class + assert( pObjNewHaigR->pEquiv == NULL ); + // add this node to the class of pObjOldHaig + if ( pObjOldHaigR->pEquiv == NULL ) + pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ); + else + pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR->pEquiv, fCompl ); + pObjOldHaigR->pEquiv = pObjNewHaigR; + // update the class of the new node + Ivy_Regular(pObjNew)->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ^ Ivy_IsComplement(pObjNew) ); +} + +/**Function************************************************************* + + Synopsis [Count the number of choices and choice nodes in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManHaigCountChoices( Ivy_Man_t * p, int * pnChoices ) +{ + Ivy_Obj_t * pObj; + int nChoices, nChoiceNodes, Counter, i; + assert( p->pHaig != NULL ); + nChoices = nChoiceNodes = 0; + Ivy_ManForEachObj( p->pHaig, pObj, i ) + { + if ( Ivy_ObjIsTerm(pObj) || i == 0 ) + continue; + if ( Ivy_ObjRefs(pObj) == 0 ) + { + assert( pObj->pEquiv == Ivy_HaigObjRepr(pObj) ); + continue; + } + Counter = Ivy_HaigObjCountClass( pObj ); + nChoiceNodes += (int)(Counter > 1); + nChoices += Counter - 1; + } + *pnChoices = nChoices; + return nChoiceNodes; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigPrintStats( Ivy_Man_t * p ) +{ + int nChoices, nChoiceNodes; + assert( p->pHaig != NULL ); + printf( "Original : " ); + Ivy_ManPrintStats( p ); + printf( "HAIG : " ); + Ivy_ManPrintStats( p->pHaig ); + + // print choice node stats + nChoiceNodes = Ivy_ManHaigCountChoices( p, &nChoices ); + printf( "Total choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); + Ivy_ManHaigSimulate( p ); +} + + +/**Function************************************************************* + + Synopsis [Applies the simulation rules.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_Init_t Ivy_ManHaigSimulateAnd( Ivy_Init_t In0, Ivy_Init_t In1 ) +{ + assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); + if ( In0 == IVY_INIT_DC || In1 == IVY_INIT_DC ) + return IVY_INIT_DC; + if ( In0 == IVY_INIT_1 && In1 == IVY_INIT_1 ) + return IVY_INIT_1; + return IVY_INIT_0; +} + +/**Function************************************************************* + + Synopsis [Simulate HAIG using modified 3-valued simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigSimulate( Ivy_Man_t * p ) +{ + Vec_Int_t * vNodes, * vLatches; + Ivy_Obj_t * pObj; + Ivy_Init_t In0, In1; + int i, k, Counter; + assert( p->pHaig != NULL ); + p = p->pHaig; + // collect latches and nodes in the DFS order + vNodes = Ivy_ManDfsSeq( p, &vLatches ); + // set the PI values + Ivy_ManConst1(p)->Init = IVY_INIT_0; + Ivy_ManForEachPi( p, pObj, i ) + pObj->Init = IVY_INIT_0; + // set the latch values + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->Init = IVY_INIT_DC; + // perform several rounds of simulation + for ( k = 0; k < 5; k++ ) + { + // count the number of non-determinate values + Counter = 0; + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + Counter += ( pObj->Init == IVY_INIT_DC ); + printf( "Iter %d : Non-determinate = %d\n", k, Counter ); + // simulate the internal nodes + Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) + { + In0 = Ivy_InitNotCond( Ivy_ObjFanin0(pObj)->Init, Ivy_ObjFaninC0(pObj) ); + In1 = Ivy_InitNotCond( Ivy_ObjFanin1(pObj)->Init, Ivy_ObjFaninC1(pObj) ); + pObj->Init = Ivy_ManHaigSimulateAnd( In0, In1 ); + } + // simulate the latches + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->Level = Ivy_ObjFanin0(pObj)->Init; + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->Init = pObj->Level, pObj->Level = 0; + } + // free arrays + Vec_IntFree( vNodes ); + Vec_IntFree( vLatches ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/temp/ivy/ivyMan.c b/src/temp/ivy/ivyMan.c index 9839567f5..e3b8a5b89 100644 --- a/src/temp/ivy/ivyMan.c +++ b/src/temp/ivy/ivyMan.c @@ -68,6 +68,62 @@ Ivy_Man_t * Ivy_ManStart() return p; } +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ) +{ + Vec_Int_t * vNodes, * vLatches; + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj; + int i; + // collect latches and nodes in the DFS order + vNodes = Ivy_ManDfsSeq( p, &vLatches ); + // create the new manager + pNew = Ivy_ManStart(); + // create the PIs + Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); + Ivy_ManForEachPi( p, pObj, i ) + pObj->pEquiv = Ivy_ObjCreatePi(pNew); + // create the fake PIs for latches + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->pEquiv = Ivy_ObjCreatePi(pNew); + // duplicate internal nodes + Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) + pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + // add the POs + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(pObj) ); + // transform additional PI nodes into latches and connect them + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + { + assert( !Ivy_ObjFaninC0(pObj) ); + pObj->pEquiv->Type = IVY_LATCH; + pObj->pEquiv->Init = pObj->Init; + Ivy_ObjConnect( pNew, pObj->pEquiv, Ivy_ObjChild0Equiv(pObj), NULL ); + } + // shrink the arrays + Vec_PtrShrink( pNew->vPis, Ivy_ManPiNum(p) ); + // update the counters of different objects + pNew->nObjs[IVY_PI] -= Ivy_ManLatchNum(p); + pNew->nObjs[IVY_LATCH] += Ivy_ManLatchNum(p); + // free arrays + Vec_IntFree( vNodes ); + Vec_IntFree( vLatches ); + // check the resulting network + if ( !Ivy_ManCheck(pNew) ) + printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); + return pNew; +} + /**Function************************************************************* Synopsis [Stops the AIG manager.] @@ -81,6 +137,8 @@ Ivy_Man_t * Ivy_ManStart() ***********************************************************************/ void Ivy_ManStop( Ivy_Man_t * p ) { + if ( p->time1 ) { PRT( "Update lev ", p->time1 ); } + if ( p->time2 ) { PRT( "Update levR ", p->time2 ); } // Ivy_TableProfile( p ); // if ( p->vFanouts ) Ivy_ManStopFanout( p ); if ( p->vChunks ) Ivy_ManStopMemory( p ); diff --git a/src/temp/ivy/ivyMem.c b/src/temp/ivy/ivyMem.c index 6ca335419..09c73c490 100644 --- a/src/temp/ivy/ivyMem.c +++ b/src/temp/ivy/ivyMem.c @@ -89,7 +89,7 @@ void Ivy_ManAddMemory( Ivy_Man_t * p ) int i, nBytes; assert( sizeof(Ivy_Obj_t) <= 64 ); assert( p->pListFree == NULL ); - assert( (Ivy_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); +// assert( (Ivy_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); // allocate new memory page nBytes = sizeof(Ivy_Obj_t) * (1< 0 ); - return Ivy_Multi_rec( p, pArgs, nArgs, Type ); -} - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/temp/ivy/ivyObj.c b/src/temp/ivy/ivyObj.c index 3122c8c82..e8924b5b1 100644 --- a/src/temp/ivy/ivyObj.c +++ b/src/temp/ivy/ivyObj.c @@ -79,7 +79,6 @@ Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) assert( Ivy_TableLookup(p, pGhost) == NULL ); // get memory for the new object pObj = Ivy_ManFetchMemory( p ); -//printf( "Reusing %p.\n", pObj ); assert( Ivy_ObjIsNone(pObj) ); pObj->Id = Vec_PtrSize(p->vObjs); Vec_PtrPush( p->vObjs, pObj ); @@ -115,6 +114,9 @@ Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) // update node counters of the manager p->nObjs[Ivy_ObjType(pObj)]++; p->nCreated++; + // if HAIG is defined, create a corresponding node + if ( p->pHaig ) + Ivy_ManHaigCreateObj( p, pObj ); return pObj; } @@ -258,7 +260,6 @@ void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) // free the node Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); Ivy_ManRecycleMemory( p, pObj ); -//printf( "Recycling after delete %p.\n", pObj ); } else { @@ -312,7 +313,7 @@ void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) ***********************************************************************/ void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ) { - int nRefsOld; + int nRefsOld;//, clk; // the object to be replaced cannot be complemented assert( !Ivy_IsComplement(pObjOld) ); // the object to be replaced cannot be a terminal @@ -321,12 +322,16 @@ void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, in assert( !Ivy_ObjIsBuf(Ivy_Regular(pObjNew)) ); // the object cannot be the same assert( pObjOld != Ivy_Regular(pObjNew) ); + // if HAIG is defined, create the choice node + if ( p->pHaig ) + Ivy_ManHaigCreateChoice( p, pObjOld, pObjNew ); // if the new object is complemented or already used, add the buffer if ( Ivy_IsComplement(pObjNew) || Ivy_ObjIsLatch(pObjNew) || Ivy_ObjRefs(pObjNew) > 0 || Ivy_ObjIsPi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) pObjNew = Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pObjNew, NULL, IVY_BUF, IVY_INIT_NONE) ); assert( !Ivy_IsComplement(pObjNew) ); if ( fUpdateLevel ) { +//clk = clock(); // if the new node's arrival time is different, recursively update arrival time of the fanouts if ( p->fFanout && !Ivy_ObjIsBuf(pObjNew) && pObjOld->Level != pObjNew->Level ) { @@ -334,7 +339,9 @@ void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, in pObjOld->Level = pObjNew->Level; Ivy_ObjUpdateLevel_rec( p, pObjOld ); } +//p->time1 += clock() - clk; // if the new node's required time has changed, recursively update required time of the fanins +//clk = clock(); if ( p->vRequired ) { int ReqNew = Vec_IntEntry(p->vRequired, pObjOld->Id); @@ -344,6 +351,7 @@ void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, in Ivy_ObjUpdateLevelR_rec( p, pObjNew, ReqNew ); } } +//p->time2 += clock() - clk; } // delete the old object if ( fDeleteOld ) @@ -375,7 +383,6 @@ void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, in // recycle the object that was taken over by pObjOld Vec_PtrWriteEntry( p->vObjs, pObjNew->Id, NULL ); Ivy_ManRecycleMemory( p, pObjNew ); -//printf( "Recycling after patch %p.\n", pObjNew ); // if the new node is the buffer propagate it if ( p->fFanout && Ivy_ObjIsBuf(pObjOld) ) Vec_PtrPush( p->vBufs, pObjOld ); diff --git a/src/temp/ivy/ivyOper.c b/src/temp/ivy/ivyOper.c index af216e45a..8115ce4fd 100644 --- a/src/temp/ivy/ivyOper.c +++ b/src/temp/ivy/ivyOper.c @@ -208,6 +208,45 @@ Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * return Ivy_Or( p, Ivy_Or(p, Ivy_And(p, pA, pB), Ivy_And(p, pA, pC)), Ivy_And(p, pB, pC) ); } +/**Function************************************************************* + + Synopsis [Constructs the well-balanced tree of gates.] + + Description [Disregards levels and possible logic sharing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Ivy_Multi_rec( p, ppObjs, nObjs/2, Type ); + pObj2 = Ivy_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); + return Ivy_Oper( p, pObj1, pObj2, Type ); +} + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + assert( Type == IVY_AND || Type == IVY_EXOR ); + assert( nArgs > 0 ); + return Ivy_Multi_rec( p, pArgs, nArgs, Type ); +} + /**Function************************************************************* Synopsis [Implements the miter.] diff --git a/src/temp/ivy/ivySeq.c b/src/temp/ivy/ivySeq.c index 7cf55b69e..11660e42d 100644 --- a/src/temp/ivy/ivySeq.c +++ b/src/temp/ivy/ivySeq.c @@ -80,10 +80,6 @@ int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ) // stop if all nodes have been tried once if ( i > nNodes ) break; - if ( i == 8648 ) - { - int x = 0; - } // for each cut, try to resynthesize it nGain = Ivy_NodeRewriteSeq( p, pManRwt, pNode, fUseZeroCost ); if ( nGain > 0 || nGain == 0 && fUseZeroCost ) diff --git a/src/temp/player/playerToAbc.c b/src/temp/player/playerToAbc.c index 91994ca6c..ca84ded15 100644 --- a/src/temp/player/playerToAbc.c +++ b/src/temp/player/playerToAbc.c @@ -446,7 +446,7 @@ static inline int Abc_NodePlayerCost( int nFanins ) SeeAlso [] ***********************************************************************/ -static inline int Abc_NtkPlayerCostOne( int nCost, int RankCost ) +static inline int Abc_NtkPlayerCostOneLevel( int nCost, int RankCost ) { return (nCost / RankCost) + ((nCost % RankCost) > 0); } @@ -466,7 +466,8 @@ int Abc_NtkPlayerCost( Abc_Ntk_t * pNtk, int RankCost, int fVerbose ) { Abc_Obj_t * pObj; int * pLevelCosts, * pLevelCostsR; - int nFanins, nLevels, LevelR, Cost, CostTotal, CostTotalR, nRanksTotal, nRanksTotalR, i; + int Cost, CostTotal, CostTotalR, nRanksTotal, nRanksTotalR; + int nFanins, nLevels, LevelR, i; // compute the reverse levels Abc_NtkStartReverseLevels( pNtk ); // compute the costs for each level @@ -491,17 +492,19 @@ int Abc_NtkPlayerCost( Abc_Ntk_t * pNtk, int RankCost, int fVerbose ) { CostTotal += pLevelCosts[i]; CostTotalR += pLevelCostsR[i]; - nRanksTotal += Abc_NtkPlayerCostOne( pLevelCosts[i], RankCost ); - nRanksTotalR += Abc_NtkPlayerCostOne( pLevelCostsR[i], RankCost ); + nRanksTotal += Abc_NtkPlayerCostOneLevel( pLevelCosts[i], RankCost ); + nRanksTotalR += Abc_NtkPlayerCostOneLevel( pLevelCostsR[i], RankCost ); } assert( CostTotal == CostTotalR ); // print out statistics if ( fVerbose ) { for ( i = 1; i <= nLevels; i++ ) + { printf( "Level %2d : Cost = %7d. Ranks = %6.3f. Cost = %7d. Ranks = %6.3f.\n", i, pLevelCosts[i], ((double)pLevelCosts[i])/RankCost, pLevelCostsR[nLevels+1-i], ((double)pLevelCostsR[nLevels+1-i])/RankCost ); + } printf( "TOTAL : Cost = %7d. Ranks = %6d. RanksR = %5d. RanksBest = %5d.\n", CostTotal, nRanksTotal, nRanksTotalR, nLevels ); }