diff --git a/.github/workflows/build-posix-cmake.yml b/.github/workflows/build-posix-cmake.yml index ea31fe0bc..def198107 100644 --- a/.github/workflows/build-posix-cmake.yml +++ b/.github/workflows/build-posix-cmake.yml @@ -5,7 +5,7 @@ jobs: build-posix: strategy: matrix: - os: [macos-latest, ubuntu-latest] + os: [macos-11, ubuntu-latest] use_namespace: [false, true] runs-on: ${{ matrix.os }} diff --git a/.gitignore b/.gitignore index f15ce2c79..203869de1 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ lib/abc* lib/m114* lib/bip* docs/ +.vscode/ src/ext* src/xxx/ diff --git a/abclib.dsp b/abclib.dsp index d460427cf..0fd96a8b8 100644 --- a/abclib.dsp +++ b/abclib.dsp @@ -675,6 +675,10 @@ SOURCE=.\src\base\io\ioWriteDot.c # End Source File # Begin Source File +SOURCE=.\src\base\io\ioWriteEdgelist.c +# End Source File +# Begin Source File + SOURCE=.\src\base\io\ioWriteEqn.c # End Source File # Begin Source File @@ -5107,6 +5111,14 @@ SOURCE=.\src\aig\gia\giaMuxes.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaNewBdd.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaNewTt.h +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaNf.c # End Source File # Begin Source File @@ -5303,6 +5315,18 @@ SOURCE=.\src\aig\gia\giaTtopt.cpp # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaTransduction.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTransduction.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTranStoch.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaUnate.c # End Source File # Begin Source File diff --git a/src/aig/aig/aig.h b/src/aig/aig/aig.h index e92e512c4..5285ae72b 100644 --- a/src/aig/aig/aig.h +++ b/src/aig/aig/aig.h @@ -225,7 +225,7 @@ static inline Aig_Cut_t * Aig_CutNext( Aig_Cut_t * pCut ) { return /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// -static inline unsigned Aig_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId & 31)); } +static inline unsigned Aig_ObjCutSign( unsigned ObjId ) { return (1U << (ObjId & 31)); } static inline int Aig_WordCountOnes( unsigned uWord ) { uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); diff --git a/src/aig/aig/aigShow.c b/src/aig/aig/aigShow.c index d983602a6..e3d89942a 100644 --- a/src/aig/aig/aigShow.c +++ b/src/aig/aig/aigShow.c @@ -340,7 +340,7 @@ void Aig_WriteDotAig( Aig_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * ***********************************************************************/ void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) { - extern void Abc_ShowFile( char * FileNameDot ); + extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); char FileNameDot[200]; FILE * pFile; // create the file name @@ -355,7 +355,7 @@ void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) // generate the file Aig_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 942c9eb73..fed64b1ad 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1105,10 +1105,12 @@ static inline Gia_Obj_t * Gia_ObjFanout( Gia_Man_t * p, Gia_Obj_t * pObj, int i static inline void Gia_ObjSetFanout( Gia_Man_t * p, Gia_Obj_t * pObj, int i, Gia_Obj_t * pFan ) { Vec_IntWriteEntry( p->vFanout, Gia_ObjFoffset(p, pObj) + i, Gia_ObjId(p, pFan) ); } static inline void Gia_ObjSetFanoutInt( Gia_Man_t * p, Gia_Obj_t * pObj, int i, int x ) { Vec_IntWriteEntry( p->vFanout, Gia_ObjFoffset(p, pObj) + i, x ); } -#define Gia_ObjForEachFanoutStatic( p, pObj, pFanout, i ) \ - for ( i = 0; (i < Gia_ObjFanoutNum(p, pObj)) && (((pFanout) = Gia_ObjFanout(p, pObj, i)), 1); i++ ) -#define Gia_ObjForEachFanoutStaticId( p, Id, FanId, i ) \ - for ( i = 0; (i < Gia_ObjFanoutNumId(p, Id)) && (((FanId) = Gia_ObjFanoutId(p, Id, i)), 1); i++ ) +#define Gia_ObjForEachFanoutStatic( p, pObj, pFanout, i ) \ + for ( i = 0; (i < Gia_ObjFanoutNum(p, pObj)) && (((pFanout) = Gia_ObjFanout(p, pObj, i)), 1); i++ ) +#define Gia_ObjForEachFanoutStaticId( p, Id, FanId, i ) \ + for ( i = 0; (i < Gia_ObjFanoutNumId(p, Id)) && ((FanId = Gia_ObjFanoutId(p, Id, i)), 1); i++ ) +#define Gia_ObjForEachFanoutStaticIndex( p, Id, FanId, i, Index ) \ + for ( i = 0; (i < Gia_ObjFanoutNumId(p, Id)) && (Index = Vec_IntEntry(p->vFanout, Id)+i) && ((FanId = Vec_IntEntry(p->vFanout, Index)), 1); i++ ) static inline int Gia_ManHasMapping( Gia_Man_t * p ) { return p->vMapping != NULL; } static inline int Gia_ObjIsLut( Gia_Man_t * p, int Id ) { return Vec_IntEntry(p->vMapping, Id) != 0; } @@ -1141,6 +1143,8 @@ static inline int Gia_ObjCellId( Gia_Man_t * p, int iLit ) { re for ( i = Gia_ManObjNum(p) - 1; i > 0; i-- ) if ( !Gia_ObjIsLut(p, i) ) {} else #define Gia_LutForEachFanin( p, i, iFan, k ) \ for ( k = 0; k < Gia_ObjLutSize(p,i) && ((iFan = Gia_ObjLutFanins(p,i)[k]),1); k++ ) +#define Gia_LutForEachFaninIndex( p, i, iFan, k, Index ) \ + for ( k = 0; k < Gia_ObjLutSize(p,i) && (Index = Vec_IntEntry(p->vMapping, i)+1+k) && ((iFan = Vec_IntEntry(p->vMapping, Index)),1); k++ ) #define Gia_LutForEachFaninObj( p, i, pFanin, k ) \ for ( k = 0; k < Gia_ObjLutSize(p,i) && ((pFanin = Gia_ManObj(p, Gia_ObjLutFanins(p,i)[k])),1); k++ ) @@ -1234,6 +1238,8 @@ static inline int Gia_ObjCellId( Gia_Man_t * p, int iLit ) { re for ( i = 0; (i < Gia_ManRegNum(p)) && ((pObj) = Gia_ManCo(p, Gia_ManPoNum(p)+i)); i++ ) #define Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) \ for ( i = 0; (i < Gia_ManRegNum(p)) && ((pObjRi) = Gia_ManCo(p, Gia_ManPoNum(p)+i)) && ((pObjRo) = Gia_ManCi(p, Gia_ManPiNum(p)+i)); i++ ) +#define Gia_ManForEachRoToRiVec( vRoIds, p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(vRoIds)) && ((pObj) = Gia_ObjRoToRi(p, Gia_ManObj(p, Vec_IntEntry(vRoIds, i)))); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// @@ -1379,6 +1385,7 @@ extern Gia_Man_t * Gia_ManDupDemiter( Gia_Man_t * p, int fVerbose ); extern Gia_Man_t * Gia_ManDemiterToDual( Gia_Man_t * p ); extern int Gia_ManDemiterDual( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 ); extern int Gia_ManDemiterTwoWords( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 ); +extern void Gia_ManProdAdderGen( int nArgA, int nArgB, int Seed, int fSigned, int fCla ); /*=== giaEdge.c ==========================================================*/ extern void Gia_ManEdgeFromArray( Gia_Man_t * p, Vec_Int_t * vArray ); extern Vec_Int_t * Gia_ManEdgeToArray( Gia_Man_t * p ); @@ -1436,7 +1443,7 @@ extern void Gia_ManFanoutStart( Gia_Man_t * p ); extern void Gia_ManFanoutStop( Gia_Man_t * p ); extern void Gia_ManStaticFanoutStart( Gia_Man_t * p ); extern void Gia_ManStaticFanoutStop( Gia_Man_t * p ); -extern void Gia_ManStaticMappingFanoutStart( Gia_Man_t * p ); +extern void Gia_ManStaticMappingFanoutStart( Gia_Man_t * p, Vec_Int_t ** pvIndex ); /*=== giaForce.c =========================================================*/ extern void For_ManExperiment( Gia_Man_t * pGia, int nIters, int fClustered, int fVerbose ); /*=== giaFrames.c =========================================================*/ @@ -1609,6 +1616,7 @@ extern Vec_Wrd_t * Gia_ManArray2SimOne( Vec_Int_t * vRes ); extern Vec_Ptr_t * Gia_ManArray2Sim( Vec_Wec_t * vRes ); extern void Gia_ManPtrWrdDumpBin( char * pFileName, Vec_Ptr_t * p, int fVerbose ); extern Vec_Ptr_t * Gia_ManPtrWrdReadBin( char * pFileName, int fVerbose ); +extern Vec_Str_t * Gia_ManComputeRange( Gia_Man_t * p ); /*=== giaSpeedup.c ============================================================*/ extern float Gia_ManDelayTraceLut( Gia_Man_t * p ); extern float Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose ); @@ -1761,10 +1769,14 @@ extern int Gia_ManCountPosWithNonZeroDrivers( Gia_Man_t * p ); extern void Gia_ManUpdateCopy( Vec_Int_t * vCopy, Gia_Man_t * p ); extern Vec_Int_t * Gia_ManComputeDistance( Gia_Man_t * p, int iObj, Vec_Int_t * vObjs, int fVerbose ); -/*=== giaTtopt.c ===========================================================*/ +/*=== giaTtopt.cpp ===========================================================*/ extern Gia_Man_t * Gia_ManTtopt( Gia_Man_t * p, int nIns, int nOuts, int nRounds ); extern Gia_Man_t * Gia_ManTtoptCare( Gia_Man_t * p, int nIns, int nOuts, int nRounds, char * pFileName, int nRarity ); +/*=== giaTransduction.cpp ===========================================================*/ +extern Gia_Man_t * Gia_ManTransductionBdd( Gia_Man_t * pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t * pExdc, int fNewLine, int nVerbose ); +extern Gia_Man_t * Gia_ManTransductionTt( Gia_Man_t * pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t * pExdc, int fNewLine, int nVerbose ); + /*=== giaCTas.c ===========================================================*/ typedef struct Tas_Man_t_ Tas_Man_t; extern Tas_Man_t * Tas_ManAlloc( Gia_Man_t * pAig, int nBTLimit ); diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index c9af8a32e..35ad6aab9 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -5407,6 +5407,138 @@ Gia_Man_t * Gia_ManDupBlackBox( Gia_Man_t * p ) return pNew; } +/**Function************************************************************* + + Synopsis [Duplicates with the care set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupWithCare( Gia_Man_t * p, Gia_Man_t * pCare ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iCare = -1; + assert( Gia_ManCiNum(pCare) == Gia_ManCiNum(p) ); + assert( Gia_ManCoNum(pCare) == 1 ); + assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManRegNum(pCare) == 0 ); + pNew = Gia_ManStart( 2*Gia_ManObjNum(p) + Gia_ManObjNum(pCare) ); + pNew->pName = Abc_UtilStrsavTwo( pNew->pName ? pNew->pName : (char *)"test", (char *)"_care" ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(pCare)->Value = 0; + Gia_ManForEachCi( pCare, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( pCare, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( pCare, pObj, i ) + iCare = Gia_ObjFanin0Copy(pObj); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManCi(pCare, i)->Value; + Gia_ManForEachAnd( p, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, iCare, pObj->Value ); + } + Gia_ManForEachCo( p, pObj, i ) + { + pObj->Value = Gia_ObjFanin0Copy(pObj); + pObj->Value = Gia_ManHashAnd( pNew, iCare, pObj->Value ); + Gia_ManAppendCo( pNew, pObj->Value ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManProdAdderGen( int nArgA, int nArgB, int Seed, int fSigned, int fCla ) +{ + extern void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vLevels, Vec_Int_t * vRes, int fSigned, int fCla ); + int i, k, x, fCompl, iLit; char pNameP[32], pNameT[32]; + Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB ); + Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB ); + Vec_Int_t * vRes = Vec_IntAlloc( nArgA + nArgB ); + Vec_Int_t * vArgA = Vec_IntAlloc( nArgA ); + Vec_Int_t * vArgB = Vec_IntAlloc( nArgB ), * vLevel; + Gia_Man_t * pProd = Gia_ManStart( 1000 ); + Gia_Man_t * pTree = Gia_ManStart( 1000 ), * pTemp; + Gia_ManHashAlloc( pTree ); + pProd->pName = Abc_UtilStrsav( "prod" ); + pTree->pName = Abc_UtilStrsav( "tree" ); + for ( x = 0; x < nArgA; x++ ) + Vec_IntPush( vArgA, Gia_ManAppendCi(pProd) ); + for ( x = 0; x < nArgB; x++ ) + Vec_IntPush( vArgB, Gia_ManAppendCi(pProd) ); + for ( x = 0; x < nArgA + nArgB; x++ ) + { + for ( i = 0; i < nArgA; i++ ) + for ( k = 0; k < nArgB; k++ ) + { + if ( i + k != x ) + continue; + fCompl = fSigned && ((i == nArgA-1) ^ (k == nArgB-1)); + iLit = Abc_LitNotCond(Gia_ManAppendAnd(pProd, Vec_IntEntry(vArgA, i), Vec_IntEntry(vArgB, k)), fCompl); + Gia_ManAppendCo( pProd, iLit ); + Vec_WecPush( vProds, i+k, Gia_ManAppendCi(pTree) ); + Vec_WecPush( vLevels, i+k, 0 ); + } + } + if ( fSigned ) + { + Vec_WecPush( vProds, nArgA, 1 ); + Vec_WecPush( vLevels, nArgA, 0 ); + + Vec_WecPush( vProds, nArgA+nArgB-1, 1 ); + Vec_WecPush( vLevels, nArgA+nArgB-1, 0 ); + } + if ( Seed ) + { + Abc_Random( 1 ); + for ( x = 0; x < Seed; x++ ) + Abc_Random( 0 ); + Vec_WecForEachLevel( vProds, vLevel, x ) + if ( Vec_IntSize(vLevel) > 1 ) + Vec_IntRandomizeOrder( vLevel ); + } + Wlc_BlastReduceMatrix( pTree, vProds, vLevels, vRes, fSigned, fCla ); + Vec_IntShrink( vRes, nArgA + nArgB ); + assert( Vec_IntSize(vRes) == nArgA + nArgB ); + Vec_IntForEachEntry( vRes, iLit, x ) + Gia_ManAppendCo( pTree, iLit ); + pTree = Gia_ManCleanup( pTemp = pTree ); + Gia_ManStop( pTemp ); + + sprintf( pNameP, "prod%d%d.aig", nArgA, nArgB ); + sprintf( pNameT, "tree%d%d.aig", nArgA, nArgB ); + Gia_AigerWrite( pProd, pNameP, 0, 0, 0 ); + Gia_AigerWrite( pTree, pNameT, 0, 0, 0 ); + Gia_ManStop( pProd ); + Gia_ManStop( pTree ); + printf( "Dumped files \"%s\" and \"%s\".\n", pNameP, pNameT ); + + Vec_WecFree( vProds ); + Vec_WecFree( vLevels ); + Vec_IntFree( vArgA ); + Vec_IntFree( vArgB ); + Vec_IntFree( vRes ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaEquiv.c b/src/aig/gia/giaEquiv.c index 030eaa60d..1c3aa4311 100644 --- a/src/aig/gia/giaEquiv.c +++ b/src/aig/gia/giaEquiv.c @@ -528,7 +528,7 @@ int Gia_ManChoiceMinLevel_rec( Gia_Man_t * p, int iPivot, int fDiveIn, Vec_Int_t { int Level0, Level1, LevelMax; Gia_Obj_t * pPivot = Gia_ManObj( p, iPivot ); - if ( Gia_ObjIsCi(pPivot) ) + if ( Gia_ObjIsCi(pPivot) || iPivot == 0 ) return 0; if ( Gia_ObjLevel(p, pPivot) ) return Gia_ObjLevel(p, pPivot); diff --git a/src/aig/gia/giaFanout.c b/src/aig/gia/giaFanout.c index 8b104e9b7..fd58bfeb8 100644 --- a/src/aig/gia/giaFanout.c +++ b/src/aig/gia/giaFanout.c @@ -324,12 +324,20 @@ Vec_Int_t * Gia_ManStartMappingFanoutMap( Gia_Man_t * p, Vec_Int_t * vFanoutNums SeeAlso [] ***********************************************************************/ -void Gia_ManStaticMappingFanoutStart( Gia_Man_t * p ) +void Gia_ObjCheckDupMappingFanins( Gia_Man_t * p, int iObj ) +{ + int * pFanins = Gia_ObjLutFanins( p, iObj ); + int i, k, nFanins = Gia_ObjLutSize( p, iObj ); + for ( i = 0; i < nFanins; i++ ) + for ( k = i + 1; k < nFanins; k++ ) + assert( pFanins[i] != pFanins[k] ); +} +void Gia_ManStaticMappingFanoutStart( Gia_Man_t * p, Vec_Int_t ** pvIndex ) { Vec_Int_t * vCounts; int * pRefsOld; Gia_Obj_t * pObj, * pFanin; - int i, k, iFan, iFanout; + int i, k, iFan, iFanout, Index; assert( p->vFanoutNums == NULL ); assert( p->vFanout == NULL ); // recompute reference counters @@ -339,17 +347,22 @@ void Gia_ManStaticMappingFanoutStart( Gia_Man_t * p ) p->pLutRefs = pRefsOld; // start the fanout maps p->vFanout = Gia_ManStartMappingFanoutMap( p, p->vFanoutNums ); + if ( pvIndex ) + *pvIndex = Vec_IntStart( Vec_IntSize(p->vFanout) ); // incrementally add fanouts vCounts = Vec_IntStart( Gia_ManObjNum(p) ); Gia_ManForEachLut( p, i ) { + Gia_ObjCheckDupMappingFanins( p, i ); pObj = Gia_ManObj( p, i ); - Gia_LutForEachFanin( p, i, iFan, k ) + Gia_LutForEachFaninIndex( p, i, iFan, k, Index ) { pFanin = Gia_ManObj( p, iFan ); iFanout = Vec_IntEntry( vCounts, iFan ); Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); Vec_IntAddToEntry( vCounts, iFan, 1 ); + if ( pvIndex ) + Vec_IntWriteEntry( *pvIndex, Vec_IntEntry(p->vFanout, iFan) + iFanout, Index ); } } Gia_ManForEachCo( p, pObj, i ) diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c index 8b4e5b123..7c5e706e8 100644 --- a/src/aig/gia/giaIf.c +++ b/src/aig/gia/giaIf.c @@ -558,11 +558,12 @@ void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile ) FILE * pTable = fopen( pDumpFile, "a+" ); if ( strcmp( FileNameOld, p->pName ) ) { - sprintf( FileNameOld, "%s", p->pName ); + sprintf( FileNameOld, "%s_out", p->pName ); fprintf( pTable, "\n" ); fprintf( pTable, "%s ", p->pName ); fprintf( pTable, " " ); - fprintf( pTable, "%d ", Gia_ManAndNum(p) ); + //fprintf( pTable, "%d ", Gia_ManAndNum(p) ); + fprintf( pTable, "%d ", Gia_ManRegNum(p) ); fprintf( pTable, "%d ", nLuts ); fprintf( pTable, "%d ", Gia_ManLutLevelWithBoxes(p) ); //fprintf( pTable, "%d ", Gia_ManRegBoxNum(p) ); @@ -575,11 +576,13 @@ void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile ) //printf( "This part of the code is currently not used.\n" ); //assert( 0 ); fprintf( pTable, " " ); + fprintf( pTable, " " ); + fprintf( pTable, "%d ", Gia_ManRegNum(p) ); fprintf( pTable, "%d ", nLuts ); fprintf( pTable, "%d ", Gia_ManLutLevelWithBoxes(p) ); //fprintf( pTable, "%d ", Gia_ManRegBoxNum(p) ); //fprintf( pTable, "%d ", Gia_ManNonRegBoxNum(p) ); - fprintf( pTable, "%.2f", 1.0*(Abc_Clock() - clk)/CLOCKS_PER_SEC ); +// fprintf( pTable, "%.2f", 1.0*(Abc_Clock() - clk)/CLOCKS_PER_SEC ); clk = Abc_Clock(); } fclose( pTable ); diff --git a/src/aig/gia/giaMf.c b/src/aig/gia/giaMf.c index e732f25e2..0e1ae9a97 100644 --- a/src/aig/gia/giaMf.c +++ b/src/aig/gia/giaMf.c @@ -1789,7 +1789,7 @@ void Mf_ManOptimization( Mf_Man_t * p ) Gia_Man_t * pGia = p->pGia0; int i, Count, nNodes = Mf_ManMappingFromMapping( p ); Gia_ManLevelNum( pGia ); - Gia_ManStaticMappingFanoutStart( pGia ); + Gia_ManStaticMappingFanoutStart( pGia, NULL ); Mf_ManPrintFanoutProfile( p, pGia->vFanoutNums ); printf( "\nIndividual logic cones for mapping with %d nodes:\n", nNodes ); Vec_IntForEachEntry( pGia->vFanoutNums, Count, i ) diff --git a/src/aig/gia/giaMfs.c b/src/aig/gia/giaMfs.c index d443ddde9..a0e6caed4 100644 --- a/src/aig/gia/giaMfs.c +++ b/src/aig/gia/giaMfs.c @@ -67,7 +67,7 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) int nBoxes = Gia_ManBoxNum(p), nVars; int nRealPis = nBoxes ? Tim_ManPiNum(pManTime) : Gia_ManPiNum(p); int nRealPos = nBoxes ? Tim_ManPoNum(pManTime) : Gia_ManPoNum(p); - int i, j, k, curCi, curCo, nBoxIns, nBoxOuts; + int i, j, k, curCi, curCo, nBoxIns, nBoxOuts, w, nWords; int Id, iFan, nMfsVars, nBbIns = 0, nBbOuts = 0, Counter = 0; int nLutSizeMax = Gia_ManLutSizeMax( p ); nLutSizeMax = Abc_MaxInt( nLutSizeMax, 6 ); @@ -113,15 +113,11 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, Id), vLeaves ); nVars = Abc_TtMinBase( pTruth, Vec_IntArray(vArray), Vec_IntSize(vArray), Vec_IntSize(vLeaves) ); Vec_IntShrink( vArray, nVars ); - if ( nVars <= 6 ) - Vec_WrdWriteEntry( vTruths, Counter, pTruth[0] ); - else - { - int w, nWords = Abc_Truth6WordNum( nVars ); - Vec_IntWriteEntry( vStarts, Counter, Vec_WrdSize(vTruths2) ); - for ( w = 0; w < nWords; w++ ) - Vec_WrdPush( vTruths2, pTruth[w] ); - } + Vec_WrdWriteEntry( vTruths, Counter, pTruth[0] ); + nWords = Abc_Truth6WordNum( nVars ); + Vec_IntWriteEntry( vStarts, Counter, Vec_WrdSize(vTruths2) ); + for ( w = 0; w < nWords; w++ ) + Vec_WrdPush( vTruths2, pTruth[w] ); if ( Gia_ObjLutIsMux(p, Id) ) { Vec_StrWriteEntry( vFixed, Counter, (char)1 ); @@ -143,6 +139,8 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) Vec_StrWriteEntry( vEmpty, Counter, (char)1 ); uTruth = Gia_ObjFaninC0(pObj) ? ~uTruths6[0]: uTruths6[0]; Vec_WrdWriteEntry( vTruths, Counter, uTruth ); + Vec_IntWriteEntry( vStarts, Counter, Vec_WrdSize(vTruths2) ); + Vec_WrdPush( vTruths2, uTruth ); } Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), Counter++ ); } diff --git a/src/aig/gia/giaMini.c b/src/aig/gia/giaMini.c index f0558cc4d..6ba85706d 100644 --- a/src/aig/gia/giaMini.c +++ b/src/aig/gia/giaMini.c @@ -769,6 +769,8 @@ Vec_Int_t * Gia_ManMapEquivAfterScorr( Gia_Man_t * p, Vec_Int_t * vMap ) { if ( iObjLit == -1 ) continue; +// if ( Gia_ObjHasRepr(p, Abc_Lit2Var(iObjLit)) && !Gia_ObjProved(p, Abc_Lit2Var(iObjLit)) ) +// continue; iReprGia = Gia_ObjReprSelf( p, Abc_Lit2Var(iObjLit) ); iReprMini = Vec_IntEntry( vGia2Mini, iReprGia ); if ( iReprMini == -1 ) diff --git a/src/aig/gia/giaNewBdd.h b/src/aig/gia/giaNewBdd.h new file mode 100644 index 000000000..6d75f4d99 --- /dev/null +++ b/src/aig/gia/giaNewBdd.h @@ -0,0 +1,839 @@ +/**CFile**************************************************************** + + FileName [giaNewBdd.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaNewBdd.h,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__gia__giaNewBdd_h +#define ABC__aig__gia__giaNewBdd_h + +#include +#include +#include +#include +#include + +ABC_NAMESPACE_CXX_HEADER_START + +namespace NewBdd { + + typedef unsigned short var; + typedef int bvar; + typedef unsigned lit; + typedef unsigned short ref; + typedef unsigned long long size; + typedef unsigned edge; + typedef unsigned uniq; + typedef unsigned cac; + static inline var VarMax() { return std::numeric_limits::max(); } + static inline bvar BvarMax() { return std::numeric_limits::max(); } + static inline lit LitMax() { return std::numeric_limits::max(); } + static inline ref RefMax() { return std::numeric_limits::max(); } + static inline size SizeMax() { return std::numeric_limits::max(); } + static inline uniq UniqHash(lit Arg0, lit Arg1) { return Arg0 + 4256249 * Arg1; } + static inline cac CacHash(lit Arg0, lit Arg1) { return Arg0 + 4256249 * Arg1; } + + class Cache { + private: + cac nSize; + cac nMax; + cac Mask; + size nLookups; + size nHits; + size nThold; + double HitRate; + int nVerbose; + std::vector vCache; + + public: + Cache(int nCacheSizeLog, int nCacheMaxLog, int nVerbose): nVerbose(nVerbose) { + if(nCacheMaxLog < nCacheSizeLog) + throw std::invalid_argument("nCacheMax must not be smaller than nCacheSize"); + nMax = (cac)1 << nCacheMaxLog; + if(!(nMax << 1)) + throw std::length_error("Memout (nCacheMax) in init"); + nSize = (cac)1 << nCacheSizeLog; + if(nVerbose) + std::cout << "Allocating " << nSize << " cache entries" << std::endl; + vCache.resize(nSize * 3); + Mask = nSize - 1; + nLookups = 0; + nHits = 0; + nThold = (nSize == nMax)? SizeMax(): nSize; + HitRate = 1; + } + ~Cache() { + if(nVerbose) + std::cout << "Free " << nSize << " cache entries" << std::endl; + } + inline lit Lookup(lit x, lit y) { + nLookups++; + if(nLookups > nThold) { + double NewHitRate = (double)nHits / nLookups; + if(nVerbose >= 2) + std::cout << "Cache Hits: " << std::setw(10) << nHits << ", " + << "Lookups: " << std::setw(10) << nLookups << ", " + << "Rate: " << std::setw(10) << NewHitRate + << std::endl; + if(NewHitRate > HitRate) + Resize(); + if(nSize == nMax) + nThold = SizeMax(); + else { + nThold <<= 1; + if(!nThold) + nThold = SizeMax(); + } + HitRate = NewHitRate; + } + cac i = (CacHash(x, y) & Mask) * 3; + if(vCache[i] == x && vCache[i + 1] == y) { + if(nVerbose >= 3) + std::cout << "Cache hit: " + << "x = " << std::setw(10) << x << ", " + << "y = " << std::setw(10) << y << ", " + << "z = " << std::setw(10) << vCache[i + 2] << ", " + << "hash = " << std::hex << (CacHash(x, y) & Mask) << std::dec + << std::endl; + nHits++; + return vCache[i + 2]; + } + return LitMax(); + } + inline void Insert(lit x, lit y, lit z) { + cac i = (CacHash(x, y) & Mask) * 3; + vCache[i] = x; + vCache[i + 1] = y; + vCache[i + 2] = z; + if(nVerbose >= 3) + std::cout << "Cache ent: " + << "x = " << std::setw(10) << x << ", " + << "y = " << std::setw(10) << y << ", " + << "z = " << std::setw(10) << z << ", " + << "hash = " << std::hex << (CacHash(x, y) & Mask) << std::dec + << std::endl; + } + inline void Clear() { + std::fill(vCache.begin(), vCache.end(), 0); + } + void Resize() { + cac nSizeOld = nSize; + nSize <<= 1; + if(nVerbose >= 2) + std::cout << "Reallocating " << nSize << " cache entries" << std::endl; + vCache.resize(nSize * 3); + Mask = nSize - 1; + for(cac j = 0; j < nSizeOld; j++) { + cac i = j * 3; + if(vCache[i] || vCache[i + 1]) { + cac hash = (CacHash(vCache[i], vCache[i + 1]) & Mask) * 3; + vCache[hash] = vCache[i]; + vCache[hash + 1] = vCache[i + 1]; + vCache[hash + 2] = vCache[i + 2]; + if(nVerbose >= 3) + std::cout << "Cache mov: " + << "x = " << std::setw(10) << vCache[i] << ", " + << "y = " << std::setw(10) << vCache[i + 1] << ", " + << "z = " << std::setw(10) << vCache[i + 2] << ", " + << "hash = " << std::hex << (CacHash(vCache[i], vCache[i + 1]) & Mask) << std::dec + << std::endl; + } + } + } + }; + + struct Param { + int nObjsAllocLog; + int nObjsMaxLog; + int nUniqueSizeLog; + double UniqueDensity; + int nCacheSizeLog; + int nCacheMaxLog; + int nCacheVerbose; + bool fCountOnes; + int nGbc; + bvar nReo; + double MaxGrowth; + bool fReoVerbose; + int nVerbose; + std::vector *pVar2Level; + Param() { + nObjsAllocLog = 20; + nObjsMaxLog = 25; + nUniqueSizeLog = 10; + UniqueDensity = 4; + nCacheSizeLog = 15; + nCacheMaxLog = 20; + nCacheVerbose = 0; + fCountOnes = false; + nGbc = 0; + nReo = BvarMax(); + MaxGrowth = 1.2; + fReoVerbose = false; + nVerbose = 0; + pVar2Level = NULL; + } + }; + + class Man { + private: + var nVars; + bvar nObjs; + bvar nObjsAlloc; + bvar nObjsMax; + bvar RemovedHead; + int nGbc; + bvar nReo; + double MaxGrowth; + bool fReoVerbose; + int nVerbose; + std::vector vVars; + std::vector Var2Level; + std::vector Level2Var; + std::vector vObjs; + std::vector vNexts; + std::vector vMarks; + std::vector vRefs; + std::vector vEdges; + std::vector vOneCounts; + std::vector vUniqueMasks; + std::vector vUniqueCounts; + std::vector vUniqueTholds; + std::vector > vvUnique; + Cache *cache; + + public: + inline lit Bvar2Lit(bvar a) const { return (lit)a << 1; } + inline lit Bvar2Lit(bvar a, bool c) const { return ((lit)a << 1) ^ (lit)c; } + inline bvar Lit2Bvar(lit x) const { return (bvar)(x >> 1); } + inline var VarOfBvar(bvar a) const { return vVars[a]; } + inline lit ThenOfBvar(bvar a) const { return vObjs[Bvar2Lit(a)]; } + inline lit ElseOfBvar(bvar a) const { return vObjs[Bvar2Lit(a, true)]; } + inline ref RefOfBvar(bvar a) const { return vRefs[a]; } + inline lit Const0() const { return (lit)0; } + inline lit Const1() const { return (lit)1; } + inline bool IsConst0(lit x) const { return x == Const0(); } + inline bool IsConst1(lit x) const { return x == Const1(); } + inline lit IthVar(var v) const { return Bvar2Lit((bvar)v + 1); } + inline lit LitRegular(lit x) const { return x & ~(lit)1; } + inline lit LitIrregular(lit x) const { return x | (lit)1; } + inline lit LitNot(lit x) const { return x ^ (lit)1; } + inline lit LitNotCond(lit x, bool c) const { return x ^ (lit)c; } + inline bool LitIsCompl(lit x) const { return x & (lit)1; } + inline bool LitIsEq(lit x, lit y) const { return x == y; } + inline var Var(lit x) const { return vVars[Lit2Bvar(x)]; } + inline var Level(lit x) const { return Var2Level[Var(x)]; } + inline lit Then(lit x) const { return LitNotCond(vObjs[LitRegular(x)], LitIsCompl(x)); } + inline lit Else(lit x) const { return LitNotCond(vObjs[LitIrregular(x)], LitIsCompl(x)); } + inline ref Ref(lit x) const { return vRefs[Lit2Bvar(x)]; } + inline double OneCount(lit x) const { + if(vOneCounts.empty()) + throw std::logic_error("fCountOnes was not set"); + if(LitIsCompl(x)) + return std::pow(2.0, nVars) - vOneCounts[Lit2Bvar(x)]; + return vOneCounts[Lit2Bvar(x)]; + } + + public: + inline void IncRef(lit x) { if(!vRefs.empty() && Ref(x) != RefMax()) vRefs[Lit2Bvar(x)]++; } + inline void DecRef(lit x) { if(!vRefs.empty() && Ref(x) != RefMax()) vRefs[Lit2Bvar(x)]--; } + + private: + inline bool Mark(lit x) const { return vMarks[Lit2Bvar(x)]; } + inline edge Edge(lit x) const { return vEdges[Lit2Bvar(x)]; } + inline void SetMark(lit x) { vMarks[Lit2Bvar(x)] = true; } + inline void ResetMark(lit x) { vMarks[Lit2Bvar(x)] = false; } + inline void IncEdge(lit x) { vEdges[Lit2Bvar(x)]++; } + inline void DecEdge(lit x) { vEdges[Lit2Bvar(x)]--; } + inline bool MarkOfBvar(bvar a) const { return vMarks[a]; } + inline edge EdgeOfBvar(bvar a) const { return vEdges[a]; } + inline void SetVarOfBvar(bvar a, var v) { vVars[a] = v; } + inline void SetThenOfBvar(bvar a, lit x) { vObjs[Bvar2Lit(a)] = x; } + inline void SetElseOfBvar(bvar a, lit x) { vObjs[Bvar2Lit(a, true)] = x; } + inline void SetMarkOfBvar(bvar a) { vMarks[a] = true; } + inline void ResetMarkOfBvar(bvar a) { vMarks[a] = false; } + inline void RemoveBvar(bvar a) { + var v = VarOfBvar(a); + SetVarOfBvar(a, VarMax()); + std::vector::iterator q = vvUnique[v].begin() + (UniqHash(ThenOfBvar(a), ElseOfBvar(a)) & vUniqueMasks[v]); + for(; *q; q = vNexts.begin() + *q) + if(*q == a) + break; + bvar next = vNexts[*q]; + vNexts[*q] = RemovedHead; + RemovedHead = *q; + *q = next; + vUniqueCounts[v]--; + } + + private: + void SetMark_rec(lit x) { + if(x < 2 || Mark(x)) + return; + SetMark(x); + SetMark_rec(Then(x)); + SetMark_rec(Else(x)); + } + void ResetMark_rec(lit x) { + if(x < 2 || !Mark(x)) + return; + ResetMark(x); + ResetMark_rec(Then(x)); + ResetMark_rec(Else(x)); + } + bvar CountNodes_rec(lit x) { + if(x < 2 || Mark(x)) + return 0; + SetMark(x); + return 1 + CountNodes_rec(Then(x)) + CountNodes_rec(Else(x)); + } + void CountEdges_rec(lit x) { + if(x < 2) + return; + IncEdge(x); + if(Mark(x)) + return; + SetMark(x); + CountEdges_rec(Then(x)); + CountEdges_rec(Else(x)); + } + void CountEdges() { + vEdges.resize(nObjsAlloc); + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + CountEdges_rec(Bvar2Lit(a)); + for(bvar a = 1; a <= (bvar)nVars; a++) + vEdges[a]++; + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + ResetMark_rec(Bvar2Lit(a)); + } + + public: + bool Resize() { + if(nObjsAlloc == nObjsMax) + return false; + lit nObjsAllocLit = (lit)nObjsAlloc << 1; + if(nObjsAllocLit > (lit)BvarMax()) + nObjsAlloc = BvarMax(); + else + nObjsAlloc = (bvar)nObjsAllocLit; + if(nVerbose >= 2) + std::cout << "Reallocating " << nObjsAlloc << " nodes" << std::endl; + vVars.resize(nObjsAlloc); + vObjs.resize((lit)nObjsAlloc * 2); + vNexts.resize(nObjsAlloc); + vMarks.resize(nObjsAlloc); + if(!vRefs.empty()) + vRefs.resize(nObjsAlloc); + if(!vEdges.empty()) + vEdges.resize(nObjsAlloc); + if(!vOneCounts.empty()) + vOneCounts.resize(nObjsAlloc); + return true; + } + void ResizeUnique(var v) { + uniq nUniqueSize, nUniqueSizeOld; + nUniqueSize = nUniqueSizeOld = vvUnique[v].size(); + nUniqueSize <<= 1; + if(!nUniqueSize) { + vUniqueTholds[v] = BvarMax(); + return; + } + if(nVerbose >= 2) + std::cout << "Reallocating " << nUniqueSize << " unique table entries for Var " << v << std::endl; + vvUnique[v].resize(nUniqueSize); + vUniqueMasks[v] = nUniqueSize - 1; + for(uniq i = 0; i < nUniqueSizeOld; i++) { + std::vector::iterator q, tail, tail1, tail2; + q = tail1 = vvUnique[v].begin() + i; + tail2 = q + nUniqueSizeOld; + while(*q) { + uniq hash = UniqHash(ThenOfBvar(*q), ElseOfBvar(*q)) & vUniqueMasks[v]; + if(hash == i) + tail = tail1; + else + tail = tail2; + if(tail != q) + *tail = *q, *q = 0; + q = vNexts.begin() + *tail; + if(tail == tail1) + tail1 = q; + else + tail2 = q; + } + } + vUniqueTholds[v] <<= 1; + if((lit)vUniqueTholds[v] > (lit)BvarMax()) + vUniqueTholds[v] = BvarMax(); + } + bool Gbc() { + if(nVerbose >= 2) + std::cout << "Garbage collect" << std::endl; + if(!vEdges.empty()) { + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(!EdgeOfBvar(a) && VarOfBvar(a) != VarMax()) + RemoveBvar(a); + } else { + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + SetMark_rec(Bvar2Lit(a)); + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(!MarkOfBvar(a) && VarOfBvar(a) != VarMax()) + RemoveBvar(a); + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + ResetMark_rec(Bvar2Lit(a)); + } + cache->Clear(); + return RemovedHead; + } + + private: + inline lit UniqueCreateInt(var v, lit x1, lit x0) { + std::vector::iterator p, q; + p = q = vvUnique[v].begin() + (UniqHash(x1, x0) & vUniqueMasks[v]); + for(; *q; q = vNexts.begin() + *q) + if(VarOfBvar(*q) == v && ThenOfBvar(*q) == x1 && ElseOfBvar(*q) == x0) + return Bvar2Lit(*q); + bvar next = *p; + if(nObjs < nObjsAlloc) + *p = nObjs++; + else if(RemovedHead) + *p = RemovedHead, RemovedHead = vNexts[*p]; + else + return LitMax(); + SetVarOfBvar(*p, v); + SetThenOfBvar(*p, x1); + SetElseOfBvar(*p, x0); + vNexts[*p] = next; + if(!vOneCounts.empty()) + vOneCounts[*p] = OneCount(x1) / 2 + OneCount(x0) / 2; + if(nVerbose >= 3) { + std::cout << "Create node " << std::setw(10) << *p << ": " + << "Var = " << std::setw(6) << v << ", " + << "Then = " << std::setw(10) << x1 << ", " + << "Else = " << std::setw(10) << x0; + if(!vOneCounts.empty()) + std::cout << ", Ones = " << std::setw(10) << vOneCounts[*q]; + std::cout << std::endl; + } + vUniqueCounts[v]++; + if(vUniqueCounts[v] > vUniqueTholds[v]) { + bvar a = *p; + ResizeUnique(v); + return Bvar2Lit(a); + } + return Bvar2Lit(*p); + } + inline lit UniqueCreate(var v, lit x1, lit x0) { + if(x1 == x0) + return x1; + lit x; + while(true) { + if(!LitIsCompl(x0)) + x = UniqueCreateInt(v, x1, x0); + else + x = UniqueCreateInt(v, LitNot(x1), LitNot(x0)); + if(x == LitMax()) { + bool fRemoved = false; + if(nGbc > 1) + fRemoved = Gbc(); + if(!Resize() && !fRemoved && (nGbc != 1 || !Gbc())) + throw std::length_error("Memout (node)"); + } else + break; + } + return LitIsCompl(x0)? LitNot(x): x; + } + lit And_rec(lit x, lit y) { + if(x == 0 || y == 1) + return x; + if(x == 1 || y == 0) + return y; + if(Lit2Bvar(x) == Lit2Bvar(y)) + return (x == y)? x: 0; + if(x > y) + std::swap(x, y); + lit z = cache->Lookup(x, y); + if(z != LitMax()) + return z; + var v; + lit x0, x1, y0, y1; + if(Level(x) < Level(y)) + v = Var(x), x1 = Then(x), x0 = Else(x), y0 = y1 = y; + else if(Level(x) > Level(y)) + v = Var(y), x0 = x1 = x, y1 = Then(y), y0 = Else(y); + else + v = Var(x), x1 = Then(x), x0 = Else(x), y1 = Then(y), y0 = Else(y); + lit z1 = And_rec(x1, y1); + IncRef(z1); + lit z0 = And_rec(x0, y0); + IncRef(z0); + z = UniqueCreate(v, z1, z0); + DecRef(z1); + DecRef(z0); + cache->Insert(x, y, z); + return z; + } + + private: + bvar Swap(var i) { + var v1 = Level2Var[i]; + var v2 = Level2Var[i + 1]; + bvar f = 0; + bvar diff = 0; + for(std::vector::iterator p = vvUnique[v1].begin(); p != vvUnique[v1].end(); p++) { + std::vector::iterator q = p; + while(*q) { + if(!EdgeOfBvar(*q)) { + SetVarOfBvar(*q, VarMax()); + bvar next = vNexts[*q]; + vNexts[*q] = RemovedHead; + RemovedHead = *q; + *q = next; + vUniqueCounts[v1]--; + continue; + } + lit f1 = ThenOfBvar(*q); + lit f0 = ElseOfBvar(*q); + if(Var(f1) == v2 || Var(f0) == v2) { + DecEdge(f1); + if(Var(f1) == v2 && !Edge(f1)) + DecEdge(Then(f1)), DecEdge(Else(f1)), diff--; + DecEdge(f0); + if(Var(f0) == v2 && !Edge(f0)) + DecEdge(Then(f0)), DecEdge(Else(f0)), diff--; + bvar next = vNexts[*q]; + vNexts[*q] = f; + f = *q; + *q = next; + vUniqueCounts[v1]--; + continue; + } + q = vNexts.begin() + *q; + } + } + while(f) { + lit f1 = ThenOfBvar(f); + lit f0 = ElseOfBvar(f); + lit f00, f01, f10, f11; + if(Var(f1) == v2) + f11 = Then(f1), f10 = Else(f1); + else + f10 = f11 = f1; + if(Var(f0) == v2) + f01 = Then(f0), f00 = Else(f0); + else + f00 = f01 = f0; + if(f11 == f01) + f1 = f11; + else { + f1 = UniqueCreate(v1, f11, f01); + if(!Edge(f1)) + IncEdge(f11), IncEdge(f01), diff++; + } + IncEdge(f1); + IncRef(f1); + if(f10 == f00) + f0 = f10; + else { + f0 = UniqueCreate(v1, f10, f00); + if(!Edge(f0)) + IncEdge(f10), IncEdge(f00), diff++; + } + IncEdge(f0); + DecRef(f1); + SetVarOfBvar(f, v2); + SetThenOfBvar(f, f1); + SetElseOfBvar(f, f0); + std::vector::iterator q = vvUnique[v2].begin() + (UniqHash(f1, f0) & vUniqueMasks[v2]); + lit next = vNexts[f]; + vNexts[f] = *q; + *q = f; + vUniqueCounts[v2]++; + f = next; + } + Var2Level[v1] = i + 1; + Var2Level[v2] = i; + Level2Var[i] = v2; + Level2Var[i + 1] = v1; + return diff; + } + void Sift() { + bvar count = CountNodes(); + std::vector sift_order(nVars); + for(var v = 0; v < nVars; v++) + sift_order[v] = v; + for(var i = 0; i < nVars; i++) { + var max_j = i; + for(var j = i + 1; j < nVars; j++) + if(vUniqueCounts[sift_order[j]] > vUniqueCounts[sift_order[max_j]]) + max_j = j; + if(max_j != i) + std::swap(sift_order[max_j], sift_order[i]); + } + for(var v = 0; v < nVars; v++) { + bvar lev = Var2Level[sift_order[v]]; + bool UpFirst = lev < (bvar)(nVars / 2); + bvar min_lev = lev; + bvar min_diff = 0; + bvar diff = 0; + bvar thold = count * (MaxGrowth - 1); + if(fReoVerbose) + std::cout << "Sift " << sift_order[v] << " : Level = " << lev << " Count = " << count << " Thold = " << thold << std::endl; + if(UpFirst) { + lev--; + for(; lev >= 0; lev--) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + if(diff < min_diff) + min_lev = lev, min_diff = diff, thold = (count + diff) * (MaxGrowth - 1); + else if(diff > thold) { + lev--; + break; + } + } + lev++; + } + for(; lev < (bvar)nVars - 1; lev++) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + if(diff <= min_diff) + min_lev = lev + 1, min_diff = diff, thold = (count + diff) * (MaxGrowth - 1); + else if(diff > thold) { + lev++; + break; + } + } + lev--; + if(UpFirst) { + for(; lev >= min_lev; lev--) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + } + } else { + for(; lev >= 0; lev--) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + if(diff <= min_diff) + min_lev = lev, min_diff = diff, thold = (count + diff) * (MaxGrowth - 1); + else if(diff > thold) { + lev--; + break; + } + } + lev++; + for(; lev < min_lev; lev++) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + } + } + count += min_diff; + if(fReoVerbose) + std::cout << "Sifted " << sift_order[v] << " : Level = " << min_lev << " Count = " << count << " Thold = " << thold << std::endl; + } + } + + public: + Man(int nVars_, Param p) { + nVerbose = p.nVerbose; + // parameter sanity check + if(p.nObjsMaxLog < p.nObjsAllocLog) + throw std::invalid_argument("nObjsMax must not be smaller than nObjsAlloc"); + if(nVars_ >= (int)VarMax()) + throw std::length_error("Memout (nVars) in init"); + nVars = nVars_; + lit nObjsMaxLit = (lit)1 << p.nObjsMaxLog; + if(!nObjsMaxLit) + throw std::length_error("Memout (nObjsMax) in init"); + if(nObjsMaxLit > (lit)BvarMax()) + nObjsMax = BvarMax(); + else + nObjsMax = (bvar)nObjsMaxLit; + lit nObjsAllocLit = (lit)1 << p.nObjsAllocLog; + if(!nObjsAllocLit) + throw std::length_error("Memout (nObjsAlloc) in init"); + if(nObjsAllocLit > (lit)BvarMax()) + nObjsAlloc = BvarMax(); + else + nObjsAlloc = (bvar)nObjsAllocLit; + if(nObjsAlloc <= (bvar)nVars) + throw std::invalid_argument("nObjsAlloc must be larger than nVars"); + uniq nUniqueSize = (uniq)1 << p.nUniqueSizeLog; + if(!nUniqueSize) + throw std::length_error("Memout (nUniqueSize) in init"); + // allocation + if(nVerbose) + std::cout << "Allocating " << nObjsAlloc << " nodes and " << nVars << " x " << nUniqueSize << " unique table entries" << std::endl; + vVars.resize(nObjsAlloc); + vObjs.resize((lit)nObjsAlloc * 2); + vNexts.resize(nObjsAlloc); + vMarks.resize(nObjsAlloc); + vvUnique.resize(nVars); + vUniqueMasks.resize(nVars); + vUniqueCounts.resize(nVars); + vUniqueTholds.resize(nVars); + for(var v = 0; v < nVars; v++) { + vvUnique[v].resize(nUniqueSize); + vUniqueMasks[v] = nUniqueSize - 1; + if((lit)(nUniqueSize * p.UniqueDensity) > (lit)BvarMax()) + vUniqueTholds[v] = BvarMax(); + else + vUniqueTholds[v] = (bvar)(nUniqueSize * p.UniqueDensity); + } + if(p.fCountOnes) { + if(nVars > 1023) + throw std::length_error("nVars must be less than 1024 to count ones"); + vOneCounts.resize(nObjsAlloc); + } + // set up cache + cache = new Cache(p.nCacheSizeLog, p.nCacheMaxLog, p.nCacheVerbose); + // create nodes for variables + nObjs = 1; + vVars[0] = VarMax(); + for(var v = 0; v < nVars; v++) + UniqueCreateInt(v, 1, 0); + // set up variable order + Var2Level.resize(nVars); + Level2Var.resize(nVars); + for(var v = 0; v < nVars; v++) { + if(p.pVar2Level) + Var2Level[v] = (*p.pVar2Level)[v]; + else + Var2Level[v] = v; + Level2Var[Var2Level[v]] = v; + } + // set other parameters + RemovedHead = 0; + nGbc = p.nGbc; + nReo = p.nReo; + MaxGrowth = p.MaxGrowth; + fReoVerbose = p.fReoVerbose; + if(nGbc || nReo != BvarMax()) + vRefs.resize(nObjsAlloc); + } + ~Man() { + if(nVerbose) { + std::cout << "Free " << nObjsAlloc << " nodes (" << nObjs << " live nodes)" << std::endl; + std::cout << "Free {"; + std::string delim; + for(var v = 0; v < nVars; v++) { + std::cout << delim << vvUnique[v].size(); + delim = ", "; + } + std::cout << "} unique table entries" << std::endl; + if(!vRefs.empty()) + std::cout << "Free " << vRefs.size() << " refs" << std::endl; + } + delete cache; + } + void Reorder() { + if(nVerbose >= 2) + std::cout << "Reorder" << std::endl; + int nGbc_ = nGbc; + nGbc = 0; + CountEdges(); + Sift(); + vEdges.clear(); + cache->Clear(); + nGbc = nGbc_; + } + inline lit And(lit x, lit y) { + if(nObjs > nReo) { + Reorder(); + while(nReo < nObjs) { + nReo <<= 1; + if((lit)nReo > (lit)BvarMax()) + nReo = BvarMax(); + } + } + return And_rec(x, y); + } + inline lit Or(lit x, lit y) { + return LitNot(And(LitNot(x), LitNot(y))); + } + + public: + void SetRef(std::vector const &vLits) { + vRefs.clear(); + vRefs.resize(nObjsAlloc); + for(size_t i = 0; i < vLits.size(); i++) + IncRef(vLits[i]); + } + void TurnOffReo() { + nReo = BvarMax(); + if(!nGbc) + vRefs.clear(); + } + bvar CountNodes() { + bvar count = 1; + if(!vEdges.empty()) { + for(bvar a = 1; a < nObjs; a++) + if(EdgeOfBvar(a)) + count++; + return count; + } + for(bvar a = 1; a <= (bvar)nVars; a++) { + count++; + SetMarkOfBvar(a); + } + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + count += CountNodes_rec(Bvar2Lit(a)); + for(bvar a = 1; a <= (bvar)nVars; a++) + ResetMarkOfBvar(a); + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + ResetMark_rec(Bvar2Lit(a)); + return count; + } + bvar CountNodes(std::vector const &vLits) { + bvar count = 1; + for(size_t i = 0; i < vLits.size(); i++) + count += CountNodes_rec(vLits[i]); + for(size_t i = 0; i < vLits.size(); i++) + ResetMark_rec(vLits[i]); + return count; + } + void PrintStats() { + bvar nRemoved = 0; + bvar a = RemovedHead; + while(a) + a = vNexts[a], nRemoved++; + bvar nLive = 1; + for(var v = 0; v < nVars; v++) + nLive += vUniqueCounts[v]; + std::cout << "ref: " << std::setw(10) << (vRefs.empty()? 0: CountNodes()) << ", " + << "used: " << std::setw(10) << nObjs << ", " + << "live: " << std::setw(10) << nLive << ", " + << "dead: " << std::setw(10) << nRemoved << ", " + << "alloc: " << std::setw(10) << nObjsAlloc + << std::endl; + } + }; + +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/aig/gia/giaNewTt.h b/src/aig/gia/giaNewTt.h new file mode 100644 index 000000000..494b8636b --- /dev/null +++ b/src/aig/gia/giaNewTt.h @@ -0,0 +1,281 @@ +/**CFile**************************************************************** + + FileName [giaNewTt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaNewTt.h,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__gia__giaNewTt_h +#define ABC__aig__gia__giaNewTt_h + +#include +#include +#include +#include +#include + +ABC_NAMESPACE_CXX_HEADER_START + +namespace NewTt { + + typedef int bvar; + typedef unsigned lit; + typedef unsigned short ref; + typedef unsigned long long size; + + static inline bvar BvarMax() { return std::numeric_limits::max(); } + static inline lit LitMax() { return std::numeric_limits::max(); } + static inline ref RefMax() { return std::numeric_limits::max(); } + static inline size SizeMax() { return std::numeric_limits::max(); } + + struct Param { + int nObjsAllocLog; + int nObjsMaxLog; + int nVerbose; + bool fCountOnes; + int nGbc; + int nReo; // dummy + Param() { + nObjsAllocLog = 15; + nObjsMaxLog = 20; + nVerbose = 0; + fCountOnes = false; + nGbc = 0; + nReo = BvarMax(); + } + }; + + class Man { + private: + typedef unsigned long long word; + typedef std::bitset<64> bsw; + static inline int ww() { return 64; } // word width + static inline int lww() { return 6; } // log word width + static inline word one() {return 0xffffffffffffffffull; } + static inline word vars(int i) { + static const word vars[] = {0xaaaaaaaaaaaaaaaaull, + 0xccccccccccccccccull, + 0xf0f0f0f0f0f0f0f0ull, + 0xff00ff00ff00ff00ull, + 0xffff0000ffff0000ull, + 0xffffffff00000000ull}; + return vars[i]; + } + static inline word ones(int i) { + static const word ones[] = {0x0000000000000001ull, + 0x0000000000000003ull, + 0x000000000000000full, + 0x00000000000000ffull, + 0x000000000000ffffull, + 0x00000000ffffffffull, + 0xffffffffffffffffull}; + return ones[i]; + } + + private: + int nVars; + bvar nObjs; + bvar nObjsAlloc; + bvar nObjsMax; + size nSize; + size nTotalSize; + std::vector vVals; + std::vector vDeads; + std::vector vRefs; + int nGbc; + int nVerbose; + + public: + inline lit Bvar2Lit(bvar a) const { return (lit)a << 1; } + inline bvar Lit2Bvar(lit x) const { return (bvar)(x >> 1); } + inline lit IthVar(int v) const { return ((lit)v + 1) << 1; } + inline lit LitNot(lit x) const { return x ^ (lit)1; } + inline lit LitNotCond(lit x, bool c) const { return x ^ (lit)c; } + inline bool LitIsCompl(lit x) const { return x & (lit)1; } + inline ref Ref(lit x) const { return vRefs[Lit2Bvar(x)]; } + inline lit Const0() const { return (lit)0; } + inline lit Const1() const { return (lit)1; } + inline bool IsConst0(lit x) const { + bvar a = Lit2Bvar(x); + word c = LitIsCompl(x)? one(): 0; + for(size j = 0; j < nSize; j++) + if(vVals[nSize * a + j] ^ c) + return false; + return true; + } + inline bool IsConst1(lit x) const { + bvar a = Lit2Bvar(x); + word c = LitIsCompl(x)? one(): 0; + for(size j = 0; j < nSize; j++) + if(~(vVals[nSize * a + j] ^ c)) + return false; + return true; + } + inline bool LitIsEq(lit x, lit y) const { + if(x == y) + return true; + if(x == LitMax() || y == LitMax()) + return false; + bvar xvar = Lit2Bvar(x); + bvar yvar = Lit2Bvar(y); + word c = LitIsCompl(x) ^ LitIsCompl(y)? one(): 0; + for(size j = 0; j < nSize; j++) + if(vVals[nSize * xvar + j] ^ vVals[nSize * yvar + j] ^ c) + return false; + return true; + } + inline size OneCount(lit x) const { + bvar a = Lit2Bvar(x); + size count = 0; + if(nVars > 6) { + for(size j = 0; j < nSize; j++) + count += bsw(vVals[nSize * a + j]).count(); + } else + count = bsw(vVals[nSize * a] & ones(nVars)).count(); + return LitIsCompl(x)? ((size)1 << nVars) - count: count; + } + + public: + inline void IncRef(lit x) { if(!vRefs.empty() && Ref(x) != RefMax()) vRefs[Lit2Bvar(x)]++; } + inline void DecRef(lit x) { if(!vRefs.empty() && Ref(x) != RefMax()) vRefs[Lit2Bvar(x)]--; } + + public: + bool Resize() { + if(nObjsAlloc == nObjsMax) + return false; + lit nObjsAllocLit = (lit)nObjsAlloc << 1; + if(nObjsAllocLit > (lit)BvarMax()) + nObjsAlloc = BvarMax(); + else + nObjsAlloc = (bvar)nObjsAllocLit; + nTotalSize = nTotalSize << 1; + if(nVerbose >= 2) + std::cout << "Reallocating " << nObjsAlloc << " nodes" << std::endl; + vVals.resize(nTotalSize); + if(!vRefs.empty()) + vRefs.resize(nObjsAlloc); + return true; + } + bool Gbc() { + if(nVerbose >= 2) + std::cout << "Garbage collect" << std::endl; + for(bvar a = nVars + 1; a < nObjs; a++) + if(!vRefs[a]) + vDeads.push_back(a); + return vDeads.size(); + } + + public: + Man(int nVars, Param p): nVars(nVars) { + if(p.nObjsMaxLog < p.nObjsAllocLog) + throw std::invalid_argument("nObjsMax must not be smaller than nObjsAlloc"); + if(nVars >= lww()) + nSize = 1ull << (nVars - lww()); + else + nSize = 1; + if(!nSize) + throw std::length_error("Memout (nVars) in init"); + if(!(nSize << p.nObjsMaxLog)) + throw std::length_error("Memout (nObjsMax) in init"); + lit nObjsMaxLit = (lit)1 << p.nObjsMaxLog; + if(!nObjsMaxLit) + throw std::length_error("Memout (nObjsMax) in init"); + if(nObjsMaxLit > (lit)BvarMax()) + nObjsMax = BvarMax(); + else + nObjsMax = (bvar)nObjsMaxLit; + lit nObjsAllocLit = (lit)1 << p.nObjsAllocLog; + if(!nObjsAllocLit) + throw std::length_error("Memout (nObjsAlloc) in init"); + if(nObjsAllocLit > (lit)BvarMax()) + nObjsAlloc = BvarMax(); + else + nObjsAlloc = (bvar)nObjsAllocLit; + if(nObjsAlloc <= (bvar)nVars) + throw std::invalid_argument("nObjsAlloc must be larger than nVars"); + nTotalSize = nSize << p.nObjsAllocLog; + vVals.resize(nTotalSize); + if(p.fCountOnes && nVars > 63) + throw std::length_error("nVars must be less than 64 to count ones"); + nObjs = 1; + for(int i = 0; i < 6 && i < nVars; i++) { + for(size j = 0; j < nSize; j++) + vVals[nSize * nObjs + j] = vars(i); + nObjs++; + } + for(int i = 0; i < nVars - 6; i++) { + for(size j = 0; j < nSize; j += (2ull << i)) + for(size k = 0; k < (1ull << i); k++) + vVals[nSize * nObjs + j + k] = one(); + nObjs++; + } + nVerbose = p.nVerbose; + nGbc = p.nGbc; + if(nGbc || p.nReo != BvarMax()) + vRefs.resize(nObjsAlloc); + } + inline lit And(lit x, lit y) { + bvar xvar = Lit2Bvar(x); + bvar yvar = Lit2Bvar(y); + word xcompl = LitIsCompl(x)? one(): 0; + word ycompl = LitIsCompl(y)? one(): 0; + unsigned j; + if(nObjs >= nObjsAlloc && vDeads.empty()) { + bool fRemoved = false; + if(nGbc > 1) + fRemoved = Gbc(); + if(!Resize() && !fRemoved && (nGbc != 1 || !Gbc())) + throw std::length_error("Memout (node)"); + } + bvar zvar; + if(nObjs < nObjsAlloc) + zvar = nObjs++; + else + zvar = vDeads.back(), vDeads.resize(vDeads.size() - 1); + for(j = 0; j < nSize; j++) + vVals[nSize * zvar + j] = (vVals[nSize * xvar + j] ^ xcompl) & (vVals[nSize * yvar + j] ^ ycompl); + return zvar << 1; + } + inline lit Or(lit x, lit y) { + return LitNot(And(LitNot(x), LitNot(y))); + } + void Reorder() {} // dummy + + public: + void SetRef(std::vector const &vLits) { + vRefs.clear(); + vRefs.resize(nObjsAlloc); + for(size_t i = 0; i < vLits.size(); i++) + IncRef(vLits[i]); + } + void TurnOffReo() { + if(!nGbc) + vRefs.clear(); + } + void PrintNode(lit x) const { + bvar a = Lit2Bvar(x); + word c = LitIsCompl(x)? one(): 0; + for(size j = 0; j < nSize; j++) + std::cout << bsw(vVals[nSize * a + j] ^ c); + std::cout << std::endl; + } + }; + +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/aig/gia/giaPat2.c b/src/aig/gia/giaPat2.c index dff2c59d2..3f928e4dd 100644 --- a/src/aig/gia/giaPat2.c +++ b/src/aig/gia/giaPat2.c @@ -851,7 +851,7 @@ Gia_Man_t * Gia_ManDupCones2( Gia_Man_t * p, int * pOuts, int nOuts, Vec_Int_t * ***********************************************************************/ int Min_ManRemoveItem( Vec_Wec_t * vCexes, int iItem, int iFirst, int iLimit ) { - Vec_Int_t * vLevel, * vLevel0 = Vec_WecEntry(vCexes, iItem); int i; + Vec_Int_t * vLevel = NULL, * vLevel0 = Vec_WecEntry(vCexes, iItem); int i; assert( iFirst <= iItem && iItem < iLimit ); Vec_WecForEachLevelReverseStartStop( vCexes, vLevel, i, iLimit, iFirst ) if ( Vec_IntSize(vLevel) > 0 ) diff --git a/src/aig/gia/giaQbf.c b/src/aig/gia/giaQbf.c index ac6fb22ce..6ccbe4605 100644 --- a/src/aig/gia/giaQbf.c +++ b/src/aig/gia/giaQbf.c @@ -482,6 +482,45 @@ void Gia_QbfDumpFile( Gia_Man_t * pGia, int nPars ) Vec_IntFree( vVarMap ); printf( "The 2QBF formula was written into file \"%s\".\n", pFileName ); } +void Gia_QbfDumpFileInv( Gia_Man_t * pGia, int nPars ) +{ + // original problem: \exists p \forall x \exists y. M(p,x,y) + // negated problem: \forall p \exists x \exists y. !M(p,x,y) + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pGia, 8, 0, 1, 0, 0 ); + Vec_Int_t * vVarMap, * vForAlls, * vExists1, * vExists2; + Gia_Obj_t * pObj; + char * pFileName; + int i, Entry; + // complement the last clause + //int * pLit = pCnf->pClauses[pCnf->nClauses] - 1; *pLit ^= 1; + // create var map + vVarMap = Vec_IntStart( pCnf->nVars ); + Gia_ManForEachCi( pGia, pObj, i ) + Vec_IntWriteEntry( vVarMap, pCnf->pVarNums[Gia_ManCiIdToId(pGia, i)], i < nPars ? 1 : 2 ); + // create various maps + vExists1 = Vec_IntAlloc( nPars ); + vForAlls = Vec_IntAlloc( Gia_ManCiNum(pGia) - nPars ); + vExists2 = Vec_IntAlloc( pCnf->nVars - Gia_ManCiNum(pGia) ); + Vec_IntForEachEntry( vVarMap, Entry, i ) + if ( Entry == 1 ) + Vec_IntPush( vExists1, i ); + else if ( Entry == 2 ) + Vec_IntPush( vForAlls, i ); + else + Vec_IntPush( vExists2, i ); + // generate CNF + pFileName = Extra_FileNameGenericAppend( pGia->pSpec, ".qdimacs" ); + Cnf_DataWriteIntoFileInv( pCnf, pFileName, 0, vExists1, vForAlls, vExists2 ); + Cnf_DataFree( pCnf ); + Vec_IntFree( vExists1 ); + Vec_IntFree( vForAlls ); + Vec_IntFree( vExists2 ); + Vec_IntFree( vVarMap ); + printf( "The 2QBF formula was written into file \"%s\".\n", pFileName ); +} + + + /**Function************************************************************* diff --git a/src/aig/gia/giaShow.c b/src/aig/gia/giaShow.c index ead794eba..c3a211849 100644 --- a/src/aig/gia/giaShow.c +++ b/src/aig/gia/giaShow.c @@ -1125,7 +1125,7 @@ void Gia_ShowProcess( Gia_Man_t * p, char * pFileName, Vec_Int_t * vBold, Vec_In } void Gia_ManShow( Gia_Man_t * pMan, Vec_Int_t * vBold, int fAdders, int fFadds, int fPath ) { - extern void Abc_ShowFile( char * FileNameDot ); + extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); char FileNameDot[200]; FILE * pFile; Vec_Int_t * vXors = NULL, * vAdds = fAdders ? Ree_ManComputeCuts( pMan, &vXors, 0 ) : NULL; @@ -1145,7 +1145,7 @@ void Gia_ManShow( Gia_Man_t * pMan, Vec_Int_t * vBold, int fAdders, int fFadds, else Gia_WriteDotAigSimple( pMan, FileNameDot, vBold ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); Vec_IntFreeP( &vAdds ); Vec_IntFreeP( &vXors ); diff --git a/src/aig/gia/giaSif.c b/src/aig/gia/giaSif.c index d25ae5db2..db7629fb3 100644 --- a/src/aig/gia/giaSif.c +++ b/src/aig/gia/giaSif.c @@ -6,7 +6,7 @@ PackageName [Scalable AIG package.] - Synopsis [] + Synopsis [Sequential mapping.] Author [Alan Mishchenko] @@ -19,11 +19,9 @@ ***********************************************************************/ #include "gia.h" -#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START - //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// @@ -43,7 +41,348 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -static inline void Gia_ManCutMerge( int * pCut, int * pCut1, int * pCut2, int nSize ) +void Gia_ManSifDupNode_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManSifDupNode_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManSifDupNode_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManAppendAnd2( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +void Gia_ManSifDupNode( Gia_Man_t * pNew, Gia_Man_t * p, int iObj, Vec_Int_t * vCopy ) +{ + int k, iFan; + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + Gia_ManIncrementTravId( p ); + Gia_LutForEachFanin( p, iObj, iFan, k ) + { + assert( Vec_IntEntry(vCopy, iFan) >= 0 ); + Gia_ManObj(p, iFan)->Value = Vec_IntEntry(vCopy, iFan); + Gia_ObjUpdateTravIdCurrentId(p, iFan); + } + Gia_ManSifDupNode_rec( pNew, p, pObj ); + Vec_IntWriteEntry( vCopy, iObj, pObj->Value ); +} +Vec_Int_t * Gia_ManSifInitNeg( Gia_Man_t * p, Vec_Int_t * vMoves, Vec_Int_t * vRegs ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( Vec_IntSize(vRegs) ); + Gia_Obj_t * pObj; int i, iObj; + Gia_Man_t * pNew = Gia_ManStart( 1000 ), * pTemp; + Vec_Int_t * vCopy = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_IntWriteEntry( vCopy, 0, 0 ); + Gia_ManForEachRo( p, pObj, i ) + Vec_IntWriteEntry( vCopy, Gia_ObjId(p, pObj), Gia_ManAppendCi(pNew) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Vec_IntForEachEntry( vMoves, iObj, i ) + Gia_ManSifDupNode( pNew, p, iObj, vCopy ); + Vec_IntForEachEntry( vRegs, iObj, i ) + { + int iLit = Vec_IntEntry( vCopy, iObj ); + assert( iLit >= 0 ); + Gia_ManAppendCo( pNew, iLit ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManSetPhase( pNew ); + Gia_ManForEachPo( pNew, pObj, i ) + Vec_IntPush( vRes, pObj->fPhase ); + Gia_ManStop( pNew ); + Vec_IntFree( vCopy ); + assert( Vec_IntSize(vRes) == Vec_IntSize(vRegs) ); + return vRes; +} +Vec_Int_t * Gia_ManSifInitPos( Gia_Man_t * p, Vec_Int_t * vMoves, Vec_Int_t * vRegs ) +{ + extern int * Abc_NtkSolveGiaMiter( Gia_Man_t * p ); + int i, iObj, iLitAnd = 1, * pResult = NULL; + Gia_Obj_t * pObj; Vec_Int_t * vRes = NULL; + Gia_Man_t * pNew = Gia_ManStart( 1000 ), * pTemp; + Vec_Int_t * vCopy = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_IntWriteEntry( vCopy, 0, 0 ); + Vec_IntForEachEntry( vRegs, iObj, i ) + Vec_IntWriteEntry( vCopy, iObj, Gia_ManAppendCi(pNew) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Vec_IntForEachEntry( vMoves, iObj, i ) + Gia_ManSifDupNode( pNew, p, iObj, vCopy ); + Gia_ManForEachRi( p, pObj, i ) + { + int iFan = Gia_ObjFaninId0p(p, pObj); + int iLit = Vec_IntEntry(vCopy, iFan); + if ( iLit == -1 ) + continue; + iLit = Abc_LitNotCond( iLit, Gia_ObjFaninC0(pObj) ); + iLitAnd = Gia_ManAppendAnd2( pNew, iLitAnd, Abc_LitNot(iLit) ); + } + Gia_ManAppendCo( pNew, iLitAnd ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + pResult = Abc_NtkSolveGiaMiter( pNew ); + if ( pResult ) + { + vRes = Vec_IntAllocArray( pResult, Vec_IntSize(vRegs) ); + Gia_ManSetPhasePattern( pNew, vRes ); + assert( Gia_ManPo(pNew, 0)->fPhase == 1 ); + } + else + { + vRes = Vec_IntStart( Vec_IntSize(vRegs) ); + printf( "***!!!*** The SAT problem has no solution. Using all-0 initial state. ***!!!***\n" ); + } + Gia_ManStop( pNew ); + Vec_IntFree( vCopy ); + assert( Vec_IntSize(vRes) == Vec_IntSize(vRegs) ); + return vRes; +} +Gia_Man_t * Gia_ManSifDerive( Gia_Man_t * p, Vec_Int_t * vCounts, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; Gia_Obj_t * pObj; + Vec_Int_t * vCopy = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_Int_t * vCopy2 = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_Int_t * vLuts[3], * vRos[3], * vRegs[2], * vInits[2], * vTemp; + int i, k, Id, iFan; + for ( i = 0; i < 3; i++ ) + { + vLuts[i] = Vec_IntAlloc(100); + vRos[i] = Vec_IntAlloc(100); + if ( i == 2 ) break; + vRegs[i] = Vec_IntAlloc(100); + } + Gia_ManForEachLut( p, i ) + if ( Vec_IntEntry(vCounts, i) == 1 ) + Vec_IntPush( vLuts[0], i ); + else if ( Vec_IntEntry(vCounts, i) == -1 ) + Vec_IntPush( vLuts[1], i ); + else if ( Vec_IntEntry(vCounts, i) == 0 ) + Vec_IntPush( vLuts[2], i ); + else assert( 0 ); + assert( Vec_IntSize(vLuts[0]) || Vec_IntSize(vLuts[1]) ); + if ( Vec_IntSize(vLuts[0]) ) + { + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_ObjSetTravIdCurrentId(p, Id); + Gia_ManForEachRo( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(Gia_ObjRoToRi(p, pObj))) ) + Vec_IntPush( vRos[0], Gia_ObjId(p, pObj) ); + assert( !Vec_IntSize(vLuts[0]) == !Vec_IntSize(vRos[0]) ); + } + if ( Vec_IntSize(vLuts[1]) ) + { + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLuts[1], Id, i ) + Gia_LutForEachFanin( p, Id, iFan, k ) + Gia_ObjSetTravIdCurrentId(p, iFan); + Gia_ManForEachRo( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + Vec_IntPush( vRos[1], Gia_ObjId(p, pObj) ); + assert( !Vec_IntSize(vLuts[1]) == !Vec_IntSize(vRos[1]) ); + } + Gia_ManIncrementTravId( p ); + for ( k = 0; k < 2; k++ ) + Vec_IntForEachEntry( vRos[k], Id, i ) + Gia_ObjSetTravIdCurrentId(p, Id); + Gia_ManForEachRo( p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) + Vec_IntPush( vRos[2], Gia_ObjId(p, pObj) ); + + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_ObjSetTravIdCurrentId(p, Id); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_LutForEachFanin( p, Id, iFan, k ) + if ( !Gia_ObjUpdateTravIdCurrentId(p, iFan) ) + Vec_IntPush( vRegs[0], iFan ); + Vec_IntSort( vRegs[0], 0 ); + assert( Vec_IntCountDuplicates(vRegs[1]) == 0 ); + assert( !Vec_IntSize(vLuts[0]) == !Vec_IntSize(vRegs[0]) ); + + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_LutForEachFanin( p, Id, iFan, k ) + Gia_ObjSetTravIdCurrentId(p, iFan); + Vec_IntForEachEntry( vLuts[2], Id, i ) + Gia_LutForEachFanin( p, Id, iFan, k ) + Gia_ObjSetTravIdCurrentId(p, iFan); + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjSetTravIdCurrentId(p, Gia_ObjFaninId0p(p, pObj)); + Vec_IntForEachEntry( vRos[1], Id, i ) + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + Vec_IntPush( vRegs[1], Id ); + Vec_IntForEachEntry( vLuts[1], Id, i ) + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + Vec_IntPush( vRegs[1], Id ); + Vec_IntSort( vRegs[1], 0 ); + assert( Vec_IntCountDuplicates(vRegs[1]) == 0 ); + assert( !Vec_IntSize(vLuts[1]) == !Vec_IntSize(vRegs[1]) ); + + vInits[0] = Vec_IntSize(vLuts[0]) ? Gia_ManSifInitPos( p, vLuts[0], vRegs[0] ) : Vec_IntAlloc(0); + vInits[1] = Vec_IntSize(vLuts[1]) ? Gia_ManSifInitNeg( p, vLuts[1], vRegs[1] ) : Vec_IntAlloc(0); + + if ( fVerbose ) + { + printf( "Flops : %5d %5d %5d\n", Vec_IntSize(vRos[0]), Vec_IntSize(vRos[1]), Vec_IntSize(vRos[2]) ); + printf( "LUTs : %5d %5d %5d\n", Vec_IntSize(vLuts[0]), Vec_IntSize(vLuts[1]), Vec_IntSize(vLuts[2]) ); + printf( "Spots : %5d %5d %5d\n", Vec_IntSize(vRegs[0]), Vec_IntSize(vRegs[1]), 0 ); + } + + pNew = Gia_ManStart( Gia_ManObjNum(p) + Vec_IntSize(vRegs[0]) + Vec_IntSize(vRegs[1]) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + + Vec_IntWriteEntry( vCopy, 0, 0 ); + Gia_ManForEachPi( p, pObj, i ) + Vec_IntWriteEntry( vCopy, Gia_ObjId(p, pObj), Gia_ManAppendCi(pNew) ); + Vec_IntForEachEntry( vRos[2], Id, i ) + Vec_IntWriteEntry( vCopy, Id, Gia_ManAppendCi(pNew) ); + Vec_IntForEachEntry( vRegs[1], Id, i ) + Vec_IntWriteEntry( vCopy, Id, Abc_LitNotCond(Gia_ManAppendCi(pNew), Vec_IntEntry(vInits[1], i)) ); + + vTemp = Vec_IntAlloc(100); + Vec_IntForEachEntry( vRegs[0], Id, i ) + Vec_IntPush( vTemp, Vec_IntEntry(vCopy, Id) ); + Vec_IntForEachEntry( vRegs[0], Id, i ) + Vec_IntWriteEntry( vCopy, Id, Abc_LitNotCond(Gia_ManAppendCi(pNew), Vec_IntEntry(vInits[0], i)) ); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_ManSifDupNode( pNew, p, Id, vCopy ); + Vec_IntForEachEntry( vRegs[0], Id, i ) + Vec_IntWriteEntry( vCopy, Id, Vec_IntEntry(vTemp, i) ); + Vec_IntFree( vTemp ); + + Gia_ManForEachRoToRiVec( vRos[0], p, pObj, i ) + Vec_IntWriteEntry( vCopy, Vec_IntEntry(vRos[0], i), Abc_LitNotCond(Vec_IntEntry(vCopy, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj)) ); + Vec_IntForEachEntry( vLuts[2], Id, i ) + Gia_ManSifDupNode( pNew, p, Id, vCopy ); + + Gia_ManForEachRoToRiVec( vRos[1], p, pObj, i ) + Vec_IntWriteEntry( vCopy2, Vec_IntEntry(vRos[1], i), Abc_LitNotCond(Vec_IntEntry(vCopy, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj)) ); + Vec_IntForEachEntry( vLuts[1], Id, i ) + Gia_ManSifDupNode( pNew, p, Id, vCopy2 ); + + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vCopy, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj)) ); + Gia_ManForEachRoToRiVec( vRos[2], p, pObj, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vCopy, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj)) ); + Vec_IntForEachEntry( vRegs[1], Id, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vCopy2, Id), Vec_IntEntry(vInits[1], i)) ); + Vec_IntForEachEntry( vRegs[0], Id, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vCopy, Id), Vec_IntEntry(vInits[0], i)) ); + + Gia_ManSetRegNum( pNew, Vec_IntSize(vRos[2]) + Vec_IntSize(vRegs[0]) + Vec_IntSize(vRegs[1]) ); + + for ( i = 0; i < 3; i++ ) + { + Vec_IntFreeP( &vLuts[i] ); + Vec_IntFreeP( &vRos[i] ); + if ( i == 2 ) break; + Vec_IntFreeP( &vRegs[i] ); + Vec_IntFreeP( &vInits[i] ); + } + Vec_IntFree( vCopy ); + Vec_IntFree( vCopy2 ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSifArea_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vCuts, int nSize ) +{ + int i, * pCut, Area = 1; + if ( Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return 0; + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + pCut = Vec_IntEntryP( vCuts, Gia_ObjId(p, pObj)*nSize ); + for ( i = 1; i <= pCut[0]; i++ ) + Area += Gia_ManSifArea_rec( p, Gia_ManObj(p, pCut[i] >> 8), vCuts, nSize ); + return Area; +} +int Gia_ManSifArea( Gia_Man_t * p, Vec_Int_t * vCuts, int nSize ) +{ + Gia_Obj_t * pObj; int i, nArea = 0; + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + nArea += Gia_ManSifArea_rec( p, Gia_ObjFanin0(pObj), vCuts, nSize ); + return nArea; +} +int Gia_ManSifDelay_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) +{ + int i, * pCut, Delay, nFails = 0; + if ( Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return 0; + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + pCut = Vec_IntEntryP( vCuts, Gia_ObjId(p, pObj)*nSize ); + Delay = -ABC_INFINITY-10000; + for ( i = 1; i <= pCut[0]; i++ ) + { + nFails += Gia_ManSifDelay_rec( p, Gia_ManObj(p, pCut[i] >> 8), vCuts, vTimes, nSize ); + Delay = Abc_MaxInt( Delay, Vec_IntEntry(vTimes, pCut[i] >> 8) ); + } + Delay += 1; + return nFails + (int)(Delay > Vec_IntEntry(vTimes, Gia_ObjId(p, pObj))); +} +int Gia_ManSifDelay( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) +{ + Gia_Obj_t * pObj; int i, nFails = 0; + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + nFails += Gia_ManSifDelay_rec( p, Gia_ObjFanin0(pObj), vCuts, vTimes, nSize ); + return nFails; +} +static inline int Gia_ManSifTimeToCount( int Value, int Period ) +{ + return (Period*0xFFFF + Value)/Period + ((Period*0xFFFF + Value)%Period != 0) - 0x10000; +} +Vec_Int_t * Gia_ManSifTimesToCounts( Gia_Man_t * p, Vec_Int_t * vTimes, int Period ) +{ + int i, Times; + Vec_Int_t * vCounts = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_IntFillExtra( vTimes, Gia_ManObjNum(p), 0 ); + Vec_IntForEachEntry( vTimes, Times, i ) + if ( Gia_ObjIsLut(p, i) ) + Vec_IntWriteEntry( vCounts, i, Gia_ManSifTimeToCount(Times, Period) ); + return vCounts; +} +Gia_Man_t * Gia_ManSifTransform( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; Vec_Int_t * vCounts = NULL; + if ( fVerbose ) + printf( "Current area = %d. Period = %d. ", Gia_ManSifArea(p, vCuts, nLutSize+1), Period ); + if ( fVerbose ) + printf( "Delay checking failed for %d cuts.\n", Gia_ManSifDelay( p, vCuts, vTimes, nLutSize+1 ) ); + vCounts = Gia_ManSifTimesToCounts( p, vTimes, Period ); + pNew = Gia_ManSifDerive( p, vCounts, fVerbose ); + Vec_IntFreeP( &vCounts ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSifCutMerge( int * pCut, int * pCut1, int * pCut2, int nSize ) { int * pBeg = pCut+1; int * pBeg1 = pCut1+1; @@ -85,7 +424,7 @@ static inline void Gia_ManCutMerge( int * pCut, int * pCut1, int * pCut2, int nS pCut[0] = pBeg-(pCut+1); assert( pCut[0] < nSize ); } -static inline int Gia_ManCutChoice( Gia_Man_t * p, int Level, int iObj, int iSibl, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) +static inline int Gia_ManSifCutChoice( Gia_Man_t * p, int Level, int iObj, int iSibl, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) { int * pCut = Vec_IntEntryP( vCuts, iObj*nSize ); int * pCut2 = Vec_IntEntryP( vCuts, iSibl*nSize ); @@ -97,127 +436,165 @@ static inline int Gia_ManCutChoice( Gia_Man_t * p, int Level, int iObj, int iSib pCut[i] = pCut2[i]; return Level2; } -static inline int Gia_ManCutOne( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) +static inline int Gia_ManSifCutOne( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) { Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); int iFan0 = Gia_ObjFaninId0(pObj, iObj); int iFan1 = Gia_ObjFaninId1(pObj, iObj); - int Cut0[2] = { 1, iFan0 }; - int Cut1[2] = { 1, iFan1 }; + int Cut0[2] = { 1, iFan0 << 8 }; + int Cut1[2] = { 1, iFan1 << 8 }; int * pCut = Vec_IntEntryP( vCuts, iObj*nSize ); int * pCut0 = Vec_IntEntryP( vCuts, iFan0*nSize ); int * pCut1 = Vec_IntEntryP( vCuts, iFan1*nSize ); int Level_ = Vec_IntEntry( vTimes, iObj ); int Level0 = Vec_IntEntry( vTimes, iFan0 ); int Level1 = Vec_IntEntry( vTimes, iFan1 ); - int Level = Abc_MaxInt( Level0, Level1 ); - if ( Level == 0 ) - Level = 1; + int Level = -ABC_INFINITY, i; + assert( pCut0[0] > 0 && pCut1[0] > 0 ); if ( Level0 == Level1 ) - Gia_ManCutMerge( pCut, pCut0, pCut1, nSize ); + Gia_ManSifCutMerge( pCut, pCut0, pCut1, nSize ); else if ( Level0 > Level1 ) - Gia_ManCutMerge( pCut, pCut0, Cut1, nSize ); + Gia_ManSifCutMerge( pCut, pCut0, Cut1, nSize ); else //if ( Level0 < Level1 ) - Gia_ManCutMerge( pCut, pCut1, Cut0, nSize ); + Gia_ManSifCutMerge( pCut, pCut1, Cut0, nSize ); if ( pCut[0] == -1 ) { pCut[0] = 2; - pCut[1] = iFan0; - pCut[2] = iFan1; - Level++; + pCut[1] = iFan0 << 8; + pCut[2] = iFan1 << 8; } + for ( i = 1; i <= pCut[0]; i++ ) + Level = Abc_MaxInt( Level, Vec_IntEntry(vTimes, pCut[i] >> 8) ); + Level++; if ( Gia_ObjSibl(p, iObj) ) - Level = Gia_ManCutChoice( p, Level, iObj, Gia_ObjSibl(p, iObj), vCuts, vTimes, nSize ); + Level = Gia_ManSifCutChoice( p, Level, iObj, Gia_ObjSibl(p, iObj), vCuts, vTimes, nSize ); assert( pCut[0] > 0 && pCut[0] < nSize ); Vec_IntUpdateEntry( vTimes, iObj, Level ); return Level > Level_; } -int Gia_ManCheckIter( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period ) +int Gia_ManSifCheckIter( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period ) { int i, fChange = 0, nSize = nLutSize+1; Gia_Obj_t * pObj, * pObjRi, * pObjRo; - Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) - Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObjRo), Vec_IntEntry(vTimes, Gia_ObjId(p, pObjRi)) - Period ); Gia_ManForEachAnd( p, pObj, i ) - fChange |= Gia_ManCutOne( p, i, vCuts, vTimes, nSize ); - Gia_ManForEachRi( p, pObj, i ) + fChange |= Gia_ManSifCutOne( p, i, vCuts, vTimes, nSize ); + Gia_ManForEachCo( p, pObj, i ) Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), Vec_IntEntry(vTimes, Gia_ObjFaninId0p(p, pObj)) ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) + { + int TimeNew = Vec_IntEntry(vTimes, Gia_ObjId(p, pObjRi)) - Period; + TimeNew = Abc_MaxInt( TimeNew, Vec_IntEntry(vTimes, Gia_ObjId(p, pObjRo)) ); + Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObjRo), TimeNew ); + } return fChange; } -int Gia_ManCheckPeriod( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period, int * pIters ) +int Gia_ManSifCheckPeriod( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period, int * pIters ) { - Gia_Obj_t * pObj; int i; + Gia_Obj_t * pObj; int i, Id, nSize = nLutSize+1; assert( Gia_ManRegNum(p) > 0 ); - Vec_IntFill( vTimes, Gia_ManObjNum(p), -ABC_INFINITY ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( vCuts, Id*nSize, 1 ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( vCuts, Id*nSize+1, Id << 8 ); + Vec_IntFill( vTimes, Gia_ManObjNum(p), -Period ); Vec_IntWriteEntry( vTimes, 0, 0 ); Gia_ManForEachPi( p, pObj, i ) Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), 0 ); for ( *pIters = 0; *pIters < 100; (*pIters)++ ) { - if ( !Gia_ManCheckIter(p, vCuts, vTimes, nLutSize, Period) ) + if ( !Gia_ManSifCheckIter(p, vCuts, vTimes, nLutSize, Period) ) return 1; Gia_ManForEachPo( p, pObj, i ) - if ( Vec_IntEntry(vTimes, Gia_ObjFaninId0p(p, pObj)) > Period ) + if ( Vec_IntEntry(vTimes, Gia_ObjId(p, pObj)) > Period ) + return 0; + Gia_ManForEachObj( p, pObj, i ) + if ( Vec_IntEntry(vTimes, Gia_ObjId(p, pObj)) > 2*Period ) return 0; } return 0; } -static inline void Gia_ManPrintCutOne( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) -{ - int i, * pCut = Vec_IntEntryP( vCuts, iObj*nSize ); - printf( "Obj %4d : Depth %d CutSize %d Cut {", iObj, Vec_IntEntry(vTimes, iObj), pCut[0] ); - for ( i = 1; i <= pCut[0]; i++ ) - printf( " %d", pCut[i] ); - printf( " }\n" ); -} -int Gia_ManTestMapComb( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize ) +int Gia_ManSifMapComb( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize ) { Gia_Obj_t * pObj; int i, Id, Res = 0, nSize = nLutSize+1; Vec_IntFill( vTimes, Gia_ManObjNum(p), 0 ); Gia_ManForEachCiId( p, Id, i ) Vec_IntWriteEntry( vCuts, Id*nSize, 1 ); Gia_ManForEachCiId( p, Id, i ) - Vec_IntWriteEntry( vCuts, Id*nSize+1, Id ); + Vec_IntWriteEntry( vCuts, Id*nSize+1, Id << 8 ); Gia_ManForEachAnd( p, pObj, i ) - Gia_ManCutOne( p, i, vCuts, vTimes, nSize ); + Gia_ManSifCutOne( p, i, vCuts, vTimes, nSize ); Gia_ManForEachCo( p, pObj, i ) Res = Abc_MaxInt( Res, Vec_IntEntry(vTimes, Gia_ObjFaninId0p(p, pObj)) ); - //Gia_ManForEachAnd( p, pObj, i ) - // Gia_ManPrintCutOne( p, i, vCuts, vTimes, nSize ); return Res; } -void Gia_ManPrintTimes( Gia_Man_t * p, Vec_Int_t * vTimes, int Period ) +void Gia_ManSifPrintTimes( Gia_Man_t * p, Vec_Int_t * vTimes, int Period ) { - int Pos[16] = {0}; - int Neg[16] = {0}; - Gia_Obj_t * pObj; int i; - Gia_ManForEachAnd( p, pObj, i ) - { - int Time = Vec_IntEntry(vTimes, i)-Period; - Time = Abc_MinInt( Time, 10*Period ); - Time = Abc_MaxInt( Time, -10*Period ); - if ( Time >= 0 ) - Pos[(Time + Period-1)/Period]++; + int i, Value, Pos[256] = {0}, Neg[256] = {0}; + Gia_ManForEachLut( p, i ) + { + Value = Gia_ManSifTimeToCount( Vec_IntEntry(vTimes, i), Period ); + Value = Abc_MinInt( Value, 255 ); + Value = Abc_MaxInt( Value, -255 ); + if ( Value >= 0 ) + Pos[Value]++; else - Neg[(-Time + Period-1)/Period]++; + Neg[-Value]++; } printf( "Statistics: " ); - for ( i = 15; i > 0; i-- ) + for ( i = 255; i > 0; i-- ) if ( Neg[i] ) printf( " -%d=%d", i, Neg[i] ); - for ( i = 0; i < 16; i++ ) + for ( i = 0; i < 256; i++ ) if ( Pos[i] ) printf( " %d=%d", i, Pos[i] ); printf( "\n" ); } -Gia_Man_t * Gia_ManTestSif( Gia_Man_t * p, int nLutSize, int fVerbose ) +int Gia_ManSifDeriveMapping_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vCuts, int nSize ) { - int nIters, nSize = nLutSize+1; // (2+1+nSize)*4=40 bytes/node + int i, * pCut, Area = 1; + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + if ( Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return 0; + pCut = Vec_IntEntryP( vCuts, Gia_ObjId(p, pObj)*nSize ); + for ( i = 1; i <= pCut[0]; i++ ) + Area += Gia_ManSifDeriveMapping_rec( p, Gia_ManObj(p, pCut[i] >> 8), vCuts, nSize ); + Vec_IntWriteEntry( p->vMapping, Gia_ObjId(p, pObj), Vec_IntSize(p->vMapping) ); + Vec_IntPush( p->vMapping, pCut[0] ); + for ( i = 1; i <= pCut[0]; i++ ) + { + Gia_Obj_t * pObj = Gia_ManObj(p, pCut[i] >> 8); + assert( !Gia_ObjIsAnd(pObj) || Gia_ObjIsLut(p, pCut[i] >> 8) ); + Vec_IntPush( p->vMapping, pCut[i] >> 8 ); + } + Vec_IntPush( p->vMapping, -1 ); + return Area; +} +int Gia_ManSifDeriveMapping( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period, int fVerbose ) +{ + Gia_Obj_t * pObj; int i, nArea = 0; + if ( p->vMapping != NULL ) + { + printf( "Removing available combinational mapping.\n" ); + Vec_IntFreeP( &p->vMapping ); + } + assert( p->vMapping == NULL ); + p->vMapping = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + nArea += Gia_ManSifDeriveMapping_rec( p, Gia_ObjFanin0(pObj), vCuts, nLutSize+1 ); + return nArea; +} +Gia_Man_t * Gia_ManSifPerform( Gia_Man_t * p, int nLutSize, int fEvalOnly, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; + int nIters, Status, nSize = nLutSize+1; // (2+1+nSize)*4=40 bytes/node abctime clk = Abc_Clock(); Vec_Int_t * vCuts = Vec_IntStart( Gia_ManObjNum(p) * nSize ); Vec_Int_t * vTimes = Vec_IntAlloc( Gia_ManObjNum(p) ); int Lower = 0; - int Upper = Gia_ManTestMapComb( p, vCuts, vTimes, nLutSize ); + int Upper = Gia_ManSifMapComb( p, vCuts, vTimes, nLutSize ); + int CombD = Upper; if ( fVerbose && Gia_ManRegNum(p) ) printf( "Clock period %2d is %s\n", Lower, 0 ? "Yes" : "No " ); if ( fVerbose && Gia_ManRegNum(p) ) @@ -225,7 +602,7 @@ Gia_Man_t * Gia_ManTestSif( Gia_Man_t * p, int nLutSize, int fVerbose ) while ( Gia_ManRegNum(p) > 0 && Upper - Lower > 1 ) { int Middle = (Upper + Lower) / 2; - int Status = Gia_ManCheckPeriod( p, vCuts, vTimes, nLutSize, Middle, &nIters ); + int Status = Gia_ManSifCheckPeriod( p, vCuts, vTimes, nLutSize, Middle, &nIters ); if ( Status ) Upper = Middle; else @@ -234,18 +611,34 @@ Gia_Man_t * Gia_ManTestSif( Gia_Man_t * p, int nLutSize, int fVerbose ) printf( "Clock period %2d is %s after %d iterations\n", Middle, Status ? "Yes" : "No ", nIters ); } if ( fVerbose ) - printf( "Clock period = %2d ", Upper ); + printf( "Best period = <<%d>> (%.2f %%) ", Upper, (float)(100.0*(CombD-Upper)/CombD) ); if ( fVerbose ) printf( "LUT size = %d ", nLutSize ); if ( fVerbose ) printf( "Memory usage = %.2f MB ", 4.0*(2+1+nSize)*Gia_ManObjNum(p)/(1 << 20) ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - //Gia_ManCheckPeriod( p, vCuts, vTimes, nLutSize, Upper, &nIters ); - //Gia_ManPrintTimes( p, vTimes, Upper ); + if ( Upper == CombD ) + { + Vec_IntFree( vCuts ); + Vec_IntFree( vTimes ); + printf( "Combinational delay (%d) cannot be improved.\n", CombD ); + return Gia_ManDup( p ); + } + Status = Gia_ManSifCheckPeriod( p, vCuts, vTimes, nLutSize, Upper, &nIters ); + assert( Status ); + Status = Gia_ManSifDeriveMapping( p, vCuts, vTimes, nLutSize, Upper, fVerbose ); + if ( fEvalOnly ) + { + printf( "Optimized level %2d (%6.2f %% less than comb level %2d). LUT size = %d. Area estimate = %d.\n", + Upper, (float)(100.0*(CombD-Upper)/CombD), CombD, nLutSize, Gia_ManSifArea(p, vCuts, nLutSize+1) ); + printf( "The command is invoked in the evaluation mode. Retiming is not performed.\n" ); + } + else + pNew = Gia_ManSifTransform( p, vCuts, vTimes, nLutSize, Upper, fVerbose ); Vec_IntFree( vCuts ); Vec_IntFree( vTimes ); - return NULL; + return pNew; } //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaSimBase.c b/src/aig/gia/giaSimBase.c index 75a6d653d..47f645413 100644 --- a/src/aig/gia/giaSimBase.c +++ b/src/aig/gia/giaSimBase.c @@ -3260,6 +3260,434 @@ void Gia_ManRelDeriveTest( Gia_Man_t * p ) } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManRelOutsTfo_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vTfo ) +{ + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + return 1; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + if ( pObj->fPhase ) + { + Gia_ObjSetTravIdPrevious(p, pObj); + return 1; + } + if ( Gia_ObjIsAnd(pObj) ) + { + int Val0 = Gia_ManRelOutsTfo_rec( p, Gia_ObjFanin0(pObj), vTfo ); + int Val1 = Gia_ManRelOutsTfo_rec( p, Gia_ObjFanin1(pObj), vTfo ); + if ( Val0 || Val1 ) + { + Gia_ObjSetTravIdPrevious(p, pObj); + Vec_IntPush( vTfo, Gia_ObjId(p, pObj) ); + return 1; + } + } + Gia_ObjSetTravIdCurrent(p, pObj); + return 0; +} +Vec_Int_t * Gia_ManRelOutsTfo( Gia_Man_t * p, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vTfo = Vec_IntAlloc( 100 ); + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrentId( p, 0 ); + Gia_ManCleanPhase( p ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + pObj->fPhase = 1; + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ManRelOutsTfo_rec( p, Gia_ObjFanin0(pObj), vTfo ) ) + Vec_IntPush( vTfo, Gia_ObjId(p, pObj) ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + pObj->fPhase = 0; + //Vec_IntPrint( vTfo ); + return vTfo; +} +void Gia_ManSimPatSimTfo( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Int_t * vTfo ) +{ + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Gia_ManForEachObjVec( vTfo, p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManSimPatSimAnd( p, Gia_ObjId(p, pObj), pObj, nWords, vSims ); + else + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj), pObj, nWords, vSims ); +} +void Gia_ManSimPatSimMiter( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vSims2, word * pSims, int nWords ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachCo( p, pObj, i ) + Abc_TtOrXor( pSims, Vec_WrdEntryP(vSims, Gia_ObjId(p, pObj)*nWords), Vec_WrdEntryP(vSims2, Gia_ObjId(p, pObj)*nWords), nWords ); + Abc_TtNot( pSims, nWords ); +} +Vec_Wrd_t * Gia_ManRelDeriveRel( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Vec_Wrd_t * vSims ) +{ + extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + int i, o, iObj, nMintsO = 1 << Vec_IntSize(vOuts); + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Vec_Wrd_t * vSims2 = Vec_WrdDup( vSims ); + Vec_Wrd_t * vRel = Vec_WrdStart( nWords * 64 ); + Vec_Wrd_t * vRel2 = Vec_WrdStart( nWords * 64 ); + Vec_Int_t * vTfo = Gia_ManRelOutsTfo( p, vOuts ); + assert( 1 + Vec_IntSize(vIns) + Vec_IntSize(vDivs) + nMintsO <= 64 ); + assert( Vec_WrdSize(p->vSimsPi) % Gia_ManCiNum(p) == 0 ); + Vec_IntForEachEntry( vIns, iObj, o ) + memcpy( Vec_WrdEntryP(vRel, nWords*o), Vec_WrdEntryP(vSims, iObj*nWords), sizeof(word)*nWords ); + Vec_IntForEachEntry( vDivs, iObj, o ) + memcpy( Vec_WrdEntryP(vRel, nWords*(Vec_IntSize(vIns)+o)), Vec_WrdEntryP(vSims, iObj*nWords), sizeof(word)*nWords ); + for ( o = 0; o < nMintsO; o++ ) + { + word * pRes = Vec_WrdEntryP(vRel, nWords*(Vec_IntSize(vIns)+Vec_IntSize(vDivs)+o)); + Vec_IntForEachEntry( vOuts, iObj, i ) + memset( Vec_WrdEntryP(vSims2, iObj*nWords), ((o >> i) & 1) ? 0xFF : 0x00, sizeof(word)*nWords ); + Gia_ManSimPatSimTfo( p, vSims2, vTfo ); + Gia_ManSimPatSimMiter( p, vSims, vSims2, pRes, nWords ); + } + Extra_BitMatrixTransposeP( vRel, nWords, vRel2, 1 ); + Vec_IntFree( vTfo ); + Vec_WrdFree( vSims2 ); + Vec_WrdFree( vRel ); + return vRel2; +} +void Gia_ManRelDeriveSims( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Vec_Wrd_t * vSims, Vec_Wrd_t * vRel, Vec_Wrd_t ** pvSimsIn, Vec_Wrd_t ** pvSimsOut ) +{ + Vec_Wrd_t * vVals = Vec_WrdStartFull( 1 << Vec_IntSize(vIns) ); + Vec_Wrd_t * vSets = Vec_WrdStartFull( 1 << Vec_IntSize(vIns) ); + int m, nMints = 1 << Gia_ManCiNum(p), nCares = 0; + int nMintsI = 1 << Vec_IntSize(vIns); + int nShift = Vec_IntSize(vIns) + Vec_IntSize(vDivs); + int MaskI = Abc_Tt6Mask( Vec_IntSize(vIns) ); + int MaskD = Abc_Tt6Mask( nShift ); + for ( m = 0; m < nMints; m++ ) + { + word Sign = Vec_WrdEntry( vRel, m ); + *Vec_WrdEntryP( vVals, (int)Sign & MaskI ) = (int)Sign & MaskD; + *Vec_WrdEntryP( vSets, (int)Sign & MaskI ) &= Sign >> nShift; + } + for ( m = 0; m < nMintsI; m++ ) + if ( ~Vec_WrdEntry(vSets, m) ) + nCares++; + assert( *pvSimsIn == NULL ); + assert( *pvSimsOut == NULL ); + *pvSimsIn = Vec_WrdAlloc( nCares ); + *pvSimsOut = Vec_WrdAlloc( nCares ); + for ( m = 0; m < nMintsI; m++ ) + if ( ~Vec_WrdEntry(vSets, m) ) + { + Vec_WrdPush( *pvSimsIn, Vec_WrdEntry(vVals, m) << 1 ); + Vec_WrdPush( *pvSimsOut, Vec_WrdEntry(vSets, m) ); + } + assert( Vec_WrdSize(*pvSimsIn) == nCares ); + Vec_WrdFree( vSets ); + Vec_WrdFree( vVals ); +} + +int Gia_ManRelCheck_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + return 1; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + if ( pObj->fPhase ) + { + Gia_ObjSetTravIdPrevious(p, pObj); + return 1; + } + if ( Gia_ObjIsAnd(pObj) ) + { + int Val0 = Gia_ManRelCheck_rec( p, Gia_ObjFanin0(pObj) ); + int Val1 = Gia_ManRelCheck_rec( p, Gia_ObjFanin1(pObj) ); + if ( Val0 && Val1 ) + { + Gia_ObjSetTravIdPrevious(p, pObj); + return 1; + } + } + Gia_ObjSetTravIdCurrent(p, pObj); + return 0; +} +int Gia_ManRelCheck( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i, Res = 1; + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrentId( p, 0 ); + Gia_ManCleanPhase( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + pObj->fPhase = 1; + Gia_ManForEachObjVec( vDivs, p, pObj, i ) + if ( !Gia_ManRelCheck_rec( p, pObj ) ) + Res = 0; + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + if ( !Gia_ManRelCheck_rec( p, pObj ) ) + Res = 0; + Gia_ManForEachObjVec( vIns, p, pObj, i ) + pObj->fPhase = 0; + return Res; +} +void Gia_ManRelCompute( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Vec_Wrd_t ** pvSimsIn, Vec_Wrd_t ** pvSimsOut ) +{ + Vec_Wrd_t * vSims, * vRel; + //Vec_Wrd_t * vSimsDiv = NULL, * vSimsOut = NULL; + + Vec_WrdFreeP( &p->vSimsPi ); + p->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + + if ( !Gia_ManRelCheck( p, vIns, vDivs, vOuts ) ) + printf( "Window is NOT consistent.\n" ); + else + printf( "Window is consistent.\n" ); + + vSims = Gia_ManSimPatSim( p ); + vRel = Gia_ManRelDeriveRel( p, vIns, vDivs, vOuts, vSims ); + + Gia_ManRelDeriveSims( p, vIns, vDivs, vOuts, vSims, vRel, pvSimsIn, pvSimsOut ); + + Vec_WrdFree( vRel ); + Vec_WrdFree( vSims ); + Vec_WrdFreeP( &p->vSimsPi ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +Vec_Int_t * Gia_ManRelInitIns1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 22 ); + Vec_IntPush( vRes, 41 ); + Vec_IntPush( vRes, 45 ); + Vec_IntPush( vRes, 59 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 46 ); + Vec_IntPush( vRes, 47 ); + Vec_IntPush( vRes, 48 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 65 ); + Vec_IntPush( vRes, 66 ); + return vRes; +} +*/ + +Vec_Int_t * Gia_ManRelInitIns1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 22 ); + Vec_IntPush( vRes, 25 ); + Vec_IntPush( vRes, 42 ); + Vec_IntPush( vRes, 59 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 43 ); + Vec_IntPush( vRes, 44 ); + Vec_IntPush( vRes, 45 ); + Vec_IntPush( vRes, 46 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 60 ); + Vec_IntPush( vRes, 61 ); + return vRes; +} + +/* +Vec_Int_t * Gia_ManRelInitIns1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 22 ); + Vec_IntPush( vRes, 25 ); + Vec_IntPush( vRes, 42 ); + Vec_IntPush( vRes, 50 ); + Vec_IntPush( vRes, 67 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 43 ); + Vec_IntPush( vRes, 44 ); + Vec_IntPush( vRes, 45 ); + Vec_IntPush( vRes, 46 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 73 ); + Vec_IntPush( vRes, 74 ); + return vRes; +} +*/ + +/* +Vec_Int_t * Gia_ManRelInitIns1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 43 ); + Vec_IntPush( vRes, 46 ); + //Vec_IntPush( vRes, 49 ); + Vec_IntPush( vRes, 50 ); + Vec_IntPush( vRes, 67 ); + Vec_IntPush( vRes, 75 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 73 ); + Vec_IntPush( vRes, 86 ); + Vec_IntPush( vRes, 88 ); + return vRes; +} +*/ + +void Gia_ManRelDeriveTest1( Gia_Man_t * p ) +{ + extern void Exa6_WriteFile2( char * pFileName, int nVars, int nDivs, int nOuts, Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut ); + + word Entry; int i; + Vec_Int_t * vIns = Gia_ManRelInitIns1(); + Vec_Int_t * vDivs = Gia_ManRelInitDivs1(); + Vec_Int_t * vOuts = Gia_ManRelInitOuts1(); + + Vec_Wrd_t * vSimsDiv = NULL, * vSimsOut = NULL; + Gia_ManRelCompute( p, vIns, vDivs, vOuts, &vSimsDiv, &vSimsOut ); + + printf( "Inputs:\n" ); + Vec_WrdForEachEntry( vSimsDiv, Entry, i ) + Abc_TtPrintBits( &Entry, 1 + Vec_IntSize(vIns) + Vec_IntSize(vDivs) ); + printf( "Outputs:\n" ); + Vec_WrdForEachEntry( vSimsOut, Entry, i ) + Abc_TtPrintBits( &Entry, 1 << Vec_IntSize(vOuts) ); + printf( "\n" ); + + Exa6_WriteFile2( "mul44_i5_n0_t3_s11.rel", Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), vSimsDiv, vSimsOut ); + + Vec_WrdFree( vSimsDiv ); + Vec_WrdFree( vSimsOut ); + + Vec_IntFree( vIns ); + Vec_IntFree( vDivs ); + Vec_IntFree( vOuts ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManChangeTest3( Gia_Man_t * p ) +{ + extern void Exa6_WriteFile2( char * pFileName, int nVars, int nDivs, int nOuts, Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut ); + extern void Exa_ManExactPrint( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut, int nDivs, int nOuts ); + extern Mini_Aig_t * Exa_ManExactSynthesis6Int( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut, int nVars, int nDivs, int nOuts, int nNodes, int fOnlyAnd, int fVerbose ); + extern Gia_Man_t * Gia_ManDupMini( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Mini_Aig_t * pMini ); + + Gia_Man_t * pNew = NULL; + Mini_Aig_t * pMini = NULL; + Vec_Int_t * vIns = Gia_ManRelInitIns1(); + Vec_Int_t * vDivs = Gia_ManRelInitDivs1(); + Vec_Int_t * vOuts = Gia_ManRelInitOuts1(); + int nNodes = 4; + + Vec_Wrd_t * vSimsDiv = NULL, * vSimsOut = NULL; + Gia_ManRelCompute( p, vIns, vDivs, vOuts, &vSimsDiv, &vSimsOut ); + Exa_ManExactPrint( vSimsDiv, vSimsOut, 1 + Vec_IntSize(vIns) + Vec_IntSize(vDivs), Vec_IntSize(vOuts) ); + //Exa6_WriteFile2( "mul44_i%d_n%d_t%d_s%d.rel", Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), nNodes ); + pMini = Exa_ManExactSynthesis6Int( vSimsDiv, vSimsOut, Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), nNodes, 1, 1 ); + if ( pMini ) + { + pNew = Gia_ManDupMini( p, vIns, vDivs, vOuts, pMini ); + Mini_AigStop( pMini ); + } + Vec_WrdFree( vSimsDiv ); + Vec_WrdFree( vSimsOut ); + + Vec_IntFree( vIns ); + Vec_IntFree( vDivs ); + Vec_IntFree( vOuts ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Gia_ManComputeRange( Gia_Man_t * p ) +{ + Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( p, vSimsPi, 1 ); + int n, nWords = Vec_WrdSize(vSimsPi) / Gia_ManCiNum(p); + int i, nLimit = Gia_ManCiNum(p) < 6 ? 1 << Gia_ManCiNum(p) : 64*nWords; + Vec_Str_t * vOut = Vec_StrAlloc( nLimit*(Gia_ManCoNum(p) + 3)+1 ); + assert( Vec_WrdSize(vSims) == nWords * Gia_ManCoNum(p) ); + for ( n = 0; n < nLimit; n++ ) + { + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + Vec_StrPush( vOut, (char)('0' + Abc_TtGetBit(Vec_WrdEntryP(vSims, i*nWords), n)) ); + Vec_StrPush( vOut, ' ' ); + Vec_StrPush( vOut, '1' ); + Vec_StrPush( vOut, '\n' ); + } + Vec_StrPush( vOut, '\0' ); + Vec_WrdFree( vSims ); + Vec_WrdFree( vSimsPi ); + return vOut; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/aig/gia/giaTranStoch.c b/src/aig/gia/giaTranStoch.c new file mode 100644 index 000000000..efc358dde --- /dev/null +++ b/src/aig/gia/giaTranStoch.c @@ -0,0 +1,424 @@ +/**CFile**************************************************************** + + FileName [giaTranStoch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaTranStoch.c,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef ABC_USE_PTHREADS + +#ifdef _WIN32 +#include "../lib/pthread.h" +#else +#include +#include +#endif + +#endif + +ABC_NAMESPACE_IMPL_START + +extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); +extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); +extern int Abc_NtkPerformMfs( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars ); +extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); +extern int Abc_NtkFxPerform( Abc_Ntk_t * pNtk, int nNewNodesMax, int nLitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose ); + +Abc_Ntk_t * Gia_ManTranStochPut( Gia_Man_t * pGia ) { + Abc_Ntk_t * pNtk; + Aig_Man_t * pMan = Gia_ManToAig( pGia, 0 ); + pNtk = Abc_NtkFromAigPhase( pMan ); + Aig_ManStop( pMan ); + return pNtk; +} +Abc_Ntk_t * Gia_ManTranStochIf( Abc_Ntk_t * pNtk ) { + If_Par_t Pars, * pPars = &Pars; + If_ManSetDefaultPars( pPars ); + pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); + pPars->nLutSize = pPars->pLutLib->LutMax; + return Abc_NtkIf( pNtk, pPars ); +} +void Gia_ManTranStochMfs2( Abc_Ntk_t * pNtk ) { + Sfm_Par_t Pars, * pPars = &Pars; + Sfm_ParSetDefault( pPars ); + Abc_NtkPerformMfs( pNtk, pPars ); +} +Gia_Man_t * Gia_ManTranStochGet( Abc_Ntk_t * pNtk ) { + Gia_Man_t * pGia; + Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pGia = Gia_ManFromAig( pAig ); + Aig_ManStop( pAig ); + return pGia; +} +void Gia_ManTranStochFx( Abc_Ntk_t * pNtk ) { + Fxu_Data_t Params, * p = &Params; + Abc_NtkSetDefaultFxParams( p ); + Abc_NtkFxPerform( pNtk, p->nNodesExt, p->LitCountMax, p->fCanonDivs, p->fVerbose, p->fVeryVerbose ); + Abc_NtkFxuFreeInfo( p ); +} +Gia_Man_t * Gia_ManTranStochRefactor( Gia_Man_t * pGia ) { + Gia_Man_t * pNew; + Aig_Man_t * pAig, * pTemp; + Dar_RefPar_t Pars, * pPars = &Pars; + Dar_ManDefaultRefParams( pPars ); + pPars->fUseZeros = 1; + pAig = Gia_ManToAig( pGia, 0 ); + Dar_ManRefactor( pAig, pPars ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + pNew = Gia_ManFromAig( pAig ); + Aig_ManStop( pAig ); + return pNew; +} + +struct Gia_ManTranStochParam { + Gia_Man_t * pStart; + int nSeed; + int nHops; + int nRestarts; + int nSeedBase; + int fMspf; + int fMerge; + int fResetHop; + int fZeroCostHop; + int fRefactor; + int fTruth; + int fNewLine; + Gia_Man_t * pExdc; + int nVerbose; + +#ifdef ABC_USE_PTHREADS + int nSp; + int nIte; + Gia_Man_t * pRes; + int fWorking; + pthread_mutex_t * mutex; +#endif +}; + +typedef struct Gia_ManTranStochParam Gia_ManTranStochParam; + +void Gia_ManTranStochLock( Gia_ManTranStochParam * p ) { +#ifdef ABC_USE_PTHREADS + if ( p->fWorking ) + pthread_mutex_lock( p->mutex ); +#endif +} +void Gia_ManTranStochUnlock( Gia_ManTranStochParam * p ) { +#ifdef ABC_USE_PTHREADS + if ( p->fWorking ) + pthread_mutex_unlock( p->mutex ); +#endif +} + +Gia_Man_t * Gia_ManTranStochOpt1( Gia_ManTranStochParam * p, Gia_Man_t * pOld ) { + Gia_Man_t * pGia, * pNew; + int i = 0, n; + pGia = Gia_ManDup( pOld ); + do { + n = Gia_ManAndNum( pGia ); + if ( p->fTruth ) + pNew = Gia_ManTransductionTt( pGia, (p->fMerge? 8: 7), p->fMspf, p->nSeed++, 0, 0, 0, 0, p->pExdc, p->fNewLine, p->nVerbose > 0? p->nVerbose - 1: 0 ); + else + pNew = Gia_ManTransductionBdd( pGia, (p->fMerge? 8: 7), p->fMspf, p->nSeed++, 0, 0, 0, 0, p->pExdc, p->fNewLine, p->nVerbose > 0? p->nVerbose - 1: 0 ); + Gia_ManStop( pGia ); + pGia = pNew; + if ( p->fRefactor ) { + pNew = Gia_ManTranStochRefactor( pGia ); + Gia_ManStop( pGia ); + pGia = pNew; + } else { + Gia_ManTranStochLock( p ); + pNew = Gia_ManCompress2( pGia, 1, 0 ); + Gia_ManTranStochUnlock( p ); + Gia_ManStop( pGia ); + pGia = pNew; + } + if ( p->nVerbose ) + printf( "* ite %d : #nodes = %5d\n", i, Gia_ManAndNum( pGia ) ); + i++; + } while ( n > Gia_ManAndNum( pGia ) ); + return pGia; +} + +Gia_Man_t * Gia_ManTranStochOpt2( Gia_ManTranStochParam * p ) { + int i, n = Gia_ManAndNum( p->pStart ); + Gia_Man_t * pGia, * pBest, * pNew; + Abc_Ntk_t * pNtk, * pNtkRes; + pGia = Gia_ManDup( p->pStart ); + pBest = Gia_ManDup( pGia ); + for ( i = 0; 1; i++ ) { + pNew = Gia_ManTranStochOpt1( p, pGia ); + Gia_ManStop( pGia ); + pGia = pNew; + if ( n > Gia_ManAndNum( pGia ) ) { + n = Gia_ManAndNum( pGia ); + Gia_ManStop( pBest ); + pBest = Gia_ManDup( pGia ); + if ( p->fResetHop ) + i = 0; + } + if ( i == p->nHops ) + break; + if ( p->fZeroCostHop ) { + pNew = Gia_ManTranStochRefactor( pGia ); + Gia_ManStop( pGia ); + pGia = pNew; + } else { + Gia_ManTranStochLock( p ); + pNtk = Gia_ManTranStochPut( pGia ); + Gia_ManTranStochUnlock( p ); + Gia_ManStop( pGia ); + pNtkRes = Gia_ManTranStochIf( pNtk ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + Gia_ManTranStochMfs2( pNtk ); + Gia_ManTranStochLock( p ); + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Gia_ManTranStochUnlock( p ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pGia = Gia_ManTranStochGet( pNtk ); + Abc_NtkDelete( pNtk ); + } + if ( p->nVerbose ) + printf( "* hop %d : #nodes = %5d\n", i, Gia_ManAndNum( pGia ) ); + } + Gia_ManStop( pGia ); + return pBest; +} + +Gia_Man_t * Gia_ManTranStochOpt3( Gia_ManTranStochParam * p ) { + int i, n = Gia_ManAndNum( p->pStart ); + Gia_Man_t * pBest, * pNew; + pBest = Gia_ManDup( p->pStart ); + for ( i = 0; i <= p->nRestarts; i++ ) { + p->nSeed = 1234 * (i + p->nSeedBase); + pNew = Gia_ManTranStochOpt2( p ); + if ( p->nRestarts && p->nVerbose ) + printf( "* res %2d : #nodes = %5d\n", i, Gia_ManAndNum( pNew ) ); + if ( n > Gia_ManAndNum( pNew ) ) { + n = Gia_ManAndNum( pNew ); + Gia_ManStop( pBest ); + pBest = pNew; + } else { + Gia_ManStop( pNew ); + } + } + return pBest; +} + +#ifdef ABC_USE_PTHREADS +void * Gia_ManTranStochWorkerThread( void * pArg ) { + Gia_ManTranStochParam * p = (Gia_ManTranStochParam *)pArg; + volatile int * pPlace = &p->fWorking; + while ( 1 ) { + while ( *pPlace == 0 ); + assert( p->fWorking ); + if ( p->pStart == NULL ) { + pthread_exit( NULL ); + assert( 0 ); + return NULL; + } + p->nSeed = 1234 * (p->nIte + p->nSeedBase); + p->pRes = Gia_ManTranStochOpt2( p ); + p->fWorking = 0; + } + assert( 0 ); + return NULL; +} +#endif + +Gia_Man_t * Gia_ManTranStoch( Gia_Man_t * pGia, int nRestarts, int nHops, int nSeedBase, int fMspf, int fMerge, int fResetHop, int fZeroCostHop, int fRefactor, int fTruth, int fSingle, int fOriginalOnly, int fNewLine, Gia_Man_t * pExdc, int nThreads, int nVerbose ) { + int i, j = 0; + Gia_Man_t * pNew, * pBest, * pStart; + Abc_Ntk_t * pNtk, * pNtkRes; Vec_Ptr_t * vpStarts; + Gia_ManTranStochParam Par, *p = &Par; + p->nRestarts = nRestarts; + p->nHops = nHops; + p->nSeedBase = nSeedBase; + p->fMspf = fMspf; + p->fMerge = fMerge; + p->fResetHop = fResetHop; + p->fZeroCostHop = fZeroCostHop; + p->fRefactor = fRefactor; + p->fTruth = fTruth; + p->fNewLine = fNewLine; + p->pExdc = pExdc; + p->nVerbose = nVerbose; +#ifdef ABC_USE_PTHREADS + p->fWorking = 0; +#endif + // setup start points + vpStarts = Vec_PtrAlloc( 4 ); + Vec_PtrPush( vpStarts, Gia_ManDup( pGia ) ); + if ( !fOriginalOnly ) { + { // &put; collapse; st; &get; + pNtk = Gia_ManTranStochPut( pGia ); + pNtkRes = Abc_NtkCollapse( pNtk, ABC_INFINITY, 0, 1, 0, 0, 0 ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pNew = Gia_ManTranStochGet( pNtk ); + Abc_NtkDelete( pNtk ); + Vec_PtrPush( vpStarts, pNew ); + } + { // &ttopt; + pNew = Gia_ManTtopt( pGia, Gia_ManCiNum( pGia ), Gia_ManCoNum( pGia ), 100 ); + Vec_PtrPush( vpStarts, pNew ); + } + { // &put; collapse; sop; fx; + pNtk = Gia_ManTranStochPut( pGia ); + pNtkRes = Abc_NtkCollapse( pNtk, ABC_INFINITY, 0, 1, 0, 0, 0 ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); + Gia_ManTranStochFx( pNtk ); + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pNew = Gia_ManTranStochGet( pNtk ); + Abc_NtkDelete( pNtk ); + Vec_PtrPush( vpStarts, pNew ); + } + } + if ( fSingle ) { + pBest = (Gia_Man_t *)Vec_PtrEntry( vpStarts, 0 ); + for ( i = 1; i < Vec_PtrSize( vpStarts ); i++ ) { + pStart = (Gia_Man_t *)Vec_PtrEntry( vpStarts, i ); + if ( Gia_ManAndNum( pStart ) < Gia_ManAndNum( pBest ) ) { + Gia_ManStop( pBest ); + pBest = pStart; + j = i; + } else { + Gia_ManStop( pStart ); + } + } + Vec_PtrClear( vpStarts ); + Vec_PtrPush( vpStarts, pBest ); + } + // optimize + pBest = Gia_ManDup( pGia ); + if ( nThreads == 1 ) { + Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, i ) { + if ( p->nVerbose ) + printf( "*begin starting point %d: #nodes = %5d\n", i + j, Gia_ManAndNum( pStart ) ); + p->pStart = pStart; + pNew = Gia_ManTranStochOpt3( p ); + if ( p->nVerbose ) + printf( "*end starting point %d: #nodes = %5d\n", i + j, Gia_ManAndNum( pNew ) ); + if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( pNew ) ) { + Gia_ManStop( pBest ); + pBest = pNew; + } else { + Gia_ManStop( pNew ); + } + Gia_ManStop( pStart ); + } + } else { +#ifdef ABC_USE_PTHREADS + static pthread_mutex_t mutex; + int k, status, nIte, fAssigned, fWorking; + Gia_ManTranStochParam ThData[100]; + pthread_t WorkerThread[100]; + p->pRes = NULL; + p->mutex = &mutex; + if ( p->nVerbose ) + p->nVerbose--; + for ( i = 0; i < nThreads; i++ ) { + ThData[i] = *p; + status = pthread_create( WorkerThread + i, NULL, Gia_ManTranStochWorkerThread, (void *)(ThData + i) ); + assert( status == 0 ); + } + Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, k ) { + for ( nIte = 0; nIte <= p->nRestarts; nIte++ ) { + fAssigned = 0; + while ( !fAssigned ) { + for ( i = 0; i < nThreads; i++ ) { + if ( ThData[i].fWorking ) + continue; + if ( ThData[i].pRes != NULL ) { + if( nVerbose ) + printf( "*sp %d res %4d : #nodes = %5d\n", ThData[i].nSp, ThData[i].nIte, Gia_ManAndNum( ThData[i].pRes ) ); + if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( ThData[i].pRes ) ) { + Gia_ManStop( pBest ); + pBest = ThData[i].pRes; + } else { + Gia_ManStop( ThData[i].pRes ); + } + ThData[i].pRes = NULL; + } + ThData[i].nSp = j + k; + ThData[i].nIte = nIte; + ThData[i].pStart = pStart; + ThData[i].fWorking = 1; + fAssigned = 1; + break; + } + } + } + } + fWorking = 1; + while ( fWorking ) { + fWorking = 0; + for ( i = 0; i < nThreads; i++ ) { + if( ThData[i].fWorking ) { + fWorking = 1; + continue; + } + if ( ThData[i].pRes != NULL ) { + if( nVerbose ) + printf( "*sp %d res %4d : #nodes = %5d\n", ThData[i].nSp, ThData[i].nIte, Gia_ManAndNum( ThData[i].pRes ) ); + if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( ThData[i].pRes ) ) { + Gia_ManStop( pBest ); + pBest = ThData[i].pRes; + } else { + Gia_ManStop( ThData[i].pRes ); + } + ThData[i].pRes = NULL; + } + } + } + for ( i = 0; i < nThreads; i++ ) { + ThData[i].pStart = NULL; + ThData[i].fWorking = 1; + } +#else + printf( "ERROR: pthread is off" ); +#endif + Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, i ) + Gia_ManStop( pStart ); + } + if ( nVerbose ) + printf( "best: %d\n", Gia_ManAndNum( pBest ) ); + Vec_PtrFree( vpStarts ); + return pBest; +} + +ABC_NAMESPACE_IMPL_END diff --git a/src/aig/gia/giaTransduction.cpp b/src/aig/gia/giaTransduction.cpp new file mode 100644 index 000000000..f9220210f --- /dev/null +++ b/src/aig/gia/giaTransduction.cpp @@ -0,0 +1,166 @@ +/**CFile**************************************************************** + + FileName [giaTransduction.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaTransduction.c,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef _WIN32 + +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma warning(disable : 4786) // warning C4786: identifier was truncated to '255' characters in the browser information +#endif +#endif + +#include "giaTransduction.h" +#include "giaNewBdd.h" +#include "giaNewTt.h" + +ABC_NAMESPACE_IMPL_START + +Gia_Man_t *Gia_ManTransductionBdd(Gia_Man_t *pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t *pExdc, int fNewLine, int nVerbose) { + if(nRandom) { + srand(nRandom); + nSortType = rand() % 4; + nPiShuffle = rand(); + nParameter = rand() % 16; + } + NewBdd::Param p; + Transduction::Transduction t(pGia, nVerbose, fNewLine, nSortType, nPiShuffle, fLevel, pExdc, p); + int count = t.CountWires(); + switch(nType) { + case 0: + count -= fMspf? t.Mspf(): t.Cspf(); + break; + case 1: + count -= t.Resub(fMspf); + break; + case 2: + count -= t.ResubMono(fMspf); + break; + case 3: + count -= t.ResubShared(fMspf); + break; + case 4: + count -= t.RepeatResub(false, fMspf); + break; + case 5: + count -= t.RepeatResub(true, fMspf); + break; + case 6: { + bool fInner = (nParameter / 4) % 2; + count -= t.RepeatInner(fMspf, fInner); + break; + } + case 7: { + bool fInner = (nParameter / 4) % 2; + bool fOuter = (nParameter / 8) % 2; + count -= t.RepeatOuter(fMspf, fInner, fOuter); + break; + } + case 8: { + bool fFirstMerge = nParameter % 2; + bool fMspfMerge = fMspf? (nParameter / 2) % 2: false; + bool fInner = (nParameter / 4) % 2; + bool fOuter = (nParameter / 8) % 2; + count -= t.RepeatAll(fFirstMerge, fMspfMerge, fMspf, fInner, fOuter); + break; + } + default: + std::cout << "Unknown transduction type " << nType << std::endl; + } + assert(t.Verify()); + assert(count == t.CountWires()); + return t.GenerateAig(); +} + +Gia_Man_t *Gia_ManTransductionTt(Gia_Man_t *pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t *pExdc, int fNewLine, int nVerbose) { + if(nRandom) { + srand(nRandom); + nSortType = rand() % 4; + nPiShuffle = rand(); + nParameter = rand() % 16; + } + NewTt::Param p; + Transduction::Transduction t(pGia, nVerbose, fNewLine, nSortType, nPiShuffle, fLevel, pExdc, p); + int count = t.CountWires(); + switch(nType) { + case 0: + count -= fMspf? t.Mspf(): t.Cspf(); + break; + case 1: + count -= t.Resub(fMspf); + break; + case 2: + count -= t.ResubMono(fMspf); + break; + case 3: + count -= t.ResubShared(fMspf); + break; + case 4: + count -= t.RepeatResub(false, fMspf); + break; + case 5: + count -= t.RepeatResub(true, fMspf); + break; + case 6: { + bool fInner = (nParameter / 4) % 2; + count -= t.RepeatInner(fMspf, fInner); + break; + } + case 7: { + bool fInner = (nParameter / 4) % 2; + bool fOuter = (nParameter / 8) % 2; + count -= t.RepeatOuter(fMspf, fInner, fOuter); + break; + } + case 8: { + bool fFirstMerge = nParameter % 2; + bool fMspfMerge = fMspf? (nParameter / 2) % 2: false; + bool fInner = (nParameter / 4) % 2; + bool fOuter = (nParameter / 8) % 2; + count -= t.RepeatAll(fFirstMerge, fMspfMerge, fMspf, fInner, fOuter); + break; + } + default: + std::cout << "Unknown transduction type " << nType << std::endl; + } + assert(t.Verify()); + assert(count == t.CountWires()); + return t.GenerateAig(); +} + +ABC_NAMESPACE_IMPL_END + +#else + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + +Gia_Man_t * Gia_ManTransductionBdd(Gia_Man_t *pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t *pExdc, int fNewLine, int nVerbose) +{ + return NULL; +} +Gia_Man_t * Gia_ManTransductionTt(Gia_Man_t *pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t *pExdc, int fNewLine, int nVerbose) +{ + return NULL; +} + +ABC_NAMESPACE_IMPL_END + +#endif diff --git a/src/aig/gia/giaTransduction.h b/src/aig/gia/giaTransduction.h new file mode 100644 index 000000000..6dd081e15 --- /dev/null +++ b/src/aig/gia/giaTransduction.h @@ -0,0 +1,1768 @@ +/**CFile**************************************************************** + + FileName [giaTransduction.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaTransduction.h,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__gia__giaTransduction_h +#define ABC__aig__gia__giaTransduction_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gia.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Transduction { + +enum PfState {none, cspf, mspf}; + +template +class ManUtil { +protected: + Man *man; + inline void IncRef(lit x) const { + if(x != LitMax) + man->IncRef(x); + } + inline void DecRef(lit x) const { + if(x != LitMax) + man->DecRef(x); + } + inline void Update(lit &x, lit y) const { + DecRef(x); + x = y; + IncRef(x); + } + inline void DelVec(std::vector &v) const { + for(unsigned i = 0; i < v.size(); i++) + DecRef(v[i]); + v.clear(); + } + inline void DelVec(std::vector > &v) const { + for(unsigned i = 0; i < v.size(); i++) + DelVec(v[i]); + v.clear(); + } + inline void CopyVec(std::vector &v, std::vector const &u) const { + DelVec(v); + v = u; + for(unsigned i = 0; i < v.size(); i++) + IncRef(v[i]); + } + inline void CopyVec(std::vector > &v, std::vector > const &u) const { + for(unsigned i = u.size(); i < v.size(); i++) + DelVec(v[i]); + v.resize(u.size()); + for(unsigned i = 0; i < v.size(); i++) + CopyVec(v[i], u[i]); + } + inline bool LitVecIsEq(std::vector const &v, std::vector const &u) const { + if(v.size() != u.size()) + return false; + for(unsigned i = 0; i < v.size(); i++) + if(!man->LitIsEq(v[i], u[i])) + return false; + return true; + } + inline bool LitVecIsEq(std::vector > const &v, std::vector > const &u) const { + if(v.size() != u.size()) + return false; + for(unsigned i = 0; i < v.size(); i++) + if(!LitVecIsEq(v[i], u[i])) + return false; + return true; + } + inline lit Xor(lit x, lit y) const { + lit f = man->And(x, man->LitNot(y)); + man->IncRef(f); + lit g = man->And(man->LitNot(x), y); + man->IncRef(g); + lit r = man->Or(f, g); + man->DecRef(f); + man->DecRef(g); + return r; + } +}; + +template +class TransductionBackup: ManUtil { +private: + int nObjsAlloc; + PfState state; + std::list vObjs; + std::vector > vvFis; + std::vector > vvFos; + std::vector vLevels; + std::vector vSlacks; + std::vector > vvFiSlacks; + std::vector vFs; + std::vector vGs; + std::vector > vvCs; + std::vector vUpdates; + std::vector vPfUpdates; + std::vector vFoConeShared; + template + friend class Transduction; + +public: + ~TransductionBackup() { + if(this->man) { + this->DelVec(vFs); + this->DelVec(vGs); + this->DelVec(vvCs); + } + } +}; + +template +class Transduction: ManUtil { +private: + int nVerbose; + int nSortType; + bool fLevel; + int nObjsAlloc; + int nMaxLevels; + PfState state; + std::vector vPis; + std::vector vPos; + std::list vObjs; + std::vector > vvFis; + std::vector > vvFos; + std::vector vLevels; + std::vector vSlacks; + std::vector > vvFiSlacks; + std::vector vFs; + std::vector vGs; + std::vector > vvCs; + std::vector vUpdates; + std::vector vPfUpdates; + std::vector vFoConeShared; + std::vector vPoFs; + + bool fNewLine; + abctime startclk; + +private: // Helper functions + inline bool AllFalse(std::vector const &v) const { + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) + if(v[*it]) + return false; + return true; + } + +public: // Counting + inline int CountGates() const { + return vObjs.size(); + } + inline int CountWires() const { + int count = 0; + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) + count += vvFis[*it].size(); + return count; + } + inline int CountNodes() const { + return CountWires() - CountGates(); + } + inline int CountLevels() const { + int count = 0; + for(unsigned i = 0; i < vPos.size(); i++) + count = std::max(count, vLevels[vvFis[vPos[i]][0] >> 1]); + return count; + } + inline void Print(std::string str, bool nl) const { + if(!fNewLine) + std::cout << "\33[2K\r"; + std::cout << str; + if(fNewLine || nl) + std::cout << std::endl; + else + std::cout << std::flush; + } + inline void PrintStats(std::string prefix, bool nl, int prefix_size = 0) const { + if(!prefix_size) + prefix_size = prefix.size(); + std::stringstream ss; + ss << std::left << std::setw(prefix_size) << prefix << ": " << std::right; + ss << "#nodes = " << std::setw(5) << CountNodes(); + if(fLevel) + ss << ", #level = " << std::setw(5) << CountLevels(); + ss << ", elapsed = " << std::setprecision(2) << std::fixed << std::setw(8) << 1.0 * (Abc_Clock() - startclk) / CLOCKS_PER_SEC << "s"; + Print(ss.str(), nl); + } + inline void PrintPfHeader(std::string prefix, int block, int block_i0) { + std::stringstream ss; + ss << "\t\t" << prefix; + if(block_i0 != -1) + ss << " (blocking Wire " << block_i0 << " -> " << block << ")"; + else if(block != -1) + ss << " (blocking Gate " << block << ")"; + Print(ss.str(), true); + } + +private: // MIAIG + void SortObjs_rec(std::list::iterator const &it) { + for(unsigned j = 0; j < vvFis[*it].size(); j++) { + int i0 = vvFis[*it][j] >> 1; + if(!vvFis[i0].empty()) { + std::list::iterator it_i0 = std::find(it, vObjs.end(), i0); + if(it_i0 != vObjs.end()) { + // if(nVerbose > 6) + // std::cout << "\t\t\t\t\t\tMove " << i0 << " before " << *it << std::endl; + vObjs.erase(it_i0); + it_i0 = vObjs.insert(it, i0); + SortObjs_rec(it_i0); + } + } + } + } + inline void Connect(int i, int f, bool fSort = false, bool fUpdate = true, lit c = LitMax) { + int i0 = f >> 1; + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\t\tadd Wire " << std::setw(5) << i0 << "(" << (f & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + assert(std::find(vvFis[i].begin(), vvFis[i].end(), f) == vvFis[i].end()); + vvFis[i].push_back(f); + vvFos[i0].push_back(i); + if(fUpdate) + vUpdates[i] = true; + this->IncRef(c); + vvCs[i].push_back(c); + if(fSort && !vvFos[i].empty() && !vvFis[i0].empty()) { + std::list::iterator it = find(vObjs.begin(), vObjs.end(), i); + std::list::iterator it_i0 = find(it, vObjs.end(), i0); + if(it_i0 != vObjs.end()) { + // if(nVerbose > 6) + // std::cout << "\t\t\t\t\t\tMove " << i0 << " before " << *it << std::endl; + vObjs.erase(it_i0); + it_i0 = vObjs.insert(it, i0); + SortObjs_rec(it_i0); + } + } + } + inline void Disconnect(int i, int i0, unsigned j, bool fUpdate = true, bool fPfUpdate = true) { + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\t\tremove Wire " << std::setw(5) << i0 << "(" << (vvFis[i][j] & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + vvFos[i0].erase(std::find(vvFos[i0].begin(), vvFos[i0].end(), i)); + vvFis[i].erase(vvFis[i].begin() + j); + this->DecRef(vvCs[i][j]); + vvCs[i].erase(vvCs[i].begin() + j); + if(fUpdate) + vUpdates[i] = true; + if(fPfUpdate) + vPfUpdates[i0] = true; + } + inline int Remove(int i, bool fPfUpdate = true) { + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\t\tremove Gate " << std::setw(5) << i; + Print(ss.str(), true); + } + assert(vvFos[i].empty()); + for(unsigned j = 0; j < vvFis[i].size(); j++) { + int i0 = vvFis[i][j] >> 1; + vvFos[i0].erase(std::find(vvFos[i0].begin(), vvFos[i0].end(), i)); + if(fPfUpdate) + vPfUpdates[i0] = true; + } + int count = vvFis[i].size(); + vvFis[i].clear(); + this->DecRef(vFs[i]); + this->DecRef(vGs[i]); + vFs[i] = vGs[i] = LitMax; + this->DelVec(vvCs[i]); + vUpdates[i] = vPfUpdates[i] = false; + return count; + } + inline int FindFi(int i, int i0) const { + for(unsigned j = 0; j < vvFis[i].size(); j++) + if((vvFis[i][j] >> 1) == i0) + return j; + return -1; + } + inline int Replace(int i, int f, bool fUpdate = true) { + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\treplace Gate " << std::setw(5) << i + << " by Node " << std::setw(5) << (f >> 1) << "(" << (f & 1) << ")"; + Print(ss.str(), true); + } + assert(i != (f >> 1)); + int count = 0; + for(unsigned j = 0; j < vvFos[i].size(); j++) { + int k = vvFos[i][j]; + int l = FindFi(k, i); + assert(l >= 0); + int fc = f ^ (vvFis[k][l] & 1); + if(find(vvFis[k].begin(), vvFis[k].end(), fc) != vvFis[k].end()) { + this->DecRef(vvCs[k][l]); + vvCs[k].erase(vvCs[k].begin() + l); + vvFis[k].erase(vvFis[k].begin() + l); + count++; + } else { + vvFis[k][l] = f ^ (vvFis[k][l] & 1); + vvFos[f >> 1].push_back(k); + } + if(fUpdate) + vUpdates[k] = true; + } + vvFos[i].clear(); + vPfUpdates[f >> 1] = true; + return count + Remove(i); + } + int ReplaceByConst(int i, bool c) { + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\treplace Gate " << std::setw(5) << i << " by Const " << c; + Print(ss.str(), true); + } + int count = 0; + for(unsigned j = 0; j < vvFos[i].size(); j++) { + int k = vvFos[i][j]; + int l = FindFi(k, i); + assert(l >= 0); + bool fc = c ^ (vvFis[k][l] & 1); + this->DecRef(vvCs[k][l]); + vvCs[k].erase(vvCs[k].begin() + l); + vvFis[k].erase(vvFis[k].begin() + l); + if(fc) { + if(vvFis[k].size() == 1) + count += Replace(k, vvFis[k][0]); + else + vUpdates[k] = true; + } else + count += ReplaceByConst(k, 0); + } + count += vvFos[i].size(); + vvFos[i].clear(); + return count + Remove(i); + } + inline void NewGate(int &pos) { + while(pos != nObjsAlloc && (!vvFis[pos].empty() || !vvFos[pos].empty())) + pos++; + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\t\tcreate Gate " << std::setw(5) << pos; + Print(ss.str(), true); + } + if(pos == nObjsAlloc) { + nObjsAlloc++; + vvFis.resize(nObjsAlloc); + vvFos.resize(nObjsAlloc); + if(fLevel) { + vLevels.resize(nObjsAlloc); + vSlacks.resize(nObjsAlloc); + vvFiSlacks.resize(nObjsAlloc); + } + vFs.resize(nObjsAlloc, LitMax); + vGs.resize(nObjsAlloc, LitMax); + vvCs.resize(nObjsAlloc); + vUpdates.resize(nObjsAlloc); + vPfUpdates.resize(nObjsAlloc); + } + } + void MarkFiCone_rec(std::vector &vMarks, int i) const { + if(vMarks[i]) + return; + vMarks[i] = true; + for(unsigned j = 0; j < vvFis[i].size(); j++) + MarkFiCone_rec(vMarks, vvFis[i][j] >> 1); + } + void MarkFoCone_rec(std::vector &vMarks, int i) const { + if(vMarks[i]) + return; + vMarks[i] = true; + for(unsigned j = 0; j < vvFos[i].size(); j++) + MarkFoCone_rec(vMarks, vvFos[i][j]); + } + bool IsFoConeShared_rec(std::vector &vVisits, int i, int visitor) const { + if(vVisits[i] == visitor) + return false; + if(vVisits[i]) + return true; + vVisits[i] = visitor; + for(unsigned j = 0; j < vvFos[i].size(); j++) + if(IsFoConeShared_rec(vVisits, vvFos[i][j], visitor)) + return true; + return false; + } + inline bool IsFoConeShared(int i) const { + std::vector vVisits(nObjsAlloc); + for(unsigned j = 0; j < vvFos[i].size(); j++) + if(IsFoConeShared_rec(vVisits, vvFos[i][j], j + 1)) + return true; + return false; + } + +private: // Level calculation + inline void add(std::vector &a, unsigned i) { + if(a.size() <= i) { + a.resize(i + 1); + a[i] = true; + return; + } + for(; i < a.size() && a[i]; i++) + a[i] = false; + if(i == a.size()) + a.resize(i + 1); + a[i] = true; + } + inline bool balanced(std::vector const &a) { + for(unsigned i = 0; i < a.size() - 1; i++) + if(a[i]) + return false; + return true; + } + inline bool noexcess(std::vector const &a, unsigned i) { + if(a.size() <= i) + return false; + for(unsigned j = i; j < a.size(); j++) + if(!a[j]) + return true; + for(unsigned j = 0; j < i; j++) + if(a[j]) + return false; + return true; + } + inline void ComputeLevel() { + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) { + if(vvFis[*it].size() == 2) + vLevels[*it] = std::max(vLevels[vvFis[*it][0] >> 1], vLevels[vvFis[*it][1] >> 1]) + 1; + else { + std::vector lev; + for(unsigned j = 0; j < vvFis[*it].size(); j++) + add(lev, vLevels[vvFis[*it][j] >> 1]); + if(balanced(lev)) + vLevels[*it] = (int)lev.size() - 1; + else + vLevels[*it] = (int)lev.size(); + } + } + if(nMaxLevels == -1) + nMaxLevels = CountLevels(); + for(unsigned i = 0; i < vPos.size(); i++) { + vvFiSlacks[vPos[i]].resize(1); + vvFiSlacks[vPos[i]][0] = nMaxLevels - vLevels[vvFis[vPos[i]][0] >> 1]; + } + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend(); it++) { + vSlacks[*it] = nMaxLevels; + for(unsigned j = 0; j < vvFos[*it].size(); j++) { + int k = vvFos[*it][j]; + int l = FindFi(k, *it); + assert(l >= 0); + vSlacks[*it] = std::min(vSlacks[*it], vvFiSlacks[k][l]); + } + vvFiSlacks[*it].resize(vvFis[*it].size()); + for(unsigned j = 0; j < vvFis[*it].size(); j++) + vvFiSlacks[*it][j] = vSlacks[*it] + vLevels[*it] - 1 - vLevels[vvFis[*it][j] >> 1]; + } + } + +private: // Cost function + inline void ShufflePis(int seed) { + srand(seed); + for(int i = (int)vPis.size() - 1; i > 0; i--) + std::swap(vPis[i], vPis[rand() % (i + 1)]); + } + inline bool CostCompare(int a, int b) const { // return (cost(a) > cost(b)) + int a0 = a >> 1; + int b0 = b >> 1; + if(vvFis[a0].empty() && vvFis[b0].empty()) + return std::find(find(vPis.begin(), vPis.end(), a0), vPis.end(), b0) != vPis.end(); + if(vvFis[a0].empty() && !vvFis[b0].empty()) + return false; + if(!vvFis[a0].empty() && vvFis[b0].empty()) + return true; + if(vvFos[a0].size() > vvFos[b0].size()) + return false; + if(vvFos[a0].size() < vvFos[b0].size()) + return true; + bool ac = a & 1; + bool bc = b & 1; + switch(nSortType) { + case 0: + return std::find(find(vObjs.begin(), vObjs.end(), a0), vObjs.end(), b0) == vObjs.end(); + case 1: + return this->man->OneCount(this->man->LitNotCond(vFs[a0], ac)) < this->man->OneCount(this->man->LitNotCond(vFs[b0], bc)); + case 2: + return this->man->OneCount(vFs[a0]) < this->man->OneCount(vFs[b0]); + case 3: + return this->man->OneCount(this->man->LitNot(vFs[a0])) < this->man->OneCount(vFs[b0]); // pseudo random + default: + return false; // no sorting + } + } + inline bool SortFis(int i) { + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\tsort FIs Gate " << std::setw(5) << i; + Print(ss.str(), true); + } + bool fSort = false; + for(int p = 1; p < (int)vvFis[i].size(); p++) { + int f = vvFis[i][p]; + lit c = vvCs[i][p]; + int q = p - 1; + for(; q >= 0 && CostCompare(f, vvFis[i][q]); q--) { + vvFis[i][q + 1] = vvFis[i][q]; + vvCs[i][q + 1] = vvCs[i][q]; + } + if(q + 1 != p) { + fSort = true; + vvFis[i][q + 1] = f; + vvCs[i][q + 1] = c; + } + } + if(nVerbose > 5) + for(unsigned j = 0; j < vvFis[i].size(); j++) { + std::stringstream ss; + ss << "\t\t\t\t\tFI " << j << " = " + << std::setw(5) << (vvFis[i][j] >> 1) << "(" << (vvFis[i][j] & 1) << ")"; + Print(ss.str(), true); + } + return fSort; + } + +private: // Symbolic simulation + inline lit LitFi(int i, int j) const { + int i0 = vvFis[i][j] >> 1; + bool c0 = vvFis[i][j] & 1; + return this->man->LitNotCond(vFs[i0], c0); + } + inline lit LitFi(int i, int j, std::vector const &vFs_) const { + int i0 = vvFis[i][j] >> 1; + bool c0 = vvFis[i][j] & 1; + return this->man->LitNotCond(vFs_[i0], c0); + } + inline void Build(int i, std::vector &vFs_) const { + if(nVerbose > 6) { + std::stringstream ss; + ss << "\t\t\t\tbuilding Gate" << std::setw(5) << i; + Print(ss.str(), nVerbose > 7); + } + this->Update(vFs_[i], this->man->Const1()); + for(unsigned j = 0; j < vvFis[i].size(); j++) + this->Update(vFs_[i], this->man->And(vFs_[i], LitFi(i, j, vFs_))); + } + inline void Build(bool fPfUpdate = true) { + if(nVerbose > 6) + Print("\t\t\tBuild", true); + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + if(vUpdates[*it]) { + lit x = vFs[*it]; + this->IncRef(x); + Build(*it, vFs); + this->DecRef(x); + if(!this->man->LitIsEq(x, vFs[*it])) + for(unsigned j = 0; j < vvFos[*it].size(); j++) + vUpdates[vvFos[*it][j]] = true; + } + if(fPfUpdate) + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vPfUpdates[*it] = vPfUpdates[*it] || vUpdates[*it]; + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vUpdates[*it] = false; + assert(AllFalse(vUpdates)); + } + void BuildFoConeCompl(int i, std::vector &vPoFsCompl) const { + if(nVerbose > 6) { + std::stringstream ss; + ss << "\t\t\tBuild with complemented Gate " << std::setw(5) << i; + Print(ss.str(), true); + } + std::vector vFsCompl; + this->CopyVec(vFsCompl, vFs); + vFsCompl[i] = this->man->LitNot(vFs[i]); + std::vector vUpdatesCompl(nObjsAlloc); + for(unsigned j = 0; j < vvFos[i].size(); j++) + vUpdatesCompl[vvFos[i][j]] = true; + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) + if(vUpdatesCompl[*it]) { + Build(*it, vFsCompl); + if(!this->man->LitIsEq(vFsCompl[*it], vFs[*it])) + for(unsigned j = 0; j < vvFos[*it].size(); j++) + vUpdatesCompl[vvFos[*it][j]] = true; + } + for(unsigned j = 0; j < vPos.size(); j++) + this->Update(vPoFsCompl[j], LitFi(vPos[j], 0, vFsCompl)); + this->DelVec(vFsCompl); + } + +private: // CSPF + inline int RemoveRedundantFis(int i, int block_i0 = -1, unsigned j = 0) { + int count = 0; + for(; j < vvFis[i].size(); j++) { + if(block_i0 == (vvFis[i][j] >> 1)) + continue; + lit x = this->man->Const1(); + this->IncRef(x); + for(unsigned jj = 0; jj < vvFis[i].size(); jj++) + if(j != jj) + this->Update(x, this->man->And(x, LitFi(i, jj))); + this->Update(x, this->man->Or(this->man->LitNot(x), vGs[i])); + this->Update(x, this->man->Or(x, LitFi(i, j))); + this->DecRef(x); + if(this->man->IsConst1(x)) { + int i0 = vvFis[i][j] >> 1; + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\t[Rrfi] remove Wire " << std::setw(5) << i0 << "(" << (vvFis[i][j] & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + Disconnect(i, i0, j--); + count++; + } + } + return count; + } + inline void CalcG(int i) { + this->Update(vGs[i], this->man->Const1()); + for(unsigned j = 0; j < vvFos[i].size(); j++) { + int k = vvFos[i][j]; + int l = FindFi(k, i); + assert(l >= 0); + this->Update(vGs[i], this->man->And(vGs[i], vvCs[k][l])); + } + } + inline int CalcC(int i) { + int count = 0; + for(unsigned j = 0; j < vvFis[i].size(); j++) { + lit x = this->man->Const1(); + this->IncRef(x); + for(unsigned jj = j + 1; jj < vvFis[i].size(); jj++) + this->Update(x, this->man->And(x, LitFi(i, jj))); + this->Update(x, this->man->Or(this->man->LitNot(x), vGs[i])); + int i0 = vvFis[i][j] >> 1; + if(this->man->IsConst1(this->man->Or(x, LitFi(i, j)))) { + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\t[Cspf] remove Wire " << std::setw(5) << i0 << "(" << (vvFis[i][j] & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + Disconnect(i, i0, j--); + count++; + } else if(!this->man->LitIsEq(vvCs[i][j], x)) { + this->Update(vvCs[i][j], x); + vPfUpdates[i0] = true; + } + this->DecRef(x); + } + return count; + } + int Cspf(bool fSortRemove, int block = -1, int block_i0 = -1) { + if(nVerbose > 3) + PrintPfHeader("Cspf", block, block_i0); + if(state != cspf) + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vPfUpdates[*it] = true; + state = cspf; + int count = 0; + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend();) { + if(vvFos[*it].empty()) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t\tremove unused Gate " << std::setw(5) << *it; + Print(ss.str(), nVerbose > 4); + } + count += Remove(*it); + it = std::list::reverse_iterator(vObjs.erase(--(it.base()))); + continue; + } + if(!vPfUpdates[*it]) { + it++; + continue; + } + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t\tprocessing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(vObjs.rbegin(), it) + 1 + << "/" << std::setw(5) << vObjs.size() << ")"; + Print(ss.str(), nVerbose > 4); + } + CalcG(*it); + if(fSortRemove) { + if(*it != block) + SortFis(*it), count += RemoveRedundantFis(*it); + else if(block_i0 != -1) + count += RemoveRedundantFis(*it, block_i0); + } + count += CalcC(*it); + vPfUpdates[*it] = false; + assert(!vvFis[*it].empty()); + if(vvFis[*it].size() == 1) { + count += Replace(*it, vvFis[*it][0]); + it = std::list::reverse_iterator(vObjs.erase(--(it.base()))); + continue; + } + it++; + } + Build(false); + assert(AllFalse(vPfUpdates)); + if(fLevel) + ComputeLevel(); + return count; + } + +private: // MSPF + inline bool MspfCalcG(int i) { + lit g = vGs[i]; + this->IncRef(g); + std::vector vPoFsCompl(vPos.size(), LitMax); + BuildFoConeCompl(i, vPoFsCompl); + this->Update(vGs[i], this->man->Const1()); + for(unsigned j = 0; j < vPos.size(); j++) { + lit x = this->man->LitNot(this->Xor(vPoFs[j], vPoFsCompl[j])); + this->IncRef(x); + this->Update(x, this->man->Or(x, vvCs[vPos[j]][0])); + this->Update(vGs[i], this->man->And(vGs[i], x)); + this->DecRef(x); + } + this->DelVec(vPoFsCompl); + this->DecRef(g); + return !this->man->LitIsEq(vGs[i], g); + } + inline int MspfCalcC(int i, int block_i0 = -1) { + for(unsigned j = 0; j < vvFis[i].size(); j++) { + lit x = this->man->Const1(); + this->IncRef(x); + for(unsigned jj = 0; jj < vvFis[i].size(); jj++) + if(j != jj) + this->Update(x, this->man->And(x, LitFi(i, jj))); + this->Update(x, this->man->Or(this->man->LitNot(x), vGs[i])); + int i0 = vvFis[i][j] >> 1; + if(i0 != block_i0 && this->man->IsConst1(this->man->Or(x, LitFi(i, j)))) { + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\t[Mspf] remove Wire " << std::setw(5) << i0 << "(" << (vvFis[i][j] & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + Disconnect(i, i0, j); + this->DecRef(x); + return RemoveRedundantFis(i, block_i0, j) + 1; + } else if(!this->man->LitIsEq(vvCs[i][j], x)) { + this->Update(vvCs[i][j], x); + vPfUpdates[i0] = true; + } + this->DecRef(x); + } + return 0; + } + int Mspf(bool fSort, int block = -1, int block_i0 = -1) { + if(nVerbose > 3) + PrintPfHeader("Mspf", block, block_i0); + assert(AllFalse(vUpdates)); + vFoConeShared.resize(nObjsAlloc); + if(state != mspf) + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vPfUpdates[*it] = true; + state = mspf; + int count = 0; + int restarts = 0; + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend();) { + if(vvFos[*it].empty()) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t\tremove unused Gate " << std::setw(5) << *it; + Print(ss.str(), nVerbose > 4); + } + count += Remove(*it); + it = std::list::reverse_iterator(vObjs.erase(--(it.base()))); + continue; + } + if(!vFoConeShared[*it] && !vPfUpdates[*it] && (vvFos[*it].size() == 1 || !IsFoConeShared(*it))) { + it++; + continue; + } + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t\tprocessing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(vObjs.rbegin(), it) + 1 + << "/" << std::setw(5) << vObjs.size() << ")" + << ", #restarts = " << std::setw(3) << restarts; + Print(ss.str(), nVerbose > 4); + } + if(vvFos[*it].size() == 1 || !IsFoConeShared(*it)) { + if(vFoConeShared[*it]) { + vFoConeShared[*it] = false; + lit g = vGs[*it]; + this->IncRef(g); + CalcG(*it); + this->DecRef(g); + if(g == vGs[*it] && !vPfUpdates[*it]) { + it++; + continue; + } + } else + CalcG(*it); + } else { + vFoConeShared[*it] = true; + if(!MspfCalcG(*it) && !vPfUpdates[*it]) { + it++; + continue; + } + bool IsConst1 = this->man->IsConst1(this->man->Or(vGs[*it], vFs[*it])); + bool IsConst0 = IsConst1? false: this->man->IsConst1(this->man->Or(vGs[*it], this->man->LitNot(vFs[*it]))); + if(IsConst1 || IsConst0) { + count += ReplaceByConst(*it, (int)IsConst1); + vObjs.erase(--(it.base())); + Build(); + it = vObjs.rbegin(); + restarts++; + continue; + } + } + if(fSort && block != *it) + SortFis(*it); + if(int diff = (block == *it)? MspfCalcC(*it, block_i0): MspfCalcC(*it)) { + count += diff; + assert(!vvFis[*it].empty()); + if(vvFis[*it].size() == 1) { + count += Replace(*it, vvFis[*it][0]); + vObjs.erase(--(it.base())); + } + Build(); + it = vObjs.rbegin(); + restarts++; + continue; + } + vPfUpdates[*it] = false; + it++; + } + assert(AllFalse(vUpdates)); + assert(AllFalse(vPfUpdates)); + if(fLevel) + ComputeLevel(); + return count; + } + +private: // Merge/decompose one + inline int TrivialMergeOne(int i) { + int count = 0; + std::vector vFisOld = vvFis[i]; + std::vector vCsOld = vvCs[i]; + vvFis[i].clear(); + vvCs[i].clear(); + for(unsigned j = 0; j < vFisOld.size(); j++) { + int i0 = vFisOld[j] >> 1; + int c0 = vFisOld[j] & 1; + if(vvFis[i0].empty() || vvFos[i0].size() > 1 || c0) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t[TrivialMerge] adding Wire " << std::setw(5) << i0 << "(" << c0 << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + vvFis[i].push_back(vFisOld[j]); + vvCs[i].push_back(vCsOld[j]); + continue; + } + vPfUpdates[i] = vPfUpdates[i] | vPfUpdates[i0]; + vvFos[i0].erase(find(vvFos[i0].begin(), vvFos[i0].end(), i)); + count++; + typename std::vector::iterator itfi = vFisOld.begin() + j; + typename std::vector::iterator itc = vCsOld.begin() + j; + for(unsigned jj = 0; jj < vvFis[i0].size(); jj++) { + int f = vvFis[i0][jj]; + std::vector::iterator it = find(vvFis[i].begin(), vvFis[i].end(), f); + if(it == vvFis[i].end()) { + vvFos[f >> 1].push_back(i); + itfi = vFisOld.insert(itfi, f); + itc = vCsOld.insert(itc, vvCs[i0][jj]); + this->IncRef(*itc); + itfi++; + itc++; + count--; + } else { + assert(state == none); + } + } + count += Remove(i0, false); + vObjs.erase(find(vObjs.begin(), vObjs.end(), i0)); + vFisOld.erase(itfi); + this->DecRef(*itc); + vCsOld.erase(itc); + j--; + } + return count; + } + inline int TrivialDecomposeOne(std::list::iterator const &it, int &pos) { + if(nVerbose > 2) { + std::stringstream ss; + ss << "\tTrivialDecompose Gate " << std::setw(5) << *it; + Print(ss.str() , nVerbose > 3); + } + assert(vvFis[*it].size() > 2); + int count = 2 - vvFis[*it].size(); + while(vvFis[*it].size() > 2) { + int f0 = vvFis[*it].back(); + lit c0 = vvCs[*it].back(); + Disconnect(*it, f0 >> 1, vvFis[*it].size() - 1, false, false); + int f1 = vvFis[*it].back(); + lit c1 = vvCs[*it].back(); + Disconnect(*it, f1 >> 1, vvFis[*it].size() - 1, false, false); + NewGate(pos); + Connect(pos, f1, false, false, c1); + Connect(pos, f0, false, false, c0); + if(!vPfUpdates[*it]) { + if(state == cspf) + this->Update(vGs[pos], vGs[*it]); + else if(state == mspf) { + lit x = this->man->Const1(); + this->IncRef(x); + for(unsigned j = 0; j < vvFis[*it].size(); j++) + this->Update(x, this->man->And(x, LitFi(*it, j))); + this->Update(vGs[pos], this->man->Or(this->man->LitNot(x), vGs[*it])); + this->DecRef(x); + } + } + Connect(*it, pos << 1, false, false, vGs[pos]); + vObjs.insert(it, pos); + Build(pos, vFs); + } + return count; + } + inline int BalancedDecomposeOne(std::list::iterator const &it, int &pos) { + if(nVerbose > 2) { + std::stringstream ss; + ss << "\tBalancedDecompose Gate " << std::setw(5) << *it; + Print(ss.str(), nVerbose > 3); + } + assert(fLevel); + assert(vvFis[*it].size() > 2); + for(int p = 1; p < (int)vvFis[*it].size(); p++) { + int f = vvFis[*it][p]; + lit c = vvCs[*it][p]; + int q = p - 1; + for(; q >= 0 && vLevels[f >> 1] > vLevels[vvFis[*it][q] >> 1]; q--) { + vvFis[*it][q + 1] = vvFis[*it][q]; + vvCs[*it][q + 1] = vvCs[*it][q]; + } + if(q + 1 != p) { + vvFis[*it][q + 1] = f; + vvCs[*it][q + 1] = c; + } + } + int count = 2 - vvFis[*it].size(); + while(vvFis[*it].size() > 2) { + int f0 = vvFis[*it].back(); + lit c0 = vvCs[*it].back(); + Disconnect(*it, f0 >> 1, vvFis[*it].size() - 1, false, false); + int f1 = vvFis[*it].back(); + lit c1 = vvCs[*it].back(); + Disconnect(*it, f1 >> 1, vvFis[*it].size() - 1, false, false); + NewGate(pos); + Connect(pos, f1, false, false, c1); + Connect(pos, f0, false, false, c0); + Connect(*it, pos << 1, false, false); + Build(pos, vFs); + vLevels[pos] = std::max(vLevels[f0 >> 1], vLevels[f1 >> 1]) + 1; + vObjs.insert(it, pos); + int f = vvFis[*it].back(); + lit c = vvCs[*it].back(); + int q = (int)vvFis[*it].size() - 2; + for(; q >= 0 && vLevels[f >> 1] > vLevels[vvFis[*it][q] >> 1]; q--) { + vvFis[*it][q + 1] = vvFis[*it][q]; + vvCs[*it][q + 1] = vvCs[*it][q]; + } + if(q + 1 != (int)vvFis[*it].size() - 1) { + vvFis[*it][q + 1] = f; + vvCs[*it][q + 1] = c; + } + } + vPfUpdates[*it] = true; + return count; + } + +public: // Merge/decompose + int TrivialMerge() { + int count = 0; + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend();) { + count += TrivialMergeOne(*it); + it++; + } + return count; + } + int TrivialDecompose() { + int count = 0; + int pos = vPis.size() + 1; + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + if(vvFis[*it].size() > 2) + count += TrivialDecomposeOne(it, pos); + return count; + } + int Decompose() { + int count = 0; + int pos = vPis.size() + 1; + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) { + std::set s1(vvFis[*it].begin(), vvFis[*it].end()); + assert(s1.size() == vvFis[*it].size()); + std::list::iterator it2 = it; + for(it2++; it2 != vObjs.end(); it2++) { + std::set s2(vvFis[*it2].begin(), vvFis[*it2].end()); + std::set s; + std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(s, s.begin())); + if(s.size() > 1) { + if(s == s1) { + if(s == s2) { + if(nVerbose > 2) { + std::stringstream ss; + ss << "\treplace Gate " << std::setw(5) << *it2 + << " by Gate " << std::setw(5) << *it; + Print(ss.str() , nVerbose > 3); + } + count += Replace(*it2, *it << 1, false); + it2 = vObjs.erase(it2); + it2--; + } else { + if(nVerbose > 2) { + std::stringstream ss; + ss << "\tdecompose Gate " << std::setw(5) << *it2 + << " by Gate " << std::setw(5) << *it; + Print(ss.str() , nVerbose > 3); + } + for(std::set::iterator it3 = s.begin(); it3 != s.end(); it3++) { + unsigned j = find(vvFis[*it2].begin(), vvFis[*it2].end(), *it3) - vvFis[*it2].begin(); + Disconnect(*it2, *it3 >> 1, j, false); + } + count += s.size(); + if(std::find(vvFis[*it2].begin(), vvFis[*it2].end(), *it << 1) == vvFis[*it2].end()) { + Connect(*it2, *it << 1, false, false); + count--; + } + vPfUpdates[*it2] = true; + } + continue; + } + if(s == s2) { + it = vObjs.insert(it, *it2); + vObjs.erase(it2); + } else { + NewGate(pos); + if(nVerbose > 2) { + std::stringstream ss; + ss << "\tdecompose Gate " << std::setw(5) << *it + << " and " << std::setw(5) << *it2 + << " by a new Gate " << std::setw(5) << pos; + Print(ss.str() , nVerbose > 3); + } + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\tIntersection:"; + for(std::set::iterator it3 = s.begin(); it3 != s.end(); it3++) + ss << " " << (*it3 >> 1) << "(" << (*it3 & 1) << ")"; + Print(ss.str(), true); + } + for(std::set::iterator it3 = s.begin(); it3 != s.end(); it3++) + Connect(pos, *it3, false, false); + count -= s.size(); + it = vObjs.insert(it, pos); + Build(pos, vFs); + vPfUpdates[*it] = true; + } + s1 = s; + it2 = it; + } + } + if(vvFis[*it].size() > 2) + count += TrivialDecomposeOne(it, pos); + } + return count; + } + +private: // Save/load + inline void Save(TransductionBackup &b) const { + b.man = this->man; + b.nObjsAlloc = nObjsAlloc; + b.state = state; + b.vObjs = vObjs; + b.vvFis = vvFis; + b.vvFos = vvFos; + b.vLevels = vLevels; + b.vSlacks = vSlacks; + b.vvFiSlacks = vvFiSlacks; + this->CopyVec(b.vFs, vFs); + this->CopyVec(b.vGs, vGs); + this->CopyVec(b.vvCs, vvCs); + b.vUpdates = vUpdates; + b.vPfUpdates = vPfUpdates; + b.vFoConeShared = vFoConeShared; + } + inline void Load(TransductionBackup const &b) { + nObjsAlloc = b.nObjsAlloc; + state = b.state; + vObjs = b.vObjs; + vvFis = b.vvFis; + vvFos = b.vvFos; + vLevels = b.vLevels; + vSlacks = b.vSlacks; + vvFiSlacks = b.vvFiSlacks; + this->CopyVec(vFs, b.vFs); + this->CopyVec(vGs, b.vGs); + this->CopyVec(vvCs, b.vvCs); + vUpdates = b.vUpdates; + vPfUpdates = b.vPfUpdates; + vFoConeShared = b.vFoConeShared; + } + +private: // Connectable condition + inline bool TryConnect(int i, int i0, bool c0) { + int f = (i0 << 1) ^ (int)c0; + if(find(vvFis[i].begin(), vvFis[i].end(), f) == vvFis[i].end()) { + lit x = this->man->Or(this->man->LitNot(vFs[i]), vGs[i]); + this->IncRef(x); + if(this->man->IsConst1(this->man->Or(x, this->man->LitNotCond(vFs[i0], c0)))) { + this->DecRef(x); + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t[TryConnect] adding Wire " << std::setw(5) << i0 << "(" << c0 << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + Connect(i, f, true); + return true; + } + this->DecRef(x); + } + return false; + } + +public: // Resubs + int Resub(bool fMspf) { + int count = fMspf? Mspf(true): Cspf(true); + int nodes = CountNodes(); + TransductionBackup b; + Save(b); + int count_ = count; + std::list targets = vObjs; + for(std::list::reverse_iterator it = targets.rbegin(); it != targets.rend(); it++) { + if(nVerbose > 1) { + std::stringstream ss; + ss << "[Resub] processing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(targets.rbegin(), it) + 1 + << "/" << std::setw(5) << targets.size() << ")"; + PrintStats(ss.str(), nVerbose > 2); + } + if(vvFos[*it].empty()) + continue; + count += TrivialMergeOne(*it); + std::vector lev; + if(fLevel) { + for(unsigned j = 0; j < vvFis[*it].size(); j++) + add(lev, vLevels[vvFis[*it][j] >> 1]); + if((int)lev.size() > vLevels[*it] + vSlacks[*it]) { + Load(b); + count = count_; + continue; + } + lev.resize(vLevels[*it] + vSlacks[*it]); + } + bool fConnect = false; + std::vector vMarks(nObjsAlloc); + MarkFoCone_rec(vMarks, *it); + std::list targets2 = vObjs; + for(std::list::iterator it2 = targets2.begin(); it2 != targets2.end(); it2++) { + if(fLevel && (int)lev.size() > vLevels[*it] + vSlacks[*it]) + break; + if(!vMarks[*it2] && !vvFos[*it2].empty()) + if(!fLevel || noexcess(lev, vLevels[*it2])) + if(TryConnect(*it, *it2, false) || TryConnect(*it, *it2, true)) { + fConnect = true; + count--; + if(fLevel) + add(lev, vLevels[*it2]); + } + } + if(fConnect) { + if(fMspf) { + Build(); + count += Mspf(true, *it); + } else { + vPfUpdates[*it] = true; + count += Cspf(true, *it); + } + if(!vvFos[*it].empty()) { + vPfUpdates[*it] = true; + count += fMspf? Mspf(true): Cspf(true); + } + } + if(nodes < CountNodes()) { + Load(b); + count = count_; + continue; + } + if(!vvFos[*it].empty() && vvFis[*it].size() > 2) { + std::list::iterator it2 = find(vObjs.begin(), vObjs.end(), *it); + int pos = nObjsAlloc; + if(fLevel) + count += BalancedDecomposeOne(it2, pos) + (fMspf? Mspf(true): Cspf(true)); + else + count += TrivialDecomposeOne(it2, pos); + } + nodes = CountNodes(); + Save(b); + count_ = count; + } + if(nVerbose) + PrintStats("Resub", true, 11); + return count; + } + int ResubMono(bool fMspf) { + int count = fMspf? Mspf(true): Cspf(true); + std::list targets = vObjs; + for(std::list::reverse_iterator it = targets.rbegin(); it != targets.rend(); it++) { + if(nVerbose > 1) { + std::stringstream ss; + ss << "[ResubMono] processing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(targets.rbegin(), it) + 1 + << "/" << std::setw(5) << targets.size() << ")"; + PrintStats(ss.str(), nVerbose > 2); + } + if(vvFos[*it].empty()) + continue; + count += TrivialMergeOne(*it); + TransductionBackup b; + Save(b); + int count_ = count; + for(unsigned i = 0; i < vPis.size(); i++) { + if(vvFos[*it].empty()) + break; + if(nVerbose > 2) { + std::stringstream ss; + ss << "\ttrying a new fanin PI " << std::setw(2) << i; + PrintStats(ss.str(), nVerbose > 3); + } + if(TryConnect(*it, vPis[i], false) || TryConnect(*it, vPis[i], true)) { + count--; + int diff; + if(fMspf) { + Build(); + diff = Mspf(true, *it, vPis[i]); + } else { + vPfUpdates[*it] = true; + diff = Cspf(true, *it, vPis[i]); + } + if(diff) { + count += diff; + if(!vvFos[*it].empty()) { + vPfUpdates[*it] = true; + count += fMspf? Mspf(true): Cspf(true); + } + if(fLevel && CountLevels() > nMaxLevels) { + Load(b); + count = count_; + } else { + Save(b); + count_ = count; + } + } else { + Load(b); + count = count_; + } + } + } + if(vvFos[*it].empty()) + continue; + std::vector vMarks(nObjsAlloc); + MarkFoCone_rec(vMarks, *it); + std::list targets2 = vObjs; + for(std::list::iterator it2 = targets2.begin(); it2 != targets2.end(); it2++) { + if(vvFos[*it].empty()) + break; + if(nVerbose > 2) { + std::stringstream ss; + ss << "\ttrying a new fanin Gate " << std::setw(5) << *it2 + << " (" << std::setw(5) << std::distance(targets2.begin(), it2) + 1 + << "/" << std::setw(5) << targets2.size() << ")"; + PrintStats(ss.str(), nVerbose > 3); + } + if(!vMarks[*it2] && !vvFos[*it2].empty()) + if(TryConnect(*it, *it2, false) || TryConnect(*it, *it2, true)) { + count--; + int diff; + if(fMspf) { + Build(); + diff = Mspf(true, *it, *it2); + } else { + vPfUpdates[*it] = true; + diff = Cspf(true, *it, *it2); + } + if(diff) { + count += diff; + if(!vvFos[*it].empty()) { + vPfUpdates[*it] = true; + count += fMspf? Mspf(true): Cspf(true); + } + if(fLevel && CountLevels() > nMaxLevels) { + Load(b); + count = count_; + } else { + Save(b); + count_ = count; + } + } else { + Load(b); + count = count_; + } + } + } + if(vvFos[*it].empty()) + continue; + if(vvFis[*it].size() > 2) { + std::list::iterator it2 = find(vObjs.begin(), vObjs.end(), *it); + int pos = nObjsAlloc; + if(fLevel) + count += BalancedDecomposeOne(it2, pos) + (fMspf? Mspf(true): Cspf(true)); + else + count += TrivialDecomposeOne(it2, pos); + } + } + if(nVerbose) + PrintStats("ResubMono", true, 11); + return count; + } + int ResubShared(bool fMspf) { + int count = fMspf? Mspf(true): Cspf(true); + std::list targets = vObjs; + for(std::list::reverse_iterator it = targets.rbegin(); it != targets.rend(); it++) { + if(nVerbose > 1) { + std::stringstream ss; + ss << "[ResubShared] processing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(targets.rbegin(), it) + 1 + << "/" << std::setw(5) << targets.size() << ")"; + PrintStats(ss.str(), nVerbose > 2); + } + if(vvFos[*it].empty()) + continue; + count += TrivialMergeOne(*it); + bool fConnect = false; + for(unsigned i = 0; i < vPis.size(); i++) + if(TryConnect(*it, vPis[i], false) || TryConnect(*it, vPis[i], true)) { + fConnect |= true; + count--; + } + std::vector vMarks(nObjsAlloc); + MarkFoCone_rec(vMarks, *it); + for(std::list::iterator it2 = targets.begin(); it2 != targets.end(); it2++) + if(!vMarks[*it2] && !vvFos[*it2].empty()) + if(TryConnect(*it, *it2, false) || TryConnect(*it, *it2, true)) { + fConnect |= true; + count--; + } + if(fConnect) { + if(fMspf) { + Build(); + count += Mspf(true, *it); + } else { + vPfUpdates[*it] = true; + count += Cspf(true, *it); + } + if(!vvFos[*it].empty()) { + vPfUpdates[*it] = true; + count += fMspf? Mspf(true): Cspf(true); + } + } + } + count += Decompose(); + if(nVerbose) + PrintStats("ResubShared", true, 11); + return count; + } + +public: // Optimization scripts + int RepeatResub(bool fMono, bool fMspf) { + int count = 0; + while(int diff = fMono? ResubMono(fMspf): Resub(fMspf)) + count += diff; + return count; + } + int RepeatInner(bool fMspf, bool fInner) { + int count = 0; + while(int diff = RepeatResub(true, fMspf) + RepeatResub(false, fMspf)) { + count += diff; + if(!fInner) + break; + } + return count; + } + int RepeatOuter(bool fMspf, bool fInner, bool fOuter) { + int count = 0; + while(int diff = fMspf? RepeatInner(false, fInner) + RepeatInner(true, fInner): RepeatInner(false, fInner)) { + count += diff; + if(!fOuter) + break; + } + return count; + } + int RepeatAll(bool fFirstMerge, bool fMspfMerge, bool fMspfResub, bool fInner, bool fOuter) { + TransductionBackup b; + Save(b); + int count = 0; + int diff = 0; + if(fFirstMerge) + diff = ResubShared(fMspfMerge); + diff += RepeatOuter(fMspfResub, fInner, fOuter); + if(diff > 0) { + count = diff; + Save(b); + diff = 0; + } + while(true) { + diff += ResubShared(fMspfMerge) + RepeatOuter(fMspfResub, fInner, fOuter); + if(diff > 0) { + count += diff; + Save(b); + diff = 0; + } else { + Load(b); + break; + } + } + return count; + } + +public: // Cspf/mspf + int Cspf() { + return Cspf(true); + } + int Mspf() { + return Mspf(true); + } + +private: // Setup + void ImportAig(Gia_Man_t *pGia) { + int i; + Gia_Obj_t *pObj; + nObjsAlloc = Gia_ManObjNum(pGia); + vvFis.resize(nObjsAlloc); + vvFos.resize(nObjsAlloc); + if(fLevel) { + vLevels.resize(nObjsAlloc); + vSlacks.resize(nObjsAlloc); + vvFiSlacks.resize(nObjsAlloc); + } + vFs.resize(nObjsAlloc, LitMax); + vGs.resize(nObjsAlloc, LitMax); + vvCs.resize(nObjsAlloc); + vUpdates.resize(nObjsAlloc); + vPfUpdates.resize(nObjsAlloc); + std::vector v(Gia_ManObjNum(pGia), -1); + int nObjs = 0; + v[Gia_ObjId(pGia, Gia_ManConst0(pGia))] = nObjs << 1; + nObjs++; + Gia_ManForEachCi(pGia, pObj, i) { + v[Gia_ObjId(pGia, pObj)] = nObjs << 1; + vPis.push_back(nObjs); + nObjs++; + } + Gia_ManForEachAnd(pGia, pObj, i) { + int id = Gia_ObjId(pGia, pObj); + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\timport Gate " << std::setw(5) << id; + Print(ss.str(), true); + } + int i0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + int i1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); + int c0 = Gia_ObjFaninC0(pObj); + int c1 = Gia_ObjFaninC1(pObj); + if(i0 == i1) { + if(c0 == c1) + v[id] = v[i0] ^ c0; + else + v[id] = 0; + } else { + Connect(nObjs , v[i0] ^ c0); + Connect(nObjs, v[i1] ^ c1); + v[id] = nObjs << 1; + vObjs.push_back(nObjs); + nObjs++; + } + } + Gia_ManForEachCo(pGia, pObj, i) { + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\timport PO " << std::setw(2) << i; + Print(ss.str(), true); + } + int i0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + int c0 = Gia_ObjFaninC0(pObj); + Connect(nObjs, v[i0] ^ c0); + vPos.push_back(nObjs); + nObjs++; + } + } + void Aig2Bdd(Gia_Man_t *pGia, std::vector &vNodes) { + if(nVerbose > 6) + Print("\t\t\tBuild Exdc", true); + int i; + Gia_Obj_t *pObj; + std::vector vCounts(pGia->nObjs); + Gia_ManStaticFanoutStart(pGia); + Gia_ManForEachAnd(pGia, pObj, i) + vCounts[Gia_ObjId(pGia, pObj)] = Gia_ObjFanoutNum(pGia, pObj); + Gia_ManStaticFanoutStop(pGia); + std::vector nodes(pGia->nObjs); + nodes[Gia_ObjId(pGia, Gia_ManConst0(pGia))] = this->man->Const0(); + Gia_ManForEachCi(pGia, pObj, i) + nodes[Gia_ObjId(pGia, pObj)] = this->man->IthVar(i); + Gia_ManForEachAnd(pGia, pObj, i) { + int id = Gia_ObjId(pGia, pObj); + if(nVerbose > 6) { + std::stringstream ss; + ss << "\t\t\t\tbuilding Exdc (" << i << " / " << Gia_ManAndNum(pGia) << ")"; + Print(ss.str(), nVerbose > 7); + } + int i0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + int i1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); + bool c0 = Gia_ObjFaninC0(pObj); + bool c1 = Gia_ObjFaninC1(pObj); + nodes[id] = this->man->And(this->man->LitNotCond(nodes[i0], c0), this->man->LitNotCond(nodes[i1], c1)); + this->IncRef(nodes[id]); + vCounts[i0]--; + if(!vCounts[i0]) + this->DecRef(nodes[i0]); + vCounts[i1]--; + if(!vCounts[i1]) + this->DecRef(nodes[i1]); + } + Gia_ManForEachCo(pGia, pObj, i) { + int i0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + bool c0 = Gia_ObjFaninC0(pObj); + vNodes.push_back(this->man->LitNotCond(nodes[i0], c0)); + } + } + void RemoveConstOutputs() { + bool fRemoved = false; + for(unsigned i = 0; i < vPos.size(); i++) { + int i0 = vvFis[vPos[i]][0] >> 1; + lit c = vvCs[vPos[i]][0]; + if(i0) { + if(this->man->IsConst1(this->man->Or(LitFi(vPos[i], 0), c))) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\tPO " << std::setw(2) << i << " is Const 1"; + Print(ss.str(), true); + } + Disconnect(vPos[i], i0, 0, false, false); + Connect(vPos[i], 1, false, false, c); + fRemoved |= vvFos[i0].empty(); + } else if(this->man->IsConst1(this->man->Or(this->man->LitNot(LitFi(vPos[i], 0)), c))) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\tPO " << std::setw(2) << i << " is Const 0"; + Print(ss.str(), true); + } + Disconnect(vPos[i], i0, 0, false, false); + Connect(vPos[i], 0, false, false, c); + fRemoved |= vvFos[i0].empty(); + } + } + } + if(fRemoved) { + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend();) { + if(vvFos[*it].empty()) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\tremove unused Gate " << std::setw(5) << *it; + Print(ss.str(), true); + } + Remove(*it, false); + it = std::list::reverse_iterator(vObjs.erase(--(it.base()))); + continue; + } + it++; + } + } + } + +public: // Constructor + Transduction(Gia_Man_t *pGia, int nVerbose, bool fNewLine, int nSortType, int nPiShuffle, bool fLevel, Gia_Man_t *pExdc, Param &p): nVerbose(nVerbose), nSortType(nSortType), fLevel(fLevel), fNewLine(fNewLine) { + startclk = Abc_Clock(); + p.nGbc = 1; + p.nReo = 4000; + if(nSortType && nSortType < 4) + p.fCountOnes = true; + this->man = new Man(Gia_ManCiNum(pGia), p); + ImportAig(pGia); + this->Update(vFs[0], this->man->Const0()); + for(unsigned i = 0; i < vPis.size(); i++) + this->Update(vFs[i + 1], this->man->IthVar(i)); + nMaxLevels = -1; + Build(false); + this->man->Reorder(); + this->man->TurnOffReo(); + if(pExdc) { + std::vector vExdc; + Aig2Bdd(pExdc, vExdc); + for(unsigned i = 0; i < vPos.size(); i++) + vvCs[vPos[i]][0] = vExdc.size() == 1? vExdc[0]: vExdc[i]; + } else + for(unsigned i = 0; i < vPos.size(); i++) + this->Update(vvCs[vPos[i]][0], this->man->Const0()); + RemoveConstOutputs(); + vPoFs.resize(vPos.size(), LitMax); + for(unsigned i = 0; i < vPos.size(); i++) + this->Update(vPoFs[i], LitFi(vPos[i], 0)); + state = none; + if(nPiShuffle) + ShufflePis(nPiShuffle); + if(fLevel) + ComputeLevel(); + if(nVerbose) + PrintStats("Init", true, 11); + } + ~Transduction() { + if(nVerbose) + PrintStats("End", true, 11); + this->DelVec(vFs); + this->DelVec(vGs); + this->DelVec(vvCs); + this->DelVec(vPoFs); + //assert(this->man->CountNodes() == (int)vPis.size() + 1); + //assert(!this->man->Ref(this->man->Const0())); + delete this->man; + } + +public: // Output + Gia_Man_t *GenerateAig() const { + Gia_Man_t * pGia, *pTemp; + pGia = Gia_ManStart(1 + vPis.size() + CountNodes() + vPos.size()); + Gia_ManHashAlloc(pGia); + std::vector values(nObjsAlloc); + values[0] = Gia_ManConst0Lit(); + for(unsigned i = 0; i < vPis.size(); i++) + values[i + 1] = Gia_ManAppendCi(pGia); + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) { + assert(vvFis[*it].size() > 1); + int i0 = vvFis[*it][0] >> 1; + int i1 = vvFis[*it][1] >> 1; + int c0 = vvFis[*it][0] & 1; + int c1 = vvFis[*it][1] & 1; + int r = Gia_ManHashAnd(pGia, Abc_LitNotCond(values[i0], c0), Abc_LitNotCond(values[i1], c1)); + for(unsigned i = 2; i < vvFis[*it].size(); i++) { + int ii = vvFis[*it][i] >> 1; + int ci = vvFis[*it][i] & 1; + r = Gia_ManHashAnd(pGia, r, Abc_LitNotCond(values[ii], ci)); + } + values[*it] = r; + } + for(unsigned i = 0; i < vPos.size(); i++) { + int i0 = vvFis[vPos[i]][0] >> 1; + int c0 = vvFis[vPos[i]][0] & 1; + Gia_ManAppendCo(pGia, Abc_LitNotCond(values[i0], c0)); + } + pGia = Gia_ManCleanup(pTemp = pGia); + Gia_ManStop(pTemp); + return pGia; + } + +public: // Debug and print + PfState State() const { + return state; + } + bool BuildDebug() { + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vUpdates[*it] = true; + std::vector vFsOld; + CopyVec(vFsOld, vFs); + Build(false); + bool r = LitVecIsEq(vFsOld, vFs); + DelVec(vFsOld); + return r; + } + bool CspfDebug() { + std::vector vGsOld; + this->CopyVec(vGsOld, vGs); + std::vector > vvCsOld; + this->CopyVec(vvCsOld, vvCs); + state = none; + Cspf(false); + bool r = this->LitVecIsEq(vGsOld, vGs) && this->LitVecIsEq(vvCsOld, vvCs); + this->DelVec(vGsOld); + this->DelVec(vvCsOld); + return r; + } + bool MspfDebug() { + std::vector vGsOld; + this->CopyVec(vGsOld, vGs); + std::vector > vvCsOld; + this->CopyVec(vvCsOld, vvCs); + state = none; + Mspf(false); + bool r = this->LitVecIsEq(vGsOld, vGs) && this->LitVecIsEq(vvCsOld, vvCs); + this->DelVec(vGsOld); + this->DelVec(vvCsOld); + return r; + } + bool Verify() const { + for(unsigned j = 0; j < vPos.size(); j++) { + lit x = this->Xor(LitFi(vPos[j], 0), vPoFs[j]); + this->IncRef(x); + this->Update(x, this->man->And(x, this->man->LitNot(vvCs[vPos[j]][0]))); + this->DecRef(x); + if(!this->man->IsConst0(x)) + return false; + } + return true; + } + void PrintObjs() const { + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) { + std::cout << "Gate " << *it << ":"; + if(fLevel) + std::cout << " Level = " << vLevels[*it] << ", Slack = " << vSlacks[*it]; + std::cout << std::endl; + std::string delim = ""; + std::cout << "\tFis: "; + for(unsigned j = 0; j < vvFis[*it].size(); j++) { + std::cout << delim << (vvFis[*it][j] >> 1) << "(" << (vvFis[*it][j] & 1) << ")"; + delim = ", "; + } + std::cout << std::endl; + delim = ""; + std::cout << "\tFos: "; + for(unsigned j = 0; j < vvFos[*it].size(); j++) { + std::cout << delim << vvFos[*it][j]; + delim = ", "; + } + std::cout << std::endl; + } + } +}; + +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/src/aig/gia/module.make b/src/aig/gia/module.make index 870da208e..236d43b32 100644 --- a/src/aig/gia/module.make +++ b/src/aig/gia/module.make @@ -103,6 +103,8 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaSwitch.c \ src/aig/gia/giaTim.c \ src/aig/gia/giaTis.c \ + src/aig/gia/giaTransduction.cpp \ + src/aig/gia/giaTranStoch.c \ src/aig/gia/giaTruth.c \ src/aig/gia/giaTsim.c \ src/aig/gia/giaTtopt.cpp \ diff --git a/src/aig/ivy/ivyShow.c b/src/aig/ivy/ivyShow.c index 3aa1e041a..3b8c7cc0a 100644 --- a/src/aig/ivy/ivyShow.c +++ b/src/aig/ivy/ivyShow.c @@ -46,7 +46,7 @@ static void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_ ***********************************************************************/ void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) { - extern void Abc_ShowFile( char * FileNameDot ); + extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); static int Counter = 0; char FileNameDot[200]; FILE * pFile; @@ -63,7 +63,7 @@ void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) // generate the file Ivy_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } /**Function************************************************************* diff --git a/src/aig/miniaig/miniaig.h b/src/aig/miniaig/miniaig.h index 9aa41b119..c7ce14e96 100644 --- a/src/aig/miniaig/miniaig.h +++ b/src/aig/miniaig/miniaig.h @@ -103,6 +103,12 @@ static int Mini_AigNodeFanin1( Mini_Aig_t * p, int Id ) assert( p->pArray[2*Id+1] == MINI_AIG_NULL || p->pArray[2*Id+1] < 2*Id ); return p->pArray[2*Id+1]; } +static void Mini_AigFlipLastPo( Mini_Aig_t * p ) +{ + assert( p->pArray[p->nSize-1] == MINI_AIG_NULL ); + assert( p->pArray[p->nSize-2] != MINI_AIG_NULL ); + p->pArray[p->nSize-2] ^= 1; +} // working with variables and literals static int Mini_AigVar2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } @@ -156,6 +162,34 @@ static Mini_Aig_t * Mini_AigStartSupport( int nIns, int nObjsAlloc ) p->pArray[i] = MINI_AIG_NULL; return p; } +static Mini_Aig_t * Mini_AigStartArray( int nIns, int n0InAnds, int * p0InAnds, int nOuts, int * pOuts ) +{ + Mini_Aig_t * p; int i; + assert( 1+nIns <= n0InAnds ); + p = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); + p->nCap = 2*(n0InAnds + nOuts); + p->nSize = 2*(n0InAnds + nOuts); + p->pArray = MINI_AIG_ALLOC( int, p->nCap ); + for ( i = 0; i < 2*(1 + nIns); i++ ) + p->pArray[i] = MINI_AIG_NULL; + memcpy( p->pArray + 2*(1 + nIns), p0InAnds + 2*(1 + nIns), 2*(n0InAnds - 1 - nIns)*sizeof(int) ); + for ( i = 0; i < nOuts; i++ ) + { + p->pArray[2*(n0InAnds + i)+0] = pOuts[i]; + p->pArray[2*(n0InAnds + i)+1] = MINI_AIG_NULL; + } + return p; +} +static Mini_Aig_t * Mini_AigDup( Mini_Aig_t * p ) +{ + Mini_Aig_t * pNew; + pNew = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); + pNew->nCap = p->nCap; + pNew->nSize = p->nSize; + pNew->pArray = MINI_AIG_ALLOC( int, p->nSize ); + memcpy( pNew->pArray, p->pArray, p->nSize * sizeof(int) ); + return pNew; +} static void Mini_AigStop( Mini_Aig_t * p ) { MINI_AIG_FREE( p->pArray ); @@ -346,6 +380,32 @@ static int Mini_AigMuxMulti_rec( Mini_Aig_t * p, int * pCtrl, int * pData, int n Res1 = Mini_AigMuxMulti_rec( p, pCtrl+1, pData+nData/2, nData/2 ); return Mini_AigMux( p, pCtrl[0], Res1, Res0 ); } +static Mini_Aig_t * Mini_AigTransformXor( Mini_Aig_t * p ) +{ + Mini_Aig_t * pNew = Mini_AigStart(); + int i, * pCopy = MINI_AIG_ALLOC( int, Mini_AigNodeNum(p) ); + Mini_AigForEachPi( p, i ) + pCopy[i] = Mini_AigCreatePi(pNew); + Mini_AigForEachAnd( p, i ) + { + int iLit0 = Mini_AigNodeFanin0(p, i); + int iLit1 = Mini_AigNodeFanin1(p, i); + iLit0 = Mini_AigLitNotCond( pCopy[Mini_AigLit2Var(iLit0)], Mini_AigLitIsCompl(iLit0) ); + iLit1 = Mini_AigLitNotCond( pCopy[Mini_AigLit2Var(iLit1)], Mini_AigLitIsCompl(iLit1) ); + if ( iLit0 <= iLit1 ) + pCopy[i] = Mini_AigAnd( pNew, iLit0, iLit1 ); + else + pCopy[i] = Mini_AigXor( pNew, iLit0, iLit1 ); + } + Mini_AigForEachPo( p, i ) + { + int iLit0 = Mini_AigNodeFanin0( p, i ); + iLit0 = Mini_AigLitNotCond( pCopy[Mini_AigLit2Var(iLit0)], Mini_AigLitIsCompl(iLit0) ); + pCopy[i] = Mini_AigCreatePo( pNew, iLit0 ); + } + MINI_AIG_FREE( pCopy ); + return pNew; +} static unsigned s_MiniTruths5[5] = { @@ -501,6 +561,76 @@ static void Mini_AigDumpVerilog( char * pFileName, char * pModuleName, Mini_Aig_ fclose( pFile ); } +// procedure to dump MiniAIG into a BLIF file +static void Mini_AigDumpBlif( char * pFileName, char * pModuleName, Mini_Aig_t * p, int fVerbose ) +{ + int i, k, iFaninLit0, iFaninLit1; + char * pObjIsPi = MINI_AIG_FALLOC( char, Mini_AigNodeNum(p) ); + FILE * pFile = fopen( pFileName, "wb" ); + assert( Mini_AigPiNum(p) <= 26 ); + if ( pFile == NULL ) { printf( "Cannot open output file %s\n", pFileName ); MINI_AIG_FREE( pObjIsPi ); return; } + // write interface + //fprintf( pFile, "// This MiniAIG dump was produced by ABC on %s\n\n", Extra_TimeStamp() ); + fprintf( pFile, ".model %s\n", pModuleName ); + if ( Mini_AigPiNum(p) ) + { + k = 0; + fprintf( pFile, ".inputs" ); + Mini_AigForEachPi( p, i ) + { + pObjIsPi[i] = k; + fprintf( pFile, " %c", (char)('a'+k++) ); + } + } + k = 0; + fprintf( pFile, "\n.outputs" ); + Mini_AigForEachPo( p, i ) + fprintf( pFile, " o%d", k++ ); + fprintf( pFile, "\n\n" ); + // write LUTs + Mini_AigForEachAnd( p, i ) + { + iFaninLit0 = Mini_AigNodeFanin0( p, i ); + iFaninLit1 = Mini_AigNodeFanin1( p, i ); + fprintf( pFile, ".names" ); + if ( pObjIsPi[iFaninLit0 >> 1] >= 0 ) + fprintf( pFile, " %c", (char)('a'+pObjIsPi[iFaninLit0 >> 1]) ); + else + fprintf( pFile, " n%d", iFaninLit0 >> 1 ); + if ( pObjIsPi[iFaninLit1 >> 1] >= 0 ) + fprintf( pFile, " %c", (char)('a'+pObjIsPi[iFaninLit1 >> 1]) ); + else + fprintf( pFile, " n%d", iFaninLit1 >> 1 ); + fprintf( pFile, " n%d\n", i ); + if ( iFaninLit0 < iFaninLit1 ) + fprintf( pFile, "%d%d 1\n", !(iFaninLit0 & 1), !(iFaninLit1 & 1) ); + else if ( !(iFaninLit0 & 1) == !(iFaninLit1 & 1) ) + fprintf( pFile, "10 1\n01 1\n" ); + else + fprintf( pFile, "00 1\n11 1\n" ); + } + // write assigns + fprintf( pFile, "\n" ); + k = 0; + Mini_AigForEachPo( p, i ) + { + iFaninLit0 = Mini_AigNodeFanin0( p, i ); + fprintf( pFile, ".names" ); + if ( pObjIsPi[iFaninLit0 >> 1] >= 0 ) + fprintf( pFile, " %c", (char)('a'+pObjIsPi[iFaninLit0 >> 1]) ); + else + fprintf( pFile, " n%d", iFaninLit0 >> 1 ); + fprintf( pFile, " o%d\n", k++ ); + fprintf( pFile, "%d 1\n", !(iFaninLit0 & 1) ); + } + fprintf( pFile, ".end\n\n" ); + MINI_AIG_FREE( pObjIsPi ); + fclose( pFile ); + if ( fVerbose ) + printf( "Written MiniAIG into the BLIF file \"%s\".\n", pFileName ); +} + + // checks if MiniAIG is normalized (first inputs, then internal nodes, then outputs) static int Mini_AigIsNormalized( Mini_Aig_t * p ) { diff --git a/src/aig/saig/saigIoa.c b/src/aig/saig/saigIoa.c index 35d7b7b27..c235c186e 100644 --- a/src/aig/saig/saigIoa.c +++ b/src/aig/saig/saigIoa.c @@ -45,17 +45,17 @@ ABC_NAMESPACE_IMPL_START ***********************************************************************/ char * Saig_ObjName( Aig_Man_t * p, Aig_Obj_t * pObj ) { - static char Buffer[16]; + static char Buffer[1000]; if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ) - sprintf( Buffer, "n%0*d", Abc_Base10Log(Aig_ManObjNumMax(p)), Aig_ObjId(pObj) ); + sprintf( Buffer, "n%0*d", (unsigned char)Abc_Base10Log(Aig_ManObjNumMax(p)), Aig_ObjId(pObj) ); else if ( Saig_ObjIsPi(p, pObj) ) - sprintf( Buffer, "pi%0*d", Abc_Base10Log(Saig_ManPiNum(p)), Aig_ObjCioId(pObj) ); + sprintf( Buffer, "pi%0*d", (unsigned char)Abc_Base10Log(Saig_ManPiNum(p)), Aig_ObjCioId(pObj) ); else if ( Saig_ObjIsPo(p, pObj) ) - sprintf( Buffer, "po%0*d", Abc_Base10Log(Saig_ManPoNum(p)), Aig_ObjCioId(pObj) ); + sprintf( Buffer, "po%0*d", (unsigned char)Abc_Base10Log(Saig_ManPoNum(p)), Aig_ObjCioId(pObj) ); else if ( Saig_ObjIsLo(p, pObj) ) - sprintf( Buffer, "lo%0*d", Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPiNum(p) ); + sprintf( Buffer, "lo%0*d", (unsigned char)Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPiNum(p) ); else if ( Saig_ObjIsLi(p, pObj) ) - sprintf( Buffer, "li%0*d", Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPoNum(p) ); + sprintf( Buffer, "li%0*d", (unsigned char)Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPoNum(p) ); else assert( 0 ); return Buffer; diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index b4e22a38c..5cf7a0f59 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -783,6 +783,7 @@ extern ABC_DLL void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_ extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromRange( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateWithNodes( Vec_Ptr_t * vSops ); extern ABC_DLL void Abc_NtkDelete( Abc_Ntk_t * pNtk ); @@ -877,7 +878,7 @@ extern ABC_DLL void Abc_NodeMffcConeSupp( Abc_Obj_t * pNode, Vec_P extern ABC_DLL int Abc_NodeDeref_rec( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeRef_rec( Abc_Obj_t * pNode ); /*=== abcRefactor.c ==========================================================*/ -extern ABC_DLL int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); +extern ABC_DLL int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nMinSaved, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); /*=== abcRewrite.c ==========================================================*/ extern ABC_DLL int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ); /*=== abcSat.c ==========================================================*/ diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c index 633533442..2c8e03b34 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -1229,6 +1229,41 @@ Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) return pNtkNew; } +/**Function************************************************************* + + Synopsis [Creates the network composed of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateFromRange( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNodeNew, * pNodePo; + Gia_Man_t * p = Abc_NtkClpGia( pNtk ); int i; + Vec_Str_t * vStr = Gia_ManComputeRange( p ); + Gia_ManStop( p ); + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtkNew->pName = Extra_UtilStrsav("range"); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pObj), NULL ); + pNodeNew = Abc_NtkCreateObj( pNtkNew, ABC_OBJ_NODE ); + pNodeNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, Vec_StrArray(vStr) ); + Vec_StrFree( vStr ); + Abc_NtkForEachCi( pNtkNew, pObj, i ) + Abc_ObjAddFanin( pNodeNew, pObj ); + pNodePo = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pNodePo, pNodeNew ); + Abc_ObjAssignName( pNodePo, "range", NULL ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateFromNode(): Network check has failed.\n" ); + return pNtkNew; +} + /**Function************************************************************* Synopsis [Creates the network composed of one node with the given SOP.] @@ -1286,7 +1321,7 @@ Abc_Ntk_t * Abc_NtkCreateWithNodes( Vec_Ptr_t * vSop ) Abc_Ntk_t * pNtkNew; Abc_Obj_t * pFanin, * pNode, * pNodePo; Vec_Ptr_t * vNames; - int i, k, nVars; char Buffer[10]; + int i, k, nVars; char Buffer[100]; char * pSop = (char *)Vec_PtrEntry(vSop, 0); // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); diff --git a/src/base/abc/abcShow.c b/src/base/abc/abcShow.c index dd8e9efed..5bf8fd8a5 100644 --- a/src/base/abc/abcShow.c +++ b/src/base/abc/abcShow.c @@ -40,7 +40,7 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -extern void Abc_ShowFile( char * FileNameDot ); +extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); static void Abc_ShowGetFileName( char * pName, char * pBuffer ); //////////////////////////////////////////////////////////////////////// @@ -71,7 +71,7 @@ void Abc_NodeShowBddOne( DdManager * dd, DdNode * bFunc ) } Cudd_DumpDot( dd, 1, (DdNode **)&bFunc, NULL, NULL, pFile ); fclose( pFile ); - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } /**Function************************************************************* @@ -119,7 +119,7 @@ void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ) fclose( pFile ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ) { @@ -181,7 +181,7 @@ void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ) Abc_NtkCleanCopy( pNtk ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } #else @@ -246,7 +246,7 @@ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) Abc_NtkManCutStop( p ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } /**Function************************************************************* @@ -260,7 +260,7 @@ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) SeeAlso [] ***********************************************************************/ -void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse ) +void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse, int fKeepDot ) { FILE * pFile; Abc_Ntk_t * pNtk; @@ -307,7 +307,7 @@ void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse ) Vec_PtrFree( vNodes ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, fKeepDot ); Abc_NtkDelete( pNtk ); } @@ -323,7 +323,7 @@ void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse ) SeeAlso [] ***********************************************************************/ -void Abc_ShowFile( char * FileNameDot ) +void Abc_ShowFile( char * FileNameDot, int fKeepDot ) { FILE * pFile; char * FileGeneric; @@ -390,7 +390,7 @@ void Abc_ShowFile( char * FileNameDot ) // spawn the viewer #ifdef WIN32 - _unlink( FileNameDot ); + if ( !fKeepDot ) _unlink( FileNameDot ); if ( _spawnl( _P_NOWAIT, pGsNameWin, pGsNameWin, FileNamePs, NULL ) == -1 ) if ( _spawnl( _P_NOWAIT, "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", FileNamePs, NULL ) == -1 ) @@ -403,7 +403,7 @@ void Abc_ShowFile( char * FileNameDot ) #else { char CommandPs[1000]; - unlink( FileNameDot ); + if ( !fKeepDot ) unlink( FileNameDot ); sprintf( CommandPs, "%s %s &", pGsNameUnix, FileNamePs ); #if defined(__wasm) if ( 1 ) @@ -524,7 +524,7 @@ void Abc_NtkShowFlopDependency( Abc_Ntk_t * pNtk ) // write the DOT file Abc_NtkWriteFlopDependency( pNtk, FileNameDot ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index fd677ace4..5007415fe 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -63,6 +63,7 @@ #include "opt/fret/fretime.h" #include "opt/nwk/nwkMerge.h" #include "base/acb/acbPar.h" +#include "misc/extra/extra.h" #ifndef _WIN32 @@ -193,6 +194,7 @@ static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandReach ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCone ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandNode ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRange ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCof ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTopmost ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBottommost ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -501,6 +503,8 @@ static int Abc_CommandAbc9LNetEval ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9LNetOpt ( Abc_Frame_t * pAbc, int argc, char ** argv ); //#ifndef _WIN32 static int Abc_CommandAbc9Ttopt ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Transduction ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9TranStoch ( 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 ); @@ -586,6 +590,7 @@ static int Abc_CommandAbc9Gla2Fla ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Gen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ProdAdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -601,6 +606,8 @@ extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); extern Vec_Ptr_t * Abc_NtkCollectCiNames( Abc_Ntk_t * pNtk ); extern Vec_Ptr_t * Abc_NtkCollectCoNames( Abc_Ntk_t * pNtk ); +extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -948,6 +955,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "reach", Abc_CommandReach, 0 ); Cmd_CommandAdd( pAbc, "Various", "cone", Abc_CommandCone, 1 ); Cmd_CommandAdd( pAbc, "Various", "node", Abc_CommandNode, 1 ); + Cmd_CommandAdd( pAbc, "Various", "range", Abc_CommandRange, 1 ); Cmd_CommandAdd( pAbc, "Various", "cof", Abc_CommandCof, 1 ); Cmd_CommandAdd( pAbc, "Various", "topmost", Abc_CommandTopmost, 1 ); Cmd_CommandAdd( pAbc, "Various", "bottommost", Abc_CommandBottommost, 1 ); @@ -1254,6 +1262,8 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&lnetopt", Abc_CommandAbc9LNetOpt, 0 ); //#ifndef _WIN32 Cmd_CommandAdd( pAbc, "ABC9", "&ttopt", Abc_CommandAbc9Ttopt, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&transduction", Abc_CommandAbc9Transduction, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&transtoch" , Abc_CommandAbc9TranStoch, 0 ); //#endif Cmd_CommandAdd( pAbc, "ABC9", "&lnetmap", Abc_CommandAbc9LNetMap, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&unmap", Abc_CommandAbc9Unmap, 0 ); @@ -1345,6 +1355,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&gen", Abc_CommandAbc9Gen, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cfs", Abc_CommandAbc9Cfs, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&prodadd", Abc_CommandAbc9ProdAdd, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); { @@ -1886,18 +1897,24 @@ usage: ***********************************************************************/ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Abc_NodePrintSop( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ); + extern void Abc_NtkPrintSop( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; - int c; + int c, fSop = 0; int fUseRealNames; // set defaults fUseRealNames = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "snh" ) ) != EOF ) { switch ( c ) { + case 's': + fSop ^= 1; + break; case 'n': fUseRealNames ^= 1; break; @@ -1934,16 +1951,23 @@ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } - Abc_NodePrintFactor( stdout, pNode, fUseRealNames ); + if ( fSop ) + Abc_NodePrintSop( stdout, pNode, fUseRealNames ); + else + Abc_NodePrintFactor( stdout, pNode, fUseRealNames ); return 0; } // print the nodes - Abc_NtkPrintFactor( stdout, pNtk, fUseRealNames ); + if ( fSop ) + Abc_NtkPrintSop( stdout, pNtk, fUseRealNames ); + else + Abc_NtkPrintFactor( stdout, pNtk, fUseRealNames ); return 0; usage: - Abc_Print( -2, "usage: print_factor [-nh] \n" ); - Abc_Print( -2, "\t prints the factored forms of nodes\n" ); + Abc_Print( -2, "usage: print_factor [-snh] \n" ); + Abc_Print( -2, "\t prints the factored forms (FFs) of nodes\n" ); + Abc_Print( -2, "\t-s : toggles printing SOP instead of FF [default = %s]\n", fSop? "SOP": "FF" ); Abc_Print( -2, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tnode : (optional) one node to consider\n"); @@ -3143,7 +3167,8 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) int fGateNames; int fUseReverse; int fFlopDep; - extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse ); + int fKeepDot; + extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse, int fKeepDot ); extern void Abc_NtkShowFlopDependency( Abc_Ntk_t * pNtk ); // set defaults @@ -3151,8 +3176,9 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) fGateNames = 0; fUseReverse = 1; fFlopDep = 0; + fKeepDot = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "rsgfh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "rsgfdh" ) ) != EOF ) { switch ( c ) { @@ -3168,6 +3194,9 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'f': fFlopDep ^= 1; break; + case 'd': + fKeepDot ^= 1; + break; default: goto usage; } @@ -3182,11 +3211,11 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fFlopDep ) Abc_NtkShowFlopDependency( pNtk ); else - Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse ); + Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse, fKeepDot ); return 0; usage: - Abc_Print( -2, "usage: show [-srgfh]\n" ); + Abc_Print( -2, "usage: show [-srgfdh]\n" ); Abc_Print( -2, " visualizes the network structure using DOT and GSVIEW\n" ); #ifdef WIN32 Abc_Print( -2, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); @@ -3196,6 +3225,7 @@ usage: Abc_Print( -2, "\t-r : toggles ordering nodes in reverse order [default = %s].\n", fUseReverse? "yes": "no" ); Abc_Print( -2, "\t-g : toggles printing gate names for mapped network [default = %s].\n", fGateNames? "yes": "no" ); Abc_Print( -2, "\t-f : toggles visualizing flop dependency graph [default = %s].\n", fFlopDep? "yes": "no" ); + Abc_Print( -2, "\t-d : toggles keeping the .dot file used to produce the .ps file [default = %s].\n", fKeepDot? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -7447,22 +7477,24 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; int c, RetValue; int nNodeSizeMax; + int nMinSaved; int nConeSizeMax; int fUpdateLevel; int fUseZeros; int fUseDcs; int fVerbose; - extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); + extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nMinSaved, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); // set defaults nNodeSizeMax = 10; + nMinSaved = 1; nConeSizeMax = 16; fUpdateLevel = 1; fUseZeros = 0; fUseDcs = 0; fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Nlzvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "NMClzvh" ) ) != EOF ) { switch ( c ) { @@ -7477,6 +7509,17 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nNodeSizeMax < 0 ) goto usage; break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMinSaved = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMinSaved < 0 ) + goto usage; + break; case 'C': if ( globalUtilOptind >= argc ) { @@ -7506,6 +7549,10 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( fUseZeros ) + nMinSaved = 0; + if ( nMinSaved == 0 ) + fUseZeros = 1; if ( pNtk == NULL ) { @@ -7536,7 +7583,7 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) // modify the current network pDup = Abc_NtkDup( pNtk ); - RetValue = Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ); + RetValue = Abc_NtkRefactor( pNtk, nNodeSizeMax, nMinSaved, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ); if ( RetValue == -1 ) { Abc_FrameReplaceCurrentNetwork( pAbc, pDup ); @@ -7554,9 +7601,10 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: refactor [-N ] [-lzvh]\n" ); + Abc_Print( -2, "usage: refactor [-NM ] [-lzvh]\n" ); Abc_Print( -2, "\t performs technology-independent refactoring of the AIG\n" ); Abc_Print( -2, "\t-N : the max support of the collapsed node [default = %d]\n", nNodeSizeMax ); + Abc_Print( -2, "\t-M : the min number of nodes saved after one step (0 <= num) [default = %d]\n", nMinSaved ); // Abc_Print( -2, "\t-C : the max support of the containing cone [default = %d]\n", nConeSizeMax ); Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); @@ -7684,22 +7732,24 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) int nCutsMax; int nNodesMax; int nLevelsOdc; + int nMinSaved; int fUpdateLevel; int fUseZeros; int fVerbose; int fVeryVerbose; - extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose ); + extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nMinSaved, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose ); // set defaults nCutsMax = 8; nNodesMax = 1; nLevelsOdc = 0; + nMinSaved = 1; fUpdateLevel = 1; fUseZeros = 0; fVerbose = 0; fVeryVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KNFlzvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KNMFlzvwh" ) ) != EOF ) { switch ( c ) { @@ -7725,6 +7775,17 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nNodesMax < 0 ) goto usage; break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMinSaved = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMinSaved < 0 ) + goto usage; + break; case 'F': if ( globalUtilOptind >= argc ) { @@ -7754,6 +7815,10 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( fUseZeros ) + nMinSaved = 0; + if ( nMinSaved == 0 ) + fUseZeros = 1; if ( pNtk == NULL ) { @@ -7782,7 +7847,7 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) } // modify the current network - if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) ) + if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nMinSaved, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) ) { Abc_Print( -1, "Refactoring has failed.\n" ); return 1; @@ -7790,10 +7855,11 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: resub [-KN ] [-lzvwh]\n" ); + Abc_Print( -2, "usage: resub [-KNMF ] [-lzvwh]\n" ); Abc_Print( -2, "\t performs technology-independent restructuring of the AIG\n" ); Abc_Print( -2, "\t-K : the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax ); Abc_Print( -2, "\t-N : the max number of nodes to add (0 <= num <= 3) [default = %d]\n", nNodesMax ); + Abc_Print( -2, "\t-M : the min number of nodes saved after one step (0 <= num) [default = %d]\n", nMinSaved ); Abc_Print( -2, "\t-F : the number of fanout levels for ODC computation [default = %d]\n", nLevelsOdc ); Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); @@ -8774,6 +8840,7 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) extern void Exa_ManExactSynthesis2( Bmc_EsPar_t * pPars ); extern void Exa_ManExactSynthesis4( Bmc_EsPar_t * pPars ); extern void Exa_ManExactSynthesis5( Bmc_EsPar_t * pPars ); + extern void Exa_ManExactSynthesis6( Bmc_EsPar_t * pPars, char * pFileName ); int c, fKissat = 0, fKissat2 = 0; Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); @@ -8852,7 +8919,14 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) } } if ( argc == globalUtilOptind + 1 ) + { + if ( strstr(argv[globalUtilOptind], ".") ) + { + Exa_ManExactSynthesis6( pPars, argv[globalUtilOptind] ); + return 0; + } pPars->pTtStr = argv[globalUtilOptind]; + } if ( pPars->pTtStr == NULL ) { Abc_Print( -1, "Truth table should be given on the command line.\n" ); @@ -11889,6 +11963,59 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRange( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + pNtk = Abc_FrameReadNtk(pAbc); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Currently can only be applied to an AIG.\n" ); + return 1; + } + pNtkRes = Abc_NtkCreateFromRange( pNtk ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Deriving the network has failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: range [-h]\n" ); + Abc_Print( -2, "\t computes the range of output values as one node\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -14103,11 +14230,14 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) //Extra_SimulationTest( nDivMax, nNumOnes, fNewOrder ); //Mnist_ExperimentWithScaling( nDecMax ); //Gyx_ProblemSolveTest(); +/* { extern Abc_Ntk_t * Abc_NtkFromArray(); Abc_Ntk_t * pNtkRes = Abc_NtkFromArray(); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } +*/ + return 0; usage: Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] \n" ); @@ -14710,7 +14840,7 @@ int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Dar_ManDefaultRwrParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CNflzrvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "CNMflzrvwh" ) ) != EOF ) { switch ( c ) { @@ -14736,6 +14866,17 @@ int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nSubgMax < 0 ) goto usage; break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMinSaved = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMinSaved < 0 ) + goto usage; + break; case 'f': pPars->fFanout ^= 1; break; @@ -14760,6 +14901,10 @@ int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( pPars->fUseZeros ) + pPars->nMinSaved = 0; + if ( pPars->nMinSaved == 0 ) + pPars->fUseZeros = 1; if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); @@ -14781,10 +14926,11 @@ int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: drw [-C num] [-N num] [-lfzrvwh]\n" ); + Abc_Print( -2, "usage: drw [-C num] [-NM num] [-lfzrvwh]\n" ); Abc_Print( -2, "\t performs combinational AIG rewriting\n" ); Abc_Print( -2, "\t-C num : the max number of cuts at a node [default = %d]\n", pPars->nCutsMax ); Abc_Print( -2, "\t-N num : the max number of subgraphs tried [default = %d]\n", pPars->nSubgMax ); + Abc_Print( -2, "\t-M num : the min number of nodes saved after one step (0 <= num) [default = %d]\n", pPars->nMinSaved ); Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" ); Abc_Print( -2, "\t-f : toggle representing fanouts [default = %s]\n", pPars->fFanout? "yes": "no" ); Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" ); @@ -30883,9 +31029,9 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) // transfer PO names to pNtk if ( pAbc->pGia->vNamesOut ) { - char pSuffix[100]; - Abc_Obj_t * pObj; - int i, nDigits = Abc_Base10Log( Abc_NtkLatchNum(pNtk) ); + char pSuffix[1000]; + Abc_Obj_t * pObj; int i; + unsigned char nDigits = (unsigned char)Abc_Base10Log( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) { if (i < Vec_PtrSize(pAbc->pGia->vNamesOut)) { Nm_ManDeleteIdName(pNtk->pManName, pObj->Id); @@ -33734,11 +33880,11 @@ usage: ***********************************************************************/ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) { - int c, fOutputs = 0, nWords = 4, fVerbose = 0; + int c, fOutputs = 0, nWords = 4, fTruth = 0, fVerbose = 0; char ** pArgvNew; int nArgcNew; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Wovh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Wtovh" ) ) != EOF ) { switch ( c ) { @@ -33753,6 +33899,9 @@ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nWords < 0 ) goto usage; break; + case 't': + fTruth ^= 1; + break; case 'o': fOutputs ^= 1; break; @@ -33775,6 +33924,19 @@ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9ReadSim(): This command works only for combinational AIGs.\n" ); return 0; } + if ( fTruth ) + { + if ( Gia_ManCiNum(pAbc->pGia) > 20 ) + { + Abc_Print( -1, "Abc_CommandAbc9ReadSim(): More than 20 inputs.\n" ); + return 1; + } + Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); + pAbc->pGia->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(pAbc->pGia) ); + Vec_WrdFreeP( &pAbc->pGia->vSimsPo ); + pAbc->pGia->vSimsPo = Gia_ManSimPatSimOut( pAbc->pGia, pAbc->pGia->vSimsPi, 1 ); + return 0; + } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) @@ -33813,9 +33975,10 @@ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &sim_read [-W num] [-ovh] \n" ); + Abc_Print( -2, "usage: &sim_read [-W num] [-tovh] \n" ); Abc_Print( -2, "\t reads simulation patterns from file\n" ); Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", nWords ); + Abc_Print( -2, "\t-t : toggle creating exhaustive simulation info [default = %s]\n", fTruth? "yes": "no" ); Abc_Print( -2, "\t-o : toggle reading output information [default = %s]\n", fOutputs? "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"); @@ -33836,17 +33999,23 @@ usage: ***********************************************************************/ int Abc_CommandAbc9WriteSim( Abc_Frame_t * pAbc, int argc, char ** argv ) { - int c, fOutputs = 0, fVerbose = 0; + int c, fOutputs = 0, fTrans = 0, fBool = 0, fVerbose = 0; char ** pArgvNew; int nArgcNew; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ovh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "otbvh" ) ) != EOF ) { switch ( c ) { case 'o': fOutputs ^= 1; break; + case 't': + fTrans ^= 1; + break; + case 'b': + fBool ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -33880,20 +34049,64 @@ int Abc_CommandAbc9WriteSim( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( fOutputs ) { + Vec_Wrd_t * vTemp; + int nWords = Vec_WrdSize(pAbc->pGia->vSimsPo) / Gia_ManCoNum(pAbc->pGia); assert( Vec_WrdSize(pAbc->pGia->vSimsPo) % Gia_ManCoNum(pAbc->pGia) == 0 ); - Vec_WrdDumpHex( pArgvNew[0], pAbc->pGia->vSimsPo, Vec_WrdSize(pAbc->pGia->vSimsPo) / Gia_ManCoNum(pAbc->pGia), 1 ); + if ( fTrans ) + { + int nSize = Vec_WrdSize(pAbc->pGia->vSimsPo); + Vec_WrdFillExtra( pAbc->pGia->vSimsPo, nWords * 64 * ((Gia_ManCoNum(pAbc->pGia) + 63)/64), 0 ); + vTemp = Vec_WrdStart( Vec_WrdSize(pAbc->pGia->vSimsPo) ); + Extra_BitMatrixTransposeP( pAbc->pGia->vSimsPo, nWords, vTemp, (Gia_ManCoNum(pAbc->pGia) + 63)/64 ); + if ( fBool ) + Vec_WrdDumpBool( pArgvNew[0], vTemp, (Gia_ManCoNum(pAbc->pGia) + 63)/64, Gia_ManCoNum(pAbc->pGia), 1, 1 ); + else + Vec_WrdDumpHex( pArgvNew[0], vTemp, (Gia_ManCoNum(pAbc->pGia) + 63)/64, 1 ); + Vec_WrdShrink( pAbc->pGia->vSimsPo, nSize ); + Vec_WrdFree( vTemp ); + } + else + { + if ( fBool ) + Vec_WrdDumpBool( pArgvNew[0], pAbc->pGia->vSimsPo, nWords, Gia_ManCoNum(pAbc->pGia), 1, 1 ); + else + Vec_WrdDumpHex( pArgvNew[0], pAbc->pGia->vSimsPo, nWords, 1 ); + } } else { + Vec_Wrd_t * vTemp; + int nWords = Vec_WrdSize(pAbc->pGia->vSimsPi) / Gia_ManCiNum(pAbc->pGia); assert( Vec_WrdSize(pAbc->pGia->vSimsPi) % Gia_ManCiNum(pAbc->pGia) == 0 ); - Vec_WrdDumpHex( pArgvNew[0], pAbc->pGia->vSimsPi, Vec_WrdSize(pAbc->pGia->vSimsPi) / Gia_ManCiNum(pAbc->pGia), 1 ); + if ( fTrans ) + { + int nSize = Vec_WrdSize(pAbc->pGia->vSimsPi); + Vec_WrdFillExtra( pAbc->pGia->vSimsPi, nWords * 64 * ((Gia_ManCiNum(pAbc->pGia) + 63)/64), 0 ); + vTemp = Vec_WrdStart( Vec_WrdSize(pAbc->pGia->vSimsPi) ); + Extra_BitMatrixTransposeP( pAbc->pGia->vSimsPi, nWords, vTemp, (Gia_ManCiNum(pAbc->pGia) + 63)/64 ); + if ( fBool ) + Vec_WrdDumpBool( pArgvNew[0], vTemp, (Gia_ManCiNum(pAbc->pGia) + 63)/64, Gia_ManCiNum(pAbc->pGia), 1, 1 ); + else + Vec_WrdDumpHex( pArgvNew[0], vTemp, (Gia_ManCiNum(pAbc->pGia) + 63)/64, 1 ); + Vec_WrdShrink( pAbc->pGia->vSimsPi, nSize ); + Vec_WrdFree( vTemp ); + } + else + { + if ( fBool ) + Vec_WrdDumpBool( pArgvNew[0], pAbc->pGia->vSimsPi, nWords, Gia_ManCiNum(pAbc->pGia), 1, 1 ); + else + Vec_WrdDumpHex( pArgvNew[0], pAbc->pGia->vSimsPi, nWords, 1 ); + } } return 0; usage: - Abc_Print( -2, "usage: &sim_write [-vh] \n" ); + Abc_Print( -2, "usage: &sim_write [-otbvh] \n" ); Abc_Print( -2, "\t writes simulation patterns into a file\n" ); Abc_Print( -2, "\t-o : toggle writing output information [default = %s]\n", fOutputs? "yes": "no" ); + Abc_Print( -2, "\t-t : toggle transposing the simulation information [default = %s]\n", fTrans? "yes": "no" ); + Abc_Print( -2, "\t-b : toggle dumping in boolean vs hexadecimal notation [default = %s]\n", fBool? "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"); Abc_Print( -2, "\t : file to store the simulation info\n"); @@ -36299,6 +36512,7 @@ usage: int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManPairWiseMiter( Gia_Man_t * p ); + extern Gia_Man_t * Gia_ManDupWithCare( Gia_Man_t * p, Gia_Man_t * pCare ); FILE * pFile; Gia_Man_t * pAux; Gia_Man_t * pSecond; @@ -36314,9 +36528,10 @@ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) int fTransX = 0; int fConvert = 0; int fTransZ = 0; + int fWithCare= 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Idsptxyzvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Idsptxyzcvh" ) ) != EOF ) { switch ( c ) { @@ -36352,6 +36567,9 @@ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'z': fTransZ ^= 1; break; + case 'c': + fWithCare ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -36439,13 +36657,16 @@ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } // compute the miter - pAux = Gia_ManMiter( pAbc->pGia, pSecond, nInsDup, fDualOut, fSeq, 0, fVerbose ); + if ( fWithCare ) + pAux = Gia_ManDupWithCare( pAbc->pGia, pSecond ); + else + pAux = Gia_ManMiter( pAbc->pGia, pSecond, nInsDup, fDualOut, fSeq, 0, fVerbose ); Gia_ManStop( pSecond ); Abc_FrameUpdateGia( pAbc, pAux ); return 0; usage: - Abc_Print( -2, "usage: &miter [-I num] [-dsptxyzvh] \n" ); + Abc_Print( -2, "usage: &miter [-I num] [-dsptxyzcvh] \n" ); Abc_Print( -2, "\t creates miter of two designs (current AIG vs. )\n" ); Abc_Print( -2, "\t-I num : the number of last PIs to replicate [default = %d]\n", nInsDup ); Abc_Print( -2, "\t-d : toggle creating dual-output miter [default = %s]\n", fDualOut? "yes": "no" ); @@ -36454,7 +36675,8 @@ usage: Abc_Print( -2, "\t-t : toggle XORing POs of dual-output miter [default = %s]\n", fTrans? "yes": "no" ); Abc_Print( -2, "\t-x : toggle XORing POs of two-word miter [default = %s]\n", fTransX? "yes": "no" ); Abc_Print( -2, "\t-y : toggle convering two-word miter into dual-output miter [default = %s]\n", fConvert? "yes": "no" ); - Abc_Print( -2, "\t-z : toggle odering sides of the dual-output miter [default = %s]\n", fTransZ? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle ordering sides of the dual-output miter [default = %s]\n", fTransZ? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle duplicating AIG with the care set [default = %s]\n", fWithCare? "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"); Abc_Print( -2, "\t : AIGER file with the design to miter\n"); @@ -36830,14 +37052,15 @@ usage: ***********************************************************************/ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern Gia_Man_t * Cec_ManScorrCorrespondence( Gia_Man_t * p, Cec_ParCor_t * pPars ); extern Gia_Man_t * Gia_ManScorrDivideTest( Gia_Man_t * p, Cec_ParCor_t * pPars ); Cec_ParCor_t Pars, * pPars = &Pars; Gia_Man_t * pTemp; int fPartition = 0; - int c; + int fUseOld = 0, c; Cec_ManCorSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FCPXpkrecqwvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "FCPXpkrecqowvh" ) ) != EOF ) { switch ( c ) { @@ -36903,6 +37126,9 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'q': pPars->fStopWhenGone ^= 1; break; + case 'o': + fUseOld ^= 1; + break; case 'w': pPars->fVerboseFlops ^= 1; break; @@ -36934,7 +37160,9 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 0, "The network is combinational.\n" ); return 0; } - if ( fPartition ) + if ( fUseOld ) + pTemp = Cec_ManScorrCorrespondence( pAbc->pGia, pPars ); + else if ( fPartition ) pTemp = Gia_ManScorrDivideTest( pAbc->pGia, pPars ); else pTemp = Cec_ManLSCorrespondence( pAbc->pGia, pPars ); @@ -36942,7 +37170,7 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &scorr [-FCPX num] [-pkrecqwvh]\n" ); + Abc_Print( -2, "usage: &scorr [-FCPX num] [-pkrecqowvh]\n" ); Abc_Print( -2, "\t performs signal correpondence computation\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-F num : the number of timeframes in inductive case [default = %d]\n", pPars->nFrames ); @@ -36954,6 +37182,7 @@ usage: Abc_Print( -2, "\t-e : toggle using equivalences as choices [default = %s]\n", pPars->fMakeChoices? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using circuit-based SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" ); Abc_Print( -2, "\t-q : toggle quitting when PO is not a constant candidate [default = %s]\n", pPars->fStopWhenGone? "yes": "no" ); + Abc_Print( -2, "\t-o : toggle calling old engine [default = %s]\n", fUseOld? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing verbose info about equivalent flops [default = %s]\n", pPars->fVerboseFlops? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -37275,12 +37504,13 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); extern void Cec4_ManSimulateTest5( Gia_Man_t * p, int nConfs, int fVerbose ); extern Gia_Man_t * Cec5_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars, int fCbs, int approxLim, int subBatchSz, int adaRecycle ); + extern Gia_Man_t * Gia_ManIvyFraig( Gia_Man_t * p, int nConfLimit, int fUseProve, int fVerbose ); Cec_ParFra_t ParsFra, * pPars = &ParsFra; Gia_Man_t * pTemp; - int c, fUseAlgo = 0, fUseAlgoG = 0, fUseAlgoX = 0, fUseAlgoY = 0, fUseSave = 0; - int fCbs = 1, approxLim = 600, subBatchSz = 1, adaRecycle = 500; + int c, fUseAlgo = 0, fUseAlgoG = 0, fUseAlgoX = 0, fUseAlgoY = 0, fUseSave = 0, fUseIvy = 0, fUseProve = 0; + int fCbs = 1, approxLim = 600, subBatchSz = 1, adaRecycle = 500, nMaxNodes = 0; Cec4_ManSetParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "JWRILDCNPrmdckngxyswvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "JWRILDCNPMrmdckngxysopwvh" ) ) != EOF ) { switch ( c ) { @@ -37383,6 +37613,17 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nGenIters < 0 ) goto usage; break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMaxNodes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxNodes < 0 ) + goto usage; + break; case 'r': pPars->fRewriting ^= 1; break; @@ -37413,6 +37654,12 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) case 's': fUseSave ^= 1; break; + case 'o': + fUseIvy ^= 1; + break; + case 'p': + fUseProve ^= 1; + break; case 'w': pPars->fVeryVerbose ^= 1; break; @@ -37433,6 +37680,8 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) Cec4_ManSimulateTest5( pAbc->pGia, pPars->nBTLimit, pPars->fVerbose ); return 0; } + else if ( fUseIvy && (!nMaxNodes || Gia_ManAndNum(pAbc->pGia) < nMaxNodes) ) + pTemp = Gia_ManIvyFraig( pAbc->pGia, pPars->nBTLimit, fUseProve, pPars->fVerbose ); else if ( fUseAlgo ) pTemp = Cec2_ManSimulateTest( pAbc->pGia, pPars ); else if ( fUseAlgoG ) @@ -37453,7 +37702,7 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &fraig [-JWRILDCNP ] [-rmdckngxyswvh]\n" ); + Abc_Print( -2, "usage: &fraig [-JWRILDCNPM ] [-rmdckngxysopwvh]\n" ); Abc_Print( -2, "\t performs combinational SAT sweeping\n" ); Abc_Print( -2, "\t-J num : the solver type [default = %d]\n", pPars->jType ); Abc_Print( -2, "\t-W num : the number of simulation words [default = %d]\n", pPars->nWords ); @@ -37464,6 +37713,7 @@ usage: Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-N num : the min number of calls to recycle the solver [default = %d]\n", pPars->nCallsRecycle ); Abc_Print( -2, "\t-P num : the number of pattern generation iterations [default = %d]\n", pPars->nGenIters ); + Abc_Print( -2, "\t-M num : the node count limit to call the old sweeper [default = %d]\n", nMaxNodes ); Abc_Print( -2, "\t-r : toggle the use of AIG rewriting [default = %s]\n", pPars->fRewriting? "yes": "no" ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); Abc_Print( -2, "\t-d : toggle using double output miters [default = %s]\n", pPars->fDualOut? "yes": "no" ); @@ -37474,6 +37724,8 @@ usage: Abc_Print( -2, "\t-x : toggle using another new implementation [default = %s]\n", fUseAlgoX? "yes": "no" ); Abc_Print( -2, "\t-y : toggle using another new implementation [default = %s]\n", fUseAlgoY? "yes": "no" ); Abc_Print( -2, "\t-s : toggle dumping equivalences into a file [default = %s]\n", fUseSave? "yes": "no" ); + Abc_Print( -2, "\t-o : toggle using the old SAT sweeper [default = %s]\n", fUseIvy? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle trying to prove when running the old SAT sweeper [default = %s]\n", fUseProve? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing even more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -40317,11 +40569,11 @@ usage: ***********************************************************************/ int Abc_CommandAbc9Sif( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Gia_ManTestSif( Gia_Man_t * p, int nLutSize, int fVerbose ); + extern Gia_Man_t * Gia_ManSifPerform( Gia_Man_t * p, int nLutSize, int fEvalOnly, int fVerbose ); Gia_Man_t * pNew; - int c, nLutSize = 6, fVerbose = 0; + int c, nLutSize = 6, fEvalOnly = 0, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Kevh" ) ) != EOF ) { switch ( c ) { @@ -40339,6 +40591,9 @@ int Abc_CommandAbc9Sif( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } break; + case 'e': + fEvalOnly ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -40352,15 +40607,16 @@ int Abc_CommandAbc9Sif( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Empty GIA network.\n" ); return 1; } - pNew = Gia_ManTestSif( pAbc->pGia, nLutSize, fVerbose ); + pNew = Gia_ManSifPerform( pAbc->pGia, nLutSize, fEvalOnly, fVerbose ); if ( pNew != NULL ) Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: - Abc_Print( -2, "usage: &sif [-K num] [-vh]\n" ); + Abc_Print( -2, "usage: &sif [-K num] [-evh]\n" ); Abc_Print( -2, "\t performs technology mapping\n" ); Abc_Print( -2, "\t-K num : sets the LUT size for the mapping [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-e : toggles the evaluation mode [default = %s]\n", fEvalOnly? "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; @@ -42342,6 +42598,328 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Transduction( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Gia_Man_t * pTemp, * pExdc = NULL; + int c, nType = 1, fMspf = 0, nRandom = 0, nSortType = 0, nPiShuffle = 0, nParameter = 0, fLevel = 0, fTruth = 0, fNewLine = 0, nVerbose = 2; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "TSIPRVtmnlh" ) ) != EOF ) + { + switch ( c ) + { + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" ); + goto usage; + } + nType = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by a positive integer.\n" ); + goto usage; + } + nRandom = 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; + } + nSortType = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nPiShuffle = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by a positive integer.\n" ); + goto usage; + } + nParameter = 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 't': + fTruth ^= 1; + break; + case 'm': + fMspf ^= 1; + break; + case 'n': + fNewLine ^= 1; + break; + case 'l': + fLevel ^= 1; + 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 ( argc == globalUtilOptind + 1 ) + { + FILE * pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", argv[globalUtilOptind] ); + return 1; + } + fclose( pFile ); + pExdc = Gia_AigerRead( argv[globalUtilOptind], 0, 0, 0 ); + if ( pExdc == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 1; + } + } + + if ( fLevel && (nType == 3 || nType == 8) ) + { + Abc_Print( -1, "Level preserving optimization does not work with transduction type 3 and 8.\n" ); + return 1; + } + + if ( fTruth ) + pTemp = Gia_ManTransductionTt( pAbc->pGia, nType, fMspf, nRandom, nSortType, nPiShuffle, nParameter, fLevel, pExdc, fNewLine, nVerbose ); + else + pTemp = Gia_ManTransductionBdd( pAbc->pGia, nType, fMspf, nRandom, nSortType, nPiShuffle, nParameter, fLevel, pExdc, fNewLine, nVerbose ); + if ( pExdc != NULL ) + Gia_ManStop( pExdc ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &transduction [-TSIPRV num] [-bmlh] \n" ); + Abc_Print( -2, "\t performs transduction-based AIG optimization\n" ); + Abc_Print( -2, "\t-T num : transduction type [default = %d]\n", nType ); + Abc_Print( -2, "\t 0: remove simply redundant nodes\n" ); + Abc_Print( -2, "\t 1: Resub\n" ); + Abc_Print( -2, "\t 2: ResubMono\n" ); + Abc_Print( -2, "\t 3: ResubShared\n" ); + Abc_Print( -2, "\t 4: repeat Resub\n" ); + Abc_Print( -2, "\t 5: repeat ResubMono\n" ); + Abc_Print( -2, "\t 6: script RepeatInner\n" ); + Abc_Print( -2, "\t 7: script RepeatOuter\n" ); + Abc_Print( -2, "\t 8: script RepeatAll\n" ); + Abc_Print( -2, "\t-S num : fanin sort type [default = %d]\n", nSortType ); + Abc_Print( -2, "\t 0: topological order\n" ); + Abc_Print( -2, "\t 1: number of ones\n" ); + Abc_Print( -2, "\t 2: number of ones before complemented edges\n" ); + Abc_Print( -2, "\t 3: pseudo random\n" ); + Abc_Print( -2, "\t 4: no sorting\n" ); + Abc_Print( -2, "\t-I num : random seed to shuffle PIs (0 = no shuffle) [default = %d]\n", nPiShuffle ); + Abc_Print( -2, "\t-P num : parameters for scripts [default = %d]\n", nParameter ); + Abc_Print( -2, "\t-R num : random seed to set all parameters (0 = no random) ([default = %d]\n", nRandom ); + Abc_Print( -2, "\t-V num : verbosity level [default = %d]\n", nVerbose ); + Abc_Print( -2, "\t-t : toggles using truth table instead of BDD [default = %s]\n", fTruth? "yes": "no" ); + Abc_Print( -2, "\t-m : toggles using MSPF instead of CSPF [default = %s]\n", fMspf? "yes": "no" ); + Abc_Print( -2, "\t-n : toggles printing with a new line [default = %s]\n", fNewLine? "yes": "no" ); + Abc_Print( -2, "\t-l : toggles level preserving optimization [default = %s]\n", fLevel? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n" ); + Abc_Print( -2, "\t : AIGER specifying external don't-cares\n" ); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Yukio Miyasaka.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9TranStoch( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManTranStoch( Gia_Man_t * pGia, int nRestarts, int nHops, int nSeedBase, int fMspf, int fMerge, int fResetHop, int fZeroCostHop, int fRefactor, int fTruth, int fSingle, int fOriginalOnly, int fNewLine, Gia_Man_t * pExdc, int nThreads, int nVerbose ); + Gia_Man_t * pTemp, * pExdc = NULL; + int c, nRestarts = 0, nHops = 10, nSeedBase = 0, fMspf = 1, fMerge = 1, fResetHop = 1, fZeroCostHop = 0, fRefactor = 0, fTruth = 0, fSingle = 0, fOriginalOnly = 0, fNewLine = 0, nThreads = 1, nVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NMRPVmgrzftsonh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); + goto usage; + } + nRestarts = 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; + } + nHops = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by a positive integer.\n" ); + goto usage; + } + nSeedBase = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by a positive integer.\n" ); + goto usage; + } + nThreads = 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 'm': + fMspf ^= 1; + break; + case 'g': + fMerge ^= 1; + break; + case 'r': + fResetHop ^= 1; + break; + case 'z': + fZeroCostHop ^= 1; + break; + case 'f': + fRefactor ^= 1; + break; + case 't': + fTruth ^= 1; + break; + case 's': + fSingle ^= 1; + break; + case 'o': + fOriginalOnly ^= 1; + break; + case 'n': + fNewLine ^= 1; + 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 ( argc == globalUtilOptind + 1 ) + { + FILE * pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", argv[globalUtilOptind] ); + return 1; + } + fclose( pFile ); + pExdc = Gia_AigerRead( argv[globalUtilOptind], 0, 0, 0 ); + if ( pExdc == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 1; + } + } + + pTemp = Gia_ManTranStoch( pAbc->pGia, nRestarts, nHops, nSeedBase, fMspf, fMerge, fResetHop, fZeroCostHop, fRefactor, fTruth, fSingle, fOriginalOnly, fNewLine, pExdc, nThreads, nVerbose ); + if ( pExdc != NULL ) + Gia_ManStop( pExdc ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &transtoch [-NMRPV num] [-mgrzftsonh] \n" ); + Abc_Print( -2, "\t iterates transduction with randomized parameters\n" ); + Abc_Print( -2, "\t-N num : number of restarts [default = %d]\n", nRestarts ); + Abc_Print( -2, "\t-M num : number of hops (if; mfs2; strash) [default = %d]\n", nHops ); + Abc_Print( -2, "\t-R num : random seed [default = %d]\n", nSeedBase ); + Abc_Print( -2, "\t-P num : number of threads [default = %d]\n", nThreads ); + Abc_Print( -2, "\t-V num : verbosity level [default = %d]\n", nVerbose); + Abc_Print( -2, "\t-m : toggles using MSPF instead of CSPF [default = %s]\n", fMspf? "yes": "no" ); + Abc_Print( -2, "\t-g : toggles using ResubShared [default = %s]\n", fMerge? "yes": "no" ); + Abc_Print( -2, "\t-r : toggles resetting hop count when new minimum is found [default = %s]\n", fResetHop? "yes": "no" ); + Abc_Print( -2, "\t-z : toggles using \"drf -z\" instead of \"if;mfs2;st\" for hop [default = %s]\n", fZeroCostHop? "yes": "no" ); + Abc_Print( -2, "\t-f : toggles using \"drf -z\" instead of \"&dc2\" for ite [default = %s]\n", fRefactor? "yes": "no" ); + Abc_Print( -2, "\t-t : toggles using truth table instead of BDD [default = %s]\n", fTruth? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles starting from the smallest starting point [default = %s]\n", fSingle? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles starting from the given AIG [default = %s]\n", fOriginalOnly? "yes": "no" ); + Abc_Print( -2, "\t-n : toggles printing with a new line [default = %s]\n", fNewLine? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n" ); + Abc_Print( -2, "\t : AIGER specifying external don't-cares\n" ); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Yukio Miyasaka.\n" ); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -42801,7 +43379,7 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Dch_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfremgcxvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfremgcxyvh" ) ) != EOF ) { switch ( c ) { @@ -42868,6 +43446,9 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'x': pPars->fUseNew ^= 1; break; + case 'y': + pPars->fUseNew2 ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -42907,7 +43488,7 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &dch [-WCS num] [-sptfremgcxvh]\n" ); + Abc_Print( -2, "usage: &dch [-WCS num] [-sptfremgcxyvh]\n" ); Abc_Print( -2, "\t computes structural choices using a new approach\n" ); Abc_Print( -2, "\t-W num : the max number of simulation words [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); @@ -42922,6 +43503,7 @@ usage: Abc_Print( -2, "\t-g : toggle using GIA to prove equivalences [default = %s]\n", pPars->fUseGia? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using circuit-based SAT vs. MiniSat [default = %s]\n", pPars->fUseCSat? "yes": "no" ); Abc_Print( -2, "\t-x : toggle using new choice computation [default = %s]\n", pPars->fUseNew? "yes": "no" ); + Abc_Print( -2, "\t-y : toggle using new choice computation [default = %s]\n", pPars->fUseNew2? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -44625,8 +45207,8 @@ int Abc_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fExtractAll ) { char Buffer[1000]; - Gia_Obj_t * pObj; - int i, nDigits = Abc_Base10Log(Gia_ManPoNum(pAbc->pGia)); + Gia_Obj_t * pObj; int i; + unsigned char nDigits = (unsigned char)Abc_Base10Log(Gia_ManPoNum(pAbc->pGia)); Gia_ManForEachPo( pAbc->pGia, pObj, i ) { Gia_Man_t * pOne = Gia_ManDupDfsCone( pAbc->pGia, pObj ); @@ -46214,6 +46796,7 @@ usage: int Abc_CommandAbc9Qbf( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_QbfDumpFile( Gia_Man_t * pGia, int nPars ); + extern void Gia_QbfDumpFileInv( Gia_Man_t * pGia, int nPars ); extern int Gia_QbfSolve( Gia_Man_t * pGia, int nPars, int nIterLimit, int nConfLimit, int nTimeOut, int nEncVars, int fGlucose, int fVerbose ); int c, nPars = -1; int nIterLimit = 0; @@ -46221,10 +46804,11 @@ int Abc_CommandAbc9Qbf( Abc_Frame_t * pAbc, int argc, char ** argv ) int nTimeOut = 0; int nEncVars = 0; int fDumpCnf = 0; + int fDumpCnf2 = 0; int fGlucose = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PICTKdgvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PICTKdegvh" ) ) != EOF ) { switch ( c ) { @@ -46286,6 +46870,9 @@ int Abc_CommandAbc9Qbf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'd': fDumpCnf ^= 1; break; + case 'e': + fDumpCnf2 ^= 1; + break; case 'g': fGlucose ^= 1; break; @@ -46320,19 +46907,22 @@ int Abc_CommandAbc9Qbf( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( fDumpCnf ) Gia_QbfDumpFile( pAbc->pGia, nPars ); + else if ( fDumpCnf2 ) + Gia_QbfDumpFileInv( pAbc->pGia, nPars ); else Gia_QbfSolve( pAbc->pGia, nPars, nIterLimit, nConfLimit, nTimeOut, nEncVars, fGlucose, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: &qbf [-PICTK num] [-dgvh]\n" ); + Abc_Print( -2, "usage: &qbf [-PICTK num] [-degvh]\n" ); Abc_Print( -2, "\t solves QBF problem EpVxM(p,x)\n" ); Abc_Print( -2, "\t-P num : number of parameters p (should be the first PIs) [default = %d]\n", nPars ); Abc_Print( -2, "\t-I num : quit after the given iteration even if unsolved [default = %d]\n", nIterLimit ); Abc_Print( -2, "\t-C num : conflict limit per problem [default = %d]\n", nConfLimit ); Abc_Print( -2, "\t-T num : global timeout [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-K num : the number of input bits (for encoding miters only) [default = %d]\n", nEncVars ); - Abc_Print( -2, "\t-d : toggle dumping QDIMACS file instead of solving [default = %s]\n", fDumpCnf? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle dumping QDIMACS file instead of solving (complemented QBF) [default = %s]\n", fDumpCnf? "yes": "no" ); + Abc_Print( -2, "\t-e : toggle dumping QDIMACS file instead of solving (original QBF) [default = %s]\n", fDumpCnf2? "yes": "no" ); Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n", fGlucose? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -50343,6 +50933,94 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9ProdAdd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int nArgA = 4; + int nArgB = 4; + int Seed = 0; + int fSigned = 0; + int fCla = 0; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ABSscvh" ) ) != EOF ) + { + switch ( c ) + { + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); + goto usage; + } + nArgA = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nArgA < 0 ) + goto usage; + break; + case 'B': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + nArgB = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nArgB < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Seed < 0 ) + goto usage; + break; + case 's': + fSigned ^= 1; + break; + case 'c': + fCla ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + Gia_ManProdAdderGen( nArgA, nArgB, Seed, fSigned, fCla ); + return 0; + +usage: + Abc_Print( -2, "usage: &prodadd [-ABSscvh]\n" ); + Abc_Print( -2, "\t generates partial products and adder trees\n" ); + Abc_Print( -2, "\t-A num : the bit-width of the first arg [default = %d]\n", nArgA ); + Abc_Print( -2, "\t-B num : the bit-width of the second arg [default = %d]\n", nArgB ); + Abc_Print( -2, "\t-S num : random seed used the node ordering [default = %d]\n", Seed ); + Abc_Print( -2, "\t-s : toggle using signed operation [default = %s]\n", fSigned? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle using CLA in the adder tree [default = %s]\n", fCla? "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; +} + /**Function************************************************************* @@ -50430,8 +51108,7 @@ int Abc_CommandAbc9Test( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_ManStop( pTemp ); return 0; } - //Abc_FrameUpdateGia( pAbc, Gia_ManPerformNewResub(pAbc->pGia, 100, 6, 1, 1) ); - Gia_ManPrintArray( pAbc->pGia ); + Abc_FrameUpdateGia( pAbc, Gia_ManPerformNewResub(pAbc->pGia, 100, 6, 1, 1) ); // printf( "AIG in \"%s\" has the sum of output support sizes equal to %d.\n", pAbc->pGia->pSpec, Gia_ManSumTotalOfSupportSizes(pAbc->pGia) ); return 0; usage: diff --git a/src/base/abci/abcIvy.c b/src/base/abci/abcIvy.c index c680f85a7..ac526a90d 100644 --- a/src/base/abci/abcIvy.c +++ b/src/base/abci/abcIvy.c @@ -25,6 +25,7 @@ #include "proof/fraig/fraig.h" #include "map/mio/mio.h" #include "aig/aig/aig.h" +#include "aig/gia/gia.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" @@ -556,7 +557,7 @@ int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ) pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); - Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 1, 16, 0, 0, 0, 0 ); //printf( "After rwsat = %d. ", Abc_NtkNodeNum(pNtk) ); //ABC_PRT( "Time", Abc_Clock() - clk ); } @@ -1141,6 +1142,105 @@ Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs ) return vArray; } +/**Function************************************************************* + + Synopsis [Convert Ivy into Gia.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_Obj_t * Gia_ObjChild0Copy3( Ivy_Obj_t ** ppNodes, Gia_Obj_t * pObj, int Id ) { return Ivy_NotCond( ppNodes[Gia_ObjFaninId0(pObj, Id)], Gia_ObjFaninC0(pObj) ); } +static inline Ivy_Obj_t * Gia_ObjChild1Copy3( Ivy_Obj_t ** ppNodes, Gia_Obj_t * pObj, int Id ) { return Ivy_NotCond( ppNodes[Gia_ObjFaninId1(pObj, Id)], Gia_ObjFaninC1(pObj) ); } + +Ivy_Man_t * Gia_ManToIvySimple( Gia_Man_t * p ) +{ + Ivy_Man_t * pNew; + Gia_Obj_t * pObj; int i; + Ivy_Obj_t ** ppNodes = ABC_FALLOC( Ivy_Obj_t *, Gia_ManObjNum(p) ); + // create the new manager + pNew = Ivy_ManStart(); + // create the PIs + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + ppNodes[i] = Ivy_And( pNew, Gia_ObjChild0Copy3(ppNodes, pObj, i), Gia_ObjChild1Copy3(ppNodes, pObj, i) ); + else if ( Gia_ObjIsCi(pObj) ) + ppNodes[i] = Ivy_ObjCreatePi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + ppNodes[i] = Ivy_ObjCreatePo( pNew, Gia_ObjChild0Copy3(ppNodes, pObj, Gia_ObjId(p, pObj)) ); + else if ( Gia_ObjIsConst0(pObj) ) + ppNodes[i] = Ivy_Not(Ivy_ManConst1(pNew)); + else + assert( 0 ); + assert( i == 0 || Ivy_ObjId(ppNodes[i]) == i ); + } + ABC_FREE( ppNodes ); + return pNew; +} +static inline int Gia_ObjChild0Copy4( int * pNodes, Ivy_Obj_t * pObj ) { return Abc_LitNotCond( pNodes[Ivy_Regular(pObj->pFanin0)->Id], Ivy_IsComplement(pObj->pFanin0) ); } +static inline int Gia_ObjChild1Copy4( int * pNodes, Ivy_Obj_t * pObj ) { return Abc_LitNotCond( pNodes[Ivy_Regular(pObj->pFanin1)->Id], Ivy_IsComplement(pObj->pFanin1) ); } + +Gia_Man_t * Gia_ManFromIvySimple( Ivy_Man_t * p ) +{ + Gia_Man_t * pNew; + Ivy_Obj_t * pObj; + int i, * pNodes = ABC_FALLOC( int, Ivy_ManObjIdMax(p) + 1 ); + pNew = Gia_ManStart( Ivy_ManObjIdMax(p) ); + pNew->pName = Abc_UtilStrsav( "from_ivy" ); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( Ivy_ObjIsAnd(pObj) ) + pNodes[pObj->Id] = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy4(pNodes, pObj), Gia_ObjChild1Copy4(pNodes, pObj) ); + else if ( Ivy_ObjIsCi(pObj) ) + pNodes[pObj->Id] = Gia_ManAppendCi( pNew ); + else if ( Ivy_ObjIsCo(pObj) ) + pNodes[pObj->Id] = Gia_ManAppendCo( pNew, Gia_ObjChild0Copy4(pNodes, pObj) ); + else if ( Ivy_ObjIsConst1(pObj) ) + pNodes[pObj->Id] = 1; + else + assert( 0 ); + } + ABC_FREE( pNodes ); + return pNew; +} +Gia_Man_t * Gia_ManIvyFraig( Gia_Man_t * p, int nConfLimit, int fUseProve, int fVerbose ) +{ + Ivy_FraigParams_t Params, * pParams = &Params; + Gia_Man_t * pNew; + Ivy_Man_t * pMan, * pTemp; + pMan = Gia_ManToIvySimple( p ); + if ( pMan == NULL ) + return NULL; + Ivy_FraigParamsDefault( pParams ); + pParams->nBTLimitNode = nConfLimit; + pParams->fVerbose = fVerbose; + pParams->fProve = fUseProve; + pParams->fDoSparse = 1; + pMan = Ivy_FraigPerform( pTemp = pMan, pParams ); + pNew = Gia_ManFromIvySimple( pMan ); + if ( pMan->pData ) + { + p->pCexSeq = Abc_CexDeriveFromCombModel( (int *)pMan->pData, Ivy_ManPiNum(pMan), 0, -1 ); + p->pCexSeq->iPo = Gia_ManFindFailedPoCex( p, p->pCexSeq, 0 ); + ABC_FREE( pMan->pData ); + } + Ivy_ManStop( pTemp ); + Ivy_ManStop( pMan ); + return pNew; +} +Gia_Man_t * Gia_ManIvyFraigTest( Gia_Man_t * p, int nConfLimit, int fVerbose ) +{ + Ivy_Man_t * pMan = Gia_ManToIvySimple( p ); + Gia_Man_t * pNew = Gia_ManFromIvySimple( pMan ); + Ivy_ManStop( pMan ); + return pNew; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abcMfs.c b/src/base/abci/abcMfs.c index d91bda66f..0533d189f 100644 --- a/src/base/abci/abcMfs.c +++ b/src/base/abci/abcMfs.c @@ -100,6 +100,8 @@ Vec_Int_t * Abc_NtkAssignStarts( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, int * pnT Vec_IntWriteEntry( vStarts, pObj->iTemp, Counter ); Counter += Abc_Truth6WordNum( Abc_ObjFaninNum(pObj) ); } + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_IntWriteEntry( vStarts, pObj->iTemp, Counter++ ); *pnTotal = Counter; return vStarts; } @@ -167,6 +169,8 @@ Sfm_Ntk_t * Abc_NtkExtractMfs( Abc_Ntk_t * pNtk, int nFirstFixed ) if ( Abc_ObjFaninNum(pObj) <= 6 ) { word uTruth = Abc_SopToTruth((char *)pObj->pData, Abc_ObjFaninNum(pObj)); + int Offset = Vec_IntEntry( vStarts, pObj->iTemp ); + Vec_WrdWriteEntry( vTruths2, Offset, uTruth ); Vec_WrdWriteEntry( vTruths, pObj->iTemp, uTruth ); if ( uTruth == 0 || ~uTruth == 0 ) continue; @@ -177,6 +181,7 @@ Sfm_Ntk_t * Abc_NtkExtractMfs( Abc_Ntk_t * pNtk, int nFirstFixed ) int Offset = Vec_IntEntry( vStarts, pObj->iTemp ); word * pRes = Vec_WrdEntryP( vTruths2, Offset ); Abc_SopToTruthBig( (char *)pObj->pData, Abc_ObjFaninNum(pObj), pTruths, pCube, pRes ); + Vec_WrdWriteEntry( vTruths, pObj->iTemp, pRes[0] ); // check const0 for ( k = 0; k < nWords; k++ ) if ( pRes[k] ) @@ -324,11 +329,13 @@ void Abc_NtkInsertMfs( Abc_Ntk_t * pNtk, Sfm_Ntk_t * p ) } // update fanins vArray = Sfm_NodeReadFanins( p, pNode->iTemp ); - Vec_IntForEachEntry( vArray, Fanin, k ) - Abc_ObjAddFanin( pNode, Abc_NtkObj(pNtk, Vec_IntEntry(vMap, Fanin)) ); pTruth = Sfm_NodeReadTruth( p, pNode->iTemp ); pNode->pData = Abc_SopCreateFromTruthIsop( (Mem_Flex_t *)pNtk->pManFunc, Vec_IntSize(vArray), pTruth, vCover ); + if ( Abc_SopGetVarNum((char *)pNode->pData) == 0 ) + continue; assert( Abc_SopGetVarNum((char *)pNode->pData) == Vec_IntSize(vArray) ); + Vec_IntForEachEntry( vArray, Fanin, k ) + Abc_ObjAddFanin( pNode, Abc_NtkObj(pNtk, Vec_IntEntry(vMap, Fanin)) ); } Vec_IntFree( vCover ); Vec_IntFree( vMap ); diff --git a/src/base/abci/abcOdc.c b/src/base/abci/abcOdc.c index b66592f68..23915b1e8 100644 --- a/src/base/abci/abcOdc.c +++ b/src/base/abci/abcOdc.c @@ -44,12 +44,13 @@ struct Odc_Obj_t_ struct Odc_Man_t_ { - // dont'-care parameters + // don't-care parameters int nVarsMax; // the max number of cut variables int nLevels; // the number of ODC levels int fVerbose; // the verbosiness flag int fVeryVerbose;// the verbosiness flag to print per-node stats int nPercCutoff; // cutoff percentage + int skipQuant; // windowing Abc_Obj_t * pNode; // the node for windowing @@ -177,6 +178,7 @@ Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int f p->fVerbose = fVerbose; p->fVeryVerbose = fVeryVerbose; p->nPercCutoff = 10; + p->skipQuant = 0; // windowing p->vRoots = Vec_PtrAlloc( 128 ); @@ -744,7 +746,10 @@ unsigned Abc_NtkDontCareCofactors_rec( Odc_Man_t * p, Odc_Lit_t Lit, unsigned uM // skip visited objects pObj = Odc_Lit2Obj( p, Lit ); if ( Odc_ObjIsTravIdCurrent(p, pObj) ) + { + p->skipQuant = 1; return pObj->uData; + } Odc_ObjSetTravIdCurrent(p, pObj); // skip objects out of the cone if ( (pObj->uMask & uMask) == 0 ) @@ -764,6 +769,7 @@ unsigned Abc_NtkDontCareCofactors_rec( Odc_Man_t * p, Odc_Lit_t Lit, unsigned uM uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Odc_ObjFaninC1(pObj) ); uRes1 = Odc_And( p, uLit0, uLit1 ); // find the result + p->skipQuant = 0; return pObj->uData = ((uRes1 << 16) | uRes0); } @@ -783,6 +789,7 @@ int Abc_NtkDontCareQuantify( Odc_Man_t * p ) Odc_Lit_t uRes0, uRes1; unsigned uData; int i; + p->skipQuant = 0; assert( p->iRoot < 0xffff ); assert( Vec_PtrSize(p->vBranches) <= 32 ); // the mask size for ( i = 0; i < Vec_PtrSize(p->vBranches); i++ ) @@ -790,6 +797,8 @@ int Abc_NtkDontCareQuantify( Odc_Man_t * p ) // compute the cofactors w.r.t. this variable Odc_ManIncrementTravId( p ); uData = Abc_NtkDontCareCofactors_rec( p, Odc_Regular(p->iRoot), (1 << i) ); + if ( p->skipQuant ) + continue; uRes0 = Odc_NotCond( (Odc_Lit_t)(uData & 0xffff), Odc_IsComplement(p->iRoot) ); uRes1 = Odc_NotCond( (Odc_Lit_t)(uData >> 16), Odc_IsComplement(p->iRoot) ); // quantify this variable existentially diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index 44d5c2c3b..8a2cd42e2 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -46,7 +46,7 @@ ABC_NAMESPACE_IMPL_START abctime s_MappingTime = 0; int s_MappingMem = 0; -abctime s_ResubTime = 0; +//abctime s_ResubTime = 0; abctime s_ResynTime = 0; //////////////////////////////////////////////////////////////////////// @@ -1069,26 +1069,6 @@ void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk ) Abc_NodeMffcConeSuppPrint( pNode ); } -/**Function************************************************************* - - Synopsis [Prints the factored form of one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ) -{ - Abc_Obj_t * pNode; - int i; - assert( Abc_NtkIsSopLogic(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - Abc_NodePrintFactor( pFile, pNode, fUseRealNames ); -} - /**Function************************************************************* Synopsis [Prints the factored form of one node.] @@ -1128,8 +1108,86 @@ void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ) Dec_GraphPrint( stdout, pGraph, (char **)NULL, Abc_ObjName(pNode) ); Dec_GraphFree( pGraph ); } +void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsSopLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + Abc_NodePrintFactor( pFile, pNode, fUseRealNames ); +} +/**Function************************************************************* + Synopsis [Prints the SOPs of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodePrintSop( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ) +{ + Vec_Ptr_t * vNamesIn = NULL; + char * pCube, * pCur, * pSop; int nVars; + if ( Abc_ObjIsCo(pNode) ) + pNode = Abc_ObjFanin0(pNode); + if ( Abc_ObjIsPi(pNode) ) + { + fprintf( pFile, "Skipping the PI node.\n" ); + return; + } + if ( Abc_ObjIsLatch(pNode) ) + { + fprintf( pFile, "Skipping the latch.\n" ); + return; + } + assert( Abc_ObjIsNode(pNode) ); + pSop = (char *)pNode->pData; + nVars = Abc_SopGetVarNum( pSop ); + if ( nVars == 0 ) + { + fprintf( pFile, "%s = ", Abc_ObjName(pNode) ); + fprintf( pFile, "Constant %d", Abc_SopGetPhase(pSop) ); + return; + } + if ( !Abc_SopGetPhase(pSop) ) + fprintf( pFile, "!" ); + fprintf( pFile, "%s = ", Abc_ObjName(pNode) ); + if ( fUseRealNames ) + vNamesIn = Abc_NodeGetFaninNames(pNode); + Abc_SopForEachCube( pSop, nVars, pCube ) + { + if ( pCube != pSop ) + fprintf( pFile, " +" ); + if ( vNamesIn ) + { + for ( pCur = pCube; *pCur != ' '; pCur++ ) + if ( *pCur != '-' ) + fprintf( pFile, " %s%s", *pCur == '0' ? "!" : "", (char *)Vec_PtrEntry(vNamesIn, pCur-pCube) ); + } + else + { + for ( pCur = pCube; *pCur != ' '; pCur++ ) + if ( *pCur != '-' ) + fprintf( pFile, " %s%c", *pCur == '0' ? "!" : "", (char)('a' + pCur-pCube) ); + } + } + fprintf( pFile, "\n" ); + if ( vNamesIn ) + Abc_NodeFreeNames( vNamesIn ); +} +void Abc_NtkPrintSop( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsSopLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + Abc_NodePrintSop( pFile, pNode, fUseRealNames ); +} + /**Function************************************************************* Synopsis [Prints the level stats of the PO node.] diff --git a/src/base/abci/abcProve.c b/src/base/abci/abcProve.c index b14c08273..c95b66863 100644 --- a/src/base/abci/abcProve.c +++ b/src/base/abci/abcProve.c @@ -34,7 +34,7 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); +extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nMinSaved, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); static Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, ABC_INT64_T nInspLimit, int * pRetValue, int * pNumFails, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects ); @@ -151,7 +151,7 @@ int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars ) break; if ( --Counter == 0 ) break; - Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 1, 16, 0, 0, 0, 0 ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) @@ -340,7 +340,7 @@ Abc_Ntk_t * Abc_NtkMiterRwsat( Abc_Ntk_t * pNtk ) Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); - Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 1, 16, 0, 0, 0, 0 ); return pNtk; } diff --git a/src/base/abci/abcQuant.c b/src/base/abci/abcQuant.c index 02f7b8384..76bd7906b 100644 --- a/src/base/abci/abcQuant.c +++ b/src/base/abci/abcQuant.c @@ -51,14 +51,14 @@ void Abc_NtkSynthesize( Abc_Ntk_t ** ppNtk, int fMoreEffort ) pNtk = *ppNtk; Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); - Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 1, 16, 0, 0, 0, 0 ); pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); if ( fMoreEffort ) { Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); - Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 1, 16, 0, 0, 0, 0 ); pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); @@ -340,7 +340,7 @@ Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtkRel, int nIters, int fVerbose ) // compute the network composed of the initial states pNtkFront = Abc_NtkInitialState( pNtkRel ); pNtkReached = Abc_NtkDup( pNtkFront ); -//Abc_NtkShow( pNtkReached, 0, 0, 0 ); +//Abc_NtkShow( pNtkReached, 0, 0, 0, 0 ); // if ( fVerbose ) // printf( "Transition relation = %6d.\n", Abc_NtkNodeNum(pNtkRel) ); diff --git a/src/base/abci/abcRefactor.c b/src/base/abci/abcRefactor.c index 8ec5944fa..ec6756aa1 100644 --- a/src/base/abci/abcRefactor.c +++ b/src/base/abci/abcRefactor.c @@ -149,7 +149,7 @@ int Abc_NodeConeIsConst1( word * pTruth, int nVars ) SeeAlso [] ***********************************************************************/ -Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ) +Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, int nMinSaved, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ) { extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); int fVeryVerbose = 0; @@ -205,7 +205,8 @@ clk = Abc_Clock(); nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Required ); p->timeEval += Abc_Clock() - clk; // quit if there is no improvement - if ( nNodesAdded == -1 || (nNodesAdded == nNodesSaved && !fUseZeros) ) + //if ( nNodesAdded == -1 || (nNodesAdded == nNodesSaved && !fUseZeros) ) + if ( nNodesAdded == -1 || nNodesSaved - nNodesAdded < nMinSaved ) { Dec_GraphFree( pFForm ); return NULL; @@ -323,7 +324,7 @@ void Abc_NtkManRefPrintStats( Abc_ManRef_t * p ) SeeAlso [] ***********************************************************************/ -int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ) +int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nMinSaved, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ) { extern int Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); ProgressBar * pProgress; @@ -371,7 +372,7 @@ clk = Abc_Clock(); pManRef->timeCut += Abc_Clock() - clk; // evaluate this cut clk = Abc_Clock(); - pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ); + pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, nMinSaved, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ); pManRef->timeRes += Abc_Clock() - clk; if ( pFForm == NULL ) continue; diff --git a/src/base/abci/abcResub.c b/src/base/abci/abcResub.c index dc1b60368..85f8a4b4c 100644 --- a/src/base/abci/abcResub.c +++ b/src/base/abci/abcResub.c @@ -117,7 +117,7 @@ static Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required ); static Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax ); static int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ); -extern abctime s_ResubTime; +//extern abctime s_ResubTime; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -134,7 +134,7 @@ extern abctime s_ResubTime; SeeAlso [] ***********************************************************************/ -int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose ) +int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nMinSaved, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose ) { extern int Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); ProgressBar * pProgress; @@ -214,6 +214,11 @@ clk = Abc_Clock(); pManRes->timeRes += Abc_Clock() - clk; if ( pFForm == NULL ) continue; + if ( pManRes->nLastGain < nMinSaved ) + { + Dec_GraphFree( pFForm ); + continue; + } pManRes->nTotalGain += pManRes->nLastGain; /* if ( pManRes->nLeaves == 4 && pManRes->nMffc == 2 && pManRes->nLastGain == 1 ) @@ -266,7 +271,7 @@ pManRes->timeTotal = Abc_Clock() - clkStart; printf( "Abc_NtkRefactor: The network check has failed.\n" ); return 0; } -s_ResubTime = Abc_Clock() - clkStart; +//s_ResubTime = Abc_Clock() - clkStart; return 1; } diff --git a/src/base/abci/abcSat.c b/src/base/abci/abcSat.c index f0ed15320..85ada2648 100644 --- a/src/base/abci/abcSat.c +++ b/src/base/abci/abcSat.c @@ -22,6 +22,8 @@ #include "base/main/main.h" #include "base/cmd/cmd.h" #include "sat/bsat/satSolver.h" +#include "aig/gia/gia.h" +#include "aig/gia/giaAig.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" @@ -143,6 +145,36 @@ sat_solver_store_free( pSat ); return RetValue; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Abc_NtkSolveGiaMiter( Gia_Man_t * p ) +{ + extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); + int RetValue = 0; + int * pResult = NULL; + Abc_Ntk_t * pNtk; + Aig_Man_t * pMan; + pMan = Gia_ManToAig( p, 0 ); + pNtk = Abc_NtkFromAigPhase( pMan ); + pNtk->pName = Extra_UtilStrsav(p->pName); + Aig_ManStop( pMan ); + RetValue = Abc_NtkMiterSat( pNtk, 1000000, 0, 0, NULL, NULL ); + if ( RetValue == 0 ) // sat + pResult = pNtk->pModel, pNtk->pModel = NULL; + Abc_NtkDelete( pNtk ); + return pResult; +} + + /**Function************************************************************* Synopsis [Returns the array of CI IDs.] diff --git a/src/base/abci/abcSaucy.c b/src/base/abci/abcSaucy.c index e4d1cc42c..faf870bf3 100644 --- a/src/base/abci/abcSaucy.c +++ b/src/base/abci/abcSaucy.c @@ -2650,7 +2650,8 @@ saucy_alloc(Abc_Ntk_t * pNtk) if (s->ninduce && s->sinduce && s->left.cfront && s->left.clen && s->right.cfront && s->right.clen && s->stuff && s->bucket && s->count && s->ccount - && s->clist && s->nextnon-1 && s->prevnon + //&& s->clist && s->nextnon-1 && s->prevnon + && s->clist && s->nextnon[-1] && s->prevnon && s->start && s->gamma && s->theta && s->left.unlab && s->right.lab && s->right.unlab && s->left.lab && s->splitvar && s->splitwho && s->junk diff --git a/src/base/abci/abcScorr.c b/src/base/abci/abcScorr.c index f224a0fd4..e228f37d2 100644 --- a/src/base/abci/abcScorr.c +++ b/src/base/abci/abcScorr.c @@ -444,6 +444,36 @@ Abc_Ntk_t * Abc_NtkTestScorr( char * pFileNameIn, char * pFileNameOut, int nStep return pResult; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Cec_ManScorrCorrespondence( Gia_Man_t * p, Cec_ParCor_t * pCorPars ) +{ + Gia_Man_t * pRes = NULL; + Aig_Man_t * pOld, * pNew; + Ssw_Pars_t SswPars, * pSswPars = &SswPars; + Ssw_ManSetDefaultParams( pSswPars ); + pSswPars->nBTLimit = pCorPars->nBTLimit; + pSswPars->nFramesK = pCorPars->nFrames; + pSswPars->fLatchCorr = pCorPars->fLatchCorr; + pSswPars->fVerbose = pCorPars->fVerbose; + pOld = Gia_ManToAigSimple( p ); + pNew = Ssw_SignalCorrespondence( pOld, pSswPars ); + pRes = Gia_ManFromAigSimple( pNew ); + Gia_ManReprFromAigRepr( pOld, p ); + Aig_ManStop( pOld ); + Aig_ManStop( pNew ); + return pRes; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/cmd/cmdLoad.c b/src/base/cmd/cmdLoad.c index bd511feca..1cf4d3ff9 100644 --- a/src/base/cmd/cmdLoad.c +++ b/src/base/cmd/cmdLoad.c @@ -58,8 +58,8 @@ int CmdCommandLoad( Abc_Frame_t * pAbc, int argc, char ** argv ) // check if there is the binary if ( (pFile = fopen( Vec_StrArray(vCommand), "r" )) == NULL ) { - Vec_StrFree( vCommand ); Abc_Print( -1, "Cannot run the binary \"%s\".\n\n", Vec_StrArray(vCommand) ); + Vec_StrFree( vCommand ); return 1; } fclose( pFile ); @@ -74,9 +74,9 @@ int CmdCommandLoad( Abc_Frame_t * pAbc, int argc, char ** argv ) // run the command line if ( Util_SignalSystem( Vec_StrArray(vCommand) ) ) { - Vec_StrFree( vCommand ); Abc_Print( -1, "The following command has returned non-zero exit status:\n" ); Abc_Print( -1, "\"%s\"\n", Vec_StrArray(vCommand) ); + Vec_StrFree( vCommand ); return 1; } Vec_StrFree( vCommand ); diff --git a/src/base/io/io.c b/src/base/io/io.c index 46f2641ff..569b63349 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -66,6 +66,7 @@ static int IoCommandWriteAigerCex( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBaf ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBblif ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteEdgelist( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBench ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBook ( Abc_Frame_t * pAbc, int argc, char **argv ); @@ -147,6 +148,7 @@ void Io_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "I/O", "&write_cnf", IoCommandWriteCnf2, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_dot", IoCommandWriteDot, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_eqn", IoCommandWriteEqn, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_edgelist",IoCommandWriteEdgelist, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_gml", IoCommandWriteGml, 0 ); // Cmd_CommandAdd( pAbc, "I/O", "write_list", IoCommandWriteList, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_pla", IoCommandWritePla, 0 ); @@ -3169,6 +3171,69 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteEdgelist( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c, fSpecial = 0; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + fSpecial ^= 1; + break; + /* + case 'a': + fUseHie ^= 1; + break; + case 'h': + goto usage; + */ + default: + goto usage; + } + } + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + if ( fSpecial ) // keep original naming + Io_WriteEdgelist( pAbc->pNtkCur, pFileName, 1, 0, 0, fSpecial); //last option is fName + else + Io_WriteEdgelist( pAbc->pNtkCur, pFileName, 1, 0, 0, fSpecial); //last option is fName + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_edgelist [-N] \n" ); + fprintf( pAbc->Err, "\t writes the network into edgelist file\n" ); + fprintf( pAbc->Err, "\t part of Verilog-2-PyG (PyTorch Geometric). more details https://github.com/ycunxi/Verilog-to-PyG \n" ); + fprintf( pAbc->Err, "\t-N : toggle keeping original naming of the netlist in edgelist (default=False)\n"); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .el)\n" ); + return 1; +} + + + /**Function************************************************************* Synopsis [] diff --git a/src/base/io/ioAbc.h b/src/base/io/ioAbc.h index 4f82efac1..9758f1963 100644 --- a/src/base/io/ioAbc.h +++ b/src/base/io/ioAbc.h @@ -125,6 +125,8 @@ extern void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, extern void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); /*=== abcWriteEqn.c ===========================================================*/ extern void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteEdgelist.c ===========================================================*/ +extern void Io_WriteEdgelist( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches, int fBb2Wb, int fSeq , int fName); /*=== abcWriteGml.c ===========================================================*/ extern void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ); /*=== abcWriteList.c ==========================================================*/ diff --git a/src/base/io/ioReadPla.c b/src/base/io/ioReadPla.c index bbce0864c..a8e5fd701 100644 --- a/src/base/io/ioReadPla.c +++ b/src/base/io/ioReadPla.c @@ -370,10 +370,11 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros, int fBoth, in Abc_Ntk_t * pNtk; Abc_Obj_t * pTermPi, * pTermPo, * pNode; Vec_Str_t ** ppSops = NULL; - char Buffer[100]; + char Buffer[1000]; int nInputs = -1, nOutputs = -1, nProducts = -1; char * pCubeIn, * pCubeOut; - int i, k, iLine, nDigits, nCubes; + int i, k, iLine, nCubes; + unsigned char nDigits; // allocate the empty network pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); @@ -445,7 +446,7 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros, int fBoth, in ABC_FREE( ppSops ); return NULL; } - nDigits = Abc_Base10Log( nInputs ); + nDigits = (unsigned char)Abc_Base10Log( nInputs ); for ( i = 0; i < nInputs; i++ ) { sprintf( Buffer, "x%0*d", nDigits, i ); @@ -462,7 +463,7 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros, int fBoth, in ABC_FREE( ppSops ); return NULL; } - nDigits = Abc_Base10Log( nOutputs ); + nDigits = (unsigned char)Abc_Base10Log( nOutputs ); for ( i = 0; i < nOutputs; i++ ) { sprintf( Buffer, "z%0*d", nDigits, i ); diff --git a/src/base/io/ioWriteEdgelist.c b/src/base/io/ioWriteEdgelist.c new file mode 100644 index 000000000..64397882e --- /dev/null +++ b/src/base/io/ioWriteEdgelist.c @@ -0,0 +1,1252 @@ +/**CFile**************************************************************** + + FileName [ioWriteEdgelist.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write Edgelist files for graph learning.] + + Author [Cunxi Yu] + + Affiliation [University of Utah] + + Date [Ver. 1.0 04/15/2023.] + + Revision [$Id: more details at https://github.com/ycunxi/Verilog-to-PyG $] + +***********************************************************************/ + +#include "ioAbc.h" +#include "base/main/main.h" +#include "map/mio/mio.h" +#include "bool/kit/kit.h" +#include "map/if/if.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_NtkEdgelistWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq , int fName); +static void Io_NtkEdgelistWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq , int fName); +static void Io_NtkEdgelistWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkEdgelistWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkEdgelistWriteSubckt( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkEdgelistWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkEdgelistWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode, int fName); +static int Io_NtkEdgelistWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length, int fName); +static void Io_NtkEdgelistWriteLatch( FILE * pFile, Abc_Obj_t * pLatch , int fName); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the network into a Edgelist file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteEdgelist( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches, int fBb2Wb, int fSeq, int fName) +{ + FILE * pFile; int i; + // start writing the file + pFile = fopen( FileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteEdgelist(): Cannot open the output file.\n" ); + return; + } + fprintf( stdout, "WriteEdgelist (Verilog-to-PyG @ https://github.com/ycunxi/Verilog-to-PyG) starts writing to %s.\n", FileName ); + fprintf( pFile, "# Benchmark Edgelist Dumping (beta) \"%s\" written by ABC on %s (more at https://github.com/ycunxi/Verilog-to-PyG)\n", pNtk->pName, Extra_TimeStamp() ); + // write the master network + Io_NtkEdgelistWrite( pFile, pNtk, fWriteLatches, fBb2Wb, fSeq , fName); + // make sure there is no logic hierarchy +// assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + // write the hierarchy if present + if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 ) + { + Abc_Ntk_t * pNtkTemp; + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pNtkTemp, i ) + { + if ( pNtkTemp == pNtk ) + continue; + fprintf( pFile, "\n\n" ); + Io_NtkEdgelistWrite( pFile, pNtkTemp, fWriteLatches, fBb2Wb, fSeq, fName); + } + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a Edgelist file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkEdgelistWrite_int( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq , int fName) +{ + Abc_Ntk_t * pExdc; + assert( Abc_NtkIsNetlist(pNtk) ); + // write the model name + // fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); + // write the network + Io_NtkEdgelistWriteOne( pFile, pNtk, fWriteLatches, fBb2Wb, fSeq , fName); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + { + fprintf( pFile, "\n" ); + fprintf( pFile, ".exdc\n" ); + Io_NtkEdgelistWriteOne( pFile, pExdc, fWriteLatches, fBb2Wb, fSeq , fName); + } + // finalize the file + //fprintf( pFile, ".end\n" ); +} +void Io_NtkEdgelistWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq , int fName) +{ + if( Abc_NtkIsNetlist(pNtk) ) + Io_NtkEdgelistWrite_int( pFile, pNtk, fWriteLatches, fBb2Wb, fSeq , fName ); + else + { + Abc_Ntk_t * pNtkTemp = Abc_NtkToNetlist(pNtk); + Io_NtkEdgelistWrite_int( pFile, pNtkTemp, fWriteLatches, fBb2Wb, fSeq , fName ); + Abc_NtkDelete( pNtkTemp ); + } +} +/**Function************************************************************* + + Synopsis [Write one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkEdgelistWriteConvertedBox( FILE * pFile, Abc_Ntk_t * pNtk, int fSeq ) +{ + Abc_Obj_t * pObj; + int i, v; + if ( fSeq ) + { + fprintf( pFile, ".attrib white box seq\n" ); + } + else + { + fprintf( pFile, ".attrib white box comb\n" ); + fprintf( pFile, ".delay 1\n" ); + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + // write the .names line + //fprintf( pFile, ".names" ); + Io_NtkEdgelistWritePis( pFile, pNtk, 1 ); + if ( fSeq ) + fprintf( pFile, " %s_in\n", Abc_ObjName(Abc_ObjFanin0(pObj)) ); + else + fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanin0(pObj)) ); + for ( v = 0; v < Abc_NtkPiNum(pNtk); v++ ) + fprintf( pFile, "1" ); + fprintf( pFile, " 1\n" ); + if ( fSeq ) + fprintf( pFile, " %s_in %s 1\n", Abc_ObjName(Abc_ObjFanin0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) ); + //fprintf( pFile, ".latch %s_in %s 1\n", Abc_ObjName(Abc_ObjFanin0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) ); + } +} + +/**Function************************************************************* + + Synopsis [Transforms truth table into an SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Io_NtkWriteEdgelistDeriveSop( Mem_Flex_t * pMem, word uTruth, int nVars, Vec_Int_t * vCover ) +{ + char * pSop; + int RetValue = Kit_TruthIsop( (unsigned *)&uTruth, nVars, vCover, 1 ); + assert( RetValue == 0 || RetValue == 1 ); + // check the case of constant cover + if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) ) + { + char * pStr0 = " 0\n", * pStr1 = " 1\n"; + assert( RetValue == 0 ); + return Vec_IntSize(vCover) == 0 ? pStr0 : pStr1; + } + // derive the AIG for that tree + pSop = Abc_SopCreateFromIsop( pMem, nVars, vCover ); + if ( RetValue ) + Abc_SopComplement( pSop ); + return pSop; +} + + +/**Function************************************************************* + + Synopsis [Write one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkEdgelistWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq , int fName) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pLatch; + int i, Length; + // write the PIs + Io_NtkEdgelistWritePis( pFile, pNtk, fWriteLatches ); + // write the blackbox + if ( Abc_NtkHasBlackbox( pNtk ) ) + { + if ( fBb2Wb ) + Io_NtkEdgelistWriteConvertedBox( pFile, pNtk, fSeq ); + else + fprintf( pFile, ".blackbox\n" ); + return; + } + + // write the timing info + Io_WriteTimingInfo( pFile, pNtk ); + + // write the latches + if ( fWriteLatches && !Abc_NtkIsComb(pNtk) ) + { + //fprintf( pFile, "\n" ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Io_NtkEdgelistWriteLatch( pFile, pLatch , fName); + //fprintf( pFile, "\n" ); + } + + // write the subcircuits +// assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachBlackbox( pNtk, pNode, i ) + Io_NtkEdgelistWriteSubckt( pFile, pNode ); + fprintf( pFile, "\n" ); + Abc_NtkForEachWhitebox( pNtk, pNode, i ) + Io_NtkEdgelistWriteSubckt( pFile, pNode ); + fprintf( pFile, "\n" ); + } + + // write each internal node + Length = Abc_NtkHasMapping(pNtk)? Mio_LibraryReadGateNameMax((Mio_Library_t *)pNtk->pManFunc) : 0; + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( Io_NtkEdgelistWriteNode( pFile, pNode, Length, fName) ) // skip the next node + i++; + } + // write the POs + Io_NtkEdgelistWritePos( pFile, pNtk, fWriteLatches ); + + Extra_ProgressBarStop( pProgress ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkEdgelistWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 7; + NameCounter = 0; + + if ( fWriteLatches ) + { + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + // fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, "%d %d Pi 00\n", Abc_ObjId(pTerm), Abc_ObjId(pNet) ); + //fprintf( pFile, "%s %s Pi 00\n", Abc_ObjName(pTerm), Abc_ObjName(pNet) ); + //fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } + else + { + Abc_NtkForEachCi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + // fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, "%d %d Pi 00\n", Abc_ObjId(pTerm), Abc_ObjId(pNet) ); + //fprintf( pFile, "%s %s Pi\n", Abc_ObjName(pTerm), Abc_ObjName(pNet) ); + //fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkEdgelistWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + if ( fWriteLatches ) + { + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + //fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, "%d %d Po 00\n",Abc_ObjId(pNet), Abc_ObjId(pTerm) ); + //fprintf( pFile, "%s %s Po 00\n", Abc_ObjName(pTerm), Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } + else + { + Abc_NtkForEachCo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + // fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + //fprintf( pFile, " %s", Abc_ObjName(pNet) ); + fprintf( pFile, "%d %d Po 00\n",Abc_ObjId(pNet), Abc_ObjId(pTerm) ); + //fprintf( pFile, "%s %s Po 00\n", Abc_ObjName(pTerm), Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkEdgelistWriteSubckt( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pModel = (Abc_Ntk_t *)pNode->pData; + Abc_Obj_t * pTerm; + int i; + // write the subcircuit +// fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) ); + fprintf( pFile, ".subckt %s", Abc_NtkName(pModel) ); + // write pairs of the formal=actual names + Abc_NtkForEachPi( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + pTerm = Abc_ObjFanin( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + } + Abc_NtkForEachPo( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + pTerm = Abc_ObjFanout( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + } + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkEdgelistWriteLatch( FILE * pFile, Abc_Obj_t * pLatch , int fName) +{ + Abc_Obj_t * pNetLi, * pNetLo; + int Reset; + pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); + pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); + Reset = (int)(ABC_PTRUINT_T)Abc_ObjData( pLatch ); + // write the latch line + // fprintf( pFile, ".latch" ); + if (fName){ + fprintf( pFile, "%s", Abc_ObjName(pNetLi) ); + fprintf( pFile, " %s", Abc_ObjName(pNetLo) ); + } + else{ + fprintf( pFile, "%d", Abc_ObjId(pNetLi) ); + fprintf( pFile, " %d", Abc_ObjId(pNetLo) ); + } + + fprintf( pFile, " REG %d\n", Reset-1 ); + //fprintf( pFile, " {type:\"REG\" reset=\"%d\"}\n", Reset-1 ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkEdgelistWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode , int fName) +{ + Abc_Obj_t * pNet; + int LineLength; + int AddedLength; + int NameCounter; + char * pName; + int i; + + LineLength = 6; + NameCounter = 0; + Abc_ObjForEachFanin( pNode, pNet, i ) + { + char * temp = NULL; + int len; + // get the fanin name + pName = Abc_ObjName(pNet); + // get the line length after the fanin name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + if (fName){ + fprintf( pFile, "%s", Abc_ObjName(pNet) ); + } + else{ + fprintf( pFile, "%d", Abc_ObjId(pNet) ); + } + LineLength += AddedLength; + NameCounter++; + + // get the output name + pName = Abc_ObjName(Abc_ObjFanout0(pNode)); + // get the line length after the output name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength > 75 ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + //char temp[sizeof((char*)Abc_ObjData(pNode))]; + //strcpy(temp, (char*)Abc_ObjData(pNode)); + temp = Abc_UtilStrsav((char*)Abc_ObjData(pNode)); + len = strlen(temp); + if (len > 0) { + temp[len - 1] = '\0'; + temp[len - 2] = '\0'; + temp[len - 3] = '\0'; + } + if (fName){ + if (Abc_ObjIsCi(pNode)) + fprintf( pFile, " %s Pi AIG %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)), temp); + else if (Abc_ObjIsCo(Abc_ObjFanout0(pNode))) + fprintf( pFile, " %s AIG Po %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)), temp); + else + fprintf( pFile, " %s AIG %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)), temp); + + } + else{ + if (Abc_ObjIsCi(pNode)) + fprintf( pFile, " %d Pi AIG %s\n", Abc_ObjId(Abc_ObjFanout0(pNode)), temp); + else if (Abc_ObjIsCo(Abc_ObjFanout0(pNode))) + fprintf( pFile, " %d AIG Po %s\n", Abc_ObjId(Abc_ObjFanout0(pNode)), temp); + else + fprintf( pFile, " %d AIG %s\n", Abc_ObjId(Abc_ObjFanout0(pNode)), temp); + + + } + + //fprintf( pFile, " %d {type:\"AIG\" cube:\"%s\"}\n", Abc_ObjId(Abc_ObjFanout0(pNode)), temp); + + ABC_FREE( temp ); + } + + /* + // get the output name + pName = Abc_ObjName(Abc_ObjFanout0(pNode)); + // get the line length after the output name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength > 75 ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); + */ +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkEdgelistWriteSubcktFanins( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNet; + int LineLength; + int AddedLength; + int NameCounter; + char * pName; + int i; + + LineLength = 6; + NameCounter = 0; + + // get the output name + pName = Abc_ObjName(Abc_ObjFanout0(pNode)); + // get the line length after the output name is written + AddedLength = strlen(pName) + 1; + fprintf( pFile, " m%d", Abc_ObjId(pNode) ); + + // get the input names + Abc_ObjForEachFanin( pNode, pNet, i ) + { + // get the fanin name + pName = Abc_ObjName(pNet); + // get the line length after the fanin name is written + AddedLength = strlen(pName) + 3; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %c=%s", 'a'+i, pName ); + LineLength += AddedLength; + NameCounter++; + } + + // get the output name + pName = Abc_ObjName(Abc_ObjFanout0(pNode)); + // get the line length after the output name is written + AddedLength = strlen(pName) + 3; + if ( NameCounter && LineLength + AddedLength > 75 ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %c=%s", 'o', pName ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_NtkEdgelistWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length, int fName) +{ + static int fReport = 0; + Mio_Gate_t * pGate = (Mio_Gate_t *)pNode->pData; + Mio_Pin_t * pGatePin; + Abc_Obj_t * pNode2; + int i; + for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ){ + if (fName) + fprintf( pFile, "%s ", Abc_ObjName( Abc_ObjFanin(pNode,i) ) ); + else + fprintf( pFile, "%d ", Abc_ObjId( Abc_ObjFanin(pNode,i) ) ); + } + //fprintf( pFile, "%s=%s ", Mio_PinReadName(pGatePin), Abc_ObjName( Abc_ObjFanin(pNode,i) ) ); + assert ( i == Abc_ObjFaninNum(pNode) ); + if (fName) + fprintf( pFile, "%s", Abc_ObjName( Abc_ObjFanout0(pNode) ) ); + else + fprintf( pFile, "%d", Abc_ObjId( Abc_ObjFanout0(pNode) ) ); + + //fprintf( pFile, "%s=%s", Mio_GateReadOutName(pGate), Abc_ObjName( Abc_ObjFanout0(pNode) ) ); + if ( Mio_GateReadTwin(pGate) == NULL ){ + //print gate type + fprintf( pFile, " %s", Mio_GateReadName(pGate) ); + fprintf( pFile, " %lu", Mio_GateReadTruth(pGate) ); + //Vec_Int_t * Expr = Mio_GateReadExpr(pGate); + //Vec_IntPrint(Expr); + return 0; + } + pNode2 = Abc_NtkFetchTwinNode( pNode ); + if ( pNode2 == NULL ) + { + if ( !fReport ) + fReport = 1, printf( "Warning: Missing second output of gate(s) \"%s\".\n", Mio_GateReadName(pGate) ); + return 0; + } + fprintf( pFile, " %s", Abc_ObjName( Abc_ObjFanout0(pNode2) ) ); + //print gate type + fprintf( pFile, " %s", Mio_GateReadName(pGate)); + fprintf( pFile, " %lu", Mio_GateReadTruth(pGate) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_NtkEdgelistWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length, int fName) +{ + int RetValue = 0; + if ( Abc_NtkHasMapping(pNode->pNtk) ) + { + // write the .gate line + if ( Abc_ObjIsBarBuf(pNode) ) + { + printf("ERROR: not implemented\n"); + return 0; + fprintf( pFile, ".barbuf " ); + fprintf( pFile, "%s %s", Abc_ObjName(Abc_ObjFanin0(pNode)), Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, "\n" ); + } + else + { + //fprintf( pFile, ".gate" ); + RetValue = Io_NtkEdgelistWriteNodeGate( pFile, pNode, Length, fName); + fprintf( pFile, "\n" ); + } + } + else + { + // write the .names line + //fprintf( pFile, ".names" ); + Io_NtkEdgelistWriteNodeFanins( pFile, pNode, fName); + // write the cubes + // fprintf( pFile, " %s", (char*)Abc_ObjData(pNode) ); + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_NtkEdgelistWriteNodeSubckt( FILE * pFile, Abc_Obj_t * pNode, int Length ) +{ + int RetValue = 0; + fprintf( pFile, ".subckt" ); + Io_NtkEdgelistWriteSubcktFanins( pFile, pNode ); + fprintf( pFile, "\n" ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkEdgelistWriteNodeInt( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vCover ) +{ + Abc_Obj_t * pNet; + int i, nVars = Abc_ObjFaninNum(pNode); + if ( nVars > 7 ) + { + printf( "Node \"%s\" has more than 7 inputs. Writing Edgelist has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return; + } + + fprintf( pFile, "\n" ); + if ( nVars <= 4 ) + { + Abc_ObjForEachFanin( pNode, pNet, i ) + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + // get the output name + fprintf( pFile, " %s ", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + // write the cubes + fprintf( pFile, "%s\n", (char*)Abc_ObjData(pNode) ); + } + else + { + extern int If_Dec6PickBestMux( word t, word Cofs[2] ); + extern int If_Dec7PickBestMux( word t[2], word c0r[2], word c1r[2] ); + extern word If_Dec6MinimumBase( word uTruth, int * pSupp, int nVarsAll, int * pnVars ); + extern void If_Dec7MinimumBase( word uTruth[2], int * pSupp, int nVarsAll, int * pnVars ); + extern word If_Dec6Perform( word t, int fDerive ); + extern word If_Dec7Perform( word t[2], int fDerive ); + + char * pSop; + word z, uTruth6 = 0, uTruth7[2], Cofs6[2], Cofs7[2][2]; + int c, iVar, nVarsMin[2], pVars[2][10]; + + // collect variables + Abc_ObjForEachFanin( pNode, pNet, i ) + pVars[0][i] = pVars[1][i] = i; + + // derive truth table + if ( nVars == 7 ) + { + Abc_SopToTruth7( (char*)Abc_ObjData(pNode), nVars, uTruth7 ); + iVar = If_Dec7PickBestMux( uTruth7, Cofs7[0], Cofs7[1] ); + } + else + { + uTruth6 = Abc_SopToTruth( (char*)Abc_ObjData(pNode), nVars ); + iVar = If_Dec6PickBestMux( uTruth6, Cofs6 ); + } + + // perform MUX decomposition + if ( iVar >= 0 ) + { + if ( nVars == 7 ) + { + If_Dec7MinimumBase( Cofs7[0], pVars[0], nVars, &nVarsMin[0] ); + If_Dec7MinimumBase( Cofs7[1], pVars[1], nVars, &nVarsMin[1] ); + } + else + { + Cofs6[0] = If_Dec6MinimumBase( Cofs6[0], pVars[0], nVars, &nVarsMin[0] ); + Cofs6[1] = If_Dec6MinimumBase( Cofs6[1], pVars[1], nVars, &nVarsMin[1] ); + } + assert( nVarsMin[0] < 5 ); + assert( nVarsMin[1] < 5 ); + // write MUX + //fprintf( pFile, ".names" ); + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,iVar)) ); + fprintf( pFile, " %s_cascade0", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, " %s_cascade1", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, "1-1 1\n01- 1\n" ); + // write cofactors + for ( c = 0; c < 2; c++ ) + { + pSop = Io_NtkWriteEdgelistDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, + (word)(nVars == 7 ? Cofs7[c][0] : Cofs6[c]), nVarsMin[c], vCover ); + //fprintf( pFile, ".names" ); + for ( i = 0; i < nVarsMin[c]; i++ ) + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pVars[c][i])) ); + fprintf( pFile, " %s_cascade%d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), c ); + fprintf( pFile, "%s", pSop ); + } + return; + } + assert( nVars == 6 || nVars == 7 ); + + // try cascade decomposition + if ( nVars == 7 ) + { + z = If_Dec7Perform( uTruth7, 1 ); + //If_Dec7Verify( uTruth7, z ); + } + else + { + z = If_Dec6Perform( uTruth6, 1 ); + //If_Dec6Verify( uTruth6, z ); + } + if ( z == 0 ) + { + printf( "Node \"%s\" is not decomposable. Writing Edgelist has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return; + } + + // derive nodes + for ( c = 1; c >= 0; c-- ) + { + // collect fanins + uTruth7[c] = ((c ? z >> 32 : z) & 0xffff); + uTruth7[c] |= (uTruth7[c] << 16); + uTruth7[c] |= (uTruth7[c] << 32); + for ( i = 0; i < 4; i++ ) + pVars[c][i] = (z >> (c*32+16+4*i)) & 7; + + // minimize truth table + Cofs6[c] = If_Dec6MinimumBase( uTruth7[c], pVars[c], 4, &nVarsMin[c] ); + + // write the nodes + //fprintf( pFile, ".names" ); + for ( i = 0; i < nVarsMin[c]; i++ ) + if ( pVars[c][i] == 7 ) + fprintf( pFile, " %s_cascade", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + else + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pVars[c][i])) ); + fprintf( pFile, " %s%s\n", Abc_ObjName(Abc_ObjFanout0(pNode)), c? "" : "_cascade" ); + + // write SOP + pSop = Io_NtkWriteEdgelistDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, + (word)Cofs6[c], nVarsMin[c], vCover ); + fprintf( pFile, "%s", pSop ); + } + } +} + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkEdgelistWriteNodeIntStruct( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vCover, char * pStr ) +{ + Abc_Obj_t * pNet; + int nLeaves = Abc_ObjFaninNum(pNode); + int i, nLutLeaf, nLutLeaf2, nLutRoot, Length; + + // quit if parameters are wrong + Length = strlen(pStr); + if ( Length != 2 && Length != 3 ) + { + printf( "Wrong LUT struct (%s)\n", pStr ); + return; + } + for ( i = 0; i < Length; i++ ) + if ( pStr[i] - '0' < 3 || pStr[i] - '0' > 6 ) + { + printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", pStr[i] - '0' ); + return; + } + + nLutLeaf = pStr[0] - '0'; + nLutLeaf2 = ( Length == 3 ) ? pStr[1] - '0' : 0; + nLutRoot = pStr[Length-1] - '0'; + if ( nLeaves > nLutLeaf - 1 + (nLutLeaf2 ? nLutLeaf2 - 1 : 0) + nLutRoot ) + { + printf( "The node size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr ); + return; + } + + // consider easy case + fprintf( pFile, "\n" ); + if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) ) + { + // write the .names line + ////fprintf( pFile, ".names" ); + Abc_ObjForEachFanin( pNode, pNet, i ) + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + // get the output name + fprintf( pFile, " %s ", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + // write the cubes + fprintf( pFile, "%s\n", (char*)Abc_ObjData(pNode) ); + return; + } + else + { + extern int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars ); + + static word TruthStore[16][1<<10] = {{0}}, * pTruths[16]; + word pCube[1<<10], pRes[1<<10], Func0, Func1, Func2; + char pLut0[32], pLut1[32], pLut2[32] = {0}, * pSop; +// int nVarsMin[3], pVars[3][20]; + + if ( TruthStore[0][0] == 0 ) + { + static word Truth6[6] = { + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000) + }; + int nVarsMax = 16; + int nWordsMax = (1 << 10); + int i, k; + assert( nVarsMax <= 16 ); + for ( i = 0; i < nVarsMax; i++ ) + pTruths[i] = TruthStore[i]; + for ( i = 0; i < 6; i++ ) + for ( k = 0; k < nWordsMax; k++ ) + pTruths[i][k] = Truth6[i]; + for ( i = 6; i < nVarsMax; i++ ) + for ( k = 0; k < nWordsMax; k++ ) + pTruths[i][k] = ((k >> (i-6)) & 1) ? ~(word)0 : 0; + } + + // collect variables +// Abc_ObjForEachFanin( pNode, pNet, i ) +// pVars[0][i] = pVars[1][i] = pVars[2][i] = i; + + // derive truth table + Abc_SopToTruthBig( (char*)Abc_ObjData(pNode), nLeaves, pTruths, pCube, pRes ); + if ( Kit_TruthIsConst0((unsigned *)pRes, nLeaves) || Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ) + { + fprintf( pFile, "%s\n const%d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ); + return; + } + +// Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); +// Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + + // perform decomposition + if ( Length == 2 ) + { + if ( !If_CluCheckExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) ) + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return; + } + } + else + { + if ( !If_CluCheckExt3( NULL, pRes, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, pLut0, pLut1, pLut2, &Func0, &Func1, &Func2 ) ) + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return; + } + } + + // write leaf node + // //fprintf( pFile, ".names" ); + for ( i = 0; i < pLut1[0]; i++ ) + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pLut1[2+i])) ); + fprintf( pFile, " %s_lut1\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + // write SOP + pSop = Io_NtkWriteEdgelistDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func1, pLut1[0], vCover ); + fprintf( pFile, "%s", pSop ); + + if ( Length == 3 && pLut2[0] > 0 ) + { + // write leaf node + // //fprintf( pFile, ".names" ); + for ( i = 0; i < pLut2[0]; i++ ) + if ( pLut2[2+i] == nLeaves ) + fprintf( pFile, " %s_lut1", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + else + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pLut2[2+i])) ); + fprintf( pFile, " %s_lut2\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + // write SOP + pSop = Io_NtkWriteEdgelistDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func2, pLut2[0], vCover ); + fprintf( pFile, "%s", pSop ); + } + + // write root node + // //fprintf( pFile, ".names" ); + for ( i = 0; i < pLut0[0]; i++ ) + if ( pLut0[2+i] == nLeaves ) + fprintf( pFile, " %s_lut1", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + else if ( pLut0[2+i] == nLeaves+1 ) + fprintf( pFile, " %s_lut2", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + else + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pLut0[2+i])) ); + fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + // write SOP + pSop = Io_NtkWriteEdgelistDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func0, pLut0[0], vCover ); + fprintf( pFile, "%s", pSop ); + } +} + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkEdgelistWriteModelIntStruct( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vCover, char * pStr ) +{ + Abc_Obj_t * pNet; + int nLeaves = Abc_ObjFaninNum(pNode); + int i, nLutLeaf, nLutLeaf2, nLutRoot, Length; + + // write the header + /* + fprintf( pFile, "\n" ); + fprintf( pFile, ".model m%d\n", Abc_ObjName(pNode) ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) + fprintf( pFile, " %c", 'a' + i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".outputs o\n" ); + */ + // quit if parameters are wrong + Length = strlen(pStr); + if ( Length != 2 && Length != 3 ) + { + printf( "Wrong LUT struct (%s)\n", pStr ); + return; + } + for ( i = 0; i < Length; i++ ) + if ( pStr[i] - '0' < 3 || pStr[i] - '0' > 6 ) + { + printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", pStr[i] - '0' ); + return; + } + + nLutLeaf = pStr[0] - '0'; + nLutLeaf2 = ( Length == 3 ) ? pStr[1] - '0' : 0; + nLutRoot = pStr[Length-1] - '0'; + if ( nLeaves > nLutLeaf - 1 + (nLutLeaf2 ? nLutLeaf2 - 1 : 0) + nLutRoot ) + { + printf( "The node size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr ); + return; + } + + // consider easy case + if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) ) + { + // write the .names line + // //fprintf( pFile, ".names" ); + Abc_ObjForEachFanin( pNode, pNet, i ) + fprintf( pFile, "%c", 'a' + i ); + // get the output name + fprintf( pFile, " %s", "o" ); + // write the cubes + fprintf( pFile, " %s\n", (char*)Abc_ObjData(pNode) ); + //fprintf( pFile, ".end\n" ); + return; + } + else + { + extern int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars ); + + static word TruthStore[16][1<<10] = {{0}}, * pTruths[16]; + word pCube[1<<10], pRes[1<<10], Func0, Func1, Func2; + char pLut0[32], pLut1[32], pLut2[32] = {0}, * pSop; +// int nVarsMin[3], pVars[3][20]; + + if ( TruthStore[0][0] == 0 ) + { + static word Truth6[6] = { + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000) + }; + int nVarsMax = 16; + int nWordsMax = (1 << 10); + int i, k; + assert( nVarsMax <= 16 ); + for ( i = 0; i < nVarsMax; i++ ) + pTruths[i] = TruthStore[i]; + for ( i = 0; i < 6; i++ ) + for ( k = 0; k < nWordsMax; k++ ) + pTruths[i][k] = Truth6[i]; + for ( i = 6; i < nVarsMax; i++ ) + for ( k = 0; k < nWordsMax; k++ ) + pTruths[i][k] = ((k >> (i-6)) & 1) ? ~(word)0 : 0; + } + + // collect variables +// Abc_ObjForEachFanin( pNode, pNet, i ) +// pVars[0][i] = pVars[1][i] = pVars[2][i] = i; + + // derive truth table + Abc_SopToTruthBig( (char*)Abc_ObjData(pNode), nLeaves, pTruths, pCube, pRes ); + if ( Kit_TruthIsConst0((unsigned *)pRes, nLeaves) || Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ) + { + fprintf( pFile, ".names %s\n %d\n", "o", Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ); + fprintf( pFile, ".end\n" ); + return; + } + +// Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); +// Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + + // perform decomposition + if ( Length == 2 ) + { + if ( !If_CluCheckExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) ) + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return; + } + } + else + { + if ( !If_CluCheckExt3( NULL, pRes, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, pLut0, pLut1, pLut2, &Func0, &Func1, &Func2 ) ) + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return; + } + } + + // write leaf node + // //fprintf( pFile, ".names" ); + for ( i = 0; i < pLut1[0]; i++ ) + fprintf( pFile, " %c", 'a' + pLut1[2+i] ); + fprintf( pFile, " lut1\n" ); + // write SOP + pSop = Io_NtkWriteEdgelistDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func1, pLut1[0], vCover ); + fprintf( pFile, "%s", pSop ); + + if ( Length == 3 && pLut2[0] > 0 ) + { + // write leaf node + // //fprintf( pFile, ".names" ); + for ( i = 0; i < pLut2[0]; i++ ) + if ( pLut2[2+i] == nLeaves ) + fprintf( pFile, " lut1" ); + else + fprintf( pFile, " %c", 'a' + pLut2[2+i] ); + fprintf( pFile, " lut2\n" ); + // write SOP + pSop = Io_NtkWriteEdgelistDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func2, pLut2[0], vCover ); + fprintf( pFile, "%s", pSop ); + } + + // write root node + //fprintf( pFile, ".names" ); + for ( i = 0; i < pLut0[0]; i++ ) + if ( pLut0[2+i] == nLeaves ) + fprintf( pFile, " lut1" ); + else if ( pLut0[2+i] == nLeaves+1 ) + fprintf( pFile, " lut2" ); + else + fprintf( pFile, " %c", 'a' + pLut0[2+i] ); + fprintf( pFile, " %s\n", "o" ); + // write SOP + pSop = Io_NtkWriteEdgelistDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func0, pLut0[0], vCover ); + fprintf( pFile, "%s", pSop ); + fprintf( pFile, ".end\n" ); + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c index e05aed2e9..48b15b559 100644 --- a/src/base/io/ioWriteVerilog.c +++ b/src/base/io/ioWriteVerilog.c @@ -557,9 +557,23 @@ void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ) } else { + Vec_Int_t * vMap = Vec_IntStartFull( 2*Abc_NtkObjNumMax(pNtk) ); vLevels = Vec_VecAlloc( 10 ); Abc_NtkForEachNode( pNtk, pObj, i ) { + if ( Abc_ObjFaninNum(pObj) == 1 || Abc_ObjIsCo(Abc_ObjFanout0(Abc_ObjFanout0(pObj))) ) + { + int iLit = Abc_Var2Lit( Abc_ObjId( Abc_ObjFanin0(Abc_ObjFanin0(pObj)) ), Abc_NodeIsInv(pObj) ); + int iObj = Vec_IntEntry( vMap, iLit ); + if ( iObj == -1 ) + Vec_IntWriteEntry( vMap, iLit, Abc_ObjId(Abc_ObjFanout0(pObj)) ); + else + { + fprintf( pFile, " assign %s = ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); + fprintf( pFile, "%s;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_NtkObj(pNtk, iObj))) ); + continue; + } + } pFunc = (Hop_Obj_t *)pObj->pData; fprintf( pFile, " assign %s = ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); // set the input names @@ -581,6 +595,7 @@ void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ) ABC_FREE( Hop_IthVar((Hop_Man_t *)pNtk->pManFunc, k)->pData ); } Vec_VecFree( vLevels ); + Vec_IntFree( vMap ); } } diff --git a/src/base/io/module.make b/src/base/io/module.make index 47c9701af..d80642134 100644 --- a/src/base/io/module.make +++ b/src/base/io/module.make @@ -24,6 +24,7 @@ SRC += src/base/io/io.c \ src/base/io/ioWriteCnf.c \ src/base/io/ioWriteDot.c \ src/base/io/ioWriteEqn.c \ + src/base/io/ioWriteEdgelist.c \ src/base/io/ioWriteGml.c \ src/base/io/ioWriteList.c \ src/base/io/ioWritePla.c \ diff --git a/src/base/main/libSupport.c b/src/base/main/libSupport.c index 4d7624133..cdab69ee7 100644 --- a/src/base/main/libSupport.c +++ b/src/base/main/libSupport.c @@ -61,7 +61,7 @@ void open_libs() { DIR* dirp; struct dirent* dp; char *env, *init_p, *p; - int done; + //int done; env = getenv ("ABC_LIB_PATH"); if (env == NULL) { @@ -74,12 +74,14 @@ void open_libs() { } // Extract directories and read libraries - done = 0; + //done = 0; p = init_p; - while (!done) { + //while (!done) { + for (;;) { char *endp = strchr (p,':'); - if (endp == NULL) done = 1; // last directory in the list - else *endp = 0; // end of string + //if (endp == NULL) done = 1; // last directory in the list + //else *endp = 0; // end of string + if (endp != NULL) *endp = 0; // end of string dirp = opendir(p); if (dirp == NULL) { @@ -119,7 +121,12 @@ void open_libs() { } } closedir(dirp); - p = endp+1; + //p = endp+1; + if (endp == NULL) { + break; // last directory in the list + } else { + p = endp+1; + } } ABC_FREE(init_p); diff --git a/src/base/main/mainUtils.c b/src/base/main/mainUtils.c index 377299fd1..245e936af 100644 --- a/src/base/main/mainUtils.c +++ b/src/base/main/mainUtils.c @@ -261,7 +261,7 @@ void Abc_UtilsSource( Abc_Frame_t * pAbc ) ******************************************************************************/ char * DateReadFromDateString( char * datestr ) { - static char result[25]; + static char result[100]; char day[10]; char month[10]; char zone[10]; diff --git a/src/base/wlc/wlc.c b/src/base/wlc/wlc.c index 261ec96ba..3ba9be96d 100644 --- a/src/base/wlc/wlc.c +++ b/src/base/wlc/wlc.c @@ -705,6 +705,81 @@ Gia_Man_t * Wlc_ManGenProd( int nInputs, int fVerbose ) return pNew; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_PrintTernary( FILE * pFile, word * pFunc, word * pCare, int nBits ) +{ + int i; + for ( i = nBits-1; i >= 0; i-- ) + if ( Abc_TtGetBit(pCare, i) ) + fprintf( pFile, "%c", '0' + Abc_TtGetBit(pFunc, i) ); + else + fprintf( pFile, "-" ); + fprintf( pFile, "\n" ); +} +void Wlc_AdderTreeGen( int n ) +{ + word Care[1<<10] = {0}; + word Truth[8][1<<10] = {{0}}; + int nIns = 0, pIns[16][2] = {{0}}; + int i, k, x, Res, Mint, nMints = 1 << (n*n); + assert( n >= 2 && n <= 4 ); + for ( x = 0; x < 2*n; x++ ) + { + for ( i = 0; i < n; i++ ) + for ( k = 0; k < n; k++ ) + if ( i + k == x ) + pIns[nIns][0] = i, pIns[nIns][1] = k, nIns++; + } + for ( x = 0; x < nIns; x++ ) + printf( "(%d, %d) ", pIns[x][0], pIns[x][1] ); + printf( "\n" ); + for ( i = 0; i < (1<> pIns[x][0]) & 1) && ((k >> pIns[x][1]) & 1) ) + Mint |= 1 << x; + assert( Mint < (1<<16) ); + Abc_TtSetBit( Care, Mint ); + + Res = i * k; + for ( x = 0; x < 2*n; x++ ) + if ( (Res >> x) & 1 ) + Abc_TtSetBit( Truth[x], Mint ); + } + if ( n == 2 ) + { + Care[0] = Abc_Tt6Stretch( Care[0], n*n ); + for ( i = 0; i < 2*n; i++ ) + Truth[i][0] = Abc_Tt6Stretch( Truth[i][0], n*n ); + nMints = 64; + } + for ( x = 0; x < nMints; x++ ) + printf( "%d", Abc_TtGetBit(Care, x) ); + printf( "\n\n" ); + for ( i = 0; i < 2*n; i++, printf( "\n" ) ) + for ( x = 0; x < nMints; x++ ) + printf( "%d", Abc_TtGetBit(Truth[i], x) ); + if ( 1 ) + { + FILE * pFile = fopen( "tadd.truth", "wb" ); + for ( i = 0; i < 2*n; i++ ) + Extra_PrintTernary( pFile, Truth[i], Care, nMints ); + fclose( pFile ); + } +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c index cf7ae5df2..4ac2f31c0 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -623,7 +623,7 @@ void Wlc_BlastDivider( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int n ABC_FREE( pQuo ); } // non-restoring divider -void Wlc_BlastDivider2( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes ) +void Wlc_BlastDividerNR( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes ) { int i, * pRes = Vec_IntArray(vRes); int k, * pQuo = ABC_ALLOC( int, nNum ); @@ -653,7 +653,14 @@ void Wlc_BlastDivider2( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int } ABC_FREE( pQuo ); } -void Wlc_BlastDividerSigned( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes ) +void Wlc_BlastDividerTop( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes, int fNonRest ) +{ + if ( fNonRest ) + Wlc_BlastDividerNR( pNew, pNum, nNum, pDiv, nDiv, fQuo, vRes ); + else + Wlc_BlastDivider( pNew, pNum, nNum, pDiv, nDiv, fQuo, vRes ); +} +void Wlc_BlastDividerSigned( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes, int fNonRest ) { Vec_Int_t * vNum = Vec_IntAlloc( nNum ); Vec_Int_t * vDiv = Vec_IntAlloc( nDiv ); @@ -665,10 +672,10 @@ void Wlc_BlastDividerSigned( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int k, iDiffSign = Gia_ManHashXor( pNew, pNum[nNum-1], pDiv[nDiv-1] ); Wlc_BlastMinus( pNew, pNum, nNum, vNum ); Wlc_BlastMinus( pNew, pDiv, nDiv, vDiv ); - Wlc_BlastDivider( pNew, pNum, nNum, pDiv, nDiv, fQuo, vRes00 ); - Wlc_BlastDivider( pNew, pNum, nNum, Vec_IntArray(vDiv), nDiv, fQuo, vRes01 ); - Wlc_BlastDivider( pNew, Vec_IntArray(vNum), nNum, pDiv, nDiv, fQuo, vRes10 ); - Wlc_BlastDivider( pNew, Vec_IntArray(vNum), nNum, Vec_IntArray(vDiv), nDiv, fQuo, vRes11 ); + Wlc_BlastDividerTop( pNew, pNum, nNum, pDiv, nDiv, fQuo, vRes00, fNonRest ); + Wlc_BlastDividerTop( pNew, pNum, nNum, Vec_IntArray(vDiv), nDiv, fQuo, vRes01, fNonRest ); + Wlc_BlastDividerTop( pNew, Vec_IntArray(vNum), nNum, pDiv, nDiv, fQuo, vRes10, fNonRest ); + Wlc_BlastDividerTop( pNew, Vec_IntArray(vNum), nNum, Vec_IntArray(vDiv), nDiv, fQuo, vRes11, fNonRest ); Vec_IntClear( vRes ); for ( k = 0; k < nNum; k++ ) { @@ -1124,13 +1131,14 @@ void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int 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 || (fSigned && i == nArgA) ) continue; - - Vec_WecPush( vProds, k+i, pp ); - Vec_WecPush( vLevels, k+i, 0 ); + if ( pp ) + { + Vec_WecPush( vProds, k+i, pp ); + Vec_WecPush( vLevels, k+i, 0 ); + } } if ( fSigned ) i--; // perform sign extension @@ -1143,13 +1151,19 @@ void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int Vec_WecPush( vProds, k+i+1, Sign ); Vec_WecPush( vLevels, k+i+1, 0 ); + if ( Sign != 1 ) + { Vec_WecPush( vProds, k+i+2, Abc_LitNot(Sign) ); Vec_WecPush( vLevels, k+i+2, 0 ); + } } else { + if ( Sign != 1 ) + { 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 ); @@ -1817,9 +1831,9 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, fSigned ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, fSigned ); if ( fSigned ) - Wlc_BlastDividerSigned( pNew, pArg0, nRangeMax, pArg1, nRangeMax, pObj->Type == WLC_OBJ_ARI_DIVIDE, vRes ); + Wlc_BlastDividerSigned( pNew, pArg0, nRangeMax, pArg1, nRangeMax, pObj->Type == WLC_OBJ_ARI_DIVIDE, vRes, pPar->fNonRest ); else - Wlc_BlastDivider( pNew, pArg0, nRangeMax, pArg1, nRangeMax, pObj->Type == WLC_OBJ_ARI_DIVIDE, vRes ); + Wlc_BlastDividerTop( pNew, pArg0, nRangeMax, pArg1, nRangeMax, pObj->Type == WLC_OBJ_ARI_DIVIDE, vRes, pPar->fNonRest ); Vec_IntShrink( vRes, nRange ); if ( !pPar->fDivBy0 ) Wlc_BlastZeroCondition( pNew, pFans1, nRange1, vRes ); diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c index e981e0fa2..13192a1eb 100644 --- a/src/base/wlc/wlcCom.c +++ b/src/base/wlc/wlcCom.c @@ -1222,7 +1222,7 @@ usage: Abc_Print( -2, "\t-o : toggle using additional POs on the word-level boundaries [default = %s]\n", pPar->fAddOutputs? "yes": "no" ); Abc_Print( -2, "\t-m : toggle creating boxes for all multipliers in the design [default = %s]\n", pPar->fMulti? "yes": "no" ); Abc_Print( -2, "\t-b : toggle generating radix-4 Booth multipliers [default = %s]\n", pPar->fBooth? "yes": "no" ); - Abc_Print( -2, "\t-q : toggle generating non-restoring square root [default = %s]\n", pPar->fNonRest? "yes": "no" ); + Abc_Print( -2, "\t-q : toggle generating non-restoring square root and divider [default = %s]\n", pPar->fNonRest? "yes": "no" ); Abc_Print( -2, "\t-a : toggle generating carry-look-ahead adder [default = %s]\n", pPar->fCla? "yes": "no" ); Abc_Print( -2, "\t-y : toggle creating different divide-by-0 condition [default = %s]\n", pPar->fDivBy0? "yes": "no" ); Abc_Print( -2, "\t-d : toggle creating dual-output multi-output miter [default = %s]\n", pPar->fCreateMiter? "yes": "no" ); diff --git a/src/base/wlc/wlcNdr.c b/src/base/wlc/wlcNdr.c index a7615c2de..5419286ff 100644 --- a/src/base/wlc/wlcNdr.c +++ b/src/base/wlc/wlcNdr.c @@ -367,7 +367,8 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) { Ndr_Data_t * p = (Ndr_Data_t *)pData; Wlc_Obj_t * pObj; Vec_Int_t * vName2Obj, * vFanins = Vec_IntAlloc( 100 ); - int Mod = 2, i, k, Obj, * pArray, nDigits, fFound, NameId, NameIdMax; + int Mod = 2, i, k, Obj, * pArray, fFound, NameId, NameIdMax; + unsigned char nDigits; Vec_Wrd_t * vTruths = NULL; int nTruths[2] = {0}; Wlc_Ntk_t * pTemp, * pNtk = Wlc_NtkAlloc( "top", Ndr_DataObjNum(p, Mod)+1 ); Wlc_NtkCheckIntegrity( pData ); @@ -488,11 +489,11 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) Vec_IntFree(vName2Obj); // create fake object names NameIdMax = Vec_IntFindMax(&pNtk->vNameIds); - nDigits = Abc_Base10Log( NameIdMax+1 ); + nDigits = (unsigned char)Abc_Base10Log( NameIdMax+1 ); pNtk->pManName = Abc_NamStart( NameIdMax+1, 10 ); for ( i = 1; i <= NameIdMax; i++ ) { - char pName[100]; sprintf( pName, "s%0*d", nDigits, i ); + char pName[1000]; sprintf( pName, "s%0*d", nDigits, i ); NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound ); assert( !fFound && i == NameId ); } diff --git a/src/base/wlc/wlcNtk.c b/src/base/wlc/wlcNtk.c index ca5e615be..5d1097202 100644 --- a/src/base/wlc/wlcNtk.c +++ b/src/base/wlc/wlcNtk.c @@ -1292,10 +1292,10 @@ Wlc_Ntk_t * Wlc_NtkDupSingleNodes( Wlc_Ntk_t * p ) void Wlc_NtkShortNames( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; - char pBuffer[100]; - int nDigits, NameId, fFound, i; + char pBuffer[1000]; + int NameId, fFound, i; int nFlops = Wlc_NtkCoNum(p) - Wlc_NtkPoNum(p); - nDigits = Abc_Base10Log( nFlops ); + unsigned char nDigits = (unsigned char)Abc_Base10Log( nFlops ); Wlc_NtkForEachCo( p, pObj, i ) { if ( Wlc_ObjIsPo(pObj) ) diff --git a/src/base/wlc/wlcShow.c b/src/base/wlc/wlcShow.c index 59f42db51..0b48e0e14 100644 --- a/src/base/wlc/wlcShow.c +++ b/src/base/wlc/wlcShow.c @@ -358,7 +358,7 @@ void Wlc_NtkDumpDot( Wlc_Ntk_t * p, char * pFileName, Vec_Int_t * vBold ) ***********************************************************************/ void Wlc_NtkShow( Wlc_Ntk_t * p, Vec_Int_t * vBold ) { - extern void Abc_ShowFile( char * FileNameDot ); + extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); FILE * pFile; char FileNameDot[200]; char * pName = Extra_FileDesignName(p->pName); @@ -377,7 +377,7 @@ void Wlc_NtkShow( Wlc_Ntk_t * p, Vec_Int_t * vBold ) // generate the file Wlc_NtkDumpDot( p, FileNameDot, vBold ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } //////////////////////////////////////////////////////////////////////// diff --git a/src/base/wln/wlnBlast.c b/src/base/wln/wlnBlast.c index 887412d62..776cdd902 100644 --- a/src/base/wln/wlnBlast.c +++ b/src/base/wln/wlnBlast.c @@ -72,8 +72,8 @@ void Rtl_NtkBlastNode( Gia_Man_t * pNew, int Type, int nIns, Vec_Int_t * vDatas, extern void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); extern void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); extern void Wlc_BlastZeroCondition( Gia_Man_t * pNew, int * pDiv, int nDiv, Vec_Int_t * vRes ); - extern void Wlc_BlastDivider( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes ); - extern void Wlc_BlastDividerSigned( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes ); + extern void Wlc_BlastDividerTop( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes, int fNonRest ); + extern void Wlc_BlastDividerSigned( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes, int fNonRest ); extern void Wlc_BlastPower( Gia_Man_t * pNew, int * pNum, int nNum, int * pExp, int nExp, Vec_Int_t * vTemp, Vec_Int_t * vRes ); int k, iLit, iLit0, iLit1; @@ -321,9 +321,9 @@ void Rtl_NtkBlastNode( Gia_Man_t * pNew, int Type, int nIns, Vec_Int_t * vDatas, int fDivBy0 = 1; // correct with 1 int fSigned = fSign0 && fSign1; if ( fSigned ) - Wlc_BlastDividerSigned( pNew, Vec_IntArray(vArg0), nRangeMax, Vec_IntArray(vArg1), nRangeMax, Type == ABC_OPER_ARI_DIV, vRes ); + Wlc_BlastDividerSigned( pNew, Vec_IntArray(vArg0), nRangeMax, Vec_IntArray(vArg1), nRangeMax, Type == ABC_OPER_ARI_DIV, vRes, 0 ); else - Wlc_BlastDivider( pNew, Vec_IntArray(vArg0), nRangeMax, Vec_IntArray(vArg1), nRangeMax, Type == ABC_OPER_ARI_DIV, vRes ); + Wlc_BlastDividerTop( pNew, Vec_IntArray(vArg0), nRangeMax, Vec_IntArray(vArg1), nRangeMax, Type == ABC_OPER_ARI_DIV, vRes, 0 ); Vec_IntShrink( vRes, nRange ); if ( !fDivBy0 ) Wlc_BlastZeroCondition( pNew, Vec_IntArray(vArg1), nRange, vRes ); diff --git a/src/base/wln/wlnNdr.c b/src/base/wln/wlnNdr.c index 9eaf71ed9..5fc598002 100644 --- a/src/base/wln/wlnNdr.c +++ b/src/base/wln/wlnNdr.c @@ -256,7 +256,7 @@ Wln_Ntk_t * Wln_NtkFromNdr( void * pData, int fDump ) pNtk->pManName = Abc_NamStart( NameIdMax+1, 10 ); for ( i = 1; i <= NameIdMax; i++ ) { - char pName[100]; sprintf( pName, "s%0*d", nDigits, i ); + char pName[1000]; sprintf( pName, "s%0*d", (unsigned char)nDigits, i ); NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound ); assert( !fFound && i == NameId ); } diff --git a/src/base/wln/wlnRead.c b/src/base/wln/wlnRead.c index b45e51f26..83dd850ba 100644 --- a/src/base/wln/wlnRead.c +++ b/src/base/wln/wlnRead.c @@ -576,7 +576,7 @@ void Rtl_NtkNormRanges( Rtl_Ntk_t * p ) int Offset = Rtl_WireOffset( p, Wire ); int First = Rtl_WireFirst( p, Wire ); assert( First >> 4 == NameId ); - if ( Offset ); + if ( Offset ) { Left -= Offset; Right -= Offset; @@ -1098,13 +1098,13 @@ void Rtl_NtkPrintWire( Rtl_Ntk_t * p, int * pWire ) void Rtl_NtkPrintCell( Rtl_Ntk_t * p, int * pCell ) { int i, Par, Val; - Rtl_CellForEachAttr( p, pCell, Par, Val, i ) - fprintf( Rtl_NtkFile(p), " attribute %s %s\n", Rtl_NtkStr(p, Par), Rtl_NtkStr(p, Val) ); + Rtl_CellForEachAttr( p, pCell, Par, Val, i ) { + fprintf( Rtl_NtkFile(p), " attribute %s %s\n", Rtl_NtkStr(p, Par), Rtl_NtkStr(p, Val) ); } fprintf( Rtl_NtkFile(p), " cell %s %s\n", Rtl_NtkStr(p, Rtl_CellType(pCell)), Rtl_NtkStr(p, pCell[1]) ); Rtl_CellForEachParam( p, pCell, Par, Val, i ) fprintf( Rtl_NtkFile(p), " parameter" ), Rtl_NtkPrintSig(p, Par), Rtl_NtkPrintSig(p, Val), printf( "\n" ); - Rtl_CellForEachConnect( p, pCell, Par, Val, i ) - fprintf( Rtl_NtkFile(p), " connect" ), Rtl_NtkPrintSig(p, Par), Rtl_NtkPrintSig(p, Val), printf( "\n" ); + Rtl_CellForEachConnect( p, pCell, Par, Val, i ) { + fprintf( Rtl_NtkFile(p), " connect" ), Rtl_NtkPrintSig(p, Par), Rtl_NtkPrintSig(p, Val), printf( "\n" ); } fprintf( Rtl_NtkFile(p), " end\n" ); } void Rtl_NtkPrintConnection( Rtl_Ntk_t * p, int * pCon ) diff --git a/src/base/wln/wlnRtl.c b/src/base/wln/wlnRtl.c index 391d168c1..becbee493 100644 --- a/src/base/wln/wlnRtl.c +++ b/src/base/wln/wlnRtl.c @@ -147,13 +147,15 @@ Rtl_Lib_t * Wln_ReadSystemVerilog( char * pFileName, char * pTopModule, char * p int fSVlog = strstr(pFileName, ".sv") != NULL; if ( strstr(pFileName, ".rtl") ) return Rtl_LibReadFile( pFileName, pFileName ); - sprintf( Command, "%s -qp \"read_verilog %s %s%s; hierarchy %s%s; %sproc; write_rtlil %s\"", + sprintf( Command, "%s -qp \"read_verilog %s%s %s%s; hierarchy %s%s; %sproc; write_rtlil %s\"", Wln_GetYosysName(), - pDefines ? pDefines : "", - fSVlog ? "-sv ":"", pFileName, + pDefines ? "-D" : "", + pDefines ? pDefines : "", + fSVlog ? "-sv " : "", + pFileName, pTopModule ? "-top " : "", pTopModule ? pTopModule : "", - fCollapse ? "flatten; " : "", + fCollapse ? "flatten; ": "", pFileTemp ); if ( fVerbose ) printf( "%s\n", Command ); @@ -176,13 +178,14 @@ Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char * char * pFileTemp = "_temp_.aig"; int fRtlil = strstr(pFileName, ".rtl") != NULL; int fSVlog = strstr(pFileName, ".sv") != NULL; - sprintf( Command, "%s -qp \"%s %s%s%s; hierarchy %s%s; flatten; proc; %saigmap; write_aiger %s\"", + sprintf( Command, "%s -qp \"%s %s%s %s%s; hierarchy %s%s; flatten; proc; %saigmap; write_aiger %s\"", Wln_GetYosysName(), - fRtlil ? "read_rtlil" : "read_verilog", + fRtlil ? "read_rtlil" : "read_verilog", + pDefines ? "-D" : "", pDefines ? pDefines : "", - fSVlog ? " -sv ":" ", - pFileName, - pTopModule ? "-top " : "-auto-top", + fSVlog ? "-sv " : "", + pFileName, + pTopModule ? "-top " : "-auto-top", pTopModule ? pTopModule : "", fTechMap ? "techmap; setundef -zero; " : "", pFileTemp ); if ( fVerbose ) diff --git a/src/bool/bdc/bdcSpfd.c b/src/bool/bdc/bdcSpfd.c index 02e932fea..9c16a7fbf 100644 --- a/src/bool/bdc/bdcSpfd.c +++ b/src/bool/bdc/bdcSpfd.c @@ -211,7 +211,7 @@ void Bdc_SpfdDecompose( word Truth, int nVars, int nCands, int nGatesMax ) vWeight = Vec_IntAlloc( 100 ); // initialize elementary variables - pNode = ABC_CALLOC( Bdc_Nod_t, nVars ); + pNode = ABC_CALLOC( Bdc_Nod_t, (unsigned char)nVars ); for ( i = 0; i < nVars; i++ ) pNode[i].Truth = Truths[i]; for ( i = 0; i < nVars; i++ ) diff --git a/src/bool/kit/kit.h b/src/bool/kit/kit.h index ee82b0841..3be9b14f8 100644 --- a/src/bool/kit/kit.h +++ b/src/bool/kit/kit.h @@ -175,10 +175,10 @@ static inline unsigned Kit_DsdLitSupport( Kit_DsdNtk_t * pNtk, int Lit ) #define KIT_MAX(a,b) (((a) > (b))? (a) : (b)) #define KIT_INFINITY (100000000) -static inline int Kit_CubeHasLit( unsigned uCube, int i ) { return(uCube & (unsigned)(1< 0; } -static inline unsigned Kit_CubeSetLit( unsigned uCube, int i ) { return uCube | (unsigned)(1< 0; } +static inline unsigned Kit_CubeSetLit( unsigned uCube, int i ) { return uCube | (unsigned)(1U<pPars->nLutSize, 8 * p->nTruth6Words[p->pPars->nLutSize], p->nCutBytes, p->nObjBytes, p->nSetBytes, p->pPars->fCutMin? "yes":"no" ); // room for temporary truth tables p->puTemp[0] = p->pPars->fTruth? ABC_ALLOC( unsigned, 8 * p->nTruth6Words[p->pPars->nLutSize] ) : NULL; - p->puTemp[1] = p->puTemp[0] + p->nTruth6Words[p->pPars->nLutSize]*2; - p->puTemp[2] = p->puTemp[1] + p->nTruth6Words[p->pPars->nLutSize]*2; - p->puTemp[3] = p->puTemp[2] + p->nTruth6Words[p->pPars->nLutSize]*2; + p->puTemp[1] = p->pPars->fTruth? p->puTemp[0] + p->nTruth6Words[p->pPars->nLutSize]*2 : NULL; + p->puTemp[2] = p->pPars->fTruth? p->puTemp[1] + p->nTruth6Words[p->pPars->nLutSize]*2 : NULL; + p->puTemp[3] = p->pPars->fTruth? p->puTemp[2] + p->nTruth6Words[p->pPars->nLutSize]*2 : NULL; p->puTempW = p->pPars->fTruth? ABC_ALLOC( word, p->nTruth6Words[p->pPars->nLutSize] ) : NULL; if ( pPars->fUseDsd ) { diff --git a/src/map/mapper/mapperLib.c b/src/map/mapper/mapperLib.c index 6356e2f3a..333844355 100644 --- a/src/map/mapper/mapperLib.c +++ b/src/map/mapper/mapperLib.c @@ -15,9 +15,12 @@ Revision [$Id: mapperLib.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $] ***********************************************************************/ -#define _BSD_SOURCE +//#define _BSD_SOURCE #ifndef WIN32 +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif #include #endif diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c index 3010bbd31..9ca6767db 100644 --- a/src/map/mio/mio.c +++ b/src/map/mio/mio.c @@ -16,9 +16,12 @@ ***********************************************************************/ -#define _BSD_SOURCE +//#define _BSD_SOURCE #ifndef WIN32 +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif #include #endif diff --git a/src/map/mio/mioUtils.c b/src/map/mio/mioUtils.c index 06e880c24..6419339f9 100644 --- a/src/map/mio/mioUtils.c +++ b/src/map/mio/mioUtils.c @@ -1711,7 +1711,7 @@ void Mio_LibraryShortNames( Mio_Library_t * pLib ) { char Buffer[10000]; Mio_Gate_t * pGate; Mio_Pin_t * pPin; - int c = 0, i, nDigits = Abc_Base10Log( Mio_LibraryReadGateNum(pLib) ); + int c = 0, i; unsigned char nDigits = (unsigned char)Abc_Base10Log( Mio_LibraryReadGateNum(pLib) ); // itereate through classes Mio_LibraryForEachGate( pLib, pGate ) { diff --git a/src/map/scl/sclLibUtil.c b/src/map/scl/sclLibUtil.c index 7197310f9..9624be93e 100644 --- a/src/map/scl/sclLibUtil.c +++ b/src/map/scl/sclLibUtil.c @@ -197,11 +197,11 @@ void Abc_SclShortNames( SC_Lib * p ) char Buffer[10000]; SC_Cell * pClass, * pCell; SC_Pin * pPin; int i, k, n, nClasses = Abc_SclLibClassNum(p); - int nDigits = Abc_Base10Log( nClasses ); + unsigned char nDigits = (unsigned char)Abc_Base10Log( nClasses ); // itereate through classes SC_LibForEachCellClass( p, pClass, i ) { - int nDigits2 = Abc_Base10Log( Abc_SclClassCellNum(pClass) ); + unsigned char nDigits2 = (unsigned char)Abc_Base10Log( Abc_SclClassCellNum(pClass) ); SC_RingForEachCell( pClass, pCell, k ) { ABC_FREE( pCell->pName ); @@ -214,13 +214,13 @@ void Abc_SclShortNames( SC_Lib * p ) SC_CellForEachPinIn( pCell, pPin, n ) { ABC_FREE( pPin->pName ); - sprintf( Buffer, "%c", 'a'+n ); + sprintf( Buffer, "%c", (char)('a'+n) ); pPin->pName = Abc_UtilStrsav( Buffer ); } SC_CellForEachPinOut( pCell, pPin, n ) { ABC_FREE( pPin->pName ); - sprintf( Buffer, "%c", 'z'-n+pCell->n_inputs ); + sprintf( Buffer, "%c", (char)('z'-n+pCell->n_inputs) ); pPin->pName = Abc_UtilStrsav( Buffer ); } } diff --git a/src/map/super/superGate.c b/src/map/super/superGate.c index 82c928a7a..6c4731107 100644 --- a/src/map/super/superGate.c +++ b/src/map/super/superGate.c @@ -147,9 +147,12 @@ void Super_Precompute( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, int n return; } vStr = Super_PrecomputeStr( pLibGen, nVarsMax, nLevels, nGatesMax, tDelayMax, tAreaMax, TimeLimit, fSkipInv, fVerbose ); - fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile ); + if ( vStr ) + { + fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile ); + Vec_StrFree( vStr ); + } fclose( pFile ); - Vec_StrFree( vStr ); // report the result of writing if ( fVerbose ) { diff --git a/src/misc/extra/extraUtilUtil.c b/src/misc/extra/extraUtilUtil.c index 2f0f4559b..7a9e8fd0b 100644 --- a/src/misc/extra/extraUtilUtil.c +++ b/src/misc/extra/extraUtilUtil.c @@ -280,7 +280,7 @@ char * Extra_UtilFileSearch(char *file, char *path, char *mode) save_path = path = Extra_UtilStrsav(path); quit = 0; - do { + for (;;) { cp = strchr(path, ':'); if (cp != 0) { *cp = '\0'; @@ -304,8 +304,12 @@ char * Extra_UtilFileSearch(char *file, char *path, char *mode) return filename; } ABC_FREE(filename); - path = ++cp; - } while (! quit); + if (quit) { + break; + } else { + path = ++cp; + } + } ABC_FREE(save_path); return 0; diff --git a/src/misc/util/utilTruth.h b/src/misc/util/utilTruth.h index 1a771afa2..2624f9463 100644 --- a/src/misc/util/utilTruth.h +++ b/src/misc/util/utilTruth.h @@ -162,24 +162,34 @@ static inline int Abc_TtBitCount16( int i ) { return Abc_TtBitCount8[i & 0xFF] + ***********************************************************************/ // read/write/flip i-th bit of a bit string table: -static inline int Abc_TtGetBit( word * p, int i ) { return (int)(p[i>>6] >> (word)(i & 63)) & 1; } -static inline void Abc_TtSetBit( word * p, int i ) { p[i>>6] |= (word)(((word)1)<<(i & 63)); } -static inline void Abc_TtXorBit( word * p, int i ) { p[i>>6] ^= (word)(((word)1)<<(i & 63)); } +static inline int Abc_TtGetBit( word * p, int k ) { return (int)(p[k>>6] >> (k & 63)) & 1; } +static inline void Abc_TtSetBit( word * p, int k ) { p[k>>6] |= (((word)1)<<(k & 63)); } +static inline void Abc_TtXorBit( word * p, int k ) { p[k>>6] ^= (((word)1)<<(k & 63)); } // read/write k-th digit d of a quaternary number: -static inline int Abc_TtGetQua( word * p, int k ) { return (int)(p[k>>5] >> (word)((k<<1) & 63)) & 3; } -static inline void Abc_TtSetQua( word * p, int k, int d ) { p[k>>5] |= (word)(((word)d)<<((k<<1) & 63)); } -static inline void Abc_TtXorQua( word * p, int k, int d ) { p[k>>5] ^= (word)(((word)d)<<((k<<1) & 63)); } +static inline int Abc_TtGetQua( word * p, int k ) { return (int)(p[k>>5] >> ((k<<1) & 63)) & 3; } +static inline void Abc_TtSetQua( word * p, int k, int d ) { p[k>>5] |= (((word)d)<<((k<<1) & 63)); } +static inline void Abc_TtXorQua( word * p, int k, int d ) { p[k>>5] ^= (((word)d)<<((k<<1) & 63)); } // read/write k-th digit d of a hexadecimal number: -static inline int Abc_TtGetHex( word * p, int k ) { return (int)(p[k>>4] >> (word)((k<<2) & 63)) & 15; } -static inline void Abc_TtSetHex( word * p, int k, int d ) { p[k>>4] |= (word)(((word)d)<<((k<<2) & 63)); } -static inline void Abc_TtXorHex( word * p, int k, int d ) { p[k>>4] ^= (word)(((word)d)<<((k<<2) & 63)); } +static inline int Abc_TtGetHex( word * p, int k ) { return (int)(p[k>>4] >> ((k<<2) & 63)) & 15; } +static inline void Abc_TtSetHex( word * p, int k, int d ) { p[k>>4] |= (((word)d)<<((k<<2) & 63)); } +static inline void Abc_TtXorHex( word * p, int k, int d ) { p[k>>4] ^= (((word)d)<<((k<<2) & 63)); } // read/write k-th digit d of a 256-base number: -static inline int Abc_TtGet256( word * p, int k ) { return (int)(p[k>>3] >> (word)((k<<3) & 63)) & 255; } -static inline void Abc_TtSet256( word * p, int k, int d ) { p[k>>3] |= (word)(((word)d)<<((k<<3) & 63)); } -static inline void Abc_TtXor256( word * p, int k, int d ) { p[k>>3] ^= (word)(((word)d)<<((k<<3) & 63)); } +static inline int Abc_TtGet256( word * p, int k ) { return (int)(p[k>>3] >> ((k<<3) & 63)) & 255; } +static inline void Abc_TtSet256( word * p, int k, int d ) { p[k>>3] |= (((word)d)<<((k<<3) & 63)); } +static inline void Abc_TtXor256( word * p, int k, int d ) { p[k>>3] ^= (((word)d)<<((k<<3) & 63)); } + +// read/write k-th digit d of a 2^16-base number: +static inline int Abc_TtGet65536( word * p, int k ) { return (int)(p[k>>2] >> ((k<<4) & 63))&0xFFFF; } +static inline void Abc_TtSet65536( word * p, int k, int d ) { p[k>>2] |= (((word)d)<<((k<<4) & 63)); } +static inline void Abc_TtXor65536( word * p, int k, int d ) { p[k>>2] ^= (((word)d)<<((k<<4) & 63)); } + +// read/write k-th digit d of a 2^2^v-base number: +static inline int Abc_TtGetV( word * p, int v, int k ) { return (int)((p[k>>(6-v)] << (64-(1<> (64-(1<>(6-v)] |= (((word)d)<<((k<>(6-v)] ^= (((word)d)<<((k<= 0 && Truth <= 0xF ); + switch ( Truth ) + { + case 0x0 : for ( w = 0; w < nWords; w++ ) pOut[w] = 0; break; // 0000 + case 0x1 : for ( w = 0; w < nWords; w++ ) pOut[w] = ~pIn1[w] & ~pIn0[w]; break; // 0001 + case 0x2 : for ( w = 0; w < nWords; w++ ) pOut[w] = ~pIn1[w] & pIn0[w]; break; // 0010 + case 0x3 : for ( w = 0; w < nWords; w++ ) pOut[w] = ~pIn1[w] ; break; // 0011 + case 0x4 : for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] & ~pIn0[w]; break; // 0100 + case 0x5 : for ( w = 0; w < nWords; w++ ) pOut[w] = ~pIn0[w]; break; // 0101 + case 0x6 : for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] ^ pIn0[w]; break; // 0110 + case 0x7 : for ( w = 0; w < nWords; w++ ) pOut[w] = ~pIn1[w] | ~pIn0[w]; break; // 0111 + case 0x8 : for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] & pIn0[w]; break; // 1000 + case 0x9 : for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] ^ ~pIn0[w]; break; // 1001 + case 0xA : for ( w = 0; w < nWords; w++ ) pOut[w] = pIn0[w]; break; // 1010 + case 0xB : for ( w = 0; w < nWords; w++ ) pOut[w] = ~pIn1[w] | pIn0[w]; break; // 1011 + case 0xC : for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] ; break; // 1100 + case 0xD : for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] | ~pIn0[w]; break; // 1101 + case 0xE : for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] | pIn0[w]; break; // 1110 + case 0xF : for ( w = 0; w < nWords; w++ ) pOut[w] = ~(word)0; break; // 1111 + default : assert( 0 ); + } +} +static inline void Abc_TtTruth4( word Entry, word ** pNodes, word * pOut, int nWords, int fCompl ) +{ + unsigned First = (unsigned)Entry; + unsigned Second = (unsigned)(Entry >> 32); + int i, k = 5; + for ( i = 0; i < 4; i++ ) + { + int Lit0, Lit1, Pair = (First >> (i*8)) & 0xFF; + if ( Pair == 0 ) + break; + Lit0 = Pair & 0xF; + Lit1 = Pair >> 4; + assert( Lit0 != Lit1 ); + if ( Lit0 < Lit1 ) + Abc_TtAndCompl( pNodes[k++], pNodes[Lit0 >> 1], Lit0 & 1, pNodes[Lit1 >> 1], Lit1 & 1, nWords ); + else + Abc_TtXor( pNodes[k++], pNodes[Lit0 >> 1], pNodes[Lit1 >> 1], nWords, (Lit0 & 1) ^ (Lit1 & 1) ); + } + for ( i = 0; i < 3; i++ ) + { + int Lit0, Lit1, Pair = (Second >> (i*10)) & 0x3FF; + if ( Pair == 0 ) + break; + Lit0 = Pair & 0x1F; + Lit1 = Pair >> 5; + assert( Lit0 != Lit1 ); + if ( Lit0 < Lit1 ) + Abc_TtAndCompl( pNodes[k++], pNodes[Lit0 >> 1], Lit0 & 1, pNodes[Lit1 >> 1], Lit1 & 1, nWords ); + else + Abc_TtXor( pNodes[k++], pNodes[Lit0 >> 1], pNodes[Lit1 >> 1], nWords, (Lit0 & 1) ^ (Lit1 & 1) ); + } + assert( k > 5 ); + Abc_TtCopy( pOut, pNodes[k-1], nWords, (int)(Entry >> 62) ^ fCompl ); +} /**Function************************************************************* @@ -1337,30 +1406,45 @@ static inline void Abc_TtPrintHex( word * pTruth, int nVars ) { word * pThis, * pLimit = pTruth + Abc_TtWordNum(nVars); int k; - assert( nVars >= 2 ); - for ( pThis = pTruth; pThis < pLimit; pThis++ ) - for ( k = 0; k < 16; k++ ) - printf( "%c", Abc_TtPrintDigit((int)(pThis[0] >> (k << 2)) & 15) ); + if ( nVars < 2 ) + printf( "%c", Abc_TtPrintDigit((int)pTruth[0] & 15) ); + else + { + assert( nVars >= 2 ); + for ( pThis = pTruth; pThis < pLimit; pThis++ ) + for ( k = 0; k < 16; k++ ) + printf( "%c", Abc_TtPrintDigit((int)(pThis[0] >> (k << 2)) & 15) ); + } printf( "\n" ); } static inline void Abc_TtPrintHexRev( FILE * pFile, word * pTruth, int nVars ) { word * pThis; int k, StartK = nVars >= 6 ? 16 : (1 << (nVars - 2)); - assert( nVars >= 2 ); - for ( pThis = pTruth + Abc_TtWordNum(nVars) - 1; pThis >= pTruth; pThis-- ) - for ( k = StartK - 1; k >= 0; k-- ) - fprintf( pFile, "%c", Abc_TtPrintDigit((int)(pThis[0] >> (k << 2)) & 15) ); + if ( nVars < 2 ) + fprintf( pFile, "%c", Abc_TtPrintDigit((int)pTruth[0] & 15) ); + else + { + assert( nVars >= 2 ); + for ( pThis = pTruth + Abc_TtWordNum(nVars) - 1; pThis >= pTruth; pThis-- ) + for ( k = StartK - 1; k >= 0; k-- ) + fprintf( pFile, "%c", Abc_TtPrintDigit((int)(pThis[0] >> (k << 2)) & 15) ); + } // printf( "\n" ); } static inline void Abc_TtPrintHexSpecial( word * pTruth, int nVars ) { word * pThis; int k; - assert( nVars >= 2 ); - for ( pThis = pTruth + Abc_TtWordNum(nVars) - 1; pThis >= pTruth; pThis-- ) - for ( k = 0; k < 16; k++ ) - printf( "%c", Abc_TtPrintDigit((int)(pThis[0] >> (k << 2)) & 15) ); + if ( nVars < 2 ) + printf( "%c", Abc_TtPrintDigit((int)pTruth[0] & 15) ); + else + { + assert( nVars >= 2 ); + for ( pThis = pTruth + Abc_TtWordNum(nVars) - 1; pThis >= pTruth; pThis-- ) + for ( k = 0; k < 16; k++ ) + printf( "%c", Abc_TtPrintDigit((int)(pThis[0] >> (k << 2)) & 15) ); + } printf( "\n" ); } static inline int Abc_TtWriteHexRev( char * pStr, word * pTruth, int nVars ) @@ -1368,10 +1452,15 @@ static inline int Abc_TtWriteHexRev( char * pStr, word * pTruth, int nVars ) word * pThis; char * pStrInit = pStr; int k, StartK = nVars >= 6 ? 16 : (1 << (nVars - 2)); - assert( nVars >= 2 ); - for ( pThis = pTruth + Abc_TtWordNum(nVars) - 1; pThis >= pTruth; pThis-- ) - for ( k = StartK - 1; k >= 0; k-- ) - *pStr++ = Abc_TtPrintDigit( (int)(pThis[0] >> (k << 2)) & 15 ); + if ( nVars < 2 ) + *pStr++ = Abc_TtPrintDigit((int)pTruth[0] & 15); + else + { + assert( nVars >= 2 ); + for ( pThis = pTruth + Abc_TtWordNum(nVars) - 1; pThis >= pTruth; pThis-- ) + for ( k = StartK - 1; k >= 0; k-- ) + *pStr++ = Abc_TtPrintDigit( (int)(pThis[0] >> (k << 2)) & 15 ); + } return pStr - pStrInit; } static inline void Abc_TtPrintHexArrayRev( FILE * pFile, word * pTruth, int nDigits ) @@ -1461,6 +1550,20 @@ static inline int Abc_TtReadHexNumber( word * pTruth, char * pString ) SeeAlso [] ***********************************************************************/ +static inline void Abc_TtPrintBits( word * pTruth, int nBits ) +{ + int k; + for ( k = 0; k < nBits; k++ ) + printf( "%d", Abc_InfoHasBit( (unsigned *)pTruth, k ) ); + printf( "\n" ); +} +static inline void Abc_TtPrintBits2( word * pTruth, int nBits ) +{ + int k; + for ( k = nBits-1; k >= 0; k-- ) + printf( "%d", Abc_InfoHasBit( (unsigned *)pTruth, k ) ); + printf( "\n" ); +} static inline void Abc_TtPrintBinary( word * pTruth, int nVars ) { word * pThis, * pLimit = pTruth + Abc_TtWordNum(nVars); diff --git a/src/misc/vec/vecWrd.h b/src/misc/vec/vecWrd.h index fdbb18666..aa16771ef 100644 --- a/src/misc/vec/vecWrd.h +++ b/src/misc/vec/vecWrd.h @@ -1217,6 +1217,36 @@ static inline Vec_Wrd_t * Vec_WrdUniqifyHash( Vec_Wrd_t * vData, int nWordSize ) return (Vec_Wrd_t *)vResInt; } +/**Function************************************************************* + + Synopsis [Returns the number of common entries.] + + Description [Assumes that the vectors are sorted in the increasing order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_WrdTwoCountCommon( Vec_Wrd_t * vArr1, Vec_Wrd_t * vArr2 ) +{ + word * pBeg1 = vArr1->pArray; + word * pBeg2 = vArr2->pArray; + word * pEnd1 = vArr1->pArray + vArr1->nSize; + word * pEnd2 = vArr2->pArray + vArr2->nSize; + int Counter = 0; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( *pBeg1 == *pBeg2 ) + pBeg1++, pBeg2++, Counter++; + else if ( *pBeg1 < *pBeg2 ) + pBeg1++; + else + pBeg2++; + } + return Counter; +} + /**Function************************************************************* Synopsis [Comparison procedure for two integers.] @@ -1284,7 +1314,46 @@ static inline void Vec_WrdAppend( Vec_Wrd_t * vVec1, Vec_Wrd_t * vVec2 ) SeeAlso [] ***********************************************************************/ -static inline void Gia_ManSimPatWriteOne( FILE * pFile, word * pSim, int nWords ) +static inline void Vec_WrdDumpBoolOne( FILE * pFile, word * pSim, int nBits, int fReverse ) +{ + int k; + if ( fReverse ) + for ( k = nBits-1; k >= 0; k-- ) + fprintf( pFile, "%d", (int)((pSim[k/64] >> (k%64)) & 1) ); + else + for ( k = 0; k < nBits; k++ ) + fprintf( pFile, "%d", (int)((pSim[k/64] >> (k%64)) & 1) ); + fprintf( pFile, "\n" ); +} +static inline void Vec_WrdDumpBool( char * pFileName, Vec_Wrd_t * p, int nWords, int nBits, int fReverse, int fVerbose ) +{ + int i, nNodes = Vec_WrdSize(p) / nWords; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + assert( Vec_WrdSize(p) % nWords == 0 ); + for ( i = 0; i < nNodes; i++ ) + Vec_WrdDumpBoolOne( pFile, Vec_WrdEntryP(p, i*nWords), nBits, fReverse ); + fclose( pFile ); + if ( fVerbose ) + printf( "Written %d bits of simulation data for %d objects into file \"%s\".\n", nBits, Vec_WrdSize(p)/nWords, pFileName ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_WrdDumpHexOne( FILE * pFile, word * pSim, int nWords ) { int k, Digit, nDigits = nWords*16; for ( k = 0; k < nDigits; k++ ) @@ -1302,7 +1371,7 @@ static inline void Vec_WrdPrintHex( Vec_Wrd_t * p, int nWords ) int i, nNodes = Vec_WrdSize(p) / nWords; assert( Vec_WrdSize(p) % nWords == 0 ); for ( i = 0; i < nNodes; i++ ) - Gia_ManSimPatWriteOne( stdout, Vec_WrdEntryP(p, i*nWords), nWords ); + Vec_WrdDumpHexOne( stdout, Vec_WrdEntryP(p, i*nWords), nWords ); } static inline void Vec_WrdDumpHex( char * pFileName, Vec_Wrd_t * p, int nWords, int fVerbose ) { @@ -1315,7 +1384,7 @@ static inline void Vec_WrdDumpHex( char * pFileName, Vec_Wrd_t * p, int nWords, } assert( Vec_WrdSize(p) % nWords == 0 ); for ( i = 0; i < nNodes; i++ ) - Gia_ManSimPatWriteOne( pFile, Vec_WrdEntryP(p, i*nWords), nWords ); + Vec_WrdDumpHexOne( pFile, Vec_WrdEntryP(p, i*nWords), nWords ); fclose( pFile ); if ( fVerbose ) printf( "Written %d words of simulation data for %d objects into file \"%s\".\n", nWords, Vec_WrdSize(p)/nWords, pFileName ); diff --git a/src/opt/dar/dar.h b/src/opt/dar/dar.h index ed1f4e743..4faee320c 100644 --- a/src/opt/dar/dar.h +++ b/src/opt/dar/dar.h @@ -46,6 +46,7 @@ struct Dar_RwrPar_t_ { int nCutsMax; // the maximum number of cuts to try int nSubgMax; // the maximum number of subgraphs to try + int nMinSaved; // the minumum number of nodes saved int fFanout; // support fanout representation int fUpdateLevel; // update level int fUseZeros; // performs zero-cost replacement diff --git a/src/opt/dar/darCore.c b/src/opt/dar/darCore.c index 24e5a7419..9d877699a 100644 --- a/src/opt/dar/darCore.c +++ b/src/opt/dar/darCore.c @@ -53,6 +53,7 @@ void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars ) memset( pPars, 0, sizeof(Dar_RwrPar_t) ); pPars->nCutsMax = 8; // 8 pPars->nSubgMax = 5; // 5 is a "magic number" + pPars->nMinSaved = 1; pPars->fFanout = 1; pPars->fUpdateLevel = 0; pPars->fUseZeros = 0; @@ -177,7 +178,8 @@ p->timeCuts += Abc_Clock() - clk; pCut->nLeaves = nLeavesOld; } // check the best gain - if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) + //if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) + if ( p->GainBest < p->pPars->nMinSaved ) { // Aig_ObjOrderAdvance( pAig ); continue; diff --git a/src/opt/dar/darScript.c b/src/opt/dar/darScript.c index d95c23d7a..8cb30bddb 100644 --- a/src/opt/dar/darScript.c +++ b/src/opt/dar/darScript.c @@ -849,6 +849,7 @@ pPars->timeSynth = Abc_Clock() - clk; Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ) { extern Aig_Man_t * Cec_ComputeChoicesNew( Gia_Man_t * pGia, int nConfs, int fVerbose ); + extern Aig_Man_t * Cec_ComputeChoicesNew2( Gia_Man_t * pGia, int nConfs, int fVerbose ); extern Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars ); // extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ); extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ); @@ -873,6 +874,8 @@ pPars->timeSynth = Abc_Clock() - clk; // perform choice computation if ( pPars->fUseNew ) pMan = Cec_ComputeChoicesNew( pGia, pPars->nBTLimit, pPars->fVerbose ); + else if ( pPars->fUseNew2 ) + pMan = Cec_ComputeChoicesNew2( pGia, pPars->nBTLimit, pPars->fVerbose ); else if ( pPars->fUseGia ) pMan = Cec_ComputeChoices( pGia, pPars ); else diff --git a/src/opt/dau/dauMerge.c b/src/opt/dau/dauMerge.c index d6b3c0ba3..0fbd126be 100644 --- a/src/opt/dau/dauMerge.c +++ b/src/opt/dau/dauMerge.c @@ -48,7 +48,7 @@ typedef struct Dau_Sto_t_ Dau_Sto_t; struct Dau_Sto_t_ { int iVarUsed; // counter of used variables - char pOutput[DAU_MAX_STR]; // storage for reduced function + char pOutput[2*DAU_MAX_STR+10]; // storage for reduced function char * pPosOutput; // place in the output char pStore[DAU_MAX_VAR][DAU_MAX_STR]; // storage for definitions char * pPosStore[DAU_MAX_VAR]; // place in the store diff --git a/src/opt/sfm/sfmCnf.c b/src/opt/sfm/sfmCnf.c index f6d434f85..e3af7e011 100644 --- a/src/opt/sfm/sfmCnf.c +++ b/src/opt/sfm/sfmCnf.c @@ -76,7 +76,7 @@ int Sfm_TruthToCnf( word Truth, word * pTruth, int nVars, Vec_Int_t * vCover, Ve { if ( Truth == 0 || ~Truth == 0 ) { - //assert( nVars == 0 ); + assert( nVars == 0 ); Vec_StrPush( vCnf, (char)(Truth == 0) ); Vec_StrPush( vCnf, (char)-1 ); return 1; @@ -92,6 +92,7 @@ int Sfm_TruthToCnf( word Truth, word * pTruth, int nVars, Vec_Int_t * vCover, Ve { Vec_StrPush( vCnf, (char)1 ); Vec_StrPush( vCnf, (char)-1 ); + assert( 0 ); return 1; } // const1 @@ -102,6 +103,7 @@ int Sfm_TruthToCnf( word Truth, word * pTruth, int nVars, Vec_Int_t * vCover, Ve { Vec_StrPush( vCnf, (char)0 ); Vec_StrPush( vCnf, (char)-1 ); + assert( 0 ); return 1; } } @@ -196,6 +198,7 @@ void Sfm_TranslateCnf( Vec_Wec_t * vRes, Vec_Str_t * vCnf, Vec_Int_t * vFaninMap Vec_Int_t * vClause; signed char Entry; int i, Lit; + assert( Vec_StrEntry(vCnf, 1) != -1 || Vec_IntSize(vFaninMap) == 1 ); Vec_WecClear( vRes ); vClause = Vec_WecPushLevel( vRes ); Vec_StrForEachEntry( vCnf, Entry, i ) diff --git a/src/opt/sfm/sfmCore.c b/src/opt/sfm/sfmCore.c index 356aea357..f363e1cb0 100644 --- a/src/opt/sfm/sfmCore.c +++ b/src/opt/sfm/sfmCore.c @@ -115,6 +115,7 @@ int Sfm_NodeResubSolve( Sfm_Ntk_t * p, int iNode, int f, int fRemoveOnly ) int fVeryVerbose = 0;//p->pPars->fVeryVerbose && Vec_IntSize(p->vDivs) < 200;// || pNode->Id == 556; int i, iFanin, iVar = -1; int iFaninRem = -1, iFaninSkip = -1; + int nFanins = Sfm_ObjFaninNum(p, iNode); word uTruth, uSign, uMask; abctime clk; assert( Sfm_ObjIsNode(p, iNode) ); @@ -214,7 +215,12 @@ finish: if ( fSkipUpdate ) return 0; // update the network - Sfm_NtkUpdate( p, iNode, f, (iVar == -1 ? iVar : Vec_IntEntry(p->vDivs, iVar)), uTruth ); + Sfm_NtkUpdate( p, iNode, f, (iVar == -1 ? iVar : Vec_IntEntry(p->vDivs, iVar)), uTruth, p->pTruth ); + // the number of fanins cannot increase + assert( nFanins >= Sfm_ObjFaninNum(p, iNode) ); + //printf( "Modifying node %d with %d fanins (resulting in %d fanins). ", iNode, nFanins, Sfm_ObjFaninNum(p, iNode) ); + //Abc_TtPrintHexRev( stdout, p->pTruth, Sfm_ObjFaninNum(p, iNode) ); + //printf( "\n" ); return 1; } @@ -304,7 +310,7 @@ int Sfm_NodeResub( Sfm_Ntk_t * p, int iNode ) return 1; } // try simplifying local functions - if ( p->pPars->fUseDcs ) + if ( p->pPars->fUseDcs && Sfm_ObjFaninNum(p, iNode) <= 6 ) if ( Sfm_NodeResubOne( p, iNode ) ) return 1; /* @@ -360,7 +366,7 @@ void Sfm_NtkPrint( Sfm_Ntk_t * p ) ***********************************************************************/ int Sfm_NtkPerform( Sfm_Ntk_t * p, Sfm_Par_t * pPars ) { - int i, k, Counter = 0; + int i, k, Counter = 0, CounterLarge = 0; //Sfm_NtkPrint( p ); p->timeTotal = Abc_Clock(); if ( pPars->fVerbose ) @@ -382,8 +388,13 @@ int Sfm_NtkPerform( Sfm_Ntk_t * p, Sfm_Par_t * pPars ) continue; if ( p->pPars->nDepthMax && Sfm_ObjLevel(p, i) > p->pPars->nDepthMax ) continue; - if ( Sfm_ObjFaninNum(p, i) < 2 || Sfm_ObjFaninNum(p, i) > 6 ) + //if ( Sfm_ObjFaninNum(p, i) < 2 ) + // continue; + if ( Sfm_ObjFaninNum(p, i) > SFM_SUPP_MAX ) + { + CounterLarge++; continue; + } for ( k = 0; Sfm_NodeResub(p, i); k++ ) { // Counter++; @@ -396,6 +407,8 @@ int Sfm_NtkPerform( Sfm_Ntk_t * p, Sfm_Par_t * pPars ) p->nTotalNodesEnd = Vec_WecSizeUsedLimits( &p->vFanins, Sfm_NtkPiNum(p), Vec_WecSize(&p->vFanins) - Sfm_NtkPoNum(p) ); p->nTotalEdgesEnd = Vec_WecSizeSize(&p->vFanins) - Sfm_NtkPoNum(p); p->timeTotal = Abc_Clock() - p->timeTotal; + if ( pPars->fVerbose && CounterLarge ) + printf( "MFS skipped %d (out of %d) nodes with more than %d fanins.\n", CounterLarge, p->nNodes, SFM_SUPP_MAX ); if ( pPars->fVerbose ) Sfm_NtkPrintStats( p ); //Sfm_NtkPrint( p ); diff --git a/src/opt/sfm/sfmInt.h b/src/opt/sfm/sfmInt.h index 08edf353c..ae4bb60a8 100644 --- a/src/opt/sfm/sfmInt.h +++ b/src/opt/sfm/sfmInt.h @@ -39,6 +39,7 @@ #include "misc/st/st.h" #include "map/mio/mio.h" #include "base/abc/abc.h" +#include "misc/util/utilTruth.h" #include "sfm.h" //////////////////////////////////////////////////////////////////////// @@ -47,7 +48,8 @@ ABC_NAMESPACE_HEADER_START -#define SFM_FANIN_MAX 6 +#define SFM_FANIN_MAX 12 +#define SFM_WORDS_MAX ((SFM_FANIN_MAX>6) ? (1<<(SFM_FANIN_MAX-6)) : 1) #define SFM_SAT_UNDEC 0x1234567812345678 #define SFM_SAT_SAT 0x8765432187654321 @@ -123,6 +125,10 @@ struct Sfm_Ntk_t_ Vec_Int_t * vValues; // SAT variable values Vec_Wec_t * vClauses; // CNF clauses for the node Vec_Int_t * vFaninMap; // mapping fanins into their SAT vars + word TtElems[SFM_FANIN_MAX][SFM_WORDS_MAX]; + word * pTtElems[SFM_FANIN_MAX]; + word pTruth[SFM_WORDS_MAX]; + word pCube[SFM_WORDS_MAX]; // nodes int nTotalNodesBeg; int nTotalEdgesBeg; @@ -216,7 +222,7 @@ extern int Sfm_LibImplementGatesDelay( Sfm_Lib_t * p, int * pFanins, Mi /*=== sfmNtk.c ==========================================================*/ extern Sfm_Ntk_t * Sfm_ConstructNetwork( Vec_Wec_t * vFanins, int nPis, int nPos ); extern void Sfm_NtkPrepare( Sfm_Ntk_t * p ); -extern void Sfm_NtkUpdate( Sfm_Ntk_t * p, int iNode, int f, int iFaninNew, word uTruth ); +extern void Sfm_NtkUpdate( Sfm_Ntk_t * p, int iNode, int f, int iFaninNew, word uTruth, word * pTruth ); /*=== sfmSat.c ==========================================================*/ extern int Sfm_NtkWindowToSolver( Sfm_Ntk_t * p ); extern word Sfm_ComputeInterpolant( Sfm_Ntk_t * p ); diff --git a/src/opt/sfm/sfmNtk.c b/src/opt/sfm/sfmNtk.c index d410aa0b3..70afd91aa 100644 --- a/src/opt/sfm/sfmNtk.c +++ b/src/opt/sfm/sfmNtk.c @@ -166,7 +166,7 @@ void Sfm_CreateLevelR( Vec_Wec_t * vFanouts, Vec_Int_t * vLevelsR, Vec_Str_t * v ***********************************************************************/ Sfm_Ntk_t * Sfm_NtkConstruct( Vec_Wec_t * vFanins, int nPis, int nPos, Vec_Str_t * vFixed, Vec_Str_t * vEmpty, Vec_Wrd_t * vTruths, Vec_Int_t * vStarts, Vec_Wrd_t * vTruths2 ) { - Sfm_Ntk_t * p; + Sfm_Ntk_t * p; int i; Sfm_CheckConsistency( vFanins, nPis, nPos, vFixed ); p = ABC_CALLOC( Sfm_Ntk_t, 1 ); p->nObjs = Vec_WecSize( vFanins ); @@ -192,6 +192,10 @@ Sfm_Ntk_t * Sfm_NtkConstruct( Vec_Wec_t * vFanins, int nPis, int nPos, Vec_Str_t Vec_IntFill( &p->vVar2Id, 2*p->nObjs, -1 ); p->vCover = Vec_IntAlloc( 1 << 16 ); p->vCnfs = Sfm_CreateCnf( p ); + // elementary truth tables + for ( i = 0; i < SFM_FANIN_MAX; i++ ) + p->pTtElems[i] = p->TtElems[i]; + Abc_TtElemInit( p->pTtElems, SFM_FANIN_MAX ); return p; } void Sfm_NtkPrepare( Sfm_Ntk_t * p ) @@ -315,13 +319,14 @@ void Sfm_NtkUpdateLevelR_rec( Sfm_Ntk_t * p, int iNode ) Sfm_ObjForEachFanin( p, iNode, iFanin, i ) Sfm_NtkUpdateLevelR_rec( p, iFanin ); } -void Sfm_NtkUpdate( Sfm_Ntk_t * p, int iNode, int f, int iFaninNew, word uTruth ) +void Sfm_NtkUpdate( Sfm_Ntk_t * p, int iNode, int f, int iFaninNew, word uTruth, word * pTruth ) { int iFanin = Sfm_ObjFanin( p, iNode, f ); + int nWords = Abc_Truth6WordNum( Sfm_ObjFaninNum(p, iNode) - (int)(iFaninNew == -1) ); assert( Sfm_ObjIsNode(p, iNode) ); assert( iFanin != iFaninNew ); - assert( Sfm_ObjFaninNum(p, iNode) <= 6 ); - if ( uTruth == 0 || ~uTruth == 0 ) + assert( Sfm_ObjFaninNum(p, iNode) <= SFM_FANIN_MAX ); + if ( Abc_TtIsConst0(pTruth, nWords) || Abc_TtIsConst1(pTruth, nWords) ) { Sfm_ObjForEachFanin( p, iNode, iFanin, f ) { @@ -346,7 +351,9 @@ void Sfm_NtkUpdate( Sfm_Ntk_t * p, int iNode, int f, int iFaninNew, word uTruth Sfm_NtkUpdateLevelR_rec( p, iFanin ); // update truth table Vec_WrdWriteEntry( p->vTruths, iNode, uTruth ); - Sfm_TruthToCnf( uTruth, NULL, Sfm_ObjFaninNum(p, iNode), p->vCover, (Vec_Str_t *)Vec_WecEntry(p->vCnfs, iNode) ); + if ( p->vTruths2 && Vec_WrdSize(p->vTruths2) ) + Abc_TtCopy( Vec_WrdEntryP(p->vTruths2, Vec_IntEntry(p->vStarts, iNode)), pTruth, nWords, 0 ); + Sfm_TruthToCnf( uTruth, pTruth, Sfm_ObjFaninNum(p, iNode), p->vCover, (Vec_Str_t *)Vec_WecEntry(p->vCnfs, iNode) ); } /**Function************************************************************* diff --git a/src/opt/sfm/sfmSat.c b/src/opt/sfm/sfmSat.c index ed38e681c..c83f86883 100644 --- a/src/opt/sfm/sfmSat.c +++ b/src/opt/sfm/sfmSat.c @@ -153,13 +153,15 @@ int Sfm_NtkWindowToSolver( Sfm_Ntk_t * p ) ***********************************************************************/ word Sfm_ComputeInterpolant( Sfm_Ntk_t * p ) { - word * pSign, uCube, uTruth = 0; + word * pSign; int status, i, Div, iVar, nFinal, * pFinal, nIter = 0; int pLits[2], nVars = sat_solver_nvars( p->pSat ); + int nWords = Abc_Truth6WordNum( Vec_IntSize(p->vDivIds) ); sat_solver_setnvars( p->pSat, nVars + 1 ); pLits[0] = Abc_Var2Lit( Sfm_ObjSatVar(p, p->iPivotNode), 0 ); // F = 1 pLits[1] = Abc_Var2Lit( nVars, 0 ); // iNewLit - assert( Vec_IntSize(p->vDivIds) <= 6 ); + assert( Vec_IntSize(p->vDivIds) <= SFM_FANIN_MAX ); + Abc_TtClear( p->pTruth, nWords ); while ( 1 ) { // find onset minterm @@ -168,7 +170,7 @@ word Sfm_ComputeInterpolant( Sfm_Ntk_t * p ) if ( status == l_Undef ) return SFM_SAT_UNDEC; if ( status == l_False ) - return uTruth; + return p->pTruth[0]; assert( status == l_True ); // remember variable values Vec_IntClear( p->vValues ); @@ -189,7 +191,7 @@ word Sfm_ComputeInterpolant( Sfm_Ntk_t * p ) assert( status == l_False ); // compute cube and add clause nFinal = sat_solver_final( p->pSat, &pFinal ); - uCube = ~(word)0; + Abc_TtFill( p->pCube, nWords ); Vec_IntClear( p->vLits ); Vec_IntPush( p->vLits, Abc_LitNot(pLits[1]) ); // NOT(iNewLit) for ( i = 0; i < nFinal; i++ ) @@ -198,9 +200,9 @@ word Sfm_ComputeInterpolant( Sfm_Ntk_t * p ) continue; Vec_IntPush( p->vLits, pFinal[i] ); iVar = Vec_IntFind( p->vDivIds, Abc_Lit2Var(pFinal[i]) ); assert( iVar >= 0 ); - uCube &= Abc_LitIsCompl(pFinal[i]) ? s_Truths6[iVar] : ~s_Truths6[iVar]; + Abc_TtAndSharp( p->pCube, p->pCube, p->pTtElems[iVar], nWords, !Abc_LitIsCompl(pFinal[i]) ); } - uTruth |= uCube; + Abc_TtOr( p->pTruth, p->pTruth, p->pCube, nWords ); status = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits) + Vec_IntSize(p->vLits) ); assert( status ); nIter++; diff --git a/src/proof/cec/cecChoice.c b/src/proof/cec/cecChoice.c index 139235119..0c7d1be05 100644 --- a/src/proof/cec/cecChoice.c +++ b/src/proof/cec/cecChoice.c @@ -422,6 +422,17 @@ Aig_Man_t * Cec_ComputeChoicesNew( Gia_Man_t * pGia, int nConfs, int fVerbose ) Gia_ManStop( pGia ); return pAig; } +Aig_Man_t * Cec_ComputeChoicesNew2( Gia_Man_t * pGia, int nConfs, int fVerbose ) +{ + extern Gia_Man_t * Cec5_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Aig_Man_t * pAig; + Gia_Man_t * pNew = Cec5_ManSimulateTest3( pGia, nConfs, fVerbose ); + Gia_ManStop( pNew ); + pGia = Gia_ManEquivToChoices( pGia, 3 ); + pAig = Gia_ManToAig( pGia, 1 ); + Gia_ManStop( pGia ); + return pAig; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 2bbc03d2e..00673c165 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -875,7 +875,7 @@ static inline void Cec4_ObjSimCi( Gia_Man_t * p, int iObj ) int w; word * pSim = Cec4_ObjSim( p, iObj ); for ( w = 0; w < p->nSimWords; w++ ) - pSim[w] = Gia_ManRandomW( 0 ); + pSim[w] = Abc_RandomW( 0 ); pSim[0] <<= 1; } static inline void Cec4_ObjClearSimCi( Gia_Man_t * p, int iObj ) @@ -1729,6 +1729,27 @@ Gia_Obj_t * Cec4_ManFindRepr( Gia_Man_t * p, Cec4_Man_t * pMan, int iObj ) pMan->timeResimLoc += Abc_Clock() - clk; return NULL; } +void Gia_ManRemoveWrongChoices( Gia_Man_t * p ) +{ + int i, iObj, iPrev, Counter = 0; + Gia_ManForEachClass( p, i ) + { + for ( iPrev = i, iObj = Gia_ObjNext(p, i); -1 < iObj; iObj = Gia_ObjNext(p, iPrev) ) + { + Gia_Obj_t * pRepr = Gia_ObjReprObj(p, iObj); + if( !Gia_ObjFailed(p,iObj) && Abc_Lit2Var(Gia_ManObj(p,iObj)->Value) == Abc_Lit2Var(pRepr->Value) ) + { + iPrev = iObj; + continue; + } + Gia_ObjSetRepr( p, iObj, GIA_VOID ); + Gia_ObjSetNext( p, iPrev, Gia_ObjNext(p, iObj) ); + Gia_ObjSetNext( p, iObj, 0 ); + Counter++; + } + } + //Abc_Print( 1, "Removed %d wrong choices.\n", Counter ); +} int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** ppNew, int fSimOnly ) { Cec4_Man_t * pMan = Cec4_ManCreate( p, pPars ); @@ -1743,7 +1764,7 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p assert( Gia_ObjId(p, pObj) == i+1 ); // check if any output trivially fails under all-0 pattern - Gia_ManRandom( 1 ); + Abc_Random( 1 ); Gia_ManSetPhase( p ); if ( pPars->nLevelMax ) Gia_ManLevelNum(p); @@ -1864,6 +1885,9 @@ finalize: Cec4_ManDestroy( pMan ); //Gia_ManStaticFanoutStop( p ); //Gia_ManEquivPrintClasses( p, 1, 0 ); + if ( ppNew && *ppNew == NULL ) + *ppNew = Gia_ManDup(p); + Gia_ManRemoveWrongChoices( p ); return p->pCexSeq ? 0 : 1; } Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ) diff --git a/src/proof/cec/cecSatG3.c b/src/proof/cec/cecSatG3.c index f8e3ad0a0..58696310b 100644 --- a/src/proof/cec/cecSatG3.c +++ b/src/proof/cec/cecSatG3.c @@ -917,7 +917,7 @@ static inline void Cec5_ObjSimCi( Gia_Man_t * p, int iObj ) int w; word * pSim = Cec5_ObjSim( p, iObj ); for ( w = 0; w < p->nSimWords; w++ ) - pSim[w] = Gia_ManRandomW( 0 ); + pSim[w] = Abc_RandomW( 0 ); pSim[0] <<= 1; } static inline void Cec5_ObjClearSimCi( Gia_Man_t * p, int iObj ) @@ -1871,6 +1871,7 @@ void Cec5_ManExtend( Cec5_Man_t * pMan, CbsP_Man_t * pCbs ){ int Cec5_ManSweepNodeCbs( Cec5_Man_t * p, CbsP_Man_t * pCbs, int iObj, int iRepr, int fTagFail ); int Cec5_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** ppNew, int fSimOnly, int fCbs, int approxLim, int subBatchSz, int adaRecycle ) { + extern void Gia_ManRemoveWrongChoices( Gia_Man_t * p ); Gia_Obj_t * pObj, * pRepr; CbsP_Man_t * pCbs = NULL; int i, fSimulate = 1; @@ -1902,7 +1903,7 @@ int Cec5_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p assert( Gia_ObjId(p, pObj) == i+1 ); // check if any output trivially fails under all-0 pattern - Gia_ManRandom( 1 ); + Abc_Random( 1 ); Gia_ManSetPhase( p ); if ( pPars->nLevelMax ) Gia_ManLevelNum(p); @@ -2119,6 +2120,7 @@ finalize: CbsP_ManStop(pCbs); //Gia_ManStaticFanoutStop( p ); //Gia_ManEquivPrintClasses( p, 1, 0 ); + Gia_ManRemoveWrongChoices( p ); return p->pCexSeq ? 0 : 1; } Gia_Man_t * Cec5_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars, int fCbs, int approxLim, int subBatchSz, int adaRecycle ) diff --git a/src/proof/dch/dch.h b/src/proof/dch/dch.h index 07f6a1d25..8372058f2 100644 --- a/src/proof/dch/dch.h +++ b/src/proof/dch/dch.h @@ -53,6 +53,7 @@ struct Dch_Pars_t_ int fUseGia; // uses GIA package int fUseCSat; // uses circuit-based solver int fUseNew; // uses new implementation + int fUseNew2; // uses new implementation int fLightSynth; // uses lighter version of synthesis int fSkipRedSupp; // skip choices with redundant support vars int fVerbose; // verbose stats diff --git a/src/proof/ssw/sswCore.c b/src/proof/ssw/sswCore.c index b48db9534..1307d67c9 100644 --- a/src/proof/ssw/sswCore.c +++ b/src/proof/ssw/sswCore.c @@ -444,6 +444,7 @@ Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) // if parameters are not given, create them if ( pPars == NULL ) Ssw_ManSetDefaultParams( pPars = &Pars ); +/* // consider the case of empty AIG if ( Aig_ManNodeNum(pAig) == 0 ) { @@ -452,6 +453,7 @@ Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) Aig_ManReprStart( pAig,Aig_ManObjNumMax(pAig) ); return Aig_ManDupOrdered(pAig); } +*/ // check and update parameters if ( pPars->fLatchCorrOpt ) { diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index 1059a4ae3..f27b6498b 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -1642,7 +1642,14 @@ Vec_Int_t * Exa4_ManSolve( char * pFileNameIn, char * pFileNameOut, int TimeOut, if ( pFile == NULL ) { printf( "Cannot find the Kissat binary \"%s\".\n", pKissat ); - return NULL; + pKissat = "./kissat"; + pFile = fopen( pKissat, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot find the Kissat binary \"%s\".\n", pKissat ); + return NULL; + } + fclose( pFile ); } fclose( pFile ); } @@ -2725,6 +2732,1018 @@ void Exa_ManExactSynthesis5( Bmc_EsPar_t * pPars ) Vec_WrdFree( vSimsOut ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mini_AigPrintArray( FILE * pFile, Mini_Aig_t * p ) +{ + int i, Count = 0; + fprintf( pFile, " { " ); + Mini_AigForEachAnd( p, i ) + fprintf( pFile, "%2d,%2d, ", Mini_AigNodeFanin0(p, i), Mini_AigNodeFanin1(p, i) ), Count++; + Mini_AigForEachPo( p, i ) + fprintf( pFile, "%2d,%2d", Mini_AigNodeFanin0(p, i), Mini_AigNodeFanin0(p, i) ), Count++; + for ( i = Count; i < 8; i++ ) + fprintf( pFile, ", %2d,%2d", 0, 0 ); + fprintf( pFile, " }" ); +} +word Mini_AigWriteEntry( Mini_Aig_t * p ) +{ + word Res = 0; int i, k = 0; + Mini_AigForEachAnd( p, i ) + { + int iLit0 = Mini_AigNodeFanin0(p, i); + int iLit1 = Mini_AigNodeFanin1(p, i); + int Pair; + if ( k < 4 ) + { + assert( (iLit1 & 0xF) != (iLit0 & 0xF) ); + Pair = ((iLit1 & 0xF) << 4) | (iLit0 & 0xF); + Res |= (word)Pair << (k*8); + } + else + { + assert( (iLit1 & 0x1F) != (iLit0 & 0x1F) ); + Pair = ((iLit1 & 0x1F) << 5) | (iLit0 & 0x1F); + Res |= (word)Pair << (32 + (k-4)*10); + } + k++; + } + Mini_AigForEachPo( p, i ) + if ( Mini_AigNodeFanin0(p, i) & 1 ) + Res |= (word)1 << 62; + return Res; +} +word Abc_TtConvertEntry( word Res ) +{ + unsigned First = (unsigned)Res; + unsigned Second = (unsigned)(Res >> 32); + word Fun0, Fun1, Nodes[16] = {0}; int i, k = 5; + for ( i = 0; i < 4; i++ ) + Nodes[i+1] = s_Truths6[i]; + for ( i = 0; i < 4; i++ ) + { + int Lit0, Lit1, Pair = (First >> (i*8)) & 0xFF; + if ( Pair == 0 ) + break; + Lit0 = Pair & 0xF; + Lit1 = Pair >> 4; + assert( Lit0 != Lit1 ); + Fun0 = (Lit0 & 1) ? ~Nodes[Lit0 >> 1] : Nodes[Lit0 >> 1]; + Fun1 = (Lit1 & 1) ? ~Nodes[Lit1 >> 1] : Nodes[Lit1 >> 1]; + Nodes[k++] = Lit0 < Lit1 ? Fun0 & Fun1 : Fun0 ^ Fun1; + } + for ( i = 0; i < 3; i++ ) + { + int Lit0, Lit1, Pair = (Second >> (i*10)) & 0x3FF; + if ( Pair == 0 ) + break; + Lit0 = Pair & 0x1F; + Lit1 = Pair >> 5; + assert( Lit0 != Lit1 ); + Fun0 = (Lit0 & 1) ? ~Nodes[Lit0 >> 1] : Nodes[Lit0 >> 1]; + Fun1 = (Lit1 & 1) ? ~Nodes[Lit1 >> 1] : Nodes[Lit1 >> 1]; + Nodes[k++] = Lit0 < Lit1 ? Fun0 & Fun1 : Fun0 ^ Fun1; + } + return (Res >> 62) ? ~Nodes[k-1] : Nodes[k-1]; +} +word Exa_ManExactSynthesis4VarsOne( int Index, int Truth, int nNodes ) +{ + Mini_Aig_t * pMini = NULL; + int i, m, nMints = 16, fCompl = 0; + Vec_Wrd_t * vSimsIn = Vec_WrdStart( nMints ); + Vec_Wrd_t * vSimsOut = Vec_WrdStart( nMints ); + word pTruth[16] = { Abc_Tt6Stretch((word)Truth, 4) }; + if ( pTruth[0] & 1 ) { fCompl = 1; Abc_TtNot( pTruth, 1 ); } + for ( m = 0; m < nMints; m++ ) + { + Abc_TtSetBit( Vec_WrdEntryP(vSimsOut, m), Abc_TtGetBit(pTruth, m) ); + for ( i = 0; i < 4; i++ ) + if ( (m >> i) & 1 ) + Abc_TtSetBit( Vec_WrdEntryP(vSimsIn, m), 1+i ); + } + assert( Vec_WrdSize(vSimsIn) == 16 ); + pMini = Exa5_ManGenTest( vSimsIn, vSimsOut, 4, 5, 1, nNodes, 0, 0, 0, 0, 0, 0 ); + if ( pMini && fCompl ) Mini_AigFlipLastPo( pMini ); + Vec_WrdFree( vSimsIn ); + Vec_WrdFree( vSimsOut ); + if ( pMini ) + { + /* + FILE * pTable = fopen( "min_xaig4.txt", "a+" ); + Mini_AigPrintArray( pTable, pMini ); + fprintf( pTable, ", // %d : 0x%04x (%d)\n", Index, Truth, nNodes ); + fclose( pTable ); + */ + word Res = Mini_AigWriteEntry( pMini ); + int uTruth = 0xFFFF & (int)Abc_TtConvertEntry( Res ); + if ( uTruth == Truth ) + printf( "Check ok.\n" ); + else + printf( "Check NOT ok!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" ); + Mini_AigStop( pMini ); + return Res; + } + return 0; +} +void Exa_ManExactSynthesis4Vars() +{ + int i, k, nFuncs = 1 << 15; + Vec_Wrd_t * vRes = Vec_WrdAlloc( nFuncs ); + Vec_WrdPush( vRes, 0 ); + for ( i = 1; i < nFuncs; i++ ) + { + word Res = 0; + printf( "\nFunction %d:\n", i ); + for ( k = 1; k < 8; k++ ) + if ( (Res = Exa_ManExactSynthesis4VarsOne( i, i, k )) ) + break; + assert( Res ); + Vec_WrdPush( vRes, Res ); + } + Vec_WrdDumpBin( "minxaig4.data", vRes, 1 ); + Vec_WrdFree( vRes ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Exa6_SortSims( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut ) +{ + word * pSims = Vec_WrdArray( vSimsDiv ); + word * pOuts = Vec_WrdArray( vSimsOut ), temp; + int i, j, best_i, nSize = Vec_WrdSize(vSimsDiv); + assert( Vec_WrdSize(vSimsOut) == nSize ); + for ( i = 0; i < nSize-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nSize; j++ ) + if ( pSims[j] < pSims[best_i] ) + best_i = j; + if ( i == best_i ) + continue; + temp = pSims[i]; + pSims[i] = pSims[best_i]; + pSims[best_i] = temp; + temp = pOuts[i]; + pOuts[i] = pOuts[best_i]; + pOuts[best_i] = temp; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Exa6_ReadFile( char * pFileName, Vec_Wrd_t ** pvSimsDiv, Vec_Wrd_t ** pvSimsOut, int * pnDivs, int * pnOuts ) +{ + int nIns = 0, nDivs = 0, nOuts = 0, nPats = 0, iLine = 0; + int iIns = 0, iDivs = 0, iOuts = 0, Value, i; + char pBuffer[1000]; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Cannot open file \"%s\".\n", pFileName ); + return 0; + } + while ( fgets( pBuffer, 1000, pFile ) != NULL ) + { + if ( pBuffer[0] == 'c' ) + break; + if ( iLine++ == 0 ) + { + char * pLine = pBuffer; + while ( (*pLine >= 'a' && *pLine <= 'z') || (*pLine >= 'A' && *pLine <= 'Z') ) + pLine++; + Value = sscanf( pLine, "%d %d %d %d", &nIns, &nDivs, &nOuts, &nPats ); + if ( Value != 4 ) + { + Abc_Print( -1, "Cannot read the parameter line in file \"%s\".\n", pFileName ); + fclose( pFile ); + return 0; + } + if ( nIns + nDivs >= 64 ) + { + printf( "The number of variables and divisors should not exceed 64.\n" ); + return 0; + } + if ( nOuts > 6 ) + { + printf( "The number of outputs should not exceed 6.\n" ); + return 0; + } + if ( nPats >= 1000 ) + { + printf( "The number of patterns should not exceed 1000.\n" ); + return 0; + } + assert( nIns + nDivs < 64 && nOuts <= 6 && (nIns == 0 || nPats <= (1 << nIns)) && nPats < 1000 ); + *pvSimsDiv = Vec_WrdStart( nPats ); + *pvSimsOut = Vec_WrdStart( nPats ); + continue; + } + if ( pBuffer[0] == '\n' || pBuffer[0] == '\r' || pBuffer[0] == ' ' ) + continue; + for ( i = 0; i < nPats; i++ ) + { + if ( pBuffer[i] == '0' ) + continue; + assert( pBuffer[i] == '1' ); + if ( iIns < nIns ) + Abc_TtSetBit( Vec_WrdEntryP(*pvSimsDiv, nPats-1-i), 1+iIns ); + else if ( iDivs < nDivs ) + Abc_TtSetBit( Vec_WrdEntryP(*pvSimsDiv, nPats-1-i), 1+nIns+iDivs ); + else if ( iOuts < (1 << nOuts) ) + Abc_TtSetBit( Vec_WrdEntryP(*pvSimsOut, nPats-1-i), iOuts ); + } + assert( pBuffer[nPats] != '0' && pBuffer[nPats] != '1' ); + if ( iIns < nIns ) + iIns++; + else if ( iDivs < nDivs ) + iDivs++; + else if ( iOuts < (1 << nOuts) ) + iOuts++; + } + printf( "Finished reading file \"%s\" with %d inputs, %d divisors, %d outputs, and %d patterns.\n", pFileName, nIns, nDivs, nOuts, nPats ); + fclose( pFile ); + assert( iIns == nIns && iDivs == nDivs && iOuts == (1 << nOuts) ); + if ( pnDivs ) + *pnDivs = nDivs; + if ( pnOuts ) + *pnOuts = nOuts; + return nIns; +} +void Exa6_WriteFile( char * pFileName, int nVars, word * pTruths, int nTruths ) +{ + int i, o, m, nMintsI = 1 << nVars, nMintsO = 1 << nTruths; + FILE * pFile = fopen( pFileName, "wb" ); + fprintf( pFile, "%d %d %d %d\n", nVars, 0, nTruths, nMintsI ); + fprintf( pFile, "\n" ); + for ( i = 0; i < nVars; i++, fprintf( pFile, "\n" ) ) + for ( m = nMintsI - 1; m >= 0; m-- ) + fprintf( pFile, "%d", (m >> i) & 1 ); + fprintf( pFile, "\n" ); + for ( o = 0; o < nMintsO; o++, fprintf( pFile, "\n" ) ) + for ( m = nMintsI - 1; m >= 0; m-- ) + { + int oMint = 0; + for ( i = 0; i < nTruths; i++ ) + if ( Abc_TtGetBit(pTruths+i, m) ) + oMint |= (word)1 << i; + fprintf( pFile, "%d", oMint == o ); + } + fclose( pFile ); +} +void Exa6_WriteFile2( char * pFileName, int nVars, int nDivs, int nOuts, Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut ) +{ + int i, o, m, nMintsO = 1 << nOuts; + FILE * pFile = fopen( pFileName, "wb" ); + assert( Vec_WrdSize(vSimsDiv) == Vec_WrdSize(vSimsOut) ); + fprintf( pFile, "%d %d %d %d\n", nVars, nDivs, nOuts, Vec_WrdSize(vSimsOut) ); + fprintf( pFile, "\n" ); + for ( i = 0; i < nVars+nDivs; i++, fprintf( pFile, "\n%s", (i == nVars && nDivs) ? "\n":"" ) ) + for ( m = Vec_WrdSize(vSimsOut) - 1; m >= 0; m-- ) + fprintf( pFile, "%d", Abc_TtGetBit(Vec_WrdEntryP(vSimsDiv, m), 1+i) ); + fprintf( pFile, "\n" ); + for ( o = 0; o < nMintsO; o++, fprintf( pFile, "\n" ) ) + for ( m = Vec_WrdSize(vSimsOut) - 1; m >= 0; m-- ) + fprintf( pFile, "%d", Abc_TtGetBit(Vec_WrdEntryP(vSimsOut, m), o) ); + fclose( pFile ); +} +void Exa6_GenCount( word * pTruths, int nVars ) +{ + int i, k; + assert( nVars >= 3 && nVars <= 7 ); + for ( k = 0; k < 3; k++ ) + pTruths[k] = 0; + for ( i = 0; i < (1 << nVars); i++ ) + { + int n = Abc_TtCountOnes( (word)i ); + for ( k = 0; k < 3; k++ ) + if ( (n >> k) & 1 ) + Abc_TtSetBit( pTruths+k, i ); + } +} +void Exa6_GenProd( word * pTruths, int nVars ) +{ + int i, j, k; + nVars /= 2; + assert( nVars >= 2 && nVars <= 3 ); + for ( k = 0; k < 2*nVars; k++ ) + pTruths[k] = 0; + for ( i = 0; i < (1 << nVars); i++ ) + for ( j = 0; j < (1 << nVars); j++ ) + { + int n = i * j; + for ( k = 0; k < 2*nVars; k++ ) + if ( (n >> k) & 1 ) + Abc_TtSetBit( pTruths+k, (i << nVars) | j ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Exa_ManExactSynthesis6_( Bmc_EsPar_t * pPars, char * pFileName ) +{ + Vec_Wrd_t * vSimsDiv = NULL, * vSimsOut = NULL; + word Entry, Truths[100] = { 0x96, 0xE8 }; +// int i, nVars = 3, nOuts = 2; +// int i, nVars = 6, nOuts = 3; + int i, nVars = 4, nOuts = 4, nDivs2, nOuts2; +// Exa6_GenCount( Truths, nVars ); + Exa6_GenProd( Truths, nVars ); + Exa6_WriteFile( pFileName, nVars, Truths, nOuts ); + + nVars = Exa6_ReadFile( pFileName, &vSimsDiv, &vSimsOut, &nDivs2, &nOuts2 ); + + Vec_WrdForEachEntry( vSimsDiv, Entry, i ) + Abc_TtPrintBits( &Entry, 1 + nVars ); + printf( "\n" ); + Vec_WrdForEachEntry( vSimsOut, Entry, i ) + Abc_TtPrintBits( &Entry, 1 << nOuts ); + printf( "\n" ); + + Vec_WrdFree( vSimsDiv ); + Vec_WrdFree( vSimsOut ); +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDupMini_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupMini_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupMini_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupMini( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Mini_Aig_t * pMini ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; int i, k; + Vec_Int_t * vCopies = Vec_IntStartFull( Mini_AigNodeNum(pMini) ); + //int nPis = Mini_AigPiNum(pMini); + Vec_IntWriteEntry( vCopies, 0, 0 ); + assert( Mini_AigPiNum(pMini) == Vec_IntSize(vIns)+Vec_IntSize(vDivs) ); + assert( Mini_AigPoNum(pMini) == Vec_IntSize(vOuts) ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + Vec_IntWriteEntry( vCopies, 1+i, Gia_ManDupMini_rec(pNew, p, pObj) ); + Gia_ManForEachObjVec( vDivs, p, pObj, i ) + Vec_IntWriteEntry( vCopies, 1+Vec_IntSize(vIns)+i, Gia_ManDupMini_rec(pNew, p, pObj) ); + Mini_AigForEachAnd( pMini, k ) + { + int iFaninLit0 = Mini_AigNodeFanin0( pMini, k ); + int iFaninLit1 = Mini_AigNodeFanin1( pMini, k ); + int iLit0 = Vec_IntEntry(vCopies, Mini_AigLit2Var(iFaninLit0)) ^ Mini_AigLitIsCompl(iFaninLit0); + int iLit1 = Vec_IntEntry(vCopies, Mini_AigLit2Var(iFaninLit1)) ^ Mini_AigLitIsCompl(iFaninLit1); + if ( iFaninLit0 < iFaninLit1 ) + Vec_IntWriteEntry( vCopies, k, Gia_ManAppendAnd(pNew, iLit0, iLit1) ); + else + Vec_IntWriteEntry( vCopies, k, Gia_ManAppendXorReal(pNew, iLit0, iLit1) ); + } + i = 0; + Mini_AigForEachPo( pMini, k ) + { + int iFaninLit0 = Mini_AigNodeFanin0( pMini, k ); + int iLit0 = Vec_IntEntry(vCopies, Mini_AigLit2Var(iFaninLit0)) ^ Mini_AigLitIsCompl(iFaninLit0); + Gia_ManObj( p, Vec_IntEntry(vOuts, i++) )->Value = iLit0; + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupMini_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Vec_IntFree( vCopies ); + return pNew; +} + + + + + + +typedef struct Exa6_Man_t_ Exa6_Man_t; +struct Exa6_Man_t_ +{ + Vec_Wrd_t * vSimsIn; // input signatures (nWords = 1, nIns <= 64) + Vec_Wrd_t * vSimsOut; // output signatures (nWords = 1, nOuts <= 6) + int fVerbose; + int nIns; + int nDivs; // divisors (const + inputs + tfi + sidedivs) + int nNodes; + int nOuts; + int nObjs; + int VarMarks[MAJ_NOBJS][2][MAJ_NOBJS]; + int nCnfVars; + int nCnfVars2; + int nCnfClauses; + FILE * pFile; +}; + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Exa6_ManMarkup( Exa6_Man_t * p ) +{ + int i, k, j, nVars[3] = {1 + 3*p->nNodes, 0, 3*p->nNodes*Vec_WrdSize(p->vSimsIn)}; + assert( p->nObjs <= MAJ_NOBJS ); + for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) + for ( k = 0; k < 2; k++ ) + for ( j = 1+!k; j < i-k; j++ ) + p->VarMarks[i][k][j] = nVars[0] + nVars[1]++; + for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) + for ( j = 0; j < p->nDivs + p->nNodes; j++ ) + p->VarMarks[i][0][j] = nVars[0] + nVars[1]++; + if ( p->fVerbose ) + printf( "Variables: Function = %d. Structure = %d. Internal = %d. Total = %d.\n", + nVars[0], nVars[1], nVars[2], nVars[0] + nVars[1] + nVars[2] ); + if ( 0 ) + { + for ( j = 0; j < 2; j++ ) + { + printf( " : " ); + for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) + { + for ( k = 0; k < 2; k++ ) + printf( "%3d ", j ? k : i ); + printf( " " ); + } + printf( " " ); + for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) + { + printf( "%3d ", j ? 0 : i ); + printf( " " ); + } + printf( "\n" ); + } + for ( j = 0; j < 5 + p->nNodes*9 + p->nOuts*5; j++ ) + printf( "-" ); + printf( "\n" ); + for ( j = p->nObjs - 2; j >= 0; j-- ) + { + if ( j > 0 && j <= p->nIns ) + printf( " %c : ", 'a'+j-1 ); + else if ( j > p->nIns && j < p->nDivs ) + printf( " %c : ", 'A'+j-1-p->nIns ); + else + printf( "%2d : ", j ); + for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) + { + for ( k = 0; k < 2; k++ ) + printf( "%3d ", p->VarMarks[i][k][j] ); + printf( " " ); + } + printf( " " ); + for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) + { + printf( "%3d ", p->VarMarks[i][0][j] ); + printf( " " ); + } + printf( "\n" ); + } + } + return nVars[0] + nVars[1] + nVars[2]; +} +Exa6_Man_t * Exa6_ManAlloc( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int fVerbose ) +{ + Exa6_Man_t * p = ABC_CALLOC( Exa6_Man_t, 1 ); + assert( Vec_WrdSize(vSimsIn) == Vec_WrdSize(vSimsOut) ); + p->vSimsIn = vSimsIn; + p->vSimsOut = vSimsOut; + p->fVerbose = fVerbose; + p->nIns = nIns; + p->nDivs = nDivs; + p->nNodes = nNodes; + p->nOuts = nOuts; + p->nObjs = p->nDivs + p->nNodes + p->nOuts; + p->nCnfVars = Exa6_ManMarkup( p ); + p->nCnfVars2 = 0; + assert( p->nObjs < 64 ); + return p; +} +void Exa6_ManFree( Exa6_Man_t * p ) +{ + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Exa6_ManAddClause( Exa6_Man_t * p, int * pLits, int nLits ) +{ + int i, k = 0; + for ( i = 0; i < nLits; i++ ) + if ( pLits[i] == 1 ) + return 0; + else if ( pLits[i] == 0 ) + continue; + else if ( pLits[i] <= 2*(p->nCnfVars + p->nCnfVars2) ) + pLits[k++] = pLits[i]; + else assert( 0 ); + nLits = k; + assert( nLits > 0 ); + if ( p->pFile ) + { + p->nCnfClauses++; + for ( i = 0; i < nLits; i++ ) + fprintf( p->pFile, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i]) ); + fprintf( p->pFile, "0\n" ); + } + if ( 0 ) + { + for ( i = 0; i < nLits; i++ ) + fprintf( stdout, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i]) ); + fprintf( stdout, "\n" ); + } + return 1; +} +static inline int Exa6_ManAddClause4( Exa6_Man_t * p, int Lit0, int Lit1, int Lit2, int Lit3 ) +{ + int pLits[4] = { Lit0, Lit1, Lit2, Lit3 }; + return Exa6_ManAddClause( p, pLits, 4 ); +} +int Exa6_ManGenStart( Exa6_Man_t * p, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans ) +{ + int pLits[2*MAJ_NOBJS], i, j, k, n, m, nLits; + for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) + { + int iVarStart = 1 + 3*(i - p->nDivs);// + for ( k = 0; k < 2; k++ ) + { + nLits = 0; + for ( j = 0; j < p->nObjs; j++ ) + if ( p->VarMarks[i][k][j] ) + pLits[nLits++] = Abc_Var2Lit( p->VarMarks[i][k][j], 0 ); + assert( nLits > 0 ); + Exa6_ManAddClause( p, pLits, nLits ); + for ( n = 0; n < nLits; n++ ) + for ( m = n+1; m < nLits; m++ ) + Exa6_ManAddClause4( p, Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0 ); + if ( k == 1 ) + break; + for ( j = 0; j < p->nObjs; j++ ) if ( p->VarMarks[i][0][j] ) + for ( n = j; n < p->nObjs; n++ ) if ( p->VarMarks[i][1][n] ) + Exa6_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][0][j], 1), Abc_Var2Lit(p->VarMarks[i][1][n], 1), 0, 0 ); + } + if ( fOrderNodes ) + for ( j = p->nDivs; j < i; j++ ) + for ( n = 0; n < p->nObjs; n++ ) if ( p->VarMarks[i][0][n] ) + for ( m = n+1; m < p->nObjs; m++ ) if ( p->VarMarks[j][0][m] ) + Exa6_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][0][n], 1), Abc_Var2Lit(p->VarMarks[j][0][m], 1), 0, 0 ); + for ( j = p->nDivs; j < i; j++ ) + for ( k = 0; k < 2; k++ ) if ( p->VarMarks[i][k][j] ) + for ( n = 0; n < p->nObjs; n++ ) if ( p->VarMarks[i][!k][n] ) + for ( m = 0; m < 2; m++ ) if ( p->VarMarks[j][m][n] ) + Exa6_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][k][j], 1), Abc_Var2Lit(p->VarMarks[i][!k][n], 1), Abc_Var2Lit(p->VarMarks[j][m][n], 1), 0 ); + if ( fFancy ) + { + nLits = 0; + for ( k = 0; k < 5-fOnlyAnd; k++ ) + pLits[nLits++] = Abc_Var2Lit( iVarStart+k, 0 ); + Exa6_ManAddClause( p, pLits, nLits ); + for ( n = 0; n < nLits; n++ ) + for ( m = n+1; m < nLits; m++ ) + Exa6_ManAddClause4( p, Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0 ); + } + else + { + for ( k = 0; k < 3; k++ ) + Exa6_ManAddClause4( p, Abc_Var2Lit(iVarStart, k==1), Abc_Var2Lit(iVarStart+1, k==2), Abc_Var2Lit(iVarStart+2, k!=0), 0); + if ( fOnlyAnd ) + Exa6_ManAddClause4( p, Abc_Var2Lit(iVarStart, 1), Abc_Var2Lit(iVarStart+1, 1), Abc_Var2Lit(iVarStart+2, 0), 0); + } + } + for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) + { + nLits = 0; + for ( k = 0; k < 2; k++ ) + for ( j = i+1; j < p->nObjs; j++ ) + if ( p->VarMarks[j][k][i] ) + pLits[nLits++] = Abc_Var2Lit( p->VarMarks[j][k][i], 0 ); + //Exa6_ManAddClause( p, pLits, nLits ); + if ( fUniqFans ) + for ( n = 0; n < nLits; n++ ) + for ( m = n+1; m < nLits; m++ ) + Exa6_ManAddClause4( p, Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0 ); + } + for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) + { + nLits = 0; + for ( j = 0; j < p->nDivs + p->nNodes; j++ ) if ( p->VarMarks[i][0][j] ) + pLits[nLits++] = Abc_Var2Lit( p->VarMarks[i][0][j], 0 ); + Exa6_ManAddClause( p, pLits, nLits ); + for ( n = 0; n < nLits; n++ ) + for ( m = n+1; m < nLits; m++ ) + Exa6_ManAddClause4( p, Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0 ); + } + return 1; +} +void Exa6_ManGenMint( Exa6_Man_t * p, int iMint, int fOnlyAnd, int fFancy ) +{ + int iNodeVar = p->nCnfVars + 3*p->nNodes*(iMint - Vec_WrdSize(p->vSimsIn)); + int iOutMint = Abc_Tt6FirstBit( Vec_WrdEntry(p->vSimsOut, iMint) ); + int fOnlyOne = Abc_TtSuppOnlyOne( (int)Vec_WrdEntry(p->vSimsOut, iMint) ); + int i, k, n, j, VarVals[MAJ_NOBJS]; + int fAllOnes = Abc_TtCountOnes( Vec_WrdEntry(p->vSimsOut, iMint) ) == (1 << p->nOuts); + if ( fAllOnes ) + return; + assert( p->nObjs <= MAJ_NOBJS ); + assert( iMint < Vec_WrdSize(p->vSimsIn) ); + assert( p->nOuts <= 6 ); + for ( i = 0; i < p->nDivs; i++ ) + VarVals[i] = (Vec_WrdEntry(p->vSimsIn, iMint) >> i) & 1; + for ( i = 0; i < p->nNodes; i++ ) + VarVals[p->nDivs + i] = Abc_Var2Lit(iNodeVar + 3*i + 2, 0); + if ( fOnlyOne ) + { + for ( i = 0; i < p->nOuts; i++ ) + VarVals[p->nDivs + p->nNodes + i] = (iOutMint >> i) & 1; + } + else + { + word t = Abc_Tt6Stretch( Vec_WrdEntry(p->vSimsOut, iMint), p->nOuts ); + int i, c, nCubes = 0, pCover[100], pLits[10]; + int iOutVar = p->nCnfVars + p->nCnfVars2; p->nCnfVars2 += p->nOuts; + for ( i = 0; i < p->nOuts; i++ ) + VarVals[p->nDivs + p->nNodes + i] = Abc_Var2Lit(iOutVar + i, 0); + assert( t ); + if ( ~t ) + { + Abc_Tt6IsopCover( t, t, p->nOuts, pCover, &nCubes ); + for ( c = 0; c < nCubes; c++ ) + { + int nLits = 0; + for ( i = 0; i < p->nOuts; i++ ) + { + int iLit = (pCover[c] >> (2*i)) & 3; + if ( iLit == 1 || iLit == 2 ) + pLits[nLits++] = Abc_Var2Lit(iOutVar + i, iLit != 1); + } + Exa6_ManAddClause( p, pLits, nLits ); + } + } + } + if ( 0 ) + { + printf( "Adding minterm %d: ", iMint ); + for ( i = 0; i < p->nObjs; i++ ) + printf( " %d=%d", i, VarVals[i] ); + printf( "\n" ); + } + for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) + { + int iVarStart = 1 + 3*(i - p->nDivs);// + int iBaseVarI = iNodeVar + 3*(i - p->nDivs); + for ( k = 0; k < 2; k++ ) + for ( j = 0; j < i; j++ ) if ( p->VarMarks[i][k][j] ) + for ( n = 0; n < 2; n++ ) + Exa6_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][k][j], 1), Abc_Var2Lit(iBaseVarI + k, n), Abc_LitNotCond(VarVals[j], !n), 0); + for ( k = 0; k < 4; k++ ) + for ( n = 0; n < 2; n++ ) + Exa6_ManAddClause4( p, Abc_Var2Lit(iBaseVarI + 0, k&1), Abc_Var2Lit(iBaseVarI + 1, k>>1), Abc_Var2Lit(iBaseVarI + 2, !n), Abc_Var2Lit(k ? iVarStart + k-1 : 0, n)); + } + for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) + { + for ( j = 0; j < p->nDivs + p->nNodes; j++ ) if ( p->VarMarks[i][0][j] ) + for ( n = 0; n < 2; n++ ) + Exa6_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][0][j], 1), Abc_LitNotCond(VarVals[j], n), Abc_LitNotCond(VarVals[i], !n), 0); + } +} +void Exa6_ManGenCnf( Exa6_Man_t * p, char * pFileName, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans ) +{ + int m; + assert( p->pFile == NULL ); + p->pFile = fopen( pFileName, "wb" ); + fputs( "p cnf \n", p->pFile ); + Exa6_ManGenStart( p, fOnlyAnd, fFancy, fOrderNodes, fUniqFans ); + for ( m = 1; m < Vec_WrdSize(p->vSimsIn); m++ ) + Exa6_ManGenMint( p, m, fOnlyAnd, fFancy ); + rewind( p->pFile ); + fprintf( p->pFile, "p cnf %d %d", p->nCnfVars + p->nCnfVars2, p->nCnfClauses ); + fclose( p->pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Exa6_ManFindFanin( Exa6_Man_t * p, Vec_Int_t * vValues, int i, int k ) +{ + int j, Count = 0, iVar = -1; + for ( j = 0; j < p->nObjs; j++ ) + if ( p->VarMarks[i][k][j] && Vec_IntEntry(vValues, p->VarMarks[i][k][j]) ) + { + iVar = j; + Count++; + } + assert( Count == 1 ); + return iVar; +} +static inline void Exa6_ManPrintFanin( Exa6_Man_t * p, int iNode, int fComp ) +{ + if ( iNode == 0 ) + printf( " %s", fComp ? "const1" : "const0" ); + else if ( iNode > 0 && iNode <= p->nIns ) + printf( " %s%c", fComp ? "~" : "", 'a'+iNode-1 ); + else if ( iNode > p->nIns && iNode < p->nDivs ) + printf( " %s%c", fComp ? "~" : "", 'A'+iNode-p->nIns-1 ); + else + printf( " %s%d", fComp ? "~" : "", iNode ); +} +void Exa6_ManPrintSolution( Exa6_Man_t * p, Vec_Int_t * vValues, int fFancy ) +{ + int i, k; + printf( "Circuit for %d-var function with %d divisors contains %d two-input gates:\n", p->nIns, p->nDivs, p->nNodes ); + for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) + { + int iVar = Exa6_ManFindFanin( p, vValues, i, 0 ); + printf( "%2d = ", i ); + Exa6_ManPrintFanin( p, iVar, 0 ); + printf( "\n" ); + } + for ( i = p->nDivs + p->nNodes - 1; i >= p->nDivs; i-- ) + { + int iVarStart = 1 + 3*(i - p->nDivs);// + int Val1 = Vec_IntEntry(vValues, iVarStart); + int Val2 = Vec_IntEntry(vValues, iVarStart+1); + int Val3 = Vec_IntEntry(vValues, iVarStart+2); + printf( "%2d = ", i ); + for ( k = 0; k < 2; k++ ) + { + int iNode = Exa6_ManFindFanin( p, vValues, i, !k ); + int fComp = k ? !Val1 && Val2 && !Val3 : Val1 && !Val2 && !Val3; + Exa6_ManPrintFanin( p, iNode, fComp ); + if ( k ) break; + printf( " %c", (Val1 && Val2) ? (Val3 ? '|' : '^') : '&' ); + } + printf( "\n" ); + } +} +Mini_Aig_t * Exa6_ManMiniAig( Exa6_Man_t * p, Vec_Int_t * vValues, int fFancy ) +{ + int i, k, Compl[MAJ_NOBJS] = {0}; + Mini_Aig_t * pMini = Mini_AigStartSupport( p->nDivs-1, p->nObjs ); + for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ ) + { + int iNodes[2] = {0}; + int iVarStart = 1 + 3*(i - p->nDivs);// + int Val1 = Vec_IntEntry(vValues, iVarStart); + int Val2 = Vec_IntEntry(vValues, iVarStart+1); + int Val3 = Vec_IntEntry(vValues, iVarStart+2); + Compl[i] = Val1 && Val2 && Val3; + for ( k = 0; k < 2; k++ ) + { + int iNode = Exa6_ManFindFanin( p, vValues, i, !k ); + int fComp = k ? !Val1 && Val2 && !Val3 : Val1 && !Val2 && !Val3; + iNodes[k] = Abc_Var2Lit(iNode, fComp ^ Compl[iNode]); + } + if ( Val1 && Val2 ) + { + if ( Val3 ) + Mini_AigOr( pMini, iNodes[0], iNodes[1] ); + else + Mini_AigXorSpecial( pMini, iNodes[0], iNodes[1] ); + } + else + Mini_AigAnd( pMini, iNodes[0], iNodes[1] ); + } + for ( i = p->nDivs + p->nNodes; i < p->nObjs; i++ ) + { + int iVar = Exa6_ManFindFanin( p, vValues, i, 0 ); + Mini_AigCreatePo( pMini, Abc_Var2Lit(iVar, Compl[iVar]) ); + } + assert( p->nObjs == Mini_AigNodeNum(pMini) ); + return pMini; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mini_Aig_t * Exa6_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int TimeOut, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans, int fVerbose ) +{ + Mini_Aig_t * pMini = NULL; + abctime clkTotal = Abc_Clock(); + Vec_Int_t * vValues = NULL; + char * pFileNameIn = "_temp_.cnf"; + char * pFileNameOut = "_temp_out.cnf"; + Exa6_Man_t * p = Exa6_ManAlloc( vSimsIn, vSimsOut, nIns, 1+nIns+nDivs, nOuts, nNodes, fVerbose ); + Exa_ManIsNormalized( vSimsIn, vSimsOut ); + Exa6_ManGenCnf( p, pFileNameIn, fOnlyAnd, fFancy, fOrderNodes, fUniqFans ); + if ( fVerbose ) + printf( "Timeout = %d. OnlyAnd = %d. Fancy = %d. OrderNodes = %d. UniqueFans = %d. Verbose = %d.\n", TimeOut, fOnlyAnd, fFancy, fOrderNodes, fUniqFans, fVerbose ); + if ( fVerbose ) + printf( "CNF with %d variables and %d clauses was dumped into file \"%s\".\n", p->nCnfVars, p->nCnfClauses, pFileNameIn ); + vValues = Exa4_ManSolve( pFileNameIn, pFileNameOut, TimeOut, fVerbose ); + if ( vValues ) pMini = Exa6_ManMiniAig( p, vValues, fFancy ); + //if ( vValues ) Exa6_ManPrintSolution( p, vValues, fFancy ); + if ( vValues ) Exa_ManMiniPrint( pMini, p->nIns ); + if ( vValues && nIns <= 6 ) Exa_ManMiniVerify( pMini, vSimsIn, vSimsOut ); + Vec_IntFreeP( &vValues ); + Exa6_ManFree( p ); + Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); + return pMini; +} +Mini_Aig_t * Mini_AigDupCompl( Mini_Aig_t * p, int ComplIns, int ComplOuts ) +{ + Mini_Aig_t * pNew = Mini_AigStartSupport( Mini_AigPiNum(p), Mini_AigNodeNum(p) ); + Vec_Int_t * vCopies = Vec_IntStartFull( Mini_AigNodeNum(p) ); int k, i = 0, o = 0; + Vec_IntWriteEntry( vCopies, 0, 0 ); + Mini_AigForEachPi( p, k ) + Vec_IntWriteEntry( vCopies, k, Abc_Var2Lit(k, (ComplIns>>i++) & 1) ); + Mini_AigForEachAnd( p, k ) + { + int iFaninLit0 = Mini_AigNodeFanin0( p, k ); + int iFaninLit1 = Mini_AigNodeFanin1( p, k ); + int iLit0 = Vec_IntEntry(vCopies, Mini_AigLit2Var(iFaninLit0)) ^ Mini_AigLitIsCompl(iFaninLit0); + int iLit1 = Vec_IntEntry(vCopies, Mini_AigLit2Var(iFaninLit1)) ^ Mini_AigLitIsCompl(iFaninLit1); + if ( iFaninLit0 < iFaninLit1 ) + Vec_IntWriteEntry( vCopies, k, Mini_AigAnd(pNew, iLit0, iLit1) ); + else + Vec_IntWriteEntry( vCopies, k, Mini_AigXorSpecial(pNew, iLit0, iLit1) ); + } + Mini_AigForEachPo( p, k ) + { + int iFaninLit0 = Mini_AigNodeFanin0( p, k ); + int iLit0 = Vec_IntEntry(vCopies, Mini_AigLit2Var(iFaninLit0)) ^ Mini_AigLitIsCompl(iFaninLit0); + Mini_AigCreatePo( pNew, iLit0 ^ ((ComplOuts >> o++) & 1) ); + } + Vec_IntFree( vCopies ); + return pNew; +} +word Exa6_ManPolarMinterm( word Mint, int nOuts, int Polar ) +{ + word MintNew = 0; + int m, nMints = 1 << nOuts; + for ( m = 0; m < nMints; m++ ) + if ( (Mint >> m) & 1 ) + MintNew |= (word)1 << (m ^ Polar); + return MintNew; +} +int Exa6_ManFindPolar( word First, int nOuts ) +{ + int i; + for ( i = 0; i < (1 << nOuts); i++ ) + if ( Exa6_ManPolarMinterm(First, nOuts, i) & 1 ) + return i; + return -1; +} +Vec_Wrd_t * Exa6_ManTransformOutputs( Vec_Wrd_t * vOuts, int nOuts ) +{ + Vec_Wrd_t * vRes = Vec_WrdAlloc( Vec_WrdSize(vOuts) ); + int i, Polar = Exa6_ManFindPolar( Vec_WrdEntry(vOuts, 0), nOuts ); word Entry; + Vec_WrdForEachEntry( vOuts, Entry, i ) + Vec_WrdPush( vRes, Exa6_ManPolarMinterm(Entry, nOuts, Polar) ); + return vRes; +} +Vec_Wrd_t * Exa6_ManTransformInputs( Vec_Wrd_t * vIns ) +{ + Vec_Wrd_t * vRes = Vec_WrdAlloc( Vec_WrdSize(vIns) ); + int i, Polar = Vec_WrdEntry( vIns, 0 ); word Entry; + Vec_WrdForEachEntry( vIns, Entry, i ) + Vec_WrdPush( vRes, Entry ^ Polar ); + return vRes; +} +void Exa_ManExactPrint( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut, int nDivs, int nOuts ) +{ + word Entry; int i; + Vec_WrdForEachEntry( vSimsDiv, Entry, i ) + Abc_TtPrintBits( &Entry, nDivs ); + printf( "\n" ); + Vec_WrdForEachEntry( vSimsOut, Entry, i ) + Abc_TtPrintBits( &Entry, 1 << nOuts ); + printf( "\n" ); +} +Mini_Aig_t * Exa_ManExactSynthesis6Int( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut, int nVars, int nDivs, int nOuts, int nNodes, int fOnlyAnd, int fVerbose ) +{ + Mini_Aig_t * pTemp, * pMini; + Vec_Wrd_t * vSimsDiv2, * vSimsOut2; + int DivCompl, OutCompl; + if ( nVars == 0 ) return NULL; + assert( nVars <= 8 ); + DivCompl = (int)Vec_WrdEntry(vSimsDiv, 0) >> 1; + OutCompl = Exa6_ManFindPolar( Vec_WrdEntry(vSimsOut, 0), nOuts ); + if ( fVerbose ) + printf( "Inputs = %d. Divisors = %d. Outputs = %d. Nodes = %d. InP = %d. OutP = %d.\n", + nVars, nDivs, nOuts, nNodes, DivCompl, OutCompl ); + vSimsDiv2 = Exa6_ManTransformInputs( vSimsDiv ); + vSimsOut2 = Exa6_ManTransformOutputs( vSimsOut, nOuts ); + pMini = Exa6_ManGenTest( vSimsDiv2, vSimsOut2, nVars, nDivs, nOuts, nNodes, 0, fOnlyAnd, 0, 0, 0, fVerbose ); + if ( pMini ) + { + if ( DivCompl || OutCompl ) + { + pMini = Mini_AigDupCompl( pTemp = pMini, DivCompl, OutCompl ); + Mini_AigStop( pTemp ); + } + Mini_AigerWrite( "exa6.aig", pMini, 1 ); + if ( nVars <= 6 ) + Exa_ManMiniVerify( pMini, vSimsDiv, vSimsOut ); + printf( "\n" ); + //Mini_AigStop( pMini ); + } + Vec_WrdFreeP( &vSimsDiv2 ); + Vec_WrdFreeP( &vSimsOut2 ); + return pMini; +} +void Exa_ManExactSynthesis6( Bmc_EsPar_t * pPars, char * pFileName ) +{ + Mini_Aig_t * pMini = NULL; + Vec_Wrd_t * vSimsDiv = NULL, * vSimsOut = NULL; + int nDivs, nOuts, nVars = Exa6_ReadFile( pFileName, &vSimsDiv, &vSimsOut, &nDivs, &nOuts ); + if ( nVars == 0 ) + return; + Exa6_SortSims( vSimsDiv, vSimsOut ); + pMini = Exa_ManExactSynthesis6Int( vSimsDiv, vSimsOut, nVars, nDivs, nOuts, pPars->nNodes, pPars->fOnlyAnd, pPars->fVerbose ); + Vec_WrdFreeP( &vSimsDiv ); + Vec_WrdFreeP( &vSimsOut ); + if ( pMini ) Mini_AigStop( pMini ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/sat/bsat/satSolver.c b/src/sat/bsat/satSolver.c index 2f3a84db7..eea280293 100644 --- a/src/sat/bsat/satSolver.c +++ b/src/sat/bsat/satSolver.c @@ -511,13 +511,14 @@ static void sortrnd(void** array, int size, int(*comp)(const void *, const void static inline int sat_clause_compute_lbd( sat_solver* s, clause* c ) { - int i, lev, minl = 0, lbd = 0; - for (i = 0; i < (int)c->size; i++) + unsigned int i, lev, minl = 0; + int lbd = 0; + for (i = 0; i < c->size; i++) { lev = var_level(s, lit_var(c->lits[i])); - if ( !(minl & (1 << (lev & 31))) ) + if ( !(minl & (1U << (lev & 31))) ) { - minl |= 1 << (lev & 31); + minl |= 1U << (lev & 31); lbd++; // printf( "%d ", lev ); } diff --git a/src/sat/cnf/cnf.h b/src/sat/cnf/cnf.h index 01728c81e..35c0fa2f7 100644 --- a/src/sat/cnf/cnf.h +++ b/src/sat/cnf/cnf.h @@ -160,6 +160,7 @@ extern void Cnf_DataCollectFlipLits( Cnf_Dat_t * p, int iFlipVar, Vec extern void Cnf_DataLiftAndFlipLits( Cnf_Dat_t * p, int nVarsPlus, Vec_Int_t * vLits ); extern void Cnf_DataPrint( Cnf_Dat_t * p, int fReadable ); extern void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable, Vec_Int_t * vForAlls, Vec_Int_t * vExists ); +extern void Cnf_DataWriteIntoFileInv( Cnf_Dat_t * p, char * pFileName, int fReadable, Vec_Int_t * vExists1, Vec_Int_t * vForAlls, Vec_Int_t * vExists2 ); extern void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit ); extern void * Cnf_DataWriteIntoSolverInt( void * pSat, Cnf_Dat_t * p, int nFrames, int fInit ); extern int Cnf_DataWriteOrClause( void * pSat, Cnf_Dat_t * pCnf ); diff --git a/src/sat/cnf/cnfMan.c b/src/sat/cnf/cnfMan.c index 5a125ec3c..f63cc6335 100644 --- a/src/sat/cnf/cnfMan.c +++ b/src/sat/cnf/cnfMan.c @@ -303,6 +303,48 @@ void Cnf_DataWriteIntoFileGz( Cnf_Dat_t * p, char * pFileName, int fReadable, Ve gzprintf( pFile, "\n" ); gzclose( pFile ); } +void Cnf_DataWriteIntoFileInvGz( Cnf_Dat_t * p, char * pFileName, int fReadable, Vec_Int_t * vExists1, Vec_Int_t * vForAlls, Vec_Int_t * vExists2 ) +{ + gzFile pFile; + int * pLit, * pStop, i, VarId; + pFile = gzopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" ); + return; + } + gzprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" ); + gzprintf( pFile, "p cnf %d %d\n", p->nVars, p->nClauses ); + if ( vExists1 ) + { + gzprintf( pFile, "e " ); + Vec_IntForEachEntry( vExists1, VarId, i ) + gzprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); + gzprintf( pFile, "0\n" ); + } + if ( vForAlls ) + { + gzprintf( pFile, "a " ); + Vec_IntForEachEntry( vForAlls, VarId, i ) + gzprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); + gzprintf( pFile, "0\n" ); + } + if ( vExists2 ) + { + gzprintf( pFile, "e " ); + Vec_IntForEachEntry( vExists2, VarId, i ) + gzprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); + gzprintf( pFile, "0\n" ); + } + for ( i = 0; i < p->nClauses; i++ ) + { + for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ ) + gzprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) ); + gzprintf( pFile, "0\n" ); + } + gzprintf( pFile, "\n" ); + gzclose( pFile ); +} /**Function************************************************************* @@ -355,6 +397,53 @@ void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable, Vec_ fprintf( pFile, "\n" ); fclose( pFile ); } +void Cnf_DataWriteIntoFileInv( Cnf_Dat_t * p, char * pFileName, int fReadable, Vec_Int_t * vExists1, Vec_Int_t * vForAlls, Vec_Int_t * vExists2 ) +{ + FILE * pFile; + int * pLit, * pStop, i, VarId; + if ( !strncmp(pFileName+strlen(pFileName)-3,".gz",3) ) + { + Cnf_DataWriteIntoFileInvGz( p, pFileName, fReadable, vExists1, vForAlls, vExists2 ); + return; + } + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" ); + return; + } + fprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" ); + fprintf( pFile, "p cnf %d %d\n", p->nVars, p->nClauses ); + if ( vExists1 ) + { + fprintf( pFile, "e " ); + Vec_IntForEachEntry( vExists1, VarId, i ) + fprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); + fprintf( pFile, "0\n" ); + } + if ( vForAlls ) + { + fprintf( pFile, "a " ); + Vec_IntForEachEntry( vForAlls, VarId, i ) + fprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); + fprintf( pFile, "0\n" ); + } + if ( vExists2 ) + { + fprintf( pFile, "e " ); + Vec_IntForEachEntry( vExists2, VarId, i ) + fprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); + fprintf( pFile, "0\n" ); + } + for ( i = 0; i < p->nClauses; i++ ) + { + for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ ) + fprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) ); + fprintf( pFile, "0\n" ); + } + fprintf( pFile, "\n" ); + fclose( pFile ); +} /**Function************************************************************* diff --git a/src/sat/glucose/Vec.h b/src/sat/glucose/Vec.h index d2781635c..4ef2bdf10 100644 --- a/src/sat/glucose/Vec.h +++ b/src/sat/glucose/Vec.h @@ -99,7 +99,7 @@ template void vec::capacity(int min_cap) { if (cap >= min_cap) return; int add = imax((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2 - if (add > INT_MAX - cap || (((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)) + if (add > INT_MAX - cap || (((data = (T*)::realloc((void*)data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)) #ifdef __wasm abort(); #else diff --git a/src/sat/glucose2/Vec.h b/src/sat/glucose2/Vec.h index bc9892177..ace47412e 100644 --- a/src/sat/glucose2/Vec.h +++ b/src/sat/glucose2/Vec.h @@ -101,7 +101,7 @@ template void vec::capacity(int min_cap) { if (cap >= min_cap) return; int add = imax((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2 - if (add > INT_MAX - cap || (((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)) + if (add > INT_MAX - cap || (((data = (T*)::realloc((void*)data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)) #ifdef __wasm abort(); #else @@ -112,7 +112,7 @@ void vec::capacity(int min_cap) { template void vec::prelocate(int ext_cap) { if (cap >= ext_cap) return; - if (ext_cap > INT_MAX || (((data = (T*)::realloc(data, ext_cap * sizeof(T))) == NULL) && errno == ENOMEM)) + if (ext_cap > INT_MAX || (((data = (T*)::realloc((void*)data, ext_cap * sizeof(T))) == NULL) && errno == ENOMEM)) #ifdef __wasm abort(); #else