diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2006-04-07 08:01:00 -0700 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2006-04-07 08:01:00 -0700 |
commit | 3f4fc5e4507f7fb9df431fc116529b4c209ab97c (patch) | |
tree | d468f472a10aa98499f98c639447b7838e495476 /src | |
parent | 8e5398c501a873dffcb562a11bc19e630872c931 (diff) | |
download | abc-3f4fc5e4507f7fb9df431fc116529b4c209ab97c.tar.gz abc-3f4fc5e4507f7fb9df431fc116529b4c209ab97c.tar.bz2 abc-3f4fc5e4507f7fb9df431fc116529b4c209ab97c.zip |
Version abc60407
Diffstat (limited to 'src')
85 files changed, 6185 insertions, 422 deletions
diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index c68c74e2..e0f0df99 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -154,6 +154,7 @@ struct Abc_Ntk_t_ Abc_NtkFunc_t ntkFunc; // functionality of the network char * pName; // the network name char * pSpec; // the name of the spec file if present + int Id; // network ID // name representation stmm_table * tName2Net; // the table hashing net names into net pointer stmm_table * tObj2Name; // the table hashing PI/PO/latch pointers into names @@ -210,7 +211,7 @@ struct Abc_Ntk_t_ // maximum/minimum operators #define ABC_MIN(a,b) (((a) < (b))? (a) : (b)) #define ABC_MAX(a,b) (((a) > (b))? (a) : (b)) -#define ABC_INFINITY (10000000) +#define ABC_INFINITY (100000000) // transforming floats into ints and back static inline int Abc_Float2Int( float Val ) { return *((int *)&Val); } @@ -439,10 +440,10 @@ extern bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ); extern bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ); extern bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); /*=== abcCollapse.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fVerbose ); +extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ); /*=== abcCut.c ==========================================================*/ -extern void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fMulti ); -extern void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fMulti ); +extern void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ); +extern void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ); extern void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fFirst ); extern void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ); extern void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ); @@ -492,6 +493,8 @@ extern int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ); extern int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode ); /*=== abcMiter.c ==========================================================*/ extern Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); +extern Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); +extern Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ); extern Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 ); extern Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ); extern Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk ); @@ -554,7 +557,7 @@ extern Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ); /*=== abcNtbdd.c ==========================================================*/ extern Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ); extern Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ); -extern DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fLatchOnly ); +extern DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fLatchOnly, int fReorder, int fVerbose ); extern void Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk ); /*=== abcNtk.c ==========================================================*/ extern Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func ); @@ -584,7 +587,7 @@ extern void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, extern void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes ); extern void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ); /*=== abcProve.c ==========================================================*/ -extern int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, int nConfLimit, int nImpLimit, int fUseRewrite, int fUseFraig, int fVerbose ); +extern int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pParams ); /*=== abcReconv.c ==========================================================*/ extern Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ); extern void Abc_NtkManCutStop( Abc_ManCut_t * p ); @@ -607,8 +610,8 @@ extern int Abc_NodeRef_rec( Abc_Obj_t * pNode ); extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); extern DdNode * Abc_NtkRenodeDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld ); /*=== abcSat.c ==========================================================*/ -extern int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nConfLimit, int nImpLimit, int fVerbose ); -extern solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk ); +extern int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nConfLimit, int nImpLimit, int fJFront, int fVerbose ); +extern solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fJFront ); /*=== abcSop.c ==========================================================*/ extern char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName ); extern char * Abc_SopStart( Extra_MmFlex_t * pMan, int nCubes, int nVars ); @@ -623,6 +626,7 @@ extern char * Abc_SopCreateNor( Extra_MmFlex_t * pMan, int nVars ); extern char * Abc_SopCreateXor( Extra_MmFlex_t * pMan, int nVars ); extern char * Abc_SopCreateXorSpecial( Extra_MmFlex_t * pMan, int nVars ); extern char * Abc_SopCreateNxor( Extra_MmFlex_t * pMan, int nVars ); +extern char * Abc_SopCreateMux( Extra_MmFlex_t * pMan ); extern char * Abc_SopCreateInv( Extra_MmFlex_t * pMan ); extern char * Abc_SopCreateBuf( Extra_MmFlex_t * pMan ); extern int Abc_SopGetCubeNum( char * pSop ); @@ -672,6 +676,19 @@ extern void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk ); extern void Abc_NodeSetReverseLevel( Abc_Obj_t * pObj, int LevelR ); extern int Abc_NodeReadReverseLevel( Abc_Obj_t * pObj ); extern int Abc_NodeReadRequiredLevel( Abc_Obj_t * pObj ); +/*=== abcTrace.c ==========================================================*/ +extern void Abc_HManStart(); +extern void Abc_HManStop(); +extern int Abc_HManIsRunning(); +extern int Abc_HManGetNewNtkId(); +extern void Abc_HManAddObj( Abc_Obj_t * pObj ); +extern void Abc_HManAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); +extern void Abc_HManXorFaninC( Abc_Obj_t * pObj, int iFanin ); +extern void Abc_HManRemoveFanins( Abc_Obj_t * pObj ); +extern void Abc_HManAddProto( Abc_Obj_t * pObj, Abc_Obj_t * pProto ); +extern void Abc_HManMapAddEqu( Abc_Obj_t * pObj, Abc_Obj_t * pEqu ); +extern int Abc_HManPopulate( Abc_Ntk_t * pNtk ); +extern int Abc_HManVerify( int NtkIdOld, int NtkIdNew ); /*=== abcUtil.c ==========================================================*/ extern void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk ); extern int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ); diff --git a/src/base/abc/abcAig.c b/src/base/abc/abcAig.c index f2f50f77..7eb62416 100644 --- a/src/base/abc/abcAig.c +++ b/src/base/abc/abcAig.c @@ -807,6 +807,7 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, i Abc_AigAndDelete( pMan, pFanout ); // remove the fanins of the old fanout Abc_ObjRemoveFanins( pFanout ); + Abc_HManRemoveFanins( pFanout ); // recreate the old fanout with new fanins and add it to the table Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout ); assert( Abc_AigNodeIsAcyclic(pFanout, pFanout) ); diff --git a/src/base/abc/abcFanio.c b/src/base/abc/abcFanio.c index 59dff196..60e847d0 100644 --- a/src/base/abc/abcFanio.c +++ b/src/base/abc/abcFanio.c @@ -50,6 +50,7 @@ void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninR->vFanouts, pObj->Id ); if ( Abc_ObjIsComplement(pFanin) ) Abc_ObjSetFaninC( pObj, Abc_ObjFaninNum(pObj)-1 ); + Abc_HManAddFanin( pObj, pFanin ); } diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c index cb20cec3..da50a9aa 100644 --- a/src/base/abc/abcFunc.c +++ b/src/base/abc/abcFunc.c @@ -24,6 +24,8 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +#define ABC_MUX_CUBES 100000 + static int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ); //////////////////////////////////////////////////////////////////////// @@ -205,6 +207,7 @@ void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect ) { Abc_Obj_t * pNode; + Extra_MmFlex_t * pManNew; DdManager * dd = pNtk->pManFunc; DdNode * bFunc; Vec_Str_t * vCube; @@ -217,10 +220,8 @@ int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect ) assert( Abc_NtkIsBddLogic(pNtk) ); Cudd_zddVarsFromBddVars( dd, 2 ); - // allocate the new manager - pNtk->pManFunc = Extra_MmFlexStart(); - // update the network type - pNtk->ntkFunc = ABC_FUNC_SOP; + // create the new manager + pManNew = Extra_MmFlexStart(); // go through the objects vCube = Vec_StrAlloc( 100 ); @@ -228,17 +229,30 @@ int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect ) { assert( pNode->pData ); bFunc = pNode->pData; - pNode->pData = Abc_ConvertBddToSop( pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), vCube, fMode ); - if ( pNode->pData == NULL ) + pNode->pNext = (Abc_Obj_t *)Abc_ConvertBddToSop( pManNew, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), vCube, fMode ); + if ( pNode->pNext == NULL ) { + Extra_MmFlexStop( pManNew, 0 ); + Abc_NtkCleanNext( pNtk ); +// printf( "Converting from BDDs to SOPs has failed.\n" ); Vec_StrFree( vCube ); - Cudd_Quit( dd ); return 0; } - Cudd_RecursiveDeref( dd, bFunc ); } Vec_StrFree( vCube ); + // update the network type + pNtk->ntkFunc = ABC_FUNC_SOP; + // set the new manager + pNtk->pManFunc = pManNew; + // transfer from next to data + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Cudd_RecursiveDeref( dd, pNode->pData ); + pNode->pData = pNode->pNext; + pNode->pNext = NULL; + } + // check for remaining references in the package Extra_StopManager( dd ); return 1; @@ -339,6 +353,13 @@ char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFun assert( 0 ); } + if ( nCubes > ABC_MUX_CUBES ) + { + Cudd_RecursiveDerefZdd( dd, zCover ); + printf( "The number of cubes exceeded the predefined limit (%d).\n", ABC_MUX_CUBES ); + return NULL; + } + // allocate memory for the cover if ( pMan ) pSop = Extra_MmFlexEntryFetch( pMan, (nFanins + 3) * nCubes + 1 ); @@ -468,6 +489,8 @@ void Abc_CountZddCubes_rec( DdManager * dd, DdNode * zCover, int * pnCubes ) (*pnCubes)++; return; } + if ( (*pnCubes) > ABC_MUX_CUBES ) + return; extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 ); Abc_CountZddCubes_rec( dd, zC0, pnCubes ); Abc_CountZddCubes_rec( dd, zC1, pnCubes ); diff --git a/src/base/abc/abcNetlist.c b/src/base/abc/abcNetlist.c index d289cd35..737d63c2 100644 --- a/src/base/abc/abcNetlist.c +++ b/src/base/abc/abcNetlist.c @@ -62,7 +62,7 @@ Abc_Ntk_t * Abc_NtkNetlistToLogic( Abc_Ntk_t * pNtk ) Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pFanin)->pCopy ); // collect the CO nodes Abc_NtkFinalize( pNtk, pNtkNew ); - // fix the problem with CO pointing directing to CIs + // fix the problem with CO pointing directly to CIs Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // duplicate EXDC if ( pNtk->pExdc ) @@ -101,7 +101,8 @@ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk, int fDirect ) } else if ( Abc_NtkIsBddLogic(pNtk) ) { - Abc_NtkBddToSop(pNtk, fDirect); + if ( !Abc_NtkBddToSop(pNtk, fDirect) ) + return NULL; pNtkNew = Abc_NtkLogicSopToNetlist( pNtk ); Abc_NtkSopToBdd(pNtk); } @@ -157,7 +158,10 @@ Abc_Ntk_t * Abc_NtkLogicSopToNetlist( Abc_Ntk_t * pNtk ) assert( Abc_NtkLogicHasSimpleCos(pNtk) ); if ( Abc_NtkIsBddLogic(pNtk) ) - Abc_NtkBddToSop(pNtk,0); + { + if ( !Abc_NtkBddToSop(pNtk,0) ) + return NULL; + } // start the netlist by creating PI/PO/Latch objects pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc ); diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c index 0692819b..60ad2412 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -50,6 +50,7 @@ Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func ) memset( pNtk, 0, sizeof(Abc_Ntk_t) ); pNtk->ntkType = Type; pNtk->ntkFunc = Func; + pNtk->Id = !Abc_HManIsRunning()? 0 : Abc_HManGetNewNtkId(); // start the object storage pNtk->vObjs = Vec_PtrAlloc( 100 ); pNtk->vLats = Vec_PtrAlloc( 100 ); @@ -136,6 +137,14 @@ Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_ Vec_PtrPush( pNtkNew->vCis, pObjNew ); Vec_PtrPush( pNtkNew->vCos, pObjNew ); } + if ( Abc_NtkIsStrash(pNtk) && Abc_HManIsRunning() ) + { + Abc_HManAddProto( Abc_NtkConst1(pNtk)->pCopy, Abc_NtkConst1(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Abc_HManAddProto( pObj->pCopy, pObj ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_HManAddProto( pObj->pCopy, pObj ); + } // transfer the names Abc_NtkDupCioNamesTable( pNtk, pNtkNew ); Abc_ManTimeDup( pNtk, pNtkNew ); @@ -407,6 +416,11 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } + if ( Abc_NtkIsStrash(pNtk) && Abc_HManIsRunning() ) + { + Abc_AigForEachAnd( pNtk, pObj, i ) + Abc_HManAddProto( pObj->pCopy, pObj ); + } // duplicate the EXDC Ntk if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); diff --git a/src/base/abc/abcObj.c b/src/base/abc/abcObj.c index d6adfeb2..0ffe3298 100644 --- a/src/base/abc/abcObj.c +++ b/src/base/abc/abcObj.c @@ -50,6 +50,8 @@ Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) pObj->pNtk = pNtk; pObj->Type = Type; pObj->Id = -1; + if ( pNtk->ntkType != ABC_NTK_NETLIST ) + Abc_HManAddObj( pObj ); return pObj; } diff --git a/src/base/abc/abcSop.c b/src/base/abc/abcSop.c index 1e59b17b..d5cc65f1 100644 --- a/src/base/abc/abcSop.c +++ b/src/base/abc/abcSop.c @@ -61,7 +61,7 @@ char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName ) /**Function************************************************************* - Synopsis [Starts the constant 1 cover with the given number of variables and cubes.] + Synopsis [Creates the constant 1 cover with the given number of variables and cubes.] Description [] @@ -92,7 +92,7 @@ char * Abc_SopStart( Extra_MmFlex_t * pMan, int nCubes, int nVars ) /**Function************************************************************* - Synopsis [Starts the constant 1 cover with 0 variables.] + Synopsis [Creates the constant 1 cover with 0 variables.] Description [] @@ -108,7 +108,7 @@ char * Abc_SopCreateConst1( Extra_MmFlex_t * pMan ) /**Function************************************************************* - Synopsis [Starts the constant 1 cover with 0 variables.] + Synopsis [Creates the constant 1 cover with 0 variables.] Description [] @@ -124,7 +124,7 @@ char * Abc_SopCreateConst0( Extra_MmFlex_t * pMan ) /**Function************************************************************* - Synopsis [Starts the AND2 cover.] + Synopsis [Creates the AND2 cover.] Description [] @@ -147,7 +147,7 @@ char * Abc_SopCreateAnd2( Extra_MmFlex_t * pMan, int fCompl0, int fCompl1 ) /**Function************************************************************* - Synopsis [Starts the multi-input AND cover.] + Synopsis [Creates the multi-input AND cover.] Description [] @@ -169,7 +169,7 @@ char * Abc_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) /**Function************************************************************* - Synopsis [Starts the multi-input NAND cover.] + Synopsis [Creates the multi-input NAND cover.] Description [] @@ -191,7 +191,7 @@ char * Abc_SopCreateNand( Extra_MmFlex_t * pMan, int nVars ) /**Function************************************************************* - Synopsis [Starts the multi-input OR cover.] + Synopsis [Creates the multi-input OR cover.] Description [] @@ -213,7 +213,7 @@ char * Abc_SopCreateOr( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) /**Function************************************************************* - Synopsis [Starts the multi-input OR cover.] + Synopsis [Creates the multi-input OR cover.] Description [] @@ -238,7 +238,7 @@ char * Abc_SopCreateOrMultiCube( Extra_MmFlex_t * pMan, int nVars, int * pfCompl /**Function************************************************************* - Synopsis [Starts the multi-input NOR cover.] + Synopsis [Creates the multi-input NOR cover.] Description [] @@ -259,7 +259,7 @@ char * Abc_SopCreateNor( Extra_MmFlex_t * pMan, int nVars ) /**Function************************************************************* - Synopsis [Starts the multi-input XOR cover.] + Synopsis [Creates the multi-input XOR cover.] Description [] @@ -276,7 +276,7 @@ char * Abc_SopCreateXor( Extra_MmFlex_t * pMan, int nVars ) /**Function************************************************************* - Synopsis [Starts the multi-input XOR cover (special case).] + Synopsis [Creates the multi-input XOR cover (special case).] Description [] @@ -296,7 +296,7 @@ char * Abc_SopCreateXorSpecial( Extra_MmFlex_t * pMan, int nVars ) /**Function************************************************************* - Synopsis [Starts the multi-input XNOR cover.] + Synopsis [Creates the multi-input XNOR cover.] Description [] @@ -313,7 +313,24 @@ char * Abc_SopCreateNxor( Extra_MmFlex_t * pMan, int nVars ) /**Function************************************************************* - Synopsis [Starts the inv cover.] + Synopsis [Creates the MUX cover.] + + Description [The first input of MUX is the control. The second input + is DATA1. The third input is DATA0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateMux( Extra_MmFlex_t * pMan ) +{ + return Abc_SopRegister(pMan, "11- 1\n0-1 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the inv cover.] Description [] @@ -329,7 +346,7 @@ char * Abc_SopCreateInv( Extra_MmFlex_t * pMan ) /**Function************************************************************* - Synopsis [Starts the buf cover.] + Synopsis [Creates the buf cover.] Description [] diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index ffab5116..26ef2b66 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -64,6 +64,7 @@ static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRestructure ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandResubstitute ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -82,6 +83,7 @@ static int Abc_CommandExdcSet ( Abc_Frame_t * pAbc, int argc, char ** argv static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandXyz ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandEspresso ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -115,6 +117,9 @@ static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv static int Abc_CommandSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTraceStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTraceCheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -167,6 +172,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "restructure", Abc_CommandRestructure, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "resub", Abc_CommandResubstitute, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 ); // Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 ); Cmd_CommandAdd( pAbc, "Various", "miter", Abc_CommandMiter, 1 ); @@ -185,6 +191,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "cut", Abc_CommandCut, 0 ); Cmd_CommandAdd( pAbc, "Various", "xyz", Abc_CommandXyz, 1 ); Cmd_CommandAdd( pAbc, "Various", "espresso", Abc_CommandEspresso, 1 ); + Cmd_CommandAdd( pAbc, "Various", "gen", Abc_CommandGen, 0 ); Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 ); Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 ); @@ -218,9 +225,13 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Verification", "sat", Abc_CommandSat, 0 ); Cmd_CommandAdd( pAbc, "Verification", "prove", Abc_CommandProve, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "trace_start", Abc_CommandTraceStart, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "trace_check", Abc_CommandTraceCheck, 0 ); + // Rwt_Man4ExploreStart(); // Map_Var3Print(); // Map_Var4Test(); + } /**Function************************************************************* @@ -1598,6 +1609,7 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Ntk_t * pNtk, * pNtkRes; int fBddSizeMax; int fDualRail; + int fReorder; int c; pNtk = Abc_FrameReadNtk(pAbc); @@ -1605,10 +1617,11 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults + fReorder = 1; fDualRail = 0; fBddSizeMax = 1000000; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Bdh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Brdh" ) ) != EOF ) { switch ( c ) { @@ -1626,6 +1639,9 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'd': fDualRail ^= 1; break; + case 'r': + fReorder ^= 1; + break; case 'h': goto usage; default: @@ -1647,11 +1663,11 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) // get the new network if ( Abc_NtkIsStrash(pNtk) ) - pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, 1 ); + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, 1 ); else { pNtk = Abc_NtkStrash( pNtk, 0, 0 ); - pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, 1 ); + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, 1 ); Abc_NtkDelete( pNtk ); } if ( pNtkRes == NULL ) @@ -1664,9 +1680,10 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: collapse [-B num] [-dh]\n" ); + fprintf( pErr, "usage: collapse [-B num] [-rdh]\n" ); fprintf( pErr, "\t collapses the network by constructing global BDDs\n" ); fprintf( pErr, "\t-B num : limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax ); + fprintf( pErr, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); fprintf( pErr, "\t-d : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; @@ -2759,6 +2776,102 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRr( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c, Window; + int nFaninLevels; + int nFanoutLevels; + int fUseFanouts; + int fVerbose; + extern int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFaninLevels = 3; + nFanoutLevels = 3; + fUseFanouts = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Wfvh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + Window = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Window < 0 ) + goto usage; + nFaninLevels = Window / 10; + nFanoutLevels = Window % 10; + break; + case 'f': + fUseFanouts ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkRR( pNtk, nFaninLevels, nFanoutLevels, fUseFanouts, fVerbose ) ) + { + fprintf( pErr, "Redundancy removal has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: rr [-W NM] [-fvh]\n" ); + fprintf( pErr, "\t performs redundancy removal in the current network\n" ); + fprintf( pErr, "\t-W NM : window size as the number of TFI (N) and TFO (M) logic levels [default = %d%d]\n", nFaninLevels, nFanoutLevels ); + fprintf( pErr, "\t-f : toggle RR w.r.t. fanouts [default = %s]\n", fUseFanouts? "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************************************************************* @@ -3806,10 +3919,12 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) pParams->fTruth = 0; // compute truth tables pParams->fFilter = 1; // filter dominated cuts pParams->fDrop = 0; // drop cuts on the fly - pParams->fMulti = 0; // use multi-input AND-gates + pParams->fDag = 0; // compute DAG cuts + pParams->fTree = 0; // compute tree cuts + pParams->fFancy = 0; // compute something fancy pParams->fVerbose = 0; // the verbosiness flag Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdmvoh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyzvoh" ) ) != EOF ) { switch ( c ) { @@ -3844,8 +3959,14 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'd': pParams->fDrop ^= 1; break; - case 'm': - pParams->fMulti ^= 1; + case 'x': + pParams->fDag ^= 1; + break; + case 'y': + pParams->fTree ^= 1; + break; + case 'z': + pParams->fFancy ^= 1; break; case 'v': pParams->fVerbose ^= 1; @@ -3875,6 +3996,11 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); return 1; } + if ( pParams->fDag && pParams->fTree ) + { + fprintf( pErr, "Cannot compute both DAG cuts and tree cuts at the same time.\n" ); + return 1; + } if ( fOracle ) pParams->fRecord = 1; @@ -3891,14 +4017,16 @@ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: cut [-K num] [-M num] [-tfdmvh]\n" ); + fprintf( pErr, "usage: cut [-K num] [-M num] [-tfdxyzvh]\n" ); fprintf( pErr, "\t computes k-feasible cuts for the AIG\n" ); fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); fprintf( pErr, "\t-f : toggle filtering of duplicated/dominated [default = %s]\n", pParams->fFilter? "yes": "no" ); fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" ); - fprintf( pErr, "\t-m : toggle computing only factor-cuts [default = %s]\n", pParams->fMulti? "yes": "no" ); + fprintf( pErr, "\t-x : toggle computing only DAG cuts [default = %s]\n", pParams->fDag? "yes": "no" ); + fprintf( pErr, "\t-y : toggle computing only tree cuts [default = %s]\n", pParams->fTree? "yes": "no" ); + fprintf( pErr, "\t-z : toggle fancy computations [default = %s]\n", pParams->fFancy? "yes": "no" ); fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; @@ -4160,6 +4288,99 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nVars; + int fAdder; + int fSorter; + int fVerbose; + char * FileName; + extern void Abc_GenAdder( char * pFileName, int nVars ); + extern void Abc_GenSorter( char * pFileName, int nVars ); + + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nVars = 8; + fAdder = 0; + fSorter = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nasvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; + case 'a': + fAdder ^= 1; + break; + case 's': + fSorter ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( fAdder ) + Abc_GenAdder( FileName, nVars ); + else if ( fSorter ) + Abc_GenSorter( FileName, nVars ); + else + printf( "Type of circuit is not specified.\n" ); + return 0; + +usage: + fprintf( pErr, "usage: gen [-N] [-asvh] <file>\n" ); + fprintf( pErr, "\t generates simple circuits\n" ); + fprintf( pErr, "\t-N num : the number of variables [default = %d]\n", nVars ); + fprintf( pErr, "\t-a : toggle ripple-carry adder [default = %s]\n", fAdder? "yes": "no" ); + fprintf( pErr, "\t-s : toggle simple sorter [default = %s]\n", fSorter? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t<file> : output file name\n"); + return 1; +} + /**Function************************************************************* @@ -4175,7 +4396,7 @@ usage: int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Ntk_t * pNtk;//, * pNtkRes; int c; // extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk ); @@ -4195,25 +4416,27 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) 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; } +*/ // Abc_NtkTestEsop( pNtk ); // Abc_NtkTestSop( pNtk ); // printf( "This command is currently not used.\n" ); // run the command // pNtkRes = Abc_NtkMiterForCofactors( pNtk, 0, 0, -1 ); - // pNtkRes = Abc_NtkNewAig( pNtk ); + +/* pNtkRes = NULL; if ( pNtkRes == NULL ) { @@ -4222,6 +4445,14 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); +*/ + +// if ( Cut_CellIsRunning() ) +// Cut_CellDumpToFile(); +// else +// Cut_CellPrecompute(); + Cut_CellLoad(); + return 0; usage: @@ -6459,6 +6690,7 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Ntk_t * pNtk; int c; int RetValue; + int fJFront; int fVerbose; int nConfLimit; int nImpLimit; @@ -6469,11 +6701,12 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) pErr = Abc_FrameReadErr(pAbc); // set defaults + fJFront = 0; fVerbose = 0; nConfLimit = 100000; nImpLimit = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "CIvjh" ) ) != EOF ) { switch ( c ) { @@ -6499,6 +6732,9 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nImpLimit < 0 ) goto usage; break; + case 'j': + fJFront ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -6528,13 +6764,13 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) clk = clock(); if ( Abc_NtkIsStrash(pNtk) ) { - RetValue = Abc_NtkMiterSat( pNtk, nConfLimit, nImpLimit, fVerbose ); + RetValue = Abc_NtkMiterSat( pNtk, nConfLimit, nImpLimit, fJFront, fVerbose ); } else { Abc_Ntk_t * pTemp; pTemp = Abc_NtkStrash( pNtk, 0, 0 ); - RetValue = Abc_NtkMiterSat( pTemp, nConfLimit, nImpLimit, fVerbose ); + RetValue = Abc_NtkMiterSat( pTemp, nConfLimit, nImpLimit, fJFront, fVerbose ); pNtk->pModel = pTemp->pModel; pTemp->pModel = NULL; Abc_NtkDelete( pTemp ); } @@ -6544,7 +6780,7 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) { int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel ); if ( pSimInfo[0] != 1 ) - printf( "ERROR in Abc_NtkMiterProve(): Generated counter example is invalid.\n" ); + printf( "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" ); free( pSimInfo ); } @@ -6559,11 +6795,12 @@ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: sat [-C num] [-I num] [-vh]\n" ); + fprintf( pErr, "usage: sat [-C num] [-I num] [-jvh]\n" ); fprintf( pErr, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" ); fprintf( pErr, "\t derives CNF from the current network and leave it unchanged\n" ); fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); fprintf( pErr, "\t-I num : limit on the number of implications [default = %d]\n", nImpLimit ); + fprintf( pErr, "\t-j : toggle the use of J-frontier [default = %s]\n", fJFront? "yes": "no" ); fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; @@ -6584,60 +6821,72 @@ int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNtkTemp; - int c; - int RetValue; - int fVerbose; - int fRewrite; - int fFraig; - int nConfLimit; - int nImpLimit; - int clk; + Prove_Params_t Params, * pParams = &Params; + int c, clk, RetValue; pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults - fVerbose = 0; - fRewrite = 1; - fFraig = 1; - nConfLimit = 300000; - nImpLimit = 0; + Prove_ParamsSetDefault( pParams ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CIrfvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "NCFLrfvh" ) ) != EOF ) { switch ( c ) { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nItersMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nItersMax < 0 ) + goto usage; + break; case 'C': if ( globalUtilOptind >= argc ) { fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } - nConfLimit = atoi(argv[globalUtilOptind]); + pParams->nMiteringLimitStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( nConfLimit < 0 ) + if ( pParams->nMiteringLimitStart < 0 ) goto usage; break; - case 'I': + case 'F': if ( globalUtilOptind >= argc ) { - fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } - nImpLimit = atoi(argv[globalUtilOptind]); + pParams->nFraigingLimitStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( nImpLimit < 0 ) + if ( pParams->nFraigingLimitStart < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nMiteringLimitLast = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nMiteringLimitLast < 0 ) goto usage; break; case 'r': - fRewrite ^= 1; + pParams->fUseRewriting ^= 1; break; case 'f': - fFraig ^= 1; + pParams->fUseFraiging ^= 1; break; case 'v': - fVerbose ^= 1; + pParams->fVerbose ^= 1; break; case 'h': goto usage; @@ -6674,7 +6923,7 @@ int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv ) else pNtkTemp = Abc_NtkStrash( pNtk, 0, 0 ); - RetValue = Abc_NtkMiterProve( &pNtkTemp, nConfLimit, nImpLimit, fRewrite, fFraig, fVerbose ); + RetValue = Abc_NtkMiterProve( &pNtkTemp, pParams ); // verify that the pattern is correct if ( RetValue == 0 ) @@ -6699,19 +6948,143 @@ int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: prove [-C num] [-I num] [-rfvh]\n" ); + fprintf( pErr, "usage: prove [-N num] [-C num] [-F num] [-L num] [-rfvh]\n" ); fprintf( pErr, "\t solves combinational miter by rewriting, FRAIGing, and SAT\n" ); fprintf( pErr, "\t replaces the current network by the cone modified by rewriting\n" ); - fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); - fprintf( pErr, "\t-I num : limit on the number of implications [default = %d]\n", nImpLimit ); - fprintf( pErr, "\t-r : toggle the use of rewriting [default = %s]\n", fRewrite? "yes": "no" ); - fprintf( pErr, "\t-f : toggle the use of FRAIGing [default = %s]\n", fFraig? "yes": "no" ); - fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax ); + fprintf( pErr, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart ); + fprintf( pErr, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart ); + fprintf( pErr, "\t-L num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast ); + fprintf( pErr, "\t-r : toggle the use of rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" ); + fprintf( pErr, "\t-f : toggle the use of FRAIGing [default = %s]\n", pParams->fUseFraiging? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTraceStart( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command is applicable to AIGs.\n" ); + return 1; + } + + Abc_HManStart(); + if ( !Abc_HManPopulate( pNtk ) ) + { + fprintf( pErr, "Failed to start the tracing database.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: trace_start [-h]\n" ); + fprintf( pErr, "\t starts verification tracing\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTraceCheck( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command is applicable to AIGs.\n" ); + return 1; + } + + if ( !Abc_HManIsRunning(pNtk) ) + { + fprintf( pErr, "The tracing database is not available.\n" ); + return 1; + } + + if ( !Abc_HManVerify( 1, pNtk->Id ) ) + fprintf( pErr, "Verification failed.\n" ); + Abc_HManStop(); + return 0; + +usage: + fprintf( pErr, "usage: trace_check [-h]\n" ); + fprintf( pErr, "\t checks the current network using verification trace\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcAuto.c b/src/base/abci/abcAuto.c index fb818ff3..cc6e8913 100644 --- a/src/base/abci/abcAuto.c +++ b/src/base/abci/abcAuto.c @@ -51,7 +51,7 @@ void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ) int nOutputs, nInputs, i; // compute the global BDDs - if ( Abc_NtkGlobalBdds(pNtk, 10000000, 0) == NULL ) + if ( Abc_NtkGlobalBdds(pNtk, 10000000, 0, 1, fVerbose) == NULL ) return; // get information about the network diff --git a/src/base/abci/abcBalance.c b/src/base/abci/abcBalance.c index 919ea3b2..9e9212aa 100644 --- a/src/base/abci/abcBalance.c +++ b/src/base/abci/abcBalance.c @@ -29,6 +29,8 @@ static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int Level, int fDuplicate, bool fSelective ); static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective ); static void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk ); +static Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -227,6 +229,7 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_ return pNodeOld->pCopy; assert( Abc_ObjIsNode(pNodeOld) ); // get the implication supergate +// Abc_NodeBalanceConeExor( pNodeOld ); vSuper = Abc_NodeBalanceCone( pNodeOld, vStorage, Level, fDuplicate, fSelective ); if ( vSuper->nSize == 0 ) { // it means that the supergate contains two nodes in the opposite polarity @@ -260,6 +263,7 @@ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_ assert( pNodeOld->pCopy == NULL ); // mark the old node with the new node pNodeOld->pCopy = vSuper->pArray[0]; + Abc_HManAddProto( pNodeOld->pCopy, pNodeOld ); vSuper->nSize = 0; return pNodeOld->pCopy; } @@ -351,6 +355,65 @@ int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeBalanceConeExor_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst ) +{ + int RetValue1, RetValue2, i; + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pNode ) + return 1; + // if the new node is complemented or a PI, another gate begins + if ( !fFirst && (!pNode->fExor || !Abc_ObjIsNode(pNode)) ) + { + Vec_PtrPush( vSuper, pNode ); + return 0; + } + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + assert( pNode->fExor ); + // go through the branches + RetValue1 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin0(Abc_ObjFanin0(pNode)), vSuper, 0 ); + RetValue2 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin1(Abc_ObjFanin0(pNode)), vSuper, 0 ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vSuper; + if ( !pNode->fExor ) + return NULL; + vSuper = Vec_PtrAlloc( 10 ); + Abc_NodeBalanceConeExor_rec( pNode, vSuper, 1 ); + printf( "%d ", Vec_PtrSize(vSuper) ); + Vec_PtrFree( vSuper ); + return NULL; +} + /**Function************************************************************* diff --git a/src/base/abci/abcClpBdd.c b/src/base/abci/abcClpBdd.c index 84016436..eed18e1b 100644 --- a/src/base/abci/abcClpBdd.c +++ b/src/base/abci/abcClpBdd.c @@ -43,14 +43,14 @@ static Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fVerbose ) +Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ) { Abc_Ntk_t * pNtkNew; assert( Abc_NtkIsStrash(pNtk) ); // compute the global BDDs - if ( Abc_NtkGlobalBdds(pNtk, fBddSizeMax, 0) == NULL ) + if ( Abc_NtkGlobalBdds(pNtk, fBddSizeMax, 0, fReorder, fVerbose) == NULL ) return NULL; if ( fVerbose ) printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(pNtk->pManGlob) - Cudd_ReadDead(pNtk->pManGlob) ); diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c index 2b1816c4..2752dc69 100644 --- a/src/base/abci/abcCut.c +++ b/src/base/abci/abcCut.c @@ -29,6 +29,9 @@ static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ); static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ); + +extern int nTotal, nGood, nEqual; + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -46,6 +49,7 @@ static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ); ***********************************************************************/ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) { + ProgressBar * pProgress; Cut_Man_t * p; Abc_Obj_t * pObj, * pNode; Vec_Ptr_t * vNodes; @@ -56,6 +60,8 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ); extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ); + nTotal = nGood = nEqual = 0; + assert( Abc_NtkIsStrash(pNtk) ); // start the manager pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); @@ -69,6 +75,7 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) // compute cuts for internal nodes vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs vChoices = Vec_IntAlloc( 100 ); + pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) ); Vec_PtrForEachEntry( vNodes, pObj, i ) { // when we reached a CO, it is time to deallocate the cuts @@ -81,8 +88,9 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) // skip constant node, it has no cuts if ( Abc_NodeIsConst(pObj) ) continue; + Extra_ProgressBarUpdate( pProgress, i, NULL ); // compute the cuts to the internal node - Abc_NodeGetCuts( p, pObj, pParams->fMulti ); + Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree ); // consider dropping the fanins cuts if ( pParams->fDrop ) { @@ -98,11 +106,16 @@ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) Cut_NodeUnionCuts( p, vChoices ); } } + Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodes ); Vec_IntFree( vChoices ); PRT( "Total", clock() - clk ); //Abc_NtkPrintCuts_( p, pNtk, 0 ); // Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk ); + + // temporary printout of stats + if ( nTotal ) + printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal ); return p; } @@ -276,14 +289,14 @@ printf( "Converged after %d iterations.\n", nIters ); SeeAlso [] ***********************************************************************/ -void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fMulti ) +void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) { void * pList; if ( pList = Abc_NodeReadCuts( p, pObj ) ) return pList; - Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fMulti ); - Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fMulti ); - return Abc_NodeGetCuts( p, pObj, fMulti ); + Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree ); + Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree ); + return Abc_NodeGetCuts( p, pObj, fDag, fTree ); } /**Function************************************************************* @@ -297,14 +310,28 @@ void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fMulti ) SeeAlso [] ***********************************************************************/ -void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fMulti ) +void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) { -// int fTriv = (!fMulti) || pObj->fMarkB; - int fTriv = (!fMulti) || (pObj->vFanouts.nSize > 1 && !Abc_NodeIsMuxControlType(pObj)); + Abc_Obj_t * pFanin; + int fDagNode, fTriv, TreeCode = 0; assert( Abc_NtkIsStrash(pObj->pNtk) ); assert( Abc_ObjFaninNum(pObj) == 2 ); + // check if the node is a DAG node + fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)); + // increment the counter of DAG nodes + if ( fDagNode ) Cut_ManIncrementDagNodes( p ); + // add the trivial cut if the node is a DAG node, or if we compute all cuts + fTriv = fDagNode || !fDag; + // check if fanins are DAG nodes + if ( fTree ) + { + pFanin = Abc_ObjFanin0(pObj); + TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)); + pFanin = Abc_ObjFanin1(pObj); + TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1); + } return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), - Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv ); + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode ); } /**Function************************************************************* diff --git a/src/base/abci/abcDsd.c b/src/base/abci/abcDsd.c index 18a85a04..79d2b729 100644 --- a/src/base/abci/abcDsd.c +++ b/src/base/abci/abcDsd.c @@ -60,7 +60,7 @@ Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool assert( Abc_NtkIsStrash(pNtk) ); // perform FPGA mapping - if ( Abc_NtkGlobalBdds(pNtk, 10000000, 0) == NULL ) + if ( Abc_NtkGlobalBdds(pNtk, 10000000, 0, 1, fVerbose) == NULL ) return NULL; if ( fVerbose ) printf( "The shared BDD size is %d nodes.\n", Cudd_ReadKeys(pNtk->pManGlob) - Cudd_ReadDead(pNtk->pManGlob) ); diff --git a/src/base/abci/abcEspresso.c b/src/base/abci/abcEspresso.c index 744169b5..ad43534d 100644 --- a/src/base/abci/abcEspresso.c +++ b/src/base/abci/abcEspresso.c @@ -54,7 +54,13 @@ void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose ) if ( Abc_NtkHasMapping(pNtk) ) Abc_NtkUnmap(pNtk); else if ( Abc_NtkHasBdd(pNtk) ) - Abc_NtkBddToSop(pNtk, 0); + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Converting to SOPs has failed.\n" ); + return; + } + } // minimize SOPs of all nodes Abc_NtkForEachNode( pNtk, pNode, i ) if ( i ) Abc_NodeEspresso( pNode ); diff --git a/src/base/abci/abcFraig.c b/src/base/abci/abcFraig.c index 4aae6ba5..2f54dcee 100644 --- a/src/base/abci/abcFraig.c +++ b/src/base/abci/abcFraig.c @@ -684,7 +684,7 @@ int Abc_NtkFraigStore( Abc_Ntk_t * pNtk ) // set the number of networks stored Abc_FrameSetNtkStoreSize( Abc_FrameReadNtkStoreSize() + 1 ); } - printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pStore) - nAndsOld ); +// printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pStore) - nAndsOld ); return 1; } diff --git a/src/base/abci/abcFxu.c b/src/base/abci/abcFxu.c index b377da1d..a8e656ce 100644 --- a/src/base/abci/abcFxu.c +++ b/src/base/abci/abcFxu.c @@ -57,7 +57,13 @@ bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) if ( Abc_NtkIsMappedLogic(pNtk) ) Abc_NtkUnmap(pNtk); else if ( Abc_NtkIsBddLogic(pNtk) ) - Abc_NtkBddToSop(pNtk, 0); + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Converting to SOPs has failed.\n" ); + return 0; + } + } else { // to make sure the SOPs are SCC-free // Abc_NtkSopToBdd(pNtk); diff --git a/src/base/abci/abcGen.c b/src/base/abci/abcGen.c new file mode 100644 index 00000000..626e5e1e --- /dev/null +++ b/src/base/abci/abcGen.c @@ -0,0 +1,261 @@ +/**CFile**************************************************************** + + FileName [abc_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 ); +void Abc_WriteComp( FILE * pFile ); +void Abc_WriteFullAdder( FILE * pFile ); + +void Abc_GenAdder( char * pFileName, int nVars ); +void Abc_GenSorter( char * pFileName, int nVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenAdder( char * pFileName, int nVars ) +{ + FILE * pFile; + int i; + + assert( nVars > 0 ); + + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# %d-bit ripple-carry adder generated by ABC on %s\n", nVars, Extra_TimeStamp() ); + fprintf( pFile, ".model Adder%02d\n", nVars ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " a%02d", i ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " b%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".outputs" ); + for ( i = 0; i <= nVars; i++ ) + fprintf( pFile, " y%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".names c\n" ); + if ( nVars == 1 ) + fprintf( pFile, ".subckt FA a=a00 b=b00 cin=c s=y00 cout=y01\n" ); + else + { + fprintf( pFile, ".subckt FA a=a00 b=b00 cin=c s=y00 cout=%02d\n", 0 ); + for ( i = 1; i < nVars-1; i++ ) + fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=%02d s=y%02d cout=%02d\n", i, i, i-1, i, i ); + fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=%02d s=y%02d cout=y%02d\n", i, i, i-1, i, i+1 ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); + + Abc_WriteFullAdder( pFile ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenSorter( char * pFileName, int nVars ) +{ + FILE * pFile; + int i, k, Counter, nDigits; + + assert( nVars > 1 ); + + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# %d-bit sorter generated by ABC on %s\n", nVars, Extra_TimeStamp() ); + fprintf( pFile, ".model Sorter%02d\n", nVars ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " x%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".outputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " y%02d", i ); + fprintf( pFile, "\n" ); + + Counter = 0; + nDigits = Extra_Base10Log( (nVars-2)*nVars ); + if ( nVars == 2 ) + fprintf( pFile, ".subckt Comp a=x00 b=x01 x=y00 y=y01\n" ); + else + { + fprintf( pFile, ".subckt Layer0" ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " x%02d=x%02d", k, k ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ ); + fprintf( pFile, "\n" ); + Counter -= nVars; + for ( i = 1; i < nVars-2; i++ ) + { + fprintf( pFile, ".subckt Layer%d", (i&1) ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ ); + fprintf( pFile, "\n" ); + Counter -= nVars; + } + fprintf( pFile, ".subckt Layer%d", (i&1) ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " y%02d=y%02d", k, k ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); + + Abc_WriteLayer( pFile, nVars, 0 ); + Abc_WriteLayer( pFile, nVars, 1 ); + Abc_WriteComp( pFile ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 ) +{ + int i; + fprintf( pFile, ".model Layer%d\n", fSkip1 ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " x%02d", i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".outputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " y%02d", i ); + fprintf( pFile, "\n" ); + if ( fSkip1 ) + { + fprintf( pFile, ".names x00 y00\n" ); + fprintf( pFile, "1 1\n" ); + i = 1; + } + else + i = 0; + for ( ; i + 1 < nVars; i += 2 ) + fprintf( pFile, ".subckt Comp a=x%02d b=x%02d x=y%02d y=y%02d\n", i, i+1, i, i+1 ); + if ( i < nVars ) + { + fprintf( pFile, ".names x%02d y%02d\n", i, i ); + fprintf( pFile, "1 1\n" ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteComp( FILE * pFile ) +{ + fprintf( pFile, ".model Comp\n" ); + fprintf( pFile, ".inputs a b\n" ); + fprintf( pFile, ".outputs x y\n" ); + fprintf( pFile, ".names a b x\n" ); + fprintf( pFile, "11 1\n" ); + fprintf( pFile, ".names a b y\n" ); + fprintf( pFile, "1- 1\n" ); + fprintf( pFile, "-1 1\n" ); + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteFullAdder( FILE * pFile ) +{ + fprintf( pFile, ".model FA\n" ); + fprintf( pFile, ".inputs a b cin\n" ); + fprintf( pFile, ".outputs s cout\n" ); + fprintf( pFile, ".names a b k\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names k cin s\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names a b cin cout\n" ); + fprintf( pFile, "11- 1\n" ); + fprintf( pFile, "1-1 1\n" ); + fprintf( pFile, "-11 1\n" ); + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c index 25d9e30f..c579eb84 100644 --- a/src/base/abci/abcMap.c +++ b/src/base/abci/abcMap.c @@ -522,7 +522,11 @@ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) // duplicate the network pNtkNew2 = Abc_NtkDup( pNtk ); pNtkNew = Abc_NtkRenode( pNtkNew2, 0, 20, 0, 0, 1, 0 ); - Abc_NtkBddToSop( pNtkNew, 0 ); + if ( !Abc_NtkBddToSop( pNtkNew, 0 ) ) + { + printf( "Converting to SOPs has failed.\n" ); + return NULL; + } // set the old network to point to the new network Abc_NtkForEachCi( pNtk, pNode, i ) diff --git a/src/base/abci/abcMiter.c b/src/base/abci/abcMiter.c index c0658d5e..87ea57f3 100644 --- a/src/base/abci/abcMiter.c +++ b/src/base/abci/abcMiter.c @@ -282,7 +282,129 @@ void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNt +/**Function************************************************************* + + Synopsis [Derives the AND of two miters.] + + Description [The network should have the same names of PIs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ) +{ + char Buffer[100]; + Abc_Ntk_t * pNtkMiter; + Abc_Obj_t * pOutput1, * pOutput2; + Abc_Obj_t * pRoot1, * pRoot2, * pMiter; + + assert( Abc_NtkIsStrash(pNtk1) ); + assert( Abc_NtkIsStrash(pNtk2) ); + assert( 1 == Abc_NtkCoNum(pNtk1) ); + assert( 1 == Abc_NtkCoNum(pNtk2) ); + assert( 0 == Abc_NtkLatchNum(pNtk1) ); + assert( 0 == Abc_NtkLatchNum(pNtk2) ); + assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) ); + + // start the new network + pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG ); + sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); + pNtkMiter->pName = Extra_UtilStrsav(Buffer); + + // perform strashing + Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, 1 ); + Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); + Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); +// Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, 1 ); + pRoot1 = Abc_NtkPo(pNtk1,0); + pRoot2 = Abc_NtkPo(pNtk2,0); + pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot1)->pCopy, Abc_ObjFaninC0(pRoot1) ); + pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot2)->pCopy, Abc_ObjFaninC0(pRoot2) ); + + // create the miter of the two outputs + pMiter = Abc_AigAnd( pNtkMiter->pManFunc, pOutput1, pOutput2 ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkMiter ) ) + { + printf( "Abc_NtkMiterAnd: The network check has failed.\n" ); + Abc_NtkDelete( pNtkMiter ); + return NULL; + } + return pNtkMiter; +} + + +/**Function************************************************************* + + Synopsis [Derives the cofactor of the miter w.r.t. the set of vars.] + + Description [The array of variable values contains -1/0/1 for each PI. + -1 means this PI remains, 0/1 means this PI is set to 0/1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ) +{ + char Buffer[100]; + Abc_Ntk_t * pNtkMiter; + Abc_Obj_t * pRoot, * pOutput1; + int Value, i; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( 1 == Abc_NtkCoNum(pNtk) ); + + // start the new network + pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG ); + sprintf( Buffer, "%s_miter", pNtk->pName ); + pNtkMiter->pName = Extra_UtilStrsav(Buffer); + + // get the root output + pRoot = Abc_NtkCo( pNtk, 0 ); + + // perform strashing + Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1 ); + // set the first cofactor + Vec_IntForEachEntry( vPiValues, Value, i ) + { + if ( Value == -1 ) + continue; + if ( Value == 0 ) + { + Abc_NtkCi(pNtk, i)->pCopy = Abc_ObjNot( Abc_NtkConst1(pNtkMiter) ); + continue; + } + if ( Value == 1 ) + { + Abc_NtkCi(pNtk, i)->pCopy = Abc_NtkConst1(pNtkMiter); + continue; + } + assert( 0 ); + } + // add the first cofactor + Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); + + // save the output + pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); + + // create the miter of the two outputs + Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pOutput1 ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkMiter ) ) + { + printf( "Abc_NtkMiterCofactor: The network check has failed.\n" ); + Abc_NtkDelete( pNtkMiter ); + return NULL; + } + return pNtkMiter; +} /**Function************************************************************* Synopsis [Derives the miter of two cofactors of one output.] diff --git a/src/base/abci/abcNewAig.c b/src/base/abci/abcNewAig.c index 209fc991..62ae51ed 100644 --- a/src/base/abci/abcNewAig.c +++ b/src/base/abci/abcNewAig.c @@ -65,7 +65,13 @@ Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk ) assert( !Abc_NtkIsNetlist(pNtk) ); assert( !Abc_NtkIsSeq(pNtk) ); if ( Abc_NtkIsBddLogic(pNtk) ) - Abc_NtkBddToSop(pNtk, 0); + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Converting to SOPs has failed.\n" ); + return; + } + } // print warning about choice nodes if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" ); diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c index d92da31b..33f432f4 100644 --- a/src/base/abci/abcNtbdd.c +++ b/src/base/abci/abcNtbdd.c @@ -27,7 +27,7 @@ static void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); static Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ); static Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st_table * tBdd2Node ); -static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax ); +static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, ProgressBar * pProgress, int * pCounter, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -243,15 +243,14 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * SeeAlso [] ***********************************************************************/ -DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fLatchOnly ) +DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fLatchOnly, int fReorder, int fVerbose ) { - int fReorder = 1; ProgressBar * pProgress; Vec_Ptr_t * vFuncsGlob; Abc_Obj_t * pNode; DdNode * bFunc; DdManager * dd; - int i; + int i, Counter; // start the manager assert( pNtk->pManGlob == NULL ); @@ -269,18 +268,20 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fLatchOnly // collect the global functions of the COs vFuncsGlob = Vec_PtrAlloc( 100 ); + Counter = 0; if ( fLatchOnly ) { // construct the BDDs - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkLatchNum(pNtk) ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); Abc_NtkForEachLatch( pNtk, pNode, i ) { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pNode), nBddSizeMax ); +// Extra_ProgressBarUpdate( pProgress, i, NULL ); + bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pNode), nBddSizeMax, pProgress, &Counter, fVerbose ); if ( bFunc == NULL ) { + if ( fVerbose ) printf( "Constructing global BDDs is aborted.\n" ); - Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vFuncsGlob ); Cudd_Quit( dd ); return NULL; } @@ -292,15 +293,16 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fLatchOnly else { // construct the BDDs - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pNode), nBddSizeMax ); +// Extra_ProgressBarUpdate( pProgress, i, NULL ); + bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pNode), nBddSizeMax, pProgress, &Counter, fVerbose ); if ( bFunc == NULL ) { + if ( fVerbose ) printf( "Constructing global BDDs is aborted.\n" ); - Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vFuncsGlob ); Cudd_Quit( dd ); return NULL; } @@ -339,12 +341,14 @@ DdManager * Abc_NtkGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fLatchOnly SeeAlso [] ***********************************************************************/ -DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax ) +DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, ProgressBar * pProgress, int * pCounter, int fVerbose ) { DdNode * bFunc, * bFunc0, * bFunc1; assert( !Abc_ObjIsComplement(pNode) ); if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax ) { + Extra_ProgressBarStop( pProgress ); + if ( fVerbose ) printf( "The number of live nodes reached %d.\n", nBddSizeMax ); fflush( stdout ); return NULL; @@ -353,11 +357,11 @@ DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSize if ( pNode->pCopy ) return (DdNode *)pNode->pCopy; // compute the result for both branches - bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0), nBddSizeMax ); + bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0), nBddSizeMax, pProgress, pCounter, fVerbose ); if ( bFunc0 == NULL ) return NULL; Cudd_Ref( bFunc0 ); - bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1), nBddSizeMax ); + bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1), nBddSizeMax, pProgress, pCounter, fVerbose ); if ( bFunc1 == NULL ) return NULL; Cudd_Ref( bFunc1 ); @@ -370,6 +374,9 @@ DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSize // set the result assert( pNode->pCopy == NULL ); pNode->pCopy = (Abc_Obj_t *)bFunc; + // increment the progress bar + if ( pProgress ) + Extra_ProgressBarUpdate( pProgress, (*pCounter)++, NULL ); return bFunc; } @@ -427,7 +434,7 @@ double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ) Vec_PtrForEachEntry( vNodes, pObj, i ) pObj->pCopy = (Abc_Obj_t *)dd->vars[i]; // build the BDD of the cone - bFunc = Abc_NodeGlobalBdds_rec( dd, pNodeR, 10000000 ); Cudd_Ref( bFunc ); + bFunc = Abc_NodeGlobalBdds_rec( dd, pNodeR, 10000000, NULL, NULL, 1 ); Cudd_Ref( bFunc ); bFunc = Cudd_NotCond( bFunc, pNode != pNodeR ); // count minterms Result = Cudd_CountMinterm( dd, bFunc, dd->size ); diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index d299a29d..56b70c5b 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -28,6 +28,9 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +//extern int s_TotalNodes = 0; +//extern int s_TotalChanges = 0; + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -147,6 +150,11 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) fclose( pTable ); } */ +/* + s_TotalNodes += Abc_NtkNodeNum(pNtk); + printf( "Total nodes = %6d %6.2f Mb Changes = %6d.\n", + s_TotalNodes, s_TotalNodes * 20.0 / (1<<20), s_TotalChanges ); +*/ } /**Function************************************************************* @@ -644,7 +652,13 @@ void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary ) // transform logic functions from BDD to SOP if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) - Abc_NtkBddToSop(pNtk, 0); + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Converting to SOPs has failed.\n" ); + return; + } + } // get hold of the SOP of the node CountConst = CountBuf = CountInv = CountAnd = CountOr = CountOther = CounterTotal = 0; diff --git a/src/base/abci/abcProve.c b/src/base/abci/abcProve.c index ae4bb250..c0e904bf 100644 --- a/src/base/abci/abcProve.c +++ b/src/base/abci/abcProve.c @@ -20,6 +20,7 @@ #include "abc.h" #include "fraig.h" +#include "math.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -32,10 +33,11 @@ extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); static Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, int * pRetValue, int * pNumFails ); static void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// - + /**Function************************************************************* Synopsis [Attempts to solve the miter using a number of tricks.] @@ -50,106 +52,126 @@ static void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fV SeeAlso [] ***********************************************************************/ -int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, int nConfLimit, int nImpLimit, int fUseRewrite, int fUseFraig, int fVerbose ) +int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars ) { + Prove_Params_t * pParams = pPars; Abc_Ntk_t * pNtk, * pNtkTemp; - int nConfsStart = 1000, nImpsStart = 0, nBTLimitStart = 2; // was 5000 - int nConfs, nImps, nBTLimit, RetValue, nSatFails; - int nIter = 0, clk, timeStart = clock(); + int RetValue, nIter, Counter, clk, timeStart = clock(); // get the starting network pNtk = *ppNtk; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkPoNum(pNtk) == 1 ); - // set the initial limits - nConfs = !nConfLimit? nConfsStart : ABC_MIN( nConfsStart, nConfLimit ); - nImps = !nImpLimit ? nImpsStart : ABC_MIN( nImpsStart , nImpLimit ); - nBTLimit = nBTLimitStart; - - if ( fVerbose ) - printf( "Global resource limits: ConfsLim = %6d. ImpsLim = %d.\n", nConfLimit, nImpLimit ); + if ( pParams->fVerbose ) + { + printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", + pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); + printf( "Mitering = %d (%3.1f). Rewriting = %d (%3.1f). Fraiging = %d (%3.1f).\n", + pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, + pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, + pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti ); + printf( "Mitering last = %d.\n", + pParams->nMiteringLimitLast ); + } // if SAT only, solve without iteration - if ( !fUseRewrite && !fUseFraig ) + if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) { clk = clock(); - RetValue = Abc_NtkMiterSat( pNtk, nConfLimit, nImpLimit, 0 ); - Abc_NtkMiterPrint( pNtk, "SAT solving", clk, fVerbose ); + RetValue = Abc_NtkMiterSat( pNtk, pParams->nMiteringLimitLast, 0, 0, 0 ); + Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); *ppNtk = pNtk; return RetValue; } // check the current resource limits - do { - nIter++; - - if ( fVerbose ) + for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) + { + if ( pParams->fVerbose ) { - printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter, nConfs, nBTLimit ); + printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, + (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), + (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); fflush( stdout ); } // try brute-force SAT clk = clock(); - RetValue = Abc_NtkMiterSat( pNtk, nConfs, nImps, 0 ); - Abc_NtkMiterPrint( pNtk, "SAT solving", clk, fVerbose ); + RetValue = Abc_NtkMiterSat( pNtk, (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), 0, 0, 0 ); + Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); if ( RetValue >= 0 ) break; - if ( fUseRewrite ) + // try rewriting + if ( pParams->fUseRewriting ) { clk = clock(); - - // try rewriting - Abc_NtkRewrite( pNtk, 0, 0, 0 ); - if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) - break; - Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); - if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) - break; - pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); - if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) - break; - - Abc_NtkMiterPrint( pNtk, "Rewriting ", clk, fVerbose ); + Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); + while ( 1 ) + { + Abc_NtkRewrite( pNtk, 0, 0, 0 ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; + Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; + } + Abc_NtkMiterPrint( pNtk, "Rewriting ", clk, pParams->fVerbose ); } - - if ( fUseFraig ) + + if ( pParams->fUseFraiging ) { + int nSatFails; // try FRAIGing clk = clock(); - pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, nBTLimit, &RetValue, &nSatFails ); Abc_NtkDelete( pNtkTemp ); - Abc_NtkMiterPrint( pNtk, "FRAIGing ", clk, fVerbose ); + pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)), &RetValue, &nSatFails ); Abc_NtkDelete( pNtkTemp ); + Abc_NtkMiterPrint( pNtk, "FRAIGing ", clk, pParams->fVerbose ); // printf( "NumFails = %d\n", nSatFails ); if ( RetValue >= 0 ) break; } - else - nSatFails = 1000; - - // increase resource limits -// nConfs = ABC_MIN( nConfs * 3 / 2, 1000000000 ); // was 4/2 - nConfs = nSatFails * nBTLimit / 2; - nImps = ABC_MIN( nImps * 3 / 2, 1000000000 ); - nBTLimit = ABC_MIN( nBTLimit * 8, 1000000000 ); - - // timeout at 5 minutes -// if ( clock() - timeStart >= 1200 * CLOCKS_PER_SEC ) -// break; - if ( nIter == 7 ) - break; } -// while ( (nConfLimit == 0 || nConfs <= nConfLimit) && -// (nImpLimit == 0 || nImps <= nImpLimit ) ); - while ( 1 ); // try to prove it using brute force SAT + if ( RetValue < 0 && pParams->fUseBdds ) + { + if ( pParams->fVerbose ) + { + printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); + fflush( stdout ); + } + clk = clock(); + pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); + if ( pNtk ) + { + Abc_NtkDelete( pNtkTemp ); + RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) ); + } + else + pNtk = pNtkTemp; + Abc_NtkMiterPrint( pNtk, "BDD building", clk, pParams->fVerbose ); + } + if ( RetValue < 0 ) { + if ( pParams->fVerbose ) + { + printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); + fflush( stdout ); + } clk = clock(); - RetValue = Abc_NtkMiterSat( pNtk, nConfLimit, nImpLimit, 0 ); - Abc_NtkMiterPrint( pNtk, "SAT solving", clk, fVerbose ); + RetValue = Abc_NtkMiterSat( pNtk, pParams->nMiteringLimitLast, 0, 0, 0 ); + Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); } // assign the model if it was proved by rewriting (const 1 miter) @@ -240,7 +262,8 @@ void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose { if ( !fVerbose ) return; - printf( "Nodes = %7d. Levels = %4d. ", Abc_NtkNodeNum(pNtk), Abc_AigGetLevelNum(pNtk) ); + printf( "Nodes = %7d. Levels = %4d. ", Abc_NtkNodeNum(pNtk), + Abc_NtkIsStrash(pNtk)? Abc_AigGetLevelNum(pNtk) : Abc_NtkGetLevelNum(pNtk) ); PRT( pString, clock() - clk ); } diff --git a/src/base/abci/abcRefactor.c b/src/base/abci/abcRefactor.c index c968025f..9ea3ad71 100644 --- a/src/base/abci/abcRefactor.c +++ b/src/base/abci/abcRefactor.c @@ -132,6 +132,10 @@ clk = clock(); Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRef->nLastGain ); pManRef->timeNtk += clock() - clk; Dec_GraphFree( pFForm ); +// { +// extern int s_TotalChanges; +// s_TotalChanges++; +// } } Extra_ProgressBarStop( pProgress ); pManRef->timeTotal = clock() - clkStart; diff --git a/src/base/abci/abcRestruct.c b/src/base/abci/abcRestruct.c index 32e878b8..49208772 100644 --- a/src/base/abci/abcRestruct.c +++ b/src/base/abci/abcRestruct.c @@ -74,7 +74,7 @@ static Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, C static Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCut ); static Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded ); -static Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fMulti ); +static Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag ); static Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ); static void Abc_NtkManRstStop( Abc_ManRst_t * p ); static void Abc_NtkManRstPrintStats( Abc_ManRst_t * p ); @@ -145,7 +145,7 @@ pManRst->timeCut += clock() - clk; break; // get the cuts for the given node clk = clock(); - pCutList = Abc_NodeGetCutsRecursive( pManCut, pNode, fMulti ); + pCutList = Abc_NodeGetCutsRecursive( pManCut, pNode, fMulti, 0 ); pManRst->timeCut += clock() - clk; // perform restructuring @@ -203,7 +203,7 @@ pManRst->timeTotal = clock() - clkStart; ***********************************************************************/ void Abc_RestructNodeDivisors( Abc_ManRst_t * p, Abc_Obj_t * pRoot, int nNodesSaved ) { - Abc_Obj_t * pNode, * pFanin, * pFanout; + Abc_Obj_t * pNode, * pFanout;//, * pFanin; int i, k; // start with the leaves Vec_PtrClear( p->vDecs ); @@ -276,7 +276,7 @@ Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_ { Dec_Graph_t * pGraph; Cut_Cut_t * pCut; - int nCuts; +// int nCuts; p->nNodesConsidered++; /* // count the number of cuts with four inputs or more @@ -949,7 +949,7 @@ Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd SeeAlso [] ***********************************************************************/ -Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fMulti ) +Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag ) { static Cut_Params_t Params, * pParams = &Params; Cut_Man_t * pManCut; @@ -963,7 +963,8 @@ Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fM pParams->fFilter = 1; // filter dominated cuts pParams->fSeq = 0; // compute sequential cuts pParams->fDrop = 0; // drop cuts on the fly - pParams->fMulti = fMulti; // compute factor-cuts + pParams->fDag = fDag; // compute DAG cuts + pParams->fTree = 0; // compute tree cuts pParams->fVerbose = 0; // the verbosiness flag pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); pManCut = Cut_ManStart( pParams ); @@ -1351,9 +1352,9 @@ Dec_Graph_t * Abc_NodeMffcSingleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int n ***********************************************************************/ Dec_Graph_t * Abc_NodeMffcDoubleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) { - Dec_Graph_t * pGraph; - unsigned uRoot, uNode; - int i; +// Dec_Graph_t * pGraph; +// unsigned uRoot, uNode; +// int i; return NULL; diff --git a/src/base/abci/abcResub.c b/src/base/abci/abcResub.c index 71a4466f..e9de4858 100644 --- a/src/base/abci/abcResub.c +++ b/src/base/abci/abcResub.c @@ -25,6 +25,9 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +#define ABC_RS_DIV1_MAX 150 // the max number of divisors to consider +#define ABC_RS_DIV2_MAX 500 // the max number of pair-wise divisors to consider + typedef struct Abc_ManRes_t_ Abc_ManRes_t; struct Abc_ManRes_t_ { @@ -79,6 +82,7 @@ struct Abc_ManRes_t_ int nUsedNodeTotal; int nTotalDivs; int nTotalLeaves; + int nTotalGain; }; // external procedures @@ -90,8 +94,8 @@ static void Abc_ManResubPrint( Abc_ManRes_t * p ); // other procedures static int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required ); -static int Abc_ManResubMffc( Abc_ManRes_t * p, Vec_Ptr_t * vDivs, Abc_Obj_t * pRoot, int nLeaves ); static void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords ); +static void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ); static void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required ); static void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required ); @@ -136,13 +140,17 @@ int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, bool fUpd // cleanup the AIG Abc_AigCleanup(pNtk->pManFunc); // start the managers - pManCut = Abc_NtkManCutStart( nCutMax, 10000, 100000, 100000 ); - pManRes = Abc_ManResubStart( nCutMax, 200 ); + pManCut = Abc_NtkManCutStart( nCutMax, 100000, 100000, 100000 ); + pManRes = Abc_ManResubStart( nCutMax, ABC_RS_DIV1_MAX ); // compute the reverse levels if level update is requested if ( fUpdateLevel ) Abc_NtkStartReverseLevels( pNtk ); + if ( Abc_NtkLatchNum(pNtk) ) + Abc_NtkForEachLatch(pNtk, pNode, i) + pNode->pNext = pNode->pData; + // resynthesize each node once nNodes = Abc_NtkObjNumMax(pNtk); pProgress = Extra_ProgressBarStart( stdout, nNodes ); @@ -179,13 +187,16 @@ clk = clock(); pManRes->timeRes += clock() - clk; if ( pFForm == NULL ) continue; + pManRes->nTotalGain += pManRes->nLastGain; /* - if ( pNode->Id % 25 == 0 ) + if ( pManRes->nLeaves == 4 && pManRes->nMffc == 2 && pManRes->nLastGain == 1 ) + { printf( "%6d : L = %2d. V = %2d. Mffc = %2d. Divs = %3d. Up = %3d. Un = %3d. B = %3d.\n", pNode->Id, pManRes->nLeaves, Abc_CutVolumeCheck(pNode, vLeaves), pManRes->nMffc, pManRes->nDivs, pManRes->vDivs1UP->nSize, pManRes->vDivs1UN->nSize, pManRes->vDivs1B->nSize ); + Abc_ManResubPrintDivs( pManRes, pNode, vLeaves ); + } */ - // acceptable replacement found, update the graph clk = clock(); Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRes->nLastGain ); @@ -207,6 +218,10 @@ pManRes->timeTotal = clock() - clkStart; Abc_NtkForEachObj( pNtk, pNode, i ) pNode->pData = NULL; + if ( Abc_NtkLatchNum(pNtk) ) + Abc_NtkForEachLatch(pNtk, pNode, i) + pNode->pData = pNode->pNext, pNode->pNext = NULL; + // put the nodes into the DFS order and reassign their IDs Abc_NtkReassignIds( pNtk ); // Abc_AigCheckFaninOrder( pNtk->pManFunc ); @@ -340,6 +355,7 @@ void Abc_ManResubPrint( Abc_ManRes_t * p ) ); PRT( "TOTAL ", p->timeTotal ); printf( "Total leaves = %8d.\n", p->nTotalLeaves ); printf( "Total divisors = %8d.\n", p->nTotalDivs ); + printf( "Total gain = %8d.\n", p->nTotalGain ); } @@ -382,7 +398,7 @@ void Abc_ManResubCollectDivs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vInternal ) ***********************************************************************/ int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required ) { - Abc_Obj_t * pNode, * pFanout;//, * pFanin; + Abc_Obj_t * pNode, * pFanout; int i, k, Limit, Counter; Vec_PtrClear( p->vDivs1UP ); @@ -451,10 +467,24 @@ Quits : assert( pRoot == Vec_PtrEntryLast(p->vDivs) ); assert( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) <= Vec_PtrSize(p->vSims) - p->nLeavesMax ); + return 1; +} -/* -if (pRoot->Id == 15281 ) +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ) { + Abc_Obj_t * pFanin, * pNode; + int i, k; // print the nodes Vec_PtrForEachEntry( p->vDivs, pNode, i ) { @@ -488,59 +518,7 @@ if (pRoot->Id == 15281 ) } printf( "\n" ); } -*/ - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ManResubMffc( Abc_ManRes_t * p, Vec_Ptr_t * vDivs, Abc_Obj_t * pRoot, int nLeaves ) -{ - Abc_Obj_t * pObj; - int Counter, i, k; - // increment the traversal ID for the leaves - // increment the fanout counters of the leaves - Abc_NtkIncrementTravId( pRoot->pNtk ); - Vec_PtrForEachEntryStop( vDivs, pObj, i, nLeaves ) - { - pObj->vFanouts.nSize++; - Abc_NodeSetTravIdCurrent( pObj ); - } - // make sure the node is in the cone and is no one of the leaves - assert( Abc_NodeIsTravIdPrevious(pRoot) ); - Counter = Abc_NodeMffcLabel( pRoot ); - // remove the extra counters - Vec_PtrForEachEntryStop( vDivs, pObj, i, nLeaves ) - pObj->vFanouts.nSize--; - - // sort the nodes by level!!! - - // move the labeled nodes to the end - Vec_PtrClear( p->vTemp ); - k = nLeaves; - Vec_PtrForEachEntryStart( vDivs, pObj, i, nLeaves ) - if ( Abc_NodeIsTravIdCurrent(pObj) ) - Vec_PtrPush( p->vTemp, pObj ); - else - Vec_PtrWriteEntry( vDivs, k++, pObj ); - // add the labeled nodes - Vec_PtrForEachEntry( p->vTemp, pObj, i ) - Vec_PtrWriteEntry( vDivs, k++, pObj ); - assert( k == Vec_PtrSize(p->vDivs) ); - assert( pRoot == Vec_PtrEntryLast(p->vDivs) ); - return Counter; -} /**Function************************************************************* @@ -928,7 +906,7 @@ void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required ) puData1 = pObj1->pData; - if ( Vec_PtrSize(p->vDivs2UP0) < 500 ) + if ( Vec_PtrSize(p->vDivs2UP0) < ABC_RS_DIV2_MAX ) { // get positive unate divisors for ( w = 0; w < p->nWords; w++ ) @@ -965,7 +943,7 @@ void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required ) } } - if ( Vec_PtrSize(p->vDivs2UN0) < 500 ) + if ( Vec_PtrSize(p->vDivs2UN0) < ABC_RS_DIV2_MAX ) { // get negative unate divisors for ( w = 0; w < p->nWords; w++ ) diff --git a/src/base/abci/abcRewrite.c b/src/base/abci/abcRewrite.c index f3360421..f11e5e9d 100644 --- a/src/base/abci/abcRewrite.c +++ b/src/base/abci/abcRewrite.c @@ -110,6 +110,10 @@ clk = clock(); Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain ); Rwr_ManAddTimeUpdate( pManRwr, clock() - clk ); if ( fCompl ) Dec_GraphComplement( pGraph ); +// { +// extern int s_TotalChanges; +// s_TotalChanges++; +// } } } Extra_ProgressBarStop( pProgress ); diff --git a/src/base/abci/abcRr.c b/src/base/abci/abcRr.c new file mode 100644 index 00000000..3a6a29c9 --- /dev/null +++ b/src/base/abci/abcRr.c @@ -0,0 +1,601 @@ +/**CFile**************************************************************** + + FileName [abcRr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Redundancy removal.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Abc_RRMan_t_ Abc_RRMan_t; +struct Abc_RRMan_t_ +{ + // the parameters + Abc_Ntk_t * pNtk; // the network + int nFaninLevels; // the number of fanin levels + int nFanoutLevels; // the number of fanout levels + // the node/fanin/fanout + Abc_Obj_t * pNode; // the node + Abc_Obj_t * pFanin; // the fanin + Abc_Obj_t * pFanout; // the fanout + // the intermediate cones + Vec_Ptr_t * vFaninLeaves; // the leaves of the fanin cone + Vec_Ptr_t * vFanoutRoots; // the roots of the fanout cone + // the window + Vec_Ptr_t * vLeaves; // the leaves of the window + Vec_Ptr_t * vCone; // the internal nodes of the window + Vec_Ptr_t * vRoots; // the roots of the window + Abc_Ntk_t * pWnd; // the window derived for the edge + // the miter + Abc_Ntk_t * pMiter; // the miter derived from the window + Prove_Params_t * pParams; // the miter proving parameters +}; + +static Abc_RRMan_t * Abc_RRManStart(); +static void Abc_RRManStop( Abc_RRMan_t * p ); +static void Abc_RRManClean( Abc_RRMan_t * p ); +static int Abc_NtkRRProve( Abc_RRMan_t * p ); +static int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ); +static int Abc_NtkRRWindow( Abc_RRMan_t * p ); + +static int Abc_NtkRRTfi_int( Vec_Ptr_t * vFaninLeaves, int LevelLimit ); +static int Abc_NtkRRTfo_int( Vec_Ptr_t * vFanoutRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ); +static int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ); +static void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ); +static Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Removes stuck-at redundancies.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose ) +{ + ProgressBar * pProgress; + Abc_RRMan_t * p; + Abc_Obj_t * pNode, * pFanin, * pFanout; + int i, k, m, nNodes; + // start the manager + p = Abc_RRManStart( nFaninLevels, nFanoutLevels ); + p->pNtk = pNtk; + p->nFaninLevels = nFaninLevels; + p->nFanoutLevels = nFanoutLevels; + // go through the nodes + nNodes = Abc_NtkObjNumMax(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + // skip the constant node + if ( Abc_NodeIsConst(pNode) ) + continue; + // skip the nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + continue; + // construct the window + if ( !fUseFanouts ) + { + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + Abc_RRManClean( p ); + p->pNode = pNode; + p->pFanin = pFanin; + p->pFanout = NULL; + if ( !Abc_NtkRRWindow( p ) ) + continue; + if ( !Abc_NtkRRProve( p ) ) + continue; + Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout ); + break; + } + continue; + } + // use the fanouts + Abc_ObjForEachFanout( pNode, pFanout, m ) + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + Abc_RRManClean( p ); + p->pNode = pNode; + p->pFanin = pFanin; + p->pFanout = pFanout; + if ( !Abc_NtkRRWindow( p ) ) + continue; + if ( !Abc_NtkRRProve( p ) ) + continue; + Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout ); + break; + } + } + Extra_ProgressBarStop( pProgress ); + Abc_RRManStop( p ); + // put the nodes into the DFS order and reassign their IDs + Abc_NtkReassignIds( pNtk ); + Abc_NtkGetLevelNum( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkRR: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Start the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_RRMan_t * Abc_RRManStart() +{ + Abc_RRMan_t * p; + p = ALLOC( Abc_RRMan_t, 1 ); + memset( p, 0, sizeof(Abc_RRMan_t) ); + p->vFaninLeaves = Vec_PtrAlloc( 100 ); // the leaves of the fanin cone + p->vFanoutRoots = Vec_PtrAlloc( 100 ); // the roots of the fanout cone + p->vLeaves = Vec_PtrAlloc( 100 ); // the leaves of the window + p->vCone = Vec_PtrAlloc( 100 ); // the internal nodes of the window + p->vRoots = Vec_PtrAlloc( 100 ); // the roots of the window + p->pParams = ALLOC( Prove_Params_t, 1 ); + memset( p->pParams, 0, sizeof(Prove_Params_t) ); + Prove_ParamsSetDefault( p->pParams ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stop the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RRManStop( Abc_RRMan_t * p ) +{ + Abc_RRManClean( p ); + Vec_PtrFree( p->vFaninLeaves ); + Vec_PtrFree( p->vFanoutRoots ); + Vec_PtrFree( p->vLeaves ); + Vec_PtrFree( p->vCone ); + Vec_PtrFree( p->vRoots ); + free( p->pParams ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Clean the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RRManClean( Abc_RRMan_t * p ) +{ + p->pNode = NULL; + p->pFanin = NULL; + p->pFanout = NULL; + Vec_PtrClear( p->vFaninLeaves ); + Vec_PtrClear( p->vFanoutRoots ); + Vec_PtrClear( p->vLeaves ); + Vec_PtrClear( p->vCone ); + Vec_PtrClear( p->vRoots ); + if ( p->pWnd ) Abc_NtkDelete( p->pWnd ); + if ( p->pMiter ) Abc_NtkDelete( p->pMiter ); + p->pWnd = NULL; + p->pMiter = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the miter is constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRProve( Abc_RRMan_t * p ) +{ + Abc_Ntk_t * pWndCopy; + int RetValue; + pWndCopy = Abc_NtkDup( p->pWnd ); + Abc_NtkRRUpdate( pWndCopy, p->pNode->pCopy, p->pFanin->pCopy, p->pFanout? p->pFanout->pCopy : NULL ); + p->pMiter = Abc_NtkMiter( p->pWnd, pWndCopy, 1 ); + RetValue = Abc_NtkMiterProve( &p->pMiter, p->pParams ); + if ( RetValue == 1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Updates the network after redundancy removal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ) +{ + Abc_Obj_t * pNodeNew, * pFanoutNew; + assert( pFanout == NULL ); + assert( !Abc_ObjIsComplement(pNode) ); + assert( !Abc_ObjIsComplement(pFanin) ); + assert( !Abc_ObjIsComplement(pFanout) ); + // find the node after redundancy removal + if ( pFanin == Abc_ObjFanin0(pNode) ) + pNodeNew = Abc_ObjChild1(pNode); + else if ( pFanin == Abc_ObjFanin1(pNode) ) + pNodeNew = Abc_ObjChild0(pNode); + else assert( 0 ); + // replace + if ( pFanout == NULL ) + { + Abc_AigReplace( pNtk->pManFunc, pNode, pNodeNew, 0 ); + return 1; + } + // find the fanout after redundancy removal + if ( pNode == Abc_ObjFanin0(pFanout) ) + pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC0(pFanout)), Abc_ObjChild1(pFanout) ); + else if ( pNode == Abc_ObjFanin1(pFanout) ) + pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC1(pFanout)), Abc_ObjChild0(pFanout) ); + else assert( 0 ); + // replace + Abc_AigReplace( pNtk->pManFunc, pFanout, pFanoutNew, 0 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Constructs window for checking RR.] + + Description [If the window (p->pWnd) with the given scope (p->nFaninLevels, + p->nFanoutLevels) cannot be constructed, returns 0. Otherwise, returns 1. + The levels are measured from the fanin node (pFanin) and the fanout node + (pEdgeFanout), respectively.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRWindow( Abc_RRMan_t * p ) +{ + Abc_Obj_t * pObj, * pFanout, * pEdgeFanin, * pEdgeFanout; + int i, k; + + // get the edge + pEdgeFanout = p->pFanout? p->pFanout : p->pNode; + pEdgeFanin = p->pFanout? p->pNode : p->pFanin; + + // start the TFI leaves with the fanin + Abc_NtkIncrementTravId( p->pNtk ); + Abc_NodeSetTravIdCurrent( p->pFanin ); + Vec_PtrPush( p->vFaninLeaves, p->pFanin ); + // mark the TFI cone and collect the leaves down to the given level + while ( Abc_NtkRRTfi_int(p->vFaninLeaves, p->pFanin->Level - p->nFaninLevels) ); + + // collect the TFO cone of the leaves + Abc_NtkIncrementTravId( p->pNtk ); + Vec_PtrForEachEntry( p->vFaninLeaves, pObj, i ) + { + Abc_ObjForEachFanout( pObj, pFanout, k ) + { + if ( !Abc_ObjIsNode(pFanout) ) + continue; + if ( pFanout->Level > pEdgeFanout->Level + p->nFanoutLevels ) + continue; + if ( Abc_NodeIsTravIdCurrent(pFanout) ) + continue; + Abc_NodeSetTravIdCurrent( pFanout ); + Vec_PtrPush( p->vFanoutRoots, pFanout ); + } + } + // mark the TFO cone and collect the leaves up to the given level (while skipping the edge) + while ( Abc_NtkRRTfo_int(p->vFanoutRoots, pEdgeFanout->Level + p->nFanoutLevels, pEdgeFanin, pEdgeFanout) ); + // unmark the nodes + Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i ) + pObj->fMarkA = 0; + + // mark the current roots + Abc_NtkIncrementTravId( p->pNtk ); + Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + // collect roots reachable from the fanout (p->vRoots) + if ( !Abc_NtkRRTfo_rec( pEdgeFanout, p->vRoots, pEdgeFanout->Level + p->nFanoutLevels + 5 ) ) + return 0; + + // collect the DFS-ordered new cone (p->vCone) and new leaves (p->vLeaves) + // using the previous marks coming from the TFO cone + Vec_PtrForEachEntry( p->vRoots, pObj, i ) + Abc_NtkRRTfi_rec( pObj, p->vLeaves, p->vCone ); + // unmark the nodes + Vec_PtrForEachEntry( p->vCone, pObj, i ) + pObj->fMarkA = 0; + Vec_PtrForEachEntry( p->vLeaves, pObj, i ) + pObj->fMarkA = 0; + + // create a new network + p->pWnd = Abc_NtkWindow( p->pNtk, p->vLeaves, p->vCone, p->vRoots ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Marks the nodes in the TFI and collects their leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRTfi_int( Vec_Ptr_t * vFaninLeaves, int LevelLimit ) +{ + Abc_Obj_t * pObj, * pNext; + int i, k, LevelMax, nSize; + // find the maximum level of leaves + LevelMax = 0; + Vec_PtrForEachEntry( vFaninLeaves, pObj, i ) + if ( LevelMax < (int)pObj->Level ) + LevelMax = pObj->Level; + // if the nodes are all PIs, LevelMax == 0 + if ( LevelMax == 0 || LevelMax <= LevelLimit ) + return 0; + // expand the nodes with the minimum level + nSize = Vec_PtrSize(vFaninLeaves); + Vec_PtrForEachEntryStop( vFaninLeaves, pObj, i, nSize ) + { + if ( LevelMax != (int)pObj->Level ) + continue; + Abc_ObjForEachFanin( pObj, pNext, k ) + { + if ( Abc_NodeIsTravIdCurrent(pNext) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + Vec_PtrPush( vFaninLeaves, pNext ); + } + } + // remove old nodes (cannot remove a PI) + k = 0; + Vec_PtrForEachEntry( vFaninLeaves, pObj, i ) + { + if ( LevelMax == (int)pObj->Level ) + continue; + Vec_PtrWriteEntry( vFaninLeaves, k++, pObj ); + } + Vec_PtrShrink( vFaninLeaves, k ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Marks the nodes in the TFO and collects their roots.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRTfo_int( Vec_Ptr_t * vFanoutRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ) +{ + Abc_Obj_t * pObj, * pNext; + int i, k, LevelMin, nSize; + // find the minimum level of roots + LevelMin = ABC_INFINITY; + Vec_PtrForEachEntry( vFanoutRoots, pObj, i ) + if ( Abc_ObjIsNode(pObj) && !pObj->fMarkA && LevelMin > (int)pObj->Level ) + LevelMin = pObj->Level; + // if the nodes are all POs, LevelMin == ABC_INFINITY + if ( LevelMin == ABC_INFINITY || LevelMin > LevelLimit ) + return 0; + // expand the nodes with the minimum level + nSize = Vec_PtrSize(vFanoutRoots); + Vec_PtrForEachEntryStop( vFanoutRoots, pObj, i, nSize ) + { + if ( LevelMin != (int)pObj->Level ) + continue; + Abc_ObjForEachFanout( pObj, pNext, k ) + { + if ( !Abc_ObjIsNode(pNext) || pNext->Level > (unsigned)LevelLimit ) + { + pObj->fMarkA = 1; + continue; + } + if ( pObj == pEdgeFanin && pNext == pEdgeFanout ) + continue; + if ( Abc_NodeIsTravIdCurrent(pNext) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + Vec_PtrPush( vFanoutRoots, pNext ); + } + } + // remove old nodes + k = 0; + Vec_PtrForEachEntry( vFanoutRoots, pObj, i ) + { + if ( LevelMin == (int)pObj->Level ) + { + // check if the node has external fanouts + Abc_ObjForEachFanout( pObj, pNext, k ) + { + if ( pObj == pEdgeFanin && pNext == pEdgeFanout ) + continue; + if ( !Abc_NodeIsTravIdCurrent(pNext) ) + break; + } + // if external fanout is found, do not remove the node + if ( pNext ) + continue; + } + Vec_PtrWriteEntry( vFanoutRoots, k++, pObj ); + } + Vec_PtrShrink( vFanoutRoots, k ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Collects the roots in the TFO of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ) +{ + Abc_Obj_t * pFanout; + int i; + if ( Abc_ObjIsCo(pNode) || pNode->Level > (unsigned)LevelLimit ) + return 0; + if ( Abc_NodeIsTravIdCurrent(pNode) ) + { + Vec_PtrPushUnique( vRoots, pNode ); + return 1; + } + Abc_NodeSetTravIdCurrent( pNode ); + Abc_ObjForEachFanout( pNode, pFanout, i ) + if ( !Abc_NtkRRTfo_rec( pFanout, vRoots, LevelLimit ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ) +{ + Abc_Obj_t * pFanin; + int i; + // skip visited nodes + if ( pNode->fMarkA ) + return; + pNode->fMarkA = 1; + // add the node if it was not visited in the previus run + if ( !Abc_NodeIsTravIdPrevious(pNode) ) + { + Vec_PtrPush( vLeaves, pNode ); + return; + } + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NtkRRTfi_rec( pFanin, vLeaves, vCone ); + Vec_PtrPush( vCone, pNode ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( "temp" ); + // map the constant nodes + if ( Abc_NtkConst1(pNtk) ) + Abc_NtkConst1(pNtk)->pCopy = Abc_NtkConst1(pNtkNew); + // create and map the PIs + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + // copy the AND gates + Vec_PtrForEachEntry( vCone, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // compare the number of nodes before and after + if ( Vec_PtrSize(vCone) != Abc_NtkNodeNum(pNtkNew) ) + printf( "Warning: Structural hashing during windowing reduced %d nodes (this is a bug).\n", + Vec_PtrSize(vCone) - Abc_NtkNodeNum(pNtkNew) ); + // create the POs + Vec_PtrForEachEntry( vRoots, pObj, i ) + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObj->pCopy ); + // add the PI/PO names + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkAddDummyPoNames( pNtkNew ); + // check + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkWindow: The network check has failed.\n" ); + return NULL; + } + return pNtkNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abci/abcSat.c b/src/base/abci/abcSat.c index f7400313..9348231b 100644 --- a/src/base/abci/abcSat.c +++ b/src/base/abci/abcSat.c @@ -24,7 +24,7 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); +extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); static nMuxes; //////////////////////////////////////////////////////////////////////// @@ -42,7 +42,7 @@ static nMuxes; SeeAlso [] ***********************************************************************/ -int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nConfLimit, int nImpLimit, int fVerbose ) +int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nConfLimit, int nImpLimit, int fJFront, int fVerbose ) { solver * pSat; lbool status; @@ -56,7 +56,7 @@ int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nConfLimit, int nImpLimit, int fVerbo // load clauses into the solver clk = clock(); - pSat = Abc_NtkMiterSatCreate( pNtk ); + pSat = Abc_NtkMiterSatCreate( pNtk, fJFront ); if ( pSat == NULL ) return 1; // printf( "Created SAT problem with %d variable and %d clauses. ", solver_nvars(pSat), solver_nclauses(pSat) ); @@ -107,6 +107,8 @@ int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int nConfLimit, int nImpLimit, int fVerbo Vec_IntFree( vCiIds ); } // free the solver + if ( fVerbose ) + Asat_SatPrintStats( stdout, pSat ); solver_delete( pSat ); return RetValue; } @@ -391,12 +393,14 @@ void Abc_NtkCollectSupergate( Abc_Obj_t * pNode, int fStopAtMux, Vec_Ptr_t * vNo SeeAlso [] ***********************************************************************/ -int Abc_NtkMiterSatCreateInt( solver * pSat, Abc_Ntk_t * pNtk ) +int Abc_NtkMiterSatCreateInt( solver * pSat, Abc_Ntk_t * pNtk, int fJFront ) { Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE; Vec_Ptr_t * vNodes, * vSuper; - Vec_Int_t * vVars; + Vec_Int_t * vVars, * vFanio; + Vec_Vec_t * vCircuit; int i, k, fUseMuxes = 1; + int clk1 = clock(), clk; assert( Abc_NtkIsStrash(pNtk) ); @@ -408,6 +412,9 @@ int Abc_NtkMiterSatCreateInt( solver * pSat, Abc_Ntk_t * pNtk ) vNodes = Vec_PtrAlloc( 1000 ); // the nodes corresponding to vars in the solver vSuper = Vec_PtrAlloc( 100 ); // the nodes belonging to the given implication supergate vVars = Vec_IntAlloc( 100 ); // the temporary array for variables in the clause + if ( fJFront ) + vCircuit = Vec_VecAlloc( 1000 ); +// vCircuit = Vec_VecStart( 184 ); // add the clause for the constant node pNode = Abc_NtkConst1(pNtk); @@ -485,6 +492,7 @@ int Abc_NtkMiterSatCreateInt( solver * pSat, Abc_Ntk_t * pNtk ) if ( vSuper->nSize == 0 ) { if ( !Abc_NtkClauseTriv( pSat, Abc_ObjNot(pNode), vVars ) ) +// if ( !Abc_NtkClauseTriv( pSat, pNode, vVars ) ) return 0; } else @@ -493,6 +501,32 @@ int Abc_NtkMiterSatCreateInt( solver * pSat, Abc_Ntk_t * pNtk ) return 0; } } + // add the variables to the J-frontier + if ( !fJFront ) + continue; + // make sure that the fanin entries go first + assert( pNode->pCopy ); + Vec_VecExpand( vCircuit, (int)pNode->pCopy ); + vFanio = Vec_VecEntry( vCircuit, (int)pNode->pCopy ); + Vec_PtrForEachEntryReverse( vSuper, pFanin, k ) +// Vec_PtrForEachEntry( vSuper, pFanin, k ) + { + pFanin = Abc_ObjRegular( pFanin ); + assert( pFanin->pCopy && pFanin->pCopy != pNode->pCopy ); + Vec_IntPushFirst( vFanio, (int)pFanin->pCopy ); + Vec_VecPush( vCircuit, (int)pFanin->pCopy, pNode->pCopy ); + } + } + + // create the variable order + if ( fJFront ) + { + clk = clock(); + Asat_JManStart( pSat, vCircuit ); + Vec_VecFree( vCircuit ); + PRT( "Setup", clock() - clk ); +// Asat_JManStop( pSat ); +// PRT( "Total", clock() - clk1 ); } // delete @@ -513,7 +547,7 @@ int Abc_NtkMiterSatCreateInt( solver * pSat, Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk ) +solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fJFront ) { solver * pSat; Abc_Obj_t * pNode; @@ -522,7 +556,7 @@ solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk ) nMuxes = 0; pSat = solver_new(); - RetValue = Abc_NtkMiterSatCreateInt( pSat, pNtk ); + RetValue = Abc_NtkMiterSatCreateInt( pSat, pNtk, fJFront ); Abc_NtkForEachObj( pNtk, pNode, i ) pNode->fMarkA = 0; // Asat_SolverWriteDimacs( pSat, "temp_sat.cnf", NULL, NULL, 1 ); diff --git a/src/base/abci/abcStrash.c b/src/base/abci/abcStrash.c index fbaca324..cfbd4694 100644 --- a/src/base/abci/abcStrash.c +++ b/src/base/abci/abcStrash.c @@ -58,7 +58,13 @@ Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup ) assert( !Abc_NtkIsNetlist(pNtk) ); assert( !Abc_NtkIsSeq(pNtk) ); if ( Abc_NtkIsBddLogic(pNtk) ) - Abc_NtkBddToSop(pNtk, 0); + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Converting to SOPs has failed.\n" ); + return NULL; + } + } // print warning about choice nodes if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" ); @@ -72,7 +78,9 @@ Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes, bool fCleanup ) // if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) // printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) - printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); + { +// printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); + } // duplicate EXDC if ( pNtk->pExdc ) pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); @@ -108,7 +116,13 @@ int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ) assert( Abc_NtkIsStrash(pNtk1) ); assert( Abc_NtkIsLogic(pNtk2) || Abc_NtkIsStrash(pNtk2) ); if ( Abc_NtkIsBddLogic(pNtk2) ) - Abc_NtkBddToSop(pNtk2, 0); + { + if ( !Abc_NtkBddToSop(pNtk2, 0) ) + { + printf( "Converting to SOPs has failed.\n" ); + return 0; + } + } // check that the networks have the same PIs // reorder PIs of pNtk2 according to pNtk1 if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1 ) ) @@ -163,6 +177,7 @@ void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, bool fAllNodes assert( pObj->pCopy == NULL ); // mark the old object with the new AIG node pObj->pCopy = pNodeNew; + Abc_HManAddProto( pObj->pCopy, pObj ); } Vec_PtrFree( vNodes ); Extra_ProgressBarStop( pProgress ); diff --git a/src/base/abci/abcSymm.c b/src/base/abci/abcSymm.c index 35cf896f..fad3bd92 100644 --- a/src/base/abci/abcSymm.c +++ b/src/base/abci/abcSymm.c @@ -88,7 +88,7 @@ void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fVerbose ) // compute the global functions clk = clock(); - dd = Abc_NtkGlobalBdds( pNtk, 10000000, 0 ); + dd = Abc_NtkGlobalBdds( pNtk, 10000000, 0, 1, fVerbose ); Cudd_AutodynDisable( dd ); Cudd_zddVarsFromBddVars( dd, 2 ); clkBdd = clock() - clk; diff --git a/src/base/abci/abcTrace.c b/src/base/abci/abcTrace.c new file mode 100644 index 00000000..0275c0a1 --- /dev/null +++ b/src/base/abci/abcTrace.c @@ -0,0 +1,804 @@ +/**CFile**************************************************************** + + FileName [abcHistory.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcHistory.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_SIM_VARS 16 // the max number of variables in the cone +#define ABC_SIM_OBJS 200 // the max number of objects in the cone + +typedef struct Abc_HMan_t_ Abc_HMan_t; +typedef struct Abc_HObj_t_ Abc_HObj_t; +typedef struct Abc_HNum_t_ Abc_HNum_t; + +struct Abc_HNum_t_ +{ + unsigned fCompl : 1; // set to 1 if the node is complemented + unsigned NtkId : 6; // the network ID + unsigned ObjId : 24; // the node ID +}; + +struct Abc_HObj_t_ +{ + // object info + unsigned fProof : 1; // set to 1 if the node is proved + unsigned fPhase : 1; // set to 1 if the node's phase differs from Old + unsigned fPi : 1; // the node is a PI + unsigned fPo : 1; // the node is a PO + unsigned fConst : 1; // the node is a constant + unsigned fVisited: 1; // the flag shows if the node is visited + unsigned NtkId : 10; // the network ID + unsigned Num : 16; // a temporary number + // history record + Abc_HNum_t Fan0; // immediate fanin + Abc_HNum_t Fan1; // immediate fanin + Abc_HNum_t Proto; // old node if present +// Abc_HNum_t Equ; // equiv node if present +}; + +struct Abc_HMan_t_ +{ + // storage for history information + Vec_Vec_t * vNtks; // the history nodes belonging to each network + Vec_Int_t * vProof; // flags showing if the network is proved + // storage for simulation info + int nVarsMax; // the max number of cone leaves + int nObjsMax; // the max number of cone nodes + Vec_Ptr_t * vObjs; // the cone nodes + int nBits; // the number of simulation bits + int nWords; // the number of unsigneds for siminfo + int nWordsCur; // the current number of words + Vec_Ptr_t * vSims; // simulation info + unsigned * pInfo; // pointer to simulation info + // other info + Vec_Ptr_t * vCone0; + Vec_Ptr_t * vCone1; + // memory manager + Extra_MmFixed_t* pMmObj; // memory manager for objects +}; + +static Abc_HMan_t * s_pHMan = NULL; + +static inline int Abc_HObjProof( Abc_HObj_t * p ) { return p->fProof; } +static inline int Abc_HObjPhase( Abc_HObj_t * p ) { return p->fPhase; } +static inline int Abc_HObjPi ( Abc_HObj_t * p ) { return p->fPi; } +static inline int Abc_HObjPo ( Abc_HObj_t * p ) { return p->fPo; } +static inline int Abc_HObjConst( Abc_HObj_t * p ) { return p->fConst; } +static inline int Abc_HObjNtkId( Abc_HObj_t * p ) { return p->NtkId; } +static inline int Abc_HObjNum ( Abc_HObj_t * p ) { return p->Num; } +static inline Abc_HObj_t * Abc_HObjFanin0( Abc_HObj_t * p ) { return !p->Fan0.NtkId ? NULL : Vec_PtrEntry( Vec_VecEntry(s_pHMan->vNtks, p->Fan0.NtkId), p->Fan0.ObjId ); } +static inline Abc_HObj_t * Abc_HObjFanin1( Abc_HObj_t * p ) { return !p->Fan1.NtkId ? NULL : Vec_PtrEntry( Vec_VecEntry(s_pHMan->vNtks, p->Fan1.NtkId), p->Fan1.ObjId ); } +static inline Abc_HObj_t * Abc_HObjProto ( Abc_HObj_t * p ) { return !p->Proto.NtkId ? NULL : Vec_PtrEntry( Vec_VecEntry(s_pHMan->vNtks, p->Proto.NtkId), p->Proto.ObjId ); } +static inline int Abc_HObjFaninC0( Abc_HObj_t * p ) { return p->Fan0.fCompl; } +static inline int Abc_HObjFaninC1( Abc_HObj_t * p ) { return p->Fan1.fCompl; } + +static inline Abc_HObj_t * Abc_ObjHObj( Abc_Obj_t * p ) { return Vec_PtrEntry( Vec_VecEntry(s_pHMan->vNtks, p->pNtk->Id), p->Id ); } + +static int Abc_HManVerifyPair( int NtkIdOld, int NtkIdNew ); +static int Abc_HManVerifyNodes_rec( Abc_HObj_t * pHOld, Abc_HObj_t * pHNew ); + +static Vec_Ptr_t * Abc_HManCollectLeaves( Abc_HObj_t * pHNew ); +static Vec_Ptr_t * Abc_HManCollectCone( Abc_HObj_t * pHOld, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ); +static int Abc_HManSimulate( Vec_Ptr_t * vCone0, Vec_Ptr_t * vCone1, int nLeaves, int * pPhase ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_HManStart() +{ + Abc_HMan_t * p; + unsigned * pData; + int i, k; + assert( s_pHMan == NULL ); + assert( sizeof(unsigned) == 4 ); + // allocate manager + p = ALLOC( Abc_HMan_t, 1 ); + memset( p, 0, sizeof(Abc_HMan_t) ); + // allocate storage for all nodes + p->vNtks = Vec_VecStart( 1 ); + p->vProof = Vec_IntStart( 1 ); + // allocate temporary storage for objects + p->nVarsMax = ABC_SIM_VARS; + p->nObjsMax = ABC_SIM_OBJS; + p->vObjs = Vec_PtrAlloc( p->nObjsMax ); + // allocate simulation info + p->nBits = (1 << p->nVarsMax); + p->nWords = (p->nBits <= 32)? 1 : (p->nBits / 32); + p->pInfo = ALLOC( unsigned, p->nWords * p->nObjsMax ); + memset( p->pInfo, 0, sizeof(unsigned) * p->nWords * p->nVarsMax ); + p->vSims = Vec_PtrAlloc( p->nObjsMax ); + for ( i = 0; i < p->nObjsMax; i++ ) + Vec_PtrPush( p->vSims, p->pInfo + i * p->nWords ); + // set elementary truth tables + for ( k = 0; k < p->nVarsMax; k++ ) + { + pData = p->vSims->pArray[k]; + for ( i = 0; i < p->nBits; i++ ) + if ( i & (1 << k) ) + pData[i/32] |= (1 << (i%32)); + } + // allocate storage for the nodes + p->pMmObj = Extra_MmFixedStart( sizeof(Abc_HObj_t) ); + p->vCone0 = Vec_PtrAlloc( p->nObjsMax ); + p->vCone1 = Vec_PtrAlloc( p->nObjsMax ); + s_pHMan = p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_HManStop() +{ + assert( s_pHMan != NULL ); + Extra_MmFixedStop( s_pHMan->pMmObj, 0 ); + Vec_PtrFree( s_pHMan->vObjs ); + Vec_PtrFree( s_pHMan->vSims ); + Vec_VecFree( s_pHMan->vNtks ); + Vec_IntFree( s_pHMan->vProof ); + Vec_PtrFree( s_pHMan->vCone0 ); + Vec_PtrFree( s_pHMan->vCone1 ); + free( s_pHMan->pInfo ); + free( s_pHMan ); + s_pHMan = NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_HManIsRunning() +{ + return s_pHMan != NULL; +} + +/**Function************************************************************* + + Synopsis [Called when a new network is created.] + + Description [Returns the new ID for the network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_HManGetNewNtkId() +{ + if ( s_pHMan == NULL ) + return 0; + return Vec_VecSize( s_pHMan->vNtks ); // what if the new network has no nodes? +} + +/**Function************************************************************* + + Synopsis [Called when the object is created.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_HManAddObj( Abc_Obj_t * pObj ) +{ + Abc_HObj_t * pHObj; + if ( s_pHMan == NULL ) + return; + pHObj = (Abc_HObj_t *)Extra_MmFixedEntryFetch( s_pHMan->pMmObj ); + memset( pHObj, 0, sizeof(Abc_HObj_t) ); + // set the object type + pHObj->NtkId = pObj->pNtk->Id; + if ( Abc_ObjIsCi(pObj) ) + pHObj->fPi = 1; + else if ( Abc_ObjIsCo(pObj) ) + pHObj->fPo = 1; + Vec_VecPush( s_pHMan->vNtks, pObj->pNtk->Id, pHObj ); + // set the proof parameter for the network + if ( Vec_IntSize( s_pHMan->vProof ) == pObj->pNtk->Id ) + Vec_IntPush( s_pHMan->vProof, 0 ); +} + +/**Function************************************************************* + + Synopsis [Called when the fanin is added to the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_HManAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +{ + Abc_HObj_t * pHObj; + int fCompl; + if ( s_pHMan == NULL ) + return; + // take off the complemented attribute + assert( !Abc_ObjIsComplement(pObj) ); + fCompl = Abc_ObjIsComplement(pFanin); + pFanin = Abc_ObjRegular(pFanin); + // add the fanin + assert( pObj->pNtk == pFanin->pNtk ); + pHObj = Abc_ObjHObj(pObj); + if ( pHObj->Fan0.NtkId == 0 ) + { + pHObj->Fan0.NtkId = pFanin->pNtk->Id; + pHObj->Fan0.ObjId = pFanin->Id; + pHObj->Fan0.fCompl = fCompl; + } + else if ( pHObj->Fan1.NtkId == 0 ) + { + pHObj->Fan1.NtkId = pFanin->pNtk->Id; + pHObj->Fan1.ObjId = pFanin->Id; + pHObj->Fan1.fCompl = fCompl; + } + else assert( 0 ); +} + +/**Function************************************************************* + + Synopsis [Called when the fanin's input should be complemented.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_HManXorFaninC( Abc_Obj_t * pObj, int iFanin ) +{ + Abc_HObj_t * pHObj; + if ( s_pHMan == NULL ) + return; + assert( iFanin < 2 ); + pHObj = Abc_ObjHObj(pObj); + if ( iFanin == 0 ) + pHObj->Fan0.fCompl ^= 1; + else if ( iFanin == 1 ) + pHObj->Fan1.fCompl ^= 1; +} + +/**Function************************************************************* + + Synopsis [Called when the fanin is added to the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_HManRemoveFanins( Abc_Obj_t * pObj ) +{ + Abc_HObj_t * pHObj; + if ( s_pHMan == NULL ) + return; + assert( !Abc_ObjIsComplement(pObj) ); + pHObj = Abc_ObjHObj(pObj); + pHObj->Fan0.NtkId = 0; + pHObj->Fan0.ObjId = 0; + pHObj->Fan0.fCompl = 0; + pHObj->Fan1.NtkId = 0; + pHObj->Fan1.ObjId = 0; + pHObj->Fan1.fCompl = 0; +} + +/**Function************************************************************* + + Synopsis [Called when a new prototype of the old object is set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_HManAddProto( Abc_Obj_t * pObj, Abc_Obj_t * pProto ) +{ + Abc_HObj_t * pHObj; + if ( s_pHMan == NULL ) + return; + // ignore polarity for now + pObj = Abc_ObjRegular(pObj); + pProto = Abc_ObjRegular(pProto); + // set the prototype + assert( pObj->pNtk != pProto->pNtk ); + if ( pObj->pNtk->Id == 0 ) + return; + pHObj = Abc_ObjHObj(pObj); + pHObj->Proto.NtkId = pProto->pNtk->Id; + pHObj->Proto.ObjId = pProto->Id; +} + +/**Function************************************************************* + + Synopsis [Called when an equivalent node is created.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_HManMapAddEqu( Abc_Obj_t * pObj, Abc_Obj_t * pEqu ) +{ +/* + Abc_HObj_t * pHObj; + if ( s_pHMan == NULL ) + return; + // ignore polarity for now + pObj = Abc_ObjRegular(pObj); + pEqu = Abc_ObjRegular(pEqu); + // set the equivalent node + assert( pObj->pNtk == pEqu->pNtk ); + pHObj = Abc_ObjHObj(pObj); + Abc_ObjHObj(pObj)->Equ.NtkId = pEqu->pNtk->Id; + Abc_ObjHObj(pObj)->Equ.ObjId = pEqu->Id; +*/ +} + + + +/**Function************************************************************* + + Synopsis [Starts the verification procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_HManPopulate( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + if ( !Abc_NtkIsStrash(pNtk) ) + return 0; + // allocate the network ID + pNtk->Id = Abc_HManGetNewNtkId(); + assert( pNtk->Id == 1 ); + // create the objects + Abc_NtkForEachObj( pNtk, pObj, i ) + { + Abc_HManAddObj( pObj ); + if ( Abc_ObjFaninNum(pObj) > 0 ) + Abc_HManAddFanin( pObj, Abc_ObjChild0(pObj) ); + if ( Abc_ObjFaninNum(pObj) > 1 ) + Abc_HManAddFanin( pObj, Abc_ObjChild1(pObj) ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [The main verification procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_HManVerify( int NtkIdOld, int NtkIdNew ) +{ + int i; + // prove the equality pairwise + for ( i = NtkIdOld; i < NtkIdNew; i++ ) + { + if ( Vec_IntEntry(s_pHMan->vProof, i) ) + continue; + if ( !Abc_HManVerifyPair( i, i+1 ) ) + return 0; + Vec_IntWriteEntry( s_pHMan->vProof, i, 1 ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Verifies two networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_HManVerifyPair( int NtkIdOld, int NtkIdNew ) +{ + Vec_Ptr_t * vNtkNew, * vNtkOld, * vPosNew; + Abc_HObj_t * pHObj; + int i; + // get hold of the network nodes + vNtkNew = Vec_VecEntry( s_pHMan->vNtks, NtkIdNew ); + vNtkOld = Vec_VecEntry( s_pHMan->vNtks, NtkIdOld ); + Vec_PtrForEachEntry( vNtkNew, pHObj, i ) + pHObj->fVisited = 0; + Vec_PtrForEachEntry( vNtkOld, pHObj, i ) + pHObj->fVisited = 0; + // collect new POs + vPosNew = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( vNtkNew, pHObj, i ) + if ( pHObj->fPo ) + Vec_PtrPush( vPosNew, pHObj ); + // prove them recursively (assuming PO ordering is the same) + Vec_PtrForEachEntry( vPosNew, pHObj, i ) + { + if ( Abc_HObjProto(pHObj) == NULL ) + { + printf( "History: PO %d has no prototype\n", i ); + return 0; + } + if ( !Abc_HManVerifyNodes_rec( Abc_HObjProto(pHObj), pHObj ) ) + { + printf( "History: Verification failed for outputs of PO pair number %d\n", i ); + return 0; + } + } + printf( "History: Verification succeeded.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Recursively verifies two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_HManVerifyNodes_rec( Abc_HObj_t * pHOld, Abc_HObj_t * pHNew ) +{ + Vec_Ptr_t * vLeaves; + Abc_HObj_t * pHObj, * pHPro0, * pHPro1; + int i, fPhase; + + assert( Abc_HObjProto(pHNew) == pHOld ); + if ( pHNew->fProof ) + return 1; + pHNew->fProof = 1; + // consider simple cases + if ( pHNew->fPi || pHNew->fConst ) + return 1; + if ( pHNew->fPo ) + { + if ( !Abc_HManVerifyNodes_rec( Abc_HObjFanin0(pHOld), Abc_HObjFanin0(pHNew) ) ) + return 0; + if ( (Abc_HObjFaninC0(pHOld) ^ Abc_HObjFaninC0(pHNew)) != (int)pHNew->fPhase ) + { + printf( "History: Phase of PO nodes does not agree.\n" ); + return 0; + } + return 1; + } + // the elementary node + pHPro0 = Abc_HObjProto( Abc_HObjFanin0(pHNew) ); + pHPro1 = Abc_HObjProto( Abc_HObjFanin1(pHNew) ); + if ( pHPro0 && pHPro1 ) + { + if ( !Abc_HManVerifyNodes_rec( pHPro0, Abc_HObjFanin0(pHNew) ) ) + return 0; + if ( !Abc_HManVerifyNodes_rec( pHPro1, Abc_HObjFanin1(pHNew) ) ) + return 0; + if ( Abc_HObjFanin0(pHOld) != pHPro0 || Abc_HObjFanin1(pHOld) != pHPro1 ) + { + printf( "History: Internal node does not match.\n" ); + return 0; + } + if ( Abc_HObjFaninC0(pHOld) != Abc_HObjFaninC0(pHNew) || + Abc_HObjFaninC1(pHOld) != Abc_HObjFaninC1(pHNew) ) + { + printf( "History: Phase of internal node does not match.\n" ); + return 0; + } + return 1; + } + // collect the leaves + vLeaves = Abc_HManCollectLeaves( pHNew ); + if ( Vec_PtrSize(vLeaves) > 16 ) + { + printf( "History: The bound on the number of inputs is exceeded.\n" ); + return 0; + } + s_pHMan->nWordsCur = ((1 << Vec_PtrSize(vLeaves)) <= 32)? 1 : ((1 << Vec_PtrSize(vLeaves)) / 32); + // prove recursively + Vec_PtrForEachEntry( vLeaves, pHObj, i ) + if ( !Abc_HManVerifyNodes_rec( Abc_HObjProto(pHObj), pHObj ) ) + { + Vec_PtrFree( vLeaves ); + return 0; + } + // get the first node + Abc_HManCollectCone( pHNew, vLeaves, s_pHMan->vCone1 ); + if ( Vec_PtrSize(s_pHMan->vCone1) > ABC_SIM_OBJS - ABC_SIM_VARS - 1 ) + { + printf( "History: The bound on the number of cone nodes is exceeded.\n" ); + return 0; + } + // get the second cone + Vec_PtrForEachEntry( vLeaves, pHObj, i ) + Vec_PtrWriteEntry( vLeaves, i, Abc_HObjProto(pHObj) ); + Abc_HManCollectCone( pHOld, vLeaves, s_pHMan->vCone0 ); + if ( Vec_PtrSize(s_pHMan->vCone0) > ABC_SIM_OBJS - ABC_SIM_VARS - 1 ) + { + printf( "History: The bound on the number of cone nodes is exceeded.\n" ); + return 0; + } + // compare the truth tables + if ( !Abc_HManSimulate( s_pHMan->vCone0, s_pHMan->vCone1, Vec_PtrSize(vLeaves), &fPhase ) ) + { + Vec_PtrFree( vLeaves ); + printf( "History: Verification failed at an internal node.\n" ); + return 0; + } + printf( "Succeeded.\n" ); + pHNew->fPhase = fPhase; + Vec_PtrFree( vLeaves ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Finds the leaves of the TFI cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_HManCollectLeaves_rec( Abc_HObj_t * pHNew, Vec_Ptr_t * vLeaves ) +{ + Abc_HObj_t * pHPro; + if ( pHPro = Abc_HObjProto( pHNew ) ) + { + Vec_PtrPushUnique( vLeaves, pHNew ); + return; + } + assert( !pHNew->fPi && !pHNew->fPo && !pHNew->fConst ); + Abc_HManCollectLeaves_rec( Abc_HObjFanin0(pHNew), vLeaves ); + Abc_HManCollectLeaves_rec( Abc_HObjFanin1(pHNew), vLeaves ); +} + +/**Function************************************************************* + + Synopsis [Finds the leaves of the TFI cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_HManCollectLeaves( Abc_HObj_t * pHNew ) +{ + Vec_Ptr_t * vLeaves; + vLeaves = Vec_PtrAlloc( 100 ); + Abc_HManCollectLeaves_rec( Abc_HObjFanin0(pHNew), vLeaves ); + Abc_HManCollectLeaves_rec( Abc_HObjFanin1(pHNew), vLeaves ); + return vLeaves; +} + + +/**Function************************************************************* + + Synopsis [Collects the TFI cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_HManCollectCone_rec( Abc_HObj_t * pHObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ) +{ + if ( pHObj->fVisited ) + return; + pHObj->fVisited = 1; + assert( !pHObj->fPi && !pHObj->fPo && !pHObj->fConst ); + Abc_HManCollectCone_rec( Abc_HObjFanin0(pHObj), vLeaves, vCone ); + Abc_HManCollectCone_rec( Abc_HObjFanin1(pHObj), vLeaves, vCone ); + pHObj->Num = Vec_PtrSize(vCone); + Vec_PtrPush( vCone, pHObj ); +} + +/**Function************************************************************* + + Synopsis [Collects the TFI cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_HManCollectCone( Abc_HObj_t * pHRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ) +{ + Abc_HObj_t * pHObj; + int i; + Vec_PtrClear( vCone ); + Vec_PtrForEachEntry( vLeaves, pHObj, i ) + { + pHObj->fVisited = 1; + pHObj->Num = Vec_PtrSize(vCone); + Vec_PtrPush( vCone, pHObj ); + } + Abc_HManCollectCone_rec( Abc_HObjFanin0(pHRoot), vLeaves, vCone ); + Abc_HManCollectCone_rec( Abc_HObjFanin1(pHRoot), vLeaves, vCone ); + return vCone; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_HManSimulateOne( Vec_Ptr_t * vCone, int nLeaves, int fUsePhase ) +{ + Abc_HObj_t * pHObj, * pHFan0, * pHFan1; + unsigned * puData0, * puData1, * puData; + int k, i, fComp0, fComp1; + // set the leaves + Vec_PtrForEachEntryStart( vCone, pHObj, i, nLeaves ) + { + pHFan0 = Abc_HObjFanin0(pHObj); + pHFan1 = Abc_HObjFanin1(pHObj); + // consider the case of interver or buffer + if ( pHFan1 == NULL ) + { + puData = Vec_PtrEntry(s_pHMan->vSims, ABC_SIM_VARS+i-nLeaves); + puData0 = ((int)pHFan0->Num < nLeaves)? Vec_PtrEntry(s_pHMan->vSims, pHFan0->Num) : + Vec_PtrEntry(s_pHMan->vSims, ABC_SIM_VARS+pHFan0->Num-nLeaves); + fComp0 = Abc_HObjFaninC0(pHObj) ^ (fUsePhase && (int)pHFan0->Num < nLeaves && pHFan0->fPhase); + if ( fComp0 ) + for ( k = 0; k < s_pHMan->nWordsCur; k++ ) + puData[k] = ~puData0[k]; + else + for ( k = 0; k < s_pHMan->nWordsCur; k++ ) + puData[k] = puData0[k]; + continue; + } + // get the pointers to simulation data + puData = Vec_PtrEntry(s_pHMan->vSims, ABC_SIM_VARS+i-nLeaves); + puData0 = ((int)pHFan0->Num < nLeaves)? Vec_PtrEntry(s_pHMan->vSims, pHFan0->Num) : + Vec_PtrEntry(s_pHMan->vSims, ABC_SIM_VARS+pHFan0->Num-nLeaves); + puData1 = ((int)pHFan1->Num < nLeaves)? Vec_PtrEntry(s_pHMan->vSims, pHFan1->Num) : + Vec_PtrEntry(s_pHMan->vSims, ABC_SIM_VARS+pHFan1->Num-nLeaves); + // here are the phases + fComp0 = Abc_HObjFaninC0(pHObj) ^ (fUsePhase && (int)pHFan0->Num < nLeaves && pHFan0->fPhase); + fComp1 = Abc_HObjFaninC1(pHObj) ^ (fUsePhase && (int)pHFan1->Num < nLeaves && pHFan1->fPhase); + // simulate + if ( fComp0 && fComp1 ) + for ( k = 0; k < s_pHMan->nWordsCur; k++ ) + puData[k] = ~puData0[k] & ~puData1[k]; + else if ( fComp0 ) + for ( k = 0; k < s_pHMan->nWordsCur; k++ ) + puData[k] = ~puData0[k] & puData1[k]; + else if ( fComp1 ) + for ( k = 0; k < s_pHMan->nWordsCur; k++ ) + puData[k] = puData0[k] & ~puData1[k]; + else + for ( k = 0; k < s_pHMan->nWordsCur; k++ ) + puData[k] = puData0[k] & puData1[k]; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_HManSimulate( Vec_Ptr_t * vCone0, Vec_Ptr_t * vCone1, int nLeaves, int * pPhase ) +{ + unsigned * pDataTop, * pDataLast; + int w; + // simulate the first one + Abc_HManSimulateOne( vCone0, nLeaves, 0 ); + // save the last simulation value + pDataTop = Vec_PtrEntry( s_pHMan->vSims, ((Abc_HObj_t *)Vec_PtrEntryLast(vCone0))->Num ); + pDataLast = Vec_PtrEntry( s_pHMan->vSims, Vec_PtrSize(s_pHMan->vSims)-1 ); + for ( w = 0; w < s_pHMan->nWordsCur; w++ ) + pDataLast[w] = pDataTop[w]; + // simulate the other one + Abc_HManSimulateOne( vCone1, nLeaves, 1 ); + // complement the output if needed + pDataTop = Vec_PtrEntry( s_pHMan->vSims, ((Abc_HObj_t *)Vec_PtrEntryLast(vCone1))->Num ); + // mask unused bits + if ( nLeaves < 5 ) + { + pDataTop[0] &= ((~((unsigned)0)) >> (32-(1<<nLeaves))); + pDataLast[0] &= ((~((unsigned)0)) >> (32-(1<<nLeaves))); + } + if ( *pPhase = ((pDataTop[0] & 1) != (pDataLast[0] & 1)) ) + for ( w = 0; w < s_pHMan->nWordsCur; w++ ) + pDataTop[w] = ~pDataTop[w]; + // compare + for ( w = 0; w < s_pHMan->nWordsCur; w++ ) + if ( pDataLast[w] != pDataTop[w] ) + return 0; + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abci/abcUnate.c b/src/base/abci/abcUnate.c index 88188655..48b7eb92 100644 --- a/src/base/abci/abcUnate.c +++ b/src/base/abci/abcUnate.c @@ -73,7 +73,7 @@ void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose ) int clkBdd, clkUnate; // compute the global BDDs - if ( Abc_NtkGlobalBdds(pNtk, 10000000, 0) == NULL ) + if ( Abc_NtkGlobalBdds(pNtk, 10000000, 0, 1, fVerbose) == NULL ) return; clkBdd = clock() - clk; diff --git a/src/base/abci/abcUnreach.c b/src/base/abci/abcUnreach.c index 5690013b..f1ec3847 100644 --- a/src/base/abci/abcUnreach.c +++ b/src/base/abci/abcUnreach.c @@ -58,7 +58,7 @@ int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose ) } // compute the global BDDs of the latches - dd = Abc_NtkGlobalBdds( pNtk, 10000000, 1 ); + dd = Abc_NtkGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); if ( dd == NULL ) return 0; if ( fVerbose ) @@ -331,7 +331,11 @@ Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUn Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // transform the network to the SOP representation - Abc_NtkBddToSop( pNtkNew, 0 ); + if ( !Abc_NtkBddToSop( pNtkNew, 0 ) ) + { + printf( "Converting to SOPs has failed.\n" ); + return NULL; + } return pNtkNew; } diff --git a/src/base/abci/abcVanEijk.c b/src/base/abci/abcVanEijk.c index c178c013..8d8784e0 100644 --- a/src/base/abci/abcVanEijk.c +++ b/src/base/abci/abcVanEijk.c @@ -713,7 +713,7 @@ Fraig_Man_t * Abc_NtkVanEijkFraig( Abc_Ntk_t * pMulti, int fInit ) Abc_Ntk_t * Abc_NtkVanEijkDeriveExdc( Abc_Ntk_t * pNtk, Vec_Ptr_t * vClasses ) { Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pClass, * pNode, * pRepr, * pObj, *pObjNew; + Abc_Obj_t * pClass, * pNode, * pRepr, * pObj;//, *pObjNew; Abc_Obj_t * pMiter, * pTotal; Vec_Ptr_t * vCone; int i, k; diff --git a/src/base/abci/abcVanImp.c b/src/base/abci/abcVanImp.c index c92667a3..77de5185 100644 --- a/src/base/abci/abcVanImp.c +++ b/src/base/abci/abcVanImp.c @@ -870,7 +870,7 @@ Abc_Ntk_t * Abc_NtkVanImpDeriveExdc( Abc_Ntk_t * pNtk, Vec_Ptr_t * vZeros, Vec_I { Abc_Ntk_t * pNtkNew; Vec_Ptr_t * vCone; - Abc_Obj_t * pObj, * pMiter, * pTotal, * pNode, * pNode1, * pNode2, * pObjNew; + Abc_Obj_t * pObj, * pMiter, * pTotal, * pNode, * pNode1, * pNode2;//, * pObjNew; unsigned Imp; int i, k; diff --git a/src/base/abci/abcVerify.c b/src/base/abci/abcVerify.c index 5456693b..e0c65058 100644 --- a/src/base/abci/abcVerify.c +++ b/src/base/abci/abcVerify.c @@ -85,7 +85,7 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nI } // solve the CNF using the SAT solver - RetValue = Abc_NtkMiterSat( pCnf, nConfLimit, nImpLimit, 0 ); + RetValue = Abc_NtkMiterSat( pCnf, nConfLimit, nImpLimit, 0, 0 ); if ( RetValue == -1 ) printf( "Networks are undecided (SAT solver timed out).\n" ); else if ( RetValue == 0 ) @@ -112,6 +112,7 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nI ***********************************************************************/ void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ) { + Prove_Params_t Params, * pParams = &Params; // Fraig_Params_t Params; // Fraig_Man_t * pMan; Abc_Ntk_t * pMiter; @@ -171,7 +172,9 @@ void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fV Abc_NtkDelete( pMiter ); */ // solve the CNF using the SAT solver - RetValue = Abc_NtkMiterProve( &pMiter, 0, 0, 1, 1, 0 ); + Prove_ParamsSetDefault( pParams ); + pParams->nItersMax = 5; + RetValue = Abc_NtkMiterProve( &pMiter, pParams ); if ( RetValue == -1 ) printf( "Networks are undecided (resource limits is reached).\n" ); else if ( RetValue == 0 ) @@ -254,7 +257,7 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nI } // solve the CNF using the SAT solver - RetValue = Abc_NtkMiterSat( pCnf, nConfLimit, nImpLimit, 0 ); + RetValue = Abc_NtkMiterSat( pCnf, nConfLimit, nImpLimit, 0, 0 ); if ( RetValue == -1 ) printf( "Networks are undecided (SAT solver timed out).\n" ); else if ( RetValue == 0 ) diff --git a/src/base/abci/abc_.c b/src/base/abci/abc_.c index 50558bdb..75ec88c3 100644 --- a/src/base/abci/abc_.c +++ b/src/base/abci/abc_.c @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// - + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -40,6 +40,7 @@ ***********************************************************************/ + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/module.make b/src/base/abci/module.make index 4339b520..41223c0b 100644 --- a/src/base/abci/module.make +++ b/src/base/abci/module.make @@ -10,6 +10,7 @@ SRC += src/base/abci/abc.c \ src/base/abci/abcFpga.c \ src/base/abci/abcFraig.c \ src/base/abci/abcFxu.c \ + src/base/abci/abcGen.c \ src/base/abci/abcMap.c \ src/base/abci/abcMiter.c \ src/base/abci/abcNtbdd.c \ @@ -22,11 +23,13 @@ SRC += src/base/abci/abc.c \ src/base/abci/abcRestruct.c \ src/base/abci/abcResub.c \ src/base/abci/abcRewrite.c \ + src/base/abci/abcRr.c \ src/base/abci/abcSat.c \ src/base/abci/abcStrash.c \ src/base/abci/abcSweep.c \ src/base/abci/abcSymm.c \ src/base/abci/abcTiming.c \ + src/base/abci/abcTrace.c \ src/base/abci/abcUnate.c \ src/base/abci/abcUnreach.c \ src/base/abci/abcVanEijk.c \ diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index c2c09697..0d90679d 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -18,6 +18,10 @@ ***********************************************************************/ +#ifdef WIN32 +#include <process.h> +#endif + #include "mainInt.h" #include "cmdInt.h" #include "abc.h" @@ -45,6 +49,7 @@ static int CmdCommandLs ( Abc_Frame_t * pAbc, int argc, char ** argv #endif static int CmdCommandSis ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandMvsis ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandCapo ( Abc_Frame_t * pAbc, int argc, char ** argv ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -85,6 +90,7 @@ void Cmd_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "sis", CmdCommandSis, 1); Cmd_CommandAdd( pAbc, "Various", "mvsis", CmdCommandMvsis, 1); + Cmd_CommandAdd( pAbc, "Various", "capo", CmdCommandCapo, 0); } /**Function******************************************************************** @@ -1253,6 +1259,11 @@ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv ) // write out the current network pNetlist = Abc_NtkLogicToNetlist(pNtk,0); + if ( pNetlist == NULL ) + { + fprintf( pErr, "Cannot produce the intermediate network.\n" ); + goto usage; + } Io_WriteBlif( pNetlist, "_sis_in.blif", 1 ); Abc_NtkDelete( pNetlist ); @@ -1389,6 +1400,11 @@ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv ) // write out the current network pNetlist = Abc_NtkLogicToNetlist(pNtk,0); + if ( pNetlist == NULL ) + { + fprintf( pErr, "Cannot produce the intermediate network.\n" ); + goto usage; + } Io_WriteBlif( pNetlist, "_mvsis_in.blif", 1 ); Abc_NtkDelete( pNetlist ); @@ -1454,6 +1470,190 @@ usage: } +/**Function******************************************************************** + + Synopsis [Calls Capo internally.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandCapo( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pFile; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNetlist; + char Command[1000], Buffer[100]; + char * pProgNameCapoWin = "capo.exe"; + char * pProgNameCapoUnix = "capo"; + char * pProgNameGnuplotWin = "wgnuplot.exe"; + char * pProgNameGnuplotUnix = "gnuplot"; + char * pProgNameCapo; + char * pProgNameGnuplot; + char * pPlotFileName; + int i; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + goto usage; + } + + if ( strcmp( argv[0], "capo" ) != 0 ) + { + fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); + goto usage; + } + + if ( argc > 1 ) + { + if ( strcmp( argv[1], "-h" ) == 0 ) + goto usage; + if ( strcmp( argv[1], "-?" ) == 0 ) + goto usage; + } + + // get the names from the resource file + if ( Cmd_FlagReadByName(pAbc, "capowin") ) + pProgNameCapoWin = Cmd_FlagReadByName(pAbc, "capowin"); + if ( Cmd_FlagReadByName(pAbc, "capounix") ) + pProgNameCapoUnix = Cmd_FlagReadByName(pAbc, "capounix"); + + // check if capo is available + if ( (pFile = fopen( pProgNameCapoWin, "r" )) ) + pProgNameCapo = pProgNameCapoWin; + else if ( (pFile = fopen( pProgNameCapoUnix, "r" )) ) + pProgNameCapo = pProgNameCapoUnix; + else if ( pFile == NULL ) + { + fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameCapoWin, pProgNameCapoUnix ); + goto usage; + } + fclose( pFile ); + + if ( Abc_NtkIsMappedLogic(pNtk) ) + { + Abc_NtkUnmap(pNtk); + printf( "The current network is unmapped before calling Capo.\n" ); + } + + // write out the current network + pNetlist = Abc_NtkLogicToNetlist(pNtk,0); + if ( pNetlist == NULL ) + { + fprintf( pErr, "Cannot produce the intermediate network.\n" ); + goto usage; + } + Io_WriteBlif( pNetlist, "_capo_in.blif", 1 ); + Abc_NtkDelete( pNetlist ); + + // create the file for Capo + sprintf( Command, "%s -f _capo_in.blif -log out.txt ", pProgNameCapo ); + pPlotFileName = NULL; + for ( i = 1; i < argc; i++ ) + { + sprintf( Buffer, " %s", argv[i] ); + strcat( Command, Buffer ); + if ( !strcmp( argv[i], "-plot" ) ) + pPlotFileName = argv[i+1]; + } + + // call Capo + if ( system( Command ) ) + { + fprintf( pErr, "The following command has returned non-zero exit status:\n" ); + fprintf( pErr, "\"%s\"\n", Command ); + unlink( "_capo_in.blif" ); + goto usage; + } + // remove temporary networks + unlink( "_capo_in.blif" ); + if ( pPlotFileName == NULL ) + return 0; + + // get the file name + sprintf( Buffer, "%s.plt", pPlotFileName ); + pPlotFileName = Buffer; + + // read in the Capo plotting output + if ( (pFile = fopen( pPlotFileName, "r" )) == NULL ) + { + fprintf( pErr, "Cannot open the plot file \"%s\".\n\n", pPlotFileName ); + goto usage; + } + fclose( pFile ); + + // get the names from the plotting software + if ( Cmd_FlagReadByName(pAbc, "gnuplotwin") ) + pProgNameGnuplotWin = Cmd_FlagReadByName(pAbc, "gnuplotwin"); + if ( Cmd_FlagReadByName(pAbc, "gnuplotunix") ) + pProgNameGnuplotUnix = Cmd_FlagReadByName(pAbc, "gnuplotunix"); + + // check if Gnuplot is available + if ( (pFile = fopen( pProgNameGnuplotWin, "r" )) ) + pProgNameGnuplot = pProgNameGnuplotWin; + else if ( (pFile = fopen( pProgNameGnuplotUnix, "r" )) ) + pProgNameGnuplot = pProgNameGnuplotUnix; + else if ( pFile == NULL ) + { + fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameGnuplotWin, pProgNameGnuplotUnix ); + goto usage; + } + fclose( pFile ); + + // spawn the viewer +#ifdef WIN32 + if ( _spawnl( _P_NOWAIT, pProgNameGnuplot, pProgNameGnuplot, pPlotFileName, NULL ) == -1 ) + { + fprintf( stdout, "Cannot find \"%s\".\n", pProgNameGnuplot ); + goto usage; + } +#else + { + sprintf( Command, "%s %s ", pProgNameGnuplot, pPlotFileName ); + if ( system( Command ) == -1 ) + { + fprintf( stdout, "Cannot execute \"%s\".\n", Command ); + goto usage; + } + } +#endif + + // remove temporary networks +// unlink( pPlotFileName ); + return 0; + +usage: + fprintf( pErr, "\n" ); + fprintf( pErr, "Usage: capo [-h] <com>\n"); + fprintf( pErr, " peforms placement of the current network using Capo\n" ); + fprintf( pErr, " a Capo binary should be present in the same directory\n" ); + fprintf( pErr, " (if plotting, the Gnuplot binary should also be present)\n" ); + fprintf( pErr, " -h : print the command usage\n" ); + fprintf( pErr, " <com> : a Capo command\n" ); + fprintf( pErr, " Example 1: capo\n" ); + fprintf( pErr, " (performs placement with default options)\n" ); + fprintf( pErr, " Example 2: capo -AR <aspec_ratio> -WS <whitespace_percentage> -save\n" ); + fprintf( pErr, " (specifies the aspect ratio [default = 1.0] and\n" ); + fprintf( pErr, " the whitespace percentage [0%%; 100%%) [default = 15%%])\n" ); + fprintf( pErr, " Example 3: capo -plot <base_fileName>\n" ); + fprintf( pErr, " (produces <base_fileName.plt> and visualize it using Gnuplot)\n" ); + fprintf( pErr, " Example 4: capo -help\n" ); + fprintf( pErr, " (prints the default usage message of the Capo binary)\n" ); + fprintf( pErr, " Please refer to the Capo webpage for additional information:\n" ); + fprintf( pErr, " http://vlsicad.eecs.umich.edu/BK/PDtools/\n" ); + return 1; // error exit +} + + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/io/ioRead.c b/src/base/io/ioRead.c index 6422461c..70e648a7 100644 --- a/src/base/io/ioRead.c +++ b/src/base/io/ioRead.c @@ -42,6 +42,9 @@ Abc_Ntk_t * Io_Read( char * pFileName, int fCheck ) { Abc_Ntk_t * pNtk, * pTemp; +// extern int s_TotalNodes; +// extern int s_TotalChanges; +// s_TotalNodes = s_TotalChanges = 0; // set the new network if ( Extra_FileNameCheckExtension( pFileName, "blif" ) ) pNtk = Io_ReadBlif( pFileName, fCheck ); diff --git a/src/base/io/ioReadBench.c b/src/base/io/ioReadBench.c index 1cb0ae5d..aa7f82e3 100644 --- a/src/base/io/ioReadBench.c +++ b/src/base/io/ioReadBench.c @@ -136,7 +136,7 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) Abc_ObjSetData( pNode, Abc_SopCreateNor(pNtk->pManFunc, nNames) ); else if ( strcmp(pType, "XOR") == 0 ) Abc_ObjSetData( pNode, Abc_SopCreateXor(pNtk->pManFunc, nNames) ); - else if ( strcmp(pType, "NXOR") == 0 ) + else if ( strcmp(pType, "NXOR") == 0 || strcmp(pType, "XNOR") == 0 ) Abc_ObjSetData( pNode, Abc_SopCreateNxor(pNtk->pManFunc, nNames) ); else if ( strncmp(pType, "BUF", 3) == 0 ) Abc_ObjSetData( pNode, Abc_SopCreateBuf(pNtk->pManFunc) ); diff --git a/src/base/io/ioWriteCnf.c b/src/base/io/ioWriteCnf.c index 9e5ceb9f..24612566 100644 --- a/src/base/io/ioWriteCnf.c +++ b/src/base/io/ioWriteCnf.c @@ -23,6 +23,8 @@ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * s_pNtk = NULL; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -57,15 +59,51 @@ int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName ) fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter for combinational circuits.\n" ); return 0; } + if ( Abc_NtkNodeNum(pNtk) == 0 ) + { + fprintf( stdout, "The network has no logic nodes. No CNF file is generaled.\n" ); + return 0; + } // create solver with clauses - pSat = Abc_NtkMiterSatCreate( pNtk ); + pSat = Abc_NtkMiterSatCreate( pNtk, 0 ); + if ( pSat == NULL ) + { + fprintf( stdout, "The problem is trivially UNSAT. No CNF file is generated.\n" ); + return 1; + } // write the clauses + s_pNtk = pNtk; Asat_SolverWriteDimacs( pSat, pFileName, 0, 0, 1 ); + s_pNtk = NULL; // free the solver solver_delete( pSat ); return 1; } +/**Function************************************************************* + + Synopsis [Output the mapping of PIs into variable numbers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteCnfOutputPiMapping( FILE * pFile, int incrementVars ) +{ + extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); + Abc_Ntk_t * pNtk = s_pNtk; + Vec_Int_t * vCiIds; + Abc_Obj_t * pObj; + int i; + vCiIds = Abc_NtkGetCiSatVarNums( pNtk ); + fprintf( pFile, "c PI variable numbers: <PI_name> <SAT_var_number>\n" ); + Abc_NtkForEachCi( pNtk, pObj, i ) + fprintf( pFile, "c %s %d\n", Abc_ObjName(pObj), Vec_IntEntry(vCiIds, i) + (int)(incrementVars > 0) ); + Vec_IntFree( vCiIds ); +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c index dbf157bf..ed6acb24 100644 --- a/src/base/io/ioWriteDot.c +++ b/src/base/io/ioWriteDot.c @@ -412,7 +412,13 @@ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesSho // transform logic functions from BDD to SOP if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) - Abc_NtkBddToSop(pNtk, 0); + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Converting to SOPs has failed.\n" ); + return; + } + } // mark the nodes from the set Vec_PtrForEachEntry( vNodes, pNode, i ) diff --git a/src/base/io/ioWriteList.c b/src/base/io/ioWriteList.c index ab216eb3..f0981a8e 100644 --- a/src/base/io/ioWriteList.c +++ b/src/base/io/ioWriteList.c @@ -120,8 +120,8 @@ void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ) if ( Abc_ObjFanoutNum( Abc_NtkConst1(pNtk) ) > 0 ) Io_WriteListEdge( pFile, Abc_NtkConst1(pNtk) ); - // write the PO edges - Abc_NtkForEachCi( pNtk, pObj, i ) + // write the PI edges + Abc_NtkForEachPi( pNtk, pObj, i ) Io_WriteListEdge( pFile, pObj ); // write the internal nodes @@ -132,7 +132,7 @@ void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ) if ( fUseHost ) Io_WriteListHost( pFile, pNtk ); else - Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_NtkForEachPo( pNtk, pObj, i ) Io_WriteListEdge( pFile, pObj ); fprintf( pFile, "\n" ); @@ -157,12 +157,13 @@ void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj ) fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) ); Abc_ObjForEachFanout( pObj, pFanout, i ) { - fprintf( pFile, " %s ([%s_to_%s] = %d)", Abc_ObjName(pFanout), Abc_ObjName(pObj), Abc_ObjName(pFanout), Seq_ObjFanoutL(pObj, pFanout) ); - if ( i == Abc_ObjFanoutNum(pObj) - 1 ) - fprintf( pFile, "." ); - else + fprintf( pFile, " %s", Abc_ObjName(pFanout) ); + fprintf( pFile, " ([%s_to_", Abc_ObjName(pObj) ); + fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), Seq_ObjFanoutL(pObj, pFanout) ); + if ( i != Abc_ObjFanoutNum(pObj) - 1 ) fprintf( pFile, "," ); } + fprintf( pFile, "." ); fprintf( pFile, "\n" ); } @@ -186,22 +187,19 @@ void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk ) { fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) ); fprintf( pFile, " %s ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), "HOST", 0 ); - if ( i == Abc_NtkPoNum(pNtk) - 1 ) - fprintf( pFile, "." ); - else - fprintf( pFile, "," ); + fprintf( pFile, "." ); + fprintf( pFile, "\n" ); } - fprintf( pFile, "\n" ); fprintf( pFile, "%-10s > ", "HOST" ); Abc_NtkForEachPi( pNtk, pObj, i ) { - fprintf( pFile, " %s ([%s_to_%s] = %d)", Abc_ObjName(pObj), "HOST", Abc_ObjName(pObj), 0 ); - if ( i == Abc_NtkPiNum(pNtk) - 1 ) - fprintf( pFile, "." ); - else + fprintf( pFile, " %s", Abc_ObjName(pObj) ); + fprintf( pFile, " ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), 0 ); + if ( i != Abc_NtkPiNum(pNtk) - 1 ) fprintf( pFile, "," ); } + fprintf( pFile, "." ); fprintf( pFile, "\n" ); } diff --git a/src/base/main/main.h b/src/base/main/main.h index 9b483904..fe511314 100644 --- a/src/base/main/main.h +++ b/src/base/main/main.h @@ -81,6 +81,7 @@ extern FILE * Abc_FrameReadErr( Abc_Frame_t * p ); extern bool Abc_FrameReadMode( Abc_Frame_t * p ); extern bool Abc_FrameSetMode( Abc_Frame_t * p, bool fNameMode ); extern void Abc_FrameRestart( Abc_Frame_t * p ); +extern bool Abc_FrameShowProgress( Abc_Frame_t * p ); extern void Abc_FrameSetCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNet ); extern void Abc_FrameSwapCurrentAndBackup( Abc_Frame_t * p ); diff --git a/src/base/main/mainFrame.c b/src/base/main/mainFrame.c index b3208740..5747443c 100644 --- a/src/base/main/mainFrame.c +++ b/src/base/main/mainFrame.c @@ -111,9 +111,12 @@ 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(); + // initialize the trace manager +// Abc_HManStart(); return p; } @@ -132,6 +135,7 @@ Abc_Frame_t * Abc_FrameAllocate() void Abc_FrameDeallocate( Abc_Frame_t * p ) { extern void undefine_cube_size(); +// Abc_HManStop(); undefine_cube_size(); if ( p->pManDec ) Dec_ManStop( p->pManDec ); if ( p->dd ) Extra_StopManager( p->dd ); @@ -155,6 +159,22 @@ void Abc_FrameRestart( Abc_Frame_t * p ) { } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_FrameShowProgress( Abc_Frame_t * p ) +{ + return p->fProgress; +} + /**Function************************************************************* diff --git a/src/base/main/mainInt.h b/src/base/main/mainInt.h index d2bca1ab..109e91c8 100644 --- a/src/base/main/mainInt.h +++ b/src/base/main/mainInt.h @@ -55,6 +55,7 @@ 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/base/seq/seqAigCore.c b/src/base/seq/seqAigCore.c index e74f3fa7..813b1ed8 100644 --- a/src/base/seq/seqAigCore.c +++ b/src/base/seq/seqAigCore.c @@ -358,7 +358,7 @@ int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int // solve the miter clk = clock(); // RetValue = Abc_NtkMiterSat_OldAndRusty( pNtkCnf, 30, 0 ); - RetValue = Abc_NtkMiterSat( pNtkCnf, 500000, 50000000, 0 ); + RetValue = Abc_NtkMiterSat( pNtkCnf, 500000, 50000000, 0, 0 ); if ( fVerbose ) if ( clock() - clk > 100 ) { diff --git a/src/base/seq/seqMapIter.c b/src/base/seq/seqMapIter.c index 67ac4a7d..185c05f3 100644 --- a/src/base/seq/seqMapIter.c +++ b/src/base/seq/seqMapIter.c @@ -613,7 +613,7 @@ void Seq_MapCanonicizeTruthTables( Abc_Ntk_t * pNtk ) if ( pList == NULL ) continue; for ( pCut = pList->pNext; pCut; pCut = pCut->pNext ) - Cut_TruthCanonicize( pCut ); + Cut_TruthNCanonicize( pCut ); } } diff --git a/src/base/seq/seqRetCore.c b/src/base/seq/seqRetCore.c index 0805a838..38915bf4 100644 --- a/src/base/seq/seqRetCore.c +++ b/src/base/seq/seqRetCore.c @@ -107,7 +107,13 @@ Abc_Ntk_t * Seq_NtkRetimeDerive( Abc_Ntk_t * pNtk, int fVerbose ) // transform logic functions from BDD to SOP if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) - Abc_NtkBddToSop(pNtk, 0); + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Converting to SOPs has failed.\n" ); + return NULL; + } + } // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_SEQ, ABC_FUNC_AIG ); diff --git a/src/map/pga/pgaMatch.c b/src/map/pga/pgaMatch.c index a4c57089..086a85d4 100644 --- a/src/map/pga/pgaMatch.c +++ b/src/map/pga/pgaMatch.c @@ -73,7 +73,7 @@ void Pga_MappingMatches( Pga_Man_t * p, int Mode ) continue; // get the cuts clk = clock(); - pList = Abc_NodeGetCutsRecursive( p->pManCut, pObj, 0 ); + pList = Abc_NodeGetCutsRecursive( p->pManCut, pObj, 0, 0 ); p->timeCuts += clock() - clk; // match the node Pga_MappingMatchNode( p, pObj->Id, pList, Mode ); diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h index 1b6abaa6..e02ec82a 100644 --- a/src/misc/extra/extra.h +++ b/src/misc/extra/extra.h @@ -293,6 +293,8 @@ extern char * Extra_TimeStamp(); extern char * Extra_StringAppend( char * pStrGiven, char * pStrAdd ); extern unsigned Extra_ReadBinary( char * Buffer ); extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ); +extern int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars ); +extern void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ); extern void Extra_PrintHex( FILE * pFile, unsigned uTruth, int nVars ); extern void Extra_PrintSymbols( FILE * pFile, char Char, int nTimes, int fPrintNewLine ); @@ -390,30 +392,68 @@ extern void Extra_ProgressBarStop( ProgressBar * p ); extern void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString ); static inline void Extra_ProgressBarUpdate( ProgressBar * p, int nItemsCur, char * pString ) -{ if ( nItemsCur < *((int*)p) ) return; Extra_ProgressBarUpdate_int(p, nItemsCur, pString); } - -/*=== extraUtilIntVec.c ================================================================*/ - -typedef struct Extra_IntVec_t_ Extra_IntVec_t; -extern Extra_IntVec_t * Extra_IntVecAlloc( int nCap ); -extern Extra_IntVec_t * Extra_IntVecAllocArray( int * pArray, int nSize ); -extern Extra_IntVec_t * Extra_IntVecAllocArrayCopy( int * pArray, int nSize ); -extern Extra_IntVec_t * Extra_IntVecDup( Extra_IntVec_t * pVec ); -extern Extra_IntVec_t * Extra_IntVecDupArray( Extra_IntVec_t * pVec ); -extern void Extra_IntVecFree( Extra_IntVec_t * p ); -extern void Extra_IntVecFill( Extra_IntVec_t * p, int nSize, int Entry ); -extern int * Extra_IntVecReleaseArray( Extra_IntVec_t * p ); -extern int * Extra_IntVecReadArray( Extra_IntVec_t * p ); -extern int Extra_IntVecReadSize( Extra_IntVec_t * p ); -extern int Extra_IntVecReadEntry( Extra_IntVec_t * p, int i ); -extern int Extra_IntVecReadEntryLast( Extra_IntVec_t * p ); -extern void Extra_IntVecWriteEntry( Extra_IntVec_t * p, int i, int Entry ); -extern void Extra_IntVecGrow( Extra_IntVec_t * p, int nCapMin ); -extern void Extra_IntVecShrink( Extra_IntVec_t * p, int nSizeNew ); -extern void Extra_IntVecClear( Extra_IntVec_t * p ); -extern void Extra_IntVecPush( Extra_IntVec_t * p, int Entry ); -extern int Extra_IntVecPop( Extra_IntVec_t * p ); -extern void Extra_IntVecSort( Extra_IntVec_t * p ); +{ if ( p && nItemsCur < *((int*)p) ) return; Extra_ProgressBarUpdate_int(p, nItemsCur, pString); } + +/*=== extraUtilTruth.c ================================================================*/ + +static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline int Extra_WordCountOnes( unsigned uWord ) +{ + uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); + uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); + uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); + uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); + return (uWord & 0x0000FFFF) + (uWord>>16); +} +static inline int Extra_TruthIsEqual( unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn0[w] != pIn1[w] ) + return 0; + return 1; +} +static inline void Extra_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn[w]; +} +static inline void Extra_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~pIn[w]; +} +static inline void Extra_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] & pIn1[w]; +} +static inline void Extra_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~(pIn0[w] & pIn1[w]); +} + +extern void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start ); +extern void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ); +extern void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ); +extern DdNode * Extra_TruthToBdd( DdManager * dd, unsigned * pTruth, int nVars ); +extern int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ); +extern int Extra_TruthSupportSize( unsigned * pTruth, int nVars ); +extern int Extra_TruthSupport( unsigned * pTruth, int nVars ); +extern void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ); +extern void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ); +extern void Extra_TruthCombine( 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 ================================================================*/ diff --git a/src/misc/extra/extraUtilFile.c b/src/misc/extra/extraUtilFile.c index b00125d1..9a47750f 100644 --- a/src/misc/extra/extraUtilFile.c +++ b/src/misc/extra/extraUtilFile.c @@ -320,6 +320,65 @@ void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ) /**Function************************************************************* + Synopsis [Reads the hex unsigned into the bit-string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars ) +{ + int nDigits, Digit, k, c; + Sign[0] = 0; + // write the number into the file + nDigits = (1 << nVars) / 4; + for ( k = 0; k < nDigits; k++ ) + { + c = nDigits-1-k; + if ( pString[c] >= '0' && pString[c] <= '9' ) + Digit = pString[c] - '0'; + else if ( pString[c] >= 'A' && pString[c] <= 'F' ) + Digit = pString[c] - 'A' + 10; + else if ( pString[c] >= 'a' && pString[c] <= 'f' ) + Digit = pString[c] - 'a' + 10; + else { assert( 0 ); return 0; } + Sign[k/8] |= ( (Digit & 15) << ((k%8) * 4) ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Prints the hex unsigned into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ) +{ + int nDigits, Digit, k; + // write the number into the file + nDigits = (1 << nVars) / 4; + for ( k = nDigits - 1; k >= 0; k-- ) + { + Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15); + if ( Digit < 10 ) + fprintf( pFile, "%d", Digit ); + else + fprintf( pFile, "%c", 'a' + Digit-10 ); + } +// fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + Synopsis [Prints the hex unsigned into a file.] Description [] diff --git a/src/misc/extra/extraUtilProgress.c b/src/misc/extra/extraUtilProgress.c index 8956af2f..ddd6197a 100644 --- a/src/misc/extra/extraUtilProgress.c +++ b/src/misc/extra/extraUtilProgress.c @@ -58,6 +58,10 @@ static void Extra_ProgressBarClean( ProgressBar * p ); ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal ) { ProgressBar * p; + extern int Abc_FrameShowProgress( void * p ); + extern void * Abc_FrameGetGlobalFrame(); + + if ( !Abc_FrameShowProgress(Abc_FrameGetGlobalFrame()) ) return NULL; p = ALLOC( ProgressBar, 1 ); memset( p, 0, sizeof(ProgressBar) ); p->pFile = pFile; @@ -82,6 +86,7 @@ ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal ) ***********************************************************************/ void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString ) { + if ( p == NULL ) return; if ( nItemsCur < p->nItemsNext ) return; if ( nItemsCur > p->nItemsTotal ) @@ -107,6 +112,7 @@ void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString ***********************************************************************/ void Extra_ProgressBarStop( ProgressBar * p ) { + if ( p == NULL ) return; Extra_ProgressBarClean( p ); FREE( p ); } @@ -125,6 +131,7 @@ void Extra_ProgressBarStop( ProgressBar * p ) void Extra_ProgressBarShow( ProgressBar * p, char * pString ) { int i; + if ( p == NULL ) return; if ( pString ) fprintf( p->pFile, "%s ", pString ); for ( i = (pString? strlen(pString) + 1 : 0); i < p->posCur; i++ ) @@ -151,6 +158,7 @@ void Extra_ProgressBarShow( ProgressBar * p, char * pString ) void Extra_ProgressBarClean( ProgressBar * p ) { int i; + if ( p == NULL ) return; for ( i = 0; i <= p->posTotal; i++ ) fprintf( p->pFile, " " ); fprintf( p->pFile, "\r" ); diff --git a/src/misc/extra/extraUtilTruth.c b/src/misc/extra/extraUtilTruth.c new file mode 100644 index 00000000..2d6f307c --- /dev/null +++ b/src/misc/extra/extraUtilTruth.c @@ -0,0 +1,1076 @@ +/**CFile**************************************************************** + + FileName [extraUtilMisc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [Various procedures for truth table manipulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +static unsigned s_VarMasks[5][2] = { + { 0x33333333, 0xAAAAAAAA }, + { 0x55555555, 0xCCCCCCCC }, + { 0x0F0F0F0F, 0xF0F0F0F0 }, + { 0x00FF00FF, 0xFF00FF00 }, + { 0x0000FFFF, 0xFFFF0000 } +}; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [Swaps two adjacent variables in the truth table.] + + Description [Swaps var number Start and var number Start+1 (0-based numbers). + The input truth table is pIn. The output truth table is pOut.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) +{ + static unsigned PMasks[4][3] = { + { 0x99999999, 0x22222222, 0x44444444 }, + { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 }, + { 0xF00FF00F, 0x00F000F0, 0x0F000F00 }, + { 0xFF0000FF, 0x0000FF00, 0x00FF0000 } + }; + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step, Shift; + + assert( iVar < nVars - 1 ); + if ( iVar < 4 ) + { + Shift = (1 << iVar); + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift); + } + else if ( iVar > 4 ) + { + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 4*Step ) + { + for ( i = 0; i < Step; i++ ) + pOut[i] = pIn[i]; + for ( i = 0; i < Step; i++ ) + pOut[Step+i] = pIn[2*Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[2*Step+i] = pIn[Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[3*Step+i] = pIn[3*Step+i]; + pIn += 4*Step; + pOut += 4*Step; + } + } + else // if ( iVar == 4 ) + { + for ( i = 0; i < nWords; i += 2 ) + { + pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); + pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); + } + } +} + +/**Function************************************************************* + + Synopsis [Swaps two adjacent variables in the truth table.] + + Description [Swaps var number Start and var number Start+1 (0-based numbers). + The input truth table is pIn. The output truth table is pOut.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int Start ) +{ + int nWords = (nVars <= 5)? 1 : (1 << (nVars-5)); + int i, k, Step; + + assert( Start < nVars - 1 ); + switch ( Start ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0x99999999) | ((pIn[i] & 0x22222222) << 1) | ((pIn[i] & 0x44444444) >> 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xC3C3C3C3) | ((pIn[i] & 0x0C0C0C0C) << 2) | ((pIn[i] & 0x30303030) >> 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xF00FF00F) | ((pIn[i] & 0x00F000F0) << 4) | ((pIn[i] & 0x0F000F00) >> 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xFF0000FF) | ((pIn[i] & 0x0000FF00) << 8) | ((pIn[i] & 0x00FF0000) >> 8); + return; + case 4: + for ( i = 0; i < nWords; i += 2 ) + { + pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); + pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); + } + return; + default: + Step = (1 << (Start - 5)); + for ( k = 0; k < nWords; k += 4*Step ) + { + for ( i = 0; i < Step; i++ ) + pOut[i] = pIn[i]; + for ( i = 0; i < Step; i++ ) + pOut[Step+i] = pIn[2*Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[2*Step+i] = pIn[Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[3*Step+i] = pIn[3*Step+i]; + pIn += 4*Step; + pOut += 4*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Expands the truth table according to the phase.] + + Description [The input and output truth tables are in pIn/pOut. The current number + of variables is nVars. The total number of variables in nVarsAll. The last variable + (Phase) contains shows how the variables should be moved.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ) +{ + unsigned * pTemp; + int i, k, Var = nVars - 1, Counter = 0; + for ( i = nVarsAll - 1; i >= 0; i-- ) + if ( Phase & (1 << i) ) + { + for ( k = Var; k < i; k++ ) + { + Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + Counter++; + } + Var--; + } + assert( Var == -1 ); + // swap if it was moved an even number of times + if ( !(Counter & 1) ) + Extra_TruthCopy( pOut, pIn, nVarsAll ); +} + +/**Function************************************************************* + + Synopsis [Shrinks the truth table according to the phase.] + + Description [The input and output truth tables are in pIn/pOut. The current number + of variables is nVars. The total number of variables in nVarsAll. The last variable + (Phase) contains shows how the variables should be moved.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ) +{ + unsigned * pTemp; + int i, k, Var = 0, Counter = 0; + for ( i = 0; i < nVarsAll; i++ ) + if ( Phase & (1 << i) ) + { + for ( k = i-1; k >= Var; k-- ) + { + Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + Counter++; + } + Var++; + } + assert( Var == nVars ); + // swap if it was moved an even number of times + if ( !(Counter & 1) ) + Extra_TruthCopy( pOut, pIn, nVarsAll ); +} + + +/**Function************************************************************* + + Synopsis [Performs truth table computation.] + + Description [Note the caching makes no sense for this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_TruthToBdd_rec( DdManager * dd, unsigned * pTruth, int iBit, int nVars, int nVarsTotal ) +{ + DdNode * bF0, * bF1, * bF; + if ( nVars == 0 ) + { + if ( pTruth[iBit/32] & (1 << iBit%32) ) + return b1; + return b0; + } + if ( nVars == 5 ) + { + if ( pTruth[iBit/32] == 0xFFFFFFFF ) + return b1; + if ( pTruth[iBit/32] == 0 ) + return b0; + } + // other special cases can be added + bF0 = Extra_TruthToBdd_rec( dd, pTruth, iBit, nVars-1, nVarsTotal ); Cudd_Ref( bF0 ); + bF1 = Extra_TruthToBdd_rec( dd, pTruth, iBit+(1<<(nVars-1)), nVars-1, nVarsTotal ); Cudd_Ref( bF1 ); + bF = Cudd_bddIte( dd, dd->vars[nVarsTotal-nVars], bF1, bF0 ); Cudd_Ref( bF ); + Cudd_RecursiveDeref( dd, bF0 ); + Cudd_RecursiveDeref( dd, bF1 ); + Cudd_Deref( bF ); + return bF; +} + +/**Function************************************************************* + + Synopsis [Compute BDD corresponding to the truth table.] + + Description [If truth table has N vars, the BDD depends on N topmost + variables of the BDD manager. The most significant variable of the table + is encoded by the topmost variable of the manager. BDD construction is + very efficient in this case because BDD is constructed one node at a time, + by simply adding BDD nodes on top of existent BDD nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_TruthToBdd( DdManager * dd, unsigned * pTruth, int nVars ) +{ + return Extra_TruthToBdd_rec( dd, pTruth, 0, nVars, nVars ); +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if TT depends on the given variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x55555555) != ((pTruth[i] & 0xAAAAAAAA) >> 1) ) + return 1; + return 0; + case 1: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x33333333) != ((pTruth[i] & 0xCCCCCCCC) >> 2) ) + return 1; + return 0; + case 2: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x0F0F0F0F) != ((pTruth[i] & 0xF0F0F0F0) >> 4) ) + return 1; + return 0; + case 3: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x00FF00FF) != ((pTruth[i] & 0xFF00FF00) >> 8) ) + return 1; + return 0; + case 4: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x0000FFFF) != ((pTruth[i] & 0xFFFF0000) >> 16) ) + return 1; + return 0; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + if ( pTruth[i] != pTruth[Step+i] ) + return 1; + pTruth += 2*Step; + } + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Returns the number of support vars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthSupportSize( unsigned * pTruth, int nVars ) +{ + int i, Counter = 0; + for ( i = 0; i < nVars; i++ ) + Counter += Extra_TruthVarInSupport( pTruth, nVars, i ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns support of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthSupport( unsigned * pTruth, int nVars ) +{ + int i, Support = 0; + for ( i = 0; i < nVars; i++ ) + if ( Extra_TruthVarInSupport( pTruth, nVars, i ) ) + Support |= (1 << i); + return Support; +} + + + +/**Function************************************************************* + + Synopsis [Computes positive cofactor of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xAAAAAAAA) | ((pTruth[i] & 0xAAAAAAAA) >> 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xCCCCCCCC) | ((pTruth[i] & 0xCCCCCCCC) >> 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xF0F0F0F0) | ((pTruth[i] & 0xF0F0F0F0) >> 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xFF00FF00) | ((pTruth[i] & 0xFF00FF00) >> 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xFFFF0000) | ((pTruth[i] & 0xFFFF0000) >> 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + pTruth[i] = pTruth[Step+i]; + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Computes negative cofactor of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x55555555) | ((pTruth[i] & 0x55555555) << 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x33333333) | ((pTruth[i] & 0x33333333) << 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x0F0F0F0F) | ((pTruth[i] & 0x0F0F0F0F) << 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x00FF00FF) | ((pTruth[i] & 0x00FF00FF) << 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x0000FFFF) | ((pTruth[i] & 0x0000FFFF) << 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + pTruth[Step+i] = pTruth[i]; + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Computes negative cofactor of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthCombine( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + pOut[i] = pCof0[i]; + pOut[Step+i] = pCof1[i]; + } + pOut += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Checks symmetry of two variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ) +{ + static unsigned uTemp0[16], uTemp1[16]; + assert( nVars <= 9 ); + // compute Cof01 + Extra_TruthCopy( uTemp0, pTruth, nVars ); + Extra_TruthCofactor0( uTemp0, nVars, iVar0 ); + Extra_TruthCofactor1( uTemp0, nVars, iVar1 ); + // compute Cof10 + Extra_TruthCopy( uTemp1, pTruth, nVars ); + Extra_TruthCofactor1( uTemp1, nVars, iVar0 ); + Extra_TruthCofactor0( uTemp1, nVars, iVar1 ); + // compare + return Extra_TruthIsEqual( uTemp0, uTemp1, nVars ); +} + +/**Function************************************************************* + + Synopsis [Checks antisymmetry of two variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ) +{ + static unsigned uTemp0[16], uTemp1[16]; + assert( nVars <= 9 ); + // compute Cof00 + Extra_TruthCopy( uTemp0, pTruth, nVars ); + Extra_TruthCofactor0( uTemp0, nVars, iVar0 ); + Extra_TruthCofactor0( uTemp0, nVars, iVar1 ); + // compute Cof11 + Extra_TruthCopy( uTemp1, pTruth, nVars ); + Extra_TruthCofactor1( uTemp1, nVars, iVar0 ); + Extra_TruthCofactor1( uTemp1, nVars, iVar1 ); + // compare + return Extra_TruthIsEqual( uTemp0, uTemp1, nVars ); +} + +/**Function************************************************************* + + Synopsis [Changes phase of the function w.r.t. one variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step; + unsigned Temp; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x55555555) << 1) | ((pTruth[i] & 0xAAAAAAAA) >> 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x33333333) << 2) | ((pTruth[i] & 0xCCCCCCCC) >> 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x0F0F0F0F) << 4) | ((pTruth[i] & 0xF0F0F0F0) >> 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x00FF00FF) << 8) | ((pTruth[i] & 0xFF00FF00) >> 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x0000FFFF) << 16) | ((pTruth[i] & 0xFFFF0000) >> 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + Temp = pTruth[i]; + pTruth[i] = pTruth[Step+i]; + pTruth[Step+i] = Temp; + } + pTruth += 2*Step; + } + return; + } +} + +/**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.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ) +{ + static unsigned uCofactor[16]; + int i, ValueCur, ValueMin, VarMin; + unsigned uSupp0, uSupp1; + assert( nVars <= 9 ); + ValueMin = 32; + for ( i = 0; i < nVars; i++ ) + { + // get negative cofactor + Extra_TruthCopy( uCofactor, pTruth, nVars ); + Extra_TruthCofactor0( uCofactor, nVars, i ); + uSupp0 = Extra_TruthSupport( uCofactor, nVars ); +//Extra_PrintBinary( stdout, &uSupp0, 8 ); printf( "\n" ); + // get positive cofactor + Extra_TruthCopy( uCofactor, pTruth, nVars ); + Extra_TruthCofactor1( uCofactor, nVars, i ); + uSupp1 = Extra_TruthSupport( uCofactor, nVars ); +//Extra_PrintBinary( stdout, &uSupp1, 8 ); printf( "\n" ); + // get the number of common vars + ValueCur = Extra_WordCountOnes( uSupp0 & uSupp1 ); + if ( ValueMin > ValueCur ) + { + ValueMin = ValueCur; + VarMin = i; + } + if ( ValueMin == 0 ) + break; + } + if ( pVarMin ) + *pVarMin = VarMin; + return ValueMin; +} + + +/**Function************************************************************* + + Synopsis [Counts the number of 1's in each cofactor.] + + Description [The resulting numbers are stored in the array of shorts, + whose length is 2*nVars. The number of 1's is counted in a different + space than the original function. For example, if the function depends + on k variables, the cofactors are assumed to depend on k-1 variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Counter; + memset( pStore, 0, sizeof(short) * 2 * nVars ); + if ( nVars <= 5 ) + { + if ( nVars > 0 ) + { + pStore[2*0+0] = Extra_WordCountOnes( pTruth[0] & 0x55555555 ); + pStore[2*0+1] = Extra_WordCountOnes( pTruth[0] & 0xAAAAAAAA ); + } + if ( nVars > 1 ) + { + pStore[2*1+0] = Extra_WordCountOnes( pTruth[0] & 0x33333333 ); + pStore[2*1+1] = Extra_WordCountOnes( pTruth[0] & 0xCCCCCCCC ); + } + if ( nVars > 2 ) + { + pStore[2*2+0] = Extra_WordCountOnes( pTruth[0] & 0x0F0F0F0F ); + pStore[2*2+1] = Extra_WordCountOnes( pTruth[0] & 0xF0F0F0F0 ); + } + if ( nVars > 3 ) + { + pStore[2*3+0] = Extra_WordCountOnes( pTruth[0] & 0x00FF00FF ); + pStore[2*3+1] = Extra_WordCountOnes( pTruth[0] & 0xFF00FF00 ); + } + if ( nVars > 4 ) + { + pStore[2*4+0] = Extra_WordCountOnes( pTruth[0] & 0x0000FFFF ); + pStore[2*4+1] = Extra_WordCountOnes( pTruth[0] & 0xFFFF0000 ); + } + return; + } + // nVars >= 6 + // count 1's for all other variables + for ( k = 0; k < nWords; k++ ) + { + Counter = Extra_WordCountOnes( pTruth[k] ); + for ( i = 5; i < nVars; i++ ) + if ( k & (1 << (i-5)) ) + pStore[2*i+1] += Counter; + else + pStore[2*i+0] += Counter; + } + // count 1's for the first five variables + for ( k = 0; k < nWords/2; k++ ) + { + pStore[2*0+0] += Extra_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) ); + pStore[2*0+1] += Extra_WordCountOnes( (pTruth[0] & 0xAAAAAAAA) | ((pTruth[1] & 0xAAAAAAAA) >> 1) ); + pStore[2*1+0] += Extra_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) ); + pStore[2*1+1] += Extra_WordCountOnes( (pTruth[0] & 0xCCCCCCCC) | ((pTruth[1] & 0xCCCCCCCC) >> 2) ); + pStore[2*2+0] += Extra_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) ); + pStore[2*2+1] += Extra_WordCountOnes( (pTruth[0] & 0xF0F0F0F0) | ((pTruth[1] & 0xF0F0F0F0) >> 4) ); + pStore[2*3+0] += Extra_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) ); + pStore[2*3+1] += Extra_WordCountOnes( (pTruth[0] & 0xFF00FF00) | ((pTruth[1] & 0xFF00FF00) >> 8) ); + pStore[2*4+0] += Extra_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) ); + pStore[2*4+1] += Extra_WordCountOnes( (pTruth[0] & 0xFFFF0000) | ((pTruth[1] & 0xFFFF0000) >> 16) ); + pTruth += 2; + } +} + + +/**Function************************************************************* + + Synopsis [Canonicize the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Extra_TruthHash( unsigned * pIn, int nWords ) +{ + // The 1,024 smallest prime numbers used to compute the hash value + // http://www.math.utah.edu/~alfeld/math/primelist.html + static int HashPrimes[1024] = { 2, 3, 5, + 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, + 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, + 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, + 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, + 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, + 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, + 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, + 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, + 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, + 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, + 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, + 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, + 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, + 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, + 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, + 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, + 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, + 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, + 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, + 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, + 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, + 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, + 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, + 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, + 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, + 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, + 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, + 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, + 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, + 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, + 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, + 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, + 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, + 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, + 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, + 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, + 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, + 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, + 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, + 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, + 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, + 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, + 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, + 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, + 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, + 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, + 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, + 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, + 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, + 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, + 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, + 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, + 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, + 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, + 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, + 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, + 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, + 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, + 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, + 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, + 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, + 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, + 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, + 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, + 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, + 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, + 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, + 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, + 8147, 8161 }; + int i; + unsigned uHashKey; + assert( nWords <= 1024 ); + uHashKey = 0; + for ( i = 0; i < nWords; i++ ) + uHashKey ^= HashPrimes[i] * pIn[i]; + return uHashKey; +} + + +/**Function************************************************************* + + Synopsis [Canonicize the truth table.] + + Description [Returns the phase. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ) +{ + unsigned * pIn = pInOut, * pOut = pAux, * pTemp; + int nWords = Extra_TruthWordNum( nVars ); + int i, Temp, fChange, Counter, nOnes;//, k, j, w, Limit; + unsigned uCanonPhase; + + // canonicize output + uCanonPhase = 0; + nOnes = Extra_TruthCountOnes(pIn, nVars); + if ( (nOnes > nWords * 16) || ((nOnes == nWords * 16) && (pIn[0] & 1)) ) + { + uCanonPhase |= (1 << nVars); + Extra_TruthNot( pIn, pIn, nVars ); + } + + // collect the minterm counts + Extra_TruthCountOnesInCofs( pIn, nVars, pStore ); + + // canonicize phase + for ( i = 0; i < nVars; i++ ) + { + if ( pStore[2*i+0] <= pStore[2*i+1] ) + continue; + uCanonPhase |= (1 << i); + Temp = pStore[2*i+0]; + pStore[2*i+0] = pStore[2*i+1]; + pStore[2*i+1] = Temp; + Extra_TruthChangePhase( pIn, nVars, i ); + } + +// Extra_PrintHexadecimal( stdout, pIn, nVars ); +// printf( "\n" ); + + // permute + Counter = 0; + do { + fChange = 0; + for ( i = 0; i < nVars-1; i++ ) + { + if ( pStore[2*i] <= pStore[2*(i+1)] ) + continue; + Counter++; + fChange = 1; + + Temp = pCanonPerm[i]; + pCanonPerm[i] = pCanonPerm[i+1]; + pCanonPerm[i+1] = Temp; + + Temp = pStore[2*i]; + pStore[2*i] = pStore[2*(i+1)]; + pStore[2*(i+1)] = Temp; + + Temp = pStore[2*i+1]; + pStore[2*i+1] = pStore[2*(i+1)+1]; + pStore[2*(i+1)+1] = Temp; + + Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + } while ( fChange ); + +/* + Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " ); + for ( i = 0; i < nVars; i++ ) + printf( "%d=%d/%d ", pCanonPerm[i], pStore[2*i], pStore[2*i+1] ); + printf( " C = %d\n", Counter ); + Extra_PrintHexadecimal( stdout, pIn, nVars ); + printf( "\n" ); +*/ + +/* + // process symmetric variable groups + uSymms = 0; + for ( i = 0; i < nVars-1; i++ ) + { + if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric + continue; + if ( pStore[2*i] != pStore[2*i+1] ) + continue; + if ( Extra_TruthVarsSymm( pIn, nVars, i, i+1 ) ) + continue; + if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, i+1 ) ) + Extra_TruthChangePhase( pIn, nVars, i+1 ); + } +*/ + +/* + // process symmetric variable groups + uSymms = 0; + for ( i = 0; i < nVars-1; i++ ) + { + if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric + continue; + // i and i+1 can be symmetric + // find the end of this group + for ( k = i+1; k < nVars; k++ ) + if ( pStore[2*i] != pStore[2*k] ) + break; + Limit = k; + assert( i < Limit-1 ); + // go through the variables in this group + for ( j = i + 1; j < Limit; j++ ) + { + // check symmetry + if ( Extra_TruthVarsSymm( pIn, nVars, i, j ) ) + { + uSymms |= (1 << j); + continue; + } + // they are phase-unknown + if ( pStore[2*i] == pStore[2*i+1] ) + { + if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, j ) ) + { + Extra_TruthChangePhase( pIn, nVars, j ); + uCanonPhase ^= (1 << j); + uSymms |= (1 << j); + continue; + } + } + + // they are not symmetric - move j as far as it goes in the group + for ( k = j; k < Limit-1; k++ ) + { + Counter++; + + Temp = pCanonPerm[k]; + pCanonPerm[k] = pCanonPerm[k+1]; + pCanonPerm[k+1] = Temp; + + assert( pStore[2*k] == pStore[2*(k+1)] ); + Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, k ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + Limit--; + j--; + } + i = Limit - 1; + } +*/ + + // swap if it was moved an even number of times + if ( Counter & 1 ) + Extra_TruthCopy( pOut, pIn, nVars ); + return uCanonPhase; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/misc/extra/module.make b/src/misc/extra/module.make index c4da05e4..93b24311 100644 --- a/src/misc/extra/module.make +++ b/src/misc/extra/module.make @@ -10,4 +10,5 @@ SRC += src/misc/extra/extraBddAuto.c \ src/misc/extra/extraUtilMisc.c \ src/misc/extra/extraUtilProgress.c \ src/misc/extra/extraUtilReader.c \ + src/misc/extra/extraUtilTruth.c \ src/misc/extra/extraUtilUtil.c diff --git a/src/misc/vec/vecInt.h b/src/misc/vec/vecInt.h index ee848df7..5a627623 100644 --- a/src/misc/vec/vecInt.h +++ b/src/misc/vec/vecInt.h @@ -457,6 +457,33 @@ static inline void Vec_IntPush( Vec_Int_t * p, int Entry ) SeeAlso [] ***********************************************************************/ +static inline void Vec_IntPushFirst( Vec_Int_t * p, int Entry ) +{ + int i; + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Vec_IntGrow( p, 16 ); + else + Vec_IntGrow( p, 2 * p->nCap ); + } + p->nSize++; + for ( i = p->nSize - 1; i >= 1; i-- ) + p->pArray[i] = p->pArray[i-1]; + p->pArray[0] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ static inline void Vec_IntPushMem( Extra_MmStep_t * pMemMan, Vec_Int_t * p, int Entry ) { if ( p->nSize == p->nCap ) diff --git a/src/misc/vec/vecVec.h b/src/misc/vec/vecVec.h index 8518184a..54dcaa37 100644 --- a/src/misc/vec/vecVec.h +++ b/src/misc/vec/vecVec.h @@ -123,6 +123,28 @@ static inline Vec_Vec_t * Vec_VecStart( int nSize ) /**Function************************************************************* + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_VecExpand( Vec_Vec_t * p, int Level ) +{ + int i; + if ( p->nSize >= Level + 1 ) + return; + Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 ); + for ( i = p->nSize; i <= Level; i++ ) + p->pArray[i] = Vec_PtrAlloc( 0 ); + p->nSize = Level + 1; +} + +/**Function************************************************************* + Synopsis [] Description [] diff --git a/src/opt/cut/cut.h b/src/opt/cut/cut.h index 0a1cd41a..c2142c4f 100644 --- a/src/opt/cut/cut.h +++ b/src/opt/cut/cut.h @@ -59,8 +59,10 @@ struct Cut_ParamsStruct_t_ int fFilter; // filter dominated cuts int fSeq; // compute sequential cuts int fDrop; // drop cuts on the fly - int fMulti; // compute factor-cuts + int fDag; // compute only DAG cuts + int fTree; // compute only tree cuts int fRecord; // record the cut computation flow + int fFancy; // perform fancy computations int fVerbose; // the verbosiness flag }; @@ -117,8 +119,9 @@ extern void Cut_ManPrintStats( Cut_Man_t * p ); extern void Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, int TimeTotal ); extern void Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts ); extern int Cut_ManReadVarsMax( Cut_Man_t * p ); +extern void Cut_ManIncrementDagNodes( Cut_Man_t * p ); /*=== cutNode.c ==========================================================*/ -extern Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv ); +extern Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode ); extern Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes ); extern Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst ); /*=== cutSeq.c ==========================================================*/ @@ -135,7 +138,13 @@ extern void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node ); extern Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 ); extern void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node ); /*=== cutTruth.c ==========================================================*/ -extern void Cut_TruthCanonicize( Cut_Cut_t * pCut ); +extern void Cut_TruthNCanonicize( Cut_Cut_t * pCut ); +/*=== cutPre22.c ==========================================================*/ +extern void Cut_CellPrecompute(); +extern void Cut_CellLoad(); +extern int Cut_CellIsRunning(); +extern void Cut_CellDumpToFile(); +extern int Cut_CellTruthLookup( unsigned * pTruth, int nVars ); #ifdef __cplusplus } diff --git a/src/opt/cut/cutInt.h b/src/opt/cut/cutInt.h index 375d2213..c6246ad7 100644 --- a/src/opt/cut/cutInt.h +++ b/src/opt/cut/cutInt.h @@ -65,13 +65,13 @@ struct Cut_ManStruct_t_ Cut_Cut_t * pStore1[2]; Cut_Cut_t * pCompareOld; Cut_Cut_t * pCompareNew; + unsigned * puTemp[4]; // record of the cut computation Vec_Int_t * vNodeCuts; // the number of cuts for each node Vec_Int_t * vNodeStarts; // the number of the starting cut of each node Vec_Int_t * vCutPairs; // the pairs of parent cuts for each cut // statistics int nCutsCur; - int nCutsMulti; int nCutsAlloc; int nCutsDealloc; int nCutsPeak; @@ -79,8 +79,8 @@ struct Cut_ManStruct_t_ int nCutsFilter; int nCutsLimit; int nNodes; - int nNodesMulti; - int nNodesMulti0; + int nNodesDag; + int nNodesNoCuts; // runtime int timeMerge; int timeUnion; @@ -130,7 +130,7 @@ extern void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut /*=== cutMerge.c ==========================================================*/ extern Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); /*=== cutNode.c ==========================================================*/ -extern void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv ); +extern void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode ); extern int Cut_CutListVerify( Cut_Cut_t * pList ); /*=== cutTable.c ==========================================================*/ extern Cut_HashTable_t * Cut_TableStart( int Size ); @@ -139,7 +139,8 @@ extern int Cut_TableLookup( Cut_HashTable_t * pTable, Cut_Cut_t extern void Cut_TableClear( Cut_HashTable_t * pTable ); extern int Cut_TableReadTime( Cut_HashTable_t * pTable ); /*=== cutTruth.c ==========================================================*/ -extern void Cut_TruthCompute( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ); +extern void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ); +extern void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ); #endif diff --git a/src/opt/cut/cutMan.c b/src/opt/cut/cutMan.c index 8269da06..0cd01bc9 100644 --- a/src/opt/cut/cutMan.c +++ b/src/opt/cut/cutMan.c @@ -61,22 +61,30 @@ Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams ) Vec_PtrFill( p->vCutsOld, pParams->nIdsMax, NULL ); p->vCutsTemp = Vec_PtrAlloc( pParams->nCutSet ); Vec_PtrFill( p->vCutsTemp, pParams->nCutSet, NULL ); + if ( pParams->fTruth && pParams->nVarsMax > 5 ) + { + pParams->fTruth = 0; + printf( "Skipping computation of truth tables for sequential cuts with more than 5 inputs.\n" ); + } } - assert( !pParams->fTruth || pParams->nVarsMax <= 5 ); // entry size p->EntrySize = sizeof(Cut_Cut_t) + pParams->nVarsMax * sizeof(int); if ( pParams->fTruth ) { - if ( pParams->nVarsMax > 8 ) + if ( pParams->nVarsMax > 14 ) { pParams->fTruth = 0; - printf( "Skipping computation of truth table for more than 8 inputs.\n" ); + printf( "Skipping computation of truth table for more than %d inputs.\n", 14 ); } else { p->nTruthWords = Cut_TruthWords( pParams->nVarsMax ); p->EntrySize += p->nTruthWords * sizeof(unsigned); } + p->puTemp[0] = ALLOC( unsigned, 4 * p->nTruthWords ); + p->puTemp[1] = p->puTemp[0] + p->nTruthWords; + p->puTemp[2] = p->puTemp[1] + p->nTruthWords; + p->puTemp[3] = p->puTemp[2] + p->nTruthWords; } // enable cut computation recording if ( pParams->fRecord ) @@ -120,6 +128,7 @@ void Cut_ManStop( Cut_Man_t * p ) if ( p->vNodeCuts ) Vec_IntFree( p->vNodeCuts ); if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts ); if ( p->vCutPairs ) Vec_IntFree( p->vCutPairs ); + if ( p->puTemp[0] ) free( p->puTemp[0] ); Extra_MmFixedStop( p->pMmCuts, 0 ); free( p ); @@ -153,15 +162,10 @@ void Cut_ManPrintStats( Cut_Man_t * p ) printf( "Cuts per node = %8.1f\n", ((float)(p->nCutsCur-p->nCutsTriv))/p->nNodes ); printf( "The cut size = %8d bytes.\n", p->EntrySize ); printf( "Peak memory = %8.2f Mb.\n", (float)p->nCutsPeak * p->EntrySize / (1<<20) ); - if ( p->pParams->fMulti ) - { - printf( "Factor-cut computation statistics:\n" ); printf( "Total nodes = %8d.\n", p->nNodes ); - printf( "Factor nodes = %8d.\n", p->nNodesMulti ); - printf( "Factor nodes 0 = %8d.\n", p->nNodesMulti0 ); - printf( "Factor cuts = %8d.\n", p->nCutsMulti ); - printf( "Cuts per node = %8.1f\n", ((float)(p->nCutsMulti))/(p->nNodesMulti-p->nNodesMulti0) ); - } + printf( "DAG nodes = %8d.\n", p->nNodesDag ); + printf( "Tree nodes = %8d.\n", p->nNodes - p->nNodesDag ); + printf( "Nodes w/o cuts = %8d.\n", p->nNodesNoCuts ); PRT( "Merge ", p->timeMerge ); PRT( "Union ", p->timeUnion ); PRT( "Filter", p->timeFilter ); @@ -229,6 +233,22 @@ int Cut_ManReadVarsMax( Cut_Man_t * p ) return p->pParams->nVarsMax; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_ManIncrementDagNodes( Cut_Man_t * p ) +{ + p->nNodesDag++; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/cut/cutNode.c b/src/opt/cut/cutNode.c index cace83bd..b651dac9 100644 --- a/src/opt/cut/cutNode.c +++ b/src/opt/cut/cutNode.c @@ -277,7 +277,7 @@ static inline int Cut_CutProcessTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t } // compute the truth table if ( p->pParams->fTruth ) - Cut_TruthCompute( pCut, pCut0, pCut1, p->fCompl0, p->fCompl1 ); + Cut_TruthCompute( p, pCut, pCut0, pCut1, p->fCompl0, p->fCompl1 ); // add to the list Cut_ListAdd( pSuperList, pCut ); // return status (0 if okay; 1 if exceeded the limit) @@ -295,7 +295,7 @@ static inline int Cut_CutProcessTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t SeeAlso [] ***********************************************************************/ -Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv ) +Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode ) { Cut_List_t Super, * pSuper = &Super; Cut_Cut_t * pList, * pCut; @@ -312,7 +312,7 @@ Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, // compute the cuts clk = clock(); Cut_ListStart( pSuper ); - Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, Cut_NodeReadCutsNew(p, Node0), Cut_NodeReadCutsNew(p, Node1), fTriv ); + Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, Cut_NodeReadCutsNew(p, Node0), Cut_NodeReadCutsNew(p, Node1), fTriv, TreeCode ); pList = Cut_ListFinish( pSuper ); p->timeMerge += clock() - clk; // verify the result of cut computation @@ -351,9 +351,9 @@ p->timeMerge += clock() - clk; SeeAlso [] ***********************************************************************/ -void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv ) +void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode ) { - Cut_Cut_t * pStop0, * pStop1, * pTemp0, * pTemp1; + Cut_Cut_t * pStop0, * pStop1, * pTemp0, * pTemp1, * pStore0, * pStore1; int i, nCutsOld, Limit; // start with the elementary cut if ( fTriv ) @@ -375,6 +375,19 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC // set temporary variables p->fCompl0 = fCompl0; p->fCompl1 = fCompl1; + // if tree cuts are computed, make sure only the unit cuts propagate over the DAG nodes + if ( TreeCode & 1 ) + { + assert( pList0->nLeaves == 1 ); + pStore0 = pList0->pNext; + pList0->pNext = NULL; + } + if ( TreeCode & 2 ) + { + assert( pList1->nLeaves == 1 ); + pStore1 = pList1->pNext; + pList1->pNext = NULL; + } // find the point in the list where the max-var cuts begin Cut_ListForEachCut( pList0, pStop0 ) if ( pStop0->nLeaves == (unsigned)Limit ) @@ -386,8 +399,10 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC // small by small Cut_ListForEachCutStop( pList0, pTemp0, pStop0 ) Cut_ListForEachCutStop( pList1, pTemp1, pStop1 ) + { if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) - return; + goto Quits; + } // small by large Cut_ListForEachCutStop( pList0, pTemp0, pStop0 ) Cut_ListForEachCut( pStop1, pTemp1 ) @@ -395,7 +410,7 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC if ( (pTemp0->uSign & pTemp1->uSign) != pTemp0->uSign ) continue; if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) - return; + goto Quits; } // small by large Cut_ListForEachCutStop( pList1, pTemp1, pStop1 ) @@ -404,7 +419,7 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC if ( (pTemp0->uSign & pTemp1->uSign) != pTemp1->uSign ) continue; if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) - return; + goto Quits; } // large by large Cut_ListForEachCut( pStop0, pTemp0 ) @@ -419,15 +434,15 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC if ( i < Limit ) continue; if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) - return; + goto Quits; } - if ( fTriv ) - { - p->nCutsMulti += p->nCutsCur - nCutsOld; - p->nNodesMulti++; - if ( p->nCutsCur == nCutsOld ) - p->nNodesMulti0++; - } + if ( p->nNodeCuts == 0 ) + p->nNodesNoCuts++; +Quits: + if ( TreeCode & 1 ) + pList0->pNext = pStore0; + if ( TreeCode & 2 ) + pList1->pNext = pStore1; } /**Function************************************************************* diff --git a/src/opt/cut/cutOracle.c b/src/opt/cut/cutOracle.c index cad0069a..8e1ad3da 100644 --- a/src/opt/cut/cutOracle.c +++ b/src/opt/cut/cutOracle.c @@ -366,7 +366,7 @@ Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int No ppTail = &pCut->pNext; // compute the truth table if ( p->pParams->fTruth ) - Cut_TruthCompute( pCut, pCut0, pCut1, fCompl0, fCompl1 ); + Cut_TruthComputeOld( pCut, pCut0, pCut1, fCompl0, fCompl1 ); } *ppTail = NULL; diff --git a/src/opt/cut/cutPre22.c b/src/opt/cut/cutPre22.c new file mode 100644 index 00000000..dd52b694 --- /dev/null +++ b/src/opt/cut/cutPre22.c @@ -0,0 +1,983 @@ +/**CFile**************************************************************** + + FileName [cutPre22.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Precomputes truth tables for the 2x2 macro cell.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutPre22.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define CUT_CELL_MVAR 9 + +typedef struct Cut_Cell_t_ Cut_Cell_t; +typedef struct Cut_CMan_t_ Cut_CMan_t; + +struct Cut_Cell_t_ +{ + Cut_Cell_t * pNext; // pointer to the next cell in the table + Cut_Cell_t * pNextVar; // pointer to the next cell of this support size + Cut_Cell_t * pParent; // pointer to the cell used to derive this one + int nUsed; // the number of times the cell is used + char Box[4]; // functions in the boxes + unsigned nVars : 4; // the number of variables + unsigned CrossBar0 : 4; // the variable set equal + unsigned CrossBar1 : 4; // the variable set equal + unsigned CrossBarPhase : 2; // the phase of the cross bar (0, 1, or 2) + unsigned CanonPhase : 18; // the canonical phase + char CanonPerm[CUT_CELL_MVAR+3]; // semicanonical permutation + short Store[2*CUT_CELL_MVAR]; // minterm counts in the cofactors + unsigned uTruth[1<<(CUT_CELL_MVAR-5)]; // the current truth table +}; + +struct Cut_CMan_t_ +{ + // storage for canonical cells + Extra_MmFixed_t * pMem; + st_table * tTable; + Cut_Cell_t * pSameVar[CUT_CELL_MVAR+1]; + // elementary truth tables + unsigned uInputs[CUT_CELL_MVAR][1<<(CUT_CELL_MVAR-5)]; + // temporary truth tables + unsigned uTemp1[22][1<<(CUT_CELL_MVAR-5)]; + unsigned uTemp2[22][1<<(CUT_CELL_MVAR-5)]; + unsigned uTemp3[22][1<<(CUT_CELL_MVAR-5)]; + unsigned uFinal[1<<(CUT_CELL_MVAR-5)]; + unsigned puAux[1<<(CUT_CELL_MVAR-5)]; + // statistical variables + int nTotal; + int nGood; + int nVarCounts[CUT_CELL_MVAR+1]; + int nSymGroups[CUT_CELL_MVAR+1]; + int nSymGroupsE[CUT_CELL_MVAR+1]; + int timeCanon; + int timeSupp; + int timeTable; + int nCellFound; + int nCellNotFound; +}; + +// NP-classes of functions of 3 variables (22) +static char * s_NP3[22] = { + " 0\n", // 00 const 0 // 0 vars + " 1\n", // 01 const 1 // 0 vars + "1 1\n", // 02 a // 1 vars + "11 1\n", // 03 ab // 2 vars + "11 0\n", // 04 (ab)' // 2 vars + "10 1\n01 1\n", // 05 a<+>b // 2 vars + "111 1\n", // 06 0s abc // 3 vars + "111 0\n", // 07 (abc)' // + "11- 1\n1-1 1\n", // 08 1p a(b+c) // + "11- 0\n1-1 0\n", // 09 (a(b+c))' // + "111 1\n100 1\n010 1\n001 1\n", // 10 2s a<+>b<+>c // + "10- 0\n1-0 0\n011 0\n", // 11 3p a<+>bc // + "101 1\n110 1\n", // 12 4p a(b<+>c) // + "101 0\n110 0\n", // 13 (a(b<+>c))' // + "11- 1\n1-1 1\n-11 1\n", // 14 5s ab+bc+ac // + "111 1\n000 1\n", // 15 6s abc+a'b'c' // + "111 0\n000 0\n", // 16 (abc+a'b'c')' // + "11- 1\n-11 1\n0-1 1\n", // 17 7 ab+bc+a'c // + "011 1\n101 1\n110 1\n", // 18 8s a'bc+ab'c+abc' // + "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' // + "100 1\n-11 1\n", // 20 9p ab'c'+bc // + "100 0\n-11 0\n" // 21 (ab'c'+bc)' // +}; + +// NP-classes of functions of 3 variables (22) +static char * s_NP3Names[22] = { + " const 0 ", + " const 1 ", + " a ", + " ab ", + " (ab)' ", + " a<+>b ", + "0s abc ", + " (abc)' ", + "1p a(b+c) ", + " (a(b+c))' ", + "2s a<+>b<+>c ", + "3p a<+>bc ", + "4p a(b<+>c) ", + " (a(b<+>c))' ", + "5s ab+bc+ac ", + "6s abc+a'b'c' ", + " (abc+a'b'c')' ", + "7 ab+bc+a'c ", + "8s a'bc+ab'c+abc' ", + " (a'bc+ab'c+abc')' ", + "9p ab'c'+bc ", + " (ab'c'+bc)' " +}; + +// the number of variables in each function +static int s_NP3VarNums[22] = { 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; + +// NPN classes of functions of exactly 3 inputs (10) +static int s_NPNe3[10] = { 6, 8, 10, 11, 12, 14, 15, 17, 18, 20 }; + +// NPN classes of functions of exactly 3 inputs that are symmetric (5) +static int s_NPNe3s[10] = { 6, 10, 14, 15, 18 }; + +// NPN classes of functions of exactly 3 inputs (4) +static int s_NPNe3p[10] = { 8, 11, 12, 20 }; + +static Cut_CMan_t * Cut_CManStart(); +static void Cut_CManStop( Cut_CMan_t * p ); +static void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type ); +static void Cut_CellCanonicize( Cut_CMan_t * p, Cut_Cell_t * pCell ); +static int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell ); +static void Cut_CellSuppMin( Cut_Cell_t * pCell ); +static void Cut_CellCrossBar( Cut_Cell_t * pCell ); + + +static Cut_CMan_t * s_pCMan = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start the precomputation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CellLoad() +{ + FILE * pFile; + char * pFileName = "cells22_daomap_iwls.txt"; + char pString[1000]; + Cut_CMan_t * p; + Cut_Cell_t * pCell; + int Length; //, i; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\".\n", pFileName ); + return; + } + // start the manager + p = Cut_CManStart(); + // load truth tables + while ( fgets(pString, 1000, pFile) ) + { + Length = strlen(pString); + pString[Length--] = 0; + if ( Length == 0 ) + continue; + // derive the cell + pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = Extra_Base2Log(Length*4); + pCell->nUsed = 1; +// Extra_TruthCopy( pCell->uTruth, pTruth, nVars ); + Extra_ReadHexadecimal( pCell->uTruth, pString, pCell->nVars ); + Cut_CellSuppMin( pCell ); +/* + // set the elementary permutation + for ( i = 0; i < (int)pCell->nVars; i++ ) + pCell->CanonPerm[i] = i; + // canonicize + pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); +*/ + // add to the table + p->nTotal++; + if ( !Cut_CellTableLookup( p, pCell ) ) // new cell + p->nGood++; + } + printf( "Read %d cells from file \"%s\". Added %d cells to the table.\n", p->nTotal, pFileName, p->nGood ); + fclose( pFile ); +// return p; +} + +/**Function************************************************************* + + Synopsis [Precomputes truth tables for the 2x2 macro cell.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CellPrecompute() +{ + Cut_CMan_t * p; + Cut_Cell_t * pCell, * pTemp; + int i1, i2, i3, i, j, k, c, clk = clock(), clk2 = clock(); + + p = Cut_CManStart(); + + // precompute truth tables + for ( i = 0; i < 22; i++ ) + Cut_CellTruthElem( p->uInputs[0], p->uInputs[1], p->uInputs[2], p->uTemp1[i], 9, i ); + for ( i = 0; i < 22; i++ ) + Cut_CellTruthElem( p->uInputs[3], p->uInputs[4], p->uInputs[5], p->uTemp2[i], 9, i ); + for ( i = 0; i < 22; i++ ) + Cut_CellTruthElem( p->uInputs[6], p->uInputs[7], p->uInputs[8], p->uTemp3[i], 9, i ); +/* + if ( k == 8 && ((i1 == 6 && i2 == 14 && i3 == 20) || (i1 == 20 && i2 == 6 && i3 == 14)) ) + { + Extra_PrintBinary( stdout, &pCell->CanonPhase, pCell->nVars+1 ); printf( " : " ); + for ( i = 0; i < pCell->nVars; i++ ) + printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); + Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); + printf( "\n" ); + } +*/ +/* + // go through symmetric roots + for ( k = 0; k < 5; k++ ) + for ( i1 = 0; i1 < 22; i1++ ) + for ( i2 = i1; i2 < 22; i2++ ) + for ( i3 = i2; i3 < 22; i3++ ) + { + // derive the cell + pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = 9; + pCell->Box[0] = s_NPNe3s[k]; + pCell->Box[1] = i1; + pCell->Box[2] = i2; + pCell->Box[3] = i3; + // fill in the truth table + Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3s[k] ); + // canonicize + Cut_CellCanonicize( pCell ); + + // add to the table + p->nTotal++; + if ( Cut_CellTableLookup( p, pCell ) ) // already exists + Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); + else + p->nGood++; + } + + // go through partially symmetric roots + for ( k = 0; k < 4; k++ ) + for ( i1 = 0; i1 < 22; i1++ ) + for ( i2 = 0; i2 < 22; i2++ ) + for ( i3 = i2; i3 < 22; i3++ ) + { + // derive the cell + pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = 9; + pCell->Box[0] = s_NPNe3p[k]; + pCell->Box[1] = i1; + pCell->Box[2] = i2; + pCell->Box[3] = i3; + // fill in the truth table + Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3p[k] ); + // canonicize + Cut_CellCanonicize( pCell ); + + // add to the table + p->nTotal++; + if ( Cut_CellTableLookup( p, pCell ) ) // already exists + Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); + else + p->nGood++; + } + + // go through non-symmetric functions + for ( i1 = 0; i1 < 22; i1++ ) + for ( i2 = 0; i2 < 22; i2++ ) + for ( i3 = 0; i3 < 22; i3++ ) + { + // derive the cell + pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = 9; + pCell->Box[0] = 17; + pCell->Box[1] = i1; + pCell->Box[2] = i2; + pCell->Box[3] = i3; + // fill in the truth table + Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, 17 ); + // canonicize + Cut_CellCanonicize( pCell ); + + // add to the table + p->nTotal++; + if ( Cut_CellTableLookup( p, pCell ) ) // already exists + Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); + else + p->nGood++; + } +*/ + + // go through non-symmetric functions + for ( k = 0; k < 10; k++ ) + for ( i1 = 0; i1 < 22; i1++ ) + for ( i2 = 0; i2 < 22; i2++ ) + for ( i3 = 0; i3 < 22; i3++ ) + { + // derive the cell + pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = 9; + pCell->Box[0] = s_NPNe3[k]; + pCell->Box[1] = i1; + pCell->Box[2] = i2; + pCell->Box[3] = i3; + // set the elementary permutation + for ( i = 0; i < (int)pCell->nVars; i++ ) + pCell->CanonPerm[i] = i; + // fill in the truth table + Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3[k] ); + // minimize the support + Cut_CellSuppMin( pCell ); + + // canonicize + pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); + + // add to the table + p->nTotal++; + if ( Cut_CellTableLookup( p, pCell ) ) // already exists + Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); + else + { + p->nGood++; + p->nVarCounts[pCell->nVars]++; + + if ( pCell->nVars ) + for ( i = 0; i < (int)pCell->nVars-1; i++ ) + { + if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric + continue; + // i and i+1 can be symmetric + // find the end of this group + for ( j = i+1; j < (int)pCell->nVars; j++ ) + if ( pCell->Store[2*i] != pCell->Store[2*j] ) + break; + + if ( pCell->Store[2*i] == pCell->Store[2*i+1] ) + p->nSymGroupsE[j-i]++; + else + p->nSymGroups[j-i]++; + i = j - 1; + } +/* + if ( pCell->nVars == 3 ) + { + Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" ); + for ( i = 0; i < (int)pCell->nVars; i++ ) + printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); + printf( "\n" ); + } +*/ + } + } + + printf( "BASIC: Total = %d. Good = %d. Entry = %d. ", p->nTotal, p->nGood, sizeof(Cut_Cell_t) ); + PRT( "Time", clock() - clk ); + printf( "Cells: " ); + for ( i = 0; i <= 9; i++ ) + printf( "%d=%d ", i, p->nVarCounts[i] ); + printf( "\nDiffs: " ); + for ( i = 0; i <= 9; i++ ) + printf( "%d=%d ", i, p->nSymGroups[i] ); + printf( "\nEquals: " ); + for ( i = 0; i <= 9; i++ ) + printf( "%d=%d ", i, p->nSymGroupsE[i] ); + printf( "\n" ); + + // continue adding new cells using support + for ( k = CUT_CELL_MVAR; k > 3; k-- ) + { + for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) + for ( i1 = 0; i1 < k; i1++ ) + for ( i2 = i1+1; i2 < k; i2++ ) + for ( c = 0; c < 3; c++ ) + { + // derive the cell + pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = pTemp->nVars; + pCell->pParent = pTemp; + // set the elementary permutation + for ( i = 0; i < (int)pCell->nVars; i++ ) + pCell->CanonPerm[i] = i; + // fill in the truth table + Extra_TruthCopy( pCell->uTruth, pTemp->uTruth, pTemp->nVars ); + // create the cross-bar + pCell->CrossBar0 = i1; + pCell->CrossBar1 = i2; + pCell->CrossBarPhase = c; + Cut_CellCrossBar( pCell ); + // minimize the support +//clk2 = clock(); + Cut_CellSuppMin( pCell ); +//p->timeSupp += clock() - clk2; + // canonicize +//clk2 = clock(); + pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); +//p->timeCanon += clock() - clk2; + + // add to the table +//clk2 = clock(); + p->nTotal++; + if ( Cut_CellTableLookup( p, pCell ) ) // already exists + Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); + else + { + p->nGood++; + p->nVarCounts[pCell->nVars]++; + + for ( i = 0; i < (int)pCell->nVars-1; i++ ) + { + if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric + continue; + // i and i+1 can be symmetric + // find the end of this group + for ( j = i+1; j < (int)pCell->nVars; j++ ) + if ( pCell->Store[2*i] != pCell->Store[2*j] ) + break; + + if ( pCell->Store[2*i] == pCell->Store[2*i+1] ) + p->nSymGroupsE[j-i]++; + else + p->nSymGroups[j-i]++; + i = j - 1; + } +/* + if ( pCell->nVars == 3 ) + { + Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" ); + for ( i = 0; i < (int)pCell->nVars; i++ ) + printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); + printf( "\n" ); + } +*/ + } +//p->timeTable += clock() - clk2; + } + + printf( "VAR %d: Total = %d. Good = %d. Entry = %d. ", k, p->nTotal, p->nGood, sizeof(Cut_Cell_t) ); + PRT( "Time", clock() - clk ); + printf( "Cells: " ); + for ( i = 0; i <= 9; i++ ) + printf( "%d=%d ", i, p->nVarCounts[i] ); + printf( "\nDiffs: " ); + for ( i = 0; i <= 9; i++ ) + printf( "%d=%d ", i, p->nSymGroups[i] ); + printf( "\nEquals: " ); + for ( i = 0; i <= 9; i++ ) + printf( "%d=%d ", i, p->nSymGroupsE[i] ); + printf( "\n" ); + } +// printf( "\n" ); + PRT( "Supp ", p->timeSupp ); + PRT( "Canon", p->timeCanon ); + PRT( "Table", p->timeTable ); +// Cut_CManStop( p ); +} + +/**Function************************************************************* + + Synopsis [Check the table.] + + Description [Returns 1 if such a truth table already exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell ) +{ + Cut_Cell_t ** pSlot, * pTemp; + unsigned Hash; + Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum( pCell->nVars ) ); + if ( !st_find_or_add( p->tTable, (char *)Hash, (char ***)&pSlot ) ) + *pSlot = NULL; + for ( pTemp = *pSlot; pTemp; pTemp = pTemp->pNext ) + { + if ( pTemp->nVars != pCell->nVars ) + continue; + if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) ) + return 1; + } + // the entry is new + pCell->pNext = *pSlot; + *pSlot = pCell; + // add it to the variable support list + pCell->pNextVar = p->pSameVar[pCell->nVars]; + p->pSameVar[pCell->nVars] = pCell; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CellSuppMin( Cut_Cell_t * pCell ) +{ + static unsigned uTemp[1<<(CUT_CELL_MVAR-5)]; + unsigned * pIn, * pOut, * pTemp; + int i, k, Counter, Temp; + + // go backward through the support variables and remove redundant + for ( k = pCell->nVars - 1; k >= 0; k-- ) + if ( !Extra_TruthVarInSupport(pCell->uTruth, pCell->nVars, k) ) + { + // shift all the variables above this one + Counter = 0; + pIn = pCell->uTruth; pOut = uTemp; + for ( i = k; i < (int)pCell->nVars - 1; i++ ) + { + Extra_TruthSwapAdjacentVars( pOut, pIn, pCell->nVars, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + // swap the support vars + Temp = pCell->CanonPerm[i]; + pCell->CanonPerm[i] = pCell->CanonPerm[i+1]; + pCell->CanonPerm[i+1] = Temp; + Counter++; + } + // return the function back into its place + if ( Counter & 1 ) + Extra_TruthCopy( pOut, pIn, pCell->nVars ); + // remove one variable + pCell->nVars--; +// Extra_PrintBinary( stdout, pCell->uTruth, (1<<pCell->nVars) ); printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CellCrossBar( Cut_Cell_t * pCell ) +{ + static unsigned uTemp0[1<<(CUT_CELL_MVAR-5)]; + static unsigned uTemp1[1<<(CUT_CELL_MVAR-5)]; + Extra_TruthCopy( uTemp0, pCell->uTruth, pCell->nVars ); + Extra_TruthCopy( uTemp1, pCell->uTruth, pCell->nVars ); + if ( pCell->CanonPhase == 0 ) + { + Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 ); + Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 ); + Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 ); + Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 ); + } + else if ( pCell->CanonPhase == 1 ) + { + Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar0 ); + Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 ); + Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar0 ); + Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 ); + } + else if ( pCell->CanonPhase == 2 ) + { + Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 ); + Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar1 ); + Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 ); + Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar1 ); + } + else assert( 0 ); + Extra_TruthCombine( pCell->uTruth, uTemp0, uTemp1, pCell->nVars, pCell->CrossBar0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i; + + assert( Type < 22 ); + switch ( Type ) + { + // " 0\n", // 00 const 0 + case 0: + for ( i = 0; i < nWords; i++ ) + pOut[i] = 0; + return; + // " 1\n", // 01 const 1 + case 1: + for ( i = 0; i < nWords; i++ ) + pOut[i] = 0xFFFFFFFF; + return; + // "1 1\n", // 02 a + case 2: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i]; + return; + // "11 1\n", // 03 ab + case 3: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] & InB[i]; + return; + // "11 0\n", // 04 (ab)' + case 4: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~(InA[i] & InB[i]); + return; + // "10 1\n01 1\n", // 05 a<+>b + case 5: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] ^ InB[i]; + return; + // "111 1\n", // 06 + abc + case 6: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] & InB[i] & InC[i]; + return; + // "111 0\n", // 07 (abc)' + case 7: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~(InA[i] & InB[i] & InC[i]); + return; + // "11- 1\n1-1 1\n", // 08 + a(b+c) + case 8: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] & (InB[i] | InC[i]); + return; + // "11- 0\n1-1 0\n", // 09 (a(b+c))' + case 9: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~(InA[i] & (InB[i] | InC[i])); + return; + // "111 1\n100 1\n010 1\n001 1\n", // 10 + a<+>b<+>c + case 10: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] ^ InB[i] ^ InC[i]; + return; + // "10- 0\n1-0 0\n011 0\n", // 11 + a<+>bc + case 11: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] ^ (InB[i] & InC[i]); + return; + // "101 1\n110 1\n", // 12 + a(b<+>c) + case 12: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] & (InB[i] ^ InC[i]); + return; + // "101 0\n110 0\n", // 13 (a(b<+>c))' + case 13: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~(InA[i] & (InB[i] ^ InC[i])); + return; + // "11- 1\n1-1 1\n-11 1\n", // 14 + ab+bc+ac + case 14: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (InA[i] & InC[i]); + return; + // "111 1\n000 1\n", // 15 + abc+a'b'c' + case 15: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]); + return; + // "111 0\n000 0\n", // 16 (abc+a'b'c')' + case 16: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~((InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i])); + return; + // "11- 1\n-11 1\n0-1 1\n", // 17 + ab+bc+a'c + case 17: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (~InA[i] & InC[i]); + return; + // "011 1\n101 1\n110 1\n", // 18 + a'bc+ab'c+abc' + case 18: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]); + return; + // "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' + case 19: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~((~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i])); + return; + // "100 1\n-11 1\n", // 20 + ab'c'+bc + case 20: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]); + return; + // "100 0\n-11 0\n" // 21 (ab'c'+bc)' + case 21: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~((InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i])); + return; + } +} + + +/**Function************************************************************* + + Synopsis [Start the precomputation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_CMan_t * Cut_CManStart() +{ + Cut_CMan_t * p; + int i, k; + // start the manager + assert( sizeof(unsigned) == 4 ); + p = ALLOC( Cut_CMan_t, 1 ); + memset( p, 0, sizeof(Cut_CMan_t) ); + // start the table and the memory manager + p->tTable = st_init_table(st_ptrcmp,st_ptrhash); + p->pMem = Extra_MmFixedStart( sizeof(Cut_Cell_t) ); + // set elementary truth tables + for ( k = 0; k < CUT_CELL_MVAR; k++ ) + for ( i = 0; i < (1<<CUT_CELL_MVAR); i++ ) + if ( i & (1 << k) ) + p->uInputs[k][i/32] |= (1 << (i%32)); + s_pCMan = p; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CManStop( Cut_CMan_t * p ) +{ + st_free_table( p->tTable ); + Extra_MmFixedStop( p->pMem, 0 ); + free( p ); +} +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_CellIsRunning() +{ + return s_pCMan != NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CellDumpToFile() +{ + FILE * pFile; + Cut_CMan_t * p = s_pCMan; + Cut_Cell_t * pTemp; + char * pFileName = "celllib22.txt"; + int NumUsed[10][5] = {{0}}; + int BoxUsed[22][5] = {{0}}; + int i, k, Counter; + int clk = clock(); + + if ( p == NULL ) + { + printf( "Cut_CellDumpToFile: Cell manager is not defined.\n" ); + return; + } + + // count the number of cells used + for ( k = CUT_CELL_MVAR; k >= 0; k-- ) + { + for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) + { + if ( pTemp->nUsed == 0 ) + NumUsed[k][0]++; + else if ( pTemp->nUsed < 10 ) + NumUsed[k][1]++; + else if ( pTemp->nUsed < 100 ) + NumUsed[k][2]++; + else if ( pTemp->nUsed < 1000 ) + NumUsed[k][3]++; + else + NumUsed[k][4]++; + + for ( i = 0; i < 4; i++ ) + if ( pTemp->nUsed == 0 ) + BoxUsed[ pTemp->Box[i] ][0]++; + else if ( pTemp->nUsed < 10 ) + BoxUsed[ pTemp->Box[i] ][1]++; + else if ( pTemp->nUsed < 100 ) + BoxUsed[ pTemp->Box[i] ][2]++; + else if ( pTemp->nUsed < 1000 ) + BoxUsed[ pTemp->Box[i] ][3]++; + else + BoxUsed[ pTemp->Box[i] ][4]++; + } + } + + printf( "Functions found = %10d. Functions not found = %10d.\n", p->nCellFound, p->nCellNotFound ); + for ( k = 0; k <= CUT_CELL_MVAR; k++ ) + { + printf( "%3d : ", k ); + for ( i = 0; i < 5; i++ ) + printf( "%8d ", NumUsed[k][i] ); + printf( "\n" ); + } + printf( "Box usage:\n" ); + for ( k = 0; k < 22; k++ ) + { + printf( "%3d : ", k ); + for ( i = 0; i < 5; i++ ) + printf( "%8d ", BoxUsed[k][i] ); + printf( " %s", s_NP3Names[k] ); + printf( "\n" ); + } + + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + printf( "Cut_CellDumpToFile: Cannout open output file.\n" ); + return; + } + + Counter = 0; + for ( k = 0; k <= CUT_CELL_MVAR; k++ ) + { + for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) + if ( pTemp->nUsed > 0 ) + { + Extra_PrintHexadecimal( pFile, pTemp->uTruth, (k <= 5? 5 : k) ); + fprintf( pFile, "\n" ); + Counter++; + } + fprintf( pFile, "\n" ); + } + fclose( pFile ); + + printf( "Library composed of %d functions is written into file \"%s\". ", Counter, pFileName ); + + PRT( "Time", clock() - clk ); +} + + +/**Function************************************************************* + + Synopsis [Looks up if the given function exists in the hash table.] + + Description [If the function exists, returns 1, meaning that it can be + implemented using two levels of 3-input LUTs. If the function does not + exist, return 0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_CellTruthLookup( unsigned * pTruth, int nVars ) +{ + Cut_CMan_t * p = s_pCMan; + Cut_Cell_t * pTemp; + Cut_Cell_t Cell, * pCell = &Cell; + unsigned Hash; + int i; + + // cell manager is not defined + if ( p == NULL ) + { + printf( "Cut_CellTruthLookup: Cell manager is not defined.\n" ); + return 0; + } + + // canonicize + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = nVars; + Extra_TruthCopy( pCell->uTruth, pTruth, nVars ); + Cut_CellSuppMin( pCell ); + // set the elementary permutation + for ( i = 0; i < (int)pCell->nVars; i++ ) + pCell->CanonPerm[i] = i; + // canonicize + pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); + + + // check if the cell exists + Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum(pCell->nVars) ); + if ( st_lookup( p->tTable, (char *)Hash, (char **)&pTemp ) ) + { + for ( ; pTemp; pTemp = pTemp->pNext ) + { + if ( pTemp->nVars != pCell->nVars ) + continue; + if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) ) + { + pTemp->nUsed++; + p->nCellFound++; + return 1; + } + } + } + p->nCellNotFound++; + return 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/opt/cut/cutSeq.c b/src/opt/cut/cutSeq.c index 4b8738a2..d36f94f7 100644 --- a/src/opt/cut/cutSeq.c +++ b/src/opt/cut/cutSeq.c @@ -109,9 +109,9 @@ void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int // merge the old and the new clk = clock(); Cut_ListStart( pSuper ); - Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[0], p->pStore1[1], 0 ); - Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[0], 0 ); - Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[1], fTriv ); + Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[0], p->pStore1[1], 0, 0 ); + Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[0], 0, 0 ); + Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[1], fTriv, 0 ); pListNew = Cut_ListFinish( pSuper ); p->timeMerge += clock() - clk; diff --git a/src/opt/cut/cutTruth.c b/src/opt/cut/cutTruth.c index b65e5eff..54b3aac0 100644 --- a/src/opt/cut/cutTruth.c +++ b/src/opt/cut/cutTruth.c @@ -20,17 +20,27 @@ #include "cutInt.h" +/* + Truth tables computed in this package are represented as bit-strings + stored in the cut data structure. Cuts of any number of inputs have + the truth table with 2^k bits, where k is the max number of cut inputs. +*/ + //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +extern int nTotal = 0; +extern int nGood = 0; +extern int nEqual = 0; + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [Performs truth table computation.] + Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] Description [] @@ -60,6 +70,48 @@ static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 ) Synopsis [Performs truth table computation.] + Description [This procedure cannot be used while recording oracle + because it will overwrite Num0 and Num1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_TruthNCanonicize( Cut_Cut_t * pCut ) +{ + unsigned uTruth; + unsigned * uCanon2; + char * pPhases2; + assert( pCut->nVarsMax < 6 ); + + // get the direct truth table + uTruth = *Cut_CutReadTruth(pCut); + + // compute the direct truth table + Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 ); +// uCanon[0] = uCanon2[0]; +// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; +// uPhases[0] = pPhases2[0]; + pCut->uCanon0 = uCanon2[0]; + pCut->Num0 = pPhases2[0]; + + // get the complemented truth table + uTruth = ~*Cut_CutReadTruth(pCut); + + // compute the direct truth table + Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 ); +// uCanon[0] = uCanon2[0]; +// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; +// uPhases[0] = pPhases2[0]; + pCut->uCanon1 = uCanon2[0]; + pCut->Num1 = pPhases2[0]; +} + +/**Function************************************************************* + + Synopsis [Performs truth table computation.] + Description [] SideEffects [] @@ -67,7 +119,7 @@ static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 ) SeeAlso [] ***********************************************************************/ -void Cut_TruthCompute( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) +void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) { static unsigned uTruth0[8], uTruth1[8]; int nTruthWords = Cut_TruthWords( pCut->nVarsMax ); @@ -111,43 +163,55 @@ void Cut_TruthCompute( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, i Synopsis [Performs truth table computation.] - Description [This procedure cannot be used while recording oracle - because it will overwrite Num0 and Num1.] + Description [] SideEffects [] SeeAlso [] ***********************************************************************/ -void Cut_TruthCanonicize( Cut_Cut_t * pCut ) +void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) { - unsigned uTruth; - unsigned * uCanon2; - char * pPhases2; - assert( pCut->nVarsMax < 6 ); - - // get the direct truth table - uTruth = *Cut_CutReadTruth(pCut); - - // compute the direct truth table - Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 ); -// uCanon[0] = uCanon2[0]; -// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; -// uPhases[0] = pPhases2[0]; - pCut->uCanon0 = uCanon2[0]; - pCut->Num0 = pPhases2[0]; + // permute the first table + if ( fCompl0 ) + Extra_TruthNot( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax ); + else + Extra_TruthCopy( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax ); + Extra_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut0) ); + // permute the second table + if ( fCompl1 ) + Extra_TruthNot( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax ); + else + Extra_TruthCopy( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax ); + Extra_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut1) ); + // produce the resulting table + if ( pCut->fCompl ) + Extra_TruthNand( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax ); + else + Extra_TruthAnd( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax ); + // quit if no fancy computation is needed + if ( !p->pParams->fFancy ) + return; + + // count the total number of truth tables computed + nTotal++; + + // MAPPING INTO ALTERA 6-2 LOGIC BLOCKS + // call this procedure to find the minimum number of common variables in the cofactors + // if this number is less or equal than 3, the cut can be implemented using the 6-2 logic block +// if ( Extra_TruthMinCofSuppOverlap( Cut_CutReadTruth(pCut), pCut->nVarsMax, NULL ) <= 3 ) +// nGood++; + + // MAPPING INTO ACTEL 2x2 CELLS + // call this procedure to see if a semi-canonical form can be found in the lookup table + // (if it exists, then a two-level 3-input LUT implementation of the cut exists) + // Before this procedure is called, cell manager should be defined by calling + // Cut_CellLoad (make sure file "cells22_daomap_iwls.txt" is available in the working dir) + if ( Cut_CellIsRunning() && pCut->nVarsMax <= 9 ) + nGood += Cut_CellTruthLookup( Cut_CutReadTruth(pCut), pCut->nVarsMax ); +} - // get the complemented truth table - uTruth = ~*Cut_CutReadTruth(pCut); - // compute the direct truth table - Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 ); -// uCanon[0] = uCanon2[0]; -// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; -// uPhases[0] = pPhases2[0]; - pCut->uCanon1 = uCanon2[0]; - pCut->Num1 = pPhases2[0]; -} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/opt/cut/module.make b/src/opt/cut/module.make index af2d8fc1..132e730b 100644 --- a/src/opt/cut/module.make +++ b/src/opt/cut/module.make @@ -4,5 +4,6 @@ SRC += src/opt/cut/cutApi.c \ src/opt/cut/cutMerge.c \ src/opt/cut/cutNode.c \ src/opt/cut/cutOracle.c \ + src/opt/cut/cutPre22.c \ src/opt/cut/cutSeq.c \ src/opt/cut/cutTruth.c diff --git a/src/opt/rwr/rwrEva.c b/src/opt/rwr/rwrEva.c index b83a524f..55132a75 100644 --- a/src/opt/rwr/rwrEva.c +++ b/src/opt/rwr/rwrEva.c @@ -66,7 +66,7 @@ int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int Required = fUpdateLevel? Abc_NodeReadRequiredLevel(pNode) : ABC_INFINITY; // get the node's cuts clk = clock(); - pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0 ); + pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 ); assert( pCut != NULL ); p->timeCut += clock() - clk; diff --git a/src/sat/aig/rwrTruth.c b/src/sat/aig/rwrTruth.c index 63a437ce..92a39f0a 100644 --- a/src/sat/aig/rwrTruth.c +++ b/src/sat/aig/rwrTruth.c @@ -95,7 +95,7 @@ static inline int Aig_WordCountOnes( unsigned val ) val = (val & 0x33333333) + ((val>>2) & 0x33333333); val = (val & 0x0F0F0F0F) + ((val>>4) & 0x0F0F0F0F); val = (val & 0x00FF00FF) + ((val>>8) & 0x00FF00FF); - return (val & 0x0000FFFF) + (val>>8); + return (val & 0x0000FFFF) + (val>>16); } /**Function************************************************************* diff --git a/src/sat/asat/added.c b/src/sat/asat/added.c index 497087fb..e1b1bb2a 100644 --- a/src/sat/asat/added.c +++ b/src/sat/asat/added.c @@ -41,6 +41,7 @@ static inline int lit_sign(lit l) { return (l & 1); } static void Asat_ClauseWriteDimacs( FILE * pFile, clause * pC, bool fIncrement ); +extern void Io_WriteCnfOutputPiMapping( FILE * pFile, int incrementVars ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -77,6 +78,7 @@ void Asat_SolverWriteDimacs( solver * p, char * pFileName, lit* assumptionsBegin return; } fprintf( pFile, "c CNF generated by ABC on %s\n", Extra_TimeStamp() ); +// Io_WriteCnfOutputPiMapping( pFile, incrementVars ); fprintf( pFile, "p cnf %d %d\n", p->size, nClauses ); // write the original clauses @@ -161,6 +163,31 @@ int * solver_get_model( solver * p, int * pVars, int nVars ) return pModel; } +/**Function************************************************************* + + Synopsis [Writes the given clause in a file in DIMACS format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Asat_SatPrintStats( FILE * pFile, solver * p ) +{ + printf( "Start = %4d. Conf = %6d. Dec = %6d. Prop = %7d. Insp = %8d.\n", + (int)p->solver_stats.starts, + (int)p->solver_stats.conflicts, + (int)p->solver_stats.decisions, + (int)p->solver_stats.propagations, + (int)p->solver_stats.inspects ); + printf( "Total runtime = %7.2f sec. Var select = %7.2f sec. Var update = %7.2f sec.\n", + (float)(p->timeTotal)/(float)(CLOCKS_PER_SEC), + (float)(p->timeSelect)/(float)(CLOCKS_PER_SEC), + (float)(p->timeUpdate)/(float)(CLOCKS_PER_SEC) ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/sat/asat/jfront.c b/src/sat/asat/jfront.c new file mode 100644 index 00000000..1def6a37 --- /dev/null +++ b/src/sat/asat/jfront.c @@ -0,0 +1,514 @@ +/**CFile**************************************************************** + + FileName [jfront.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [C-language MiniSat solver.] + + Synopsis [Implementation of J-frontier.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: jfront.c,v 1.4 2005/09/16 22:55:03 casem Exp $] + +***********************************************************************/ + +#include <stdio.h> +#include <assert.h> +#include "solver.h" +#include "extra.h" +#include "vec.h" + +/* + At any time during the solving process, the J-frontier is the set of currently + unassigned variables, each of which has at least one fanin/fanout variable that + is currently assigned. In the context of a CNF-based solver, default decisions + based on variable activity are modified to choose the most active variable among + those currently on the J-frontier. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// variable on the J-frontier +typedef struct Asat_JVar_t_ Asat_JVar_t; +struct Asat_JVar_t_ +{ + unsigned int Num; // variable number + unsigned int nRefs; // the number of adjacent assigned vars + unsigned int Prev; // the previous variable + unsigned int Next; // the next variable + unsigned int nFans; // the number of fanins/fanouts + unsigned int Fans[0]; // the fanin/fanout variables +}; + +// the J-frontier as a ring of variables +// (ring is used instead of list because it allows to control the insertion point) +typedef struct Asat_JRing_t_ Asat_JRing_t; +struct Asat_JRing_t_ +{ + Asat_JVar_t * pRoot; // the pointer to the root + int nItems; // the number of variables in the ring +}; + +// the J-frontier manager +struct Asat_JMan_t_ +{ + solver * pSat; // the SAT solver + Asat_JRing_t rVars; // the ring of variables + Vec_Ptr_t * vVars; // the pointers to variables + Extra_MmFlex_t * pMem; // the memory manager for variables +}; + +// getting hold of the given variable +static inline Asat_JVar_t * Asat_JManVar( Asat_JMan_t * p, int Num ) { return !Num? NULL : Vec_PtrEntry(p->vVars, Num); } +static inline Asat_JVar_t * Asat_JVarPrev( Asat_JMan_t * p, Asat_JVar_t * pVar ) { return Asat_JManVar(p, pVar->Prev); } +static inline Asat_JVar_t * Asat_JVarNext( Asat_JMan_t * p, Asat_JVar_t * pVar ) { return Asat_JManVar(p, pVar->Next); } + +//The solver can communicate to the variable order the following parts: +//- the array of current assignments (pSat->pAssigns) +//- the array of variable activities (pSat->pdActivity) +//- the array of variables currently in the cone +//- the array of arrays of variables adjacent to each other + +static inline int Asat_JVarIsInBoundary( Asat_JMan_t * p, Asat_JVar_t * pVar ) { return pVar->Next > 0; } +static inline int Asat_JVarIsAssigned( Asat_JMan_t * p, Asat_JVar_t * pVar ) { return p->pSat->assigns[pVar->Num] != l_Undef; } +//static inline int Asat_JVarIsUsedInCone( Asat_JMan_t * p, int Var ) { return p->pSat->vVarsUsed->pArray[i]; } + +// manipulating the ring of variables +static void Asat_JRingAddLast( Asat_JMan_t * p, Asat_JVar_t * pVar ); +static void Asat_JRingRemove( Asat_JMan_t * p, Asat_JVar_t * pVar ); + +// iterator through the entries in J-boundary +#define Asat_JRingForEachEntry( p, pVar, pNext ) \ + for ( pVar = p->rVars.pRoot, \ + pNext = pVar? Asat_JVarNext(p, pVar) : NULL; \ + pVar; \ + pVar = (pNext != p->rVars.pRoot)? pNext : NULL, \ + pNext = pVar? Asat_JVarNext(p, pVar) : NULL ) + +// iterator through the adjacent variables +#define Asat_JVarForEachFanio( p, pVar, pFan, i ) \ + for ( i = 0; (i < pVar->nFans) && (((pFan) = Asat_JManVar(p, pVar->Fans[i])), 1); i++ ) + +extern void Asat_JManAssign( Asat_JMan_t * p, int Var ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start the J-frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Asat_JMan_t * Asat_JManStart( solver * pSat, void * pCircuit ) +{ + Vec_Vec_t * vCircuit = pCircuit; + Asat_JMan_t * p; + Asat_JVar_t * pVar; + Vec_Int_t * vConnect; + int i, nBytes, Entry, k; + // make sure the number of variables is less than sizeof(unsigned int) + assert( Vec_VecSize(vCircuit) < (1 << 16) ); + assert( Vec_VecSize(vCircuit) == pSat->size ); + // allocate the manager + p = ALLOC( Asat_JMan_t, 1 ); + memset( p, 0, sizeof(Asat_JMan_t) ); + p->pSat = pSat; + p->pMem = Extra_MmFlexStart(); + // fill in the variables + p->vVars = Vec_PtrAlloc( Vec_VecSize(vCircuit) ); + for ( i = 0; i < Vec_VecSize(vCircuit); i++ ) + { + vConnect = Vec_VecEntry( vCircuit, i ); + nBytes = sizeof(Asat_JVar_t) + sizeof(int) * Vec_IntSize(vConnect); + nBytes = sizeof(void *) * (nBytes / sizeof(void *) + ((nBytes % sizeof(void *)) != 0)); + pVar = (Asat_JVar_t *)Extra_MmFlexEntryFetch( p->pMem, nBytes ); + memset( pVar, 0, nBytes ); + pVar->Num = i; + // add fanins/fanouts + pVar->nFans = Vec_IntSize( vConnect ); + Vec_IntForEachEntry( vConnect, Entry, k ) + pVar->Fans[k] = Entry; + // add the variable + Vec_PtrPush( p->vVars, pVar ); + } + // set the current assignments + Vec_PtrForEachEntryStart( p->vVars, pVar, i, 1 ) + { +// if ( !Asat_JVarIsUsedInCone(p, pVar) ) +// continue; + // skip assigned vars, vars in the boundary, and vars not used in the cone + if ( Asat_JVarIsAssigned(p, pVar) ) + Asat_JManAssign( p, pVar->Num ); + } + + pSat->pJMan = p; + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the J-frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Asat_JManStop( solver * pSat ) +{ + Asat_JMan_t * p = pSat->pJMan; + if ( p == NULL ) + return; + pSat->pJMan = NULL; + Extra_MmFlexStop( p->pMem, 0 ); + Vec_PtrFree( p->vVars ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Asat_JManCheck( Asat_JMan_t * p ) +{ + Asat_JVar_t * pVar, * pNext, * pFan; +// Msat_IntVec_t * vRound; +// int * pRound, nRound; +// int * pVars, nVars, i, k; + int i, k; + int Counter = 0; + + // go through all the variables in the boundary + Asat_JRingForEachEntry( p, pVar, pNext ) + { + assert( !Asat_JVarIsAssigned(p, pVar) ); + // go though all the variables in the neighborhood + // and check that it is true that there is least one assigned +// vRound = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( p->pSat->vAdjacents, pVar->Num ); +// nRound = Msat_IntVecReadSize( vRound ); +// pRound = Msat_IntVecReadArray( vRound ); +// for ( i = 0; i < nRound; i++ ) + Asat_JVarForEachFanio( p, pVar, pFan, i ) + { +// if ( !Asat_JVarIsUsedInCone(p, pFan) ) +// continue; + if ( Asat_JVarIsAssigned(p, pFan) ) + break; + } +// assert( i != pVar->nFans ); +// if ( i == pVar->nFans ) +// return 0; + if ( i == pVar->nFans ) + Counter++; + } + if ( Counter > 0 ) + printf( "%d(%d) ", Counter, p->rVars.nItems ); + + // we may also check other unassigned variables in the cone + // to make sure that if they are not in J-boundary, + // then they do not have an assigned neighbor +// nVars = Msat_IntVecReadSize( p->pSat->vConeVars ); +// pVars = Msat_IntVecReadArray( p->pSat->vConeVars ); +// for ( i = 0; i < nVars; i++ ) + Vec_PtrForEachEntry( p->vVars, pVar, i ) + { +// assert( Asat_JVarIsUsedInCone(p, pVar) ); + // skip assigned vars, vars in the boundary, and vars not used in the cone + if ( Asat_JVarIsAssigned(p, pVar) || Asat_JVarIsInBoundary(p, pVar) ) + continue; + // make sure, it does not have assigned neighbors +// vRound = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( p->pSat->vAdjacents, pVars[i] ); +// nRound = Msat_IntVecReadSize( vRound ); +// pRound = Msat_IntVecReadArray( vRound ); +// for ( i = 0; i < nRound; i++ ) + Asat_JVarForEachFanio( p, pVar, pFan, k ) + { +// if ( !Asat_JVarIsUsedInCone(p, pFan) ) +// continue; + if ( Asat_JVarIsAssigned(p, pFan) ) + break; + } +// assert( k == pVar->nFans ); +// if ( k != pVar->nFans ) +// return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Asat_JManAssign( Asat_JMan_t * p, int Var ) +{ +// Msat_IntVec_t * vRound; + Asat_JVar_t * pVar, * pFan; + int i, clk = clock(); + + // make sure the variable is in the boundary + assert( Var < Vec_PtrSize(p->vVars) ); + // if it is not in the boundary (initial decision, random decision), do not remove + pVar = Asat_JManVar( p, Var ); + if ( Asat_JVarIsInBoundary( p, pVar ) ) + Asat_JRingRemove( p, pVar ); + // add to the boundary those neighbors that are (1) unassigned, (2) not in boundary + // because for them we know that there is a variable (Var) which is assigned +// vRound = (Msat_IntVec_t *)p->pSat->vAdjacents->pArray[Var]; +// for ( i = 0; i < vRound->nSize; i++ ) + Asat_JVarForEachFanio( p, pVar, pFan, i ) + { +// if ( !Asat_JVarIsUsedInCone(p, pFan) ) +// continue; + pFan->nRefs++; + if ( Asat_JVarIsAssigned(p, pFan) || Asat_JVarIsInBoundary(p, pFan) ) + continue; + Asat_JRingAddLast( p, pFan ); + } +//timeSelect += clock() - clk; +// Asat_JManCheck( p ); + p->pSat->timeUpdate += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Asat_JManUnassign( Asat_JMan_t * p, int Var ) +{ +// Msat_IntVec_t * vRound, * vRound2; + Asat_JVar_t * pVar, * pFan; + int i, clk = clock();//, k + + // make sure the variable is not in the boundary + assert( Var < Vec_PtrSize(p->vVars) ); + pVar = Asat_JManVar( p, Var ); + assert( !Asat_JVarIsInBoundary( p, pVar ) ); + // go through its neigbors - if one of them is assigned add this var + // add to the boundary those neighbors that are not there already + // this will also get rid of variable outside of the current cone + // because they are unassigned in Msat_SolverPrepare() +// vRound = (Msat_IntVec_t *)p->pSat->vAdjacents->pArray[Var]; +// for ( i = 0; i < vRound->nSize; i++ ) +// if ( Asat_JVarIsAssigned(p, vRound->pArray[i]) ) +// break; +// if ( i != vRound->nSize ) +// Asat_JRingAddLast( &p->rVars, &p->pVars[Var] ); + if ( pVar->nRefs != 0 ) + Asat_JRingAddLast( p, pVar ); + +/* + // unassigning a variable may lead to its adjacents dropping from the boundary + for ( i = 0; i < vRound->nSize; i++ ) + if ( Asat_JVarIsInBoundary(p, vRound->pArray[i]) ) + { // the neighbor is in the J-boundary (and unassigned) + assert( !Asat_JVarIsAssigned(p, vRound->pArray[i]) ); + vRound2 = (Msat_IntVec_t *)p->pSat->vAdjacents->pArray[vRound->pArray[i]]; + // go through its neighbors and determine if there is at least one assigned + for ( k = 0; k < vRound2->nSize; k++ ) + if ( Asat_JVarIsAssigned(p, vRound2->pArray[k]) ) + break; + if ( k == vRound2->nSize ) // there is no assigned vars, delete this one + Asat_JRingRemove( &p->rVars, &p->pVars[vRound->pArray[i]] ); + } +*/ + Asat_JVarForEachFanio( p, pVar, pFan, i ) + { +// if ( !Asat_JVarIsUsedInCone(p, pFan) ) +// continue; + assert( pFan->nRefs > 0 ); + pFan->nRefs--; + if ( !Asat_JVarIsInBoundary(p, pFan) ) + continue; + // the neighbor is in the J-boundary (and unassigned) + assert( !Asat_JVarIsAssigned(p, pFan) ); + // if there is no assigned vars, delete this one + if ( pFan->nRefs == 0 ) + Asat_JRingRemove( p, pFan ); + } + +//timeSelect += clock() - clk; +// Asat_JManCheck( p ); + p->pSat->timeUpdate += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Asat_JManSelect( Asat_JMan_t * p ) +{ + Asat_JVar_t * pVar, * pNext, * pVarBest; + double * pdActs = p->pSat->activity; + double dfActBest; + int clk = clock(); + + pVarBest = NULL; + dfActBest = -1.0; + Asat_JRingForEachEntry( p, pVar, pNext ) + { + if ( dfActBest <= pdActs[pVar->Num] )//+ 0.00001 ) + { + dfActBest = pdActs[pVar->Num]; + pVarBest = pVar; + } + } +//timeSelect += clock() - clk; +//timeAssign += clock() - clk; +//if ( pVarBest && pVarBest->Num % 1000 == 0 ) +//printf( "%d ", p->rVars.nItems ); + +// Asat_JManCheck( p ); + p->pSat->timeSelect += clock() - clk; + if ( pVarBest ) + { +// assert( Asat_JVarIsUsedInCone(p, pVarBest) ); + return pVarBest->Num; + } + return var_Undef; +} + + + +/**Function************************************************************* + + Synopsis [Adds node to the end of the ring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Asat_JRingAddLast( Asat_JMan_t * p, Asat_JVar_t * pVar ) +{ + Asat_JRing_t * pRing = &p->rVars; +//printf( "adding %d\n", pVar->Num ); + // check that the node is not in a ring + assert( pVar->Prev == 0 ); + assert( pVar->Next == 0 ); + // if the ring is empty, make the node point to itself + pRing->nItems++; + if ( pRing->pRoot == NULL ) + { + pRing->pRoot = pVar; +// pVar->pPrev = pVar; + pVar->Prev = pVar->Num; +// pVar->pNext = pVar; + pVar->Next = pVar->Num; + return; + } + // if the ring is not empty, add it as the last entry +// pVar->pPrev = pRing->pRoot->pPrev; + pVar->Prev = pRing->pRoot->Prev; +// pVar->pNext = pRing->pRoot; + pVar->Next = pRing->pRoot->Num; +// pVar->pPrev->pNext = pVar; + Asat_JVarPrev(p, pVar)->Next = pVar->Num; +// pVar->pNext->pPrev = pVar; + Asat_JVarNext(p, pVar)->Prev = pVar->Num; + + // move the root so that it points to the new entry +// pRing->pRoot = pRing->pRoot->pPrev; + pRing->pRoot = Asat_JVarPrev(p, pRing->pRoot); +} + +/**Function************************************************************* + + Synopsis [Removes the node from the ring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Asat_JRingRemove( Asat_JMan_t * p, Asat_JVar_t * pVar ) +{ + Asat_JRing_t * pRing = &p->rVars; +//printf( "removing %d\n", pVar->Num ); + // check that the var is in a ring + assert( pVar->Prev ); + assert( pVar->Next ); + pRing->nItems--; + if ( pRing->nItems == 0 ) + { + assert( pRing->pRoot == pVar ); +// pVar->pPrev = NULL; + pVar->Prev = 0; +// pVar->pNext = NULL; + pVar->Next = 0; + pRing->pRoot = NULL; + return; + } + // move the root if needed + if ( pRing->pRoot == pVar ) +// pRing->pRoot = pVar->pNext; + pRing->pRoot = Asat_JVarNext(p, pVar); + // move the root to the next entry after pVar + // this way all the additions to the list will be traversed first +// pRing->pRoot = pVar->pNext; + pRing->pRoot = Asat_JVarPrev(p, pVar); + // delete the node +// pVar->pPrev->pNext = pVar->pNext; + Asat_JVarPrev(p, pVar)->Next = Asat_JVarNext(p, pVar)->Num; +// pVar->pNext->pPrev = pVar->pPrev; + Asat_JVarNext(p, pVar)->Prev = Asat_JVarPrev(p, pVar)->Num; +// pVar->pPrev = NULL; + pVar->Prev = 0; +// pVar->pNext = NULL; + pVar->Next = 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/sat/asat/module.make b/src/sat/asat/module.make index d5cf69bf..26489191 100644 --- a/src/sat/asat/module.make +++ b/src/sat/asat/module.make @@ -1,3 +1,4 @@ SRC += src/sat/asat/added.c \ src/sat/asat/asatmem.c \ + src/sat/asat/jfront.c \ src/sat/asat/solver.c diff --git a/src/sat/asat/solver.c b/src/sat/asat/solver.c index 1130d437..6d76d890 100644 --- a/src/sat/asat/solver.c +++ b/src/sat/asat/solver.c @@ -121,6 +121,7 @@ static inline void vec_remove(vec* v, void* e) static inline void order_update(solver* s, int v) // updateorder { +// int clk = clock(); int* orderpos = s->orderpos; double* activity = s->activity; int* heap = (int*)vec_begin(&s->order); @@ -138,6 +139,7 @@ static inline void order_update(solver* s, int v) // updateorder } heap[i] = x; orderpos[x] = i; +// s->timeUpdate += clock() - clk; } static inline void order_assigned(solver* s, int v) @@ -146,16 +148,19 @@ static inline void order_assigned(solver* s, int v) static inline void order_unassigned(solver* s, int v) // undoorder { +// int clk = clock(); int* orderpos = s->orderpos; if (orderpos[v] == -1){ orderpos[v] = vec_size(&s->order); vec_push(&s->order,(void*)v); order_update(s,v); } +// s->timeUpdate += clock() - clk; } static int order_select(solver* s, float random_var_freq) // selectvar { +// int clk = clock(); int* heap; double* activity; int* orderpos; @@ -215,9 +220,15 @@ static int order_select(solver* s, float random_var_freq) // selectvar return next; } +// s->timeSelect += clock() - clk; return var_Undef; } +// J-frontier +extern void Asat_JManAssign( Asat_JMan_t * p, int Var ); +extern void Asat_JManUnassign( Asat_JMan_t * p, int Var ); +extern int Asat_JManSelect( Asat_JMan_t * p ); + //================================================================================================= // Activity functions: @@ -236,7 +247,7 @@ static inline void act_var_bump(solver* s, int v) { //printf("bump %d %f\n", v-1, activity[v]); - if (s->orderpos[v] != -1) + if ( s->pJMan == NULL && s->orderpos[v] != -1 ) order_update(s,v); } @@ -422,7 +433,10 @@ static inline bool enqueue(solver* s, lit l, clause* from) reasons[v] = from; s->trail[s->qtail++] = l; - order_assigned(s, v); + if ( s->pJMan ) + Asat_JManAssign( s->pJMan, v ); + else + order_assigned(s, v); return 1; } } @@ -460,8 +474,12 @@ static inline void solver_canceluntil(solver* s, int level) { reasons[x] = (clause*)0; } - for (c = s->qhead-1; c >= bound; c--) - order_unassigned(s,lit_var(trail[c])); + if ( s->pJMan ) + for (c = s->qtail-1; c >= bound; c--) + Asat_JManUnassign( s->pJMan, lit_var(trail[c]) ); + else + for (c = s->qhead-1; c >= bound; c--) + order_unassigned( s, lit_var(trail[c]) ); s->qhead = s->qtail = bound; vec_resize(&s->trail_lim,level); @@ -803,7 +821,7 @@ static lbool solver_search(solver* s, int nof_conflicts, int nof_learnts) int* levels = s->levels; double var_decay = 0.95; double clause_decay = 0.999; - double random_var_freq = 0.02; + double random_var_freq = 0.0;//0.02; int conflictC = 0; vec learnt_clause; @@ -872,7 +890,10 @@ static lbool solver_search(solver* s, int nof_conflicts, int nof_learnts) // New variable decision: s->solver_stats.decisions++; - next = order_select(s,(float)random_var_freq); + if ( s->pJMan ) + next = Asat_JManSelect( s->pJMan ); + else + next = order_select(s,(float)random_var_freq); if (next == var_Undef){ // Model found: @@ -953,7 +974,10 @@ solver* solver_new(void) #else s->pMem = Asat_MmStepStart( 10 ); #endif - + s->pJMan = NULL; + s->timeTotal = clock(); + s->timeSelect = 0; + s->timeUpdate = 0; return s; } @@ -998,6 +1022,7 @@ void solver_delete(solver* s) free(s->tags ); } + if ( s->pJMan ) Asat_JManStop( s ); free(s); } @@ -1155,6 +1180,7 @@ bool solver_solve(solver* s, lit* begin, lit* end, int nConfLimit, int nImpLimit printf("==============================================================================\n"); solver_canceluntil(s,0); + s->timeTotal = clock() - s->timeTotal; return status; } diff --git a/src/sat/asat/solver.h b/src/sat/asat/solver.h index 62815656..3684d259 100644 --- a/src/sat/asat/solver.h +++ b/src/sat/asat/solver.h @@ -64,6 +64,8 @@ static inline lit toLitCond (int v, int c) { return v + v + (int)(c != 0); } //================================================================================================= // Public interface: +typedef struct Asat_JMan_t_ Asat_JMan_t; + struct solver_t; typedef struct solver_t solver; @@ -82,6 +84,12 @@ extern int solver_nclauses(solver* s); extern void Asat_SolverWriteDimacs( solver * pSat, char * pFileName, lit* assumptionsBegin, lit* assumptionsEnd, int incrementVars); +extern void Asat_SatPrintStats( FILE * pFile, solver * p ); + +// J-frontier support +extern Asat_JMan_t * Asat_JManStart( solver * pSat, void * vCircuit ); +extern void Asat_JManStop( solver * pSat ); + struct stats_t { @@ -143,7 +151,13 @@ struct solver_t // the memory manager Asat_MmStep_t * pMem; + // J-frontier + Asat_JMan_t * pJMan; + stats solver_stats; + int timeTotal; + int timeSelect; + int timeUpdate; }; #ifdef __cplusplus diff --git a/src/sat/csat/csat_apis.c b/src/sat/csat/csat_apis.c index 2129bfb0..9184cab9 100644 --- a/src/sat/csat/csat_apis.c +++ b/src/sat/csat/csat_apis.c @@ -17,6 +17,7 @@ ***********************************************************************/ #include "abc.h" +#include "fraig.h" #include "csat_apis.h" //////////////////////////////////////////////////////////////////////// @@ -105,6 +106,8 @@ ABC_Manager ABC_InitManager() ***********************************************************************/ void ABC_ReleaseManager( ABC_Manager mng ) { + CSAT_Target_ResultT * p_res = ABC_Get_Target_Result( mng,0 ); + ABC_TargetResFree(p_res); if ( mng->tNode2Name ) stmm_free_table( mng->tNode2Name ); if ( mng->tName2Node ) stmm_free_table( mng->tName2Node ); if ( mng->pMmNames ) Extra_MmFlexStop( mng->pMmNames, 0 ); @@ -536,6 +539,7 @@ void ABC_AnalyzeTargets( ABC_Manager mng ) ***********************************************************************/ enum CSAT_StatusT ABC_Solve( ABC_Manager mng ) { + Prove_Params_t Params, * pParams = &Params; int RetValue, i; // check if the target network is available @@ -544,9 +548,16 @@ enum CSAT_StatusT ABC_Solve( ABC_Manager mng ) // try to prove the miter using a number of techniques if ( mng->mode ) - RetValue = Abc_NtkMiterSat( mng->pTarget, mng->nConfLimit, mng->nImpLimit, 0 ); + RetValue = Abc_NtkMiterSat( mng->pTarget, mng->nConfLimit, mng->nImpLimit, 0, 0 ); else - RetValue = Abc_NtkMiterProve( &mng->pTarget, mng->nConfLimit, mng->nImpLimit, 1, 1, 0 ); + { + // set default parameters for CEC + Prove_ParamsSetDefault( pParams ); + // set infinite resource limit for the final mitering + pParams->nMiteringLimitLast = ABC_INFINITY; + // call the checker + RetValue = Abc_NtkMiterProve( &mng->pTarget, pParams ); + } // analyze the result mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) ); @@ -658,6 +669,14 @@ void ABC_TargetResFree( CSAT_Target_ResultT * p ) { if ( p == NULL ) return; + if( p->names ) + { + int i = 0; + for ( i = 0; i < p->no_sig; i++ ) + { + FREE(p->names[i]); + } + } FREE( p->names ); FREE( p->values ); free( p ); diff --git a/src/sat/fraig/fraig.h b/src/sat/fraig/fraig.h index 4e2a295e..d6215465 100644 --- a/src/sat/fraig/fraig.h +++ b/src/sat/fraig/fraig.h @@ -41,6 +41,7 @@ typedef struct Fraig_NodeVecStruct_t_ Fraig_NodeVec_t; typedef struct Fraig_HashTableStruct_t_ Fraig_HashTable_t; typedef struct Fraig_ParamsStruct_t_ Fraig_Params_t; typedef struct Fraig_PatternsStruct_t_ Fraig_Patterns_t; +typedef struct Prove_ParamsStruct_t_ Prove_Params_t; struct Fraig_ParamsStruct_t_ { @@ -61,6 +62,31 @@ struct Fraig_ParamsStruct_t_ int fInternal; // is set to 1 for internal fraig calls }; +struct Prove_ParamsStruct_t_ +{ + // general parameters + int fUseFraiging; // enables fraiging + int fUseRewriting; // enables rewriting + int fUseBdds; // enables BDD construction when other methods fail + int fVerbose; // prints verbose stats + // iterations + int nItersMax; // the number of iterations + // mitering + int nMiteringLimitStart; // starting mitering limit + float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // rewriting + int nRewritingLimitStart; // the number of rewriting iterations + float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // fraiging + int nFraigingLimitStart; // starting backtrack(conflict) limit + float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // last-gasp BDD construction + int nBddSizeLimit; // the number of BDD nodes when construction is aborted + int fBddReorder; // enables dynamic BDD variable reordering + // last-gasp mitering + int nMiteringLimitLast; // final mitering limit +}; + //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// @@ -155,6 +181,7 @@ extern Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pNode, extern void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew ); /*=== fraigMan.c =============================================================*/ +extern void Prove_ParamsSetDefault( Prove_Params_t * pParams ); extern void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ); extern void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams ); extern Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ); diff --git a/src/sat/fraig/fraigApi.c b/src/sat/fraig/fraigApi.c index 3b8da17f..b4bdbcab 100644 --- a/src/sat/fraig/fraigApi.c +++ b/src/sat/fraig/fraigApi.c @@ -65,7 +65,7 @@ int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ) { // returns the number of dynamic patterns proved useful to distinquish some FRAIG nodes (this number is more than 0 after the first garbage collection of patterns) int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ) { return p->iPatsPerm; } // returns the number of times FRAIG package timed out -int Fraig_ManReadSatFails( Fraig_Man_t * p ) { return p->nSatFails; } +int Fraig_ManReadSatFails( Fraig_Man_t * p ) { return p->nSatFailsReal; } /**Function************************************************************* diff --git a/src/sat/fraig/fraigInt.h b/src/sat/fraig/fraigInt.h index 890af13c..8e016331 100644 --- a/src/sat/fraig/fraigInt.h +++ b/src/sat/fraig/fraigInt.h @@ -189,7 +189,8 @@ struct Fraig_ManStruct_t_ int nSatCalls; // the number of times equivalence checking was called int nSatProof; // the number of times a proof was found int nSatCounter; // the number of times a counter example was found - int nSatFails; // the number of times the SAT solver failed to complete + int nSatFails; // the number of times the SAT solver failed to complete due to resource limit or prediction + int nSatFailsReal; // the number of times the SAT solver failed to complete due to resource limit int nSatCallsImp; // the number of times equivalence checking was called int nSatProofImp; // the number of times a proof was found @@ -243,8 +244,9 @@ struct Fraig_NodeStruct_t_ unsigned fMark3 : 1; // the mark used for traversals unsigned fFeedUse : 1; // the presence of the variable in the feedback unsigned fFeedVal : 1; // the value of the variable in the feedback + unsigned fFailTfo : 1; // the node is in the TFO of the failed SAT run unsigned nFanouts : 2; // the indicator of fanouts (none, one, or many) - unsigned nOnes : 21; // the number of 1's in the random sim info + unsigned nOnes : 20; // the number of 1's in the random sim info // the children of the node Fraig_Node_t * p1; // the first child diff --git a/src/sat/fraig/fraigMan.c b/src/sat/fraig/fraigMan.c index ff6faa33..3268ac3a 100644 --- a/src/sat/fraig/fraigMan.c +++ b/src/sat/fraig/fraigMan.c @@ -40,6 +40,42 @@ int timeAssign; SeeAlso [] ***********************************************************************/ +void Prove_ParamsSetDefault( Prove_Params_t * pParams ) +{ + // general parameters + pParams->fUseFraiging = 1; // enables fraiging + pParams->fUseRewriting = 1; // enables rewriting + pParams->fUseBdds = 1; // enables BDD construction when other methods fail + pParams->fVerbose = 0; // prints verbose stats + // iterations + pParams->nItersMax = 6; // the number of iterations + // mitering + pParams->nMiteringLimitStart = 1000; // starting mitering limit + pParams->nMiteringLimitMulti = 2.0; // multiplicative coefficient to increase the limit in each iteration + // rewriting + pParams->nRewritingLimitStart = 3; // the number of rewriting iterations + pParams->nRewritingLimitMulti = 1.0; // multiplicative coefficient to increase the limit in each iteration + // fraiging + pParams->nFraigingLimitStart = 2; // starting backtrack(conflict) limit + pParams->nFraigingLimitMulti = 8.0; // multiplicative coefficient to increase the limit in each iteration + // last-gasp BDD construction + pParams->nBddSizeLimit = 1000000; // the number of BDD nodes when construction is aborted + pParams->fBddReorder = 1; // enables dynamic BDD variable reordering + // last-gasp mitering + pParams->nMiteringLimitLast = 1000000; // final mitering limit +} + +/**Function************************************************************* + + Synopsis [Sets the default parameters of the package.] + + Description [This set of parameters is tuned for equivalence checking.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ) { memset( pParams, 0, sizeof(Fraig_Params_t) ); @@ -271,8 +307,8 @@ void Fraig_ManPrintStats( Fraig_Man_t * p ) (sizeof(Fraig_Node_t) + sizeof(unsigned)*(p->nWordsRand + p->nWordsDyna) /*+ p->nSuppWords*sizeof(unsigned)*/))/(1<<20); printf( "Words: Random = %d. Dynamic = %d. Used = %d. Memory = %0.2f Mb.\n", p->nWordsRand, p->nWordsDyna, p->iWordPerm, nMemory ); - printf( "Proof = %d. Counter-example = %d. Fail = %d. Zero = %d.\n", - p->nSatProof, p->nSatCounter, p->nSatFails, p->nSatZeros ); + printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", + p->nSatProof, p->nSatCounter, p->nSatFails, p->nSatFailsReal, p->nSatZeros ); printf( "Nodes: Final = %d. Total = %d. Mux = %d. (Exor = %d.) ClaVars = %d.\n", Fraig_CountNodes(p,0), p->vNodes->nSize, Fraig_ManCountMuxes(p), Fraig_ManCountExors(p), p->nVarsClauses ); if ( p->pSat ) Msat_SolverPrintStats( p->pSat ); diff --git a/src/sat/fraig/fraigNode.c b/src/sat/fraig/fraigNode.c index 84509e9e..6e3d3c7d 100644 --- a/src/sat/fraig/fraigNode.c +++ b/src/sat/fraig/fraigNode.c @@ -176,6 +176,7 @@ Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_ // compute the level of this node pNode->Level = 1 + FRAIG_MAX(Fraig_Regular(p1)->Level, Fraig_Regular(p2)->Level); pNode->fInv = Fraig_NodeIsSimComplement(p1) & Fraig_NodeIsSimComplement(p2); + pNode->fFailTfo = Fraig_Regular(p1)->fFailTfo | Fraig_Regular(p2)->fFailTfo; // derive the simulation info clk = clock(); diff --git a/src/sat/fraig/fraigPrime.c b/src/sat/fraig/fraigPrime.c index 9745b7e6..127ad478 100644 --- a/src/sat/fraig/fraigPrime.c +++ b/src/sat/fraig/fraigPrime.c @@ -22,7 +22,7 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -// The 1,000 smallest prime numbers used to compute the hash value +// The 1,024 smallest prime numbers used to compute the hash value // http://www.math.utah.edu/~alfeld/math/primelist.html int s_FraigPrimes[FRAIG_MAX_PRIMES] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, @@ -93,7 +93,9 @@ int s_FraigPrimes[FRAIG_MAX_PRIMES] = { 2, 3, 5, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, -7877, 7879, 7883, 7901, 7907, 7919 }; +7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, +8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, +8147, 8161 }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// diff --git a/src/sat/fraig/fraigSat.c b/src/sat/fraig/fraigSat.c index d4358772..aa28a4f2 100644 --- a/src/sat/fraig/fraigSat.c +++ b/src/sat/fraig/fraigSat.c @@ -17,6 +17,7 @@ ***********************************************************************/ #include "fraigInt.h" +#include "math.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -304,6 +305,20 @@ int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * assert( !Fraig_IsComplement(pOld) ); assert( pNew != pOld ); + // if at least one of the nodes is a failed node, perform adjustments: + // if the backtrack limit is small, simply skip this node + // if the backtrack limit is > 10, take the quare root of the limit + if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) + { + p->nSatFails++; +// return 0; +// if ( nBTLimit > 10 ) +// nBTLimit /= 10; + if ( nBTLimit <= 10 ) + return 0; + nBTLimit = (int)sqrt(nBTLimit); + } + p->nSatCalls++; // make sure the solver is allocated and has enough variables @@ -394,13 +409,27 @@ PRT( "time", clock() - clk ); // record the counter example Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "s(%d)", pNew->Level ); p->nSatCounter++; return 0; } else // if ( RetValue1 == MSAT_UNKNOWN ) { p->time3 += clock() - clk; - p->nSatFails++; + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "T(%d)", pNew->Level ); + + // mark the node as the failed node + if ( pOld != p->pConst1 ) + pOld->fFailTfo = 1; + pNew->fFailTfo = 1; +// p->nSatFails++; + p->nSatFailsReal++; return 0; } @@ -454,17 +483,34 @@ PRT( "time", clock() - clk ); // record the counter example Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); p->nSatCounter++; + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "s(%d)", pNew->Level ); return 0; } else // if ( RetValue1 == MSAT_UNKNOWN ) { p->time3 += clock() - clk; - p->nSatFails++; + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "T(%d)", pNew->Level ); + + // mark the node as the failed node + pOld->fFailTfo = 1; + pNew->fFailTfo = 1; +// p->nSatFails++; + p->nSatFailsReal++; return 0; } // return SAT proof p->nSatProof++; + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "u(%d)", pNew->Level ); return 1; } diff --git a/src/sat/msat/msatOrderJ.c b/src/sat/msat/msatOrderJ.c index 5cba1165..4db7ff7b 100644 --- a/src/sat/msat/msatOrderJ.c +++ b/src/sat/msat/msatOrderJ.c @@ -38,7 +38,7 @@ struct Msat_OrderVar_t_ { Msat_OrderVar_t * pNext; Msat_OrderVar_t * pPrev; - int Num; + int Num; }; // the ring of variables data structure (J-boundary) @@ -170,7 +170,8 @@ int Msat_OrderCheck( Msat_Order_t * p ) Msat_OrderVar_t * pVar, * pNext; Msat_IntVec_t * vRound; int * pRound, nRound; - int * pVars, nVars, i; + int * pVars, nVars, i, k; + int Counter = 0; // go through all the variables in the boundary Msat_OrderRingForEachEntry( p->rVars.pRoot, pVar, pNext ) @@ -188,10 +189,14 @@ int Msat_OrderCheck( Msat_Order_t * p ) if ( Msat_OrderVarIsAssigned(p, pRound[i]) ) break; } - assert( i != nRound ); - if ( i != nRound ) - return 0; +// assert( i != nRound ); +// if ( i == nRound ) +// return 0; + if ( i == nRound ) + Counter++; } + if ( Counter > 0 ) + printf( "%d(%d) ", Counter, p->rVars.nItems ); // we may also check other unassigned variables in the cone // to make sure that if they are not in J-boundary, @@ -209,16 +214,16 @@ int Msat_OrderCheck( Msat_Order_t * p ) vRound = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( p->pSat->vAdjacents, pVars[i] ); nRound = Msat_IntVecReadSize( vRound ); pRound = Msat_IntVecReadArray( vRound ); - for ( i = 0; i < nRound; i++ ) + for ( k = 0; k < nRound; k++ ) { - if ( !Msat_OrderVarIsUsedInCone(p, pRound[i]) ) + if ( !Msat_OrderVarIsUsedInCone(p, pRound[k]) ) continue; - if ( Msat_OrderVarIsAssigned(p, pRound[i]) ) + if ( Msat_OrderVarIsAssigned(p, pRound[k]) ) break; } - assert( i == nRound ); - if ( i == nRound ) - return 0; +// assert( k == nRound ); +// if ( k != nRound ) +// return 0; } return 1; } @@ -256,7 +261,7 @@ int Msat_OrderVarSelect( Msat_Order_t * p ) Msat_OrderVar_t * pVar, * pNext, * pVarBest; double * pdActs = p->pSat->pdActivity; double dfActBest; - int clk = clock(); +// int clk = clock(); pVarBest = NULL; dfActBest = -1.0; @@ -268,12 +273,13 @@ int Msat_OrderVarSelect( Msat_Order_t * p ) pVarBest = pVar; } } -timeSelect += clock() - clk; -timeAssign += clock() - clk; +//timeSelect += clock() - clk; +//timeAssign += clock() - clk; //if ( pVarBest && pVarBest->Num % 1000 == 0 ) //printf( "%d ", p->rVars.nItems ); +// Msat_OrderCheck( p ); if ( pVarBest ) { assert( Msat_OrderVarIsUsedInCone(p, pVarBest->Num) ); @@ -296,7 +302,7 @@ timeAssign += clock() - clk; void Msat_OrderVarAssigned( Msat_Order_t * p, int Var ) { Msat_IntVec_t * vRound; - int i, clk = clock(); + int i;//, clk = clock(); // make sure the variable is in the boundary assert( Var < p->nVarsAlloc ); @@ -316,7 +322,7 @@ void Msat_OrderVarAssigned( Msat_Order_t * p, int Var ) continue; Msat_OrderRingAddLast( &p->rVars, &p->pVars[vRound->pArray[i]] ); } -timeSelect += clock() - clk; +//timeSelect += clock() - clk; // Msat_OrderCheck( p ); } @@ -334,7 +340,7 @@ timeSelect += clock() - clk; void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var ) { Msat_IntVec_t * vRound, * vRound2; - int i, k, clk = clock(); + int i, k;//, clk = clock(); // make sure the variable is not in the boundary assert( Var < p->nVarsAlloc ); @@ -363,7 +369,7 @@ void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var ) if ( k == vRound2->nSize ) // there is no assigned vars, delete this one Msat_OrderRingRemove( &p->rVars, &p->pVars[vRound->pArray[i]] ); } -timeSelect += clock() - clk; +//timeSelect += clock() - clk; // Msat_OrderCheck( p ); } @@ -450,7 +456,7 @@ void Msat_OrderRingRemove( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar ) pRing->pRoot = pVar->pNext; // move the root to the next entry after pVar // this way all the additions to the list will be traversed first -// pRing->pRoot = pVar->pNext; +// pRing->pRoot = pVar->pPrev; // delete the node pVar->pPrev->pNext = pVar->pNext; pVar->pNext->pPrev = pVar->pPrev; |