diff options
Diffstat (limited to 'src/base')
-rw-r--r-- | src/base/abc/abc.h | 8 | ||||
-rw-r--r-- | src/base/abc/abcFunc.c | 16 | ||||
-rw-r--r-- | src/base/abc/abcUtil.c | 20 | ||||
-rw-r--r-- | src/base/abci/abc.c | 515 | ||||
-rw-r--r-- | src/base/abci/abcDetect.c | 2 | ||||
-rw-r--r-- | src/base/abci/abcDress3.c | 344 | ||||
-rw-r--r-- | src/base/abci/abcExact.c | 1696 | ||||
-rw-r--r-- | src/base/abci/abcFx.c | 199 | ||||
-rw-r--r-- | src/base/abci/abcIf.c | 20 | ||||
-rw-r--r-- | src/base/abci/abcMini.c | 2 | ||||
-rw-r--r-- | src/base/abci/abcPrint.c | 8 | ||||
-rw-r--r-- | src/base/abci/module.make | 2 | ||||
-rw-r--r-- | src/base/io/ioReadBench.c | 2 | ||||
-rw-r--r-- | src/base/io/ioReadPlaMo.c | 79 | ||||
-rw-r--r-- | src/base/wlc/wlc.h | 2 | ||||
-rw-r--r-- | src/base/wlc/wlcBlast.c | 114 | ||||
-rw-r--r-- | src/base/wlc/wlcCom.c | 45 | ||||
-rw-r--r-- | src/base/wlc/wlcReadSmt.c | 22 | ||||
-rw-r--r-- | src/base/wlc/wlcReadVer.c | 4 | ||||
-rw-r--r-- | src/base/wlc/wlcSim.c | 2 |
20 files changed, 2904 insertions, 198 deletions
diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 971f29bb..35b20dbe 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -642,6 +642,11 @@ extern ABC_DLL int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkIsAcyclicWithBoxes( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ); +/*=== abcExact.c ==========================================================*/ +extern ABC_DLL int Abc_ExactInputNum(); +extern ABC_DLL int Abc_ExactIsRunning(); +extern ABC_DLL Abc_Obj_t * Abc_ExactBuildNode( word * pTruth, int nVars, int * pArrTimeProfile, Abc_Obj_t ** pFanins, Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrivalTimes, int fVerbose ); /*=== abcFanio.c ==========================================================*/ extern ABC_DLL void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); extern ABC_DLL void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); @@ -820,7 +825,7 @@ extern ABC_DLL void Abc_NtkDontCareFree( Odc_Man_t * p ); extern ABC_DLL int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ); /*=== abcPrint.c ==========================================================*/ extern ABC_DLL float Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk ); -extern ABC_DLL void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fPrintMem ); +extern ABC_DLL void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fSkipSmall, int fPrintMem ); extern ABC_DLL void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintFlops ); extern ABC_DLL void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk, int fUseFanio, int fUsePio, int fUseSupp, int fUseCone ); @@ -986,6 +991,7 @@ extern ABC_DLL double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetBufNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetLargeNodeNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetFanoutMax( Abc_Ntk_t * pNtk ); diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c index 94706504..5d0261d7 100644 --- a/src/base/abc/abcFunc.c +++ b/src/base/abc/abcFunc.c @@ -810,7 +810,7 @@ int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; Hop_Man_t * pMan; - int i; + int i, Max; assert( Abc_NtkHasSop(pNtk) ); @@ -819,7 +819,8 @@ int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ) // start the functionality manager pMan = Hop_ManStart(); - Hop_IthVar( pMan, Abc_NtkGetFaninMax(pNtk)-1 ); + Max = Abc_NtkGetFaninMax(pNtk); + if ( Max ) Hop_IthVar( pMan, Max-1 ); // convert each node from SOP to BDD Abc_NtkForEachNode( pNtk, pNode, i ) @@ -979,7 +980,7 @@ Gia_Man_t * Abc_NtkAigToGia( Abc_Ntk_t * p, int fGiaSimple ) Vec_Int_t * vMapping = NULL; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pFanin; - int i, k, nObjs; + int i, k, nObjs, iGiaObj; assert( Abc_NtkIsAigLogic(p) ); pHopMan = (Hop_Man_t *)p->pManFunc; // create new manager @@ -1015,15 +1016,14 @@ Gia_Man_t * Abc_NtkAigToGia( Abc_Ntk_t * p, int fGiaSimple ) { assert( Abc_ObjFaninNum(pNode) <= Hop_ManPiNum(pHopMan) ); Abc_ConvertAigToGia( pNew, pHopObj ); - if ( !Gia_ObjIsAnd(Gia_ManObj(pNew, Abc_Lit2Var(pHopObj->iData))) ) - continue; - if ( vMapping && !Vec_IntEntry(vMapping, Abc_Lit2Var(pHopObj->iData)) ) + iGiaObj = Abc_Lit2Var( pHopObj->iData ); + if ( vMapping && Gia_ObjIsAnd(Gia_ManObj(pNew, iGiaObj)) && !Vec_IntEntry(vMapping, iGiaObj) ) { - Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pHopObj->iData), Vec_IntSize(vMapping) ); + Vec_IntWriteEntry( vMapping, iGiaObj, Vec_IntSize(vMapping) ); Vec_IntPush( vMapping, Abc_ObjFaninNum(pNode) ); Abc_ObjForEachFanin( pNode, pFanin, k ) Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->iTemp) ); - Vec_IntPush( vMapping, Abc_Lit2Var(pHopObj->iData) ); + Vec_IntPush( vMapping, iGiaObj ); } } pNode->iTemp = Abc_LitNotCond( pHopObj->iData, Hop_IsComplement( (Hop_Obj_t *)pNode->pData ) ); diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c index 59993614..f01ef07a 100644 --- a/src/base/abc/abcUtil.c +++ b/src/base/abc/abcUtil.c @@ -429,6 +429,26 @@ int Abc_NtkGetBufNum( Abc_Ntk_t * pNtk ) /**Function************************************************************* + Synopsis [Counts the number of exors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetLargeNodeNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += (Abc_ObjFaninNum(pNode) > 1); + return Counter; +} + +/**Function************************************************************* + Synopsis [Returns 1 if it is an AIG with choice nodes.] Description [] diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 699b5ec1..31f3a275 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -135,6 +135,10 @@ static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandVarMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDetect ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmsStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmsStop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmsPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -232,6 +236,7 @@ static int Abc_CommandFraigRestore ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandFraigClean ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraigSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraigDress ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDumpEquiv ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecStart3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecStop3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -773,6 +778,11 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "extract", Abc_CommandExtract, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "varmin", Abc_CommandVarMin, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "detect", Abc_CommandDetect, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "exact", Abc_CommandExact, 1 ); + + Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_start", Abc_CommandBmsStart, 0 ); + Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_stop", Abc_CommandBmsStop, 0 ); + Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_ps", Abc_CommandBmsPs, 0 ); Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 ); Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 ); @@ -867,6 +877,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Fraiging", "fraig_clean", Abc_CommandFraigClean, 0 ); Cmd_CommandAdd( pAbc, "Fraiging", "fraig_sweep", Abc_CommandFraigSweep, 1 ); Cmd_CommandAdd( pAbc, "Fraiging", "dress", Abc_CommandFraigDress, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "dump_equiv", Abc_CommandDumpEquiv, 0 ); Cmd_CommandAdd( pAbc, "Choicing", "rec_start3", Abc_CommandRecStart3, 0 ); Cmd_CommandAdd( pAbc, "Choicing", "rec_stop3", Abc_CommandRecStop3, 0 ); @@ -1223,6 +1234,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) int fPower; int fGlitch; int fSkipBuf; + int fSkipSmall; int fPrintMem; int c; @@ -1238,9 +1250,10 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) fPower = 0; fGlitch = 0; fSkipBuf = 0; + fSkipSmall = 0; fPrintMem = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmpgsuh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmpgscuh" ) ) != EOF ) { switch ( c ) { @@ -1271,6 +1284,9 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) case 's': fSkipBuf ^= 1; break; + case 'c': + fSkipSmall ^= 1; + break; case 'u': fPrintMem ^= 1; break; @@ -1291,7 +1307,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Cannot print LUT delay for a non-logic network.\n" ); return 1; } - Abc_NtkPrintStats( pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fPrintMem ); + Abc_NtkPrintStats( pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fSkipSmall, fPrintMem ); if ( fPrintTime ) { pAbc->TimeTotal += pAbc->TimeCommand; @@ -1301,7 +1317,7 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: print_stats [-fbdltmpgsuh]\n" ); + Abc_Print( -2, "usage: print_stats [-fbdltmpgscuh]\n" ); Abc_Print( -2, "\t prints the network statistics\n" ); Abc_Print( -2, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" ); Abc_Print( -2, "\t-b : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" ); @@ -1312,6 +1328,7 @@ usage: Abc_Print( -2, "\t-p : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" ); Abc_Print( -2, "\t-g : toggles printing percentage of increased power due to glitching [default = %s]\n", fGlitch? "yes": "no" ); Abc_Print( -2, "\t-s : toggles not counting single-output nodes as nodes [default = %s]\n", fSkipBuf? "yes": "no" ); + Abc_Print( -2, "\t-c : toggles not counting constants and single-output nodes as nodes [default = %s]\n", fSkipSmall? "yes": "no" ); Abc_Print( -2, "\t-u : toggles printing memory usage [default = %s]\n", fPrintMem? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -1393,7 +1410,7 @@ int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv ) } else Abc_Print( 1, "EXDC network statistics: \n" ); - Abc_NtkPrintStats( pNtk->pExdc, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + Abc_NtkPrintStats( pNtk->pExdc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); return 0; usage: @@ -7218,15 +7235,18 @@ usage: ***********************************************************************/ int Abc_CommandDetect( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fVerbose ); + extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose ); Abc_Ntk_t * pNtk; - int c, fVerbose = 0; + int c, fSeq = 0, fVerbose = 0; pNtk = Abc_FrameReadNtk(pAbc); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) { switch ( c ) { + case 's': + fSeq ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -7246,12 +7266,13 @@ int Abc_CommandDetect( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Only applicable to a logic network.\n" ); return 1; } - Abc_NtkDetectClassesTest( pNtk, fVerbose ); + Abc_NtkDetectClassesTest( pNtk, fSeq, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: detect [-vh]\n" ); + Abc_Print( -2, "usage: detect [-svh]\n" ); Abc_Print( -2, "\t detects properties of internal nodes\n" ); + Abc_Print( -2, "\t-s : toggle using sequential circuit information [default = %s]\n", fSeq? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -7268,6 +7289,310 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandExact( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrivalTimes, int fVerbose ); + + int c, nMaxDepth = -1, fMakeAIG = 0, fTest = 0, fVerbose = 0, nVars = 0, nVarsTmp, nFunc = 0; + word pTruth[64]; + Abc_Ntk_t * pNtkRes; + Gia_Man_t * pGiaRes; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Datvh" ) ) != EOF ) + { + switch ( c ) + { + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + nMaxDepth = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxDepth < 0 ) + goto usage; + break; + case 'a': + fMakeAIG ^= 1; + break; + case 't': + fTest ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( fTest ) + { + extern void Abc_ExactTest( int fVerbose ); + extern void Abc_ExactStoreTest( int fVerbose ); + + printf( "run test suite, ignore all other settings\n" ); + Abc_ExactTest( fVerbose ); + Abc_ExactStoreTest( fVerbose ); + return 0; + } + + if ( argc == globalUtilOptind ) + goto usage; + + memset( pTruth, 0, 64 ); + while ( globalUtilOptind < argc ) + { + if ( nFunc == 16 ) + { + Abc_Print( -1, "Too many functions (at most 16 supported).\n" ); + goto usage; + } + nVarsTmp = Abc_TtReadHex( &pTruth[nFunc << 2], argv[globalUtilOptind++] ); + nFunc++; + if ( nVars == 0 ) + nVars = nVarsTmp; + else if ( nVars > 8 ) + { + Abc_Print( -1, "Only 8-variable functions are supported.\n" ); + goto usage; + } + else if ( nVars != nVarsTmp ) + { + Abc_Print( -1, "All functions need to have the same size.\n" ); + goto usage; + } + } + + if ( fMakeAIG ) + { + pGiaRes = Gia_ManFindExact( pTruth, nVars, nFunc, nMaxDepth, NULL, fVerbose ); + if ( pGiaRes ) + Abc_FrameUpdateGia( pAbc, pGiaRes ); + else + Abc_Print( 0, "Could not find AIG within given resource constraints.\n" ); + } + else + { + pNtkRes = Abc_NtkFindExact( pTruth, nVars, nFunc, nMaxDepth, NULL, fVerbose ); + if ( pNtkRes ) + { + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + Abc_FrameClearVerifStatus( pAbc ); + } + else + Abc_Print( 0, "Could not find network within given resource constraints.\n" ); + } + return 0; + +usage: + Abc_Print( -2, "usage: exact [-D <num>] [-atvh] <truth1> <truth2> ...\n" ); + Abc_Print( -2, "\t finds optimum networks using SAT-based exact synthesis for hex truth tables <truth1> <truth2> ...\n" ); + Abc_Print( -2, "\t-D <num> : constrain maximum depth (if too low, algorithm may not terminate)\n" ); + Abc_Print( -2, "\t-a : toggle create AIG [default = %s]\n", fMakeAIG ? "yes" : "no" ); + Abc_Print( -2, "\t-t : run test suite\n" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); + Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBmsStart( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Abc_ExactIsRunning(); + extern void Abc_ExactStart( int nBTLimit, int fMakeAIG, int fVerbose, const char *pFilename ); + + int c, fMakeAIG = 0, fVerbose = 0, nBTLimit = 10000; + char * pFilename = NULL; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Cavh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'a': + fMakeAIG ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc > globalUtilOptind ) + { + pFilename = argv[globalUtilOptind++]; + } + + if ( Abc_ExactIsRunning() ) + { + Abc_Print( -1, "BMS manager is already started." ); + return 1; + } + + Abc_ExactStart( nBTLimit, fMakeAIG, fVerbose, pFilename ); + return 0; + +usage: + Abc_Print( -2, "usage: bms_start [-C <num>] [-avh] [<file>]\n" ); + Abc_Print( -2, "\t starts BMS manager for recording optimum networks\n" ); + Abc_Print( -2, "\t if <file> is specified, store entries are read from that file\n" ); + Abc_Print( -2, "\t-C <num> : the limit on the number of conflicts [default = %d]\n", nBTLimit ); + Abc_Print( -2, "\t-a : toggle create AIG [default = %s]\n", fMakeAIG ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); + Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBmsStop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Abc_ExactIsRunning(); + extern void Abc_ExactStop( const char *pFilename ); + + int c; + char * pFilename = NULL; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc > globalUtilOptind ) + { + pFilename = argv[globalUtilOptind++]; + } + + if ( !Abc_ExactIsRunning() ) + { + Abc_Print( -1, "BMS manager is not started." ); + return 1; + } + + Abc_ExactStop( pFilename ); + return 0; + +usage: + Abc_Print( -2, "usage: bms_stop [-C <num>] [-vh] [<file>]\n" ); + Abc_Print( -2, "\t stops BMS manager for recording optimum networks\n" ); + Abc_Print( -2, "\t if <file> is specified, store entries are written to that file\n" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); + Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBmsPs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Abc_ExactIsRunning(); + extern void Abc_ExactStats(); + + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( !Abc_ExactIsRunning() ) + { + Abc_Print( -1, "BMS manager is not started." ); + return 1; + } + + Abc_ExactStats(); + return 0; + +usage: + Abc_Print( -2, "usage: bms_ps [-h]\n" ); + Abc_Print( -2, "\t shows statistics about BMS manager\n" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); + Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; @@ -14745,6 +15070,93 @@ usage: SeeAlso [] ***********************************************************************/ +int Abc_CommandDumpEquiv( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkDumpEquiv( Abc_Ntk_t * pNtks[2], char * pFileName, int nConfs, int fByName, int fVerbose ); + Abc_Ntk_t * pNtks[2] = {NULL}; + char * pFileName[2], * pFileNameOut; + int c, nConfs = 1000, fByName = 1, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Cnvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfs < 0 ) + goto usage; + break; + case 'n': + fByName ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 3 ) + { + Abc_Print( -1, "Expecting three file names on the command line.\n" ); + goto usage; + } + pFileName[0] = argv[globalUtilOptind]; + pFileName[1] = argv[globalUtilOptind+1]; + pFileNameOut = argv[globalUtilOptind+2]; + for ( c = 0; c < 2; c++ ) + { + pNtks[c] = Io_Read( pFileName[c], Io_ReadFileType(pFileName[c]), 1, 0 ); + if ( pNtks[c] == NULL ) + goto usage; + Abc_NtkToAig( pNtks[c] ); + } +// if ( Abc_NtkCiNum(pNtks[0]) != Abc_NtkCiNum(pNtks[1]) ) +// Abc_Print( -1, "The number of primary inputs of networks \"%s\" and \"%s\" does not match.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]) ); +// else if ( Abc_NtkCoNum(pNtks[0]) != Abc_NtkCoNum(pNtks[1]) ) +// Abc_Print( -1, "The number of primary outputs of networks \"%s\" and \"%s\" does not match.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]) ); +// else + Abc_NtkDumpEquiv( pNtks, pFileNameOut, nConfs, fByName, fVerbose ); + Abc_NtkDelete( pNtks[0] ); + Abc_NtkDelete( pNtks[1] ); + return 0; + +usage: + Abc_Print( -2, "usage: dump_equiv [-C num] [-nvh] <file1.blif> <file2.blif> <file_dump_equiv.txt>\n" ); + Abc_Print( -2, "\t computes equivalence classes of nodes in <file1> and <file2>\n" ); + Abc_Print( -2, "\t By default this procedure performs matching of primary inputs by name.\n" ); + Abc_Print( -2, "\t Those inputs that cannot be matched are treated as free variables.\n" ); + Abc_Print( -2, "\t There is no effort to match primary outputs. Indeed, if two outputs\n" ); + Abc_Print( -2, "\t are equivalent, they will belong to the same equivalence class in the end.\n" ); + Abc_Print( -2, "\t-C num : the maximum number of conflicts at each node [default = %d]\n", nConfs ); + Abc_Print( -2, "\t-n : enable matching of primary inputs by name [default = %s]\n", fByName? "yes": "no" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t<file1> : first network whose nodes are considered\n" ); + Abc_Print( -2, "\t<file2> : second network whose nodes are considered\n" ); + Abc_Print( -2, "\t<file_dump_equiv> : text file with node equivalence classes\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ int Abc_CommandRecStart3( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * FileName, * pTemp; @@ -16277,7 +16689,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) If_ManSetDefaultPars( pPars ); pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyojiktncvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyuojiktncvh" ) ) != EOF ) { switch ( c ) { @@ -16482,6 +16894,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'y': pPars->fUserRecLib ^= 1; break; + case 'u': + pPars->fUserSesLib ^= 1; + break; case 'o': pPars->fUseBuffs ^= 1; break; @@ -16625,7 +17040,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fExpRed = 0; } // modify the subgraph recording - if ( pPars->fUserRecLib ) + if ( pPars->fUserRecLib || pPars->fUserSesLib ) { pPars->fTruth = 1; pPars->fCutMin = 1; @@ -16699,7 +17114,21 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( Abc_NtkRecInputNum3() != pPars->nLutSize ) { - printf( "The number of library inputs (%d) different from the K parameters (%d).\n", Abc_NtkRecInputNum3(), pPars->nLutSize ); + printf( "The number of library inputs (%d) is different from the K parameters (%d).\n", Abc_NtkRecInputNum3(), pPars->nLutSize ); + return 0; + } + } + + if ( pPars->fUserSesLib ) + { + if ( !Abc_ExactIsRunning() ) + { + printf( "BMS manager is not running (use \"bms_start\").\n" ); + return 0; + } + if ( Abc_ExactInputNum() < pPars->nLutSize ) + { + printf( "The number of library inputs (%d) is smaller than the K parameters (%d).\n", Abc_ExactInputNum(), pPars->nLutSize ); return 0; } } @@ -16766,7 +17195,7 @@ usage: sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyojiktncvh]\n" ); + Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -16795,6 +17224,7 @@ usage: Abc_Print( -2, "\t-g : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" ); Abc_Print( -2, "\t-x : toggles delay optimization by DSD balancing [default = %s]\n", pPars->fDsdBalance? "yes": "no" ); Abc_Print( -2, "\t-y : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" ); + Abc_Print( -2, "\t-u : toggles delay optimization with SAT-based library [default = %s]\n", pPars->fUserSesLib? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" ); Abc_Print( -2, "\t-j : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" ); Abc_Print( -2, "\t-i : toggles using cofactoring variables [default = %s]\n", pPars->fUseCofVars? "yes": "no" ); @@ -26955,7 +27385,7 @@ usage: Abc_Print( -2, "\t converts the current network into GIA and moves it to the &-space\n" ); Abc_Print( -2, "\t (if the network is a sequential logic network, normalizes the flops\n" ); Abc_Print( -2, "\t to have const-0 initial values, equivalent to \"undc; st; zero\")\n" ); - Abc_Print( -2, "\t-c : toggles allowing simple GIA to be improved [default = %s]\n", fGiaSimple? "yes": "no" ); + Abc_Print( -2, "\t-c : toggles allowing simple GIA to be imported [default = %s]\n", fGiaSimple? "yes": "no" ); Abc_Print( -2, "\t-m : toggles preserving the current mapping [default = %s]\n", fMapped? "yes": "no" ); Abc_Print( -2, "\t-n : toggles saving CI/CO names of the AIG [default = %s]\n", fNames? "yes": "no" ); Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); @@ -27110,7 +27540,7 @@ usage: SeeAlso [] ***********************************************************************/ -static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int * pnBestLuts, int * pnBestEdges, int * pnBestLevels ) +static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int * pnBestLuts, int * pnBestEdges, int * pnBestLevels, int fArea ) { int nCurLuts, nCurEdges, nCurLevels; Gia_ManLutParams( p, &nCurLuts, &nCurEdges, &nCurLevels ); @@ -27119,8 +27549,9 @@ static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int Gia_ManPoNum(pBest) != Gia_ManPoNum(p) || Gia_ManRegNum(pBest) != Gia_ManRegNum(p) || strcmp(Gia_ManName(pBest), Gia_ManName(p)) || - (*pnBestLevels > nCurLevels) || - (*pnBestLevels == nCurLevels && 2*(*pnBestLuts) + *pnBestEdges > 2*nCurLuts + nCurEdges) ) + (!fArea && (*pnBestLevels > nCurLevels || (*pnBestLevels == nCurLevels && 2*(*pnBestLuts) + *pnBestEdges > 2*nCurLuts + nCurEdges))) || + ( fArea && (*pnBestLuts > nCurLuts || (*pnBestLuts == nCurLuts && *pnBestLevels > nCurLevels))) + ) { *pnBestLuts = nCurLuts; *pnBestEdges = nCurEdges; @@ -27143,12 +27574,15 @@ static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int ***********************************************************************/ int Abc_CommandAbc9Save( Abc_Frame_t * pAbc, int argc, char ** argv ) { - int c; + int c, fArea = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) { switch ( c ) { + case 'a': + fArea ^= 1; + break; case 'h': goto usage; default: @@ -27165,7 +27599,7 @@ int Abc_CommandAbc9Save( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "GIA has no mapping.\n" ); return 1; } - if ( !Gia_ManCompareWithBest( pAbc->pGiaBest, pAbc->pGia, &pAbc->nBestLuts, &pAbc->nBestEdges, &pAbc->nBestLevels ) ) + if ( !Gia_ManCompareWithBest( pAbc->pGiaBest, pAbc->pGia, &pAbc->nBestLuts, &pAbc->nBestEdges, &pAbc->nBestLevels, fArea ) ) return 0; // save the design as best Gia_ManStopP( &pAbc->pGiaBest ); @@ -27173,8 +27607,9 @@ int Abc_CommandAbc9Save( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &save [-h]\n" ); + Abc_Print( -2, "usage: &save [-ah]\n" ); Abc_Print( -2, "\t compares and possibly saves AIG with mapping\n" ); + Abc_Print( -2, "\t-a : toggle using area as the primary metric [default = %s]\n", fArea? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -33363,7 +33798,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) { if ( !Abc_FrameReadFlag("silentmode") ) Abc_Print( -1, "Empty GIA network.\n" ); - return 1; + return 0; } if ( Gia_ManBufNum(pAbc->pGia) ) { @@ -35224,14 +35659,23 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Edg_ManAssignEdgeNew( Gia_Man_t * p, int nEdges, int fVerbose ); extern void Seg_ManComputeDelay( Gia_Man_t * pGia, int Delay, int nFanouts, int fTwo, int fVerbose ); - extern void Sle_ManExplore( Gia_Man_t * pGia, int DelayInit, int fVerbose ); + extern void Sle_ManExplore( Gia_Man_t * pGia, int nBTLimit, int DelayInit, int fDynamic, int fTwoEdges, int fVerbose ); - int c, DelayMax = 0, nFanouts = 0, nEdges = 1, fReverse = 0, fUsePack = 0, fUseOld = 0, fMapping = 0, fVerbose = 0; + int c, nBTLimit = 0, DelayMax = 0, nFanouts = 0, nEdges = 1, fReverse = 0, fUsePack = 0, fUseOld = 0, fMapping = 0, fDynamic = 1, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "DFErpomvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "CDFErpomdvh" ) ) != EOF ) { switch ( c ) { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); + goto usage; + } + nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; case 'D': if ( globalUtilOptind >= argc ) { @@ -35276,6 +35720,9 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fMapping ^= 1; break; + case 'd': + fDynamic ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -35289,16 +35736,16 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Empty GIA network.\n" ); return 1; } + if ( fMapping ) + { + Sle_ManExplore( pAbc->pGia, nBTLimit, DelayMax, fDynamic, nEdges==2, fVerbose ); + return 0; + } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Current AIG has no mapping. Run \"&if\".\n" ); return 1; } - if ( fMapping ) - { - Sle_ManExplore( pAbc->pGia, DelayMax, fVerbose ); - return 0; - } if ( Gia_ManLutSizeMax(pAbc->pGia) > 6 ) { Abc_Print( 0, "Current AIG has mapping into %d-LUTs.\n", Gia_ManLutSizeMax(pAbc->pGia) ); @@ -35333,8 +35780,9 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &edge [-DFE num] [-rpomvh]\n" ); + Abc_Print( -2, "usage: &edge [-CDFE num] [-rpomdvh]\n" ); Abc_Print( -2, "\t find edge assignment of the LUT-mapped network\n" ); + Abc_Print( -2, "\t-C num : the SAT solver conflict limit (0 = unused) [default = %d]\n", nBTLimit ); Abc_Print( -2, "\t-D num : the upper bound on delay [default = %d]\n", DelayMax ); Abc_Print( -2, "\t-F num : skip using edge if fanout higher than this [default = %d]\n", nFanouts ); Abc_Print( -2, "\t-E num : the limit on the number of edges (1 <= num <= 2) [default = %d]\n", nEdges ); @@ -35342,6 +35790,7 @@ usage: Abc_Print( -2, "\t-p : toggles deriving edges from packing [default = %s]\n", fUsePack? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using old algorithm [default = %s]\n", fUseOld? "yes": "no" ); Abc_Print( -2, "\t-m : toggles combining edge assignment with mapping [default = %s]\n", fMapping? "yes": "no" ); + Abc_Print( -2, "\t-d : toggles dynamic addition of clauses [default = %s]\n", fDynamic? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; @@ -35505,6 +35954,8 @@ int Abc_CommandAbc9Unmap( Abc_Frame_t * pAbc, int argc, char ** argv ) Vec_IntFreeP( &pAbc->pGia->vMapping ); Vec_IntFreeP( &pAbc->pGia->vPacking ); Vec_IntFreeP( &pAbc->pGia->vCellMapping ); + Vec_IntFreeP( &pAbc->pGia->vEdge1 ); + Vec_IntFreeP( &pAbc->pGia->vEdge2 ); return 0; usage: @@ -39675,7 +40126,7 @@ usage: int Abc_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv ) { Vec_Int_t * vOrder = NULL; - int c, fSimple = 0, fSigned = 0, fVerbose = 0, fVeryVerbose = 0; + int c, fSimple = 1, fSigned = 0, fVerbose = 0, fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "asvwh" ) ) != EOF ) { diff --git a/src/base/abci/abcDetect.c b/src/base/abci/abcDetect.c index 8fa395e8..c87169b5 100644 --- a/src/base/abci/abcDetect.c +++ b/src/base/abci/abcDetect.c @@ -193,7 +193,7 @@ finish: SeeAlso [] ***********************************************************************/ -void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fVerbose ) +void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose ) { printf( "This procedure is currently not used.\n" ); } diff --git a/src/base/abci/abcDress3.c b/src/base/abci/abcDress3.c new file mode 100644 index 00000000..33545f0a --- /dev/null +++ b/src/base/abci/abcDress3.c @@ -0,0 +1,344 @@ +/**CFile**************************************************************** + + FileName [abcDress3.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Transfers names from one netlist to the other.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDress3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "base/abc/abc.h" +#include "base/io/ioAbc.h" +#include "proof/cec/cec.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Compute equivalence classes of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkComputeGiaEquivs( Gia_Man_t * pGia, int nConfs, int fVerbose ) +{ + Gia_Man_t * pTemp; + Cec_ParFra_t ParsFra, * pPars = &ParsFra; + Cec_ManFraSetDefaultParams( pPars ); + pPars->fUseOrigIds = 1; + pPars->fSatSweeping = 1; + pPars->nBTLimit = nConfs; + pPars->fVerbose = fVerbose; + pTemp = Cec_ManSatSweeping( pGia, pPars, 0 ); + Gia_ManStop( pTemp ); + pTemp = Gia_ManOrigIdsReduce( pGia, pGia->vIdsEquiv ); + Gia_ManStop( pTemp ); +} + +/**Function************************************************************* + + Synopsis [Converts AIG from HOP to GIA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertHopToGia_rec1( Gia_Man_t * p, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertHopToGia_rec1( p, Hop_ObjFanin0(pObj) ); + Abc_ConvertHopToGia_rec1( p, Hop_ObjFanin1(pObj) ); + pObj->iData = Gia_ManHashAnd( p, Hop_ObjChild0CopyI(pObj), Hop_ObjChild1CopyI(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} +void Abc_ConvertHopToGia_rec2( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertHopToGia_rec2( Hop_ObjFanin0(pObj) ); + Abc_ConvertHopToGia_rec2( Hop_ObjFanin1(pObj) ); + assert( Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjClearMarkA( pObj ); +} +int Abc_ConvertHopToGia( Gia_Man_t * p, Hop_Obj_t * pRoot ) +{ + assert( !Hop_IsComplement(pRoot) ); + if ( Hop_ObjIsConst1( pRoot ) ) + return 1; + Abc_ConvertHopToGia_rec1( p, pRoot ); + Abc_ConvertHopToGia_rec2( pRoot ); + return pRoot->iData; +} + +/**Function************************************************************* + + Synopsis [Add logic from pNtk to the AIG manager p.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAigToGiaOne( Gia_Man_t * p, Abc_Ntk_t * pNtk, Vec_Int_t * vMap ) +{ + Hop_Man_t * pHopMan; + Hop_Obj_t * pHopObj; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanin; + int i, k; + assert( Abc_NtkIsAigLogic(pNtk) ); + pHopMan = (Hop_Man_t *)pNtk->pManFunc; + Hop_ManConst1(pHopMan)->iData = 1; + // image primary inputs + Abc_NtkCleanCopy( pNtk ); + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->iTemp = Gia_ManCiLit(p, Vec_IntEntry(vMap, i)); + // iterate through nodes used in the mapping + vNodes = Abc_NtkDfs( pNtk, 1 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) + { + Abc_ObjForEachFanin( pNode, pFanin, k ) + Hop_ManPi(pHopMan, k)->iData = pFanin->iTemp; + pHopObj = Hop_Regular( (Hop_Obj_t *)pNode->pData ); + assert( Abc_ObjFaninNum(pNode) <= Hop_ManPiNum(pHopMan) ); + if ( Hop_DagSize(pHopObj) > 0 ) + Abc_ConvertHopToGia( p, pHopObj ); + pNode->iTemp = Abc_LitNotCond( pHopObj->iData, Hop_IsComplement( (Hop_Obj_t *)pNode->pData ) ); + } + Vec_PtrFree( vNodes ); + // create primary outputs + Abc_NtkForEachCo( pNtk, pNode, i ) + Gia_ManAppendCo( p, Abc_ObjFanin0(pNode)->iTemp ); +} +Gia_Man_t * Abc_NtkAigToGiaTwo( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fByName ) +{ + Gia_Man_t * p; + Gia_Obj_t * pObj; + Abc_Obj_t * pNode; + Vec_Int_t * vMap1, * vMap2; + int i, Index = 0; + assert( Abc_NtkIsAigLogic(pNtk1) ); + assert( Abc_NtkIsAigLogic(pNtk2) ); + // find common variables + if ( fByName ) + { + int nCommon = 0; + vMap1 = Vec_IntStartNatural( Abc_NtkCiNum(pNtk1) ); + vMap2 = Vec_IntAlloc( Abc_NtkCiNum(pNtk2) ); + Abc_NtkForEachCi( pNtk1, pNode, i ) + pNode->iTemp = Index++; + assert( Index == Abc_NtkCiNum(pNtk1) ); + Abc_NtkForEachCi( pNtk2, pNode, i ) + { + int Num = Nm_ManFindIdByName( pNtk1->pManName, Abc_ObjName(pNode), ABC_OBJ_PI ); + if ( Num < 0 ) + Num = Nm_ManFindIdByName( pNtk1->pManName, Abc_ObjName(pNode), ABC_OBJ_BO ); + assert( Num < 0 || Abc_ObjIsCi(Abc_NtkObj(pNtk1, Num)) ); + if ( Num >= 0 ) + Vec_IntPush( vMap2, Abc_NtkObj(pNtk1, Num)->iTemp ), nCommon++; + else + Vec_IntPush( vMap2, Index++ ); + } + // report + printf( "Matched %d vars by name.", nCommon ); + if ( nCommon != Abc_NtkCiNum(pNtk1) ) + printf( " Netlist1 has %d unmatched vars.", Abc_NtkCiNum(pNtk1) - nCommon ); + if ( nCommon != Abc_NtkCiNum(pNtk2) ) + printf( " Netlist2 has %d unmatched vars.", Abc_NtkCiNum(pNtk2) - nCommon ); + printf( "\n" ); + } + else + { + vMap1 = Vec_IntStartNatural( Abc_NtkCiNum(pNtk1) ); + vMap2 = Vec_IntStartNatural( Abc_NtkCiNum(pNtk2) ); + Index = Abc_MaxInt( Vec_IntSize(vMap1), Vec_IntSize(vMap2) ); + // report + printf( "Matched %d vars by order.", Abc_MinInt(Abc_NtkCiNum(pNtk1), Abc_NtkCiNum(pNtk2)) ); + if ( Abc_NtkCiNum(pNtk1) < Abc_NtkCiNum(pNtk2) ) + printf( " The last %d vars of Netlist2 are unmatched vars.", Abc_NtkCiNum(pNtk2) - Abc_NtkCiNum(pNtk1) ); + if ( Abc_NtkCiNum(pNtk1) > Abc_NtkCiNum(pNtk2) ) + printf( " The last %d vars of Netlist1 are unmatched vars.", Abc_NtkCiNum(pNtk1) - Abc_NtkCiNum(pNtk2) ); + printf( "\n" ); + } + // create new manager + p = Gia_ManStart( 10000 ); + p->pName = Abc_UtilStrsav( Abc_NtkName(pNtk1) ); + p->pSpec = Abc_UtilStrsav( Abc_NtkSpec(pNtk1) ); + for ( i = 0; i < Index; i++ ) + Gia_ManAppendCi(p); + // add logic + Gia_ManHashAlloc( p ); + Abc_NtkAigToGiaOne( p, pNtk1, vMap1 ); + Abc_NtkAigToGiaOne( p, pNtk2, vMap2 ); + Gia_ManHashStop( p ); + Vec_IntFree( vMap1 ); + Vec_IntFree( vMap2 ); + // add extra POs to dangling nodes + Gia_ManCreateValueRefs( p ); + Gia_ManForEachAnd( p, pObj, i ) + if ( pObj->Value == 0 ) + Gia_ManAppendCo( p, Abc_Var2Lit(i, 0) ); + return p; +} + +/**Function************************************************************* + + Synopsis [Collect equivalence class information.] + + Description [Each class is represented as follows: + <num_entries><entry1><entry2>...<entryN> + where <entry> is nodeId with 1-bit for complement and 1-bit for network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_NtkCollectAddOne( int iNtk, int iObj, int iGiaLit, Gia_Man_t * pGia, Vec_Int_t * vGia2Cla, Vec_Int_t * vNexts[2] ) +{ + int iRepr = Gia_ObjReprSelf( pGia, Abc_Lit2Var(iGiaLit) ); + int Compl = Abc_LitIsCompl(iGiaLit) ^ Gia_ObjPhase(Gia_ManObj(pGia, iRepr)) ^ Gia_ObjPhase(Gia_ManObj(pGia, Abc_Lit2Var(iGiaLit))); + int Added = Abc_Var2Lit( Abc_Var2Lit(iObj, Compl), iNtk ); + int Entry = Vec_IntEntry( vGia2Cla, iRepr ); + Vec_IntWriteEntry( vNexts[iNtk], iObj, Entry ); + Vec_IntWriteEntry( vGia2Cla, iRepr, Added ); +} +Vec_Int_t * Abc_NtkCollectEquivClasses( Abc_Ntk_t * pNtks[2], Gia_Man_t * pGia ) +{ + Vec_Int_t * vClass = Vec_IntAlloc( 100 ); + Vec_Int_t * vClasses = Vec_IntAlloc( 1000 ); + Vec_Int_t * vGia2Cla = Vec_IntStartFull( Gia_ManObjNum(pGia) ); // mapping objId into classId + Vec_Int_t * vNexts[2] = { Vec_IntStartFull(Abc_NtkObjNumMax(pNtks[0])), Vec_IntStartFull(Abc_NtkObjNumMax(pNtks[1])) }; + Abc_Obj_t * pObj; + int n, i, k, Entry, fCompl; + Abc_NtkForEachCi( pNtks[0], pObj, i ) + Abc_NtkCollectAddOne( 0, Abc_ObjId(pObj), pObj->iTemp, pGia, vGia2Cla, vNexts ); + for ( n = 0; n < 2; n++ ) + Abc_NtkForEachNode( pNtks[n], pObj, i ) + Abc_NtkCollectAddOne( n, Abc_ObjId(pObj), pObj->iTemp, pGia, vGia2Cla, vNexts ); + Vec_IntForEachEntry( vGia2Cla, Entry, i ) + { + Vec_IntClear( vClass ); + for ( ; Entry >= 0; Entry = Vec_IntEntry(vNexts[Entry&1], Entry>>2) ) + Vec_IntPush( vClass, Entry ); + if ( Vec_IntSize(vClass) < 2 ) + continue; + Vec_IntReverseOrder( vClass ); + fCompl = 2 & Vec_IntEntry( vClass, 0 ); + Vec_IntForEachEntry( vClass, Entry, k ) + Vec_IntWriteEntry( vClass, k, Entry ^ fCompl ); + Vec_IntPush( vClasses, Vec_IntSize(vClass) ); + Vec_IntAppend( vClasses, vClass ); + } + Vec_IntFree( vGia2Cla ); + Vec_IntFree( vNexts[0] ); + Vec_IntFree( vNexts[1] ); + Vec_IntFree( vClass ); + return vClasses; +} + +/**Function************************************************************* + + Synopsis [Write the output file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDumpEquivFile( char * pFileName, Vec_Int_t * vClasses, Abc_Ntk_t * pNtks[2] ) +{ + int i, c, k, Entry; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) { printf( "Cannot open file %s for writing.\n", pFileName ); return; } + fprintf( pFile, "# Node equivalences computed by ABC for networks \"%s\" and \"%s\" on %s\n\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]), Extra_TimeStamp() ); + for ( i = c = 0; i < Vec_IntSize(vClasses); c++, i += 1 + Vec_IntEntry(vClasses, i) ) + { + Vec_IntForEachEntryStartStop( vClasses, Entry, k, i + 1, i + 1 + Vec_IntEntry(vClasses, i) ) + { + Abc_Ntk_t * pNtk = pNtks[Entry & 1]; + char * pObjName = Abc_ObjName( Abc_NtkObj(pNtk, Entry>>2) ); + fprintf( pFile, "%d:%s:%s%s\n", c+1, Abc_NtkName(pNtk), (Entry&2) ? "NOT:":"", pObjName ); + } + fprintf( pFile, "\n" ); + } + fclose( pFile ); +} + + +/**Function************************************************************* + + Synopsis [Compute and dump equivalent name classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDumpEquiv( Abc_Ntk_t * pNtks[2], char * pFileName, int nConfs, int fByName, int fVerbose ) +{ + //abctime clk = Abc_Clock(); + Vec_Int_t * vClasses; + // derive shared AIG for the two networks + Gia_Man_t * pGia = Abc_NtkAigToGiaTwo( pNtks[0], pNtks[1], fByName ); + if ( fVerbose ) + printf( "Computing equivalences for networks \"%s\" and \"%s\" with conflict limit %d.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]), nConfs ); + // compute equivalences in this AIG + Abc_NtkComputeGiaEquivs( pGia, nConfs, fVerbose ); + //if ( fVerbose ) + // Abc_PrintTime( 1, "Equivalence computation time", Abc_Clock() - clk ); + if ( fVerbose ) + Gia_ManPrintStats( pGia, NULL ); + // collect equivalence class information + vClasses = Abc_NtkCollectEquivClasses( pNtks, pGia ); + Gia_ManStop( pGia ); + // dump information into the output file + Abc_NtkDumpEquivFile( pFileName, vClasses, pNtks ); + Vec_IntFree( vClasses ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/abci/abcExact.c b/src/base/abci/abcExact.c new file mode 100644 index 00000000..8c508b63 --- /dev/null +++ b/src/base/abci/abcExact.c @@ -0,0 +1,1696 @@ +/**CFile**************************************************************** + + FileName [abcExact.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Find minimum size networks with a SAT solver.] + + Author [Mathias Soeken] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - July 15, 2016.] + + Revision [$Id: abcFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +/* This implementation is based on Exercises 477 and 478 in + * Donald E. Knuth TAOCP Fascicle 6 (Satisfiability) Section 7.2.2.2 + */ + +#include "base/abc/abc.h" + +#include "aig/gia/gia.h" +#include "bool/kit/kit.h" +#include "misc/util/utilTruth.h" +#include "misc/vec/vecInt.h" +#include "misc/vec/vecPtr.h" +#include "proof/cec/cec.h" +#include "sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static word s_Truths8[32] = { + ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0xFFFFFFFF00000000), + ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), + ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0xFFFFFFFFFFFFFFFF) +}; + +#define ABC_EXACT_SOL_NVARS 0 +#define ABC_EXACT_SOL_NFUNC 1 +#define ABC_EXACT_SOL_NGATES 2 + +typedef struct Ses_Man_t_ Ses_Man_t; +struct Ses_Man_t_ +{ + sat_solver * pSat; /* SAT solver */ + + word * pSpec; /* specification */ + int bSpecInv; /* remembers whether spec was inverted for normalization */ + int nSpecVars; /* number of variables in specification */ + int nSpecFunc; /* number of functions to synthesize */ + int nRows; /* number of rows in the specification (without 0) */ + int nMaxDepth; /* maximum depth (-1 if depth is not constrained) */ + int * pArrTimeProfile; /* arrival times of inputs (NULL if arrival times are ignored) */ + int nArrTimeDelta; /* delta to the original arrival times (arrival times are normalized to have 0 as minimum element) */ + int nArrTimeMax; /* maximum normalized arrival time */ + int nBTLimit; /* conflict limit */ + int fMakeAIG; /* create AIG instead of general network */ + int fVerbose; /* be verbose */ + int fVeryVerbose; /* be very verbose */ + + int nGates; /* number of gates */ + + int nSimVars; /* number of simulation vars x(i, t) */ + int nOutputVars; /* number of output variables g(h, i) */ + int nGateVars; /* number of gate variables f(i, p, q) */ + int nSelectVars; /* number of select variables s(i, j, k) */ + int nDepthVars; /* number of depth variables d(i, j) */ + + int nOutputOffset; /* offset where output variables start */ + int nGateOffset; /* offset where gate variables start */ + int nSelectOffset; /* offset where select variables start */ + int nDepthOffset; /* offset where depth variables start */ + + abctime timeSat; /* SAT runtime */ + abctime timeSatSat; /* SAT runtime (sat instance) */ + abctime timeSatUnsat; /* SAT runtime (unsat instance) */ + abctime timeTotal; /* all runtime */ +}; + +/*********************************************************************** + + Synopsis [Store truth tables based on normalized arrival times.] + +***********************************************************************/ + +// The hash table is a list of pointers to Ses_TruthEntry_t elements, which +// are arranged in a linked list, each of which pointing to a linked list +// of Ses_TimesEntry_t elements which contain the char* representation of the +// optimum netlist according to then normalized arrival times: + +typedef struct Ses_TimesEntry_t_ Ses_TimesEntry_t; +struct Ses_TimesEntry_t_ +{ + int pArrTimeProfile[8]; /* normalized arrival time profile */ + Ses_TimesEntry_t * next; /* linked list pointer */ + char * pNetwork; /* pointer to char array representation of optimum network */ +}; + +typedef struct Ses_TruthEntry_t_ Ses_TruthEntry_t; +struct Ses_TruthEntry_t_ +{ + word pTruth[4]; /* truth table for comparison */ + int nVars; /* number of variables */ + Ses_TruthEntry_t * next; /* linked list pointer */ + Ses_TimesEntry_t * head; /* pointer to head of sub list with arrival times */ +}; + +#define SES_STORE_TABLE_SIZE 1024 +typedef struct Ses_Store_t_ Ses_Store_t; +struct Ses_Store_t_ +{ + int fMakeAIG; /* create AIG instead of general network */ + int fVerbose; /* be verbose */ + int nBTLimit; /* conflict limit */ + int nEntriesCount; /* number of entries */ + Ses_TruthEntry_t * pEntries[SES_STORE_TABLE_SIZE]; /* hash table for truth table entries */ + + unsigned long nCutCount; + unsigned long pCutCount[9]; + unsigned long nCacheHit; +}; + +static Ses_Store_t * s_pSesStore = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NormalizeArrivalTimes( int * pArrTimeProfile, int nVars, int * maxNormalized ) +{ + int * p = pArrTimeProfile, * pEnd = pArrTimeProfile + nVars; + int delta = *p; + + while ( ++p < pEnd ) + if ( *p < delta ) + delta = *p; + + *maxNormalized = 0; + p = pArrTimeProfile; + while ( p < pEnd ) + { + *p -= delta; + if ( *p > *maxNormalized ) + *maxNormalized = *p; + ++p; + } + + *maxNormalized += 1; + + return delta; +} + +static inline Ses_Store_t * Ses_StoreAlloc( int nBTLimit, int fMakeAIG, int fVerbose ) +{ + Ses_Store_t * pStore = ABC_CALLOC( Ses_Store_t, 1 ); + pStore->fMakeAIG = fMakeAIG; + pStore->fVerbose = fVerbose; + pStore->nBTLimit = nBTLimit; + pStore->nEntriesCount = 0; + memset( pStore->pEntries, 0, SES_STORE_TABLE_SIZE ); + + pStore->nCutCount = 0; + memset( pStore->pCutCount, 0, 9 ); + pStore->nCacheHit = 0; + + return pStore; +} + +static inline void Ses_StoreClean( Ses_Store_t * pStore ) +{ + int i; + Ses_TruthEntry_t * pTEntry, * pTEntry2; + Ses_TimesEntry_t * pTiEntry, * pTiEntry2; + + for ( i = 0; i < SES_STORE_TABLE_SIZE; ++i ) + if ( pStore->pEntries[i] ) + { + pTEntry = pStore->pEntries[i]; + + while ( pTEntry ) + { + pTiEntry = pTEntry->head; + while ( pTiEntry ) + { + ABC_FREE( pTiEntry->pNetwork ); + pTiEntry2 = pTiEntry; + pTiEntry = pTiEntry->next; + ABC_FREE( pTiEntry2 ); + } + pTEntry2 = pTEntry; + pTEntry = pTEntry->next; + ABC_FREE( pTEntry2 ); + } + } + + ABC_FREE( pStore ); +} + +static inline int Ses_StoreTableHash( word * pTruth, int nVars ) +{ + static int s_Primes[4] = { 1291, 1699, 1999, 2357 }; + int i; + unsigned uHash = 0; + for ( i = 0; i < Kit_TruthWordNum( nVars ); ++i ) + uHash ^= pTruth[i] * s_Primes[i & 0xf]; + return (int)(uHash % SES_STORE_TABLE_SIZE ); +} + +static inline int Ses_StoreTruthEqual( Ses_TruthEntry_t * pEntry, word * pTruth, int nVars ) +{ + int i; + + if ( pEntry->nVars != nVars ) + return 0; + + for ( i = 0; i < Kit_TruthWordNum( nVars ); ++i ) + if ( pEntry->pTruth[i] != pTruth[i] ) + return 0; + return 1; +} + +static inline void Ses_StoreTruthCopy( Ses_TruthEntry_t * pEntry, word * pTruthSrc, int nVars ) +{ + int i; + pEntry->nVars = nVars; + for ( i = 0; i < Kit_TruthWordNum( nVars ); ++i ) + pEntry->pTruth[i] = pTruthSrc[i]; +} + +static inline int Ses_StoreTimesEqual( int * pTimes1, int * pTimes2, int nVars ) +{ + int i; + for ( i = 0; i < nVars; ++i ) + if ( pTimes1[i] != pTimes2[i] ) + return 0; + return 1; +} + +static inline void Ses_StoreTimesCopy( int * pTimesDest, int * pTimesSrc, int nVars ) +{ + int i; + for ( i = 0; i < nVars; ++i ) + pTimesDest[i] = pTimesSrc[i]; +} + +// pArrTimeProfile is not normalized +// returns 1 if and only if a new TimesEntry has been created +int Ses_StoreAddEntry( Ses_Store_t * pStore, word * pTruth, int nVars, int * pArrTimeProfile, char * pSol ) +{ + int i, nDelta, maxNormalized, key, fAdded; + Ses_TruthEntry_t * pTEntry; + Ses_TimesEntry_t * pTiEntry; + + nDelta = Abc_NormalizeArrivalTimes( pArrTimeProfile, nVars, &maxNormalized ); + + key = Ses_StoreTableHash( pTruth, nVars ); + pTEntry = pStore->pEntries[key]; + + /* does truth table already exist? */ + while ( pTEntry ) + { + if ( Ses_StoreTruthEqual( pTEntry, pTruth, nVars ) ) + break; + else + pTEntry = pTEntry->next; + } + + /* entry does not yet exist, so create new one and enqueue */ + if ( !pTEntry ) + { + pTEntry = ABC_CALLOC( Ses_TruthEntry_t, 1 ); + Ses_StoreTruthCopy( pTEntry, pTruth, nVars ); + pTEntry->next = pStore->pEntries[key]; + pStore->pEntries[key] = pTEntry; + } + + /* does arrival time already exist? */ + pTiEntry = pTEntry->head; + while ( pTiEntry ) + { + if ( Ses_StoreTimesEqual( pArrTimeProfile, pTiEntry->pArrTimeProfile, nVars ) ) + break; + else + pTiEntry = pTiEntry->next; + } + + /* entry does not yet exist, so create new one and enqueue */ + if ( !pTiEntry ) + { + pTiEntry = ABC_CALLOC( Ses_TimesEntry_t, 1 ); + Ses_StoreTimesCopy( pTiEntry->pArrTimeProfile, pArrTimeProfile, nVars ); + pTiEntry->pNetwork = pSol; + pTiEntry->next = pTEntry->head; + pTEntry->head = pTiEntry; + + /* item has been added */ + fAdded = 1; + pStore->nEntriesCount++; + } + else + /* item was already present */ + fAdded = 0; + + for ( i = 0; i < nVars; ++i ) + pArrTimeProfile[i] += nDelta; + return fAdded; +} + +// pArrTimeProfile is not normalized +// returns 0 if no solution was found +char * Ses_StoreGetEntry( Ses_Store_t * pStore, word * pTruth, int nVars, int * pArrTimeProfile ) +{ + int i, nDelta, maxNormalized, key; + Ses_TruthEntry_t * pTEntry; + Ses_TimesEntry_t * pTiEntry; + + key = Ses_StoreTableHash( pTruth, nVars ); + pTEntry = pStore->pEntries[key]; + + /* find truth table entry */ + while ( pTEntry ) + { + if ( Ses_StoreTruthEqual( pTEntry, pTruth, nVars ) ) + break; + else + pTEntry = pTEntry->next; + } + + /* no entry found? */ + if ( !pTEntry ) + return 0; + + nDelta = Abc_NormalizeArrivalTimes( pArrTimeProfile, nVars, &maxNormalized ); + + /* find times entry */ + pTiEntry = pTEntry->head; + while ( pTiEntry ) + { + if ( Ses_StoreTimesEqual( pArrTimeProfile, pTiEntry->pArrTimeProfile, nVars ) ) + break; + else + pTiEntry = pTiEntry->next; + } + + for ( i = 0; i < nVars; ++i ) + pArrTimeProfile[i] += nDelta; + + /* no entry found? */ + if ( !pTiEntry ) + return 0; + + return pTiEntry->pNetwork; +} + +static void Ses_StoreWrite( Ses_Store_t * pStore, const char * pFilename ) +{ + int i; + Ses_TruthEntry_t * pTEntry; + Ses_TimesEntry_t * pTiEntry; + FILE * pFile; + + pFile = fopen( pFilename, "wb" ); + if (pFile == NULL) + { + printf( "cannot open file \"%s\" for writing\n", pFilename ); + return; + } + + fwrite( &pStore->nEntriesCount, sizeof( int ), 1, pFile ); + + for ( i = 0; i < SES_STORE_TABLE_SIZE; ++i ) + if ( pStore->pEntries[i] ) + { + pTEntry = pStore->pEntries[i]; + + while ( pTEntry ) + { + pTiEntry = pTEntry->head; + while ( pTiEntry ) + { + fwrite( pTEntry->pTruth, sizeof( word ), 4, pFile ); + fwrite( &pTEntry->nVars, sizeof( int ), 1, pFile ); + fwrite( pTiEntry->pArrTimeProfile, sizeof( int ), 8, pFile ); + fwrite( pTiEntry->pNetwork, sizeof( char ), 3 + 4 * pTiEntry->pNetwork[ABC_EXACT_SOL_NGATES] + 2 + pTiEntry->pNetwork[ABC_EXACT_SOL_NVARS], pFile ); + pTiEntry = pTiEntry->next; + } + pTEntry = pTEntry->next; + } + } + + + fclose( pFile ); +} + +static void Ses_StoreRead( Ses_Store_t * pStore, const char * pFilename ) +{ + int i, nEntries; + word pTruth[4]; + int nVars; + int pArrTimeProfile[8]; + char pHeader[3]; + char * pNetwork; + FILE * pFile; + int value; + + pFile = fopen( pFilename, "rb" ); + if (pFile == NULL) + { + printf( "cannot open file \"%s\" for reading\n", pFilename ); + return; + } + + value = fread( &nEntries, sizeof( int ), 1, pFile ); + + for ( i = 0; i < nEntries; ++i ) + { + value = fread( pTruth, sizeof( word ), 4, pFile ); + value = fread( &nVars, sizeof( int ), 1, pFile ); + value = fread( pArrTimeProfile, sizeof( int ), 8, pFile ); + value = fread( pHeader, sizeof( char ), 3, pFile ); + + pNetwork = ABC_CALLOC( char, 3 + 4 * pHeader[ABC_EXACT_SOL_NGATES] + 2 + pHeader[ABC_EXACT_SOL_NVARS] ); + pNetwork[0] = pHeader[0]; + pNetwork[1] = pHeader[1]; + pNetwork[2] = pHeader[2]; + + value = fread( pNetwork + 3, sizeof( char ), 4 * pHeader[ABC_EXACT_SOL_NGATES] + 2 + pHeader[ABC_EXACT_SOL_NVARS], pFile ); + + Ses_StoreAddEntry( pStore, pTruth, nVars, pArrTimeProfile, pNetwork ); + } + + fclose( pFile ); +} + +static inline Ses_Man_t * Ses_ManAlloc( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrTimeProfile, int fMakeAIG, int fVerbose ) +{ + int h, i; + + Ses_Man_t * p = ABC_CALLOC( Ses_Man_t, 1 ); + p->pSat = NULL; + p->bSpecInv = 0; + for ( h = 0; h < nFunc; ++h ) + if ( pTruth[h << 2] & 1 ) + { + for ( i = 0; i < 4; ++i ) + pTruth[(h << 2) + i] = ~pTruth[(h << 2) + i]; + p->bSpecInv |= ( 1 << h ); + } + p->pSpec = pTruth; + p->nSpecVars = nVars; + p->nSpecFunc = nFunc; + p->nRows = ( 1 << nVars ) - 1; + p->nMaxDepth = nMaxDepth; + p->pArrTimeProfile = nMaxDepth >= 0 ? pArrTimeProfile : NULL; + if ( p->pArrTimeProfile ) + p->nArrTimeDelta = Abc_NormalizeArrivalTimes( p->pArrTimeProfile, nVars, &p->nArrTimeMax ); + else + p->nArrTimeDelta = p->nArrTimeMax = 0; + p->fMakeAIG = fMakeAIG; + p->nBTLimit = nMaxDepth >= 0 ? 50000 : 0; + p->fVerbose = fVerbose; + p->fVeryVerbose = 0; + + return p; +} + +static inline void Ses_ManClean( Ses_Man_t * pSes ) +{ + int h, i; + for ( h = 0; h < pSes->nSpecFunc; ++h ) + if ( ( pSes->bSpecInv >> h ) & 1 ) + for ( i = 0; i < 4; ++i ) + pSes->pSpec[(h << 2) + i] = ~( pSes->pSpec[(h << 2) + i] ); + + if ( pSes->pArrTimeProfile ) + for ( i = 0; i < pSes->nSpecVars; ++i ) + pSes->pArrTimeProfile[i] += pSes->nArrTimeDelta; + + if ( pSes->pSat ) + sat_solver_delete( pSes->pSat ); + + ABC_FREE( pSes ); +} + +/**Function************************************************************* + + Synopsis [Access variables based on indexes.] + +***********************************************************************/ +static inline int Ses_ManSimVar( Ses_Man_t * pSes, int i, int t ) +{ + assert( i < pSes->nGates ); + assert( t < pSes->nRows ); + + return pSes->nRows * i + t; +} + +static inline int Ses_ManOutputVar( Ses_Man_t * pSes, int h, int i ) +{ + assert( h < pSes->nSpecFunc ); + assert( i < pSes->nGates ); + + return pSes->nOutputOffset + pSes->nGates * h + i; +} + +static inline int Ses_ManGateVar( Ses_Man_t * pSes, int i, int p, int q ) +{ + assert( i < pSes->nGates ); + assert( p < 2 ); + assert( q < 2 ); + assert( p > 0 || q > 0 ); + + return pSes->nGateOffset + i * 3 + ( p << 1 ) + q - 1; +} + +static inline int Ses_ManSelectVar( Ses_Man_t * pSes, int i, int j, int k ) +{ + int a; + int offset; + + assert( i < pSes->nGates ); + assert( k < pSes->nSpecVars + i ); + assert( j < k ); + + offset = pSes->nSelectOffset; + for ( a = pSes->nSpecVars; a < pSes->nSpecVars + i; ++a ) + offset += a * ( a - 1 ) / 2; + + return offset + ( -j * ( 1 + j - 2 * ( pSes->nSpecVars + i ) ) ) / 2 + ( k - j - 1 ); +} + +static inline int Ses_ManDepthVar( Ses_Man_t * pSes, int i, int j ) +{ + assert( i < pSes->nGates ); + assert( j <= pSes->nArrTimeMax + i ); + + return pSes->nDepthOffset + i * pSes->nArrTimeMax + ( ( i * ( i + 1 ) ) / 2 ) + j; +} + +/**Function************************************************************* + + Synopsis [Setup variables to find network with nGates gates.] + +***********************************************************************/ +static void Ses_ManCreateVars( Ses_Man_t * pSes, int nGates ) +{ + int i; + + if ( pSes->fVerbose ) + { + printf( "create variables for network with %d functions over %d variables and %d gates\n", pSes->nSpecFunc, pSes->nSpecVars, nGates ); + } + + pSes->nGates = nGates; + pSes->nSimVars = nGates * pSes->nRows; + pSes->nOutputVars = pSes->nSpecFunc * nGates; + pSes->nGateVars = nGates * 3; + pSes->nSelectVars = 0; + for ( i = pSes->nSpecVars; i < pSes->nSpecVars + nGates; ++i ) + pSes->nSelectVars += ( i * ( i - 1 ) ) / 2; + pSes->nDepthVars = pSes->nMaxDepth > 0 ? nGates * pSes->nArrTimeMax + ( nGates * ( nGates + 1 ) ) / 2 : 0; + + pSes->nOutputOffset = pSes->nSimVars; + pSes->nGateOffset = pSes->nSimVars + pSes->nOutputVars; + pSes->nSelectOffset = pSes->nSimVars + pSes->nOutputVars + pSes->nGateVars; + pSes->nDepthOffset = pSes->nSimVars + pSes->nOutputVars + pSes->nGateVars + pSes->nSelectVars; + + if ( pSes->pSat ) + sat_solver_delete( pSes->pSat ); + pSes->pSat = sat_solver_new(); + sat_solver_setnvars( pSes->pSat, pSes->nSimVars + pSes->nOutputVars + pSes->nGateVars + pSes->nSelectVars + pSes->nDepthVars ); +} + +/**Function************************************************************* + + Synopsis [Create clauses.] + +***********************************************************************/ +static inline void Ses_ManCreateMainClause( Ses_Man_t * pSes, int t, int i, int j, int k, int a, int b, int c ) +{ + int pLits[5], ctr = 0, value; + + pLits[ctr++] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); + pLits[ctr++] = Abc_Var2Lit( Ses_ManSimVar( pSes, i, t ), a ); + + if ( j < pSes->nSpecVars ) + { + if ( Abc_TtGetBit( s_Truths8 + ( j << 2 ), t + 1 ) != b ) /* 1 in clause, we can omit the clause */ + return; + } + else + pLits[ctr++] = Abc_Var2Lit( Ses_ManSimVar( pSes, j - pSes->nSpecVars, t ), b ); + + if ( k < pSes->nSpecVars ) + { + if ( Abc_TtGetBit( s_Truths8 + ( k << 2 ), t + 1 ) != c ) /* 1 in clause, we can omit the clause */ + return; + } + else + pLits[ctr++] = Abc_Var2Lit( Ses_ManSimVar( pSes, k - pSes->nSpecVars, t ), c ); + + if ( b > 0 || c > 0 ) + pLits[ctr++] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, b, c ), 1 - a ); + + value = sat_solver_addclause( pSes->pSat, pLits, pLits + ctr ); + assert( value ); +} + +static int Ses_ManCreateClauses( Ses_Man_t * pSes ) +{ + extern int Extra_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ); + + int h, i, j, k, t, ii, jj, kk, p, q, d; + int pLits[3]; + Vec_Int_t * vLits; + + for ( t = 0; t < pSes->nRows; ++t ) + for ( i = 0; i < pSes->nGates; ++i ) + { + /* main clauses */ + for ( j = 0; j < pSes->nSpecVars + i; ++j ) + for ( k = j + 1; k < pSes->nSpecVars + i; ++k ) + { + Ses_ManCreateMainClause( pSes, t, i, j, k, 0, 0, 1 ); + Ses_ManCreateMainClause( pSes, t, i, j, k, 0, 1, 0 ); + Ses_ManCreateMainClause( pSes, t, i, j, k, 0, 1, 1 ); + Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 0, 0 ); + Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 0, 1 ); + Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 1, 0 ); + Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 1, 1 ); + } + + /* output clauses */ + for ( h = 0; h < pSes->nSpecFunc; ++h ) + { + pLits[0] = Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 1 ); + pLits[1] = Abc_Var2Lit( Ses_ManSimVar( pSes, i, t ), 1 - Abc_TtGetBit( &pSes->pSpec[h << 2], t + 1 ) ); + assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) ); + } + } + + /* some output is selected */ + for ( h = 0; h < pSes->nSpecFunc; ++h ) + { + vLits = Vec_IntAlloc( pSes->nGates ); + for ( i = 0; i < pSes->nGates; ++i ) + Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 0 ) ); + assert( sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ) ); + Vec_IntFree( vLits ); + } + + /* each gate has two operands */ + for ( i = 0; i < pSes->nGates; ++i ) + { + vLits = Vec_IntAlloc( ( ( pSes->nSpecVars + i ) * ( pSes->nSpecVars + i - 1 ) ) / 2 ); + for ( j = 0; j < pSes->nSpecVars + i; ++j ) + for ( k = j + 1; k < pSes->nSpecVars + i; ++k ) + Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 0 ) ); + assert( sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ) ); + Vec_IntFree( vLits ); + } + + /* only AIG */ + if ( pSes->fMakeAIG ) + { + for ( i = 0; i < pSes->nGates; ++i ) + { + /* not 2 ones */ + pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 1 ); + pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 1 ); + pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 0 ); + assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) ); + + pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 1 ); + pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 0 ); + pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 1 ); + assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) ); + + pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 0 ); + pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 1 ); + pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 1 ); + assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) ); + } + } + + /* EXTRA clauses: use gate i at least once */ + for ( i = 0; i < pSes->nGates; ++i ) + { + vLits = Vec_IntAlloc( 0 ); + for ( h = 0; h < pSes->nSpecFunc; ++h ) + Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 0 ) ); + for ( ii = i + 1; ii < pSes->nGates; ++ii ) + { + for ( j = 0; j < pSes->nSpecVars + i; ++j ) + Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, ii, j, pSes->nSpecVars + i ), 0 ) ); + for ( j = pSes->nSpecVars + i + 1; j < pSes->nSpecVars + ii; ++j ) + Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, ii, pSes->nSpecVars + i, j ), 0 ) ); + } + assert( sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ) ); + Vec_IntFree( vLits ); + } + + /* EXTRA clauses: co-lexicographic order */ + for ( i = 0; i < pSes->nGates - 1; ++i ) + { + for ( k = 2; k < pSes->nSpecVars + i; ++k ) + { + for ( j = 1; j < k; ++j ) + for ( jj = 0; jj < j; ++jj ) + { + pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); + pLits[1] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i + 1, jj, k ), 1 ); + } + + for ( j = 0; j < k; ++j ) + for ( kk = 1; kk < k; ++kk ) + for ( jj = 0; jj < kk; ++jj ) + { + pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); + pLits[1] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i + 1, jj, kk ), 1 ); + } + } + } + + /* EXTRA clauses: symmetric variables */ + if ( pSes->nSpecFunc == 1 ) /* only check if there is one output function */ + for ( q = 1; q < pSes->nSpecVars; ++q ) + for ( p = 0; p < q; ++p ) + if ( Extra_TruthVarsSymm( (unsigned*)( &pSes->pSpec[h << 2] ), pSes->nSpecVars, p, q ) ) + { + if ( pSes->fVeryVerbose ) + printf( "variables %d and %d are symmetric\n", p, q ); + for ( i = 0; i < pSes->nGates; ++i ) + for ( j = 0; j < q; ++j ) + { + if ( j == p ) continue; + + vLits = Vec_IntAlloc( 0 ); + Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, q ), 1 ) ); + for ( ii = 0; ii < i; ++ii ) + for ( kk = 1; kk < pSes->nSpecVars + ii; ++kk ) + for ( jj = 0; jj < kk; ++jj ) + if ( jj == p || kk == p ) + Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, ii, jj, kk ), 0 ) ); + assert( sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ) ); + Vec_IntFree( vLits ); + } + } + + /* DEPTH clauses */ + if ( pSes->nMaxDepth > 0 ) + { + for ( i = 0; i < pSes->nGates; ++i ) + { + /* propagate depths from children */ + for ( k = 1; k < i; ++k ) + for ( j = 0; j < k; ++j ) + { + pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, pSes->nSpecVars + j, pSes->nSpecVars + k ), 1 ); + for ( jj = 0; jj <= pSes->nArrTimeMax + j; ++jj ) + { + pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, j, jj ), 1 ); + pLits[2] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, jj + 1 ), 0 ); + assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) ); + } + } + + for ( k = 0; k < i; ++k ) + for ( j = 0; j < pSes->nSpecVars + k; ++j ) + { + pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, pSes->nSpecVars + k ), 1 ); + for ( kk = 0; kk <= pSes->nArrTimeMax + k; ++kk ) + { + pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, k, kk ), 1 ); + pLits[2] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, kk + 1 ), 0 ); + assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ) ); + } + } + + /* propagate depths from arrival times at PIs */ + if ( pSes->pArrTimeProfile ) + { + for ( k = 1; k < pSes->nSpecVars + i; ++k ) + for ( j = 0; j < ( ( k < pSes->nSpecVars ) ? k : pSes->nSpecVars ); ++j ) + { + d = pSes->pArrTimeProfile[j]; + if ( k < pSes->nSpecVars && pSes->pArrTimeProfile[k] > d ) + d = pSes->pArrTimeProfile[k]; + + pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); + pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, d + 1 ), 0 ); + assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) ); + } + } + else + { + /* arrival times are 0 */ + pLits[0] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, 0 ), 0 ); + assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 1 ) ); + } + + /* reverse order encoding of depth variables */ + for ( j = 1; j <= pSes->nArrTimeMax + i; ++j ) + { + pLits[0] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, j ), 1 ); + pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, j - 1 ), 0 ); + assert( sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) ); + } + + /* constrain maximum depth */ + if ( pSes->nMaxDepth < pSes->nArrTimeMax + i ) + for ( h = 0; h < pSes->nSpecFunc; ++h ) + { + pLits[0] = Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 1 ); + pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, pSes->nMaxDepth ), 1 ); + if ( !sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) ) + return 0; + } + } + } + + return 1; +} + +/**Function************************************************************* + + Synopsis [Solve.] + +***********************************************************************/ +static inline int Ses_ManSolve( Ses_Man_t * pSes ) +{ + int status; + abctime timeStart, timeDelta; + + if ( pSes->fVeryVerbose ) + { + printf( "solve SAT instance with %d clauses and %d variables\n", sat_solver_nclauses( pSes->pSat ), sat_solver_nvars( pSes->pSat ) ); + } + + timeStart = Abc_Clock(); + status = sat_solver_solve( pSes->pSat, NULL, NULL, pSes->nBTLimit, 0, 0, 0 ); + timeDelta = Abc_Clock() - timeStart; + + pSes->timeSat += timeDelta; + + if ( status == l_True ) + { + pSes->timeSatSat += timeDelta; + return 1; + } + else if ( status == l_False ) + { + pSes->timeSatUnsat += timeDelta; + return 0; + } + else + { + if ( pSes->fVerbose ) + { + printf( "resource limit reached\n" ); + } + return 2; + } +} + +/**Function************************************************************* + + Synopsis [Extract solution.] + +***********************************************************************/ +// char is an array of short integers that stores the synthesized network +// using the following format +// | nvars | nfunc | ngates | gate[1] | ... | gate[ngates] | func[1] | .. | func[nfunc] | +// nvars: integer with number of variables +// nfunc: integer with number of functions +// ngates: integer with number of gates +// gate[i]: | op | nfanin | fanin[1] | ... | fanin[nfanin] | +// op: integer of gate's truth table (divided by 2, because gate is normal) +// nfanin[i]: integer with number of fanins +// fanin: integer to primary input or other gate +// func[i]: | fanin | delay | pin[1] | ... | pin[nvars] | +// fanin: integer as literal to some gate (not primary input), can be complemented +// delay: maximum delay to output (taking arrival times into account, not normalized) or 0 if not specified +// pin[i]: pin to pin delay to input i or 0 if not specified or if there is no connection to input i +// NOTE: since outputs can only point to gates, delay and pin-to-pin times cannot be 0 +static char * Ses_ManExtractSolution( Ses_Man_t * pSes ) +{ + int nSol, h, i, j, k, l, aj, ak, d, nOp; + char * pSol, * p; + int * pPerm = NULL; /* will be a 2d array [i][l] where is is gate id and l is PI id */ + + /* compute length of solution, for now all gates have 2 inputs */ + nSol = 3 + pSes->nGates * 4 + pSes->nSpecFunc * ( 2 + pSes->nSpecVars ); + + p = pSol = ABC_CALLOC( char, nSol ); + + /* header */ + *p++ = pSes->nSpecVars; + *p++ = pSes->nSpecFunc; + *p++ = pSes->nGates; + + /* gates */ + for ( i = 0; i < pSes->nGates; ++i ) + { + nOp = sat_solver_var_value( pSes->pSat, Ses_ManGateVar( pSes, i, 0, 1 ) ); + nOp |= sat_solver_var_value( pSes->pSat, Ses_ManGateVar( pSes, i, 1, 0 ) ) << 1; + nOp |= sat_solver_var_value( pSes->pSat, Ses_ManGateVar( pSes, i, 1, 1 ) ) << 2; + + *p++ = nOp; + *p++ = 2; + + if ( pSes->fVeryVerbose ) + printf( "add gate %d with operation %d", pSes->nSpecVars + i, nOp ); + + for ( k = 0; k < pSes->nSpecVars + i; ++k ) + for ( j = 0; j < k; ++j ) + if ( sat_solver_var_value( pSes->pSat, Ses_ManSelectVar( pSes, i, j, k ) ) ) + { + if ( pSes->fVeryVerbose ) + printf( " and operands %d and %d", j, k ); + *p++ = j; + *p++ = k; + break; + } + + if ( pSes->fVeryVerbose ) + { + if ( pSes->nMaxDepth > 0 ) + { + printf( " and depth vector " ); + for ( j = 0; j <= pSes->nArrTimeMax + i; ++j ) + printf( "%d", sat_solver_var_value( pSes->pSat, Ses_ManDepthVar( pSes, i, j ) ) ); + } + printf( "\n" ); + } + } + + /* pin-to-pin delay */ + if ( pSes->nMaxDepth != -1 ) + { + pPerm = ABC_CALLOC( int, pSes->nGates * pSes->nSpecVars ); + for ( i = 0; i < pSes->nGates; ++i ) + { + /* since all gates are binary for now */ + j = pSol[3 + i * 4 + 2]; + k = pSol[3 + i * 4 + 3]; + + for ( l = 0; l < pSes->nSpecVars; ++l ) + { + /* pin-to-pin delay to input l of child nodes */ + aj = j < pSes->nSpecVars ? 0 : pPerm[(j - pSes->nSpecVars) * pSes->nSpecVars + l]; + ak = k < pSes->nSpecVars ? 0 : pPerm[(k - pSes->nSpecVars) * pSes->nSpecVars + l]; + + if ( aj == 0 && ak == 0 ) + pPerm[i * pSes->nSpecVars + l] = ( l == j || l == k ) ? 1 : 0; + else + pPerm[i * pSes->nSpecVars + l] = Abc_MaxInt( aj, ak ) + 1; + } + } + } + + /* outputs */ + for ( h = 0; h < pSes->nSpecFunc; ++h ) + for ( i = 0; i < pSes->nGates; ++i ) + if ( sat_solver_var_value( pSes->pSat, Ses_ManOutputVar( pSes, h, i ) ) ) + { + *p++ = Abc_Var2Lit( i, ( pSes->bSpecInv >> h ) & 1 ); + d = 0; + if ( pSes->nMaxDepth != -1 ) + while ( d < pSes->nArrTimeMax + i && sat_solver_var_value( pSes->pSat, Ses_ManDepthVar( pSes, i, d ) ) ) + ++d; + *p++ = d + pSes->nArrTimeDelta; + if ( pSes->fVeryVerbose ) + printf( "output %d points to %d and has normalized delay %d\n", h, i, d ); + for ( l = 0; l < pSes->nSpecVars; ++l ) + { + d = ( pSes->nMaxDepth != -1 ) ? pPerm[i * pSes->nSpecVars + l] : 0; + if ( pSes->fVeryVerbose ) + printf( " pin-to-pin arrival time from input %d is %d\n", l, d ); + *p++ = d; + } + } + + /* pin-to-pin delays */ + if ( pSes->nMaxDepth != -1 ) + ABC_FREE( pPerm ); + + /* have we used all the fields? */ + assert( ( p - pSol ) == nSol ); + + return pSol; +} + +static Abc_Ntk_t * Ses_ManExtractNtk( char const * pSol ) +{ + int h, i; + char const * p; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj; + Vec_Ptr_t * pGates, * vNames; + char pGateTruth[5]; + char * pSopCover; + + pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtk->pName = Extra_UtilStrsav( "exact" ); + pGates = Vec_PtrAlloc( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NGATES] ); + pGateTruth[3] = '0'; + pGateTruth[4] = '\0'; + vNames = Abc_NodeGetFakeNames( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NFUNC] ); + + /* primary inputs */ + Vec_PtrPush( pNtk->vObjs, NULL ); + for ( i = 0; i < pSol[ABC_EXACT_SOL_NVARS]; ++i ) + { + pObj = Abc_NtkCreatePi( pNtk ); + Abc_ObjAssignName( pObj, (char*)Vec_PtrEntry( vNames, i ), NULL ); + Vec_PtrPush( pGates, pObj ); + } + + /* gates */ + p = pSol + 3; + for ( i = 0; i < pSol[ABC_EXACT_SOL_NGATES]; ++i ) + { + pGateTruth[2] = '0' + ( *p & 1 ); + pGateTruth[1] = '0' + ( ( *p >> 1 ) & 1 ); + pGateTruth[0] = '0' + ( ( *p >> 2 ) & 1 ); + ++p; + + assert( *p == 2 ); /* binary gate */ + ++p; + + pSopCover = Abc_SopFromTruthBin( pGateTruth ); + pObj = Abc_NtkCreateNode( pNtk ); + pObj->pData = Abc_SopRegister( (Mem_Flex_t*)pNtk->pManFunc, pSopCover ); + Vec_PtrPush( pGates, pObj ); + ABC_FREE( pSopCover ); + + Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) ); + Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) ); + } + + /* outputs */ + for ( h = 0; h < pSol[ABC_EXACT_SOL_NFUNC]; ++h ) + { + pObj = Abc_NtkCreatePo( pNtk ); + Abc_ObjAssignName( pObj, (char*)Vec_PtrEntry( vNames, pSol[ABC_EXACT_SOL_NVARS] + h ), NULL ); + if ( Abc_LitIsCompl( *p ) ) + Abc_ObjAddFanin( pObj, Abc_NtkCreateNodeInv( pNtk, (Abc_Obj_t *)Vec_PtrEntry( pGates, pSol[ABC_EXACT_SOL_NVARS] + Abc_Lit2Var( *p ) ) ) ); + else + Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, pSol[ABC_EXACT_SOL_NVARS] + Abc_Lit2Var( *p ) ) ); + p += ( 2 + pSol[ABC_EXACT_SOL_NVARS] ); + } + Abc_NodeFreeNames( vNames ); + + Vec_PtrFree( pGates ); + + if ( !Abc_NtkCheck( pNtk ) ) + printf( "Ses_ManExtractSolution(): Network check has failed.\n" ); + + return pNtk; +} + +static Gia_Man_t * Ses_ManExtractGia( char const * pSol ) +{ + int h, i; + char const * p; + Gia_Man_t * pGia; + Vec_Int_t * pGates; + Vec_Ptr_t * vNames; + int nObj, nChild1, nChild2, fChild1Comp, fChild2Comp; + + pGia = Gia_ManStart( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NGATES] + pSol[ABC_EXACT_SOL_NFUNC] + 1 ); + pGia->nConstrs = 0; + pGia->pName = Extra_UtilStrsav( "exact" ); + + pGates = Vec_IntAlloc( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NGATES] ); + vNames = Abc_NodeGetFakeNames( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NFUNC] ); + + /* primary inputs */ + pGia->vNamesIn = Vec_PtrStart( pSol[ABC_EXACT_SOL_NVARS] ); + for ( i = 0; i < pSol[ABC_EXACT_SOL_NVARS]; ++i ) + { + nObj = Gia_ManAppendCi( pGia ); + Vec_IntPush( pGates, nObj ); + Vec_PtrSetEntry( pGia->vNamesIn, i, Extra_UtilStrsav( Vec_PtrEntry( vNames, i ) ) ); + } + + /* gates */ + p = pSol + 3; + for ( i = 0; i < pSol[ABC_EXACT_SOL_NGATES]; ++i ) + { + assert( p[1] == 2 ); + nChild1 = Vec_IntEntry( pGates, p[2] ); + nChild2 = Vec_IntEntry( pGates, p[3] ); + fChild1Comp = fChild2Comp = 0; + + if ( *p & 1 ) + { + nChild1 = Abc_LitNot( nChild1 ); + fChild1Comp = 1; + } + if ( ( *p >> 1 ) & 1 ) + { + nChild2 = Abc_LitNot( nChild2 ); + fChild2Comp = 1; + } + nObj = Gia_ManAppendAnd( pGia, nChild1, nChild2 ); + if ( fChild1Comp && fChild2Comp ) + { + assert( ( *p >> 2 ) & 1 ); + nObj = Abc_LitNot( nObj ); + } + + Vec_IntPush( pGates, nObj ); + + p += 4; + } + + /* outputs */ + pGia->vNamesOut = Vec_PtrStart( pSol[ABC_EXACT_SOL_NFUNC] ); + for ( h = 0; h < pSol[ABC_EXACT_SOL_NFUNC]; ++h ) + { + nObj = Vec_IntEntry( pGates, pSol[ABC_EXACT_SOL_NVARS] + Abc_Lit2Var( *p ) ); + if ( Abc_LitIsCompl( *p ) ) + nObj = Abc_LitNot( nObj ); + Gia_ManAppendCo( pGia, nObj ); + Vec_PtrSetEntry( pGia->vNamesOut, h, Extra_UtilStrsav( Vec_PtrEntry( vNames, pSol[ABC_EXACT_SOL_NVARS] + h ) ) ); + p += ( 2 + pSol[ABC_EXACT_SOL_NVARS] ); + } + Abc_NodeFreeNames( vNames ); + + Vec_IntFree( pGates ); + + return pGia; +} + +/**Function************************************************************* + + Synopsis [Debug.] + +***********************************************************************/ +static void Ses_ManPrintRuntime( Ses_Man_t * pSes ) +{ + printf( "Runtime breakdown:\n" ); + ABC_PRTP( "Sat ", pSes->timeSat, pSes->timeTotal ); + ABC_PRTP( " Sat ", pSes->timeSatSat, pSes->timeTotal ); + ABC_PRTP( " Unsat", pSes->timeSatUnsat, pSes->timeTotal ); + ABC_PRTP( "ALL ", pSes->timeTotal, pSes->timeTotal ); +} + +static inline void Ses_ManPrintFuncs( Ses_Man_t * pSes ) +{ + int h; + + printf( "find optimum circuit for %d %d-variable functions:\n", pSes->nSpecFunc, pSes->nSpecVars ); + for ( h = 0; h < pSes->nSpecFunc; ++h ) + { + printf( " func %d: ", h + 1 ); + Abc_TtPrintHexRev( stdout, &pSes->pSpec[h >> 2], pSes->nSpecVars ); + printf( "\n" ); + } +} + +static inline void Ses_ManPrintVars( Ses_Man_t * pSes ) +{ + int h, i, j, k, p, q, t; + + for ( i = 0; i < pSes->nGates; ++i ) + for ( t = 0; t < pSes->nRows; ++t ) + printf( "x(%d, %d) : %d\n", i, t, Ses_ManSimVar( pSes, i, t ) ); + + for ( h = 0; h < pSes->nSpecFunc; ++h ) + for ( i = 0; i < pSes->nGates; ++i ) + printf( "h(%d, %d) : %d\n", h, i, Ses_ManOutputVar( pSes, h, i ) ); + + for ( i = 0; i < pSes->nGates; ++i ) + for ( p = 0; p <= 1; ++p ) + for ( q = 0; q <= 1; ++ q) + { + if ( p == 0 && q == 0 ) { continue; } + printf( "f(%d, %d, %d) : %d\n", i, p, q, Ses_ManGateVar( pSes, i, p, q ) ); + } + + for ( i = 0; i < pSes->nGates; ++i ) + for ( j = 0; j < pSes->nSpecVars + i; ++j ) + for ( k = j + 1; k < pSes->nSpecVars + i; ++k ) + printf( "s(%d, %d, %d) : %d\n", i, j, k, Ses_ManSelectVar( pSes, i, j, k ) ); + + if ( pSes->nMaxDepth > 0 ) + for ( i = 0; i < pSes->nGates; ++i ) + for ( j = 0; j <= i; ++j ) + printf( "d(%d, %d) : %d\n", i, j, Ses_ManDepthVar( pSes, i, j ) ); + +} + +/**Function************************************************************* + + Synopsis [Synthesis algorithm.] + +***********************************************************************/ +static int Ses_ManFindMinimumSize( Ses_Man_t * pSes ) +{ + int nGates = 0; + + while ( true ) + { + ++nGates; + + /* give up if number of gates is impossible for given depth */ + if ( pSes->nMaxDepth != -1 && nGates >= ( 1 << pSes->nMaxDepth ) ) + return 0; + + Ses_ManCreateVars( pSes, nGates ); + if ( !Ses_ManCreateClauses( pSes ) ) + return 0; /* proven UNSAT while creating clauses */ + + switch ( Ses_ManSolve( pSes ) ) + { + case 1: return 1; /* SAT */ + case 2: return 0; /* resource limit */ + } + } + + return 0; +} + +/**Function************************************************************* + + Synopsis [Find minimum size networks with a SAT solver.] + + Description [If nMaxDepth is -1, then depth constraints are ignored. + If nMaxDepth is not -1, one can set pArrTimeProfile which should have the length of nVars. + One can ignore pArrTimeProfile by setting it to NULL.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrTimeProfile, int fVerbose ) +{ + Ses_Man_t * pSes; + char * pSol; + Abc_Ntk_t * pNtk = NULL; + abctime timeStart; + + /* some checks */ + assert( nVars >= 2 && nVars <= 8 ); + + timeStart = Abc_Clock(); + + pSes = Ses_ManAlloc( pTruth, nVars, nFunc, nMaxDepth, pArrTimeProfile, 0, fVerbose ); + if ( fVerbose ) + Ses_ManPrintFuncs( pSes ); + + if ( Ses_ManFindMinimumSize( pSes ) ) + { + pSol = Ses_ManExtractSolution( pSes ); + pNtk = Ses_ManExtractNtk( pSol ); + ABC_FREE( pSol ); + } + + pSes->timeTotal = Abc_Clock() - timeStart; + + if ( fVerbose ) + Ses_ManPrintRuntime( pSes ); + + /* cleanup */ + Ses_ManClean( pSes ); + + return pNtk; +} + +Gia_Man_t * Gia_ManFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrTimeProfile, int fVerbose ) +{ + Ses_Man_t * pSes; + char * pSol; + Gia_Man_t * pGia = NULL; + abctime timeStart; + + /* some checks */ + assert( nVars >= 2 && nVars <= 8 ); + + timeStart = Abc_Clock(); + + pSes = Ses_ManAlloc( pTruth, nVars, nFunc, nMaxDepth, pArrTimeProfile, 1, fVerbose ); + if ( fVerbose ) + Ses_ManPrintFuncs( pSes ); + + if ( Ses_ManFindMinimumSize( pSes ) ) + { + pSol = Ses_ManExtractSolution( pSes ); + pGia = Ses_ManExtractGia( pSol ); + ABC_FREE( pSol ); + } + + pSes->timeTotal = Abc_Clock() - timeStart; + + if ( fVerbose ) + Ses_ManPrintRuntime( pSes ); + + /* cleanup */ + Ses_ManClean( pSes ); + + return pGia; +} + +/**Function************************************************************* + + Synopsis [Some test cases.] + +***********************************************************************/ + +Abc_Ntk_t * Abc_NtkFromTruthTable( word * pTruth, int nVars ) +{ + Abc_Ntk_t * pNtk; + Mem_Flex_t * pMan; + char * pSopCover; + + pMan = Mem_FlexStart(); + pSopCover = Abc_SopCreateFromTruth( pMan, nVars, (unsigned*)pTruth ); + pNtk = Abc_NtkCreateWithNode( pSopCover ); + Abc_NtkShortNames( pNtk ); + Mem_FlexStop( pMan, 0 ); + + return pNtk; +} + +void Abc_ExactTestSingleOutput( int fVerbose ) +{ + extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ); + + word pTruth[4] = {0xcafe, 0, 0, 0}; + Abc_Ntk_t * pNtk, * pNtk2, * pNtk3, * pNtk4; + int pArrTimeProfile[4] = {6, 2, 8, 5}; + + pNtk = Abc_NtkFromTruthTable( pTruth, 4 ); + + pNtk2 = Abc_NtkFindExact( pTruth, 4, 1, -1, NULL, fVerbose ); + Abc_NtkShortNames( pNtk2 ); + Abc_NtkCecSat( pNtk, pNtk2, 10000, 0 ); + assert( pNtk2 ); + assert( Abc_NtkNodeNum( pNtk2 ) == 6 ); + Abc_NtkDelete( pNtk2 ); + + pNtk3 = Abc_NtkFindExact( pTruth, 4, 1, 3, NULL, fVerbose ); + Abc_NtkShortNames( pNtk3 ); + Abc_NtkCecSat( pNtk, pNtk3, 10000, 0 ); + assert( pNtk3 ); + assert( Abc_NtkLevel( pNtk3 ) <= 3 ); + Abc_NtkDelete( pNtk3 ); + + pNtk4 = Abc_NtkFindExact( pTruth, 4, 1, 9, pArrTimeProfile, fVerbose ); + Abc_NtkShortNames( pNtk4 ); + Abc_NtkCecSat( pNtk, pNtk4, 10000, 0 ); + assert( pNtk4 ); + assert( Abc_NtkLevel( pNtk4 ) <= 9 ); + Abc_NtkDelete( pNtk4 ); + + assert( !Abc_NtkFindExact( pTruth, 4, 1, 2, NULL, fVerbose ) ); + + assert( !Abc_NtkFindExact( pTruth, 4, 1, 8, pArrTimeProfile, fVerbose ) ); + + Abc_NtkDelete( pNtk ); +} + +void Abc_ExactTestSingleOutputAIG( int fVerbose ) +{ + word pTruth[4] = {0xcafe, 0, 0, 0}; + Abc_Ntk_t * pNtk; + Gia_Man_t * pGia, * pGia2, * pGia3, * pGia4, * pMiter; + Cec_ParCec_t ParsCec, * pPars = &ParsCec; + int pArrTimeProfile[4] = {6, 2, 8, 5}; + + Cec_ManCecSetDefaultParams( pPars ); + + pNtk = Abc_NtkFromTruthTable( pTruth, 4 ); + Abc_NtkToAig( pNtk ); + pGia = Abc_NtkAigToGia( pNtk, 1 ); + + pGia2 = Gia_ManFindExact( pTruth, 4, 1, -1, NULL, fVerbose ); + pMiter = Gia_ManMiter( pGia, pGia2, 0, 1, 0, 0, 1 ); + assert( pMiter ); + Cec_ManVerify( pMiter, pPars ); + Gia_ManStop( pMiter ); + + pGia3 = Gia_ManFindExact( pTruth, 4, 1, 3, NULL, fVerbose ); + pMiter = Gia_ManMiter( pGia, pGia3, 0, 1, 0, 0, 1 ); + assert( pMiter ); + Cec_ManVerify( pMiter, pPars ); + Gia_ManStop( pMiter ); + + pGia4 = Gia_ManFindExact( pTruth, 4, 1, 9, pArrTimeProfile, fVerbose ); + pMiter = Gia_ManMiter( pGia, pGia4, 0, 1, 0, 0, 1 ); + assert( pMiter ); + Cec_ManVerify( pMiter, pPars ); + Gia_ManStop( pMiter ); + + assert( !Gia_ManFindExact( pTruth, 4, 1, 2, NULL, fVerbose ) ); + + assert( !Gia_ManFindExact( pTruth, 4, 1, 8, pArrTimeProfile, fVerbose ) ); + + Gia_ManStop( pGia ); + Gia_ManStop( pGia2 ); + Gia_ManStop( pGia3 ); + Gia_ManStop( pGia4 ); +} + +void Abc_ExactTest( int fVerbose ) +{ + Abc_ExactTestSingleOutput( fVerbose ); + Abc_ExactTestSingleOutputAIG( fVerbose ); + + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [APIs for integraging with the mapper.] + +***********************************************************************/ +// may need to have a static pointer to the SAT-based synthesis engine and/or loaded library +// this procedure should return 1, if the engine/library are available, and 0 otherwise +int Abc_ExactIsRunning() +{ + return s_pSesStore != NULL; +} +// this procedure returns the number of inputs of the library +// for example, somebody may try to map into 10-cuts while the library only contains 8-functions +int Abc_ExactInputNum() +{ + return 8; +} +// start exact store manager +void Abc_ExactStart( int nBTLimit, int fMakeAIG, int fVerbose, const char * pFilename ) +{ + if ( !s_pSesStore ) + { + s_pSesStore = Ses_StoreAlloc( nBTLimit, fMakeAIG, fVerbose ); + if ( pFilename ) + Ses_StoreRead( s_pSesStore, pFilename ); + } + else + printf( "BMS manager already started\n" ); +} +// stop exact store manager +void Abc_ExactStop( const char * pFilename ) +{ + if ( s_pSesStore ) + { + if ( pFilename ) + Ses_StoreWrite( s_pSesStore, pFilename ); + Ses_StoreClean( s_pSesStore ); + } + else + printf( "BMS manager has not been started\n" ); +} +// show statistics about store manager +void Abc_ExactStats() +{ + int i; + + if ( !s_pSesStore ) + { + printf( "BMS manager has not been started\n" ); + return; + } + + printf( "number of considered cuts :" ); + for ( i = 2; i < 9; ++i ) + printf( " %d = %lu ", i, s_pSesStore->pCutCount[i] ); + printf( " total = %lu\n", s_pSesStore->nCutCount ); + printf( "cache hits : %lu\n", s_pSesStore->nCacheHit ); + printf( "number of entries : %d\n", s_pSesStore->nEntriesCount ); +} +// this procedure takes TT and input arrival times (pArrTimeProfile) and return the smallest output arrival time; +// it also returns the pin-to-pin delays (pPerm) between each cut leaf and the cut output and the cut area cost (Cost) +// the area cost should not exceed 2048, if the cut is implementable; otherwise, it should be ABC_INFINITY +int Abc_ExactDelayCost( word * pTruth, int nVars, int * pArrTimeProfile, char * pPerm, int * Cost, int AigLevel ) +{ + int i, l, fExists = 0; + Ses_Man_t * pSes = NULL; + char * pSol = NULL, * p; + int Delay = ABC_INFINITY, nMaxDepth; + abctime timeStart; + + /* some checks */ + if ( nVars < 0 || nVars > 8 ) + { + printf( "invalid truth table size %d\n", nVars ); + assert( 0 ); + } + + if ( nVars == 0 ) + { + *Cost = 0; + return 0; + } + + if ( nVars == 1 ) + { + *Cost = 0; + pPerm[0] = (char)0; + return pArrTimeProfile[0]; + } + + /* statistics */ + s_pSesStore->nCutCount++; + s_pSesStore->pCutCount[nVars]++; + + pSol = Ses_StoreGetEntry( s_pSesStore, pTruth, nVars, pArrTimeProfile ); + if ( pSol ) + { + s_pSesStore->nCacheHit++; + fExists = 1; + } + else + { + nMaxDepth = pArrTimeProfile[0]; + for ( i = 1; i < nVars; ++i ) + nMaxDepth = Abc_MaxInt( nMaxDepth, pArrTimeProfile[i] ); + nMaxDepth = Abc_MinInt( AigLevel, nMaxDepth + nVars + 1 ); + + timeStart = Abc_Clock(); + + *Cost = ABC_INFINITY; + + pSes = Ses_ManAlloc( pTruth, nVars, 1 /* fSpecFunc */, nMaxDepth, pArrTimeProfile, s_pSesStore->fMakeAIG, s_pSesStore->fVerbose ); + pSes->nBTLimit = s_pSesStore->nBTLimit; + + while ( 1 ) /* there is improvement */ + { + if ( Ses_ManFindMinimumSize( pSes ) ) + { + if ( pSol ) + ABC_FREE( pSol ); + pSol = Ses_ManExtractSolution( pSes ); + pSes->nMaxDepth--; + } + else + break; + } + + pSes->timeTotal = Abc_Clock() - timeStart; + + /* cleanup */ + Ses_ManClean( pSes ); + } + + if ( pSol ) + { + *Cost = pSol[ABC_EXACT_SOL_NGATES]; + p = pSol + 3 + 4 * pSol[ABC_EXACT_SOL_NGATES] + 1; + Delay = *p++; + for ( l = 0; l < nVars; ++l ) + pPerm[l] = *p++; + + /* store solution */ + if ( !fExists ) + Ses_StoreAddEntry( s_pSesStore, pTruth, nVars, pArrTimeProfile, pSol ); + } + + return Delay; +} +// this procedure returns a new node whose output in terms of the given fanins +// has the smallest possible arrival time (in agreement with the above Abc_ExactDelayCost) +Abc_Obj_t * Abc_ExactBuildNode( word * pTruth, int nVars, int * pArrTimeProfile, Abc_Obj_t ** pFanins, Abc_Ntk_t * pNtk ) +{ + char * pSol; + int i, j; + char const * p; + Abc_Obj_t * pObj; + Vec_Ptr_t * pGates; + char pGateTruth[5]; + char * pSopCover; + + if ( nVars == 0 ) + return (pTruth[0] & 1) ? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); + if ( nVars == 1 ) + return (pTruth[0] & 1) ? Abc_NtkCreateNodeInv(pNtk, pFanins[0]) : Abc_NtkCreateNodeBuf(pNtk, pFanins[0]); + + pSol = Ses_StoreGetEntry( s_pSesStore, pTruth, nVars, pArrTimeProfile ); + if ( !pSol ) + return NULL; + + assert( pSol[ABC_EXACT_SOL_NVARS] == nVars ); + assert( pSol[ABC_EXACT_SOL_NFUNC] == 1 ); + + pGates = Vec_PtrAlloc( nVars + pSol[ABC_EXACT_SOL_NGATES] ); + pGateTruth[3] = '0'; + pGateTruth[4] = '\0'; + + /* primary inputs */ + for ( i = 0; i < nVars; ++i ) + { + Vec_PtrPush( pGates, pFanins[i] ); + } + + /* gates */ + p = pSol + 3; + for ( i = 0; i < pSol[ABC_EXACT_SOL_NGATES]; ++i ) + { + pGateTruth[2] = '0' + ( *p & 1 ); + pGateTruth[1] = '0' + ( ( *p >> 1 ) & 1 ); + pGateTruth[0] = '0' + ( ( *p >> 2 ) & 1 ); + ++p; + + assert( *p == 2 ); /* binary gate */ + ++p; + + /* invert truth table if we are last gate and inverted */ + if ( i + 1 == pSol[ABC_EXACT_SOL_NGATES] && Abc_LitIsCompl( *( p + 2 ) ) ) + for ( j = 0; j < 4; ++j ) + pGateTruth[j] = ( pGateTruth[j] == '0' ) ? '1' : '0'; + + pSopCover = Abc_SopFromTruthBin( pGateTruth ); + pObj = Abc_NtkCreateNode( pNtk ); + pObj->pData = Abc_SopRegister( (Mem_Flex_t*)pNtk->pManFunc, pSopCover ); + Vec_PtrPush( pGates, pObj ); + ABC_FREE( pSopCover ); + + Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) ); + Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) ); + } + + /* output */ + pObj = (Abc_Obj_t *)Vec_PtrEntry( pGates, nVars + Abc_Lit2Var( *p ) ); + + Vec_PtrFree( pGates ); + + return pObj; +} + +void Abc_ExactStoreTest( int fVerbose ) +{ + int i; + word pTruth[4] = {0xcafe, 0, 0, 0}; + int pArrTimeProfile[4] = {6, 2, 8, 5}; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pFanins[4]; + Vec_Ptr_t * vNames; + char pPerm[4]; + int Cost; + + pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtk->pName = Extra_UtilStrsav( "exact" ); + vNames = Abc_NodeGetFakeNames( 4u ); + + /* primary inputs */ + Vec_PtrPush( pNtk->vObjs, NULL ); + for ( i = 0; i < 4; ++i ) + { + pFanins[i] = Abc_NtkCreatePi( pNtk ); + Abc_ObjAssignName( pFanins[i], (char*)Vec_PtrEntry( vNames, i ), NULL ); + } + Abc_NodeFreeNames( vNames ); + + Abc_ExactStart( 10000, 1, fVerbose, NULL ); + + assert( !Abc_ExactBuildNode( pTruth, 4, pArrTimeProfile, pFanins, pNtk ) ); + + assert( Abc_ExactDelayCost( pTruth, 4, pArrTimeProfile, pPerm, &Cost, 12 ) == 1 ); + + assert( Abc_ExactBuildNode( pTruth, 4, pArrTimeProfile, pFanins, pNtk ) ); + + (*pArrTimeProfile)++; + assert( !Abc_ExactBuildNode( pTruth, 4, pArrTimeProfile, pFanins, pNtk ) ); + (*pArrTimeProfile)--; + + Abc_ExactStop( NULL ); + + Abc_NtkDelete( pNtk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END diff --git a/src/base/abci/abcFx.c b/src/base/abci/abcFx.c index 60f2e562..81b3e802 100644 --- a/src/base/abci/abcFx.c +++ b/src/base/abci/abcFx.c @@ -8,9 +8,9 @@ Synopsis [Implementation of traditional "fast_extract" algorithm.] - Author [Alan Mishchenko] + Author [Alan Mishchenko, Bruno Schmitt] - Affiliation [UC Berkeley] + Affiliation [UC Berkeley, UFRGS] Date [Ver. 1.0. Started - April 26, 2013.] @@ -103,6 +103,7 @@ struct Fx_Man_t_ Vec_Int_t * vCompls; // complemented attribute of each cube pair Vec_Int_t * vCubeFree; // cube-free divisor Vec_Int_t * vDiv; // selected divisor + Vec_Int_t * vSCC; // single cubes containment cubes // statistics abctime timeStart; // starting time int nVars; // original problem variables @@ -312,11 +313,6 @@ int Abc_NtkFxPerform( Abc_Ntk_t * pNtk, int nNewNodesMax, int LitCountMax, int f printf( "Abc_NtkFastExtract: Nodes have duplicated fanins. FX is not performed.\n" ); return 0; } - // sweep removes useless nodes - Abc_NtkCleanup( pNtk, 0 ); -// Abc_NtkOrderFanins( pNtk ); - // makes sure the SOPs are SCC-free and D1C-free - Abc_NtkMakeLegit( pNtk ); // collect information about the covers vCubes = Abc_NtkFxRetrieve( pNtk ); // call the fast extract procedure @@ -359,6 +355,7 @@ Fx_Man_t * Fx_ManStart( Vec_Wec_t * vCubes ) p->vCompls = Vec_IntAlloc( 100 ); p->vCubeFree = Vec_IntAlloc( 100 ); p->vDiv = Vec_IntAlloc( 100 ); + p->vSCC = Vec_IntAlloc( 100 ); return p; } void Fx_ManStop( Fx_Man_t * p ) @@ -377,6 +374,7 @@ void Fx_ManStop( Fx_Man_t * p ) Vec_IntFree( p->vCompls ); Vec_IntFree( p->vCubeFree ); Vec_IntFree( p->vDiv ); + Vec_IntFree( p->vSCC ); ABC_FREE( p ); } @@ -435,39 +433,16 @@ void Fx_ManComputeLevel( Fx_Man_t * p ) SeeAlso [] ***********************************************************************/ -static inline char Fx_PrintDivLit( int Lit ) { return (Abc_LitIsCompl(Lit) ? 'A' : 'a') + Abc_Lit2Var(Lit); } -static inline void Fx_PrintDivOneReal( Vec_Int_t * vDiv ) -{ - int i, Lit; - Vec_IntForEachEntry( vDiv, Lit, i ) - if ( !Abc_LitIsCompl(Lit) ) - printf( "%c", Fx_PrintDivLit(Abc_Lit2Var(Lit)) ); - printf( " + " ); - Vec_IntForEachEntry( vDiv, Lit, i ) - if ( Abc_LitIsCompl(Lit) ) - printf( "%c", Fx_PrintDivLit(Abc_Lit2Var(Lit)) ); -} -static inline void Fx_PrintDivOne( Vec_Int_t * vDiv ) -{ - int i, Lit; - Vec_IntForEachEntry( vDiv, Lit, i ) - if ( !Abc_LitIsCompl(Lit) ) - printf( "%c", Fx_PrintDivLit( Abc_Var2Lit(i, Abc_LitIsCompl(Lit)) ) ); - printf( " + " ); - Vec_IntForEachEntry( vDiv, Lit, i ) - if ( Abc_LitIsCompl(Lit) ) - printf( "%c", Fx_PrintDivLit( Abc_Var2Lit(i, Abc_LitIsCompl(Lit)) ) ); -} static inline void Fx_PrintDivArray( Vec_Int_t * vDiv ) { int i, Lit; Vec_IntForEachEntry( vDiv, Lit, i ) if ( !Abc_LitIsCompl(Lit) ) - printf( "%d(1) ", Abc_Lit2Var(Lit) ); + printf( "%d(1)", Abc_Lit2Var(Lit) ); printf( " + " ); Vec_IntForEachEntry( vDiv, Lit, i ) if ( Abc_LitIsCompl(Lit) ) - printf( "%d(2) ", Abc_Lit2Var(Lit) ); + printf( "%d(2)", Abc_Lit2Var(Lit) ); } static inline void Fx_PrintDiv( Fx_Man_t * p, int iDiv ) { @@ -475,8 +450,7 @@ static inline void Fx_PrintDiv( Fx_Man_t * p, int iDiv ) printf( "%4d : ", p->nDivs ); printf( "Div %7d : ", iDiv ); printf( "Weight %12.5f ", Vec_FltEntry(p->vWeights, iDiv) ); -// printf( "Compl %4d ", p->nCompls ); - Fx_PrintDivOne( Hsh_VecReadEntry(p->pHash, iDiv) ); + Fx_PrintDivArray( Hsh_VecReadEntry(p->pHash, iDiv) ); for ( i = Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) + 3; i < 16; i++ ) printf( " " ); printf( "Lits =%7d ", p->nLits ); @@ -489,45 +463,6 @@ static void Fx_PrintDivisors( Fx_Man_t * p ) for ( iDiv = 0; iDiv < Vec_FltSize(p->vWeights); iDiv++ ) Fx_PrintDiv( p, iDiv ); } -static void Fx_PrintLiterals( Fx_Man_t * p ) -{ - Vec_Int_t * vTemp; - int i; - Vec_WecForEachLevel( p->vLits, vTemp, i ) - { - printf( "%c : ", Fx_PrintDivLit(i) ); - Vec_IntPrint( vTemp ); - } -} -static void Fx_PrintMatrix( Fx_Man_t * p ) -{ - Vec_Int_t * vCube; - int i, v, Lit, nObjs; - char * pLine; - if ( Vec_WecSize(p->vLits)/2 > 26 ) - return; - printf( " " ); - nObjs = Vec_WecSize(p->vLits)/2; - for ( i = 0; i < Abc_MinInt(nObjs, 26); i++ ) - printf( "%c", 'a' + i ); - printf( "\n" ); - pLine = ABC_CALLOC( char, nObjs+1 ); - Vec_WecForEachLevel( p->vCubes, vCube, i ) - { - if ( Vec_IntSize(vCube) == 0 ) - continue; - memset( pLine, '-', nObjs ); - Vec_IntForEachEntryStart( vCube, Lit, v, 1 ) - { - assert( Abc_Lit2Var(Lit) < nObjs ); - pLine[Abc_Lit2Var(Lit)] = Abc_LitIsCompl(Lit) ? '0' : '1'; - } - printf( "%6d : %s %4d\n", i, pLine, Vec_IntEntry(vCube, 0) ); - } - ABC_FREE( pLine ); - Fx_PrintLiterals( p ); - Fx_PrintDivisors( p ); -} static void Fx_PrintStats( Fx_Man_t * p, abctime clk ) { printf( "Cubes =%8d ", Vec_WecSizeUsed(p->vCubes) ); @@ -536,11 +471,7 @@ static void Fx_PrintStats( Fx_Man_t * p, abctime clk ) printf( "Divs+ =%8d ", Vec_QueSize(p->vPrio) ); printf( "Compl =%8d ", p->nDivMux[1] ); printf( "Extr =%7d ", p->nDivs ); -// printf( "DivsS =%6d ", p->nDivsS ); -// printf( "PairS =%6d ", p->nPairsS ); -// printf( "PairD =%6d ", p->nPairsD ); Abc_PrintTime( 1, "Time", clk ); -// printf( "\n" ); } /**Function************************************************************* @@ -638,10 +569,10 @@ static int Fx_ManDivNormalize( Vec_Int_t * vCubeFree ) // return 1 if complement ***********************************************************************/ int Fx_ManDivFindCubeFree( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vCubeFree, int * fWarning ) { - int * pBeg1 = vArr1->pArray + 1; // skip variable ID - int * pBeg2 = vArr2->pArray + 1; // skip variable ID - int * pEnd1 = vArr1->pArray + vArr1->nSize; - int * pEnd2 = vArr2->pArray + vArr2->nSize; + int * pBeg1 = Vec_IntArray( vArr1 ) + 1; // skip variable ID + int * pBeg2 = Vec_IntArray( vArr2 ) + 1; // skip variable ID + int * pEnd1 = Vec_IntLimit( vArr1 ); + int * pEnd2 = Vec_IntLimit( vArr2 ); int Counter = 0, fAttr0 = 0, fAttr1 = 1; Vec_IntClear( vCubeFree ); while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) @@ -664,9 +595,38 @@ int Fx_ManDivFindCubeFree( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vCu if ( Vec_IntSize(vCubeFree) == 0 ) printf( "The SOP has duplicated cubes.\n" ); else if ( Vec_IntSize(vCubeFree) == 1 ) - printf( "The SOP has contained cubes.\n" ); -// else if ( Vec_IntSize(vCubeFree) == 2 && Abc_Lit2Var(Abc_Lit2Var(Vec_IntEntry(vCubeFree, 0))) == Abc_Lit2Var(Abc_Lit2Var(Vec_IntEntry(vCubeFree, 1))) && !*fWarning ) -// printf( "The SOP has distance-1 cubes or it is not a prime cover. Please make sure the result verifies.\n" ), *fWarning = 1; + return -1; + else if ( Vec_IntSize( vCubeFree ) == 3 ) + { + int * pArray = Vec_IntArray( vCubeFree ); + + if ( Abc_Lit2Var( pArray[0] ) == Abc_LitNot( Abc_Lit2Var( pArray[1] ) ) ) + { + if ( Abc_LitIsCompl( pArray[0] ) == Abc_LitIsCompl( pArray[2] ) ) + Vec_IntDrop( vCubeFree, 0 ); + else + Vec_IntDrop( vCubeFree, 1 ); + } + else if ( Abc_Lit2Var( pArray[1] ) == Abc_LitNot( Abc_Lit2Var( pArray[2] ) ) ) + { + if ( Abc_LitIsCompl( pArray[1] ) == Abc_LitIsCompl( pArray[0] ) ) + Vec_IntDrop( vCubeFree, 1 ); + else + Vec_IntDrop( vCubeFree, 2 ); + } + + if ( Vec_IntSize( vCubeFree ) == 2 ) + { + int Lit0 = Abc_Lit2Var( pArray[0] ), + Lit1 = Abc_Lit2Var( pArray[1] ); + + if ( Lit0 > Lit1 ) + ABC_SWAP( int, Lit0, Lit1 ); + + Vec_IntWriteEntry( vCubeFree, 0, Abc_Var2Lit( Lit0, 0 ) ); + Vec_IntWriteEntry( vCubeFree, 1, Abc_Var2Lit( Lit1, 1 ) ); + } + } assert( !Abc_LitIsCompl(Vec_IntEntry(vCubeFree, 0)) ); return Counter; } @@ -708,7 +668,11 @@ static inline int Fx_ManDivRemoveLits( Vec_Int_t * vCube, Vec_Int_t * vDiv, int int i, Lit, Count = 0; assert( !fCompl || Vec_IntSize(vDiv) == 4 ); Vec_IntForEachEntry( vDiv, Lit, i ) + { Count += Vec_IntRemove1( vCube, Abc_Lit2Var(Lit) ^ (fCompl && i > 1) ); // the last two lits can be complemented + if ( Vec_IntSize( vDiv ) == 2 ) + Count += Vec_IntRemove1( vCube, Abc_LitNot( Abc_Lit2Var(Lit) ) ); + } return Count; } static inline void Fx_ManDivAddLits( Vec_Int_t * vCube, Vec_Int_t * vCube2, Vec_Int_t * vDiv ) @@ -833,6 +797,17 @@ void Fx_ManCubeDoubleCubeDivisors( Fx_Man_t * p, int iFirst, Vec_Int_t * vPivot, if ( Vec_IntEntry(vCube, 0) != Vec_IntEntry(vPivot, 0) ) break; Base = Fx_ManDivFindCubeFree( vCube, vPivot, p->vCubeFree, fWarning ); + if ( Base == -1 ) + { + if ( fRemove == 0 ) + { + if ( Vec_IntSize( vCube ) > Vec_IntSize( vPivot ) ) + Vec_IntPush( p->vSCC, Vec_WecLevelId( p->vCubes, vCube ) ); + else + Vec_IntPush( p->vSCC, Vec_WecLevelId( p->vCubes, vPivot ) ); + } + continue; + } if ( Vec_IntSize(p->vCubeFree) == 4 ) { int Value = Fx_ManDivNormalize( p->vCubeFree ); @@ -988,10 +963,9 @@ void Fx_ManFindCommonPairs( Vec_Wec_t * vCubes, Vec_Int_t * vPart0, Vec_Int_t * ***********************************************************************/ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning ) { - Vec_Int_t * vCube, * vCube2, * vLitP, * vLitN; + Vec_Int_t * vCube, * vCube2, * vLitP = NULL, * vLitN = NULL; Vec_Int_t * vDiv = p->vDiv; - int nLitsNew = p->nLits - (int)Vec_FltEntry(p->vWeights, iDiv); - int i, k, Lit0, Lit1, iVarNew, RetValue, Level; + int i, k, Lit0, Lit1, iVarNew = 0, RetValue, Level; float Diff = Vec_FltEntry(p->vWeights, iDiv) - (float)((int)Vec_FltEntry(p->vWeights, iDiv)); assert( Diff > 0.0 && Diff < 1.0 ); @@ -1002,10 +976,6 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning ) Fx_ManDivFindPivots( vDiv, &Lit0, &Lit1 ); assert( Lit0 >= 0 && Lit1 >= 0 ); - // if the input cover is not prime, it may happen that we are extracting divisor (x + !x) - // although it is not strictly correct, it seems to be fine to just skip such divisors - if ( Abc_Lit2Var(Lit0) == Abc_Lit2Var(Lit1) && Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) == 2 ) - return; // collect single-cube-divisor cubes Vec_IntClear( p->vCubesS ); @@ -1041,6 +1011,9 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning ) Vec_WecUnmarkLevels( p->vCubes, p->vCubesS ); Vec_WecUnmarkLevels( p->vCubes, p->vCubesD ); + if ( Abc_Lit2Var(Lit0) == Abc_Lit2Var(Lit1) && Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) == 2 ) + goto ExtractFromPairs; + // create new divisor iVarNew = Vec_WecSize( p->vLits ) / 2; assert( Vec_IntSize(p->vVarCube) == iVarNew ); @@ -1080,6 +1053,7 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning ) p->nLits--; } // create updated double-cube divisor cube pairs +ExtractFromPairs: k = 0; p->nCompls = 0; assert( Vec_IntSize(p->vCubesD) % 2 == 0 ); @@ -1092,18 +1066,22 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning ) vCube2 = Vec_WecEntry( p->vCubes, Vec_IntEntry(p->vCubesD, i+1) ); RetValue = Fx_ManDivRemoveLits( vCube, vDiv, fCompl ); // cube 2*i RetValue += Fx_ManDivRemoveLits( vCube2, vDiv, fCompl ); // cube 2*i+1 - assert( RetValue == Vec_IntSize(vDiv) ); - if ( Vec_IntSize(vDiv) == 2 || fCompl ) + assert( RetValue == Vec_IntSize(vDiv) || RetValue == Vec_IntSize( vDiv ) + 1); + if ( iVarNew > 0 ) { - Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 1) ); - Vec_IntPush( vLitN, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID - } - else - { - Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 0) ); - Vec_IntPush( vLitP, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID + if ( Vec_IntSize(vDiv) == 2 || fCompl ) + { + Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 1) ); + Vec_IntPush( vLitN, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID + } + else + { + Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 0) ); + Vec_IntPush( vLitP, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID + } } p->nLits -= Vec_IntSize(vDiv) + Vec_IntSize(vCube2) - 2; + // remove second cube Vec_IntWriteEntry( p->vCubesD, k++, Vec_WecLevelId(p->vCubes, vCube) ); Vec_IntClear( vCube2 ); @@ -1134,6 +1112,17 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning ) Vec_WecUnmarkLevels( p->vCubes, p->vCubesS ); Vec_WecUnmarkLevels( p->vCubes, p->vCubesD ); + // Deal with SCC + if ( Vec_IntSize( p->vSCC ) ) + { + Vec_IntUniqify( p->vSCC ); + Fx_ManForEachCubeVec( p->vSCC, p->vCubes, vCube, i ) + { + Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 1, 1, fWarning ); // remove - update + Vec_IntClear( vCube ); + } + Vec_IntClear( p->vSCC ); + } // add cost of the new divisor if ( Vec_IntSize(vDiv) > 2 ) { @@ -1151,12 +1140,10 @@ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning ) Vec_IntForEachEntry( vDiv, Lit0, i ) { Vec_IntTwoRemove( Vec_WecEntry(p->vLits, Abc_Lit2Var(Lit0)), p->vCubesD ); - if ( p->nCompls && i > 1 ) // the last two lits are possibly complemented + if ( (p->nCompls && i > 1) || Vec_IntSize( vDiv ) == 2 ) // the last two lits are possibly complemented Vec_IntTwoRemove( Vec_WecEntry(p->vLits, Abc_LitNot(Abc_Lit2Var(Lit0))), p->vCubesD ); } - - // check predicted improvement: (new SOP lits == old SOP lits - divisor weight) - assert( p->nLits == nLitsNew ); + } /**Function************************************************************* @@ -1186,7 +1173,7 @@ int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitC Fx_ManComputeLevel( p ); Fx_ManCreateDivisors( p ); if ( fVeryVerbose ) - Fx_PrintMatrix( p ); + Fx_PrintDivisors( p ); if ( fVerbose ) Fx_PrintStats( p, Abc_Clock() - clk ); // perform extraction @@ -1198,7 +1185,7 @@ int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitC Fx_PrintDiv( p, iDiv ); Fx_ManUpdate( p, iDiv, &fWarning ); if ( fVeryVeryVerbose ) - Fx_PrintMatrix( p ); + Fx_PrintDivisors( p ); } if ( fVerbose ) Fx_PrintStats( p, Abc_Clock() - clk ); diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index c45eaec5..08e2a560 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -116,7 +116,7 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk); // update timing info to reflect logic level - if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib) && pNtk->pManTime ) + if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib) && pNtk->pManTime ) { int c; if ( pNtk->AndGateDelay == 0.0 ) @@ -318,7 +318,7 @@ Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk ) // create the new network if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); - else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->nGateSize > 0 ) + else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->fUserSesLib || pIfMan->pPars->nGateSize > 0 ) pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); else pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG ); @@ -445,12 +445,22 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t return pNodeNew; assert( pIfObj->Type == IF_AND ); // get the parameters of the best cut + pCutBest = If_ObjCutBest( pIfObj ); + if ( pIfMan->pPars->fUserSesLib ) + { + // create the subgraph composed of Abc_Obj_t nodes based on the given cut + Abc_Obj_t * pFanins[IF_MAX_FUNC_LUTSIZE]; + If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) + pFanins[i] = Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover); + pNodeNew = Abc_ExactBuildNode( If_CutTruthW(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), If_CutArrTimeProfile(pIfMan, pCutBest), pFanins, pNtkNew ); + If_ObjSetCopy( pIfObj, pNodeNew ); + return pNodeNew; + } // create a new node pNodeNew = Abc_NtkCreateNode( pNtkNew ); - pCutBest = If_ObjCutBest( pIfObj ); -// printf( "%d 0x%02X %d\n", pCutBest->nLeaves, 0xff & *If_CutTruth(pCutBest), pIfMan->pPars->pFuncCost(pCutBest) ); // if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays ) - if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->nGateSize ) + if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm && + !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize ) If_CutRotatePins( pIfMan, pCutBest ); if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) { diff --git a/src/base/abci/abcMini.c b/src/base/abci/abcMini.c index bd893b5b..876f4c8c 100644 --- a/src/base/abci/abcMini.c +++ b/src/base/abci/abcMini.c @@ -205,7 +205,7 @@ void Abc_NtkMiniAigTest( Abc_Ntk_t * pNtk ) p = Abc_NtkToMiniAig( pNtk ); pNtkNew = Abc_NtkFromMiniAig( p ); Mini_AigStop( p ); - Abc_NtkPrintStats( pNtkNew, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + Abc_NtkPrintStats( pNtkNew, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); Abc_NtkDelete( pNtkNew ); // test dumping diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index 40ce38b4..2129782f 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -235,7 +235,7 @@ float Abc_NtkGetArea( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fPrintMem ) +void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fSkipSmall, int fPrintMem ) { int nSingles = fSkipBuf ? Abc_NtkGetBufNum(pNtk) : 0; if ( fPrintMuxes && Abc_NtkIsStrash(pNtk) ) @@ -283,7 +283,7 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum if ( Abc_NtkIsNetlist(pNtk) ) { Abc_Print( 1," net =%5d", Abc_NtkNetNum(pNtk) ); - Abc_Print( 1," nd =%5d", Abc_NtkNodeNum(pNtk) - nSingles ); + Abc_Print( 1," nd =%5d", fSkipSmall ? Abc_NtkGetLargeNodeNum(pNtk) : Abc_NtkNodeNum(pNtk) - nSingles ); Abc_Print( 1," wbox =%3d", Abc_NtkWhiteboxNum(pNtk) ); Abc_Print( 1," bbox =%3d", Abc_NtkBlackboxNum(pNtk) ); } @@ -295,7 +295,7 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum } else { - Abc_Print( 1," nd =%6d", Abc_NtkNodeNum(pNtk) - nSingles ); + Abc_Print( 1," nd =%6d", fSkipSmall ? Abc_NtkGetLargeNodeNum(pNtk) : Abc_NtkNodeNum(pNtk) - nSingles ); Abc_Print( 1," edge =%7d", Abc_NtkGetTotalFanins(pNtk) - nSingles ); } @@ -455,7 +455,7 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum fflush( stdout ); if ( pNtk->pExdc ) - Abc_NtkPrintStats( pNtk->pExdc, fFactored, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fPrintMem ); + Abc_NtkPrintStats( pNtk->pExdc, fFactored, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fSkipSmall, fPrintMem ); } /**Function************************************************************* diff --git a/src/base/abci/module.make b/src/base/abci/module.make index a3c343ee..b97f526f 100644 --- a/src/base/abci/module.make +++ b/src/base/abci/module.make @@ -15,7 +15,9 @@ SRC += src/base/abci/abc.c \ src/base/abci/abcDetect.c \ src/base/abci/abcDress.c \ src/base/abci/abcDress2.c \ + src/base/abci/abcDress3.c \ src/base/abci/abcDsd.c \ + src/base/abci/abcExact.c \ src/base/abci/abcExtract.c \ src/base/abci/abcFraig.c \ src/base/abci/abcFx.c \ diff --git a/src/base/io/ioReadBench.c b/src/base/io/ioReadBench.c index 4fb21ad1..4d038200 100644 --- a/src/base/io/ioReadBench.c +++ b/src/base/io/ioReadBench.c @@ -94,6 +94,7 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) // allocate the empty network pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); + pNtk->nConstrs = 0; // go through the lines of the file vString = Vec_StrAlloc( 100 ); @@ -140,6 +141,7 @@ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) pTerm = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pTerm, pNet ); } + pNtk->nConstrs++; } else { diff --git a/src/base/io/ioReadPlaMo.c b/src/base/io/ioReadPlaMo.c index 1cd453d2..d190d30a 100644 --- a/src/base/io/ioReadPlaMo.c +++ b/src/base/io/ioReadPlaMo.c @@ -297,6 +297,32 @@ static inline void Mop_ManRemoveEmpty( Mop_Man_t * p ) /**Function************************************************************* + Synopsis [Count how many times each variable appears in the input parts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Mop_ManCollectStats( Mop_Man_t * p ) +{ + int i, v, iCube, nVars = 32 * p->nWordsIn; + Vec_Int_t * vStats = Vec_IntStart( nVars ); + Vec_IntForEachEntry( p->vCubes, iCube, i ) + { + word * pCube = Mop_ManCubeIn(p, iCube); + int nOutLits = Mop_ManCountOnes( Mop_ManCubeOut(p, iCube), p->nWordsOut ); + for ( v = 0; v < nVars; v++ ) + if ( Abc_TtGetQua(pCube, v) ) + Vec_IntAddToEntry( vStats, v, nOutLits ); + } + return vStats; +} + +/**Function************************************************************* + Synopsis [] Description [] @@ -306,6 +332,20 @@ static inline void Mop_ManRemoveEmpty( Mop_Man_t * p ) SeeAlso [] ***********************************************************************/ +// knowing that cubes are distance-1, find the different input variable +static inline int Mop_ManFindDiffVar( word * pCube1, word * pCube2, int nWords ) +{ + int w, i; + for ( w = 0; w < nWords; w++ ) + { + word Xor = pCube1[w] ^ pCube2[w]; + for ( i = 0; i < 32; i++ ) + if ( (Xor >> (i << 1)) & 0x3 ) + return w * 32 + i; + } + assert( 0 ); + return -1; +} // check containment of input parts of two cubes static inline int Mop_ManCheckDist1( word * pCube1, word * pCube2, int nWords ) { @@ -439,21 +479,30 @@ Vec_Int_t * Mop_ManFindDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup ) return vPairs; } // merge distance-1 with identical output part -int Mop_ManMergeDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGroupPrev ) +int Mop_ManMergeDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGroupPrev, Vec_Int_t * vStats, int nLimit ) { Vec_Int_t * vPairs = Mop_ManFindDist1Pairs( p, vGroup ); Vec_Int_t * vPairsNew = Mop_ManCompatiblePairs( vPairs, Vec_IntSize(vGroup) ); - int w, i, c1, c2, nCubes = Vec_IntSize(vGroup) + Vec_IntSize(vGroupPrev); + int nCubes = Vec_IntSize(vGroup) + Vec_IntSize(vGroupPrev); + int w, i, c1, c2, iCubeNew, iVar; // move cubes to the previous group + word * pCube, * pCube1, * pCube2; + Vec_Int_t * vToFree = Vec_IntAlloc( Vec_IntSize(vPairsNew) ); Vec_IntForEachEntryDouble( vPairsNew, c1, c2, i ) { - int iCubeNew = Vec_IntPop( p->vFree ); + pCube1 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c1) ); + pCube2 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c2) ); + assert( Mop_ManCheckDist1(pCube1, pCube2, p->nWordsIn) ); - word * pCube = Mop_ManCubeIn( p, iCubeNew ); - word * pCube1 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c1) ); - word * pCube2 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c2) ); + // skip those cubes that have frequently appearing variables + iVar = Mop_ManFindDiffVar( pCube1, pCube2, p->nWordsIn ); + if ( Vec_IntEntry( vStats, iVar ) > nLimit ) + continue; + Vec_IntPush( vToFree, c1 ); + Vec_IntPush( vToFree, c2 ); - assert( Mop_ManCheckDist1(pCube1, pCube2, p->nWordsIn) ); + iCubeNew = Vec_IntPop( p->vFree ); + pCube = Mop_ManCubeIn( p, iCubeNew ); for ( w = 0; w < p->nWordsIn; w++ ) pCube[w] = pCube1[w] & pCube2[w]; @@ -467,13 +516,15 @@ int Mop_ManMergeDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGrou Vec_IntPush( vGroupPrev, iCubeNew ); } - Vec_IntForEachEntry( vPairsNew, c1, i ) +// Vec_IntForEachEntry( vPairsNew, c1, i ) + Vec_IntForEachEntry( vToFree, c1, i ) { if ( Vec_IntEntry(vGroup, c1) == -1 ) continue; Vec_IntPush( p->vFree, Vec_IntEntry(vGroup, c1) ); Vec_IntWriteEntry( vGroup, c1, -1 ); } + Vec_IntFree( vToFree ); if ( Vec_IntSize(vPairsNew) > 0 ) Map_ManGroupCompact( vGroup ); Vec_IntFree( vPairs ); @@ -529,7 +580,7 @@ int Mop_ManMergeDist1Pairs2( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGro Map_ManGroupCompact( vGroup ); return Count; } -int Mop_ManMergeDist1All( Mop_Man_t * p, Vec_Wec_t * vGroups ) +int Mop_ManMergeDist1All( Mop_Man_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vStats, int nLimit ) { Vec_Int_t * vGroup; int i, nEqual, nReduce, Count = 0; @@ -544,7 +595,7 @@ int Mop_ManMergeDist1All( Mop_Man_t * p, Vec_Wec_t * vGroups ) return -1; } nEqual = Mop_ManRemoveIdentical( p, vGroup ); - nReduce = Mop_ManMergeDist1Pairs( p, vGroup, Vec_WecEntry(vGroups, i-1) ); + nReduce = Mop_ManMergeDist1Pairs( p, vGroup, Vec_WecEntry(vGroups, i-1), vStats, nLimit ); //Mop_ManMergeDist1Pairs2( p, vGroup, Vec_WecEntry(vGroups, i-1) ); Count += nEqual + nReduce; //printf( "Group %3d : Equal =%5d. Reduce =%5d.\n", i, nEqual, nReduce ); @@ -599,16 +650,20 @@ void Mop_ManReduce2( Mop_Man_t * p ) { abctime clk = Abc_Clock(); int nCubes = Vec_IntSize(p->vCubes); + Vec_Int_t * vStats = Mop_ManCollectStats( p ); Vec_Wec_t * vGroups = Mop_ManCreateGroups( p ); + int nLimit = ABC_INFINITY; // 5 * Vec_IntSum(vStats) / Vec_IntSize(vStats) + 1; int nOutLits = Mop_ManCountOutputLits( p ); int Count1 = Mop_ManMergeContainAll( p, vGroups ); - int Count2 = Mop_ManMergeDist1All( p, vGroups ); + int Count2 = Mop_ManMergeDist1All( p, vGroups, vStats, nLimit ); int Count3 = Mop_ManMergeContainAll( p, vGroups ); - int Count4 = Mop_ManMergeDist1All( p, vGroups ); + int Count4 = Mop_ManMergeDist1All( p, vGroups, vStats, nLimit ); int Count5 = Mop_ManMergeContainAll( p, vGroups ); int Removed = Mop_ManUnCreateGroups( p, vGroups ); int nOutLits2 = Mop_ManCountOutputLits( p ); Vec_WecFree( vGroups ); +//Vec_IntPrint( vStats ); + Vec_IntFree( vStats ); assert( Removed == Count1 + Count2 + Count3 ); // report printf( "Cubes: %d -> %d. C = %d. M = %d. C = %d. M = %d. C = %d. Output lits: %d -> %d. ", diff --git a/src/base/wlc/wlc.h b/src/base/wlc/wlc.h index 51152fa8..bb5c4bfe 100644 --- a/src/base/wlc/wlc.h +++ b/src/base/wlc/wlc.h @@ -259,7 +259,7 @@ extern Vec_Int_t * Wlc_NtkFindUifableMultiplierPairs( Wlc_Ntk_t * p ); extern Wlc_Ntk_t * Wlc_NtkAbstractNodes( Wlc_Ntk_t * pNtk, Vec_Int_t * vNodes ); extern Wlc_Ntk_t * Wlc_NtkUifNodePairs( Wlc_Ntk_t * pNtk, Vec_Int_t * vPairs ); /*=== wlcBlast.c ========================================================*/ -extern Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int fGiaSimple, int fAddOutputs ); +extern Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int iOutput, int nRange, int fGiaSimple, int fAddOutputs, int fBooth ); /*=== wlcCom.c ========================================================*/ extern void Wlc_SetNtk( Abc_Frame_t * pAbc, Wlc_Ntk_t * pNtk ); /*=== wlcNtk.c ========================================================*/ diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c index 79ad3659..c86c7cf0 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -143,16 +143,19 @@ void Wlc_BlastShiftRightInt( Gia_Man_t * pNew, int * pNum, int nNum, int * pShif void Wlc_BlastShiftRight( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, int fSticky, Vec_Int_t * vRes ) { int nShiftMax = Abc_Base2Log(nNum); + int * pShiftNew = ABC_ALLOC( int, nShift ); + memcpy( pShiftNew, pShift, sizeof(int)*nShift ); if ( nShiftMax < nShift ) { - int i, iRes = pShift[nShiftMax]; + int i, iRes = pShiftNew[nShiftMax]; for ( i = nShiftMax + 1; i < nShift; i++ ) - iRes = Gia_ManHashOr( pNew, iRes, pShift[i] ); - pShift[nShiftMax++] = iRes; + iRes = Gia_ManHashOr( pNew, iRes, pShiftNew[i] ); + pShiftNew[nShiftMax++] = iRes; } else nShiftMax = nShift; - Wlc_BlastShiftRightInt( pNew, pNum, nNum, pShift, nShiftMax, fSticky, vRes ); + Wlc_BlastShiftRightInt( pNew, pNum, nNum, pShiftNew, nShiftMax, fSticky, vRes ); + ABC_FREE( pShiftNew ); } void Wlc_BlastShiftLeftInt( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, int fSticky, Vec_Int_t * vRes ) { @@ -176,16 +179,19 @@ void Wlc_BlastShiftLeftInt( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift void Wlc_BlastShiftLeft( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, int fSticky, Vec_Int_t * vRes ) { int nShiftMax = Abc_Base2Log(nNum); + int * pShiftNew = ABC_ALLOC( int, nShift ); + memcpy( pShiftNew, pShift, sizeof(int)*nShift ); if ( nShiftMax < nShift ) { - int i, iRes = pShift[nShiftMax]; + int i, iRes = pShiftNew[nShiftMax]; for ( i = nShiftMax + 1; i < nShift; i++ ) - iRes = Gia_ManHashOr( pNew, iRes, pShift[i] ); - pShift[nShiftMax++] = iRes; + iRes = Gia_ManHashOr( pNew, iRes, pShiftNew[i] ); + pShiftNew[nShiftMax++] = iRes; } else nShiftMax = nShift; - Wlc_BlastShiftLeftInt( pNew, pNum, nNum, pShift, nShiftMax, fSticky, vRes ); + Wlc_BlastShiftLeftInt( pNew, pNum, nNum, pShiftNew, nShiftMax, fSticky, vRes ); + ABC_FREE( pShiftNew ); } void Wlc_BlastRotateRight( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, Vec_Int_t * vRes ) { @@ -674,6 +680,7 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL Vec_IntPush( vProd, 0 ); assert( Vec_IntSize(vProd) == 2 ); } +// Vec_WecPrint( vProds, 0 ); vLevel = Vec_WecEntry( vLevels, 0 ); Vec_IntClear( vRes ); @@ -684,7 +691,9 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL Vec_IntPush( vRes, Vec_IntEntry(vProd, 0) ); Vec_IntPush( vLevel, Vec_IntEntry(vProd, 1) ); } - Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), nSize ); + Vec_IntPush( vRes, 0 ); + Vec_IntPush( vLevel, 0 ); + Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), Vec_IntSize(vRes) ); } void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes ) { @@ -728,6 +737,81 @@ void Wlc_BlastSquare( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, Vec_WecFree( vProds ); Vec_WecFree( vLevels ); } +void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned ) +{ + Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB + 3 ); + Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB + 3 ); + int FillA = fSigned ? pArgA[nArgA-1] : 0; + int FillB = fSigned ? pArgB[nArgB-1] : 0; + int i, k, Sign; + // create new arguments + Vec_Int_t * vArgB = Vec_IntAlloc( nArgB + 3 ); + Vec_IntPush( vArgB, 0 ); + for ( i = 0; i < nArgB; i++ ) + Vec_IntPush( vArgB, pArgB[i] ); + Vec_IntPush( vArgB, FillB ); + if ( Vec_IntSize(vArgB) % 2 == 0 ) + Vec_IntPush( vArgB, FillB ); + assert( Vec_IntSize(vArgB) % 2 == 1 ); + // iterate through bit-pairs + for ( k = 0; k+2 < Vec_IntSize(vArgB); k+=2 ) + { + int pp = -1; + int Q2jM1 = Vec_IntEntry(vArgB, k); // q(2*j-1) + int Q2j = Vec_IntEntry(vArgB, k+1); // q(2*j+0) + int Q2jP1 = Vec_IntEntry(vArgB, k+2); // q(2*j+1) + int Neg = Q2jP1; + int One = Gia_ManHashXor( pNew, Q2j, Q2jM1 ); + int Two = Gia_ManHashMux( pNew, Neg, Gia_ManHashAnd(pNew, Abc_LitNot(Q2j), Abc_LitNot(Q2jM1)), Gia_ManHashAnd(pNew, Q2j, Q2jM1) ); + for ( i = 0; i <= nArgA; i++ ) + { + int This = i == nArgA ? FillA : pArgA[i]; + int Prev = i ? pArgA[i-1] : 0; + int Part = Gia_ManHashOr( pNew, Gia_ManHashAnd(pNew, One, This), Gia_ManHashAnd(pNew, Two, Prev) ); + + pp = Gia_ManHashXor( pNew, Part, Neg ); + + if ( pp == 0 ) + continue; + Vec_WecPush( vProds, k+i, pp ); + Vec_WecPush( vLevels, k+i, 0 ); + } + // perform sign extension + Sign = fSigned ? pp : Neg; + if ( k == 0 ) + { + Vec_WecPush( vProds, k+i, Sign ); + Vec_WecPush( vLevels, k+i, 0 ); + + Vec_WecPush( vProds, k+i+1, Sign ); + Vec_WecPush( vLevels, k+i+1, 0 ); + + Vec_WecPush( vProds, k+i+2, Abc_LitNot(Sign) ); + Vec_WecPush( vLevels, k+i+2, 0 ); + } + else + { + Vec_WecPush( vProds, k+i, Abc_LitNot(Sign) ); + Vec_WecPush( vLevels, k+i, 0 ); + + Vec_WecPush( vProds, k+i+1, 1 ); + Vec_WecPush( vLevels, k+i+1, 0 ); + } + // add neg to the first column + if ( Neg == 0 ) + continue; + Vec_WecPush( vProds, k, Neg ); + Vec_WecPush( vLevels, k, 0 ); + } + //Vec_WecPrint( vProds, 0 ); + + Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes ); + + Vec_WecFree( vProds ); + Vec_WecFree( vLevels ); + Vec_IntFree( vArgB ); +} + /**Function************************************************************* @@ -740,7 +824,7 @@ void Wlc_BlastSquare( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, SeeAlso [] ***********************************************************************/ -Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int fGiaSimple, int fAddOutputs ) +Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int iOutput, int nOutputRange, int fGiaSimple, int fAddOutputs, int fBooth ) { int fVerbose = 0; int fUseOldMultiplierBlasting = 0; @@ -1149,9 +1233,12 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int fGiaSimple, int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, fSigned ); if ( Wlc_NtkCountConstBits(pArg0, nRangeMax) < Wlc_NtkCountConstBits(pArg1, nRangeMax) ) ABC_SWAP( int *, pArg0, pArg1 ); - Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned ); + if ( fBooth ) + Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned ); + else + Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned ); //Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes ); - if ( nRange > nRangeMax + nRangeMax ) + if ( nRange > Vec_IntSize(vRes) ) Vec_IntFillExtra( vRes, nRange, fSigned ? Vec_IntEntryLast(vRes) : 0 ); else Vec_IntShrink( vRes, nRange ); @@ -1233,6 +1320,9 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int fGiaSimple, // create COs Wlc_NtkForEachCo( p, pObj, i ) { + // skip all outputs except the given ones + if ( iOutput >= 0 && (i < iOutput || i >= iOutput + nOutputRange) ) + continue; // create additional PO literals if ( vAddOutputs && pObj->fIsFi ) { diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c index 77bf36ba..2c504127 100644 --- a/src/base/wlc/wlcCom.c +++ b/src/base/wlc/wlcCom.c @@ -128,10 +128,10 @@ int Abc_CommandReadWlc( Abc_Frame_t * pAbc, int argc, char ** argv ) switch ( c ) { case 'o': - fPrintTree ^= 1; + fOldParser ^= 1; break; case 'p': - fOldParser ^= 1; + fPrintTree ^= 1; break; case 'v': fVerbose ^= 1; @@ -338,12 +338,34 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); Vec_Int_t * vBoxIds = NULL; Gia_Man_t * pNew = NULL; - int c, fGiaSimple = 0, fAddOutputs = 0, fMulti = 0, fVerbose = 0; + int c, iOutput = -1, nOutputRange = 2, fGiaSimple = 0, fAddOutputs = 0, fMulti = 0, fBooth = 0, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "comvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ORcombvh" ) ) != EOF ) { switch ( c ) { + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + iOutput = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iOutput < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nOutputRange = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nOutputRange < 0 ) + goto usage; + break; case 'c': fGiaSimple ^= 1; break; @@ -353,6 +375,9 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fMulti ^= 1; break; + case 'b': + fBooth ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -373,8 +398,13 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( vBoxIds == NULL ) Abc_Print( 1, "Warning: There is no multipliers in the design.\n" ); } + if ( iOutput >= 0 && iOutput + nOutputRange > Wlc_NtkPoNum(pNtk) ) + { + Abc_Print( 1, "Abc_CommandBlast(): The output range [%d:%d] is incorrect.\n", iOutput, iOutput + nOutputRange - 1 ); + return 0; + } // transform - pNew = Wlc_NtkBitBlast( pNtk, vBoxIds, fGiaSimple, fAddOutputs ); + pNew = Wlc_NtkBitBlast( pNtk, vBoxIds, iOutput, nOutputRange, fGiaSimple, fAddOutputs, fBooth ); Vec_IntFreeP( &vBoxIds ); if ( pNew == NULL ) { @@ -384,11 +414,14 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: - Abc_Print( -2, "usage: %%blast [-comvh]\n" ); + Abc_Print( -2, "usage: %%blast [-OR num] [-combvh]\n" ); Abc_Print( -2, "\t performs bit-blasting of the word-level design\n" ); + Abc_Print( -2, "\t-O num : zero-based index of the first word-level PO to bit-blast [default = %d]\n", iOutput ); + Abc_Print( -2, "\t-R num : the total number of word-level POs to bit-blast [default = %d]\n", nOutputRange ); Abc_Print( -2, "\t-c : toggle using AIG w/o const propagation and strashing [default = %s]\n", fGiaSimple? "yes": "no" ); Abc_Print( -2, "\t-o : toggle using additional POs on the word-level boundaries [default = %s]\n", fAddOutputs? "yes": "no" ); Abc_Print( -2, "\t-m : toggle creating boxes for all multipliers in the design [default = %s]\n", fMulti? "yes": "no" ); + Abc_Print( -2, "\t-b : toggle generating radix-4 Booth multipliers [default = %s]\n", fBooth? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; diff --git a/src/base/wlc/wlcReadSmt.c b/src/base/wlc/wlcReadSmt.c index ed6092a5..fcd47274 100644 --- a/src/base/wlc/wlcReadSmt.c +++ b/src/base/wlc/wlcReadSmt.c @@ -276,13 +276,9 @@ static inline int Smt_PrsCreateNode( Wlc_Ntk_t * pNtk, int Type, int fSigned, in assert( fSigned >= 0 ); Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), vFanins ); if ( fSigned ) - { Wlc_NtkObj(pNtk, iObj)->Signed = fSigned; -// if ( Vec_IntSize(vFanins) > 0 ) -// Wlc_NtkObj(pNtk, Vec_IntEntry(vFanins, 0))->Signed = fSigned; -// if ( Vec_IntSize(vFanins) > 1 ) -// Wlc_NtkObj(pNtk, Vec_IntEntry(vFanins, 1))->Signed = fSigned; - } + if ( Type == WLC_OBJ_SHIFT_RA ) + Wlc_NtkObj(pNtk, iObj)->Signed = 1; if ( pName == NULL ) { sprintf( Buffer, "_n%d_", iObj ); @@ -511,6 +507,13 @@ Wlc_Ntk_t * Smt_PrsBuild( Smt_Prs_t * p ) // skip () Fan = Vec_IntEntry(vFans, 2); assert( !Smt_EntryIsName(Fan) ); + vFans2 = Smt_VecEntryNode(p, vFans, 2); + if ( Vec_IntSize(vFans2) > 0 ) + { + printf( "File parsing error: Uninterpreted functions are not supported.\n" ); + Wlc_NtkFree( pNtk ); pNtk = NULL; + goto finish; + } // check type (Bool or BitVec) Fan = Vec_IntEntry(vFans, 3); if ( Smt_EntryIsName(Fan) ) @@ -921,6 +924,13 @@ Wlc_Ntk_t * Smt_PrsBuild2( Smt_Prs_t * p ) // skip () Fan = Vec_IntEntry(vFans, 2); assert( !Smt_EntryIsName(Fan) ); + vFans2 = Smt_VecEntryNode(p, vFans, 2); + if ( Vec_IntSize(vFans2) > 0 ) + { + printf( "File parsing error: Uninterpreted functions are not supported.\n" ); + Wlc_NtkFree( pNtk ); pNtk = NULL; + goto finish; + } // check type (Bool or BitVec) Fan = Vec_IntEntry(vFans, 3); if ( Smt_EntryIsName(Fan) ) diff --git a/src/base/wlc/wlcReadVer.c b/src/base/wlc/wlcReadVer.c index 824cf80b..08dc8e98 100644 --- a/src/base/wlc/wlcReadVer.c +++ b/src/base/wlc/wlcReadVer.c @@ -1265,10 +1265,10 @@ Wlc_Ntk_t * Wlc_ReadVer( char * pFileName ) // derive topological order pNtk = Wlc_NtkDupDfs( p->pNtk ); Wlc_NtkTransferNames( pNtk, p->pNtk ); + pNtk->pSpec = Abc_UtilStrsav( pFileName ); finish: Wlc_PrsPrintErrorMessage( p ); Wlc_PrsStop( p ); - pNtk->pSpec = Abc_UtilStrsav( pFileName ); return pNtk; } @@ -1291,7 +1291,7 @@ void Io_ReadWordTest( char * pFileName ) return; Wlc_WriteVer( pNtk, "test.v", 0, 0 ); - pNew = Wlc_NtkBitBlast( pNtk, NULL, 0, 0 ); + pNew = Wlc_NtkBitBlast( pNtk, NULL, -1, 0, 0, 0, 0 ); Gia_AigerWrite( pNew, "test.aig", 0, 0 ); Gia_ManStop( pNew ); diff --git a/src/base/wlc/wlcSim.c b/src/base/wlc/wlcSim.c index 73d5307f..20ac8c61 100644 --- a/src/base/wlc/wlcSim.c +++ b/src/base/wlc/wlcSim.c @@ -129,7 +129,7 @@ Vec_Ptr_t * Wlc_NtkSimulate( Wlc_Ntk_t * p, Vec_Int_t * vNodes, int nWords, int { Gia_Obj_t * pObj; Vec_Ptr_t * vOne, * vRes; - Gia_Man_t * pGia = Wlc_NtkBitBlast( p, NULL, 0, 0 ); + Gia_Man_t * pGia = Wlc_NtkBitBlast( p, NULL, -1, 0, 0, 0, 0 ); Wlc_Obj_t * pWlcObj; int f, i, k, w, nBits, Counter = 0; // allocate simulation info for one timeframe |