diff --git a/.gitignore b/.gitignore index cdf34f18d1..9bd049424a 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ src/aig/ddb/ *.plg *.zip +*.DS_Store abcspaceext.dsw abcext.dsp diff --git a/Makefile b/Makefile index dc909bb632..9b4838ce8d 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ MODULES := \ src/misc/vec src/misc/hash src/misc/tim src/misc/bzlib src/misc/zlib \ src/misc/mem src/misc/bar src/misc/bbl src/misc/parse \ src/opt/cut src/opt/fxu src/opt/fxch src/opt/rwr src/opt/mfs src/opt/sim \ - src/opt/ret src/opt/fret src/opt/res src/opt/lpk src/opt/nwk src/opt/rwt \ + src/opt/ret src/opt/fret src/opt/res src/opt/lpk src/opt/nwk src/opt/rwt src/opt/rar \ src/opt/cgt src/opt/csw src/opt/dar src/opt/dau src/opt/dsc src/opt/sfm src/opt/sbd \ src/sat/bsat src/sat/xsat src/sat/satoko src/sat/csat src/sat/msat src/sat/psat src/sat/cnf src/sat/bmc src/sat/glucose src/sat/glucose2 \ src/bool/bdc src/bool/deco src/bool/dec src/bool/kit src/bool/lucky \ diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 911f682456..ac178258f2 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -295,6 +295,7 @@ static int Abc_CommandAttach ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandSuperChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSuperChoiceLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTimeScale ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRewire ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandFpgaFast ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -523,6 +524,7 @@ static int Abc_CommandAbc9Ttopt ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Transduction ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9TranStoch ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Rrr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Rewire ( Abc_Frame_t * pAbc, int argc, char ** argv ); //#endif static int Abc_CommandAbc9LNetMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Unmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -1099,6 +1101,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "SC mapping", "superc", Abc_CommandSuperChoice, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "supercl", Abc_CommandSuperChoiceLut, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "timescale", Abc_CommandTimeScale, 0 ); + Cmd_CommandAdd( pAbc, "SC mapping", "rewire", Abc_CommandRewire, 1 ); // Cmd_CommandAdd( pAbc, "FPGA mapping", "fpga", Abc_CommandFpga, 1 ); // Cmd_CommandAdd( pAbc, "FPGA mapping", "ffpga", Abc_CommandFpgaFast, 1 ); @@ -1328,6 +1331,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&transduction", Abc_CommandAbc9Transduction, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&transtoch" , Abc_CommandAbc9TranStoch, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&rrr", Abc_CommandAbc9Rrr, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&rewire" , Abc_CommandAbc9Rewire, 0 ); //#endif Cmd_CommandAdd( pAbc, "ABC9", "&lnetmap", Abc_CommandAbc9LNetMap, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&unmap", Abc_CommandAbc9Unmap, 0 ); @@ -20402,6 +20406,162 @@ int Abc_CommandTimeScale( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRewire( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose); + Abc_Ntk_t *pNtk, *pTemp; + int c, nIters = 100000, nExpands = 128, nGrowth = 4, nDivs = -1, nFaninMax = 8, nSeed = 1, nTimeOut = 0, nVerbose = 1, nMode = 0, nDist = 0; + Extra_UtilGetoptReset(); + // Cmd_CommandExecute + + pNtk = Abc_FrameReadNtk(pAbc); + + while ( ( c = Extra_UtilGetopt( argc, argv, "IEGDFSTMLVh" ) ) != EOF ) { + switch ( c ) { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'E': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-E\" should be followed by a positive integer.\n" ); + goto usage; + } + nExpands = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'G': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer.\n" ); + goto usage; + } + nGrowth = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); + goto usage; + } + nDivs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a positive integer.\n" ); + goto usage; + } + nFaninMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by a positive integer.\n" ); + goto usage; + } + nSeed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by a positive integer.\n" ); + goto usage; + } + nTimeOut = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" ); + goto usage; + } + nMode = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a positive integer.\n" ); + goto usage; + } + nDist = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'V': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-V\" should be followed by a positive integer.\n" ); + goto usage; + } + nVerbose = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'h': + default: + goto usage; + } + } + if ( argc > globalUtilOptind + 1 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( nMode == 1 && Abc_FrameReadLibGen2() == NULL ) + { + Abc_Print( -1, "Library is not available.\n" ); + return 1; + } + + pTemp = Abc_ManRewire( pNtk, nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, nSeed, nVerbose ); + Abc_FrameReplaceCurrentNetwork( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: rewrire [-IEGDFSTV ]\n" ); + Abc_Print( -2, "\t performs AIG re-wiring\n" ); + Abc_Print( -2, "\t-I : the number of iterations [default = %d]\n", nIters ); + Abc_Print( -2, "\t-E : the number of fanins to add to all nodes [default = %d]\n", nExpands ); + Abc_Print( -2, "\t-G : the number of fanins to add to one node [default = %d]\n", nGrowth ); + Abc_Print( -2, "\t-D : the number of shared divisors to extract [default = %d]\n", nDivs ); + Abc_Print( -2, "\t-F : the limit on the fanin count at a node [default = %d]\n", nFaninMax); + Abc_Print( -2, "\t-L : localization distances [default = %d]\n", nDist); + Abc_Print( -2, "\t-M : optimization target [default = %s]\n", nMode ? "transistor" : "node" ); + Abc_Print( -2, "\t-S : the random seed [default = %d]\n", nSeed ); + Abc_Print( -2, "\t-T : the timeout in seconds [default = unused]\n" ); + Abc_Print( -2, "\t-V : the verbosity level [default = %d]\n", nVerbose ); + Abc_Print( -2, "\t-h : prints the command usage\n" ); + Abc_Print( -2, "\t\n" ); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -45391,6 +45551,159 @@ int Abc_CommandAbc9Rrr( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Rewire( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose); + Gia_Man_t *pTemp; + int c, nIters = 100000, nExpands = 128, nGrowth = 4, nDivs = -1, nFaninMax = 8, nSeed = 1, nTimeOut = 0, nVerbose = 1, nMode = 0, nDist = 0; + Extra_UtilGetoptReset(); + // Cmd_CommandExecute + while ( ( c = Extra_UtilGetopt( argc, argv, "IEGDFSTMLVh" ) ) != EOF ) { + switch ( c ) { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'E': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-E\" should be followed by a positive integer.\n" ); + goto usage; + } + nExpands = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'G': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer.\n" ); + goto usage; + } + nGrowth = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); + goto usage; + } + nDivs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a positive integer.\n" ); + goto usage; + } + nFaninMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by a positive integer.\n" ); + goto usage; + } + nSeed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by a positive integer.\n" ); + goto usage; + } + nTimeOut = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" ); + goto usage; + } + nMode = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a positive integer.\n" ); + goto usage; + } + nDist = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'V': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-V\" should be followed by a positive integer.\n" ); + goto usage; + } + nVerbose = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'h': + default: + goto usage; + } + } + if ( argc > globalUtilOptind + 1 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + if ( nMode == 1 && Abc_FrameReadLibGen2() == NULL ) + { + Abc_Print( -1, "Library is not available.\n" ); + return 1; + } + + pTemp = Gia_ManRewire( pAbc->pGia, nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, nSeed, nVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &rewrire [-IEGDFSTV ]\n" ); + Abc_Print( -2, "\t performs AIG re-wiring\n" ); + Abc_Print( -2, "\t-I : the number of iterations [default = %d]\n", nIters ); + Abc_Print( -2, "\t-E : the number of fanins to add to all nodes [default = %d]\n", nExpands ); + Abc_Print( -2, "\t-G : the number of fanins to add to one node [default = %d]\n", nGrowth ); + Abc_Print( -2, "\t-D : the number of shared divisors to extract [default = %d]\n", nDivs ); + Abc_Print( -2, "\t-F : the limit on the fanin count at a node [default = %d]\n", nFaninMax); + Abc_Print( -2, "\t-L : localization distances [default = %d]\n", nDist); + Abc_Print( -2, "\t-M : optimization target [default = %s]\n", nMode ? "transistor" : "node" ); + Abc_Print( -2, "\t-S : the random seed [default = %d]\n", nSeed ); + Abc_Print( -2, "\t-T : the timeout in seconds [default = unused]\n" ); + Abc_Print( -2, "\t-V : the verbosity level [default = %d]\n", nVerbose ); + Abc_Print( -2, "\t-h : prints the command usage\n" ); + Abc_Print( -2, "\t\n" ); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c index 07b685eea9..b08962e509 100644 --- a/src/base/abci/abcMap.c +++ b/src/base/abci/abcMap.c @@ -884,6 +884,73 @@ Vec_Int_t * Abc_NtkWriteMiniMapping( Abc_Ntk_t * pNtk ) return vMapping; } +/**Function************************************************************* + + Synopsis [Build mapped network from the mini-mapped format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromMiniMapping( int *pArray ) +{ + if ( !pArray ) { + printf("Mapping is not available.\n"); + return NULL; + } + Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); + if ( !pLib ) { + printf("Library is not available.\n"); + return NULL; + } + Abc_Ntk_t *pNtkMapped = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_MAP, 1 ); + pNtkMapped->pName = Extra_UtilStrsav( "mapped" ); + int nCis, nCos, nNodes, nFlops; + int i, k, nLeaves, Pos = 4; + char * pBuffer, * pName; + Mio_Gate_t *pGate; + nCis = pArray[0]; + nCos = pArray[1]; + nNodes = pArray[2]; + nFlops = pArray[3]; + // create pi + for ( i = 0; i < nCis; i++ ) + Abc_NtkCreatePi( pNtkMapped ); + // create nodes + for ( i = 0; i < nNodes; i++ ) + Abc_NtkCreateNode( pNtkMapped ); + // create po + for ( i = 0; i < nCos; i++ ) + Abc_NtkCreatePo( pNtkMapped ); + // connect nodes + for ( i = 0; i < nNodes; i++ ) + { + nLeaves = pArray[Pos++]; + for ( k = 0; k < nLeaves; k++ ) + Abc_ObjAddFanin( Abc_NtkObj( pNtkMapped, nCis + i + 1 ), Abc_NtkObj( pNtkMapped, pArray[Pos++] + 1 ) ); + } + for ( i = 0; i < nCos; i++ ) + Abc_ObjAddFanin( Abc_NtkCo( pNtkMapped, i ), Abc_NtkObj( pNtkMapped, pArray[Pos++] + 1 ) ); + + pBuffer = (char *)(pArray + Pos); + for ( i = 0; i < nNodes; i++ ) + { + pName = pBuffer; + pBuffer += strlen(pName) + 1; + pGate = Mio_LibraryReadGateByName( pLib, pName, NULL ); + Abc_NtkObj( pNtkMapped, nCis + i + 1 )->pData = pGate; + } + Abc_NtkAddDummyPiNames( pNtkMapped ); + Abc_NtkAddDummyPoNames( pNtkMapped ); + if ( !Abc_NtkCheck( pNtkMapped ) ) + fprintf( stdout, "Abc_NtkFromMiniMapping(): Network check has failed.\n" ); + + return pNtkMapped; +} + /**Function************************************************************* Synopsis [Prints mapped network represented in mini-mapped format.] @@ -925,6 +992,26 @@ void Abc_NtkPrintMiniMapping( int * pArray ) } } +/**Function************************************************************* + + Synopsis [Procedures to update internal ABC network using mini-mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkInputMiniMapping( Abc_Frame_t * pAbc, void *p ) +{ + Abc_Ntk_t * pNtk; + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + pNtk = Abc_NtkFromMiniMapping( (int *)p ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); +} + /**Function************************************************************* Synopsis [This procedure outputs an array representing mini-mapped network.] diff --git a/src/base/abci/abcMini.c b/src/base/abci/abcMini.c index 67ce8382fe..40e28dad66 100644 --- a/src/base/abci/abcMini.c +++ b/src/base/abci/abcMini.c @@ -144,6 +144,22 @@ Mini_Aig_t * Abc_NtkToMiniAig( Abc_Ntk_t * pNtk ) Mini_AigSetRegNum( p, Abc_NtkLatchNum(pNtk) ); return p; } +Mini_Aig_t * Abc_MiniAigFromNtk ( Abc_Ntk_t *pNtk ) +{ + Abc_Ntk_t *pNtkRes = NULL; + Mini_Aig_t *pAig; + if (Abc_NtkHasMapping(pNtk)) { + pNtk = pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + if ( pNtkRes == NULL ) + { + printf("Strashing has failed.\n" ); + return NULL; + } + } + pAig = Abc_NtkToMiniAig(pNtk); + if (pNtkRes) Abc_NtkDelete(pNtkRes); + return pAig; +} /**Function************************************************************* diff --git a/src/opt/rar/module.make b/src/opt/rar/module.make new file mode 100644 index 0000000000..47e9101969 --- /dev/null +++ b/src/opt/rar/module.make @@ -0,0 +1,4 @@ +SRC += src/opt/rar/rewire_rng.c \ + src/opt/rar/rewire_map.c \ + src/opt/rar/rewire_rar.c \ + src/opt/rar/rewire_miaig.cpp \ No newline at end of file diff --git a/src/opt/rar/rewire_map.c b/src/opt/rar/rewire_map.c new file mode 100644 index 0000000000..2c961dd503 --- /dev/null +++ b/src/opt/rar/rewire_map.c @@ -0,0 +1,45 @@ +#include "rewire_map.h" + +ABC_NAMESPACE_IMPL_START + +extern Abc_Ntk_t *Abc_NtkFromAigPhase(Aig_Man_t *pMan); +extern Abc_Ntk_t *Abc_NtkDarAmap(Abc_Ntk_t *pNtk, Amap_Par_t *pPars); +extern void *Abc_FrameReadLibGen2(); +extern Vec_Int_t * Abc_NtkWriteMiniMapping( Abc_Ntk_t * pNtk ); +extern void Abc_NtkPrintMiniMapping( int * pArray ); +extern Abc_Ntk_t * Abc_NtkFromMiniMapping( int *vMapping ); +extern Mini_Aig_t * Abc_MiniAigFromNtk ( Abc_Ntk_t *pNtk ); + +Abc_Ntk_t *Gia_ManRewirePut(Gia_Man_t *pGia) { + Aig_Man_t *pMan = Gia_ManToAig(pGia, 0); + Abc_Ntk_t *pNtk = Abc_NtkFromAigPhase(pMan); + Aig_ManStop(pMan); + return pNtk; +} + +Abc_Ntk_t *Abc_ManRewireMap(Abc_Ntk_t *pNtk) { + Amap_Par_t Pars, *pPars = &Pars; + Amap_ManSetDefaultParams(pPars); + Abc_Ntk_t *pNtkMapped = Abc_NtkDarAmap(pNtk, pPars); + if (pNtkMapped == NULL) { + Abc_NtkDelete(pNtk); + Abc_Print(-1, "Mapping has failed.\n"); + return NULL; + } + + return pNtkMapped; +} + +Vec_Int_t *Abc_ManRewireNtkWriteMiniMapping(Abc_Ntk_t *pNtk) { + return Abc_NtkWriteMiniMapping(pNtk); +} + +Abc_Ntk_t *Abc_ManRewireNtkFromMiniMapping(int *vMapping) { + return Abc_NtkFromMiniMapping(vMapping); +} + +Mini_Aig_t *Abc_ManRewireMiniAigFromNtk(Abc_Ntk_t *pNtk) { + return Abc_MiniAigFromNtk(pNtk); +} + +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/opt/rar/rewire_map.h b/src/opt/rar/rewire_map.h new file mode 100644 index 0000000000..bde8ef5045 --- /dev/null +++ b/src/opt/rar/rewire_map.h @@ -0,0 +1,20 @@ +#ifndef REWIRE_MAP_H +#define REWIRE_MAP_H + +#include "base/abc/abc.h" +#include "aig/gia/giaAig.h" +#include "map/amap/amap.h" +#include "map/mio/mio.h" +#include "aig/miniaig/miniaig.h" + +ABC_NAMESPACE_HEADER_START + +Abc_Ntk_t *Gia_ManRewirePut(Gia_Man_t *pGia); +Abc_Ntk_t *Abc_ManRewireMap(Abc_Ntk_t *pNtk); +Vec_Int_t *Abc_ManRewireNtkWriteMiniMapping(Abc_Ntk_t *pNtk); +Abc_Ntk_t *Abc_ManRewireNtkFromMiniMapping(int *vMapping); +Mini_Aig_t *Abc_ManRewireMiniAigFromNtk(Abc_Ntk_t *pNtk); + +ABC_NAMESPACE_HEADER_END + +#endif // REWIRE_MAP_H \ No newline at end of file diff --git a/src/opt/rar/rewire_miaig.cpp b/src/opt/rar/rewire_miaig.cpp new file mode 100644 index 0000000000..98aeeea93e --- /dev/null +++ b/src/opt/rar/rewire_miaig.cpp @@ -0,0 +1,1159 @@ +#include "rewire_rar.h" +#include "rewire_miaig.h" + +#ifdef RW_ABC +ABC_NAMESPACE_IMPL_START +#endif // RW_ABC + +#ifdef RW_ABC +Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose) { + Random_Num(nSeed); + + Rewire::Miaig pNtkMiaig(pGia); + Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, fVerbose); + + return pNew.toGia(); +} + +Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose) { + Random_Num(nSeed); + + Rewire::Miaig pNtkMiaig(pNtk); + Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, fVerbose); + + return pNew.toNtk(nMode); +} + +Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose) { + Random_Num(nSeed); + + Rewire::Miaig pNtkMiaig(pAig); + Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, fVerbose); + + return pNew.toMiniAig(); +} +#endif // RW_ABC + +namespace Rewire { + +void Miaig::create(int nIns, int nOuts, int nObjsAlloc) { + assert(1 + nIns + nOuts <= nObjsAlloc); + release(); + + _data = (Miaig_Data *)calloc(sizeof(Miaig_Data), 1); + + if (_data) { + _data->nIns = nIns; + _data->nOuts = nOuts; + _data->nObjs = 1 + nIns; // const0 + nIns + _data->nObjsAlloc = nObjsAlloc; + _data->nWords = Tt_WordNum(nIns); + _data->nTravIds = 0; + _data->pTravIds = (int *)calloc(sizeof(int), _data->nObjsAlloc); + _data->pCopy = (int *)calloc(sizeof(int), _data->nObjsAlloc); + _data->pRefs = (int *)calloc(sizeof(int), _data->nObjsAlloc); + _data->vOrder = Vi_Alloc(1000); + _data->vOrderF = Vi_Alloc(1000); + _data->vOrderF2 = Vi_Alloc(1000); + _data->vTfo = Vi_Alloc(1000); + _data->pvFans = (vi *)calloc(sizeof(vi), _data->nObjsAlloc); + _data->pLevel = nullptr; + _data->pTable = nullptr; + _data->refcount = 1; + _refcount = &_data->refcount; + } +} + +void Miaig::print(void) { + int i, k, iLit; + printf("\nAIG printout:\n"); + printf("Const0\n"); + Miaig_ForEachInput(i) + printf("Pi%d\n", i); + Miaig_ForEachNode(i) { + printf("Node%d {", i); + Miaig_ForEachObjFanin(i, iLit, k) + printf(" %d", iLit); + printf(" }\n"); + } + Miaig_ForEachOutput(i) { + printf("Po%d ", i); + Miaig_ForEachObjFanin(i, iLit, k) + printf(" %d", iLit); + printf("\n"); + } +} + +#ifdef RW_ABC +int Miaig::fromGia(Gia_Man_t *pGia) { + Gia_Obj_t *pObj; + int *pCopy = (int *)calloc(sizeof(int), Gia_ManObjNum(pGia)); // obj2obj + // printf("[INFO] Converting GIA into MIAIG\n"); + // printf("[INFO] PI/PO/OBJ = %d/%d/%d\n", Gia_ManPiNum(pGia), Gia_ManPoNum(pGia), Gia_ManObjNum(pGia)); + create(Gia_ManPiNum(pGia), Gia_ManPoNum(pGia), Gia_ManObjNum(pGia)); + int i; + pCopy[0] = Gia_ObjId(pGia, Gia_ManConst0(pGia)); + Miaig_ForEachInput(i) { + pCopy[i] = i; + } + Gia_ManForEachAnd(pGia, pObj, i) { + pCopy[i] = appendObj(); + assert(pCopy[i] == i); + appendFanin(pCopy[i], Rw_Lit2LitV(pCopy, Gia_Obj2Lit(pGia, Gia_ObjChild1(pObj)))); + appendFanin(pCopy[i], Rw_Lit2LitV(pCopy, Gia_Obj2Lit(pGia, Gia_ObjChild0(pObj)))); + } + Gia_ManForEachPo(pGia, pObj, i) + appendFanin(appendObj(), Rw_Lit2LitV(pCopy, Gia_Obj2Lit(pGia, Gia_ObjChild0(pObj)))); + free(pCopy); + return 1; +} + +int Miaig::fromMiniAig(Mini_Aig_t *pMiniAig) { + int *pCopy = (int *)calloc(sizeof(int), Mini_AigNodeNum(pMiniAig)); // obj2obj + create(Mini_AigPiNum(pMiniAig), Mini_AigPoNum(pMiniAig), Mini_AigNodeNum(pMiniAig)); + int i; + Miaig_ForEachInput(i) + pCopy[i] = i; + Mini_AigForEachAnd( pMiniAig, i ) { + pCopy[i] = appendObj(); + assert( pCopy[i] == i ); + appendFanin(pCopy[i], Rw_Lit2LitV(pCopy, Mini_AigNodeFanin0(pMiniAig, i))); + appendFanin(pCopy[i], Rw_Lit2LitV(pCopy, Mini_AigNodeFanin1(pMiniAig, i))); + } + Mini_AigForEachPo( pMiniAig, i ) + appendFanin(appendObj(), Rw_Lit2LitV(pCopy, Mini_AigNodeFanin0(pMiniAig, i))); + free(pCopy); + return 1; +} + +Gia_Man_t *Miaig::toGia(void) { + int i, k, iLit, And2 = countAnd2(); + Gia_Man_t *pGia = Gia_ManStart(1 + nIns() + And2 + nOuts()), *pTemp; + Gia_ManHashAlloc(pGia); + memset(_data->pCopy, 0, sizeof(int) * nObjs()); + Miaig_ForEachInput(i) + objCopy(i) = Gia_ManAppendCi(pGia); + Miaig_ForEachNode(i) { + assert(objFaninNum(i) > 0); + Miaig_ForEachObjFanin(i, iLit, k) { + if (k == 0) + objCopy(i) = Rw_Lit2LitL(_data->pCopy, iLit); + else + objCopy(i) = Gia_ManHashAnd(pGia, objCopy(i), Rw_Lit2LitL(_data->pCopy, iLit)); + } + } + Miaig_ForEachOutput(i) { + assert(objFaninNum(i) == 1); + Miaig_ForEachObjFanin(i, iLit, k) + Gia_ManAppendCo(pGia, Rw_Lit2LitL(_data->pCopy, iLit)); + } + // assert(Gia_ManObjNum(pGia) == (1 + nIns() + nOuts() + And2)); + pGia = Gia_ManCleanup(pTemp = pGia); + Gia_ManStop(pTemp); + return pGia; +} + +Mini_Aig_t *Miaig::toMiniAig(void) { + int i, k, iLit; + Mini_Aig_t * pMini = Mini_AigStart(); + memset(_data->pCopy, 0, sizeof(int) * nObjs()); + Miaig_ForEachInput(i) + objCopy(i) = Mini_AigCreatePi(pMini); + Miaig_ForEachNode(i) { + assert(objFaninNum(i) > 0); + Miaig_ForEachObjFanin(i, iLit, k) + if (k == 0) + objCopy(i) = Rw_Lit2LitL(_data->pCopy, iLit); + else + objCopy(i) = Mini_AigAnd(pMini, objCopy(i), Rw_Lit2LitL(_data->pCopy, iLit)); + } + Miaig_ForEachOutput(i) { + assert(objFaninNum(i) == 1); + Miaig_ForEachObjFanin(i, iLit, k) + Mini_AigCreatePo(pMini, Rw_Lit2LitL(_data->pCopy, iLit)); + } + assert(pMini->nSize == 2 * (1 + nIns() + nOuts() + countAnd2())); + return pMini; +} + +Abc_Ntk_t *Miaig::toNtk(int fMapped) { + if (_data->pNtkMapped && fMapped) { + return Abc_ManRewireNtkFromMiniMapping(Vi_Array(_data->pNtkMapped)); + } + Gia_Man_t *pGia = toGia(); + Abc_Ntk_t *pNtk = Gia_ManRewirePut(pGia); + Gia_ManStop(pGia); + return pNtk; +} +#endif // RW_ABC + +// technology mapping +float Miaig::countTransistors(int reset) { + if (!reset && _data->nTransistor) return _data->nTransistor; +#ifdef RW_ABC + Abc_Ntk_t *pNtk = toNtk(); + Abc_Ntk_t *pNtkMapped = Abc_ManRewireMap(pNtk); + + float area = Abc_NtkGetMappedArea(pNtkMapped); + Vec_Int_t *vMapping = Abc_ManRewireNtkWriteMiniMapping(pNtkMapped); + _data->pNtkMapped = (vi *)malloc(sizeof(vi)); + _data->pNtkMapped->size = Vec_IntSize(vMapping); + _data->pNtkMapped->cap = Vec_IntCap(vMapping); + _data->pNtkMapped->ptr = Vec_IntArray(vMapping); + free(vMapping); + Abc_NtkDelete(pNtk); + Abc_NtkDelete(pNtkMapped); +#else + float area = 0; +#endif // RW_ABC + + return _data->nTransistor = area; +} + +// topological collection +void Miaig::topoCollect_rec(int iObj) { + int i, iLit; + if (objTravId(iObj) == nTravIds()) + return; + objTravId(iObj) = nTravIds(); + Vi_PushOrder(_data->vOrder, iObj); + Miaig_ForEachObjFanin(iObj, iLit, i) + topoCollect_rec(Abc_Lit2Var(iLit)); +} + +vi *Miaig::topoCollect(void) { + int i; + nTravIds()++; + Vi_Shrink(_data->vOrder, 0); + Miaig_ForEachConstInput(i) + objTravId(i) = nTravIds(); + Miaig_ForEachOutput(i) + topoCollect_rec(Abc_Lit2Var(objFanin0(i))); + return _data->vOrder; +} + +// initializeLevels +int Miaig::initializeLevels_rec(int iObj) { + int i, iLit; + if (objLevel(iObj) != -1) + return objLevel(iObj); + int level = -1; + Miaig_ForEachObjFanin(iObj, iLit, i) { + level = Abc_MaxInt(initializeLevels_rec(Abc_Lit2Var(iLit)), level); + } + return objLevel(iObj) = level + 1; +} + +void Miaig::initializeLevels(void) { + if (_data->pLevel) return; + _data->pLevel = (int *)malloc(sizeof(int) * nObjs()); + + int i; + Miaig_ForEachObj(i) { + objLevel(i) = -1; + } + Miaig_ForEachConstInput(i) { + objLevel(i) = 0; + } + Miaig_ForEachOutput(i) { + objLevel(i) = initializeLevels_rec(Abc_Lit2Var(objFanin0(i))); + } +} + +// distance computation +void Miaig::initializeDists(void) { + if (_data->pDist) return; + _data->pDist = (int *)malloc(sizeof(int) * nObjs()); +} + +void Miaig::markDistanceN_rec(int iObj, int n, int limit) { + int i, iLit; + if (objDist(iObj) >= 0 && objDist(iObj) <= n) + return; + objDist(iObj) = n; + if (n == limit) + return; + Miaig_ForEachObjFanin(iObj, iLit, i) + markDistanceN_rec(Abc_Lit2Var(iLit), n + 1, limit); +} + +void Miaig::markDistanceN(int iObj, int n) { + int i, j, k, iLit; + memset(_data->pDist, 0xFF, sizeof(int) * nObjs()); + markDistanceN_rec(iObj, 0, n); + for (i = 0; i < n; ++i) { + Miaig_ForEachNode(j) { + if (objDist(j) >= 0) continue; + int minDist = nObjs(); + Miaig_ForEachObjFanin(j, iLit, k) { + if (objDist(Abc_Lit2Var(iLit)) == -1) continue; + minDist = Abc_MinInt(minDist, objDist(Abc_Lit2Var(iLit))); + } + if (minDist != nObjs()) { + markDistanceN_rec(j, minDist + 1, n); + } + } + } +} + +// reference counting +void Miaig::refObj(int iObj) { + int k, iLit; + Miaig_ForEachObjFanin(iObj, iLit, k) + objRef(Abc_Lit2Var(iLit))++; +} + +void Miaig::derefObj(int iObj) { + int k, iLit; + Miaig_ForEachObjFanin(iObj, iLit, k) + objRef(Abc_Lit2Var(iLit))--; +} + +void Miaig::derefObj_rec(int iObj, int iLitSkip) { + int k, iLit; + Miaig_ForEachObjFanin(iObj, iLit, k) { + if (iLit != iLitSkip && --objRef(Abc_Lit2Var(iLit)) == 0 && objIsNode(Abc_Lit2Var(iLit))) { + derefObj_rec(Abc_Lit2Var(iLit), -1); + Vi_Fill(_data->pvFans + Abc_Lit2Var(iLit), 1, 0); + refObj(Abc_Lit2Var(iLit)); + } + } +} + +void Miaig::initializeRefs(void) { + int i; + memset(_data->pRefs, 0, sizeof(int) * _data->nObjs); + Miaig_ForEachNodeOutput(i) + refObj(i); +} + +void Miaig::verifyRefs(void) { + int i; + Miaig_ForEachNodeOutput(i) + derefObj(i); + for (i = 0; i < _data->nObjs; i++) + if (objRef(i)) + printf("Ref count of node %d is incorrect (%d).\n", i, objRef(i)); + initializeRefs(); +} + +// this procedure marks Const0, PIs, POs, and used nodes with the current trav ID +void Miaig::markDfs_rec(int iObj) { + int i, iLit; + if (objTravId(iObj) == nTravIds()) + return; + objTravId(iObj) = nTravIds(); + Miaig_ForEachObjFanin(iObj, iLit, i) + markDfs_rec(Abc_Lit2Var(iLit)); +} + +int Miaig::markDfs(void) { + int i, nUnused = 0; + nTravIds()++; + Miaig_ForEachConstInput(i) + objTravId(i) = nTravIds(); + Miaig_ForEachOutput(i) + markDfs_rec(Abc_Lit2Var(objFanin0(i))); + Miaig_ForEachOutput(i) + objTravId(i) = nTravIds(); + Miaig_ForEachNode(i) + nUnused += (int)(objTravId(i) != nTravIds()); + return nUnused; +} + +// simple duplicator (optionally removes unused nodes) +Miaig Miaig::dup(int fRemDangle, int fMapped) { + // Miaig pNew = Maig_Alloc(nIns(), nOuts(), nObjs()); + Miaig pNew(nIns(), nOuts(), nObjs()); + memset(_data->pCopy, 0, sizeof(int) * nObjs()); + int i, k, iLit; // obj2obj + if (fRemDangle) + markDfs(); + Miaig_ForEachInput(i) + objCopy(i) = i; + Miaig_ForEachNodeOutput(i) { + assert(objFaninNum(i) > 0); + if (fRemDangle && objTravId(i) != nTravIds()) + continue; + objCopy(i) = pNew.appendObj(); + Miaig_ForEachObjFanin(i, iLit, k) + pNew.appendFanin(objCopy(i), Rw_Lit2LitV(_data->pCopy, iLit)); + } + if (_data->pNtkMapped && fMapped) + pNew._data->pNtkMapped = Vi_Dup(_data->pNtkMapped); + return pNew; +} + +// duplicator to restore the topological order +// (the input AIG can have "hidden" internal nodes listed after primary outputs) +void Miaig::dupDfs_rec(Miaig &pNew, int iObj) { + int i, iLit; + // 1. return if current node is already marked + if (objCopy(iObj) >= 0) + return; + // 2. create fanins for a given node + Miaig_ForEachObjFanin(iObj, iLit, i) + dupDfs_rec(pNew, Abc_Lit2Var(iLit)); + assert(objCopy(iObj) < 0); // combinational loop catching + assert(objFaninNum(iObj) > 0); + // 3. create current node + objCopy(iObj) = pNew.appendObj(); + // 4. append newly created fanins to the current node + Miaig_ForEachObjFanin(iObj, iLit, i) + pNew.appendFanin(objCopy(iObj), Rw_Lit2LitV(_data->pCopy, iLit)); +} + +Miaig Miaig::dupDfs(void) { + Miaig pNew(nIns(), nOuts(), nObjsAlloc()); + // 1. the array is filled with -1 to distinct visited nodes from unvisited + memset(_data->pCopy, 0xFF, sizeof(int) * nObjsAlloc()); + int i; // obj2obj + // for each primary input we mark it with it's index + Miaig_ForEachConstInput(i) + objCopy(i) = i; + // 2. for each primary output we call recursive function for it's fanin + Miaig_ForEachOutput(i) + dupDfs_rec(pNew, Abc_Lit2Var(objFanin0(i))); + // 3. for each primary output append it's fanin + Miaig_ForEachOutput(i) + pNew.appendFanin(pNew.appendObj(), Rw_Lit2LitV(_data->pCopy, objFanin0(i))); + return pNew; +} + +// reduces multi-input and-gate represented by an array of fanin literals +void Miaig::reduceFanins(vi *v) { + assert(Vi_Size(v) > 0); + Vi_SelectSort(v); + + if (Vi_Read(v, 0) == 0) { + Vi_Shrink(v, 1); + return; + } + while (Vi_Read(v, 0) == 1) + Vi_Drop(v, 0); + if (Vi_Size(v) == 0) { + Vi_Push(v, 1); + return; + } + if (Vi_Size(v) == 1) + return; + int i, iLit, iPrev = Vi_Read(v, 0); + Vi_ForEachEntryStart(v, iLit, i, 1) { + if ((iPrev ^ iLit) == 1) { + Vi_Fill(v, 1, 0); + return; + } + if (iPrev == iLit) + Vi_Drop(v, i--); + else + iPrev = iLit; + } +} + +int Miaig::hashTwo(int l0, int l1, int TableSize) { + unsigned Key = 0; + Key += Abc_Lit2Var(l0) * 7937; + Key += Abc_Lit2Var(l1) * 2971; + Key += Abc_LitIsCompl(l0) * 911; + Key += Abc_LitIsCompl(l1) * 353; + return Key % TableSize; +} + +int *Miaig::hashLookup(int *pTable, int l0, int l1, int TableSize) { + int Key = hashTwo(l0, l1, TableSize); + for (; pTable[3 * Key]; Key = (Key + 1) % TableSize) + if (pTable[3 * Key] == l0 && pTable[3 * Key + 1] == l1) + return pTable + 3 * Key + 2; + assert(pTable[3 * Key] == 0); + assert(pTable[3 * Key + 1] == 0); + assert(pTable[3 * Key + 2] == 0); + pTable[3 * Key] = l0; + pTable[3 * Key + 1] = l1; + return pTable + 3 * Key + 2; +} + +// this duplicator creates two-input nodes, propagates constants, and does structural hashing +int Miaig::buildNode(int l0, int l1, int fCprop, int fStrash) { + if (fCprop) { + if (l0 == 0 || l1 == 0 || (l0 ^ l1) == 1) return 0; + if (l0 == l1 || l1 == 1) return l0; + if (l0 == 1) return l1; + } + int *pPlace = NULL; + if (fStrash) { + pPlace = hashLookup(_data->pTable, Abc_MinInt(l0, l1), Abc_MaxInt(l0, l1), _data->TableSize); + if (*pPlace) + return *pPlace; + } + int iObj = appendObj(); + appendFanin(iObj, Abc_MinInt(l0, l1)); + appendFanin(iObj, Abc_MaxInt(l0, l1)); + return pPlace ? (*pPlace = Abc_Var2Lit(iObj, 0)) : Abc_Var2Lit(iObj, 0); +} + +int Miaig::buildNodeBalance_rec(Miaig &pNew, vi *vFanins, int begin, int end, int fCprop, int fStrash) { + int length = end - begin + 1; + if (length == 1) { + return Rw_Lit2LitL(_data->pCopy, Vi_Read(vFanins, begin)); + } else if (length == 2) { + return pNew.buildNode(Rw_Lit2LitL(_data->pCopy, Vi_Read(vFanins, begin)), Rw_Lit2LitL(_data->pCopy, Vi_Read(vFanins, end)), fCprop, fStrash); + } + int middle = begin + length / 2; + int iLit0 = buildNodeBalance_rec(pNew, vFanins, begin, middle - 1, fCprop, fStrash); + int iLit1 = buildNodeBalance_rec(pNew, vFanins, middle, end, fCprop, fStrash); + return pNew.buildNode(iLit0, iLit1, fCprop, fStrash); +} + +int Miaig::buildNodeBalance(Miaig &pNew, vi *vFanins, int fCprop, int fStrash) { + return buildNodeBalance_rec(pNew, vFanins, 0, Vi_Size(vFanins) - 1, fCprop, fStrash); +} + +int Miaig::buildNodeCascade(Miaig &pNew, vi *vFanins, int fCprop, int fStrash) { + int iLit = -1; + for (int i = 0; i < Vi_Size(vFanins); ++i) { + if (i == 0) + iLit = Rw_Lit2LitL(_data->pCopy, Vi_Read(vFanins, i)); + else + iLit = pNew.buildNode(iLit, Rw_Lit2LitL(_data->pCopy, Vi_Read(vFanins, i)), fCprop, fStrash); + } + return iLit; +} + +Miaig Miaig::dupStrash(int fCprop, int fStrash, int fCascade) { + int i, nObjsAlloc = 1 + nIns() + nOuts() + countAnd2(); + Miaig pNew(nIns(), nOuts(), nObjsAlloc); + memset(_data->pCopy, 0, sizeof(int) * nObjs()); // obj2lit + if (fStrash) { + assert(pNew._data->pTable == NULL); + pNew._data->TableSize = Abc_PrimeCudd(3 * countAnd2()); + pNew._data->pTable = (int *)calloc(sizeof(int), 3 * pNew._data->TableSize); + } + Miaig_ForEachInput(i) + objCopy(i) = Abc_Var2Lit(i, 0); + Miaig_ForEachNode(i) { + assert(objFaninNum(i) > 0); + if (fCascade) + objCopy(i) = buildNodeCascade(pNew, _data->pvFans + i, fCprop, fStrash); + else + objCopy(i) = buildNodeBalance(pNew, _data->pvFans + i, fCprop, fStrash); + } + Miaig_ForEachOutput(i) + pNew.appendFanin(pNew.appendObj(), Rw_Lit2LitL(_data->pCopy, objFanin0(i))); + return pNew.dup(1); +} + +// this duplicator converts two-input-node AIG into multi-input-node AIG +int *Miaig::createStops(void) { + int i, *pStop = (int *)calloc(sizeof(int), nObjs()); + Miaig_ForEachConstInput(i) + pStop[i] = 2; + Miaig_ForEachNode(i) { + assert(objFaninNum(i) == 2); + int iLit0 = objFanin0(i); + int iLit1 = objFanin1(i); + pStop[Abc_Lit2Var(iLit0)] += 1 + Abc_LitIsCompl(iLit0); + pStop[Abc_Lit2Var(iLit1)] += 1 + Abc_LitIsCompl(iLit1); + } + Miaig_ForEachOutput(i) + pStop[Abc_Lit2Var(objFanin0(i))] += 2; + return pStop; +} + +void Miaig::collectSuper_rec(int iLit, int *pStop, vi *vSuper) { + if (pStop[Abc_Lit2Var(iLit)] > 1) + Vi_Push(vSuper, Rw_Lit2LitL(_data->pCopy, iLit)); + else { + assert(Abc_LitIsCompl(iLit) == 0); + collectSuper_rec(objFanin0(Abc_Lit2Var(iLit)), pStop, vSuper); + collectSuper_rec(objFanin1(Abc_Lit2Var(iLit)), pStop, vSuper); + } +} + +Miaig Miaig::dupMulti(int nFaninMax_, int nGrowth) { + Miaig pNew(nIns(), nOuts(), nObjs()); + int *pStop = createStops(); + int i, k, iLit; + vi *vArray = Vi_Alloc(100); + assert(nFaninMax_ >= 2 && nGrowth >= 1); + memset(_data->pCopy, 0, sizeof(int) * nObjs()); // obj2lit + Miaig_ForEachConstInput(i) + objCopy(i) = Abc_Var2Lit(i, 0); + Miaig_ForEachNode(i) { + if (pStop[i] == 1) + continue; + assert(pStop[i] > 1); // no dangling + Vi_Shrink(vArray, 0); + collectSuper_rec(objFanin0(i), pStop, vArray); + collectSuper_rec(objFanin1(i), pStop, vArray); + assert(Vi_Size(vArray) > 1); + reduceFanins(vArray); + assert(Vi_Size(vArray) > 0); + if (Vi_Size(vArray) == 1) + objCopy(i) = Vi_Read(vArray, 0); + else { + int nFaninMaxLocal = 2 + (Random_Num(0) % (nFaninMax_ - 1)); + int nGrowthLocal = 1 + (Random_Num(0) % nGrowth); + assert(nFaninMaxLocal >= 2 && nFaninMaxLocal <= nFaninMax_); + assert(nGrowthLocal >= 1 && nGrowthLocal <= nGrowth); + + if (Vi_Size(vArray) > nFaninMaxLocal) + Vi_Randomize(vArray); + // create a cascade of nodes + while (Vi_Size(vArray) > nFaninMaxLocal) { + int iObj = pNew.appendObj(); + vi *vFanins = pNew._data->pvFans + iObj; + assert(vFanins->ptr == NULL); + vFanins->cap = nFaninMaxLocal + nGrowthLocal; + vFanins->ptr = (int *)malloc(sizeof(int) * vFanins->cap); + Vi_ForEachEntryStop(vArray, iLit, k, nFaninMaxLocal) + pNew.appendFanin(iObj, iLit); + assert(Vi_Space(vFanins) == nGrowthLocal); + for (k = 0; k < nFaninMaxLocal; k++) + Vi_Drop(vArray, 0); + Vi_Push(vArray, Abc_Var2Lit(iObj, 0)); + } + // create the last node + int iObj = pNew.appendObj(); + vi *vFanins = pNew._data->pvFans + iObj; + assert(vFanins->ptr == NULL); + vFanins->cap = Vi_Size(vArray) + nGrowthLocal; + vFanins->ptr = (int *)malloc(sizeof(int) * vFanins->cap); + Vi_ForEachEntry(vArray, iLit, k) + pNew.appendFanin(iObj, iLit); + assert(Vi_Space(vFanins) == nGrowthLocal); + objCopy(i) = Abc_Var2Lit(iObj, 0); + } + } + Miaig_ForEachOutput(i) + pNew.appendFanin(pNew.appendObj(), Rw_Lit2LitL(_data->pCopy, objFanin0(i))); + Vi_Free(vArray); + free(pStop); + return pNew; +} + +// compute truth table of the node +void Miaig::truthSimNode(int i) { + int k, iLit; + Miaig_ForEachObjFanin(i, iLit, k) { + if (k == 0) Tt_DupC(objTruth(i, objType(i)), objTruth(Abc_Lit2Var(iLit), objType(Abc_Lit2Var(iLit))), Abc_LitIsCompl(iLit), nWords()); + else Tt_Sharp(objTruth(i, objType(i)), objTruth(Abc_Lit2Var(iLit), objType(Abc_Lit2Var(iLit))), Abc_LitIsCompl(iLit), nWords()); + } +} + +// compute truth table of the node using a subset of its current fanin +word *Miaig::truthSimNodeSubset(int i, int m) { + int k, iLit, Counter = 0; + assert(m > 0); + Miaig_ForEachObjFanin(i, iLit, k) { + if ((m >> k) & 1) { // fanin is included in the subset + if (Counter++ == 0) + Tt_DupC(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords()); + else + Tt_Sharp(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords()); + } + } + assert(Counter == Tt_BitCount16(m)); + return _data->pProd; +} + +word *Miaig::truthSimNodeSubset2(int i, vi *vFanins, int nFanins) { + int k, iLit; + Vi_ForEachEntryStop(vFanins, iLit, k, nFanins) { + if (k == 0) Tt_DupC(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords()); + else Tt_Sharp(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords()); + } + return _data->pProd; +} + +void Miaig::initializeTruth(void) { + int i; + if (_data->pTruths[0]) + return; + _data->pTruths[0] = (word *)calloc(sizeof(word), 3 * nWords() * nObjs()); + _data->pTruths[1] = _data->pTruths[0] + 1 * nWords() * nObjs(); + _data->pTruths[2] = _data->pTruths[0] + 2 * nWords() * nObjs(); + _data->pCare = (word *)calloc(sizeof(word), nWords()); + _data->pProd = (word *)calloc(sizeof(word), nWords()); + float MemMB = 8.0 * nWords() * (3 * nObjs() + 2) / (1 << 20); + if (MemMB > 100.0) + printf("Allocated %d truth tables of %d-variable functions (%.2f MB),\n", 3 * nObjs() + 2, nIns(), MemMB); + nTravIds()++; + Miaig_ForEachInput(i) + Tt_ElemInit(objTruth(i, 0), i - 1, nWords()); + Miaig_ForEachNodeOutput(i) + truthSimNode(i); + Miaig_ForEachOutput(i) + assert(objFaninNum(i) == 1); + Miaig_ForEachOutput(i) + Tt_Dup(objTruth(i, 2), objTruth(i, 0), nWords()); +} + +void Miaig::truthUpdate(vi *vTfo) { + int i, iTemp, nFails = 0; + nTravIds()++; + Vi_ForEachEntry(vTfo, iTemp, i) { + truthSimNode(iTemp); + if (objIsPo(iTemp) && !Tt_Equal(objTruth(iTemp, 2), objTruth(iTemp, 0), nWords())) + printf("Verification failed at output %d.\n", iTemp - (nObjs() - nOuts())), nFails++; + } + if (nFails) + printf("Verification failed for %d outputs after updating node %d.\n", nFails, Vi_Read(vTfo, 0)); +} + +int Miaig::computeTfo_rec(int iObj) { + int k, iLit, Value = 0; + if (objTravId(iObj) == nTravIds()) + return 1; + if (objTravId(iObj) == nTravIds() - 1) + return 0; + Miaig_ForEachObjFanin(iObj, iLit, k) { + Value |= computeTfo_rec(Abc_Lit2Var(iLit)); + } + objTravId(iObj) = nTravIds() - 1 + Value; + if (Value) Vi_Push(_data->vTfo, iObj); + return Value; +} + +vi *Miaig::computeTfo(int iObj) { + int i; + assert(objIsNode(iObj)); + nTravIds() += 2; + objTravId(iObj) = nTravIds(); + Vi_Fill(_data->vTfo, 1, iObj); + Miaig_ForEachConstInput(i) + objTravId(i) = nTravIds() - 1; + Miaig_ForEachOutput(i) + computeTfo_rec(i); + Miaig_ForEachNode(i) { + computeTfo_rec(i); + } + return _data->vTfo; +} + +word *Miaig::computeCareSet(int iObj) { + vi *vTfo = computeTfo(iObj); + int i, iTemp; + Tt_Not(objTruth(iObj, 1), objTruth(iObj, 0), nWords()); + Tt_Clear(_data->pCare, nWords()); + Vi_ForEachEntryStart(vTfo, iTemp, i, 1) { + truthSimNode(iTemp); + if (objIsPo(iTemp)) + Tt_OrXor(_data->pCare, objTruth(iTemp, 0), objTruth(iTemp, 1), nWords()); + } + return _data->pCare; +} + +// adds fanin pair to storage +void Miaig::addPair(vi *vPair, int iFan1, int iFan2) { + assert(iFan1 < iFan2); + int i, *pArray = Vi_Array(vPair); + assert(Vi_Size(vPair) % 3 == 0); + for (i = 0; i < Vi_Size(vPair); i += 3) + if (pArray[i] == iFan1 && pArray[i + 1] == iFan2) + break; + if (i == Vi_Size(vPair)) { + Vi_Push(vPair, iFan1); + Vi_Push(vPair, iFan2); + Vi_Push(vPair, 1); + pArray = Vi_Array(vPair); + } + pArray[i + 2]++; + //printf( "Adding pair (%d, %d)\n", iFan1, iFan2 ); +} + +// find fanin pair that appears most often +int Miaig::findPair(vi *vPair) { + int iBest = -1, BestCost = 0; + int i, *pArray = Vi_Array(vPair); + assert(Vi_Size(vPair) % 3 == 0); + for (i = 0; i < Vi_Size(vPair); i += 3) + if (BestCost < pArray[i + 2]) { + BestCost = pArray[i + 2]; + iBest = i; + } + //if ( iBest >= 0 ) printf( "Extracting pair (%d, %d) used %d times.\n", pArray[iBest], pArray[iBest+1], pArray[iBest+2] ); + return iBest; +} + +// updates one fanin array by replacing the pair with a new literal (iLit) +int Miaig::updateFanins(vi *vFans, int iFan1, int iFan2, int iLit) { + int f1, f2, iFan1_, iFan2_; + Vi_ForEachEntry(vFans, iFan1_, f1) if (iFan1_ == iFan1) + Vi_ForEachEntryStart(vFans, iFan2_, f2, f1 + 1) if (iFan2_ == iFan2) { + assert(f1 < f2); + Vi_Drop(vFans, f2); + Vi_Drop(vFans, f1); + Vi_Push(vFans, iLit); + return 1; + } + return 0; +} + +// updates the network by extracting one pair +void Miaig::extractBest(vi *vPairs) { + int i, iObj = appendObj(); + int Counter = 0, *pArray = Vi_Array(vPairs); + int iBest = findPair(vPairs); + assert(iBest >= 0); + //printf( "Creating node %d with fanins (%d, %d).\n", iObj, pArray[iBest], pArray[iBest+1] ); + assert(Vi_Size(_data->pvFans + iObj) == 0); + appendFanin(iObj, pArray[iBest]); + appendFanin(iObj, pArray[iBest + 1]); + Miaig_ForEachNode(i) + Counter += updateFanins(_data->pvFans + i, pArray[iBest], pArray[iBest + 1], Abc_Var2Lit(iObj, 0)); + assert(Counter == pArray[iBest + 2]); +} + +// find the set of all pairs that appear more than once +vi *Miaig::findPairs(word *pSto, int nWords) { + vi *vPairs = Vi_Alloc(30); + int i, f1, f2, iFan1, iFan2; + Miaig_ForEachNode(i) { + vi *vFans = _data->pvFans + i; + Vi_ForEachEntry(vFans, iFan1, f1) { + word *pRowFan1 = pSto + iFan1 * nWords; + Vi_ForEachEntryStart(vFans, iFan2, f2, f1 + 1) { + if (Tt_GetBit(pRowFan1, iFan2)) addPair(vPairs, iFan1, iFan2); + else Tt_SetBit(pRowFan1, iFan2); + } + } + } + return vPairs; +} + +// extract shared fanin pairs and return the number of pairs extracted +int Miaig::findShared(int nNewNodesMax) { + if (nObjs() + nNewNodesMax > nObjsAlloc()) { + nObjsAlloc() = nObjs() + nNewNodesMax; + _data->pCopy = (int *)realloc((void *)_data->pCopy, sizeof(int) * nObjsAlloc()); + _data->pvFans = (vi *)realloc((void *)_data->pvFans, sizeof(vi) * nObjsAlloc()); + memset(_data->pCopy + nObjs(), 0, sizeof(int) * (nObjsAlloc() - nObjs())); + memset(_data->pvFans + nObjs(), 0, sizeof(vi) * (nObjsAlloc() - nObjs())); + } + assert(sizeof(word) == 8); + int i, nWords = (2 * nObjsAlloc() + 63) / 64; // how many words are needed to have a bitstring with one bit for each literal + int nBytesAll = sizeof(word) * nWords * 2 * nObjsAlloc(); + word *pSto = (word *)malloc(nBytesAll); + vi *vPairs; + for (i = 0; i < nNewNodesMax; i++) { + memset(pSto, 0, nBytesAll); + nObjs() -= i; + vPairs = findPairs(pSto, nWords); + nObjs() += i; + if (Vi_Size(vPairs) > 0) + extractBest(vPairs); + int Size = Vi_Size(vPairs); + Vi_Free(vPairs); + if (Size == 0) + break; + } + free(pSto); + return i; +} + +int Miaig::checkConst(int iObj, word *pCare, int fVerbose) { + word *pFunc = objTruth(iObj, 0); + if (!Tt_IntersectC(pCare, pFunc, 0, nWords())) { + derefObj_rec(iObj, -1); + Vi_Fill(_data->pvFans + iObj, 1, 0); // const0 + refObj(iObj); + truthUpdate(_data->vTfo); + if (fVerbose) printf("Detected Const0 at node %d.\n", iObj); + return 1; + } + if (!Tt_IntersectC(pCare, pFunc, 1, nWords())) { + derefObj_rec(iObj, -1); + Vi_Fill(_data->pvFans + iObj, 1, 1); // const1 + refObj(iObj); + truthUpdate(_data->vTfo); + if (fVerbose) printf("Detected Const1 at node %d.\n", iObj); + return 1; + } + return 0; +} + +int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int fVerbose) { + int i, k, n, iLit, nAdded = 0; + word *pCare = computeCareSet(iObj); + assert(nAddedMax > 0); + assert(nAddedMax <= Vi_Space(_data->pvFans + iObj)); + // mark node's fanins + Miaig_ForEachObjFanin(iObj, iLit, k) + objTravId(Abc_Lit2Var(iLit)) = nTravIds(); + // compute the onset + word *pOnset = objTruth(iObj, 0); + Tt_Sharp(pOnset, pCare, 0, nWords()); + // create a random order of fanin candidates + Vi_Shrink(_data->vOrderF, 0); + if (nDist) markDistanceN(iObj, nDist); + Miaig_ForEachInputNode(i) { + if (nDist && objDist(i) < 0 && !objIsPi(i)) continue; + if (objTravId(i) != nTravIds() && (objIsPi(i) || (objFaninNum(i) > 1 && objRef(i) > 0))) // this node is NOT in the TFO + Vi_Push(_data->vOrderF, i); + } + Vi_Randomize(_data->vOrderF); + + int *pOrderF = Vi_Array(_data->vOrderF); + std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) { + return objLevel(Abc_Lit2Var(a)) > objLevel(Abc_Lit2Var(b)); + }); + std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) { + if (objLevel(Abc_Lit2Var(a)) == 0 || objLevel(Abc_Lit2Var(b)) == 0) { + return false; + } + return objRef(Abc_Lit2Var(a)) < objRef(Abc_Lit2Var(b)); + }); + + // iterate through candidate fanins (nodes that are not in the TFO of iObj) + Vi_ForEachEntry(_data->vOrderF, i, k) { + assert(objTravId(i) != nTravIds()); + // new fanin can be added if its offset does not intersect with the node's onset + for (n = 0; n < 2; n++) + if (!Tt_IntersectC(pOnset, objTruth(i, 0), !n, nWords())) { + if (fVerbose) printf("Adding node %d fanin %d\n", iObj, Abc_Var2Lit(i, n)); + appendFanin(iObj, Abc_Var2Lit(i, n)); + objRef(i)++; + nAdded++; + break; + } + if (nAdded == nAddedMax) + break; + } + //printf( "Updating TFO of node %d: ", iObj ); Vi_Print(_data->vTfo); + truthUpdate(_data->vTfo); + //assert( objFaninNum(iObj) <= nFaninMax ); + return nAdded; +} + +int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, int fVerbose) { + int n, k, iLit, nFans = objFaninNum(iObj); + word *pCare = computeCareSet(iObj); + if (checkConst(iObj, pCare, fVerbose)) + return nFans; + if (fOnlyConst) + return 0; + if (nFans == 1) + return 0; + // if one fanin can be used, take it + word *pFunc = objTruth(iObj, 0); + Miaig_ForEachObjFanin(iObj, iLit, k) { + Tt_DupC(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords()); + if (Tt_EqualOnCare(pCare, pFunc, _data->pProd, nWords())) { + derefObj(iObj); + Vi_Fill(_data->pvFans + iObj, 1, iLit); + refObj(iObj); + truthUpdate(_data->vTfo); + if (fVerbose) printf("Reducing node %d fanin count from %d to %d.\n", iObj, nFans, objFaninNum(iObj)); + return nFans - 1; + } + } + if (fOnlyBuffer) + return 0; + Vi_Shrink(_data->vOrderF, 0); + Miaig_ForEachObjFanin(iObj, iLit, k) + Vi_Push(_data->vOrderF, iLit); + Vi_Randomize(_data->vOrderF); + + if (fHeuristic) { + int *pOrderF = Vi_Array(_data->vOrderF); + std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) { + return objLevel(Abc_Lit2Var(a)) < objLevel(Abc_Lit2Var(b)); + }); + std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) { + if (objLevel(Abc_Lit2Var(a)) == 0 || objLevel(Abc_Lit2Var(b)) == 0) { + return false; + } + return objRef(Abc_Lit2Var(a)) > objRef(Abc_Lit2Var(b)); + }); + } + + assert(Vi_Size(_data->vOrderF) == nFans); + // try to remove fanins starting from the end of the list + for (n = Vi_Size(_data->vOrderF) - 1; n >= 0; n--) { + int iFanin = Vi_Drop(_data->vOrderF, n); + word *pProd = truthSimNodeSubset2(iObj, _data->vOrderF, Vi_Size(_data->vOrderF)); + if (!Tt_EqualOnCare(pCare, pFunc, pProd, nWords())) + Vi_Push(_data->vOrderF, iFanin); + } + assert(Vi_Size(_data->vOrderF) >= 1); + // update the node if it is reduced + if (Vi_Size(_data->vOrderF) < nFans) { + derefObj(iObj); + Vi_Shrink(_data->pvFans + iObj, 0); + Vi_ForEachEntry(_data->vOrderF, iLit, k) + Vi_PushOrder(_data->pvFans + iObj, iLit); + refObj(iObj); + truthUpdate(_data->vTfo); + if (fVerbose) printf("Reducing node %d fanin count from %d to %d.\n", iObj, nFans, objFaninNum(iObj)); + return nFans - Vi_Size(_data->vOrderF); + } + return 0; +} + +int Miaig::expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int fVerbose) { + expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimit), nDist, fVerbose); + reduceOne(iNode, 0, 0, 0, fVerbose); + return 0; +} + +vi *Miaig::createRandomOrder(void) { + int i; + Vi_Shrink(_data->vOrder, 0); + Miaig_ForEachNode(i) + Vi_Push(_data->vOrder, i); + Vi_Randomize(_data->vOrder); + return _data->vOrder; +} + +Miaig Miaig::expand(int nFaninAddLimitAll, int nDist, int fVerbose) { + int i, iNode, nAdded = 0; + assert(nFaninAddLimitAll > 0); + vi *vOrder = createRandomOrder(); + + initializeTruth(); + initializeRefs(); + initializeLevels(); + if (nDist) initializeDists(); + Vi_ForEachEntry(vOrder, iNode, i) { + nAdded += expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimitAll - nAdded), nDist, fVerbose); + if (nAdded >= nFaninAddLimitAll) + break; + } + assert(nAdded <= nFaninAddLimitAll); + verifyRefs(); + return dupDfs(); +} + +// perform shared logic extraction +Miaig Miaig::share(int nNewNodesMax) { + Miaig pCopy = dup(0); + int nNewNodes = pCopy.findShared(nNewNodesMax); + if (nNewNodes == 0) + return pCopy; + // temporarily create "hidden" nodes for DFS duplicator + pCopy.nObjs() -= nNewNodes; + Miaig pNew = pCopy.dupDfs(); + pCopy.nObjs() += nNewNodes; + return pNew; +} + +Miaig Miaig::reduce(int fVerbose) { + int i, iNode; + vi *vOrder = topoCollect(); + + initializeTruth(); + initializeRefs(); + initializeLevels(); + // works best for final + Vi_ForEachEntry(vOrder, iNode, i) + reduceOne(iNode, 0, 0, 1, fVerbose); + verifyRefs(); + return dupStrash(1, 1, 1); +} + +Miaig Miaig::expandThenReduce(int nFaninAddLimit, int nDist, int fVerbose) { + Miaig pTemp; + int i, iNode; + vi *vOrder = topoCollect(); + + initializeTruth(); + initializeRefs(); + initializeLevels(); + if (nDist) initializeDists(); + Vi_ForEachEntry(vOrder, iNode, i) { + expandThenReduceOne(iNode, nFaninAddLimit, nDist, fVerbose); + } + verifyRefs(); + return dupDfs().dupStrash(1, 1, 1); +} + +Miaig Miaig::expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nVerbose) { + // expand + Miaig pNew = expand(nFaninAddLimitAll, nDist, nVerbose); + // share + pNew = pNew.share(nDivs == -1 ? pNew.nObjs() : nDivs); + // reduce + pNew = pNew.reduce(nVerbose); + return pNew; +} + +void randomAddBest(std::vector &pBests, Miaig pNew, int nBestSave) { + if (pBests.size() < nBestSave) { + pBests.push_back(pNew); + } else { + int iNum = Random_Num(0) % nBestSave; + pBests[iNum] = pNew; + } +} + +Miaig randomRead(std::vector &pBests) { + return pBests[Random_Num(0) % pBests.size()]; +} + +Miaig Miaig::rewire(int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nVerbose) { + const int nRootSave = 8; + const int nBestSave = 4; + int nRestart = 5000; + std::vector pRoots = {this->dup(0)}; + std::vector pBests = {this->dup(0)}; + iword clkStart = Time_Clock(); + Miaig pNew; + Miaig pRoot = pRoots[0]; + Miaig pBest = this->dup(0); + float (Miaig::*Miaig_ObjectiveFunction)(int) = (nMode == 0) ? &Miaig::countAnd2 : &Miaig::countTransistors; + + float PrevBest = ((&pBest)->*Miaig_ObjectiveFunction)(1); + int iterNotImproveAfterRestart = 0; + if (nVerbose) printf("Initial target : %5g (AND2 = %5g Level = %3d)\n", PrevBest, this->countAnd2(1), this->countLevel()); + for (int i = 0; i < nIters; i++) { + if (nVerbose) printf("\rIteration %7d : %5g -> ", i + 1, ((&pRoot)->*Miaig_ObjectiveFunction)(0)); + if (nTimeOut && nTimeOut < 1.0 * (Time_Clock() - clkStart) / CLOCKS_PER_SEC) break; + pNew = pRoot.dupMulti(nFaninMax, nGrowth); + + if (i % 2 == 0) { + pNew = pNew.expandThenReduce(nGrowth, nDist, nVerbose > 1); + } + pNew = pNew.expandShareReduce(nExpands, nDivs, nDist, nVerbose > 1); + + ++iterNotImproveAfterRestart; + // report + float rootTarget = ((&pRoot)->*Miaig_ObjectiveFunction)(0); + float newTarget = ((&pNew)->*Miaig_ObjectiveFunction)(1); + if (PrevBest > newTarget) { + if (nVerbose) printf("%5g (AND2 = %5g Level = %3d) ", newTarget, pNew.countAnd2(), pNew.countLevel()); + if (nVerbose) Time_PrintEndl("Elapsed time", Time_Clock() - clkStart); + PrevBest = newTarget; + pBests = {pNew.dup(0), pNew.dup(0)}; + pBest = pNew.dup(0, 1); + iterNotImproveAfterRestart = 0; + } else if (PrevBest == newTarget) { + randomAddBest(pBests, pNew.dup(0), nBestSave); + } + // compare + if (rootTarget < newTarget) { + if (iterNotImproveAfterRestart > nRestart) { + pNew = randomRead(pBests).dupMulti(nFaninMax, nGrowth); + pNew = pNew.expand(nExpands, nDist, nVerbose > 1); + pNew = pNew.share(nDivs == -1 ? pNew.nObjs() : nDivs); + pNew = pNew.dupStrash(1, 1, 0); + pRoots = {pNew}; + iterNotImproveAfterRestart = 0; + } else if (rootTarget * 1.05 > newTarget) { + pRoots = {pNew}; + } + } else if (rootTarget == newTarget) { + randomAddBest(pRoots, pNew, nRootSave); + } else { + pRoots = {pNew}; + } + pRoot = randomRead(pRoots); + } + if (nVerbose) Time_PrintEndl("Total solving time", Time_Clock() - clkStart); + return pBest; +} + +} // namespace Rewire + +#ifdef RW_ABC +ABC_NAMESPACE_IMPL_END +#endif // RW_ABC diff --git a/src/opt/rar/rewire_miaig.h b/src/opt/rar/rewire_miaig.h new file mode 100644 index 0000000000..16aeaa3016 --- /dev/null +++ b/src/opt/rar/rewire_miaig.h @@ -0,0 +1,473 @@ +#ifndef REWIRE_MIAIG_H +#define REWIRE_MIAIG_H + +#define RW_ABC + +#ifdef RW_ABC +#include "base/abc/abc.h" +#include "aig/miniaig/miniaig.h" +#include "rewire_map.h" +#else +#ifdef _WIN32 +typedef unsigned __int64 word; // 32-bit windows +#else +typedef long long unsigned word; // other platforms +#endif +#ifdef _WIN32 +typedef __int64 iword; // 32-bit windows +#else +typedef long long iword; // other platforms +#endif +#endif // RW_ABC +#include "rewire_vec.h" +#include "rewire_tt.h" +#include "rewire_time.h" + + +#include +#include + +#ifdef RW_ABC +ABC_NAMESPACE_CXX_HEADER_START +#endif // RW_ABC + +namespace Rewire { + +#if RW_THREADS +// exchange-add operation for atomic operations on reference counters +#if defined __riscv && !defined __riscv_atomic +// riscv target without A extension +static inline int RW_XADD(int *addr, int delta) { + int tmp = *addr; + *addr += delta; + return tmp; +} +#elif defined __INTEL_COMPILER && !(defined WIN32 || defined _WIN32) +// atomic increment on the linux version of the Intel(tm) compiler +#define RW_XADD(addr, delta) \ + (int)_InterlockedExchangeAdd( \ + const_cast(reinterpret_cast(addr)), delta) +#elif defined __GNUC__ +#if defined __clang__ && __clang_major__ >= 3 && !defined __ANDROID__ && !defined __EMSCRIPTEN__ && !defined(__CUDACC__) +#ifdef __ATOMIC_ACQ_REL +#define RW_XADD(addr, delta) \ + __c11_atomic_fetch_add((_Atomic(int) *)(addr), delta, __ATOMIC_ACQ_REL) +#else +#define RW_XADD(addr, delta) \ + __atomic_fetch_add((_Atomic(int) *)(addr), delta, 4) +#endif +#else +#if defined __ATOMIC_ACQ_REL && !defined __clang__ +// version for gcc >= 4.7 +#define RW_XADD(addr, delta) \ + (int)__atomic_fetch_add((unsigned *)(addr), (unsigned)(delta), \ + __ATOMIC_ACQ_REL) +#else +#define RW_XADD(addr, delta) \ + (int)__sync_fetch_and_add((unsigned *)(addr), (unsigned)(delta)) +#endif +#endif +#elif defined _MSC_VER && !defined RC_INVOKED +#define RW_XADD(addr, delta) \ + (int)_InterlockedExchangeAdd((long volatile *)addr, delta) +#else +// thread-unsafe branch +static inline int RW_XADD(int *addr, int delta) { + int tmp = *addr; + *addr += delta; + return tmp; +} +#endif +#else // RW_THREADS +static inline int RW_XADD(int *addr, int delta) { + int tmp = *addr; + *addr += delta; + return tmp; +} +#endif // RW_THREADS + +#define Miaig_CustomForEachConstInput(p, i) for (i = 0; i <= p->nIns; i++) +#define Miaig_CustomForEachInput(p, i) for (i = 1; i <= p->nIns; i++) +#define Miaig_CustomForEachNode(p, i) for (i = 1 + p->nIns; i < p->nObjs - p->nOuts; i++) +#define Miaig_CustomForEachNodeReverse(p, i) for (i = p->nObjs - p->nOuts - 1; i > 1 + p->nIns; i--) +#define Miaig_CustomForEachInputNode(p, i) for (i = 1; i < p->nObjs - p->nOuts; i++) +#define Miaig_CustomForEachNodeStart(p, i, s) for (i = s; i < p->nObjs - p->nOuts; i++) +#define Miaig_CustomForEachOutput(p, i) for (i = p->nObjs - p->nOuts; i < p->nObjs; i++) +#define Miaig_CustomForEachNodeOutput(p, i) for (i = 1 + p->nIns; i < p->nObjs; i++) +#define Miaig_CustomForEachNodeOutputStart(p, i, s) for (i = s; i < p->nObjs; i++) +#define Miaig_CustomForEachObj(p, i) for (i = 0; i < p->nObjs; i++) +#define Miaig_CustomForEachObjFanin(p, i, iLit, k) Vi_ForEachEntry(&p->pvFans[i], iLit, k) + +#define Miaig_ForEachConstInput(i) for (i = 0; i <= _data->nIns; i++) +#define Miaig_ForEachInput(i) for (i = 1; i <= _data->nIns; i++) +#define Miaig_ForEachNode(i) for (i = 1 + _data->nIns; i < _data->nObjs - _data->nOuts; i++) +#define Miaig_ForEachNodeReverse(i) for (i = _data->nObjs - p->nOuts - 1; i > 1 + _data->nIns; i--) +#define Miaig_ForEachInputNode(i) for (i = 1; i < _data->nObjs - _data->nOuts; i++) +#define Miaig_ForEachNodeStart(i, s) for (i = s; i < _data->nObjs - _data->nOuts; i++) +#define Miaig_ForEachOutput(i) for (i = _data->nObjs - _data->nOuts; i < _data->nObjs; i++) +#define Miaig_ForEachNodeOutput(i) for (i = 1 + _data->nIns; i < _data->nObjs; i++) +#define Miaig_ForEachNodeOutputStart(i, s) for (i = s; i < _data->nObjs; i++) +#define Miaig_ForEachObj(i) for (i = 0; i < _data->nObjs; i++) +#define Miaig_ForEachObjFanin(i, iLit, k) Vi_ForEachEntry(&_data->pvFans[i], iLit, k) + +static inline int Rw_Lit2LitV(int *pMapV2V, int Lit) { + assert(Lit >= 0); + return Abc_Var2Lit(pMapV2V[Abc_Lit2Var(Lit)], Abc_LitIsCompl(Lit)); +} + +static inline int Rw_Lit2LitL(int *pMapV2L, int Lit) { + assert(Lit >= 0); + return Abc_LitNotCond(pMapV2L[Abc_Lit2Var(Lit)], Abc_LitIsCompl(Lit)); +} + +struct Miaig_Data { + int refcount; // Reference counter + int nIns; // primary inputs + int nOuts; // primary outputs + int nObjs; // all objects + int nObjsAlloc; // allocated space + int nWords; // the truth table size + int nTravIds; // traversal ID counter + int *pTravIds; // traversal IDs + int *pCopy; // temp copy + int *pRefs; // reference counters + int *pLevel; // levels + int *pDist; // distances + word *pTruths[3]; // truth tables + word *pCare; // careset + word *pProd; // product + vi *vOrder; // node order + vi *vOrderF; // fanin order + vi *vOrderF2; // fanin order + vi *vTfo; // transitive fanout cone + vi *pvFans; // the array of objects' fanins + int *pTable; // structural hashing table + int TableSize; // the size of the hash table + float nTransistor; // objective value + vi *pNtkMapped; // mapped network +}; + +class Miaig { +public: + Miaig(void); + ~Miaig(void); + Miaig(const Miaig &m); + Miaig &operator=(const Miaig &m); + Miaig(int nIns, int nOuts, int nObjsAlloc); +#ifdef RW_ABC + Miaig(Gia_Man_t *pGia); + Miaig(Abc_Ntk_t *pNtk); + Miaig(Mini_Aig_t *pMiniAig); +#endif // RW_ABC + +public: + void addref(void); + void release(void); + +private: + void create(int nIns, int nOuts, int nObjsAlloc); + +public: + int fromGia(Gia_Man_t *pGia); + int fromMiniAig(Mini_Aig_t *pMiniAig); + +public: + int &nIns(void); + int &nOuts(void); + int &nObjs(void); + int &nObjsAlloc(void); + int objIsPi(int i); + int objIsPo(int i); + int objIsNode(int i); + void print(void); + int appendObj(void); + void appendFanin(int i, int iLit); + int objFaninNum(int i); + int objFanin0(int i); + int objFanin1(int i); + int &objLevel(int i); + int &objRef(int i); + int &objTravId(int i); + int &objCopy(int i); + int &objDist(int i); + int &nTravIds(void); + word *objTruth(int i, int n); + int objType(int i); + int nWords(void); + void refObj(int iObj); + void derefObj(int iObj); + void derefObj_rec(int iObj, int iLitSkip); + +private: + int initializeLevels_rec(int iObj); + void initializeLevels(void); + void initializeRefs(void); + void verifyRefs(void); + void initializeTruth(void); + void initializeDists(void); + +private: + void markDfs_rec(int iObj); + int markDfs(void); + void markDistanceN_rec(int iObj, int n, int limit); + void markDistanceN(int Obj, int n); + void topoCollect_rec(int iObj); + vi *topoCollect(void); + void reduceFanins(vi *v); + int *createStops(void); + void collectSuper_rec(int iLit, int *pStop, vi *vSuper); + int checkConst(int iObj, word *pCare, int fVerbose); + void truthSimNode(int i); + word *truthSimNodeSubset(int i, int m); + word *truthSimNodeSubset2(int i, vi *vFanins, int nFanins); + void truthUpdate(vi *vTfo); + int computeTfo_rec(int iObj); + vi *computeTfo(int iObj); + word *computeCareSet(int iObj); + vi *createRandomOrder(void); + void addPair(vi *vPair, int iFan1, int iFan2); + int findPair(vi *vPair); + int updateFanins(vi *vFans, int iFan1, int iFan2, int iLit); + void extractBest(vi *vPairs); + vi *findPairs(word *pSto, int nWords); + int findShared(int nNewNodesMax); + int hashTwo(int l0, int l1, int TableSize); + int *hashLookup(int *pTable, int l0, int l1, int TableSize); + +public: + float countAnd2(int reset = 0); + float countTransistors(int reset = 0); + int countLevel(void); + +private: + void dupDfs_rec(Miaig &pNew, int iObj); + int buildNodeBalance_rec(Miaig &pNew, vi *vFanins, int begin, int end, int fCprop, int fStrash); + +private: + int buildNode(int l0, int l1, int fCprop, int fStrash); + int buildNodeBalance(Miaig &pNew, vi *vFanins, int fCprop, int fStrash); + int buildNodeCascade(Miaig &pNew, vi *vFanins, int fCprop, int fStrash); + +private: + int expandOne(int iObj, int nAddedMax, int nDist, int fVerbose); + int reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, int fVerbose); + int expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int fVerbose); + +public: + Miaig dup(int fRemDangle, int fMapped = 0); + Miaig dupDfs(void); + Miaig dupStrash(int fCprop, int fStrash, int fCascade); + Miaig dupMulti(int nFaninMax_, int nGrowth); + Miaig expand(int nFaninAddLimitAll, int nDist, int nVerbose); + Miaig share(int nNewNodesMax); + Miaig reduce(int fVerbose); + Miaig expandThenReduce(int nFaninAddLimit, int nDist, int fVerbose); + Miaig expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nVerbose); + Miaig rewire(int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nVerbose); + #ifdef RW_ABC + Gia_Man_t *toGia(void); + Abc_Ntk_t *toNtk(int fMapped = 0); + Mini_Aig_t *toMiniAig(void); +#endif // RW_ABC + +private: + int *_refcount; + Miaig_Data *_data; +}; + +inline Miaig::Miaig(void) + : _refcount(nullptr), _data(nullptr) { +} + +inline Miaig::Miaig(int nIns, int nOuts, int nObjsAlloc) + : Miaig() { + create(nIns, nOuts, nObjsAlloc); +} + +#ifdef RW_ABC +inline Miaig::Miaig(Gia_Man_t *pGia) : Miaig() { + fromGia(pGia); +} + +inline Miaig::Miaig(Abc_Ntk_t *pNtk) : Miaig() { + Mini_Aig_t *pMiniAig = Abc_ManRewireMiniAigFromNtk(pNtk); + fromMiniAig(pMiniAig); + Mini_AigStop(pMiniAig); +} + +inline Miaig::Miaig(Mini_Aig_t *pMiniAig) : Miaig() { + fromMiniAig(pMiniAig); +} +#endif // RW_ABC + +inline Miaig::~Miaig(void) { + release(); +} + +inline Miaig::Miaig(const Miaig &m) + : _refcount(m._refcount), _data(m._data) { + addref(); +} + +inline Miaig &Miaig::operator=(const Miaig &m) { + if (this == &m) { + return *this; + } + + if (m._refcount) { + RW_XADD(m._refcount, 1); + } + + release(); + + _refcount = m._refcount; + _data = m._data; + + return *this; +} + +inline void Miaig::addref(void) { + if (_refcount) { + RW_XADD(_refcount, 1); + } +} + +inline void Miaig::release(void) { + if (_refcount && RW_XADD(_refcount, -1) == 1) { + if (_data) { + for (int i = 0; i < _data->nObjsAlloc; ++i) + if (_data->pvFans[i].ptr) + free(_data->pvFans[i].ptr); + free(_data->pvFans); + Vi_Free(_data->vOrder); + Vi_Free(_data->vOrderF); + Vi_Free(_data->vOrderF2); + Vi_Free(_data->vTfo); + free(_data->pTravIds); + free(_data->pCopy); + free(_data->pRefs); + free(_data->pTruths[0]); + if (_data->pCare) free(_data->pCare); + if (_data->pProd) free(_data->pProd); + if (_data->pLevel) free(_data->pLevel); + if (_data->pDist) free(_data->pDist); + if (_data->pTable) free(_data->pTable); + if (_data->pNtkMapped) Vi_Free(_data->pNtkMapped); + delete _data; + } + } + + _data = nullptr; + _refcount = nullptr; +} + +inline int &Miaig::nIns(void) { + return _data->nIns; +} + +inline int &Miaig::nOuts(void) { + return _data->nOuts; +} + +inline int &Miaig::nObjs(void) { + return _data->nObjs; +} + +inline int &Miaig::nObjsAlloc(void) { + return _data->nObjsAlloc; +} + +inline int Miaig::objIsPi(int i) { + return i > 0 && i <= _data->nIns; +} + +inline int Miaig::objIsPo(int i) { + return i >= _data->nObjs - _data->nOuts; +} + +inline int Miaig::objIsNode(int i) { + return i > _data->nIns && i < _data->nObjs - _data->nOuts; +} + +inline int Miaig::appendObj(void) { + assert(_data->nObjs < _data->nObjsAlloc); + return _data->nObjs++; +} + +inline void Miaig::appendFanin(int i, int iLit) { + Vi_PushOrder(_data->pvFans + i, iLit); +} + +inline int Miaig::objFaninNum(int i) { + return Vi_Size(_data->pvFans + i); +} + +inline int Miaig::objFanin0(int i) { + return Vi_Read(_data->pvFans + i, 0); +} + +inline int Miaig::objFanin1(int i) { + assert(objFaninNum(i) == 2); + return Vi_Read(_data->pvFans + i, 1); +} + +inline int &Miaig::objLevel(int i) { + return _data->pLevel[i]; +} + +inline int &Miaig::objRef(int i) { + return _data->pRefs[i]; +} + +inline int &Miaig::objTravId(int i) { + return _data->pTravIds[i]; +} + +inline int &Miaig::objCopy(int i) { + return _data->pCopy[i]; +} + +inline int &Miaig::objDist(int i) { + return _data->pDist[i]; +} + +inline int &Miaig::nTravIds(void) { + return _data->nTravIds; +} + +inline int Miaig::nWords(void) { + return _data->nWords; +} + +inline float Miaig::countAnd2(int reset) { + int i, Counter = 0; + Miaig_ForEachNode(i) { + Counter += objFaninNum(i) - 1; + } + return Counter; +} + +inline int Miaig::countLevel(void) { + initializeLevels(); + int i, Level = -1; + Miaig_ForEachOutput(i) { + Level = Abc_MaxInt(Level, objLevel(i)); + } + return Level; +} + +inline word *Miaig::objTruth(int i, int n) { + return _data->pTruths[n] + nWords() * i; +} + +inline int Miaig::objType(int i) { + return objTravId(i) == nTravIds(); +} + +} // namespace Rewire + +#ifdef RW_ABC +ABC_NAMESPACE_CXX_HEADER_END +#endif // RW_ABC + +#endif // REWIRE_MIAIG_H \ No newline at end of file diff --git a/src/opt/rar/rewire_rar.c b/src/opt/rar/rewire_rar.c new file mode 100644 index 0000000000..afd99bb90b --- /dev/null +++ b/src/opt/rar/rewire_rar.c @@ -0,0 +1,17 @@ +#include "rewire_rar.h" + +ABC_NAMESPACE_IMPL_START + +Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose) { + return Gia_ManRewireInt(pGia, nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, nSeed, fVerbose); +} + +Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose) { + return Abc_ManRewireInt(pNtk, nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, nSeed, fVerbose); +} + +Mini_Aig_t *MiniAig_ManRewire(Mini_Aig_t *pAig, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose) { + return MiniAig_ManRewireInt(pAig, nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, nSeed, fVerbose); +} + +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/opt/rar/rewire_rar.h b/src/opt/rar/rewire_rar.h new file mode 100644 index 0000000000..8cfef8e459 --- /dev/null +++ b/src/opt/rar/rewire_rar.h @@ -0,0 +1,27 @@ +#ifndef RAR_H +#define RAR_H + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "base/abc/abc.h" +#include "aig/gia/gia.h" +#include "aig/miniaig/miniaig.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose); +Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose); +Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose); +Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose); +Mini_Aig_t *MiniAig_ManRewire(Mini_Aig_t *pAig, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose); +Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose); + +ABC_NAMESPACE_HEADER_END + +#endif // RAR_H \ No newline at end of file diff --git a/src/opt/rar/rewire_rng.c b/src/opt/rar/rewire_rng.c new file mode 100644 index 0000000000..61ac02a092 --- /dev/null +++ b/src/opt/rar/rewire_rng.c @@ -0,0 +1,33 @@ +#include "rewire_rng.h" + +ABC_NAMESPACE_IMPL_START + +unsigned Random_Int(int fReset) { + static unsigned int m_z = NUMBER1; + static unsigned int m_w = NUMBER2; + if (fReset) { + m_z = NUMBER1; + m_w = NUMBER2; + } + m_z = 36969 * (m_z & 65535) + (m_z >> 16); + m_w = 18000 * (m_w & 65535) + (m_w >> 16); + return (m_z << 16) + m_w; +} + +word Random_Word(int fReset) { + return ((word)Random_Int(fReset) << 32) | ((word)Random_Int(fReset) << 0); +} + +// This procedure should be called once with Seed > 0 to initialize the generator. +// After initialization, the generator should be always called with Seed == 0. +unsigned Random_Num(int Seed) { + static unsigned RandMask = 0; + if (Seed == 0) + return RandMask ^ Random_Int(0); + RandMask = Random_Int(1); + for (int i = 0; i < Seed; i++) + RandMask = Random_Int(0); + return RandMask; +} + +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/opt/rar/rewire_rng.h b/src/opt/rar/rewire_rng.h new file mode 100644 index 0000000000..9261857b27 --- /dev/null +++ b/src/opt/rar/rewire_rng.h @@ -0,0 +1,28 @@ +#ifndef RAR_RNG_H +#define RAR_RNG_H + +/************************************************************* + random number generation +**************************************************************/ + +#include "base/abc/abc.h" + +// Creates a sequence of random numbers. +// http://www.codeproject.com/KB/recipes/SimpleRNG.aspx + +ABC_NAMESPACE_HEADER_START + +#define NUMBER1 3716960521u +#define NUMBER2 2174103536u + +unsigned Random_Int(int fReset); + +word Random_Word(int fReset); + +// This procedure should be called once with Seed > 0 to initialize the generator. +// After initialization, the generator should be always called with Seed == 0. +unsigned Random_Num(int Seed); + +ABC_NAMESPACE_HEADER_END + +#endif // RAR_RNG_H \ No newline at end of file diff --git a/src/opt/rar/rewire_time.h b/src/opt/rar/rewire_time.h new file mode 100644 index 0000000000..f3f63b54c5 --- /dev/null +++ b/src/opt/rar/rewire_time.h @@ -0,0 +1,41 @@ +#ifndef RAR_TIME_H +#define RAR_TIME_H + +/************************************************************* + counting wall time +**************************************************************/ + +#include "base/abc/abc.h" + +ABC_NAMESPACE_HEADER_START + +static inline iword Time_Clock() { +#if defined(__APPLE__) && defined(__MACH__) +#define APPLE_MACH (__APPLE__ & __MACH__) +#else +#define APPLE_MACH 0 +#endif +#if (defined(LIN) || defined(LIN64)) && !APPLE_MACH && !defined(__MINGW32__) + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) + return (iword)-1; + iword res = ((iword)ts.tv_sec) * CLOCKS_PER_SEC; + res += (((iword)ts.tv_nsec) * CLOCKS_PER_SEC) / 1000000000; + return res; +#else + return (iword)clock(); +#endif +} + +static inline void Time_Print(const char *pStr, iword time) { + printf("%s = %10.2f sec", pStr, (float)1.0 * ((double)(time)) / ((double)CLOCKS_PER_SEC)); +} + +static inline void Time_PrintEndl(const char *pStr, iword time) { + Time_Print(pStr, time); + printf("\n"); +} + +ABC_NAMESPACE_HEADER_END + +#endif // RAR_TIME_H diff --git a/src/opt/rar/rewire_tt.h b/src/opt/rar/rewire_tt.h new file mode 100644 index 0000000000..2e4d375029 --- /dev/null +++ b/src/opt/rar/rewire_tt.h @@ -0,0 +1,210 @@ +#ifndef RAR_TT_H +#define RAR_TT_H + +/************************************************************* + truth table manipulation +**************************************************************/ + +#include "base/abc/abc.h" + +ABC_NAMESPACE_HEADER_START + +// the bit count for the first 256 integer numbers +static int Tt_BitCount8[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8}; + +static inline int Tt_BitCount16(int i) { + return Tt_BitCount8[i & 0xFF] + Tt_BitCount8[i >> 8]; +} + +static word ss_Truths6[6] = { + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000)}; + +static inline int Tt_HexDigitNum(int n) { + return n <= 2 ? 1 : 1 << (n - 2); +} + +static inline void Tt_Print(word *p, int nWords) { + int k, Digit, nDigits = nWords * 16; + for (k = nDigits - 1; k >= 0; k--) { + Digit = (int)((p[k / 16] >> ((k % 16) * 4)) & 15); + if (Digit < 10) + printf("%d", Digit); + else + printf("%c", 'A' + Digit - 10); + } + printf("\n"); +} + +static inline int Tt_CountOnes(word x) { + x = x - ((x >> 1) & ABC_CONST(0x5555555555555555)); + x = (x & ABC_CONST(0x3333333333333333)) + ((x >> 2) & ABC_CONST(0x3333333333333333)); + x = (x + (x >> 4)) & ABC_CONST(0x0F0F0F0F0F0F0F0F); + x = x + (x >> 8); + x = x + (x >> 16); + x = x + (x >> 32); + return (int)(x & 0xFF); +} + +static inline int Tt_CountOnes2(word x) { + return x ? Tt_CountOnes(x) : 0; +} + +static inline int Tt_CountOnesVec(word *x, int nWords) { + int w, Count = 0; + for (w = 0; w < nWords; w++) + Count += Tt_CountOnes2(x[w]); + return Count; +} + +static inline int Tt_CountOnesVecMask(word *x, word *pMask, int nWords) { + int w, Count = 0; + for (w = 0; w < nWords; w++) + Count += Tt_CountOnes2(pMask[w] & x[w]); + return Count; +} + +static inline void Tt_Clear(word *pOut, int nWords) { + int w; + for (w = 0; w < nWords; w++) + pOut[w] = 0; +} + +static inline void Tt_Fill(word *pOut, int nWords) { + int w; + for (w = 0; w < nWords; w++) + pOut[w] = ~(word)0; +} + +static inline void Tt_Dup(word *pOut, word *pIn, int nWords) { + int w; + for (w = 0; w < nWords; w++) + pOut[w] = pIn[w]; +} + +static inline void Tt_DupC(word *pOut, word *pIn, int fC, int nWords) { + int w; + if (fC) + for (w = 0; w < nWords; w++) + pOut[w] = ~pIn[w]; + else + for (w = 0; w < nWords; w++) + pOut[w] = pIn[w]; +} + +static inline void Tt_Not(word *pOut, word *pIn, int nWords) { + int w; + for (w = 0; w < nWords; w++) + pOut[w] = ~pIn[w]; +} + +static inline void Tt_And(word *pOut, word *pIn1, word *pIn2, int nWords) { + int w; + for (w = 0; w < nWords; w++) + pOut[w] = pIn1[w] & pIn2[w]; +} + +static inline void Tt_Sharp(word *pOut, word *pIn, int fC, int nWords) { + int w; + if (fC) + for (w = 0; w < nWords; w++) + pOut[w] &= ~pIn[w]; + else + for (w = 0; w < nWords; w++) + pOut[w] &= pIn[w]; +} + +static inline void Tt_OrXor(word *pOut, word *pIn1, word *pIn2, int nWords) { + int w; + for (w = 0; w < nWords; w++) + pOut[w] |= pIn1[w] ^ pIn2[w]; +} + +static inline int Tt_WordNum(int n) { + return n > 6 ? (1 << (n - 6)) : 1; +} + +static inline void Tt_ElemInit(word *pTruth, int iVar, int nWords) { + int k; + if (iVar < 6) + for (k = 0; k < nWords; k++) + pTruth[k] = ss_Truths6[iVar]; + else + for (k = 0; k < nWords; k++) + pTruth[k] = (k & (1 << (iVar - 6))) ? ~(word)0 : 0; +} + +static inline int Tt_IntersectC(word *pIn1, word *pIn2, int fC, int nWords) { + int w; + if (fC) { + for (w = 0; w < nWords; w++) + if (pIn1[w] & ~pIn2[w]) + return 1; + } else { + for (w = 0; w < nWords; w++) + if (pIn1[w] & pIn2[w]) + return 1; + } + return 0; +} + +static inline int Tt_Equal(word *pIn1, word *pIn2, int nWords) { + int w; + for (w = 0; w < nWords; w++) + if (pIn1[w] != pIn2[w]) + return 0; + return 1; +} + +static inline int Tt_EqualOnCare(word *pCare, word *pIn1, word *pIn2, int nWords) { + int w; + for (w = 0; w < nWords; w++) + if (pCare[w] & (pIn1[w] ^ pIn2[w])) + return 0; + return 1; +} + +static inline int Tt_IsConst0(word *pIn, int nWords) { + int w; + for (w = 0; w < nWords; w++) + if (pIn[w]) + return 0; + return 1; +} + +static inline int Tt_IsConst1(word *pIn, int nWords) { + int w; + for (w = 0; w < nWords; w++) + if (pIn[w] != ~(word)0) + return 0; + return 1; +} + +// read/write/flip i-th bit of a bit string table: +static inline int Tt_GetBit(word *p, int k) { + return (int)(p[k >> 6] >> (k & 63)) & 1; +} + +static inline void Tt_SetBit(word *p, int k) { + p[k >> 6] |= (((word)1) << (k & 63)); +} + +static inline void Tt_XorBit(word *p, int k) { + p[k >> 6] ^= (((word)1) << (k & 63)); +} + +ABC_NAMESPACE_HEADER_END + +#endif // RAR_TT_H \ No newline at end of file diff --git a/src/opt/rar/rewire_vec.h b/src/opt/rar/rewire_vec.h new file mode 100644 index 0000000000..17097be02f --- /dev/null +++ b/src/opt/rar/rewire_vec.h @@ -0,0 +1,206 @@ +#ifndef RAR_VI_H +#define RAR_VI_H + +/************************************************************* + vector of 32-bit integers +**************************************************************/ + +#include +#include +#include +#include + +#include "rewire_rng.h" + +ABC_NAMESPACE_HEADER_START + +// swapping two variables +#define RW_SWAP(Type, a, b) \ + { \ + Type t = a; \ + a = b; \ + b = t; \ + } + +typedef struct vi_ { + int size; + int cap; + int *ptr; +} vi; + +// iterator through the entries in the vector +#define Vi_ForEachEntry(v, entry, i) for (i = 0; (i < (v)->size) && (((entry) = Vi_Read((v), i)), 1); i++) +#define Vi_ForEachEntryReverse(v, entry, i) for (i = (v)->size - 1; (i >= 0) && (((entry) = Vi_Read((v), i)), 1); i--) +#define Vi_ForEachEntryStart(v, entry, i, start) for (i = start; (i < (v)->size) && (((entry) = Vi_Read((v), i)), 1); i++) +#define Vi_ForEachEntryStop(v, entry, i, stop) for (i = 0; (i < stop) && (((entry) = Vi_Read((v), i)), 1); i++) + +static inline void Vi_Start(vi *v, int cap) { + v->size = 0; + v->cap = cap; + v->ptr = (int *)malloc(sizeof(int) * cap); +} + +static inline vi *Vi_Alloc(int cap) { + vi *v = (vi *)malloc(sizeof(vi)); + Vi_Start(v, cap); + return v; +} + +static inline void Vi_Stop(vi *v) { + if (v->ptr) free(v->ptr); +} + +static inline void Vi_Free(vi *v) { + if (v->ptr) free(v->ptr); + free(v); +} + +static inline int Vi_Size(vi *v) { + return v->size; +} + +static inline int Vi_Space(vi *v) { + return v->cap - v->size; +} + +static inline int *Vi_Array(vi *v) { + return v->ptr; +} + +static inline int Vi_Read(vi *v, int k) { + assert(k < v->size); + return v->ptr[k]; +} + +static inline void Vi_Write(vi *v, int k, int e) { + assert(k < v->size); + v->ptr[k] = e; +} + +static inline void Vi_Shrink(vi *v, int k) { + assert(k <= v->size); + v->size = k; +} // only safe to shrink !! + +static inline int Vi_Pop(vi *v) { + assert(v->size > 0); + return v->ptr[--v->size]; +} + +static inline void Vi_Grow(vi *v) { + if (v->size < v->cap) + return; + int newcap = (v->cap < 4) ? 8 : (v->cap / 2) * 3; + v->ptr = (int *)realloc(v->ptr, sizeof(int) * newcap); + if (v->ptr == NULL) { + printf("Failed to realloc memory from %.1f MB to %.1f MB.\n", 4.0 * v->cap / (1 << 20), (float)4.0 * newcap / (1 << 20)); + fflush(stdout); + } + v->cap = newcap; +} + +static inline vi *Vi_Dup(vi *v) { + vi *pNew = Vi_Alloc(v->size); + memcpy(pNew->ptr, v->ptr, sizeof(int) * v->size); + pNew->size = v->size; + return pNew; +} + +static inline void Vi_Push(vi *v, int e) { + Vi_Grow(v); + v->ptr[v->size++] = e; +} + +static inline void Vi_PushTwo(vi *v, int e1, int e2) { + Vi_Push(v, e1); + Vi_Push(v, e2); +} + +static inline void Vi_PushArray(vi *v, int *p, int n) { + for (int i = 0; i < n; i++) + Vi_Push(v, p[i]); +} + +static inline void Vi_PushOrder(vi *v, int e) { + Vi_Push(v, e); + if (v->size > 1) + for (int i = v->size - 2; i >= 0; i--) { + if (v->ptr[i] > v->ptr[i + 1]) { + RW_SWAP(int, v->ptr[i], v->ptr[i + 1]) + } else { + break; + } + } +} + +static inline void Vi_Fill(vi *v, int n, int fill) { + int i; + Vi_Shrink(v, 0); + for (i = 0; i < n; i++) + Vi_Push(v, fill); +} + +static inline int Vi_Drop(vi *v, int i) { + assert(i >= 0 && i < v->size); + int Entry = v->ptr[i]; + for (; i < v->size - 1; i++) + v->ptr[i] = v->ptr[i + 1]; + Vi_Shrink(v, v->size - 1); + return Entry; +} + +static inline int Vi_Find(vi *v, int e) { + int j; + for (j = 0; j < v->size; j++) + if (v->ptr[j] == e) + return j; + return -1; +} + +static inline int Vi_Remove(vi *v, int e) { + int j = Vi_Find(v, e); + if (j == -1) + return 0; + Vi_Drop(v, j); + return 1; +} + +static inline void Vi_Randomize(vi *v) { + for (int i = 0; i < v->size; i++) { + int iRand = Random_Num(0) % v->size; + RW_SWAP(int, v->ptr[iRand], v->ptr[i]); + } +} + +static inline void Vi_Reverse(vi *v) { + int i, j; + for (i = 0, j = v->size - 1; i < j; i++, j--) + RW_SWAP(int, v->ptr[i], v->ptr[j]); +} + +static inline void Vi_Print(vi *v) { + printf("Array with %d entries:", v->size); + int i, entry; + Vi_ForEachEntry(v, entry, i) + printf(" %d", entry); + printf("\n"); +} + +static inline void Vi_SelectSort(vi *v) { + int *pArray = Vi_Array(v); + int nSize = Vi_Size(v); + int temp, i, j, best_i; + for (i = 0; i < nSize - 1; i++) { + best_i = i; + for (j = i + 1; j < nSize; j++) + if (pArray[j] < pArray[best_i]) + best_i = j; + temp = pArray[i]; + pArray[i] = pArray[best_i]; + pArray[best_i] = temp; + } +} + +ABC_NAMESPACE_HEADER_END + +#endif // RAR_VI_H \ No newline at end of file