diff options
Diffstat (limited to 'src')
97 files changed, 7920 insertions, 1062 deletions
diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index fcf6fd2..d637531 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -1191,7 +1191,7 @@ static inline int Gia_ObjCellId( Gia_Man_t * p, int iLit ) { re extern int Gia_FileSize( char * pFileName ); extern Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSimple, int fSkipStrash, int fCheck ); extern Gia_Man_t * Gia_AigerRead( char * pFileName, int fGiaSimple, int fSkipStrash, int fCheck ); -extern void Gia_AigerWrite( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact ); +extern void Gia_AigerWrite( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine ); extern void Gia_DumpAiger( Gia_Man_t * p, char * pFilePrefix, int iFileNum, int nFileNumDigits ); extern Vec_Str_t * Gia_AigerWriteIntoMemoryStr( Gia_Man_t * p ); extern Vec_Str_t * Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs ); diff --git a/src/aig/gia/giaAiger.c b/src/aig/gia/giaAiger.c index 97f40ae..03929af 100644 --- a/src/aig/gia/giaAiger.c +++ b/src/aig/gia/giaAiger.c @@ -1076,7 +1076,7 @@ Vec_Str_t * Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Ve SeeAlso [] ***********************************************************************/ -void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact ) +void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine ) { int fVerbose = XAIG_VERBOSE; FILE * pFile; @@ -1194,8 +1194,10 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int } // write the comment -// fprintf( pFile, "c\n" ); - fprintf( pFile, "c" ); + if ( fWriteNewLine ) + fprintf( pFile, "c\n" ); + else + fprintf( pFile, "c" ); // write additional AIG if ( p->pAigExtra ) @@ -1406,6 +1408,8 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fprintf( pFile, "%c", '\0' ); } // write comments + if ( fWriteNewLine ) + fprintf( pFile, "c\n" ); fprintf( pFile, "\nThis file was produced by the GIA package in ABC on %s\n", Gia_TimeStamp() ); fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); fclose( pFile ); @@ -1433,7 +1437,7 @@ void Gia_DumpAiger( Gia_Man_t * p, char * pFilePrefix, int iFileNum, int nFileNu { char Buffer[100]; sprintf( Buffer, "%s%0*d.aig", pFilePrefix, nFileNumDigits, iFileNum ); - Gia_AigerWrite( p, Buffer, 0, 0 ); + Gia_AigerWrite( p, Buffer, 0, 0, 0 ); } /**Function************************************************************* diff --git a/src/aig/gia/giaBalAig.c b/src/aig/gia/giaBalAig.c index 018bfca..a3a0719 100644 --- a/src/aig/gia/giaBalAig.c +++ b/src/aig/gia/giaBalAig.c @@ -399,6 +399,12 @@ Gia_Man_t * Gia_ManBalanceInt( Gia_Man_t * p, int fStrict ) Gia_ManForEachCiId( pNew, Id, i ) Vec_IntWriteEntry( pNew->vLevels, Id, Vec_IntEntry(p->vCiArrs, i)/And2Delay ); } + else if ( p->vInArrs ) + { + int Id, And2Delay = p->And2Delay ? p->And2Delay : 1; + Gia_ManForEachCiId( pNew, Id, i ) + Vec_IntWriteEntry( pNew->vLevels, Id, (int)(Vec_FltEntry(p->vInArrs, i)/And2Delay) ); + } // create internal nodes Gia_ManHashStart( pNew ); Gia_ManForEachBuf( p, pObj, i ) @@ -1051,6 +1057,12 @@ Gia_Man_t * Gia_ManAreaBalance( Gia_Man_t * p, int fSimpleAnd, int nNewNodesMax, Gia_ManForEachCiId( p, Id, i ) Vec_IntWriteEntry( p->vLevels, Id, Vec_IntEntry(p->vCiArrs, i)/And2Delay ); } + else if ( p->vInArrs ) + { + int i, Id, And2Delay = p->And2Delay ? p->And2Delay : 1; + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( p->vLevels, Id, (int)(Vec_FltEntry(p->vInArrs, i)/And2Delay) ); + } // determine CI levels if ( p->pManTime && p->vLevels == NULL ) Gia_ManLevelWithBoxes( p ); diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 01c01f3..923fbba 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -2815,6 +2815,30 @@ Gia_Man_t * Gia_ManDupAndOr( Gia_Man_t * p, int nOuts, int fUseOr, int fCompl ) /**Function************************************************************* + Synopsis [Transforms output names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_ManMiterNames( Vec_Ptr_t * p ) +{ + char * pName1, * pName2, pBuffer[1000]; int i; + Vec_Ptr_t * pNew = Vec_PtrAlloc( Vec_PtrSize(p)/2 ); + assert( Vec_PtrSize(p) % 2 == 0 ); + Vec_PtrForEachEntryDouble( char *, char *, p, pName1, pName2, i ) + { + sprintf( pBuffer, "%s_xor_%s", pName1, pName2 ); + Vec_PtrPush( pNew, Abc_UtilStrsav(pBuffer) ); + } + return pNew; +} + +/**Function************************************************************* + Synopsis [Transforms the circuit into a regular miter.] Description [] @@ -2851,6 +2875,10 @@ Gia_Man_t * Gia_ManTransformMiter( Gia_Man_t * p ) Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); + if ( p->vNamesIn ) + pNew->vNamesIn = Vec_PtrDupStr(p->vNamesIn); + if ( p->vNamesOut ) + pNew->vNamesOut = Gia_ManMiterNames(p->vNamesOut); return pNew; } Gia_Man_t * Gia_ManTransformMiter2( Gia_Man_t * p ) diff --git a/src/aig/gia/giaEquiv.c b/src/aig/gia/giaEquiv.c index 84d9f1b..2098768 100644 --- a/src/aig/gia/giaEquiv.c +++ b/src/aig/gia/giaEquiv.c @@ -1994,14 +1994,14 @@ int Gia_CommandSpecI( Gia_Man_t * pGia, int nFramesInit, int nBTLimitInit, int f } } // write equivalence classes - Gia_AigerWrite( pGia, "gore.aig", 0, 0 ); + Gia_AigerWrite( pGia, "gore.aig", 0, 0, 0 ); // reduce the model pReduce = Gia_ManSpecReduce( pGia, 0, 0, 1, 0, 0 ); if ( pReduce ) { pReduce = Gia_ManSeqStructSweep( pAux = pReduce, 1, 1, 0 ); Gia_ManStop( pAux ); - Gia_AigerWrite( pReduce, "gsrm.aig", 0, 0 ); + Gia_AigerWrite( pReduce, "gsrm.aig", 0, 0, 0 ); // Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", "gsrm.aig" ); // Gia_ManPrintStatsShort( pReduce ); Gia_ManStop( pReduce ); diff --git a/src/aig/gia/giaFalse.c b/src/aig/gia/giaFalse.c index a055b5b..50cb8ea 100644 --- a/src/aig/gia/giaFalse.c +++ b/src/aig/gia/giaFalse.c @@ -457,7 +457,7 @@ Gia_Man_t * Gia_ManCheckOne( Gia_Man_t * p, int iOut, int iObj, int nTimeOut, in if ( pNew ) { Gia_Man_t * pTemp = Gia_ManDupDfsNode( p, Gia_ManObj(p, iObj) ); - Gia_AigerWrite( pTemp, "false.aig", 0, 0 ); + Gia_AigerWrite( pTemp, "false.aig", 0, 0, 0 ); Abc_Print( 1, "Dumping cone with %d nodes into file \"%s\".\n", Gia_ManAndNum(pTemp), "false.aig" ); Gia_ManStop( pTemp ); } diff --git a/src/aig/gia/giaHcd.c b/src/aig/gia/giaHcd.c index 5d3e28f..8e8461e 100644 --- a/src/aig/gia/giaHcd.c +++ b/src/aig/gia/giaHcd.c @@ -626,7 +626,7 @@ Aig_Man_t * Hcd_ComputeChoices( Aig_Man_t * pAig, int nBTLimit, int fSynthesis, Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) Gia_ManStop( pGia ); - Gia_AigerWrite( pMiter, "m3.aig", 0, 0 ); + Gia_AigerWrite( pMiter, "m3.aig", 0, 0, 0 ); } else { diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c index 0c39cae..53e1953 100644 --- a/src/aig/gia/giaIf.c +++ b/src/aig/gia/giaIf.c @@ -2132,6 +2132,7 @@ void Gia_ManTransferTiming( Gia_Man_t * p, Gia_Man_t * pGia ) p->vOutReqs = pGia->vOutReqs; pGia->vOutReqs = NULL; p->DefInArrs = pGia->DefInArrs; p->DefOutReqs = pGia->DefOutReqs; + p->And2Delay = pGia->And2Delay; } if ( pGia->vNamesIn || pGia->vNamesOut ) { @@ -2231,7 +2232,7 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars ) { extern void Gia_ManIffTest( Gia_Man_t * pGia, If_LibLut_t * pLib, int fVerbose ); Gia_Man_t * pNew; - If_Man_t * pIfMan; int i, Entry; + If_Man_t * pIfMan; int i, Entry;//, Id, EntryF; assert( pPars->pTimesArr == NULL ); assert( pPars->pTimesReq == NULL ); if ( p->vCiArrs ) @@ -2241,6 +2242,15 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars ) Vec_IntForEachEntry( p->vCiArrs, Entry, i ) pPars->pTimesArr[i] = (float)Entry; } +/* // uncommenting this leads to a mysterious memory corruption + else if ( p->vInArrs ) + { + assert( Vec_FltSize(p->vInArrs) == Gia_ManCiNum(p) ); + pPars->pTimesArr = ABC_CALLOC( float, Gia_ManCiNum(p)); + Gia_ManForEachCiId( p, Id, i ) + pPars->pTimesArr[i] = Vec_FltEntry(p->vInArrs, i); + } +*/ if ( p->vCoReqs ) { assert( Vec_IntSize(p->vCoReqs) == Gia_ManCoNum(p) ); @@ -2248,6 +2258,15 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars ) Vec_IntForEachEntry( p->vCoReqs, Entry, i ) pPars->pTimesReq[i] = (float)Entry; } +/* // uncommenting this leads to a mysterious memory corruption + else if ( p->vOutReqs ) + { + assert( Vec_FltSize(p->vOutReqs) == Gia_ManCoNum(p) ); + pPars->pTimesReq = ABC_CALLOC( float, Gia_ManCoNum(p) ); + Vec_FltForEachEntry( p->vOutReqs, EntryF, i ) + pPars->pTimesReq[i] = EntryF; + } +*/ ABC_FREE( p->pCellStr ); Vec_IntFreeP( &p->vConfigs ); // disable cut minimization when GIA strucure is needed diff --git a/src/aig/gia/giaIso.c b/src/aig/gia/giaIso.c index 0e040b6..76419e9 100644 --- a/src/aig/gia/giaIso.c +++ b/src/aig/gia/giaIso.c @@ -1293,7 +1293,7 @@ void Gia_IsoTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose ) // create AIG with two primary outputs (original and permuted) pPerm = Gia_ManDupPerm( p, vPiPerm ); pDouble = Gia_ManDupAppendNew( p, pPerm ); -//Gia_AigerWrite( pDouble, "test.aig", 0, 0 ); +//Gia_AigerWrite( pDouble, "test.aig", 0, 0, 0 ); // analyze the two-output miter pAig = Gia_ManIsoReduce( pDouble, &vPosEquivs, &vPisPerm, 0, 0, 0, 0 ); diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index 53b686a..25355fe 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -241,10 +241,10 @@ void Gia_ManPrintClasses_old( Gia_Man_t * p ) { Gia_Man_t * pTemp; pTemp = Gia_ManDupFlopClass( p, 1 ); - Gia_AigerWrite( pTemp, "dom1.aig", 0, 0 ); + Gia_AigerWrite( pTemp, "dom1.aig", 0, 0, 0 ); Gia_ManStop( pTemp ); pTemp = Gia_ManDupFlopClass( p, 2 ); - Gia_AigerWrite( pTemp, "dom2.aig", 0, 0 ); + Gia_AigerWrite( pTemp, "dom2.aig", 0, 0, 0 ); Gia_ManStop( pTemp ); } } diff --git a/src/aig/gia/giaMini.c b/src/aig/gia/giaMini.c index 0ba2c4f..78d99ca 100644 --- a/src/aig/gia/giaMini.c +++ b/src/aig/gia/giaMini.c @@ -573,7 +573,7 @@ int * Abc_FrameReadMiniLutNameMapping( Abc_Frame_t * pAbc ) if ( pAbc->pGiaMiniAig == NULL || pAbc->pGiaMiniLut == NULL ) return NULL; pGia = Gia_ManDup2( pAbc->pGiaMiniAig, pAbc->pGiaMiniLut ); - //Gia_AigerWrite( pGia, "aig_m_lut.aig", 0, 0 ); + //Gia_AigerWrite( pGia, "aig_m_lut.aig", 0, 0, 0 ); // compute equivalences in this AIG pTemp = Gia_ManComputeGiaEquivs( pGia, nConfs, fVerbose ); Gia_ManStop( pTemp ); @@ -593,7 +593,14 @@ int * Abc_FrameReadMiniLutNameMapping( Abc_Frame_t * pAbc ) Synopsis [Returns equivalences of MiniAig nodes.] - Description [] + Description [The resulting array contains as many entries as there are objects + in the initial MiniAIG. If the i-th entry of the array is equal to -1, it means + that the i-th MiniAIG object is not equivalent to any other object. Otherwise, + the i-th entry contains the literal of the representative of the equivalence + class of objects, to which the i-th object belongs. The representative is defined + as the first object belonging to the equivalence class in the current topological + order. It can be the constant 0 node, a flop output or an internal node. It is + the user's responsibility to free the resulting array when it is not needed.] SideEffects [] @@ -658,6 +665,137 @@ int * Abc_FrameReadMiniAigEquivClasses( Abc_Frame_t * pAbc ) return pRes; } +/**Function************************************************************* + + Synopsis [Verifies equivalences of MiniAig nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_MiniAigReduce( Mini_Aig_t * p, int * pEquivs ) +{ + Gia_Man_t * pGia, * pTemp; + Vec_Int_t * vCopies; + int i, iGiaLit = 0, nNodes; + // get the number of nodes + nNodes = Mini_AigNodeNum(p); + // create ABC network + pGia = Gia_ManStart( nNodes ); + pGia->pName = Abc_UtilStrsav( "MiniAig" ); + // create mapping from MiniAIG objects into ABC objects + vCopies = Vec_IntAlloc( nNodes ); + Vec_IntPush( vCopies, 0 ); + // iterate through the objects + Gia_ManHashAlloc( pGia ); + for ( i = 1; i < nNodes; i++ ) + { + if ( Mini_AigNodeIsPi( p, i ) ) + iGiaLit = Gia_ManAppendCi(pGia); + else if ( Mini_AigNodeIsPo( p, i ) ) + iGiaLit = Gia_ManAppendCo(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i)); + else if ( Mini_AigNodeIsAnd( p, i ) ) + iGiaLit = Gia_ManHashAnd(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i), Gia_ObjFromMiniFanin1Copy(pGia, vCopies, p, i)); + else assert( 0 ); + if ( pEquivs[i] != -1 ) + iGiaLit = Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(pEquivs[i])), Abc_LitIsCompl(pEquivs[i]) ); + Vec_IntPush( vCopies, iGiaLit ); + } + Gia_ManHashStop( pGia ); + assert( Vec_IntSize(vCopies) == nNodes ); + Vec_IntFree( vCopies ); + Gia_ManSetRegNum( pGia, Mini_AigRegNum(p) ); + pGia = Gia_ManSeqCleanup( pTemp = pGia ); + Gia_ManStop( pTemp ); + return pGia; +} +Gia_Man_t * Gia_MiniAigMiter( Mini_Aig_t * p, int * pEquivs ) +{ + Gia_Man_t * pGia, * pTemp; + Vec_Int_t * vCopies; + int i, iGiaLit = 0, iGiaLit2, nNodes, iPos = 0, nPos = 0, Temp; + // get the number of nodes + nNodes = Mini_AigNodeNum(p); + // create ABC network + pGia = Gia_ManStart( 2 * nNodes ); + pGia->pName = Abc_UtilStrsav( "MiniAig" ); + // create mapping from MiniAIG objects into ABC objects + vCopies = Vec_IntAlloc( nNodes ); + Vec_IntPush( vCopies, 0 ); + // iterate through the objects + Gia_ManHashAlloc( pGia ); + for ( i = 1; i < nNodes; i++ ) + { + if ( Mini_AigNodeIsPi( p, i ) ) + iGiaLit = Gia_ManAppendCi(pGia); + else if ( Mini_AigNodeIsPo( p, i ) ) + { + nPos++; + Vec_IntPush( vCopies, -1 ); + continue; + } + else if ( Mini_AigNodeIsAnd( p, i ) ) + iGiaLit = Gia_ManHashAnd(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i), Gia_ObjFromMiniFanin1Copy(pGia, vCopies, p, i)); + else assert( 0 ); + Vec_IntPush( vCopies, iGiaLit ); + } + assert( Vec_IntSize(vCopies) == nNodes ); + assert( nPos > Mini_AigRegNum(p) ); + // create miters for each equiv class + for ( i = 1; i < nNodes; i++ ) + { + if ( pEquivs[i] == -1 ) + continue; + iGiaLit = Vec_IntEntry(vCopies, i); + iGiaLit2 = Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(pEquivs[i])), Abc_LitIsCompl(pEquivs[i]) ); + Gia_ManAppendCo( pGia, Gia_ManHashXor(pGia, iGiaLit, iGiaLit2) ); + } + // create flop inputs + Temp = Gia_ManCoNum(pGia); + for ( i = 1; i < nNodes; i++ ) + { + if ( !Mini_AigNodeIsPo( p, i ) ) + continue; + if ( iPos++ >= nPos - Mini_AigRegNum(p) ) + Gia_ManAppendCo(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i)); + } + assert( iPos == nPos ); + assert( Mini_AigRegNum(p) == Gia_ManCoNum(pGia) - Temp ); + Gia_ManSetRegNum( pGia, Mini_AigRegNum(p) ); + Gia_ManHashStop( pGia ); + Vec_IntFree( vCopies ); + pGia = Gia_ManCleanup( pTemp = pGia ); + Gia_ManStop( pTemp ); + return pGia; +} +void Gia_MiniAigVerify( Abc_Frame_t * pAbc, char * pFileName ) +{ + int * pEquivs; + Gia_Man_t * pGia; + char * pFileMiter = "mini_aig_miter.aig"; + char * pFileReduced = "mini_aig_reduced.aig"; + Mini_Aig_t * p = Mini_AigLoad( pFileName ); + Abc_FrameGiaInputMiniAig( pAbc, p ); + Cmd_CommandExecute( pAbc, "&ps; &scorr; &ps" ); + pEquivs = Abc_FrameReadMiniAigEquivClasses( pAbc ); + // dump miter for verification + pGia = Gia_MiniAigMiter( p, pEquivs ); + Gia_AigerWrite( pGia, pFileMiter, 0, 0, 0 ); + printf( "Dumped miter AIG in file \"%s\".\n", pFileMiter ); + Gia_ManStop( pGia ); + // dump reduced AIG + pGia = Gia_MiniAigReduce( p, pEquivs ); + Gia_AigerWrite( pGia, pFileReduced, 0, 0, 0 ); + printf( "Dumped reduced AIG in file \"%s\".\n", pFileReduced ); + Gia_ManStop( pGia ); + // cleanup + ABC_FREE( pEquivs ); + Mini_AigStop( p ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaSweeper.c b/src/aig/gia/giaSweeper.c index c1ce596..de3f404 100644 --- a/src/aig/gia/giaSweeper.c +++ b/src/aig/gia/giaSweeper.c @@ -439,7 +439,7 @@ void Gia_SweeperLogicDump( Gia_Man_t * p, Vec_Int_t * vProbeIds, int fDumpConds, Gia_ManStop( pGiaCond ); printf( " and conditions" ); } - Gia_AigerWrite( pGiaOuts, pFileName, 0, 0 ); + Gia_AigerWrite( pGiaOuts, pFileName, 0, 0, 0 ); Gia_ManStop( pGiaOuts ); printf( " into file \"%s\".\n", pFileName ); } diff --git a/src/aig/gia/giaTim.c b/src/aig/gia/giaTim.c index 2221279..e136f68 100644 --- a/src/aig/gia/giaTim.c +++ b/src/aig/gia/giaTim.c @@ -962,8 +962,8 @@ int Gia_ManVerifyWithBoxes( Gia_Man_t * pGia, int nBTLimit, int nTimeLim, int fS char * pNameGeneric = Extra_FileNameGeneric( pFileSpec ? pFileSpec : pGia->pSpec ); sprintf( pFileName0, "%s_spec.aig", pNameGeneric ); sprintf( pFileName1, "%s_impl.aig", pNameGeneric ); - Gia_AigerWrite( pGia0, pFileName0, 0, 0 ); - Gia_AigerWrite( pGia1, pFileName1, 0, 0 ); + Gia_AigerWrite( pGia0, pFileName0, 0, 0, 0 ); + Gia_AigerWrite( pGia1, pFileName1, 0, 0, 0 ); ABC_FREE( pNameGeneric ); printf( "Dumped two parts of the miter into files \"%s\" and \"%s\".\n", pFileName0, pFileName1 ); } diff --git a/src/aig/ivy/ivyFraig.c b/src/aig/ivy/ivyFraig.c index d9887d7..b51902b 100644 --- a/src/aig/ivy/ivyFraig.c +++ b/src/aig/ivy/ivyFraig.c @@ -1354,7 +1354,7 @@ int Ivy_FraigCheckOutputSims( Ivy_FraigMan_t * p ) // pObj = Ivy_ManPo( p->pManAig, 0 ); Ivy_ManForEachPo( p->pManAig, pObj, i ) { - assert( Ivy_ObjFanin0(pObj)->fPhase == (unsigned)Ivy_ObjFaninC0(pObj) ); // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) == 0 + //assert( Ivy_ObjFanin0(pObj)->fPhase == (unsigned)Ivy_ObjFaninC0(pObj) ); // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) == 0 // complement simulation info // if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) // Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) ); diff --git a/src/aig/miniaig/abcOper.h b/src/aig/miniaig/abcOper.h index 5719d88..6ee043a 100644 --- a/src/aig/miniaig/abcOper.h +++ b/src/aig/miniaig/abcOper.h @@ -60,7 +60,7 @@ typedef enum { ABC_OPER_BIT_NXOR, // 18 ABC_OPER_BIT_SHARP, // 19 ABC_OPER_BIT_SHARPL, // 20 - ABC_OPER_BIT_MUX, // 21 + ABC_OPER_BIT_MUX, // 21 fanins are: {Ctrl, Data1, Data0} ABC_OPER_BIT_MAJ, // 22 ABC_OPER_ABC, // 23 @@ -86,7 +86,7 @@ typedef enum { ABC_OPER_LOGIC_XOR, // 41 ABC_OPER_LOGIC_XNOR, // 42 - ABC_OPER_SEL_NMUX, // 43 + ABC_OPER_SEL_NMUX, // 43 fanins are: {Ctrl, Data0, Data1, Data2, ...} ABC_OPER_SEL_SEL, // 44 ABC_OPER_SEL_PSEL, // 45 ABC_OPER_SEL_ENC, // 46 @@ -217,11 +217,14 @@ static inline char * Abc_OperName( int Type ) if ( Type == ABC_OPER_SHIFT_ROTL ) return "rotL"; if ( Type == ABC_OPER_SHIFT_ROTR ) return "rotR"; + if ( Type == ABC_OPER_DFFRSE ) return "DFFRSE"; + if ( Type == ABC_OPER_SLICE ) return "[:]"; if ( Type == ABC_OPER_CONCAT ) return "{}"; if ( Type == ABC_OPER_ZEROPAD ) return "zPad"; if ( Type == ABC_OPER_SIGNEXT ) return "sExt"; + if ( Type == ABC_OPER_CONST ) return "const"; if ( Type == ABC_OPER_TABLE ) return "table"; if ( Type == ABC_OPER_LAST ) return NULL; assert( 0 ); diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 65461ab..dd189c6 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -657,6 +657,7 @@ extern ABC_DLL void Abc_ObjPatchFanoutFanin( Abc_Obj_t * pObj, int extern ABC_DLL Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ); extern ABC_DLL void Abc_ObjTransferFanout( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); extern ABC_DLL void Abc_ObjReplace( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); +extern ABC_DLL void Abc_ObjReplaceByConstant( Abc_Obj_t * pNode, int fConst1 ); extern ABC_DLL int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin ); /*=== abcFanOrder.c ==========================================================*/ extern ABC_DLL int Abc_NtkMakeLegit( Abc_Ntk_t * pNtk ); diff --git a/src/base/abc/abcFanio.c b/src/base/abc/abcFanio.c index caa57a4..519debb 100644 --- a/src/base/abc/abcFanio.c +++ b/src/base/abc/abcFanio.c @@ -337,6 +337,30 @@ void Abc_ObjReplace( Abc_Obj_t * pNodeOld, Abc_Obj_t * pNodeNew ) /**Function************************************************************* + Synopsis [Replaces a node by a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjReplaceByConstant( Abc_Obj_t * pNode, int fConst1 ) +{ + Abc_Obj_t * pNodeNew; + assert( Abc_NtkIsLogic(pNode->pNtk) ); + assert( !Abc_ObjIsCo(pNode) ); + pNodeNew = fConst1 ? Abc_NtkCreateNodeConst1(pNode->pNtk) : Abc_NtkCreateNodeConst0(pNode->pNtk); + // transfer the fanouts to the old node + Abc_ObjTransferFanout( pNode, pNodeNew ); + // remove the old node + if ( Abc_ObjIsNode(pNode) ) + Abc_NtkDeleteObj_rec( pNode, 1 ); +} + +/**Function************************************************************* + Synopsis [Returns the index of the fanin in the fanin list of the fanout.] Description [] diff --git a/src/base/abc/abcShow.c b/src/base/abc/abcShow.c index 13dd934..f91397d 100644 --- a/src/base/abc/abcShow.c +++ b/src/base/abc/abcShow.c @@ -85,12 +85,13 @@ void Abc_NodeShowBddOne( DdManager * dd, DdNode * bFunc ) SeeAlso [] ***********************************************************************/ -void Abc_NodeShowBdd( Abc_Obj_t * pNode ) +void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ) { FILE * pFile; Vec_Ptr_t * vNamesIn; char FileNameDot[200]; char * pNameOut; + DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; assert( Abc_NtkIsBddLogic(pNode->pNtk) ); // create the file name @@ -105,7 +106,14 @@ void Abc_NodeShowBdd( Abc_Obj_t * pNode ) // set the node names vNamesIn = Abc_NodeGetFaninNames( pNode ); pNameOut = Abc_ObjName(pNode); - Cudd_DumpDot( (DdManager *)pNode->pNtk->pManFunc, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); + if ( fCompl ) + Cudd_DumpDot( dd, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); + else + { + DdNode * bAdd = Cudd_BddToAdd( dd, (DdNode *)pNode->pData ); Cudd_Ref( bAdd ); + Cudd_DumpDot( dd, 1, (DdNode **)&bAdd, (char **)vNamesIn->pArray, &pNameOut, pFile ); + Cudd_RecursiveDeref( dd, bAdd ); + } Abc_NodeFreeNames( vNamesIn ); Abc_NtkCleanCopy( pNode->pNtk ); fclose( pFile ); @@ -113,9 +121,72 @@ void Abc_NodeShowBdd( Abc_Obj_t * pNode ) // visualize the file Abc_ShowFile( FileNameDot ); } +void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl ) +{ + char FileNameDot[200]; + char ** ppNamesIn, ** ppNamesOut; + DdManager * dd; DdNode * bFunc; + Vec_Ptr_t * vFuncsGlob; + Abc_Obj_t * pObj; int i; + FILE * pFile; + + assert( Abc_NtkIsStrash(pNtk) ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, 0, 0 ); + if ( dd == NULL ) + { + printf( "Construction of global BDDs has failed.\n" ); + return; + } + //printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); + + // create the file name + Abc_ShowGetFileName( pNtk->pName, FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + + // set the node names + ppNamesIn = Abc_NtkCollectCioNames( pNtk, 0 ); + ppNamesOut = Abc_NtkCollectCioNames( pNtk, 1 ); + if ( fCompl ) + Cudd_DumpDot( dd, Abc_NtkCoNum(pNtk), (DdNode **)Vec_PtrArray(vFuncsGlob), ppNamesIn, ppNamesOut, pFile ); + else + { + DdNode ** pbAdds = ABC_ALLOC( DdNode *, Vec_PtrSize(vFuncsGlob) ); + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + { pbAdds[i] = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( pbAdds[i] ); } + Cudd_DumpDot( dd, Abc_NtkCoNum(pNtk), pbAdds, ppNamesIn, ppNamesOut, pFile ); + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + Cudd_RecursiveDeref( dd, pbAdds[i] ); + ABC_FREE( pbAdds ); + } + ABC_FREE( ppNamesIn ); + ABC_FREE( ppNamesOut ); + fclose( pFile ); + + // cleanup + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vFuncsGlob ); + Extra_StopManager( dd ); + Abc_NtkCleanCopy( pNtk ); + + // visualize the file + Abc_ShowFile( FileNameDot ); +} #else -void Abc_NodeShowBdd( Abc_Obj_t * pNode ) {} +void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ) {} +void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl ) {} #endif /**Function************************************************************* diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index d652b9f..3a3ccac 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -186,6 +186,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_CommandCof ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTopmost ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTopAnd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTrim ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -317,6 +318,7 @@ static int Abc_CommandPermute ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandUnpermute ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCubeEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPathEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFunEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -879,8 +881,9 @@ 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", "cof", Abc_CommandCof, 1 ); Cmd_CommandAdd( pAbc, "Various", "topmost", Abc_CommandTopmost, 1 ); - Cmd_CommandAdd( pAbc, "Various", "topand", Abc_CommandTopAnd, 1 ); + Cmd_CommandAdd( pAbc, "Various", "topand", Abc_CommandTopAnd, 1 ); Cmd_CommandAdd( pAbc, "Various", "trim", Abc_CommandTrim, 1 ); Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 0 ); Cmd_CommandAdd( pAbc, "Various", "move_names", Abc_CommandMoveNames, 0 ); @@ -1005,6 +1008,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Sequential", "unpermute", Abc_CommandUnpermute, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "cubeenum", Abc_CommandCubeEnum, 0 ); Cmd_CommandAdd( pAbc, "Sequential", "pathenum", Abc_CommandPathEnum, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "funenum", Abc_CommandFunEnum, 0 ); Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 ); Cmd_CommandAdd( pAbc, "Verification", "dcec", Abc_CommandDCec, 0 ); @@ -3059,15 +3063,22 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; - int c; - extern void Abc_NodeShowBdd( Abc_Obj_t * pNode ); + int c, fCompl = 0, fGlobal = 0; + extern void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ); + extern void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl ); // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "cgh" ) ) != EOF ) { switch ( c ) { + case 'c': + fCompl ^= 1; + break; + case 'g': + fGlobal ^= 1; + break; case 'h': goto usage; default: @@ -3081,12 +3092,20 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } + if ( fGlobal ) + { + Abc_Ntk_t * pTemp = Abc_NtkIsStrash(pNtk) ? pNtk : Abc_NtkStrash(pNtk, 0, 0, 0); + Abc_NtkShowBdd( pTemp, fCompl ); + if ( pTemp != pNtk ) + Abc_NtkDelete( pTemp ); + return 0; + } + if ( !Abc_NtkIsBddLogic(pNtk) ) { Abc_Print( -1, "Visualizing BDDs can only be done for logic BDD networks (run \"bdd\").\n" ); return 1; } - if ( argc > globalUtilOptind + 1 ) { Abc_Print( -1, "Wrong number of auguments.\n" ); @@ -3110,17 +3129,20 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } } - Abc_NodeShowBdd( pNode ); + Abc_NodeShowBdd( pNode, fCompl ); return 0; usage: - Abc_Print( -2, "usage: show_bdd [-h] <node>\n" ); - Abc_Print( -2, " visualizes the BDD of a node using DOT and GSVIEW\n" ); + Abc_Print( -2, "usage: show_bdd [-cgh] <node>\n" ); + Abc_Print( -2, " uses DOT and GSVIEW to visualize the global BDDs of primary outputs\n" ); + Abc_Print( -2, " in terms of primary inputs or the local BDD of a node in terms of its fanins\n" ); #ifdef WIN32 Abc_Print( -2, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); Abc_Print( -2, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); #endif - Abc_Print( -2, "\t<node>: the node to consider [default = the driver of the first PO]\n"); + Abc_Print( -2, "\t<node>: (optional) the node to consider [default = the driver of the first PO]\n"); + Abc_Print( -2, "\t-c : toggle visualizing BDD with complemented edges [default = %s].\n", fCompl? "yes": "no" ); + Abc_Print( -2, "\t-g : toggle visualizing the global BDDs of primary outputs [default = %s].\n", fGlobal? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -8291,7 +8313,7 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INaogvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INTaogvh" ) ) != EOF ) { switch ( c ) { @@ -8317,6 +8339,17 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nNodes < 0 ) goto usage; break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + pPars->RuntimeLim = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->RuntimeLim < 0 ) + goto usage; + break; case 'a': pPars->fOnlyAnd ^= 1; break; @@ -8364,10 +8397,11 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: twoexact [-IN <num>] [-aogvh] <hex>\n" ); + Abc_Print( -2, "usage: twoexact [-INT <num>] [-aogvh] <hex>\n" ); Abc_Print( -2, "\t exact synthesis of multi-input function using two-input gates\n" ); Abc_Print( -2, "\t-I <num> : the number of input variables [default = %d]\n", pPars->nVars ); - Abc_Print( -2, "\t-N <num> : the number of MAJ3 nodes [default = %d]\n", pPars->nNodes ); + Abc_Print( -2, "\t-N <num> : the number of two-input nodes [default = %d]\n", pPars->nNodes ); + Abc_Print( -2, "\t-T <num> : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); Abc_Print( -2, "\t-a : toggle using only AND-gates (without XOR-gates) [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n", pPars->fGlucose ? "yes" : "no" ); @@ -8403,7 +8437,7 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INKiaogvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INKTiaogvh" ) ) != EOF ) { switch ( c ) { @@ -8440,6 +8474,17 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nLutSize < 0 ) goto usage; break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + pPars->RuntimeLim = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->RuntimeLim < 0 ) + goto usage; + break; case 'i': pPars->fUseIncr ^= 1; break; @@ -8495,11 +8540,12 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutexact [-INK <num>] [-iaogvh] <hex>\n" ); + Abc_Print( -2, "usage: lutexact [-INKT <num>] [-iaogvh] <hex>\n" ); Abc_Print( -2, "\t exact synthesis of I-input function using N K-input gates\n" ); Abc_Print( -2, "\t-I <num> : the number of input variables [default = %d]\n", pPars->nVars ); Abc_Print( -2, "\t-N <num> : the number of K-input nodes [default = %d]\n", pPars->nNodes ); Abc_Print( -2, "\t-K <num> : the number of node fanins [default = %d]\n", pPars->nLutSize ); + Abc_Print( -2, "\t-T <num> : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); Abc_Print( -2, "\t-i : toggle using incremental solving [default = %s]\n", pPars->fUseIncr ? "yes" : "no" ); Abc_Print( -2, "\t-a : toggle using only AND-gates when K = 2 [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); @@ -10681,7 +10727,7 @@ int Abc_CommandExpand( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_NtkDelete( pNtk2 ); // convert it into an AIG pGia = Abc_NtkClpGia( pStrash ); - //Gia_AigerWrite( pGia, "aig_dump.aig", 0, 0 ); + //Gia_AigerWrite( pGia, "aig_dump.aig", 0, 0, 0 ); Abc_NtkDelete( pStrash ); // get the new network Abc_NtkExpandCubes( pNtk, pGia, fVerbose ); @@ -10946,6 +10992,11 @@ int Abc_CommandReach( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Reachability analysis works only for AIGs (run \"strash\").\n" ); return 1; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } pAbc->Status = Abc_NtkDarReach( pNtk, pPars ); pAbc->nFrames = pPars->iFrame; Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); @@ -11197,6 +11248,81 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCof( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c, Const; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Currently can only be applied to a logic network.\n" ); + return 1; + } + + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + pNode = Abc_NtkFindCi( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Const = atoi( argv[globalUtilOptind+1] ); + if ( Const != 0 && Const != 1 ) + { + Abc_Print( -1, "Constant should be 0 or 1.\n", argv[globalUtilOptind+1] ); + return 1; + } + Abc_ObjReplaceByConstant( pNode, Const ); + return 0; + +usage: + Abc_Print( -2, "usage: cof [-h] <node> <const>\n" ); + Abc_Print( -2, "\t replaces one node in a logic network by constant 0 or 1\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t<node> : the node to replace\n"); + Abc_Print( -2, "\t<const> : the constant to replace the node with\n"); + Abc_Print( -2, "\tname : the node name\n"); + return 1; +} + /**Function************************************************************* @@ -13030,6 +13156,7 @@ int Abc_CommandTestColor( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Dau_NetworkEnumTest(); //Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int nCutMax = 1; int nLeafMax = 4; @@ -13188,7 +13315,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) */ { // extern void Abc_EnumerateFuncs( int nDecMax, int nDivMax, int fVerbose ); -// Abc_EnumerateFuncs( nDecMax, nDivMax, fVerbose ); +// Abc_EnumerateFuncs( 4, 7, 0 ); } /* if ( fNewAlgo ) @@ -13239,7 +13366,8 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) // Cba_PrsReadBlifTest(); } // Abc_NtkComputePaths( Abc_FrameReadNtk(pAbc) ); - Dau_NetworkEnumTest(); + //Dau_NetworkEnumTest(); + //Ext_TruthDiagnoseTest(); return 0; usage: Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] <file_name>\n" ); @@ -14991,6 +15119,7 @@ int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) Prove_Params_t Params, * pParams = &Params; Abc_Ntk_t * pNtk, * pNtkTemp; int c, RetValue, iOut = -1; + char * pLogFileName = NULL; abctime clk; extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ); @@ -15001,7 +15130,7 @@ int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) pParams->fUseRewriting = 1; pParams->fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NCFGLIrfbvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "NCFGMILrfbvh" ) ) != EOF ) { switch ( c ) { @@ -15049,10 +15178,10 @@ int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pParams->nFraigingLimitMulti < 0 ) goto usage; break; - case 'L': + case 'M': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } pParams->nMiteringLimitLast = atoi(argv[globalUtilOptind]); @@ -15071,6 +15200,15 @@ int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pParams->nTotalInspectLimit < 0 ) goto usage; break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); + goto usage; + } + pLogFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'r': pParams->fUseRewriting ^= 1; break; @@ -15144,17 +15282,20 @@ int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Cex_t * pCex = Abc_CexDeriveFromCombModel( pNtkTemp->pModel, Abc_NtkPiNum(pNtkTemp), 0, iOut ); Abc_FrameReplaceCex( pAbc, &pCex ); } + if ( pLogFileName ) + Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "iprove" ); return 0; usage: - Abc_Print( -2, "usage: iprove [-NCFGLI num] [-rfbvh]\n" ); + Abc_Print( -2, "usage: iprove [-NCFGMI num] [-L file] [-rfbvh]\n" ); Abc_Print( -2, "\t performs CEC using a new method\n" ); Abc_Print( -2, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax ); Abc_Print( -2, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart ); Abc_Print( -2, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart ); Abc_Print( -2, "\t-G num : multiplicative coefficient for fraiging [default = %d]\n", (int)pParams->nFraigingLimitMulti ); - Abc_Print( -2, "\t-L num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast ); + Abc_Print( -2, "\t-M num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast ); Abc_Print( -2, "\t-I num : max number of clause inspections in all SAT calls [default = %d]\n", (int)pParams->nTotalInspectLimit ); + Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-r : toggle the use of rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" ); Abc_Print( -2, "\t-f : toggle the use of FRAIGing [default = %s]\n", pParams->fUseFraiging? "yes": "no" ); Abc_Print( -2, "\t-b : toggle the use of BDDs [default = %s]\n", pParams->fUseBdds? "yes": "no" ); @@ -16716,7 +16857,7 @@ int Abc_CommandRecDump3( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 0, "No structure in the library.\n" ); return 1; } - Gia_AigerWrite( pGia, FileName, 0, 0 ); + Gia_AigerWrite( pGia, FileName, 0, 0, 0 ); } return 0; @@ -22972,6 +23113,126 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFunEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Dtt_EnumerateLf( int nVars, int nNodeMax, int fDelay, int fMulti, int fVerbose ); + extern void Dau_FunctionEnum( int nInputs, int nVars, int nNodeMax, int fUseTwo, int fReduce, int fVerbose ); + int c, nInputs = 4, nVars = 4, nNodeMax = 32, fUseTwo = 0, fReduce = 0, fSimple = 0, fDelay = 0, fMulti = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "SIMtrldmvh" ) ) != EOF ) + { + switch ( c ) + { + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + nInputs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInputs < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 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; + } + nNodeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodeMax < 0 ) + goto usage; + break; + case 't': + fUseTwo ^= 1; + break; + case 'r': + fReduce ^= 1; + break; + case 'l': + fSimple ^= 1; + break; + case 'd': + fDelay ^= 1; + break; + case 'm': + fMulti ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + Abc_Print( -2, "Unknown switch.\n"); + goto usage; + } + } + if ( fSimple || fDelay ) + { + if ( nVars < 3 || nVars > 5 ) + { + Abc_Print( -1, "The number of inputs should be 3 <= I <= 5.\n" ); + goto usage; + } + Dtt_EnumerateLf( nVars, nNodeMax, fDelay, fMulti, fVerbose ); + } + else + { + if ( nVars < 2 || nVars > 6 ) + { + Abc_Print( -1, "The number of inputs should be 2 <= I <= 6.\n" ); + goto usage; + } + if ( nInputs < nVars || nInputs > 6 ) + { + Abc_Print( -1, "The intermediate support size should be I <= S <= 6.\n" ); + goto usage; + } + Dau_FunctionEnum( nInputs, nVars, nNodeMax, fUseTwo, fReduce, fVerbose ); + } + return 0; + +usage: + Abc_Print( -2, "usage: funenum [-SIM num] [-trldmvh]\n" ); + Abc_Print( -2, "\t enumerates minimum 2-input-gate implementations\n" ); + Abc_Print( -2, "\t-S num : the maximum intermediate support size [default = %d]\n", nInputs ); + Abc_Print( -2, "\t-I num : the number of inputs of Boolean functions [default = %d]\n", nVars ); + Abc_Print( -2, "\t-M num : the maximum number of 2-input gates [default = %d]\n", nNodeMax ); + Abc_Print( -2, "\t-t : toggle adding combination of two gates [default = %s]\n", fUseTwo? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle reducing the last level [default = %s]\n", fReduce? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle generating L(f) rather than C(f) [default = %s]\n", fSimple? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle generating D(f) rather than C(f) [default = %s]\n", fDelay? "yes": "no" ); + Abc_Print( -2, "\t-m : toggle generating multiplicity statistics [default = %s]\n", fMulti? "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"); + return 1; +} + /**Function************************************************************* @@ -23645,12 +23906,16 @@ int Abc_CommandDProve( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Empty network.\n" ); return 1; } - if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" ); return 0; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } // perform verification pAbc->Status = Abc_NtkDarProve( pNtk, pSecPar, nBmcFramesMax, nBmcConfMax ); @@ -25349,6 +25614,11 @@ int Abc_CommandBmc( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Does not work for combinational networks.\n" ); return 0; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } pAbc->Status = Abc_NtkDarBmc( pNtk, 0, nFrames, nSizeMax, nNodeDelta, 0, nBTLimit, nBTLimitAll, fRewrite, fNewAlgo, 0, nCofFanLit, fVerbose, &iFrames, fUseSatoko ); pAbc->nFrames = iFrames; Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); @@ -25544,6 +25814,11 @@ int Abc_CommandBmc2( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Does not work for combinational networks.\n" ); return 0; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } pAbc->Status = Abc_NtkDarBmc( pNtk, nStart, nFrames, nSizeMax, nNodeDelta, nTimeOut, nBTLimit, nBTLimitAll, fRewrite, fNewAlgo, fOrDecomp, 0, fVerbose, &iFrames, fUseSatoko ); pAbc->nFrames = iFrames; Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); @@ -25798,6 +26073,11 @@ int Abc_CommandBmc3( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Constraints have to be folded (use \"fold\").\n" ); return 0; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } pPars->fUseBridge = pAbc->fBridgeMode; pAbc->Status = Abc_NtkDarBmc3( pNtk, pPars, fOrDecomp ); pAbc->nFrames = pNtk->vSeqModelVec ? -1 : pPars->iFrame; @@ -26004,6 +26284,11 @@ int Abc_CommandBmcInter( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); return 0; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( -1, "Does not work for combinational networks.\n" ); @@ -27049,6 +27334,11 @@ int Abc_CommandFold( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 0, "The network has no constraints.\n" ); return 0; } + if ( Abc_NtkConstrNum(pNtk) == Abc_NtkPoNum(pNtk) ) + { + Abc_Print( 0, "The network has no primary outputs (only constraints).\n" ); + return 0; + } if ( Abc_NtkIsComb(pNtk) ) Abc_Print( 0, "The network is combinational.\n" ); // modify the current network @@ -27532,11 +27822,12 @@ int Abc_CommandPdr( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_NtkDarPdr( Abc_Ntk_t * pNtk, Pdr_Par_t * pPars ); Pdr_Par_t Pars, * pPars = &Pars; - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkUsed, * pNtkFlop = NULL; + char * pLogFileName = NULL; int c; Pdr_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "MFCDQTHGSaxrmuyfqipdegjonctkvwzh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "MFCDQTHGSLaxrmuyfqipdegjonctkvwzh" ) ) != EOF ) { switch ( c ) { @@ -27639,6 +27930,15 @@ int Abc_CommandPdr( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nRandomSeed < 0 ) goto usage; break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); + goto usage; + } + pLogFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'a': pPars->fSolveAll ^= 1; break; @@ -27715,29 +28015,38 @@ int Abc_CommandPdr( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "There is no current network.\n"); return 0; } - if ( Abc_NtkLatchNum(pNtk) == 0 ) - { - Abc_Print( 0, "The current network is combinational.\n"); - return 0; - } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -2, "The current network is not an AIG (run \"strash\").\n"); return 0; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + pNtkFlop = Abc_NtkDup( pNtk ); + Abc_NtkAddLatch( pNtkFlop, Abc_AigConst1(pNtkFlop), ABC_INIT_ONE ); + } // run the procedure pPars->fUseBridge = pAbc->fBridgeMode; - pAbc->Status = Abc_NtkDarPdr( pNtk, pPars ); - pAbc->nFrames = pNtk->vSeqModelVec ? -1 : pPars->iFrame; + pNtkUsed = pNtkFlop ? pNtkFlop : pNtk; + pAbc->Status = Abc_NtkDarPdr( pNtkUsed, pPars ); + pAbc->nFrames = pNtkUsed->vSeqModelVec ? -1 : pPars->iFrame; Abc_FrameReplacePoStatuses( pAbc, &pPars->vOutMap ); - if ( pNtk->vSeqModelVec ) - Abc_FrameReplaceCexVec( pAbc, &pNtk->vSeqModelVec ); + if ( pNtkUsed->vSeqModelVec ) + Abc_FrameReplaceCexVec( pAbc, &pNtkUsed->vSeqModelVec ); else - Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); + Abc_FrameReplaceCex( pAbc, &pNtkUsed->pSeqModel ); + if ( pNtkFlop ) Abc_NtkDelete( pNtkFlop ); + if ( pLogFileName ) + Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "pdr" ); return 0; usage: - Abc_Print( -2, "usage: pdr [-MFCDQTHGS <num>] [-axrmuyfqipdegjonctkvwzh]\n" ); + Abc_Print( -2, "usage: pdr [-MFCDQTHGS <num>] [-L <file>] [-axrmuyfqipdegjonctkvwzh]\n" ); Abc_Print( -2, "\t model checking using property directed reachability (aka IC3)\n" ); Abc_Print( -2, "\t pioneered by Aaron R. Bradley (http://theory.stanford.edu/~arbrad/)\n" ); Abc_Print( -2, "\t with improvements by Niklas Een (http://een.se/niklas/)\n" ); @@ -27750,6 +28059,7 @@ usage: Abc_Print( -2, "\t-H num : runtime limit per output, in miliseconds (with \"-a\") [default = %d]\n", pPars->nTimeOutOne ); Abc_Print( -2, "\t-G num : runtime gap since the last CEX (0 = no limit) [default = %d]\n", pPars->nTimeOutGap ); Abc_Print( -2, "\t-S num : * value to seed the SAT solver with [default = %d]\n", pPars->nRandomSeed ); + Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-a : toggle solving all outputs even if one of them is SAT [default = %s]\n", pPars->fSolveAll? "yes": "no" ); Abc_Print( -2, "\t-x : toggle storing CEXes when solving all outputs [default = %s]\n", pPars->fStoreCex? "yes": "no" ); Abc_Print( -2, "\t-r : toggle using more effort in generalization [default = %s]\n", pPars->fTwoRounds? "yes": "no" ); @@ -29192,6 +29502,7 @@ int Abc_CommandAbc9Get( Abc_Frame_t * pAbc, int argc, char ** argv ) pGia->DefOutReqs = Abc_NtkReadDefaultRequiredWorst(pNtk); pGia->vInArrs = Vec_FltAllocArray( Abc_NtkGetCiArrivalFloats(pNtk), Abc_NtkCiNum(pNtk) ); pGia->vOutReqs = Vec_FltAllocArray( Abc_NtkGetCoRequiredFloats(pNtk), Abc_NtkCoNum(pNtk) ); + pGia->And2Delay = pNtk->AndGateDelay; } Abc_FrameUpdateGia( pAbc, pGia ); return 0; @@ -29759,9 +30070,10 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) int fVerilog = 0; int fMiniAig = 0; int fMiniLut = 0; + int fWriteNewLine = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "upmlvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "upmlcvh" ) ) != EOF ) { switch ( c ) { @@ -29777,6 +30089,9 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'l': fMiniLut ^= 1; break; + case 'c': + fWriteNewLine ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -29812,16 +30127,17 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) else if ( fMiniLut ) Gia_ManWriteMiniLut( pAbc->pGia, pFileName ); else - Gia_AigerWrite( pAbc->pGia, pFileName, 0, 0 ); + Gia_AigerWrite( pAbc->pGia, pFileName, 0, 0, fWriteNewLine ); return 0; usage: - Abc_Print( -2, "usage: &w [-upmlvh] <file>\n" ); + Abc_Print( -2, "usage: &w [-upmlcvh] <file>\n" ); Abc_Print( -2, "\t writes the current AIG into the AIGER file\n" ); Abc_Print( -2, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); Abc_Print( -2, "\t-p : toggle writing Verilog with 'and' and 'not' [default = %s]\n", fVerilog? "yes" : "no" ); Abc_Print( -2, "\t-m : toggle writing MiniAIG rather than AIGER [default = %s]\n", fMiniAig? "yes" : "no" ); Abc_Print( -2, "\t-l : toggle writing MiniLUT rather than AIGER [default = %s]\n", fMiniLut? "yes" : "no" ); + Abc_Print( -2, "\t-c : toggle writing \'\\n\' after \'c\' in the AIGER file [default = %s]\n", fWriteNewLine? "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"); Abc_Print( -2, "\t<file> : the file name\n"); @@ -34399,7 +34715,7 @@ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) pTemp = Gia_ManSeqStructSweep( pAux = pTemp, 1, 1, 0 ); Gia_ManStop( pAux ); } - Gia_AigerWrite( pTemp, pFileNameIn ? pFileNameIn : pFileName, 0, 0 ); + Gia_AigerWrite( pTemp, pFileNameIn ? pFileNameIn : pFileName, 0, 0, 0 ); Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", pFileName ); Gia_ManPrintStatsShort( pTemp ); Gia_ManStop( pTemp ); @@ -34412,7 +34728,7 @@ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) pTemp = Gia_ManSeqStructSweep( pAux = pTemp, 1, 1, 0 ); Gia_ManStop( pAux ); - Gia_AigerWrite( pTemp, pFileName2, 0, 0 ); + Gia_AigerWrite( pTemp, pFileName2, 0, 0, 0 ); Abc_Print( 1, "Reduced original network was written into file \"%s\".\n", pFileName2 ); Gia_ManPrintStatsShort( pTemp ); Gia_ManStop( pTemp ); @@ -34513,7 +34829,7 @@ int Abc_CommandAbc9Srm2( Abc_Frame_t * pAbc, int argc, char ** argv ) pTemp = Gia_ManSeqStructSweep( pAux = pTemp, 1, 1, 0 ); Gia_ManStop( pAux ); - Gia_AigerWrite( pTemp, pFileName, 0, 0 ); + Gia_AigerWrite( pTemp, pFileName, 0, 0, 0 ); Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", pFileName ); Gia_ManPrintStatsShort( pTemp ); Gia_ManStop( pTemp ); @@ -34970,7 +35286,7 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fDumpMiter ) { Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" ); - Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0 ); + Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 ); } pAbc->Status = Cec_ManVerify( pMiter, pPars ); Abc_FrameReplaceCex( pAbc, &pGias[0]->pCexComb ); @@ -40227,7 +40543,7 @@ int Abc_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pOne = Gia_ManDupDfsCone( pAbc->pGia, pObj ); sprintf( Buffer, "%s_%0*d.aig", Extra_FileNameGeneric(pAbc->pGia->pSpec), nDigits, i ); - Gia_AigerWrite( pOne, Buffer, 0, 0 ); + Gia_AigerWrite( pOne, Buffer, 0, 0, 0 ); Gia_ManStop( pOne ); } printf( "Dumped all outputs into individual AIGER files.\n" ); @@ -41513,7 +41829,7 @@ int Abc_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; Gia_ParFfSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ATNKSGkbsfdeunvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ATNKSGkbsfcdeunvh" ) ) != EOF ) { switch ( c ) { @@ -41591,6 +41907,9 @@ int Abc_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'f': pPars->fFfOnly ^= 1; break; + case 'c': + pPars->fCheckUntest ^= 1; + break; case 'd': pPars->fDump ^= 1; break; @@ -41681,7 +42000,7 @@ int Abc_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &fftest [-ATNK num] [-kbsfdeunvh] <file> [-G file] [-S str]\n" ); + Abc_Print( -2, "usage: &fftest [-ATNK num] [-kbsfcdeunvh] <file> [-G file] [-S str]\n" ); Abc_Print( -2, "\t performs functional fault test generation\n" ); Abc_Print( -2, "\t-A num : selects fault model for all gates [default = %d]\n", pPars->Algo ); Abc_Print( -2, "\t 0: fault model is not selected (use -S str)\n" ); @@ -41696,9 +42015,10 @@ usage: Abc_Print( -2, "\t-b : toggles testing for single faults (the same as \"-K 1\") [default = %s]\n", pPars->fBasic? "yes": "no" ); Abc_Print( -2, "\t-s : toggles starting with the all-0 and all-1 patterns [default = %s]\n", pPars->fStartPats? "yes": "no" ); Abc_Print( -2, "\t-f : toggles faults at flop inputs only with \"-A 1\" and \"-S str\" [default = %s]\n", pPars->fFfOnly? "yes": "no" ); - Abc_Print( -2, "\t-d : toggles dumping test patterns into file \"tests.txt\" [default = %s]\n", pPars->fDump? "yes": "no" ); + Abc_Print( -2, "\t-c : toggles checking if there are untestable faults [default = %s]\n", pPars->fCheckUntest? "yes": "no" ); + Abc_Print( -2, "\t-d : toggles dumping test patterns into file \"<file>_tests.txt\" [default = %s]\n", pPars->fDump? "yes": "no" ); Abc_Print( -2, "\t-e : toggles dumping test pattern pairs (delay faults only) [default = %s]\n", pPars->fDumpDelay? "yes": "no" ); - Abc_Print( -2, "\t-u : toggles dumping untestable faults into \"untest.txt\" [default = %s]\n", pPars->fDumpUntest? "yes": "no" ); + Abc_Print( -2, "\t-u : toggles dumping untestable faults into \"<file>_untest.txt\" [default = %s]\n", pPars->fDumpUntest? "yes": "no" ); Abc_Print( -2, "\t-n : toggles dumping faults not detected by a given test set [default = %s]\n", pPars->fDumpNewFaults? "yes": "no" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -42614,8 +42934,8 @@ int Abc_CommandAbc9Demiter( Abc_Frame_t * pAbc, int argc, char ** argv ) sprintf( pName1, "%s_2.aig", pGen ); ABC_FREE( pGen ); } - Gia_AigerWrite( pPart1, pName0, 0, 0 ); - Gia_AigerWrite( pPart2, pName1, 0, 0 ); + Gia_AigerWrite( pPart1, pName0, 0, 0, 0 ); + Gia_AigerWrite( pPart2, pName1, 0, 0, 0 ); Gia_ManStop( pPart1 ); Gia_ManStop( pPart2 ); if ( fDumpFilesTwo ) @@ -43333,10 +43653,16 @@ usage: int Abc_CommandAbc9Exorcism( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_ExorcismMain( Vec_Wec_t * vEsop, int nIns, int nOuts, char * pFileNameOut, int Quality, int Verbosity, int nCubesMax, int fUseQCost ); + extern Vec_Wec_t * Abc_ExorcismNtk2Esop( Abc_Ntk_t * pNtk ); + extern Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose, Vec_Wec_t ** pvRes ); Vec_Wec_t * vEsop = NULL; + Abc_Ntk_t * pNtk = NULL; + char * pFileNameIn = NULL; char * pFileNameOut = NULL; int c, Quality = 2, Verbosity = 0, nCubesMax = 20000, fUseQCost = 0, fVerbose = 0; + int nInputs = -1, nOutputs = -1; + Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "QVCqvh" ) ) != EOF ) { @@ -43387,30 +43713,72 @@ int Abc_CommandAbc9Exorcism( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( pAbc->pGia == NULL ) + + if ( argc == globalUtilOptind + 2 ) { - Abc_Print( -1, "Abc_CommandAbc9Exorcism(): There is no AIG.\n" ); - return 0; + pFileNameIn = argv[globalUtilOptind]; + pFileNameOut = argv[globalUtilOptind + 1]; } - // get the output file name - if ( argc == globalUtilOptind + 1 ) + else if ( argc == globalUtilOptind + 1 ) + { pFileNameOut = argv[globalUtilOptind]; - // generate starting cover and run minimization - Eso_ManCompute( pAbc->pGia, fVerbose, &vEsop ); - Abc_ExorcismMain( vEsop, Gia_ManCiNum(pAbc->pGia), Gia_ManCoNum(pAbc->pGia), pFileNameOut, Quality, Verbosity, nCubesMax, fUseQCost ); - Vec_WecFree( vEsop ); - return 0; - -usage: - Abc_Print( -2, "usage: &exorcism [-Q N] [-V N] [-C N] -q <file>\n" ); - Abc_Print( -2, " performs heuristic exclusive sum-of-project minimization\n" ); - Abc_Print( -2, " -Q N : minimization quality [default = %d]\n", Quality); - Abc_Print( -2, " increasing this number improves quality and adds to runtime\n"); - Abc_Print( -2, " -V N : verbosity level [default = %d]\n", Verbosity); - Abc_Print( -2, " 0 = no output; 1 = outline; 2 = verbose\n"); - Abc_Print( -2, " -C N : maximum number of cubes in startign cover [default = %d]\n", nCubesMax ); - Abc_Print( -2, " -q : toggle using quantum cost [default = %s]\n", fUseQCost? "yes": "no" ); - Abc_Print( -2, " <file>: the output file name in ESOP-PLA format\n"); + } + else + { + Abc_Print( -1, "Abc_CommandAbc9Exorcism(): Argument error.\n" ); + goto usage; + } + + if ( pAbc->pGia == NULL && pFileNameIn == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Exorcism(): There is neither an AIG nor an ESOP-PLA file.\n" ); + return 0; + } + + if ( pFileNameIn ) + { + pNtk = Io_ReadPla( pFileNameIn, 0, 0, 0, /* no preprocessing = */1, /* check = */1 ); + if ( pNtk == NULL ) + { + printf( "Reading PLA file has failed.\n" ); + return 1; + } + nInputs = Abc_NtkCiNum( pNtk ); + nOutputs = Abc_NtkCoNum( pNtk ); + vEsop = Abc_ExorcismNtk2Esop( pNtk ); + if ( vEsop == NULL ) + { + printf( "Converting PLA to ESOP failed.\n" ); + return 1; + } + } + else if ( pAbc->pGia ) + { + // generate starting cover + nInputs = Gia_ManCiNum( pAbc->pGia ); + nOutputs = Gia_ManCoNum( pAbc->pGia ); + Eso_ManCompute( pAbc->pGia, fVerbose, &vEsop ); + } + + if ( vEsop ) + { + // run minimization + Abc_ExorcismMain( vEsop, nInputs, nOutputs, pFileNameOut, Quality, Verbosity, nCubesMax, fUseQCost ); + Vec_WecFree( vEsop ); + } + return 0; + +usage: + Abc_Print( -2, "usage: &exorcism [-Q N] [-V N] [-C N] -q [file_in] <file_out>\n" ); + Abc_Print( -2, " performs heuristic exclusive sum-of-project minimization\n" ); + Abc_Print( -2, " -Q N : minimization quality [default = %d]\n", Quality); + Abc_Print( -2, " increasing this number improves quality and adds to runtime\n"); + Abc_Print( -2, " -V N : verbosity level [default = %d]\n", Verbosity); + Abc_Print( -2, " 0 = no output; 1 = outline; 2 = verbose\n"); + Abc_Print( -2, " -C N : maximum number of cubes in startign cover [default = %d]\n", nCubesMax ); + Abc_Print( -2, " -q : toggle using quantum cost [default = %s]\n", fUseQCost? "yes": "no" ); + Abc_Print( -2, " [file_in] : optional input file in ESOP-PLA format (otherwise current AIG is used)\n"); + Abc_Print( -2, " <file_out> : output file in ESOP-PLA format\n"); Abc_Print( -2, "\n" ); return 1; } @@ -43556,6 +43924,16 @@ int Abc_CommandAbc9Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Mfs(): The current AIG has no mapping.\n" ); return 0; } + if ( Gia_ManLutSizeMax(pAbc->pGia) > 6 ) + { + Abc_Print( -1, "Abc_CommandAbc9Mfs(): The current mapping has nodes with more than 6 inputs. Cannot use \"mfs\".\n" ); + return 0; + } + if ( pAbc->pGia->pAigExtra && Gia_ManPiNum(pAbc->pGia->pAigExtra) > 6 ) + { + Abc_Print( -1, "Abc_CommandAbc9Mfs(): The current white-boxes have more than 6 inputs. Cannot use \"mfs\".\n" ); + return 0; + } pTemp = Gia_ManPerformMfs( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; @@ -43573,7 +43951,7 @@ usage: Abc_Print( -2, "\t-d : toggle performing redundancy removal [default = %s]\n", pPars->fRrOnly? "yes": "no" ); Abc_Print( -2, "\t-a : toggle minimizing area or area+edges [default = %s]\n", pPars->fArea? "area": "area+edges" ); Abc_Print( -2, "\t-e : toggle high-effort resubstitution [default = %s]\n", pPars->fMoreEffort? "yes": "no" ); - Abc_Print( -2, "\t-b : toggle preserving all while boxes [default = %s]\n", pPars->fAllBoxes? "yes": "no" ); + Abc_Print( -2, "\t-b : toggle preserving all white boxes [default = %s]\n", pPars->fAllBoxes? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -44134,6 +44512,11 @@ int Abc_CommandAbc9GlaDerive( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } */ + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } if ( pAbc->pGia->vGateClasses == NULL ) { Abc_Print( -1, "Abstraction gate map is missing.\n" ); diff --git a/src/base/abci/abcDarUnfold2.c b/src/base/abci/abcDarUnfold2.c index 7ebc316..08dca0b 100644 --- a/src/base/abci/abcDarUnfold2.c +++ b/src/base/abci/abcDarUnfold2.c @@ -13,7 +13,7 @@ Abc_Ntk_t * Abc_NtkDarFold2( Abc_Ntk_t * pNtk, int fCompl, int fVerbose , int); Abc_Ntk_t * Abc_NtkDarUnfold2( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose ) { Abc_Ntk_t * pNtkAig; - Aig_Man_t * pMan, * pTemp; + Aig_Man_t * pMan, * pTemp = NULL; int typeII_cnt = 0; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); diff --git a/src/base/abci/abcDetect.c b/src/base/abci/abcDetect.c index 7adbed5..089d3fe 100644 --- a/src/base/abci/abcDetect.c +++ b/src/base/abci/abcDetect.c @@ -914,7 +914,7 @@ Vec_Int_t * Abc_NtkFinCheckPair( Abc_Ntk_t * pNtk, Vec_Int_t * vTypes, Vec_Int_t int i, nConfLimit = 10000; Vec_Int_t * vPat = NULL; int status, iVarBeg = pCnf->nVars - Gia_ManPiNum(pGia);// - 1; - //Gia_AigerWrite( pGia, "temp_detect.aig", 0, 0 ); + //Gia_AigerWrite( pGia, "temp_detect.aig", 0, 0, 0 ); Gia_ManStop( pGia ); Cnf_DataFree( pCnf ); status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); diff --git a/src/base/abci/abcIvy.c b/src/base/abci/abcIvy.c index e4a5d3b..5dc125d 100644 --- a/src/base/abci/abcIvy.c +++ b/src/base/abci/abcIvy.c @@ -482,6 +482,7 @@ Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, in } else pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + pNtkAig->pModel = (int *)pMan->pData; pMan->pData = NULL; Ivy_ManStop( pTemp ); Ivy_ManStop( pMan ); return pNtkAig; diff --git a/src/base/abci/abcLog.c b/src/base/abci/abcLog.c index e0ad3cc..31cf5a9 100644 --- a/src/base/abci/abcLog.c +++ b/src/base/abci/abcLog.c @@ -227,7 +227,16 @@ int Abc_NtkReadLogFile( char * pFileName, Abc_Cex_t ** ppCex, int * pnFrames ) ABC_FREE( pCex ); } else - Vec_IntFree( vNums ); + { + // corner case of seq circuit with no PIs + int iFrameCex = (nFrames2 == -1) ? nFrames : nFrames2; + pCex = Abc_CexAlloc( 0, 0, iFrameCex + 1 ); + pCex->iFrame = iFrameCex; + pCex->iPo = iPo; + if ( ppCex ) + *ppCex = pCex; + Vec_IntFree( vNums ); + } if ( pnFrames ) *pnFrames = nFrames; return Status; diff --git a/src/base/abci/abcNpn.c b/src/base/abci/abcNpn.c index d2d0692..744b644 100644 --- a/src/base/abci/abcNpn.c +++ b/src/base/abci/abcNpn.c @@ -295,10 +295,6 @@ void Abc_TruthNpnPerform( Abc_TtStore_t * p, int NpnType, int fVerbose ) } else if ( NpnType == 7 ) { - extern unsigned Abc_TtCanonicizeHie(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int fExact ); - extern Abc_TtHieMan_t * Abc_TtHieManStart( int nVars, int nLevels ); - extern void Abc_TtHieManStop(Abc_TtHieMan_t * p ); - int fExact = 0; Abc_TtHieMan_t * pMan = Abc_TtHieManStart( p->nVars, 5 ); for ( i = 0; i < p->nFuncs; i++ ) @@ -318,8 +314,6 @@ void Abc_TruthNpnPerform( Abc_TtStore_t * p, int NpnType, int fVerbose ) typedef unsigned(*TtCanonicizeFunc)(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag); unsigned Abc_TtCanonicizeWrap(TtCanonicizeFunc func, Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag); unsigned Abc_TtCanonicizeAda(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int iThres); - Abc_TtHieMan_t * Abc_TtHieManStart(int nVars, int nLevels); - void Abc_TtHieManStop(Abc_TtHieMan_t * p); int fHigh = 1, iEnumThres = 25; Abc_TtHieMan_t * pMan = Abc_TtHieManStart(p->nVars, 5); diff --git a/src/base/abci/abcRec3.c b/src/base/abci/abcRec3.c index 43da483..3e5f29a 100644 --- a/src/base/abci/abcRec3.c +++ b/src/base/abci/abcRec3.c @@ -1106,7 +1106,7 @@ int Abc_RecToGia3( Gia_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Int { Lms_Man_t * p = s_pMan3; char pCanonPerm[LMS_VAR_MAX]; - unsigned uCanonPhase; + unsigned uCanonPhase = 0; int iFan0, iFan1, iGiaObj; Gia_Man_t * pGia = p->pGia; Gia_Obj_t * pGiaPo, * pGiaTemp = NULL; diff --git a/src/base/abci/abcTim.c b/src/base/abci/abcTim.c index 3f68b81..c850cc5 100644 --- a/src/base/abci/abcTim.c +++ b/src/base/abci/abcTim.c @@ -170,7 +170,7 @@ void Abc_NtkTestPinGia( Abc_Ntk_t * pNtk, int fWhiteBoxOnly, int fVerbose ) Gia_Man_t * pGia; char * pFileName = "testpin.aig"; pGia = Abc_NtkTestPinDeriveGia( pNtk, fWhiteBoxOnly, fVerbose ); - Gia_AigerWrite( pGia, pFileName, 0, 0 ); + Gia_AigerWrite( pGia, pFileName, 0, 0, 0 ); Gia_ManStop( pGia ); printf( "AIG with pins derived from mapped network \"%s\" was written into file \"%s\".\n", Abc_NtkName(pNtk), pFileName ); @@ -391,7 +391,7 @@ Gia_Man_t * Abc_NtkTestTimDeriveGia( Abc_Ntk_t * pNtk, int fVerbose ) Vec_FltFree( vArrTimes ); Vec_FltFree( vReqTimes ); -Gia_AigerWrite( pHoles, "holes00.aig", 0, 0 ); +Gia_AigerWrite( pHoles, "holes00.aig", 0, 0, 0 ); // return pGia->pAigExtra = pHoles; @@ -560,7 +560,7 @@ void Abc_NtkTestTimByWritingFile( Gia_Man_t * pGia, char * pFileName ) Gia_ManReverseClasses( pGia, 0 ); } // write file - Gia_AigerWrite( pGia, pFileName, 0, 0 ); + Gia_AigerWrite( pGia, pFileName, 0, 0, 0 ); // unnormalize choices if ( Gia_ManHasChoices(pGia) ) Gia_ManReverseClasses( pGia, 1 ); diff --git a/src/base/acb/acbCom.c b/src/base/acb/acbCom.c index c2eae92..3d62454 100644 --- a/src/base/acb/acbCom.c +++ b/src/base/acb/acbCom.c @@ -664,7 +664,7 @@ int Acb_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fDumpMiter ) { Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" ); - Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0 ); + Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 ); } pAbc->Status = Cec_ManVerify( pMiter, pPars ); //Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb ); diff --git a/src/base/acb/acbFunc.c b/src/base/acb/acbFunc.c index d73d1d5..f6fcf2b 100644 --- a/src/base/acb/acbFunc.c +++ b/src/base/acb/acbFunc.c @@ -198,7 +198,7 @@ int Acb_WireIsTarget( int Token, Abc_Nam_t * pNames ) } void * Acb_VerilogSimpleParse( Vec_Int_t * vBuffer, Abc_Nam_t * pNames ) { - void * pDesign = NULL; + Ndr_Data_t * pDesign = NULL; Vec_Int_t * vInputs = Vec_IntAlloc(100); Vec_Int_t * vOutputs = Vec_IntAlloc(100); Vec_Int_t * vWires = Vec_IntAlloc(100); @@ -2036,14 +2036,14 @@ Cnf_Dat_t * Acb_NtkEcoCompute( Gia_Man_t * p, int iTar, int nTars ) Gia_ManStop( p ); pCof1 = Acb_NtkEcoSynthesize( p = pCof1 ); Gia_ManStop( p ); - Gia_AigerWrite( pCof0, "eco_qbf0.aig", 0, 0 ); - Gia_AigerWrite( pCof1, "eco_qbf1.aig", 0, 0 ); + Gia_AigerWrite( pCof0, "eco_qbf0.aig", 0, 0, 0 ); + Gia_AigerWrite( pCof1, "eco_qbf1.aig", 0, 0, 0 ); Gia_ManStop( pCof0 ); Gia_ManStop( pCof1 ); printf( "Dumped cof0 into file \"%s\".\n", "eco_qbf0.aig" ); printf( "Dumped cof1 into file \"%s\".\n", "eco_qbf1.aig" ); } -// Gia_AigerWrite( pCof, "eco_qbf.aig", 0, 0 ); +// Gia_AigerWrite( pCof, "eco_qbf.aig", 0, 0, 0 ); // printf( "Dumped the result of quantification into file \"%s\".\n", "eco_qbf.aig" ); pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pCof, 8, 0, 0, 0, 0 ); Gia_ManStop( pCof ); @@ -2445,7 +2445,7 @@ int Acb_NtkEcoPerform( Acb_Ntk_t * pNtkF, Acb_Ntk_t * pNtkG, char * pFileNameF, // generate output files Acb_GenerateFilePatch( vPatch, "patch.v" ); Acb_GenerateFileOut( vInst, pFileNameF, "out.v", vPatch ); - //Gia_AigerWrite( pGiaG, "test.aig", 0, 0 ); + //Gia_AigerWrite( pGiaG, "test.aig", 0, 0, 0 ); cleanup: // cleanup if ( vGias ) diff --git a/src/base/bac/bacCom.c b/src/base/bac/bacCom.c index e7d94d5..f1e3be5 100644 --- a/src/base/bac/bacCom.c +++ b/src/base/bac/bacCom.c @@ -651,7 +651,7 @@ int Bac_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fDumpMiter ) { Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" ); - Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0 ); + Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 ); } pAbc->Status = Cec_ManVerify( pMiter, pPars ); //Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb ); diff --git a/src/base/cba/cbaCom.c b/src/base/cba/cbaCom.c index b6a8c80..fa13030 100644 --- a/src/base/cba/cbaCom.c +++ b/src/base/cba/cbaCom.c @@ -662,7 +662,7 @@ int Cba_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fDumpMiter ) { Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" ); - Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0 ); + Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 ); } pAbc->Status = Cec_ManVerify( pMiter, pPars ); //Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb ); diff --git a/src/base/cmd/cmdPlugin.c b/src/base/cmd/cmdPlugin.c index ab517ed..efee671 100644 --- a/src/base/cmd/cmdPlugin.c +++ b/src/base/cmd/cmdPlugin.c @@ -502,7 +502,7 @@ int Cmd_CommandAbcPlugIn( Abc_Frame_t * pAbc, int argc, char ** argv ) } // create input file - Gia_AigerWrite( pAbc->pGia, pFileIn, 0, 0 ); + Gia_AigerWrite( pAbc->pGia, pFileIn, 0, 0, 0 ); // create command line vCommand = Vec_StrAlloc( 100 ); diff --git a/src/base/cmd/cmdStarter.c b/src/base/cmd/cmdStarter.c index 47cdd9e..ffb2b75 100644 --- a/src/base/cmd/cmdStarter.c +++ b/src/base/cmd/cmdStarter.c @@ -176,7 +176,8 @@ void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCor ABC_FREE( Buffer ); fclose( pFile ); return; - } + } + fclose( pFileTemp ); } } diff --git a/src/base/exor/exor.c b/src/base/exor/exor.c index 2310de5..6e95b84 100644 --- a/src/base/exor/exor.c +++ b/src/base/exor/exor.c @@ -46,6 +46,7 @@ //////////////////////////////////////////////////////////////////////// #include "exor.h" +#include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START @@ -947,6 +948,69 @@ int Abc_ExorcismMain( Vec_Wec_t * vEsop, int nIns, int nOuts, char * pFileNameOu return 1; } +Vec_Wec_t * Abc_ExorcismNtk2Esop( Abc_Ntk_t * pNtk ) +{ + Vec_Wec_t * vEsop = NULL; + Abc_Obj_t * pNode, * pFanin, * pDriver; + char * pCube; + int nIns, nOuts, nProducts, nFanins, i, k; + + nIns = Abc_NtkCiNum( pNtk ); + nOuts = Abc_NtkCoNum( pNtk ); + + nProducts = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); + if ( !Abc_ObjIsNode(pDriver) ) + { + nProducts++; + continue; + } + if ( Abc_NodeIsConst(pDriver) ) + { + if ( Abc_NodeIsConst1(pDriver) ) + nProducts++; + continue; + } + nProducts += Abc_SopGetCubeNum((char *)pDriver->pData); + } + + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)i; + + vEsop = Vec_WecAlloc( nProducts+1 ); + + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); + if ( Abc_NodeIsConst(pDriver) ) continue; + + nFanins = Abc_ObjFaninNum(pDriver); + Abc_SopForEachCube( (char *)pDriver->pData, nFanins, pCube ) + { + Vec_Int_t *vCubeIn = Vec_WecPushLevel( vEsop ); + Vec_IntGrow( vCubeIn, nIns+2 ); + + Abc_ObjForEachFanin( pDriver, pFanin, k ) + { + pFanin = Abc_ObjFanin0Ntk(pFanin); + assert( (int)(ABC_PTRUINT_T)pFanin->pCopy < nIns ); + if ( pCube[k] == '0' ) + { + Vec_IntPush( vCubeIn, 2*k + 1 ); + } + else if ( pCube[k] == '1' ) + { + Vec_IntPush( vCubeIn, 2*k ); + } + } + Vec_IntPush( vCubeIn, -( i + 1 ) ); + } + } + + return vEsop; +} /////////////////////////////////////////////////////////////////// diff --git a/src/base/io/io.c b/src/base/io/io.c index 5133ef0..a85d64e 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -2421,6 +2421,8 @@ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); + fprintf( pFile, "# FALSIFYING OUTPUTS:"); + fprintf( pFile, " %s", Abc_ObjName(Abc_NtkCo(pNtk, pCex->iPo)) ); if ( fUseOldMin ) { pCare = Saig_ManCbaFindCexCareBits( pAig, pCex, 0, fVerbose ); @@ -2432,15 +2434,24 @@ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv ) else pCare = Bmc_CexCareMinimize( pAig, Saig_ManPiNum(pAig), pCex, 4, fCheckCex, fVerbose ); Aig_ManStop( pAig ); + if(pCare == NULL) + printf( "Counter-example minimization has failed.\n" ); } + else + { + fprintf( pFile, "# FALSIFYING OUTPUTS:"); + fprintf( pFile, " %s", Abc_ObjName(Abc_NtkCo(pNtk, pCex->iPo)) ); + } + fprintf( pFile, "\n"); + fprintf( pFile, "# COUNTEREXAMPLE LENGTH: %u\n", pCex->iFrame+1); // output flop values (unaffected by the minimization) Abc_NtkForEachLatch( pNtk, pObj, i ) - fprintf( pFile, "%s@0=%c ", Abc_ObjName(Abc_ObjFanout0(pObj)), '0'+!Abc_LatchIsInit0(pObj) ); + fprintf( pFile, "%s@0=%c\n", Abc_ObjName(Abc_ObjFanout0(pObj)), '0'+!Abc_LatchIsInit0(pObj) ); // output PI values (while skipping the minimized ones) for ( f = 0; f <= pCex->iFrame; f++ ) Abc_NtkForEachPi( pNtk, pObj, i ) if ( !pCare || Abc_InfoHasBit(pCare->pData, pCare->nRegs+pCare->nPis*f + i) ) - fprintf( pFile, "%s@%d=%c ", Abc_ObjName(pObj), f, '0'+Abc_InfoHasBit(pCex->pData, pCex->nRegs+pCex->nPis*f + i) ); + fprintf( pFile, "%s@%d=%c\n", Abc_ObjName(pObj), f, '0'+Abc_InfoHasBit(pCex->pData, pCex->nRegs+pCex->nPis*f + i) ); Abc_CexFreeP( &pCare ); } else @@ -2455,7 +2466,7 @@ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv ) fprintf( pFile, "%c", '0'+Abc_InfoHasBit(pCex->pData, i) ); } } - fprintf( pFile, "\n" ); + fprintf( pFile, "# DONE\n" ); fclose( pFile ); } else @@ -2678,14 +2689,24 @@ usage: ***********************************************************************/ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) { + extern int Io_WriteMoPlaM( Abc_Ntk_t * pNtk, char * pFileName, int nMints ); char * pFileName; - int c, fUseMoPla = 0; + int c, fUseMoPla = 0, nMints = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Mmh" ) ) != EOF ) { switch ( c ) { + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMints = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; case 'm': fUseMoPla ^= 1; break; @@ -2705,15 +2726,28 @@ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer - Io_Write( pAbc->pNtkCur, pFileName, fUseMoPla ? IO_FILE_MOPLA : IO_FILE_PLA ); + if ( nMints ) + { + if ( Abc_NtkIsBddLogic(pAbc->pNtkCur) ) + Io_WriteMoPlaM( pAbc->pNtkCur, pFileName, nMints ); + else + { + Abc_Ntk_t * pStrash = Abc_NtkStrash( pAbc->pNtkCur, 0, 0, 0 ); + Io_WriteMoPlaM( pStrash, pFileName, nMints ); + Abc_NtkDelete( pStrash ); + } + } + else + Io_Write( pAbc->pNtkCur, pFileName, fUseMoPla ? IO_FILE_MOPLA : IO_FILE_PLA ); return 0; usage: - fprintf( pAbc->Err, "usage: write_pla [-mh] <file>\n" ); - fprintf( pAbc->Err, "\t writes the collapsed network into a PLA file\n" ); - fprintf( pAbc->Err, "\t-m : toggle writing multi-output PLA [default = %s]\n", fUseMoPla? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + fprintf( pAbc->Err, "usage: write_pla [-M <num>] [-mh] <file>\n" ); + fprintf( pAbc->Err, "\t writes the collapsed network into a PLA file\n" ); + fprintf( pAbc->Err, "\t-M <num> : the number of on-set minterms to write [default = %d]\n", nMints ); + fprintf( pAbc->Err, "\t-m : toggle writing multi-output PLA [default = %s]\n", fUseMoPla? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } diff --git a/src/base/io/ioWritePla.c b/src/base/io/ioWritePla.c index df2618c..8aa9ee1 100644 --- a/src/base/io/ioWritePla.c +++ b/src/base/io/ioWritePla.c @@ -383,7 +383,7 @@ int Io_WriteMoPlaOneIntMinterms( FILE * pFile, Abc_Ntk_t * pNtk, DdManager * dd, ***********************************************************************/ int Io_WriteMoPlaOne( FILE * pFile, Abc_Ntk_t * pNtk ) { - int fVerbose = 1; + int fVerbose = 0; DdManager * dd; DdNode * bFunc; Vec_Ptr_t * vFuncsGlob; @@ -445,9 +445,136 @@ int Io_WriteMoPla( Abc_Ntk_t * pNtk, char * pFileName ) return 1; } + + +/**Function************************************************************* + + Synopsis [Writes the network in PLA format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteMoPlaOneIntMintermsM( FILE * pFile, Abc_Ntk_t * pNtk, DdManager * dd, DdNode * bFunc, int nMints ) +{ + Abc_Obj_t * pNode; + int * pArray = ABC_CALLOC( int, dd->size ); + DdNode ** pbMints = Cudd_bddPickArbitraryMinterms( dd, bFunc, dd->vars, dd->size, nMints ); + int i, k, nInputs = Abc_NtkCiNum(pNtk); + assert( dd->size == Abc_NtkCiNum(pNtk) ); + + // write the header + fprintf( pFile, ".i %d\n", nInputs ); + fprintf( pFile, ".o %d\n", 1 ); + fprintf( pFile, ".ilb" ); + Abc_NtkForEachCi( pNtk, pNode, i ) + fprintf( pFile, " %s", Abc_ObjName(pNode) ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".ob" ); + fprintf( pFile, " %s", Abc_ObjName(Abc_NtkCo(pNtk, 0)) ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".p %d\n", nMints ); + + // iterate through minterms + for ( k = 0; k < nMints; k++ ) + { + Cudd_BddToCubeArray( dd, pbMints[k], pArray ); + for ( i = 0; i < Abc_NtkCiNum(pNtk); i++ ) + if ( pArray[i] == 0 ) + fprintf( pFile, "%c", '0' ); + else if ( pArray[i] == 1 ) + fprintf( pFile, "%c", '1' ); + else if ( pArray[i] == 2 ) + fprintf( pFile, "%c", '-' ); + fprintf( pFile, " " ); + fprintf( pFile, "%c", '1' ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".e\n" ); + + //for ( k = 0; k < nMints; k++ ) + // Cudd_RecursiveDeref( dd, pbMints[k] ); + ABC_FREE( pbMints ); + ABC_FREE( pArray ); + return 1; +} +int Io_WriteMoPlaOneM( FILE * pFile, Abc_Ntk_t * pNtk, int nMints ) +{ + int fVerbose = 0; + DdManager * dd; + DdNode * bFunc; + Vec_Ptr_t * vFuncsGlob; + Abc_Obj_t * pObj; + int i; + if ( Abc_NtkIsStrash(pNtk) ) + { + assert( Abc_NtkIsStrash(pNtk) ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, 0, fVerbose ); + if ( dd == NULL ) + return 0; + if ( fVerbose ) + printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); + + // get the output function + bFunc = (DdNode *)Vec_PtrEntry(vFuncsGlob, 0); + if ( bFunc == Cudd_ReadOne(dd) ) + printf( "First primary output has constant 1 function.\n" ); + else if ( Cudd_Not(bFunc) == Cudd_ReadOne(dd) ) + printf( "First primary output has constant 0 function.\n" ); + else + Io_WriteMoPlaOneIntMintermsM( pFile, pNtk, dd, bFunc, nMints ); + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + + // cleanup + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vFuncsGlob ); + //Extra_StopManager( dd ); + Cudd_Quit( dd ); + } + else if ( Abc_NtkIsBddLogic(pNtk) ) + { + DdNode * bFunc = (DdNode *)Abc_ObjFanin0(Abc_NtkCo(pNtk, 0))->pData; + dd = (DdManager *)pNtk->pManFunc; + if ( dd->size == Abc_NtkCiNum(pNtk) ) + Io_WriteMoPlaOneIntMintermsM( pFile, pNtk, dd, bFunc, nMints ); + else + { + printf( "Cannot write minterms because the size of the manager for local BDDs is not equal to\n" ); + printf( "the number of primary inputs. (It is likely that the current network is not collapsed.)\n" ); + } + } + return 1; +} +int Io_WriteMoPlaM( Abc_Ntk_t * pNtk, char * pFileName, int nMints ) +{ + FILE * pFile; + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsBddLogic(pNtk) ); + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteMoPlaM(): Cannot open the output file.\n" ); + return 0; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + Io_WriteMoPlaOneM( pFile, pNtk, nMints ); + fclose( pFile ); + return 1; +} + + #else -int Io_WriteMoPla( Abc_Ntk_t * pNtk, char * pFileName ) { return 1; } +int Io_WriteMoPla( Abc_Ntk_t * pNtk, char * pFileName ) { return 1; } +int Io_WriteMoPlaM( Abc_Ntk_t * pNtk, char * pFileName, int nMints ) { return 1; } #endif diff --git a/src/base/main/mainReal.c b/src/base/main/mainReal.c index 31bfef7..180ec44 100644 --- a/src/base/main/mainReal.c +++ b/src/base/main/mainReal.c @@ -44,6 +44,14 @@ SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ***********************************************************************/ +#ifndef WIN32 +#include <sys/time.h> +#include <sys/times.h> +#include <sys/resource.h> +#include <unistd.h> +#include <signal.h> +#include <stdlib.h> +#endif #include "base/abc/abc.h" #include "mainInt.h" @@ -62,6 +70,7 @@ static int TypeCheck( Abc_Frame_t * pAbc, const char * s); /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +unsigned enable_dbg_outs = 1; /**Function************************************************************* @@ -115,8 +124,37 @@ int Abc_RealMain( int argc, char * argv[] ) sprintf( sWriteCmd, "write" ); Extra_UtilGetoptReset(); - while ((c = Extra_UtilGetopt(argc, argv, "c:q:C:Q:S:hf:F:o:st:T:xb")) != EOF) { + while ((c = Extra_UtilGetopt(argc, argv, "dm:l:c:q:C:Q:S:hf:F:o:st:T:xb")) != EOF) { switch(c) { + + case 'd': + enable_dbg_outs ^= 1; + break; + + case 'm': { +#ifndef WIN32 + int maxMb = atoi(globalUtilOptarg); + printf("Limiting memory use to %d MB\n", maxMb); + struct rlimit limit = { + maxMb * (1llu << 20), /* soft limit */ + maxMb * (1llu << 20) /* hard limit */ + }; + setrlimit(RLIMIT_AS, &limit); +#endif + break; + } + case 'l': { +#ifndef WIN32 + int maxTime = atoi(globalUtilOptarg); + printf("Limiting time to %d seconds\n", maxTime); + struct rlimit limit = { + maxTime, /* soft limit */ + maxTime /* hard limit */ + }; + setrlimit(RLIMIT_CPU, &limit); +#endif + break; + } case 'c': if( Vec_StrSize(sCommandUsr) > 0 ) { diff --git a/src/base/wlc/wlc.h b/src/base/wlc/wlc.h index e947e36..3a84031 100644 --- a/src/base/wlc/wlc.h +++ b/src/base/wlc/wlc.h @@ -140,6 +140,7 @@ struct Wlc_Ntk_t_ Vec_Int_t vCis; // combinational inputs Vec_Int_t vCos; // combinational outputs Vec_Int_t vFfs; // flops + Vec_Int_t vFfs2; // flops Vec_Int_t * vInits; // initial values char * pInits; // initial values int nObjs[WLC_OBJ_NUMBER]; // counter of objects of each type @@ -275,6 +276,7 @@ static inline Wlc_Obj_t * Wlc_NtkPo( Wlc_Ntk_t * p, int i ) static inline Wlc_Obj_t * Wlc_NtkCi( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vCis, i) ); } static inline Wlc_Obj_t * Wlc_NtkCo( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vCos, i) ); } static inline Wlc_Obj_t * Wlc_NtkFf( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vFfs, i) ); } +static inline Wlc_Obj_t * Wlc_NtkFf2( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vFfs2, i) ); } static inline int Wlc_ObjIsPi( Wlc_Obj_t * p ) { return p->Type == WLC_OBJ_PI; } static inline int Wlc_ObjIsPo( Wlc_Obj_t * p ) { return p->fIsPo; } @@ -350,6 +352,8 @@ static inline Wlc_Obj_t * Wlc_ObjCo2PoFo( Wlc_Ntk_t * p, int iCoId ) for ( i = 0; (i < Wlc_NtkCoNum(p)) && (((pCo) = Wlc_NtkCo(p, i)), 1); i++ ) #define Wlc_NtkForEachFf( p, pFf, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vFfs)) && (((pFf) = Wlc_NtkFf(p, i)), 1); i++ ) +#define Wlc_NtkForEachFf2( p, pFf, i ) \ + for ( i = 0; (i < Vec_IntSize(&p->vFfs2)) && (((pFf) = Wlc_NtkFf2(p, i)), 1); i++ ) #define Wlc_ObjForEachFanin( pObj, iFanin, i ) \ for ( i = 0; (i < Wlc_ObjFaninNum(pObj)) && (((iFanin) = Wlc_ObjFaninId(pObj, i)), 1); i++ ) diff --git a/src/base/wlc/wlcAbc.c b/src/base/wlc/wlcAbc.c index 1836f4e..e1b06ff 100644 --- a/src/base/wlc/wlcAbc.c +++ b/src/base/wlc/wlcAbc.c @@ -42,6 +42,58 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ +void Wlc_NtkPrintInputInfo( Wlc_Ntk_t * pNtk ) +{ + Wlc_Obj_t * pObj; + int i, k, nRange, nBeg, nEnd, nBits = 0; + FILE * output; + + output = fopen("abc_blast_input.info","w"); + + Wlc_NtkForEachCi( pNtk, pObj, i ) + { + nRange = Wlc_ObjRange(pObj); + nBeg = pObj->Beg; + nEnd = pObj->End; + + for ( k = 0; k < nRange; k++ ) + { + int index = nEnd > nBeg ? nBeg + k : nEnd + k; + char c = pObj->Type != WLC_OBJ_FO ? 'i' : pNtk->pInits[nBits + k]; + fprintf(output,"%s[%d] : %c \n", Wlc_ObjName(pNtk, Wlc_ObjId(pNtk, pObj)), index , c ); + } + if (pObj->Type == WLC_OBJ_FO) + nBits += nRange; + } + + Wlc_NtkForEachPo( pNtk, pObj, i ) + { + nRange = Wlc_ObjRange(pObj); + nBeg = pObj->Beg; + nEnd = pObj->End; + + for ( k = 0; k < nRange; k++ ) + { + int index = nEnd > nBeg ? nBeg + k : nEnd + k; + fprintf(output,"%s[%d] : o \n", Wlc_ObjName(pNtk, Wlc_ObjId(pNtk, pObj)), index); + } + } + + fclose(output); + return; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ void Wlc_NtkPrintInvStats( Wlc_Ntk_t * pNtk, Vec_Int_t * vCounts, int fVerbose ) { Wlc_Obj_t * pObj; diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c index 2efed1f..c5c351c 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -131,6 +131,12 @@ int Wlc_NtkMuxTree2( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData Vec_IntPush( vTemp, Abc_LitNot( Gia_ManHashAnd(pNew, iLit, Vec_IntEntry(vData, m)) ) ); return Abc_LitNot( Gia_ManHashAndMulti(pNew, vTemp) ); } +void Wlc_NtkPrintNameArray( Vec_Ptr_t * vNames ) +{ + int i; char * pTemp; + Vec_PtrForEachEntry( char *, vNames, pTemp, i ) + printf( "%2d : %s\n", i, pTemp ); +} /**Function************************************************************* @@ -167,7 +173,7 @@ void Wlc_BlastShiftRight( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShiftMax = Abc_Base2Log(nNum); int * pShiftNew = ABC_ALLOC( int, nShift ); memcpy( pShiftNew, pShift, sizeof(int)*nShift ); - if ( nShiftMax < nShift ) + if ( nShiftMax < nShift && nShift > 30 ) { int i, iRes = pShiftNew[nShiftMax]; for ( i = nShiftMax + 1; i < nShift; i++ ) @@ -1134,13 +1140,15 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) Tim_Man_t * pManTime = NULL; If_LibBox_t * pBoxLib = NULL; Vec_Ptr_t * vTables = NULL; + Vec_Int_t * vFf2Ci = Vec_IntAlloc( 100 ); + Vec_Int_t * vRegClasses = NULL; Gia_Man_t * pTemp, * pNew, * pExtra = NULL; Wlc_Obj_t * pObj, * pObj2; Vec_Int_t * vBits = &p->vBits, * vTemp0, * vTemp1, * vTemp2, * vRes, * vAddOutputs = NULL, * vAddObjs = NULL; int nBits = Wlc_NtkPrepareBits( p ); int nRange, nRange0, nRange1, nRange2, nRange3; int i, k, b, iFanin, iLit, nAndPrev, * pFans0, * pFans1, * pFans2, * pFans3; - int nFFins = 0, nFFouts = 0, curPi = 0, curPo = 0; + int nFFins = 0, nFFouts = 0, curPi = 0, curPo = 0, nFf2Regs = 0; int nBitCis = 0, nBitCos = 0, fAdded = 0; Wlc_BstPar_t Par, * pPar = &Par; Wlc_BstParDefault( pPar ); @@ -1167,6 +1175,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) if ( pPar->vBoxIds ) { int nNewCis = 0, nNewCos = 0; + assert( Vec_IntSize(&p->vFfs2) == 0 ); Wlc_NtkForEachObj( p, pObj, i ) pObj->Mark = 0; // count bit-width of regular CIs/COs @@ -1198,6 +1207,61 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) // create box library pBoxLib = If_LibBoxStart(); } + if ( Vec_IntSize(&p->vFfs2) > 0 ) + { + Vec_Int_t * vSignature; + int nNewCis = 0, nNewCos = 0; + assert( pPar->vBoxIds == 0 ); + // count bit-width of regular CIs/COs + Wlc_NtkForEachCi( p, pObj, i ) + nBitCis += Wlc_ObjRange( pObj ); + Wlc_NtkForEachCo( p, pObj, i ) + nBitCos += Wlc_ObjRange( pObj ); + // count bit-width of additional CIs/COs due to selected multipliers + Wlc_NtkForEachFf2( p, pObj, i ) + { + // currently works only for multipliers + assert( pObj->Type == WLC_OBJ_FF ); + assert( Wlc_ObjRange(pObj) == Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); + nNewCis += Wlc_ObjRange(pObj); + nNewCos += 2*Wlc_ObjRange(pObj) + 3; + nFf2Regs+= Wlc_ObjRange(pObj); + } + // create hierarchy manager + pManTime = Tim_ManStart( nBitCis + nNewCis + nFf2Regs, nBitCos + nNewCos + nFf2Regs ); + curPi = nBitCis + nFf2Regs; + curPo = 0; + // create AIG manager for logic of the boxes + pExtra = Gia_ManStart( Wlc_NtkObjNum(p) ); + Gia_ManHashAlloc( pExtra ); + assert( !pPar->fGiaSimple ); + // create register classes + vRegClasses = Vec_IntAlloc(0); + vSignature = Vec_IntAlloc( 100 ); + Vec_IntPushTwo( vSignature, -1, -1 ); + Wlc_NtkForEachFf2( p, pObj, i ) + { + int iClk0, iClk = Wlc_ObjFaninId( pObj, 1 ); + int iAsyn0, iAsyn = Wlc_ObjFaninId( pObj, 5 ); + nRange = Wlc_ObjRange(pObj); + Vec_IntForEachEntryDouble( vSignature, iClk0, iAsyn0, k ) + if ( iClk == iClk0 && iAsyn == iAsyn0 ) + { + for ( b = 0; b < nRange; b++ ) + Vec_IntPush( vRegClasses, k/2 ); + break; + } + if ( k < Vec_IntSize(vSignature) ) + continue; + for ( b = 0; b < nRange; b++ ) + Vec_IntPush( vRegClasses, k/2 ); + Vec_IntPushTwo( vSignature, iClk, iAsyn ); + } + assert( Vec_IntSize(vRegClasses) == nFf2Regs ); + Vec_IntFree( vSignature ); + // create box library + pBoxLib = If_LibBoxStart(); + } // blast in the topological order Wlc_NtkForEachObj( p, pObj, i ) { @@ -1210,10 +1274,10 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) nRange1 = Wlc_ObjFaninNum(pObj) > 1 ? Wlc_ObjRange( Wlc_ObjFanin1(p, pObj) ) : -1; nRange2 = Wlc_ObjFaninNum(pObj) > 2 ? Wlc_ObjRange( Wlc_ObjFanin2(p, pObj) ) : -1; nRange3 = Wlc_ObjFaninNum(pObj) > 3 ? Wlc_ObjRange( Wlc_ObjFanin(p, pObj, 3) ) : -1; - pFans0 = Wlc_ObjFaninNum(pObj) > 0 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId0(pObj)) ) : NULL; - pFans1 = Wlc_ObjFaninNum(pObj) > 1 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId1(pObj)) ) : NULL; - pFans2 = Wlc_ObjFaninNum(pObj) > 2 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId2(pObj)) ) : NULL; - pFans3 = Wlc_ObjFaninNum(pObj) > 3 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId(pObj,3)) ) : NULL; + pFans0 = pObj->Type != WLC_OBJ_FF && Wlc_ObjFaninNum(pObj) > 0 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId0(pObj)) ) : NULL; + pFans1 = pObj->Type != WLC_OBJ_FF && Wlc_ObjFaninNum(pObj) > 1 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId1(pObj)) ) : NULL; + pFans2 = pObj->Type != WLC_OBJ_FF && Wlc_ObjFaninNum(pObj) > 2 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId2(pObj)) ) : NULL; + pFans3 = pObj->Type != WLC_OBJ_FF && Wlc_ObjFaninNum(pObj) > 3 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId(pObj,3)) ) : NULL; Vec_IntClear( vRes ); assert( nRange > 0 ); if ( pPar->vBoxIds && pObj->Mark ) @@ -1317,13 +1381,15 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) // add box to the library sprintf( Buffer, "%s%03d", pObj->Type == WLC_OBJ_ARI_ADD ? "add":"mul", 1+If_LibBoxNum(pBoxLib) ); - pBox = If_BoxStart( Abc_UtilStrsav(Buffer), 1+If_LibBoxNum(pBoxLib), nRange, nRange0 + nRange1 + nRange2, 0, 0, 0 ); + pBox = If_BoxStart( Abc_UtilStrsav(Buffer), 1+If_LibBoxNum(pBoxLib), nRange0 + nRange1 + nRange2, nRange, 0, 0, 0 ); If_LibBoxAdd( pBoxLib, pBox ); for ( k = 0; k < pBox->nPis * pBox->nPos; k++ ) pBox->pDelays[k] = 1; } - else if ( Wlc_ObjIsCi(pObj) ) + else if ( Wlc_ObjIsCi(pObj) || pObj->Type == WLC_OBJ_FF ) // assuming that FFs are ordered immediately after PIs { + if ( pObj->Type == WLC_OBJ_FF ) + Vec_IntPush( vFf2Ci, Gia_ManCiNum(pNew) ); if ( Wlc_ObjRangeIsReversed(pObj) ) { for ( k = 0; k < nRange; k++ ) @@ -1338,6 +1404,10 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) } if ( pObj->Type == WLC_OBJ_FO ) nFFouts += Vec_IntSize(vRes); + if ( pObj->Type == WLC_OBJ_FF ) + { + // complement flop output whose init state is 1 + } } else if ( pObj->Type == WLC_OBJ_BUF ) { @@ -1767,6 +1837,102 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) Vec_IntFree( vTemp1 ); Vec_IntFree( vTemp2 ); Vec_IntFree( vRes ); + // create flop boxes + Wlc_NtkForEachFf2( p, pObj, i ) + { + If_Box_t * pBox; + char Buffer[100]; + float * pTable; + Vec_Int_t * vTemp0 = Vec_IntAlloc( 100 ); + Vec_Int_t * vTemp1 = Vec_IntAlloc( 100 ); + int iLit, nRange = Wlc_ObjRange(pObj); + int * pFans0, * pFans1, * pFans2, * pFans3; + int iReset, iSet, iEnable; + int nRangeIn = 2*nRange + 3; // D, reset, set, enable, Q + int iSre = Wlc_ObjFaninId(pObj, 6); + + assert( pObj->Type == WLC_OBJ_FF ); + + // create new box + if ( vTables == NULL ) + Tim_ManSetDelayTables( pManTime, (vTables = Vec_PtrAlloc(100)) ); + Tim_ManCreateBox( pManTime, curPo, nRangeIn, curPi, nRange, Vec_PtrSize(vTables), 0 ); + curPi += nRange; + curPo += nRangeIn; + + // create delay table + pTable = ABC_ALLOC( float, 3 + nRange * nRangeIn ); + pTable[0] = Vec_PtrSize(vTables); + pTable[1] = nRangeIn; + pTable[2] = nRange; + for ( k = 0; k < nRange * nRangeIn; k++ ) + pTable[3 + k] = 1.0; + Vec_PtrPush( vTables, pTable ); + + // create combinational outputs in the normal manager + pFans0 = Wlc_ObjFaninNum(pObj) > 0 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId0(pObj)) ) : NULL; + pFans1 = Wlc_ObjFaninNum(pObj) > 1 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId1(pObj)) ) : NULL; + pFans2 = Wlc_ObjFaninNum(pObj) > 2 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId2(pObj)) ) : NULL; + pFans3 = Wlc_ObjFaninNum(pObj) > 3 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId(pObj,3)) ) : NULL; + for ( k = 0; k < nRange; k++ ) + Gia_ManAppendCo( pNew, pFans0[k] ); + Gia_ManAppendCo( pNew, pFans1[0] ); + Gia_ManAppendCo( pNew, pFans2[0] ); + Gia_ManAppendCo( pNew, pFans3[0] ); + for ( k = 0; k < nRange; k++ ) + Gia_ManAppendCo( pNew, Gia_Obj2Lit(pNew, Gia_ManCi(pNew, Vec_IntEntry(vFf2Ci, i)+k)) ); + + // make sure there is enough primary inputs in the manager + for ( k = Gia_ManPiNum(pExtra); k < nRangeIn; k++ ) + Gia_ManAppendCi( pExtra ); + // create combinational inputs + for ( k = 0; k < nRange; k++ ) + Vec_IntPush( vTemp0, Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, k)) ); + iReset = Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRange+0)); + iSet = Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRange+1)); + iEnable = Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRange+2)); + for ( k = 0; k < nRange; k++ ) + Vec_IntPush( vTemp1, Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRangeIn-nRange+k)) ); + + // bit-blast in the external manager + for ( k = 0; k < nRange; k++ ) + { + // enable + //iLitFlop = Gia_LitNotCond( Gia_ObjCopy(pObj), Gia_FlopIsOne(pObj) ); + //iLit = Gia_ManHashMux( Gia_ObjGia(pObj), Gia_FlopEnableCopy(pObj), iLit, iLitFlop ); + iLit = Gia_ManHashMux( pExtra, iEnable, Vec_IntEntry(vTemp0, k), Vec_IntEntry(vTemp1, k) ); + if ( iSre ) + { + // reset + //iLit = Gia_ManHashAnd( Gia_ObjGia(pObj), iLit, Gia_LitNot(Gia_FlopResetCopy(pObj)) ); + iLit = Gia_ManHashAnd( pExtra, iLit, Abc_LitNot(iReset) ); + // set + //iLit = Gia_ManHashOr( Gia_ObjGia(pObj), iLit, Gia_FlopSetCopy(pObj) ); + iLit = Gia_ManHashOr( pExtra, iLit, iSet ); + } + else + { + // set + //iLit = Gia_ManHashOr( Gia_ObjGia(pObj), iLit, Gia_FlopSetCopy(pObj) ); + iLit = Gia_ManHashOr( pExtra, iLit, iSet ); + // reset + //iLit = Gia_ManHashAnd( Gia_ObjGia(pObj), iLit, Gia_LitNot(Gia_FlopResetCopy(pObj)) ); + iLit = Gia_ManHashAnd( pExtra, iLit, Abc_LitNot(iReset) ); + } + // create outputs in the external manager + Gia_ManAppendCo( pExtra, iLit ); + } + + // add box to the library + sprintf( Buffer, "%s%03d", "ff_comb", 1+If_LibBoxNum(pBoxLib) ); + pBox = If_BoxStart( Abc_UtilStrsav(Buffer), 1+If_LibBoxNum(pBoxLib), nRangeIn, nRange, 0, 0, 0 ); + If_LibBoxAdd( pBoxLib, pBox ); + for ( k = 0; k < pBox->nPis * pBox->nPos; k++ ) + pBox->pDelays[k] = 1; + Vec_IntFree( vTemp0 ); + Vec_IntFree( vTemp1 ); + } + Vec_IntFree( vFf2Ci ); // create COs if ( pPar->fCreateMiter ) { @@ -1856,8 +2022,19 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) //Vec_IntErase( vBits ); //Vec_IntErase( &p->vCopies ); // set the number of registers - assert( nFFins == nFFouts ); - Gia_ManSetRegNum( pNew, nFFins ); + if ( Vec_IntSize(&p->vFfs2) > 0 ) + { + assert( nFFins == 0 && nFFouts == 0 ); + // complement flop inputs whose init state is 1 + for ( i = 0; i < nFf2Regs; i++ ) + Gia_ManAppendCo( pNew, Gia_ManAppendCi(pNew) ); + //Gia_ManSetRegNum( pNew, nFf2Regs ); + } + else + { + assert( nFFins == nFFouts ); + Gia_ManSetRegNum( pNew, nFFins ); + } // finalize AIG if ( !pPar->fGiaSimple && !pPar->fNoCleanup ) { @@ -1882,6 +2059,24 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) } } // finalize AIG with boxes + if ( Vec_IntSize(&p->vFfs2) > 0 ) + { + curPo += nBitCos + nFf2Regs; + assert( curPi == Tim_ManCiNum(pManTime) ); + assert( curPo == Tim_ManCoNum(pManTime) ); + // finalize the extra AIG + pExtra = Gia_ManCleanup( pTemp = pExtra ); + Gia_ManStop( pTemp ); + assert( Gia_ManPoNum(pExtra) == Gia_ManCiNum(pNew) - nBitCis - nFf2Regs ); + // attach + pNew->pAigExtra = pExtra; + pNew->pManTime = pManTime; + // normalize AIG + pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); + Gia_ManTransferTiming( pNew, pTemp ); + Gia_ManStop( pTemp ); + //Tim_ManPrint( pManTime ); + } if ( pPar->vBoxIds ) { curPo += nBitCos; @@ -1890,7 +2085,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) // finalize the extra AIG pExtra = Gia_ManCleanup( pTemp = pExtra ); Gia_ManStop( pTemp ); - assert( Gia_ManPoNum(pExtra) == Gia_ManCiNum(pNew) - nBitCis ); + assert( Gia_ManPoNum(pExtra) == Gia_ManCiNum(pNew) - nBitCis - nFf2Regs ); // attach pNew->pAigExtra = pExtra; pNew->pManTime = pManTime; @@ -1944,6 +2139,38 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); } } + Wlc_NtkForEachFf2( p, pObj, i ) + { + char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); + nRange = Wlc_ObjRange( pObj ); + if ( fSkipBitRange && nRange == 1 ) + { + char Buffer[1000]; + sprintf( Buffer, "%s_fo", pName ); + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); + } + else + for ( k = 0; k < nRange; k++ ) + { + char Buffer[1000]; + sprintf( Buffer, "%s_fo[%d]", pName, k ); + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); + } + } + Wlc_NtkForEachFf2( p, pObj, i ) + { + char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); + nRange = Wlc_ObjRange( pObj ); + if ( fSkipBitRange && nRange == 1 ) + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(pName) ); + else + for ( k = 0; k < nRange; k++ ) + { + char Buffer[1000]; + sprintf( Buffer, "%s[%d]", pName, k ); + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); + } + } if ( p->pInits && fAdded ) Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav("abc_reset_flop") ); if ( pPar->vBoxIds ) @@ -1964,6 +2191,43 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) assert( Vec_PtrSize(pNew->vNamesIn) == Gia_ManCiNum(pNew) ); // create output names pNew->vNamesOut = Vec_PtrAlloc( Gia_ManCoNum(pNew) ); + Wlc_NtkForEachFf2( p, pObj, i ) + { + int iFanin; + Wlc_ObjForEachFanin( pObj, iFanin, b ) + { + char * pName = Wlc_ObjName(p, iFanin); + nRange = Wlc_ObjRange( Wlc_NtkObj(p, iFanin) ); + if ( fSkipBitRange && nRange == 1 ) + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(pName) ); + else + for ( k = 0; k < nRange; k++ ) + { + char Buffer[1000]; + sprintf( Buffer, "%s[%d]", pName, k ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + if ( b == 3 ) + break; + } + { + char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); + nRange = Wlc_ObjRange( pObj ); + if ( fSkipBitRange && nRange == 1 ) + { + char Buffer[1000]; + sprintf( Buffer, "%s_in", pName ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + else + for ( k = 0; k < nRange; k++ ) + { + char Buffer[1000]; + sprintf( Buffer, "%s_in[%d]", pName, k ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + } + } if ( pPar->vBoxIds ) { Wlc_NtkForEachObjVec( pPar->vBoxIds, p, pObj, i ) @@ -2045,12 +2309,34 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); nRange = Wlc_ObjRange( pObj ); if ( fSkipBitRange && nRange == 1 ) - Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(pName) ); + { + char Buffer[1000]; + sprintf( Buffer, "%s_fi", pName ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } else for ( k = 0; k < nRange; k++ ) { char Buffer[1000]; - sprintf( Buffer, "%s[%d]", pName, k ); + sprintf( Buffer, "%s_fi[%d]", pName, k ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + } + Wlc_NtkForEachFf2( p, pObj, i ) + { + char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); + nRange = Wlc_ObjRange( pObj ); + if ( fSkipBitRange && nRange == 1 ) + { + char Buffer[1000]; + sprintf( Buffer, "%s_fi", pName ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + else + for ( k = 0; k < nRange; k++ ) + { + char Buffer[1000]; + sprintf( Buffer, "%s_fi[%d]", pName, k ); Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); } } @@ -2075,19 +2361,22 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) assert( Gia_ManPoNum(pNew) % 2 == 0 ); sprintf( pFileName0, "%s_lhs_.aig", pNameGeneric ); sprintf( pFileName1, "%s_rhs_.aig", pNameGeneric ); - Gia_AigerWrite( pGia0, pFileName0, 0, 0 ); - Gia_AigerWrite( pGia1, pFileName1, 0, 0 ); + Gia_AigerWrite( pGia0, pFileName0, 0, 0, 0 ); + Gia_AigerWrite( pGia1, pFileName1, 0, 0, 0 ); Gia_ManStop( pGia0 ); Gia_ManStop( pGia1 ); Vec_IntFree( vOrder ); ABC_FREE( pNameGeneric ); printf( "Dumped two parts of the miter into files \"%s\" and \"%s\".\n", pFileName0, pFileName1 ); } + //Wlc_NtkPrintNameArray( pNew->vNamesIn ); + //Wlc_NtkPrintNameArray( pNew->vNamesOut ); if ( pPar->vBoxIds ) { - Vec_PtrFreeP( &pNew->vNamesIn ); - Vec_PtrFreeP( &pNew->vNamesOut ); + Vec_PtrFreeFree( pNew->vNamesIn ); pNew->vNamesIn = NULL; + Vec_PtrFreeFree( pNew->vNamesOut ); pNew->vNamesOut = NULL; } + pNew->vRegClasses = vRegClasses; return pNew; } diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c index 06c2346..6df2c84 100644 --- a/src/base/wlc/wlcCom.c +++ b/src/base/wlc/wlcCom.c @@ -40,6 +40,7 @@ static int Abc_CommandMemAbs ( Abc_Frame_t * pAbc, int argc, char ** argv ) static int Abc_CommandBlast ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBlastMem ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGraft ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandProfile ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -85,6 +86,7 @@ void Wlc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Word level", "%blast", Abc_CommandBlast, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%blastmem", Abc_CommandBlastMem, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%graft", Abc_CommandGraft, 0 ); + Cmd_CommandAdd( pAbc, "Word level", "%retime", Abc_CommandRetime, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%profile", Abc_CommandProfile, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%short_names", Abc_CommandShortNames, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%show", Abc_CommandShow, 0 ); @@ -968,13 +970,14 @@ usage: ******************************************************************************/ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Wlc_NtkPrintInputInfo( Wlc_Ntk_t * pNtk ); Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); - Gia_Man_t * pNew = NULL; int c; + Gia_Man_t * pNew = NULL; int c, fMiter = 0, fDumpNames = 0, fPrintInputInfo = 0; Wlc_BstPar_t Par, * pPar = &Par; Wlc_BstParDefault( pPar ); pPar->nOutputRange = 2; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ORAMcombadsvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ORAMcombadstnivh" ) ) != EOF ) { switch ( c ) { @@ -1043,6 +1046,16 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) case 's': pPar->fDecMuxes ^= 1; break; + case 't': + pPar->fCreateMiter ^= 1; + fMiter ^= 1; + break; + case 'n': + fDumpNames ^= 1; + break; + case 'i': + fPrintInputInfo ^= 1; + break; case 'v': pPar->fVerbose ^= 1; break; @@ -1057,6 +1070,8 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 1, "Abc_CommandBlast(): There is no current design.\n" ); return 0; } + if ( fPrintInputInfo ) + Wlc_NtkPrintInputInfo(pNtk); if ( pPar->fMulti ) { pPar->vBoxIds = Wlc_NtkCollectMultipliers( pNtk ); @@ -1085,10 +1100,31 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 1, "Abc_CommandBlast(): Bit-blasting has failed.\n" ); return 0; } + // generate miter + if ( fMiter ) + { + Gia_Man_t * pTemp = pNew; + pNew = Gia_ManTransformMiter( pNew ); + Gia_ManStop( pTemp ); + Abc_Print( 1, "Bit-blasting created a traditional multi-output miter by XORing POs pair-wise.\n" ); + if ( fDumpNames ) + { + int i; char * pName; + FILE * pFile = fopen( "pio_name_map.txt", "wb" ); + if ( pNew->vNamesIn ) + Vec_PtrForEachEntry( char *, pNew->vNamesIn, pName, i ) + fprintf( pFile, "i%d %s\n", i, pName ); + if ( pNew->vNamesOut ) + Vec_PtrForEachEntry( char *, pNew->vNamesOut, pName, i ) + fprintf( pFile, "o%d %s\n", i, pName ); + fclose( pFile ); + Abc_Print( 1, "Finished dumping file \"pio_name_map.txt\" containing PI/PO name mapping.\n" ); + } + } Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: - Abc_Print( -2, "usage: %%blast [-ORAM num] [-combadsvh]\n" ); + Abc_Print( -2, "usage: %%blast [-ORAM num] [-combadstnivh]\n" ); Abc_Print( -2, "\t performs bit-blasting of the word-level design\n" ); Abc_Print( -2, "\t-O num : zero-based index of the first word-level PO to bit-blast [default = %d]\n", pPar->iOutput ); Abc_Print( -2, "\t-R num : the total number of word-level POs to bit-blast [default = %d]\n", pPar->nOutputRange ); @@ -1099,8 +1135,11 @@ usage: 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-a : toggle generating carry-look-ahead adder [default = %s]\n", pPar->fCla? "yes": "no" ); - Abc_Print( -2, "\t-d : toggle creating dual-output miter [default = %s]\n", pPar->fCreateMiter? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle creating dual-output multi-output miter [default = %s]\n", pPar->fCreateMiter? "yes": "no" ); Abc_Print( -2, "\t-s : toggle creating decoded MUXes [default = %s]\n", pPar->fDecMuxes? "yes": "no" ); + Abc_Print( -2, "\t-t : toggle creating regular multi-output miter [default = %s]\n", fMiter? "yes": "no" ); + Abc_Print( -2, "\t-n : toggle dumping signal names into a text file [default = %s]\n", fDumpNames? "yes": "no" ); + Abc_Print( -2, "\t-i : toggle to print input names after blasting [default = %s]\n", fPrintInputInfo ? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPar->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -1138,7 +1177,7 @@ int Abc_CommandBlastMem( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( pNtk == NULL ) { - Abc_Print( 1, "Abc_CommandGraft(): There is no current design.\n" ); + Abc_Print( 1, "Abc_CommandBlastMem(): There is no current design.\n" ); return 0; } pNtk = Wlc_NtkMemBlast( pNtk ); @@ -1209,6 +1248,63 @@ usage: SeeAlso [] ******************************************************************************/ +int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Wln_NtkRetimeTest( char * pFileName ); + FILE * pFile; + char * pFileName = NULL; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + { + printf( "Abc_CommandRetime(): Input file name should be given on the command line.\n" ); + return 0; + } + // get the file name + pFileName = argv[globalUtilOptind]; + if ( (pFile = fopen( pFileName, "r" )) == NULL ) + { + Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName ); + if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".ndr", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", pFileName ); + Abc_Print( 1, "\n" ); + return 0; + } + fclose( pFile ); + Wln_NtkRetimeTest( pFileName ); + return 0; +usage: + Abc_Print( -2, "usage: %%retime [-vh]\n" ); + Abc_Print( -2, "\t performs retiming for the NDR design\n" ); + 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******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ int Abc_CommandProfile( Abc_Frame_t * pAbc, int argc, char ** argv ) { Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); @@ -1724,7 +1820,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) //Wlc_NtkSimulateTest( (Wlc_Ntk_t *)pAbc->pAbcWlc ); //pNtk = Wlc_NtkDupSingleNodes( pNtk ); //Wlc_AbcUpdateNtk( pAbc, pNtk ); - Ndr_ModuleTestDec(); + //Wln_ReadNdrTest(); //pNtk = Wlc_NtkMemAbstractTest( pNtk ); //Wlc_AbcUpdateNtk( pAbc, pNtk ); return 0; diff --git a/src/base/wlc/wlcMem.c b/src/base/wlc/wlcMem.c index ccc319e..fd844b6 100644 --- a/src/base/wlc/wlcMem.c +++ b/src/base/wlc/wlcMem.c @@ -1006,7 +1006,7 @@ int Wlc_NtkMemAbstract( Wlc_Ntk_t * p, int nIterMax, int fDumpAbs, int fPdrVerbo if ( fDumpAbs ) { char * pFileName = "mem_abs.aig"; - Gia_AigerWrite( pAbs, pFileName, 0, 0 ); + Gia_AigerWrite( pAbs, pFileName, 0, 0, 0 ); printf( "Iteration %3d: Dumped abstraction in file \"%s\" after finding CEX in frame %d.\n", nIters, pFileName, pCex ? pCex->iFrame : -1 ); } diff --git a/src/base/wlc/wlcNdr.c b/src/base/wlc/wlcNdr.c index 5f3bc12..16c7d77 100644 --- a/src/base/wlc/wlcNdr.c +++ b/src/base/wlc/wlcNdr.c @@ -344,9 +344,10 @@ void Wlc_NtkCheckIntegrity( void * pData ) } Ndr_ModForEachObj( p, Mod, Obj ) { + int Type = Ndr_ObjReadBody( p, Obj, NDR_OPERTYPE ); int i, * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); for ( i = 0; i < nArray; i++ ) - if ( Vec_IntGetEntry(vMap, pArray[i]) == 0 ) + if ( Vec_IntGetEntry(vMap, pArray[i]) == 0 && !(Type == ABC_OPER_DFFRSE && (i >= 5 || i <= 7)) ) printf( "Input name %d appearing as fanin %d of obj %d is not used as output name in any object.\n", pArray[i], i, Obj ); } Vec_IntFree( vMap ); @@ -398,6 +399,8 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) Vec_IntPush( &pNtk->vFfs, Vec_IntEntry(vFanins, 0) ); continue; } + if ( Type == ABC_OPER_DFFRSE ) + Vec_IntPush( &pNtk->vFfs2, iObj ); if ( Type == ABC_OPER_SLICE ) Vec_IntPushTwo( vFanins, End, Beg ); else if ( Type == ABC_OPER_CONST ) @@ -469,6 +472,7 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData ) assert( !fFound && i == NameId ); } //Ndr_NtkPrintNodes( pNtk ); + //Wlc_WriteVer( pNtk, "temp_ndr.v", 0, 0 ); // derive topological order pNtk = Wlc_NtkDupDfs( pTemp = pNtk, 0, 1 ); Wlc_NtkFree( pTemp ); diff --git a/src/base/wlc/wlcNtk.c b/src/base/wlc/wlcNtk.c index 7f56207..4ac0c66 100644 --- a/src/base/wlc/wlcNtk.c +++ b/src/base/wlc/wlcNtk.c @@ -264,6 +264,7 @@ void Wlc_NtkFree( Wlc_Ntk_t * p ) ABC_FREE( p->vCis.pArray ); ABC_FREE( p->vCos.pArray ); ABC_FREE( p->vFfs.pArray ); + ABC_FREE( p->vFfs2.pArray ); Vec_IntFreeP( &p->vInits ); ABC_FREE( p->vTravIds.pArray ); ABC_FREE( p->vNameIds.pArray ); @@ -286,6 +287,7 @@ int Wlc_NtkMemUsage( Wlc_Ntk_t * p ) Mem += 4 * p->vCis.nCap; Mem += 4 * p->vCos.nCap; Mem += 4 * p->vFfs.nCap; + Mem += 4 * p->vFfs2.nCap; Mem += sizeof(Wlc_Obj_t) * p->nObjsAlloc; Mem += Abc_NamMemUsed(p->pManName); Mem += Mem_FlexReadMemUsage(p->pMemFanin); @@ -866,10 +868,13 @@ void Wlc_NtkDupDfs_rec( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, int iObj, Vec_Int_t * v { Wlc_Obj_t * pObj; int i, iFanin; + if ( iObj == 0 ) + return; if ( Wlc_ObjCopy(p, iObj) ) return; //printf( "Visiting node %d\n", iObj ); pObj = Wlc_NtkObj( p, iObj ); + assert( pObj->Type != WLC_OBJ_FF ); Wlc_ObjForEachFanin( pObj, iFanin, i ) Wlc_NtkDupDfs_rec( pNew, p, iFanin, vFanins ); Wlc_ObjDup( pNew, p, iObj, vFanins ); @@ -906,9 +911,9 @@ Wlc_Ntk_t * Wlc_NtkDupDfsSimple( Wlc_Ntk_t * p ) Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p, int fMarked, int fSeq ) { Wlc_Ntk_t * pNew; - Wlc_Obj_t * pObj; + Wlc_Obj_t * pObj, * pObjNew; Vec_Int_t * vFanins; - int i; + int i, k, iObj, iFanin; vFanins = Vec_IntAlloc( 100 ); Wlc_NtkCleanCopy( p ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); @@ -923,12 +928,28 @@ Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p, int fMarked, int fSeq ) Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins ); pObj->Type = Type; } + Wlc_NtkForEachFf2( p, pObj, i ) + { + int iObjNew = Wlc_ObjAlloc( pNew, pObj->Type, Wlc_ObjIsSigned(pObj), pObj->End, pObj->Beg ); + Wlc_ObjSetCopy( p, Wlc_ObjId(p, pObj), iObjNew ); + Vec_IntPush( &pNew->vFfs2, iObjNew ); + } Wlc_NtkForEachCo( p, pObj, i ) if ( !fMarked || pObj->Mark ) Wlc_NtkDupDfs_rec( pNew, p, Wlc_ObjId(p, pObj), vFanins ); Wlc_NtkForEachCo( p, pObj, i ) if ( !fMarked || pObj->Mark ) Wlc_ObjSetCo( pNew, Wlc_ObjCopyObj(pNew, p, pObj), fSeq ? pObj->fIsFi : 0 ); + Wlc_NtkForEachFf2( p, pObj, i ) + { + iObj = Wlc_ObjId(p, pObj); + Wlc_ObjForEachFanin( pObj, iFanin, k ) + Wlc_NtkDupDfs_rec( pNew, p, iFanin, vFanins ); + Wlc_ObjCollectCopyFanins( p, iObj, vFanins ); + pObjNew = Wlc_NtkObj( pNew, Wlc_ObjCopy(p, iObj) ); + Wlc_ObjAddFanins( pNew, pObjNew, vFanins ); + pObjNew->fXConst = pObj->fXConst; + } Vec_IntFree( vFanins ); if ( fSeq ) { diff --git a/src/base/wlc/wlcReadVer.c b/src/base/wlc/wlcReadVer.c index da7ccba..d8187bd 100644 --- a/src/base/wlc/wlcReadVer.c +++ b/src/base/wlc/wlcReadVer.c @@ -1203,7 +1203,13 @@ startword: break; } // check range of the control - if ( nValues != Vec_IntSize(p->vFanins) - 1 ) + if ( nValues < Vec_IntSize(p->vFanins) - 1 ) // may occur if default is not there + { + //return Wlc_PrsWriteErrorMessage( p, pStart, "The number of values in the case statement is wrong.", pName ); + printf( "Warning: The number of values in the case statement is wrong.\n" ); + Vec_IntShrink(p->vFanins,nValues+1); + } + else if ( nValues > Vec_IntSize(p->vFanins) - 1 ) return Wlc_PrsWriteErrorMessage( p, pStart, "The number of values in the case statement is wrong.", pName ); if ( Wlc_ObjRange(pObj) == 1 ) { @@ -1277,7 +1283,7 @@ startword: } else if ( Wlc_PrsStrCmp( pStart, "ABC_DFFRSE" ) ) { - int NameId[8] = {0}, fFound, fFlopIn, fFlopOut, fFlopClk, fFlopRst, fFlopSet, fFlopEna, fFlopAsync, fFlopInit; + int NameId[10] = {0}, fFound, fFlopIn, fFlopClk, fFlopRst, fFlopSet, fFlopEna, fFlopAsync, fFlopSre, fFlopInit, fFlopOut; pStart += strlen("ABC_DFF"); while ( 1 ) { @@ -1286,13 +1292,14 @@ startword: break; pStart = Wlc_PrsSkipSpaces( pStart+1 ); fFlopIn = (pStart[0] == 'd'); - fFlopOut = (pStart[0] == 'q'); fFlopClk = (pStart[0] == 'c'); fFlopRst = (pStart[0] == 'r'); - fFlopSet = (pStart[0] == 's'); + fFlopSet = (pStart[0] == 's' && pStart[1] == 'e'); fFlopEna = (pStart[0] == 'e'); fFlopAsync = (pStart[0] == 'a'); + fFlopSre = (pStart[0] == 's' && pStart[1] == 'r'); fFlopInit = (pStart[0] == 'i'); + fFlopOut = (pStart[0] == 'q'); pStart = Wlc_PrsFindSymbol( pStart, '(' ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." ); @@ -1301,8 +1308,6 @@ startword: return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." ); if ( fFlopIn ) NameId[0] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); - else if ( fFlopOut ) - NameId[7] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); else if ( fFlopClk ) NameId[1] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); else if ( fFlopRst ) @@ -1313,8 +1318,12 @@ startword: NameId[4] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); else if ( fFlopAsync ) NameId[5] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); - else if ( fFlopInit ) + else if ( fFlopSre ) NameId[6] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); + else if ( fFlopInit ) + NameId[7] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); + else if ( fFlopOut ) + NameId[8] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); else assert( 0 ); if ( !fFound ) @@ -1323,7 +1332,7 @@ startword: if ( NameId[0] == -1 || NameId[7] == -1 ) return Wlc_PrsWriteErrorMessage( p, pStart, "Name of flop input or flop output is missing." ); // create output - pObj = Wlc_NtkObj( p->pNtk, NameId[7] ); + pObj = Wlc_NtkObj( p->pNtk, NameId[8] ); Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_FF ); Vec_IntClear( p->vFanins ); Vec_IntPush( p->vFanins, NameId[0] ); @@ -1333,6 +1342,7 @@ startword: Vec_IntPush( p->vFanins, NameId[4] ); Vec_IntPush( p->vFanins, NameId[5] ); Vec_IntPush( p->vFanins, NameId[6] ); + Vec_IntPush( p->vFanins, NameId[7] ); Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins ); } else if ( Wlc_PrsStrCmp( pStart, "ABC_DFF" ) ) @@ -1522,6 +1532,55 @@ startword: Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins ); p->pNtk->fMemPorts = 1; } + else if ( Wlc_PrsStrCmp( pStart, "CPL_RROT" ) || Wlc_PrsStrCmp( pStart, "CPL_LROT" ) ) + { + // CPL_RROT #(128, 6) I_47479(.o ( E_46713 ) , .d ( E_46718 ) , .s ( E_46712 ) ); + int right_rotation = Wlc_PrsStrCmp( pStart, "CPL_RROT" ); + int NameId = -1, NameIdOut = -1, NameIdInD = -1, NameIdInS = -1, fFound, fRotInD, fRotInS, fRotOut; + pStart += strlen("CPL_RROT"); + + // NOTE: no need to parse the parameter values + //if ( pStart[0] == '#' ) + + // read names + while ( 1 ) + { + pStart = Wlc_PrsFindSymbol( pStart, '.' ); + if ( pStart == NULL ) + break; + pStart = Wlc_PrsSkipSpaces( pStart+1 ); + if ( pStart[0] != 'o' && pStart[0] != 'd' && pStart[0] != 's') + continue; + fRotInD = (pStart[0] == 'd'); + fRotInS = (pStart[0] == 's'); + fRotOut = (pStart[0] == 'o'); + pStart = Wlc_PrsFindSymbol( pStart, '(' ); + if ( pStart == NULL ) + return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the rotation description." ); + pStart = Wlc_PrsFindName( pStart+1, &pName ); + if ( pStart == NULL ) + return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside rotation description." ); + if ( fRotInD ) + NameIdInD = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); + else if ( fRotInS ) + NameIdInS = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); + else if ( fRotOut ) + NameIdOut = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); + else + NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); + if ( !fFound ) + return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName ); + } + if ( NameIdOut == -1 || NameIdInD == -1 || NameIdInS == -1 ) + return Wlc_PrsWriteErrorMessage( p, pStart, "Some fields of CPL_ROT are missing." ); + // create rot output + pObj = Wlc_NtkObj( p->pNtk, NameIdOut ); + Wlc_ObjUpdateType( p->pNtk, pObj, right_rotation ? WLC_OBJ_ROTATE_R : WLC_OBJ_ROTATE_L ); + Vec_IntClear( p->vFanins ); + Vec_IntPush( p->vFanins, NameIdInD ); + Vec_IntPush( p->vFanins, NameIdInS ); + Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins ); + } else if ( pStart[0] == '(' && pStart[1] == '*' ) // skip comments { while ( *pStart++ != ')' ); @@ -1571,6 +1630,10 @@ Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr ) // derive topological order if ( p->pNtk ) { + Wlc_Obj_t * pObj; int i; + Wlc_NtkForEachObj( p->pNtk, pObj, i ) + if ( pObj->Type == WLC_OBJ_FF ) + Vec_IntPush( &p->pNtk->vFfs2, Wlc_ObjId(p->pNtk, pObj) ); pNtk = Wlc_NtkDupDfs( p->pNtk, 0, 1 ); pNtk->pSpec = Abc_UtilStrsav( pFileName ); } @@ -1600,7 +1663,7 @@ void Io_ReadWordTest( char * pFileName ) Wlc_WriteVer( pNtk, "test.v", 0, 0 ); pNew = Wlc_NtkBitBlast( pNtk, NULL ); - Gia_AigerWrite( pNew, "test.aig", 0, 0 ); + Gia_AigerWrite( pNew, "test.aig", 0, 0, 0 ); Gia_ManStop( pNew ); Wlc_NtkFree( pNtk ); diff --git a/src/base/wlc/wlcWriteVer.c b/src/base/wlc/wlcWriteVer.c index dd25196..30f10e1 100644 --- a/src/base/wlc/wlcWriteVer.c +++ b/src/base/wlc/wlcWriteVer.c @@ -192,7 +192,7 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) continue; fprintf( pFile, " assign " ); } - else if ( (pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3) || pObj->Type == WLC_OBJ_FF || pObj->Type == WLC_OBJ_SEL ) + else if ( (pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3) || pObj->Type == WLC_OBJ_SEL ) fprintf( pFile, "reg %s ", Range ); else fprintf( pFile, "wire %s ", Range ); @@ -361,13 +361,7 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) } else if ( pObj->Type == WLC_OBJ_FF ) { - char * pInNames[8] = {"d", "clk", "reset", "set", "enable", "async", "sre", "init"}; fprintf( pFile, "%s ;\n", Wlc_ObjName(p, i) ); - fprintf( pFile, " " ); - fprintf( pFile, "%s (", "ABC_DFFRSE" ); - Wlc_ObjForEachFanin( pObj, iFanin, k ) - fprintf( pFile, " .%s(%s),", pInNames[k], Wlc_ObjName(p, iFanin) ); - fprintf( pFile, " .%s(%s) ) ;\n", "q", Wlc_ObjName(p, i) ); continue; } else @@ -561,6 +555,18 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) } assert( !p->vInits || iFanin == (int)strlen(p->pInits) ); } + // write DFFs in the end + fprintf( pFile, "\n" ); + Wlc_NtkForEachFf2( p, pObj, i ) + { + char * pInNames[8] = {"d", "clk", "reset", "set", "enable", "async", "sre", "init"}; + fprintf( pFile, " " ); + fprintf( pFile, "%s (", "ABC_DFFRSE" ); + Wlc_ObjForEachFanin( pObj, iFanin, k ) + if ( iFanin ) fprintf( pFile, " .%s(%s),", pInNames[k], Wlc_ObjName(p, iFanin) ); + fprintf( pFile, " .%s(%s) ) ;\n", "q", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) ); + } + fprintf( pFile, "\n" ); fprintf( pFile, "endmodule\n\n" ); } void Wlc_WriteVer( Wlc_Ntk_t * p, char * pFileName, int fAddCos, int fNoFlops ) diff --git a/src/base/wln/module.make b/src/base/wln/module.make new file mode 100644 index 0000000..6689baf --- /dev/null +++ b/src/base/wln/module.make @@ -0,0 +1,6 @@ +SRC += src/base/wln/wln.c \ + src/base/wln/wlnNdr.c \ + src/base/wln/wlnNtk.c \ + src/base/wln/wlnObj.c \ + src/base/wln/wlnRetime.c \ + src/base/wln/wlnWriteVer.c diff --git a/src/base/wln/wln.c b/src/base/wln/wln.c new file mode 100644 index 0000000..2fbe26e --- /dev/null +++ b/src/base/wln/wln.c @@ -0,0 +1,51 @@ +/**CFile**************************************************************** + + FileName [wln.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Word-level network.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 23, 2018.] + + Revision [$Id: wln.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wln.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/wln/wln.h b/src/base/wln/wln.h new file mode 100644 index 0000000..c862b26 --- /dev/null +++ b/src/base/wln/wln.h @@ -0,0 +1,259 @@ +/**CFile**************************************************************** + + FileName [wlc.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 22, 2014.] + + Revision [$Id: wlc.h,v 1.00 2014/09/12 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__base__wln__wln_h +#define ABC__base__wln__wln_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "aig/gia/gia.h" +#include "misc/vec/vecHash.h" +#include "misc/extra/extra.h" +#include "misc/util/utilNam.h" +#include "misc/util/utilTruth.h" +#include "aig/miniaig/abcOper.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Wln_Vec_t_ Wln_Vec_t; +struct Wln_Vec_t_ +{ + int nCap; + int nSize; + union { int Array[2]; + int * pArray[1]; }; +}; + +typedef struct Wln_Ntk_t_ Wln_Ntk_t; +struct Wln_Ntk_t_ +{ + char * pName; // model name + char * pSpec; // input file name + int fSmtLib; // derived from SMT-LIB + Vec_Int_t vCis; // combinational inputs + Vec_Int_t vCos; // combinational outputs + Vec_Int_t vFfs; // flops + Vec_Int_t vTypes; // object types + Wln_Vec_t * vFanins; // object fanins (exceptions: const, select) + Vec_Int_t vRanges; // object ranges + Hash_IntMan_t * pRanges; // object ranges + Vec_Int_t vNameIds; // object name IDs + Vec_Int_t vInstIds; // object name IDs + Abc_Nam_t * pManName; // object names + Vec_Str_t vSigns; // object signedness + int nTravIds; // counter of traversal IDs + Vec_Int_t vTravIds; // trav IDs of the objects + Vec_Int_t vCopies; // object first bits + Vec_Int_t vBits; // object mapping into AIG nodes + Vec_Int_t vLevels; // object levels + Vec_Int_t vRefs; // object reference counters + Vec_Int_t vFanout; // static fanout + Vec_Int_t vFaninAttrs; // static fanin attributes + Vec_Int_t vFaninLists; // static fanin attributes + Vec_Ptr_t * vTables; // tables + int nObjs[ABC_OPER_LAST]; // counter of objects of each type + int nAnds[ABC_OPER_LAST]; // counter of AND gates after blasting +}; + +static inline int Wln_NtkObjNum( Wln_Ntk_t * p ) { return Vec_IntSize(&p->vTypes); } +static inline int Wln_NtkCiNum( Wln_Ntk_t * p ) { return Vec_IntSize(&p->vCis); } +static inline int Wln_NtkCoNum( Wln_Ntk_t * p ) { return Vec_IntSize(&p->vCos); } +static inline int Wln_NtkFfNum( Wln_Ntk_t * p ) { return Vec_IntSize(&p->vFfs); } +static inline int Wln_NtkPiNum( Wln_Ntk_t * p ) { return Wln_NtkCiNum(p) - Wln_NtkFfNum(p); } +static inline int Wln_NtkPoNum( Wln_Ntk_t * p ) { return Wln_NtkCoNum(p) - Wln_NtkFfNum(p); } + +static inline int Wln_NtkCi( Wln_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vCis, i); } +static inline int Wln_NtkCo( Wln_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vCos, i); } +static inline int Wln_NtkFf( Wln_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vFfs, i); } + +static inline int Wln_ObjType( Wln_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vTypes, i); } +static inline int Wln_ObjIsNone( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_NONE; } +static inline int Wln_ObjIsCi( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_CI; } +static inline int Wln_ObjIsCo( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_CO; } +static inline int Wln_ObjIsCio( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_CI || Wln_ObjType(p, i)==ABC_OPER_CO; } +static inline int Wln_ObjIsFon( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_FON; } +static inline int Wln_ObjIsFf( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_DFFRSE; } +static inline int Wln_ObjIsConst( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_CONST; } +static inline int Wln_ObjIsSlice( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_SLICE; } +static inline int Wln_ObjIsRotate( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_SHIFT_ROTL || Wln_ObjType(p, i) == ABC_OPER_SHIFT_ROTR; } +static inline int Wln_ObjIsTable( Wln_Ntk_t * p, int i ) { return Wln_ObjType(p, i) == ABC_OPER_TABLE; } + +static inline int Wln_ObjFaninNum( Wln_Ntk_t * p, int i ) { return p->vFanins[i].nSize; } +static inline int * Wln_ObjFanins( Wln_Ntk_t * p, int i ) { return Wln_ObjFaninNum(p, i) > 2 ? p->vFanins[i].pArray[0] : p->vFanins[i].Array; } +static inline int Wln_ObjFanin( Wln_Ntk_t * p, int i, int f ) { return Wln_ObjFaninNum(p, i) > 2 ? p->vFanins[i].pArray[0][f] : p->vFanins[i].Array[f]; } +static inline void Wln_ObjSetFanin( Wln_Ntk_t * p, int i, int f, int v ) { Wln_ObjFanins( p, i )[f] = v; } +static inline int Wln_ObjFanin0( Wln_Ntk_t * p, int i ) { return Wln_ObjFanin( p, i, 0 ); } +static inline int Wln_ObjFanin1( Wln_Ntk_t * p, int i ) { return Wln_ObjFanin( p, i, 1 ); } +static inline int Wln_ObjFanin2( Wln_Ntk_t * p, int i ) { return Wln_ObjFanin( p, i, 2 ); } + +static inline int Wln_ObjRangeId( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vRanges, i ); } +static inline int Wln_ObjRangeEnd( Wln_Ntk_t * p, int i ) { return Hash_IntObjData0( p->pRanges, Wln_ObjRangeId(p, i) ); } +static inline int Wln_ObjRangeBeg( Wln_Ntk_t * p, int i ) { return Hash_IntObjData1( p->pRanges, Wln_ObjRangeId(p, i) ); } +static inline int Wln_ObjRangeIsReversed( Wln_Ntk_t * p, int i ) { return Wln_ObjRangeEnd(p, i) < Wln_ObjRangeBeg(p, i); } +static inline int Wln_ObjRange( Wln_Ntk_t * p, int i ) { return 1 + Abc_AbsInt(Wln_ObjRangeEnd(p, i)-Wln_ObjRangeBeg(p, i)); } + +static inline int Wln_ObjIsSigned( Wln_Ntk_t * p, int i ) { return (int)Vec_StrEntry(&p->vSigns, i); } +static inline void Wln_ObjSetSigned( Wln_Ntk_t * p, int i ) { Vec_StrSetEntry(&p->vSigns, i, (char)1); } +static inline int Wln_ObjIsSignedFanin0( Wln_Ntk_t * p, int i ) { return Wln_ObjIsSigned( p, p->fSmtLib ? i : Wln_ObjFanin0(p, i) ); } +static inline int Wln_ObjIsSignedFanin1( Wln_Ntk_t * p, int i ) { return Wln_ObjIsSigned( p, p->fSmtLib ? i : Wln_ObjFanin1(p, i) ); } +static inline int Wln_ObjIsSignedFanin01( Wln_Ntk_t * p, int i ) { return Wln_ObjIsSignedFanin0( p, i ) && Wln_ObjIsSignedFanin1( p, i ); } +static inline int Wln_ObjSign( Wln_Ntk_t * p, int i ) { return Abc_Var2Lit( Wln_ObjRange(p, i), Wln_ObjIsSigned(p, i) ); } + +static inline void Wln_NtkCleanCopy( Wln_Ntk_t * p ) { Vec_IntFill( &p->vCopies, Vec_IntCap(&p->vTypes), 0 ); } +static inline int Wln_NtkHasCopy( Wln_Ntk_t * p ) { return Vec_IntSize( &p->vCopies ) > 0; } +static inline void Wln_ObjSetCopy( Wln_Ntk_t * p, int i, int c ) { Vec_IntWriteEntry( &p->vCopies, i, c ); } +static inline int Wln_ObjCopy( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vCopies, i ); } + +static inline void Wln_NtkCleanLevel( Wln_Ntk_t * p ) { Vec_IntFill( &p->vLevels, Vec_IntCap(&p->vTypes), 0 ); } +static inline int Wln_NtkHasLevel( Wln_Ntk_t * p ) { return Vec_IntSize( &p->vLevels ) > 0; } +static inline void Wln_ObjSetLevel( Wln_Ntk_t * p, int i, int l ) { Vec_IntWriteEntry( &p->vLevels, i, l ); } +static inline int Wln_ObjLevel( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vLevels, i ); } + +static inline void Wln_NtkCleanNameId( Wln_Ntk_t * p ) { Vec_IntFill( &p->vNameIds, Vec_IntCap(&p->vTypes), 0 ); } +static inline int Wln_NtkHasNameId( Wln_Ntk_t * p ) { return Vec_IntSize( &p->vNameIds ) > 0; } +static inline void Wln_ObjSetNameId( Wln_Ntk_t * p, int i, int n ) { Vec_IntWriteEntry( &p->vNameIds, i, n ); } +static inline int Wln_ObjNameId( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vNameIds, i ); } + +static inline void Wln_NtkCleanInstId( Wln_Ntk_t * p ) { Vec_IntFill( &p->vInstIds, Vec_IntCap(&p->vTypes), 0 ); } +static inline int Wln_NtkHasInstId( Wln_Ntk_t * p ) { return Vec_IntSize( &p->vInstIds ) > 0; } +static inline void Wln_ObjSetInstId( Wln_Ntk_t * p, int i, int n ) { Vec_IntWriteEntry( &p->vInstIds, i, n ); } +static inline int Wln_ObjInstId( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vInstIds, i ); } + +static inline void Wln_NtkCleanRefs( Wln_Ntk_t * p ) { Vec_IntFill( &p->vRefs, Vec_IntCap(&p->vTypes), 0 ); } +static inline int Wln_NtkHasRefs( Wln_Ntk_t * p ) { return Vec_IntSize( &p->vRefs ) > 0; } +static inline void Wln_ObjSetRefs( Wln_Ntk_t * p, int i, int n ) { Vec_IntWriteEntry( &p->vRefs, i, n ); } +static inline int Wln_ObjRefs( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vRefs, i ); } +static inline int Wln_ObjRefsInc( Wln_Ntk_t * p, int i ) { return (*Vec_IntEntryP( &p->vRefs, i ))++; } +static inline int Wln_ObjRefsDec( Wln_Ntk_t * p, int i ) { return --(*Vec_IntEntryP( &p->vRefs, i )); } +static inline void Wln_ObjRefsFaninInc( Wln_Ntk_t * p, int i, int k ) { Wln_ObjRefsInc( p, Wln_ObjFanin(p, i, k) ); } +static inline void Wln_ObjRefsFaninDec( Wln_Ntk_t * p, int i, int k ) { Wln_ObjRefsDec( p, Wln_ObjFanin(p, i, k) ); } + +static inline int Wln_ObjFanoutNum( Wln_Ntk_t * p, int i ) { return Vec_IntEntry( &p->vRefs, i ); } +static inline int * Wln_ObjFanouts( Wln_Ntk_t * p, int i ) { return Vec_IntEntryP( &p->vFanout, Vec_IntEntry(&p->vFanout, i) ); } +static inline int Wln_ObjFanout( Wln_Ntk_t * p, int i, int f ) { return Wln_ObjFanouts( p, i )[f]; } +static inline void Wln_ObjSetFanout( Wln_Ntk_t * p, int i, int f, int v ){ Wln_ObjFanouts( p, i )[f] = v; } + +static inline void Wln_NtkIncrementTravId( Wln_Ntk_t * p ) { if (!p->nTravIds++) Vec_IntFill(&p->vTravIds, Vec_IntCap(&p->vTypes), 0); } +static inline void Wln_ObjSetTravIdCurrent( Wln_Ntk_t * p, int i ) { Vec_IntWriteEntry( &p->vTravIds, i, p->nTravIds ); } +static inline int Wln_ObjIsTravIdCurrent( Wln_Ntk_t * p, int i ) { return (Vec_IntEntry(&p->vTravIds, i) == p->nTravIds); } +static inline int Wln_ObjIsTravIdPrevious( Wln_Ntk_t * p, int i ) { return (Vec_IntEntry(&p->vTravIds, i) == p->nTravIds-1); } +static inline int Wln_ObjCheckTravId( Wln_Ntk_t * p, int i ) { if ( Wln_ObjIsTravIdCurrent(p, i) ) return 1; Wln_ObjSetTravIdCurrent(p, i); return 0; } + +static inline int Wln_ObjCioId( Wln_Ntk_t * p, int i ) { assert( Wln_ObjIsCio(p, i) ); return Wln_ObjFanin1(p, i); } +static inline int Wln_ObjIsPi( Wln_Ntk_t * p, int i ) { return Wln_ObjIsCi(p, i) && Wln_ObjCioId(p, i) < Wln_NtkPiNum(p); } +static inline int Wln_ObjIsPo( Wln_Ntk_t * p, int i ) { return Wln_ObjIsCo(p, i) && Wln_ObjCioId(p, i) < Wln_NtkPoNum(p); } +static inline int Wln_ObjIsRo( Wln_Ntk_t * p, int i ) { return Wln_ObjIsCi(p, i) && Wln_ObjCioId(p, i) >= Wln_NtkPiNum(p); } +static inline int Wln_ObjIsRi( Wln_Ntk_t * p, int i ) { return Wln_ObjIsCo(p, i) && Wln_ObjCioId(p, i) >= Wln_NtkPoNum(p); } +static inline int Wln_ObjRoToRi( Wln_Ntk_t * p, int i ) { assert( Wln_ObjIsRo(p, i) ); return Wln_NtkCo(p, Wln_NtkCoNum(p) - Wln_NtkCiNum(p) + Wln_ObjCioId(p, i)); } +static inline int Wln_ObjRiToRo( Wln_Ntk_t * p, int i ) { assert( Wln_ObjIsRi(p, i) ); return Wln_NtkCi(p, Wln_NtkCiNum(p) - Wln_NtkCoNum(p) + Wln_ObjCioId(p, i)); } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +#define Wln_NtkForEachObj( p, i ) \ + for ( i = 1; i < Wln_NtkObjNum(p); i++ ) +#define Wln_NtkForEachObjReverse( p, i ) \ + for ( i = Wln_NtkObjNum(p) - 1; i > 0; i-- ) +#define Wln_NtkForEachObjInternal( p, i ) \ + for ( i = 1; i < Wln_NtkObjNum(p); i++ ) if ( Wln_ObjIsCio(p, i) ) {} else + +#define Wln_NtkForEachPi( p, iPi, i ) \ + for ( i = 0; (i < Wln_NtkPiNum(p)) && (((iPi) = Wln_NtkCi(p, i)), 1); i++ ) +#define Wln_NtkForEachPo( p, iPo, i ) \ + for ( i = 0; (i < Wln_NtkPoNum(p)) && (((iPo) = Wln_NtkCo(p, i)), 1); i++ ) +#define Wln_NtkForEachCi( p, iCi, i ) \ + for ( i = 0; (i < Wln_NtkCiNum(p)) && (((iCi) = Wln_NtkCi(p, i)), 1); i++ ) +#define Wln_NtkForEachCo( p, iCo, i ) \ + for ( i = 0; (i < Wln_NtkCoNum(p)) && (((iCo) = Wln_NtkCo(p, i)), 1); i++ ) +#define Wln_NtkForEachFf( p, iFf, i ) \ + for ( i = 0; (i < Wln_NtkFfNum(p)) && (((iFf) = Wln_NtkFf(p, i)), 1); i++ ) + +#define Wln_ObjForEachFanin( p, iObj, iFanin, i ) \ + for ( i = 0; (i < Wln_ObjFaninNum(p, iObj)) && (((iFanin) = Wln_ObjFanin(p, iObj, i)), 1); i++ ) if ( !iFanin ) {} else +#define Wln_ObjForEachFaninReverse( pObj, iFanin, i ) \ + for ( i = Wln_ObjFaninNum(p, iObj) - 1; (i >= 0) && (((iFanin) = Wln_ObjFanin(p, iObj, i)), 1); i-- ) if ( !iFanin ) {} else + +#define Wln_ObjForEachFanoutStatic( p, iObj, iFanout, i ) \ + for ( i = 0; (i < Wln_ObjRefs(p, iObj)) && (((iFanout) = Wln_ObjFanout(p, iObj, i)), 1); i++ ) + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== wlcNdr.c ========================================================*/ +extern Wln_Ntk_t * Wln_ReadNdr( char * pFileName ); +extern void Wln_WriteNdr( Wln_Ntk_t * pNtk, char * pFileName ); +extern Wln_Ntk_t * Wln_NtkFromNdr( void * pData ); +extern void * Wln_NtkToNdr( Wln_Ntk_t * pNtk ); +/*=== wlcNtk.c ========================================================*/ +extern Wln_Ntk_t * Wln_NtkAlloc( char * pName, int nObjsMax ); +extern void Wln_NtkFree( Wln_Ntk_t * p ); +extern int Wln_NtkMemUsage( Wln_Ntk_t * p ); +extern void Wln_NtkPrint( Wln_Ntk_t * p ); +extern Wln_Ntk_t * Wln_NtkDupDfs( Wln_Ntk_t * p ); +extern void Wln_NtkCreateRefs( Wln_Ntk_t * p ); +extern void Wln_NtkStartFaninMap( Wln_Ntk_t * p, Vec_Int_t * vFaninMap, int nMulti ); +extern void Wln_NtkStartFanoutMap( Wln_Ntk_t * p, Vec_Int_t * vFanoutMap, Vec_Int_t * vFanoutNums, int nMulti ); +extern void Wln_NtkStaticFanoutStart( Wln_Ntk_t * p ); +extern void Wln_NtkStaticFanoutStop( Wln_Ntk_t * p ); +extern void Wln_NtkStaticFanoutTest( Wln_Ntk_t * p ); +/*=== wlcObj.c ========================================================*/ +extern char * Wln_ObjName( Wln_Ntk_t * p, int iObj ); +extern char * Wln_ObjConstString( Wln_Ntk_t * p, int iObj ); +extern void Wln_ObjUpdateType( Wln_Ntk_t * p, int iObj, int Type ); +extern void Wln_ObjSetConst( Wln_Ntk_t * p, int iObj, int NameId ); +extern void Wln_ObjSetSlice( Wln_Ntk_t * p, int iObj, int SliceId ); +extern void Wln_ObjAddFanin( Wln_Ntk_t * p, int iObj, int i ); +extern int Wln_ObjAddFanins( Wln_Ntk_t * p, int iObj, Vec_Int_t * vFanins ); +extern int Wln_ObjAlloc( Wln_Ntk_t * p, int Type, int Signed, int End, int Beg ); +extern int Wln_ObjClone( Wln_Ntk_t * pNew, Wln_Ntk_t * p, int iObj ); +extern int Wln_ObjCreateCo( Wln_Ntk_t * p, int iFanin ); +extern void Wln_ObjPrint( Wln_Ntk_t * p, int iObj ); +/*=== wlcRetime.c ========================================================*/ +extern Vec_Int_t * Wln_NtkRetime( Wln_Ntk_t * p ); +/*=== wlcWriteVer.c ========================================================*/ +extern void Wln_WriteVer( Wln_Ntk_t * p, char * pFileName ); + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/base/wln/wlnNdr.c b/src/base/wln/wlnNdr.c new file mode 100644 index 0000000..c87100a --- /dev/null +++ b/src/base/wln/wlnNdr.c @@ -0,0 +1,332 @@ +/**CFile**************************************************************** + + FileName [wlnNdr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Word-level network.] + + Synopsis [Constructing WLN network from NDR data structure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 23, 2018.] + + Revision [$Id: wlnNdr.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wln.h" +#include "aig/miniaig/ndr.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Wln_NtkToNdr( Wln_Ntk_t * p ) +{ + Vec_Int_t * vFanins; + int i, k, iObj, iFanin; + // create a new module + void * pDesign = Ndr_Create( 1 ); + int ModId = Ndr_AddModule( pDesign, 1 ); + // add primary inputs + Wln_NtkForEachPi( p, iObj, i ) + { + Ndr_AddObject( pDesign, ModId, ABC_OPER_CI, 0, + Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj), Wln_ObjIsSigned(p, iObj), + 0, NULL, 1, &iObj, NULL ); // no fanins + } + // add internal nodes + vFanins = Vec_IntAlloc( 10 ); + Wln_NtkForEachObjInternal( p, iObj ) + { + Vec_IntClear( vFanins ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + Vec_IntPush( vFanins, iFanin ); + Ndr_AddObject( pDesign, ModId, Wln_ObjType(p, iObj), 0, + Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj), Wln_ObjIsSigned(p, iObj), + Vec_IntSize(vFanins), Vec_IntArray(vFanins), 1, &iObj, + Wln_ObjIsConst(p, iObj) ? Wln_ObjConstString(p, iObj) : NULL ); + } + Vec_IntFree( vFanins ); + // add primary outputs + Wln_NtkForEachPo( p, iObj, i ) + { + Ndr_AddObject( pDesign, ModId, ABC_OPER_CO, 0, + Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj), Wln_ObjIsSigned(p, iObj), + 1, &iObj, 0, NULL, NULL ); + } + return pDesign; +} +void Wln_WriteNdr( Wln_Ntk_t * p, char * pFileName ) +{ + void * pDesign = Wln_NtkToNdr( p ); + Ndr_Write( pFileName, pDesign ); + Ndr_Delete( pDesign ); + printf( "Dumped the current design into file \"%s\".\n", pFileName ); +} +void Wln_NtkToNdrTest( Wln_Ntk_t * p ) +{ + // transform + void * pDesign = Wln_NtkToNdr( p ); + + // collect names + char ** ppNames = ABC_ALLOC( char *, Wln_NtkObjNum(p) + 1 ); int i; + Wln_NtkForEachObj( p, i ) + ppNames[i] = Abc_UtilStrsav(Wln_ObjName(p, i)); + + // verify by writing Verilog + Ndr_WriteVerilog( NULL, pDesign, ppNames ); + Ndr_Write( "test.ndr", pDesign ); + + // cleanup + Ndr_Delete( pDesign ); + Wln_NtkForEachObj( p, i ) + ABC_FREE( ppNames[i] ); + ABC_FREE( ppNames ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ndr_ObjGetRange( Ndr_Data_t * p, int Obj, int * End, int * Beg ) +{ + int * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_RANGE, &pArray ); + int Signed = 0; *End = *Beg = 0; + if ( nArray == 0 ) + return 0; + if ( nArray == 3 ) + Signed = 1; + if ( nArray == 1 ) + *End = *Beg = pArray[0]; + else + *End = pArray[0], *Beg = pArray[1]; + return Signed; +} +void Ndr_NtkPrintObjects( Wln_Ntk_t * pNtk ) +{ + int k, iObj, iFanin; + printf( "Node IDs and their fanins:\n" ); + Wln_NtkForEachObj( pNtk, iObj ) + { + printf( "%5d = ", iObj ); + Wln_ObjForEachFanin( pNtk, iObj, iFanin, k ) + printf( "%5d ", iFanin ); + for ( ; k < 4; k++ ) + printf( " " ); + printf( " Name Id %d ", Wln_ObjNameId(pNtk, iObj) ); + if ( Wln_ObjIsPi(pNtk, iObj) ) + printf( " pi " ); + if ( Wln_ObjIsPo(pNtk, iObj) ) + printf( " po " ); + printf( "\n" ); + } +} +void Wln_NtkCheckIntegrity( void * pData ) +{ + Ndr_Data_t * p = (Ndr_Data_t *)pData; + Vec_Int_t * vMap = Vec_IntAlloc( 100 ); + int Mod = 2, Obj; + Ndr_ModForEachObj( p, Mod, Obj ) + { + int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); + if ( NameId == -1 ) + { + int Type = Ndr_ObjReadBody( p, Obj, NDR_OPERTYPE ); + if ( Type != ABC_OPER_CO ) + printf( "Internal object %d of type %s has no output name.\n", Obj, Abc_OperName(Type) ); + continue; + } + if ( Vec_IntGetEntry(vMap, NameId) > 0 ) + printf( "Output name %d is used more than once (obj %d and obj %d).\n", NameId, Vec_IntGetEntry(vMap, NameId), Obj ); + Vec_IntSetEntry( vMap, NameId, Obj ); + } + Ndr_ModForEachObj( p, Mod, Obj ) + { + int Type = Ndr_ObjReadBody( p, Obj, NDR_OPERTYPE ); + int i, * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + for ( i = 0; i < nArray; i++ ) + if ( Vec_IntGetEntry(vMap, pArray[i]) == 0 && !(Type == ABC_OPER_DFFRSE && (i >= 5 || i <= 7)) ) + printf( "Input name %d appearing as fanin %d of obj %d is not used as output name in any object.\n", pArray[i], i, Obj ); + } + Vec_IntFree( vMap ); +} +Wln_Ntk_t * Wln_NtkFromNdr( void * pData ) +{ + Ndr_Data_t * p = (Ndr_Data_t *)pData; + Vec_Int_t * vName2Obj, * vFanins = Vec_IntAlloc( 100 ); + Vec_Ptr_t * vConstStrings = Vec_PtrAlloc( 100 ); + int Mod = 2, i, k, iFanin, iObj, Obj, * pArray, nDigits, fFound, NameId, NameIdMax; + Wln_Ntk_t * pTemp, * pNtk = Wln_NtkAlloc( "top", Ndr_DataObjNum(p, Mod) ); + Wln_NtkCheckIntegrity( pData ); + //pNtk->pSpec = Abc_UtilStrsav( pFileName ); + // construct network and save name IDs + Wln_NtkCleanNameId( pNtk ); + Wln_NtkCleanInstId( pNtk ); + Ndr_ModForEachPi( p, Mod, Obj ) + { + int End, Beg, Signed = Ndr_ObjGetRange(p, Obj, &End, &Beg); + int iObj = Wln_ObjAlloc( pNtk, ABC_OPER_CI, Signed, End, Beg ); + int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); + int InstId = Ndr_ObjReadBody( p, Obj, NDR_NAME ); + Wln_ObjSetNameId( pNtk, iObj, NameId ); + if ( InstId > 0 ) Wln_ObjSetInstId( pNtk, iObj, InstId ); + } + Ndr_ModForEachNode( p, Mod, Obj ) + { + int End, Beg, Signed = Ndr_ObjGetRange(p, Obj, &End, &Beg); + int Type = Ndr_ObjReadBody( p, Obj, NDR_OPERTYPE ); + int nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + Vec_Int_t F = {nArray, nArray, pArray}, * vTemp = &F; + int iObj = Wln_ObjAlloc( pNtk, Type, Signed, End, Beg ); + int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); + int InstId = Ndr_ObjReadBody( p, Obj, NDR_NAME ); + Vec_IntClear( vFanins ); + Vec_IntAppend( vFanins, vTemp ); + assert( Type != ABC_OPER_DFF ); + if ( Wln_ObjIsSlice(pNtk, iObj) ) + Wln_ObjSetSlice( pNtk, iObj, Hash_Int2ManInsert(pNtk->pRanges, End, Beg, 0) ); + else if ( Wln_ObjIsConst(pNtk, iObj) ) + Vec_PtrPush( vConstStrings, (char *)Ndr_ObjReadBodyP(p, Obj, NDR_FUNCTION) ); +// else if ( Type == ABC_OPER_BIT_MUX && Vec_IntSize(vFanins) == 3 ) +// ABC_SWAP( int, Wln_ObjFanins(pNtk, iObj)[1], Wln_ObjFanins(pNtk, iObj)[2] ); + Wln_ObjAddFanins( pNtk, iObj, vFanins ); + Wln_ObjSetNameId( pNtk, iObj, NameId ); + if ( InstId > 0 ) Wln_ObjSetInstId( pNtk, iObj, InstId ); + if ( Type == ABC_OPER_ARI_SMUL ) + { + assert( Wln_ObjFaninNum(pNtk, iObj) == 2 ); + Wln_ObjSetSigned( pNtk, Wln_ObjFanin0(pNtk, iObj) ); + Wln_ObjSetSigned( pNtk, Wln_ObjFanin1(pNtk, iObj) ); + } + } + // mark primary outputs + Ndr_ModForEachPo( p, Mod, Obj ) + { + int End, Beg, Signed = Ndr_ObjGetRange(p, Obj, &End, &Beg); + int nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + int iObj = Wln_ObjAlloc( pNtk, ABC_OPER_CO, Signed, End, Beg ); + int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); + int InstId = Ndr_ObjReadBody( p, Obj, NDR_NAME ); + assert( nArray == 1 && NameId == -1 && InstId == -1 ); + Wln_ObjAddFanin( pNtk, iObj, pArray[0] ); + } + Vec_IntFree( vFanins ); + // remove instance names if they are not given + //Vec_IntPrint( &pNtk->vInstIds ); + if ( Vec_IntCountPositive(&pNtk->vInstIds) == 0 ) + Vec_IntErase( &pNtk->vInstIds ); + // map name IDs into object IDs + vName2Obj = Vec_IntInvert( &pNtk->vNameIds, 0 ); + Wln_NtkForEachObj( pNtk, i ) + Wln_ObjForEachFanin( pNtk, i, iFanin, k ) + Wln_ObjSetFanin( pNtk, i, k, Vec_IntEntry(vName2Obj, iFanin) ); + Vec_IntFree(vName2Obj); + // create fake object names + NameIdMax = Vec_IntFindMax(&pNtk->vNameIds); + nDigits = Abc_Base10Log( NameIdMax+1 ); + pNtk->pManName = Abc_NamStart( NameIdMax+1, 10 ); + for ( i = 1; i <= NameIdMax; i++ ) + { + char pName[20]; sprintf( pName, "s%0*d", nDigits, i ); + NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound ); + assert( !fFound && i == NameId ); + } + // add const strings + i = 0; + Wln_NtkForEachObj( pNtk, iObj ) + if ( Wln_ObjIsConst(pNtk, iObj) ) + Wln_ObjSetConst( pNtk, iObj, Abc_NamStrFindOrAdd(pNtk->pManName, (char *)Vec_PtrEntry(vConstStrings, i++), NULL) ); + assert( i == Vec_PtrSize(vConstStrings) ); + Vec_PtrFree( vConstStrings ); + //Ndr_NtkPrintObjects( pNtk ); + //Wln_WriteVer( pNtk, "temp_ndr.v", 0, 0 ); + // derive topological order + pNtk = Wln_NtkDupDfs( pTemp = pNtk ); + Wln_NtkFree( pTemp ); + //Ndr_NtkPrintObjects( pNtk ); + //pNtk->fMemPorts = 1; // the network contains memory ports + //pNtk->fEasyFfs = 1; // the network contains simple flops + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Wln_Ntk_t * Wln_ReadNdr( char * pFileName ) +{ + void * pData = Ndr_Read( pFileName ); + Wln_Ntk_t * pNtk = Wln_NtkFromNdr( pData ); + //char * ppNames[10] = { NULL, "a", "b", "c", "d", "e", "f", "g", "h", "i" }; + //Ndr_WriteVerilog( NULL, pData, ppNames ); + Ndr_Delete( pData ); + return pNtk; +} +void Wln_ReadNdrTest() +{ + Wln_Ntk_t * pNtk = Wln_ReadNdr( "D:\\temp\\brijesh\\for_alan_dff_warning\\work_fir_filter_fir_filter_proc_out.ndr" ); + //Wln_Ntk_t * pNtk = Wln_ReadNdr( "flop.ndr" ); + Wln_WriteVer( pNtk, "test__test.v" ); + Wln_NtkPrint( pNtk ); + Wln_NtkStaticFanoutTest( pNtk ); + Wln_NtkFree( pNtk ); +} +void Wln_NtkRetimeTest( char * pFileName ) +{ + void * pData = Ndr_Read( pFileName ); + Wln_Ntk_t * pNtk = Wln_NtkFromNdr( pData ); + Ndr_Delete( pData ); + if ( !Wln_NtkHasInstId(pNtk) ) + printf( "The design has no delay information.\n" ); + else + { + Vec_Int_t * vMoves = Wln_NtkRetime( pNtk ); + Vec_IntPrint( vMoves ); + Vec_IntFree( vMoves ); + } + Wln_NtkFree( pNtk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/wln/wlnNtk.c b/src/base/wln/wlnNtk.c new file mode 100644 index 0000000..39c0396 --- /dev/null +++ b/src/base/wln/wlnNtk.c @@ -0,0 +1,321 @@ +/**CFile**************************************************************** + + FileName [wlnNtk.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Word-level network.] + + Synopsis [Network construction procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 23, 2018.] + + Revision [$Id: wlnNtk.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wln.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creating networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Wln_Ntk_t * Wln_NtkAlloc( char * pName, int nObjsMax ) +{ + Wln_Ntk_t * p; int i; + p = ABC_CALLOC( Wln_Ntk_t, 1 ); + p->pName = pName ? Extra_FileNameGeneric( pName ) : NULL; + Vec_IntGrow( &p->vCis, 111 ); + Vec_IntGrow( &p->vCos, 111 ); + Vec_IntGrow( &p->vFfs, 111 ); + Vec_IntGrow( &p->vTypes, nObjsMax+1 ); + Vec_StrGrow( &p->vSigns, nObjsMax+1 ); + Vec_IntGrow( &p->vRanges, nObjsMax+1 ); + Vec_IntPush( &p->vTypes, -1 ); + Vec_StrPush( &p->vSigns, -1 ); + Vec_IntPush( &p->vRanges, -1 ); + p->vFanins = ABC_CALLOC( Wln_Vec_t, nObjsMax+1 ); + p->pRanges = Hash_IntManStart( 1000 ); + for ( i = 0; i < 65; i++ ) + Hash_Int2ManInsert( p->pRanges, i, i, 0 ); + for ( i = 1; i < 64; i++ ) + Hash_Int2ManInsert( p->pRanges, i, 0, 0 ); + assert( Hash_IntManEntryNum(p->pRanges) == 128 ); + return p; +} +void Wln_NtkFree( Wln_Ntk_t * p ) +{ + int i; + for ( i = 0; i < Wln_NtkObjNum(p); i++ ) + if ( Wln_ObjFaninNum(p, i) > 2 ) + ABC_FREE( p->vFanins[i].pArray[0] ); + ABC_FREE( p->vFanins ); + + if ( p->pRanges ) Hash_IntManStop( p->pRanges ); + if ( p->pManName ) Abc_NamStop( p->pManName ); + + ABC_FREE( p->vCis.pArray ); + ABC_FREE( p->vCos.pArray ); + ABC_FREE( p->vFfs.pArray ); + + ABC_FREE( p->vTypes.pArray ); + ABC_FREE( p->vSigns.pArray ); + ABC_FREE( p->vRanges.pArray ); + ABC_FREE( p->vNameIds.pArray ); + ABC_FREE( p->vInstIds.pArray ); + ABC_FREE( p->vTravIds.pArray ); + ABC_FREE( p->vCopies.pArray ); + ABC_FREE( p->vBits.pArray ); + ABC_FREE( p->vLevels.pArray ); + ABC_FREE( p->vRefs.pArray ); + ABC_FREE( p->vFanout.pArray ); + ABC_FREE( p->vFaninAttrs.pArray ); + ABC_FREE( p->vFaninLists.pArray ); + + ABC_FREE( p->pName ); + ABC_FREE( p->pSpec ); + ABC_FREE( p ); +} +int Wln_NtkMemUsage( Wln_Ntk_t * p ) +{ + int Mem = sizeof(Wln_Ntk_t); + Mem += 4 * p->vCis.nCap; + Mem += 4 * p->vCos.nCap; + Mem += 4 * p->vFfs.nCap; + Mem += 1 * p->vTypes.nCap; + Mem += 4 * p->vRanges.nCap; + Mem += 4 * p->vNameIds.nCap; + Mem += 4 * p->vInstIds.nCap; + Mem += 4 * p->vTravIds.nCap; + Mem += 4 * p->vCopies.nCap; + Mem += 4 * p->vBits.nCap; + Mem += 4 * p->vLevels.nCap; + Mem += 4 * p->vRefs.nCap; + Mem += 4 * p->vFanout.nCap; + Mem += 4 * p->vFaninAttrs.nCap; + Mem += 4 * p->vFaninLists.nCap; + Mem += 20 * Hash_IntManEntryNum(p->pRanges); + Mem += Abc_NamMemUsed(p->pManName); + return Mem; +} +void Wln_NtkPrint( Wln_Ntk_t * p ) +{ + int iObj; + printf( "Printing %d objects of network \"%s\":\n", Wln_NtkObjNum(p), p->pName ); + Wln_NtkForEachObj( p, iObj ) + Wln_ObjPrint( p, iObj ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Duplicating network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_NtkTransferNames( Wln_Ntk_t * pNew, Wln_Ntk_t * p ) +{ + assert( pNew->pManName == NULL && p->pManName != NULL ); + pNew->pManName = p->pManName; + p->pManName = NULL; + assert( !Wln_NtkHasCopy(pNew) && Wln_NtkHasCopy(p) ); + if ( Wln_NtkHasNameId(p) ) + { + int i; + assert( !Wln_NtkHasNameId(pNew) && Wln_NtkHasNameId(p) ); + Wln_NtkCleanNameId( pNew ); + Wln_NtkForEachObj( p, i ) + if ( Wln_ObjCopy(p, i) && i < Vec_IntSize(&p->vNameIds) && Wln_ObjNameId(p, i) ) + Wln_ObjSetNameId( pNew, Wln_ObjCopy(p, i), Wln_ObjNameId(p, i) ); + Vec_IntErase( &p->vNameIds ); + } + if ( Wln_NtkHasInstId(p) ) + { + int i; + assert( !Wln_NtkHasInstId(pNew) && Wln_NtkHasInstId(p) ); + Wln_NtkCleanInstId( pNew ); + Wln_NtkForEachObj( p, i ) + if ( Wln_ObjCopy(p, i) && i < Vec_IntSize(&p->vInstIds) && Wln_ObjInstId(p, i) ) + Wln_ObjSetInstId( pNew, Wln_ObjCopy(p, i), Wln_ObjInstId(p, i) ); + Vec_IntErase( &p->vInstIds ); + } +} +int Wln_ObjDup( Wln_Ntk_t * pNew, Wln_Ntk_t * p, int iObj ) +{ + int i, iFanin, iObjNew = Wln_ObjClone( pNew, p, iObj ); + Wln_ObjForEachFanin( p, iObj, iFanin, i ) + Wln_ObjAddFanin( pNew, iObjNew, Wln_ObjCopy(p, iFanin) ); + if ( Wln_ObjIsConst(p, iObj) ) + Wln_ObjSetConst( pNew, iObjNew, Wln_ObjFanin0(p, iObj) ); + else if ( Wln_ObjIsSlice(p, iObj) || Wln_ObjIsRotate(p, iObj) || Wln_ObjIsTable(p, iObj) ) + Wln_ObjSetFanin( p, iObjNew, 1, Wln_ObjFanin1(p, iObj) ); + Wln_ObjSetCopy( p, iObj, iObjNew ); + return iObjNew; +} +int Wln_NtkDupDfs_rec( Wln_Ntk_t * pNew, Wln_Ntk_t * p, int iObj ) +{ + int i, iFanin; + if ( iObj == 0 ) + return 0; + if ( Wln_ObjCopy(p, iObj) ) + return Wln_ObjCopy(p, iObj); + //printf( "Visiting node %d\n", iObj ); + assert( !Wln_ObjIsFf(p, iObj) ); + Wln_ObjForEachFanin( p, iObj, iFanin, i ) + Wln_NtkDupDfs_rec( pNew, p, iFanin ); + return Wln_ObjDup( pNew, p, iObj ); +} +Wln_Ntk_t * Wln_NtkDupDfs( Wln_Ntk_t * p ) +{ + int i, k, iObj, iFanin; + Wln_Ntk_t * pNew = Wln_NtkAlloc( p->pName, Wln_NtkObjNum(p) ); + pNew->fSmtLib = p->fSmtLib; + if ( p->pSpec ) pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Wln_NtkCleanCopy( p ); + Wln_NtkForEachCi( p, iObj, i ) + Wln_ObjDup( pNew, p, iObj ); + Wln_NtkForEachFf( p, iObj, i ) + Wln_ObjSetCopy( p, iObj, Wln_ObjClone(pNew, p, iObj) ); + Wln_NtkForEachCo( p, iObj, i ) + Wln_NtkDupDfs_rec( pNew, p, iObj ); + Wln_NtkForEachFf( p, iObj, i ) + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + Wln_ObjAddFanin( pNew, Wln_ObjCopy(p, iObj), Wln_NtkDupDfs_rec(pNew, p, iFanin) ); + if ( Wln_NtkHasNameId(p) ) + Wln_NtkTransferNames( pNew, p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Create fanin/fanout map.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_NtkCreateRefs( Wln_Ntk_t * p ) +{ + int k, iObj, iFanin; + Wln_NtkCleanRefs( p ); + Wln_NtkForEachObj( p, iObj ) + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + Wln_ObjRefsInc( p, iFanin ); +} +int Wln_NtkFaninNum( Wln_Ntk_t * p ) +{ + int iObj, nEdges = 0; + Wln_NtkForEachObj( p, iObj ) + nEdges += Wln_ObjFaninNum(p, iObj); + return nEdges; +} +void Wln_NtkStartFaninMap( Wln_Ntk_t * p, Vec_Int_t * vFaninMap, int nMulti ) +{ + int iObj, iOffset = Wln_NtkObjNum(p); + Vec_IntFill( vFaninMap, iOffset + nMulti * Wln_NtkFaninNum(p), 0 ); + Wln_NtkForEachObj( p, iObj ) + { + Vec_IntWriteEntry( vFaninMap, iObj, iOffset ); + iOffset += nMulti * Wln_ObjFaninNum(p, iObj); + } + assert( iOffset == Vec_IntSize(vFaninMap) ); +} +void Wln_NtkStartFanoutMap( Wln_Ntk_t * p, Vec_Int_t * vFanoutMap, Vec_Int_t * vFanoutNums, int nMulti ) +{ + int iObj, iOffset = Wln_NtkObjNum(p); + Vec_IntFill( vFanoutMap, iOffset + nMulti * Vec_IntSum(vFanoutNums), 0 ); + Wln_NtkForEachObj( p, iObj ) + { + Vec_IntWriteEntry( vFanoutMap, iObj, iOffset ); + iOffset += nMulti * Wln_ObjRefs(p, iObj); + } + assert( iOffset == Vec_IntSize(vFanoutMap) ); +} + +/**Function************************************************************* + + Synopsis [Static fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_NtkStaticFanoutStart( Wln_Ntk_t * p ) +{ + int k, iObj, iFanin; + Vec_Int_t * vRefsCopy = Vec_IntAlloc(0); + Wln_NtkCreateRefs( p ); + Wln_NtkStartFanoutMap( p, &p->vFanout, &p->vRefs, 1 ); + ABC_SWAP( Vec_Int_t, *vRefsCopy, p->vRefs ); + // add fanouts + Wln_NtkCleanRefs( p ); + Wln_NtkForEachObj( p, iObj ) + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + Wln_ObjSetFanout( p, iFanin, Wln_ObjRefsInc(p, iFanin), iObj ); + // double-check the current number of fanouts added + Wln_NtkForEachObj( p, iObj ) + assert( Wln_ObjRefs(p, iObj) == Vec_IntEntry(vRefsCopy, iObj) ); + Vec_IntFree( vRefsCopy ); +} +void Wln_NtkStaticFanoutStop( Wln_Ntk_t * p ) +{ + Vec_IntErase( &p->vRefs ); + Vec_IntErase( &p->vFanout ); +} +void Wln_NtkStaticFanoutTest( Wln_Ntk_t * p ) +{ + int k, iObj, iFanout; + printf( "Printing fanouts of %d objects of network \"%s\":\n", Wln_NtkObjNum(p), p->pName ); + Wln_NtkStaticFanoutStart( p ); + Wln_NtkForEachObj( p, iObj ) + { + Wln_ObjPrint( p, iObj ); + printf( " Fanouts : " ); + Wln_ObjForEachFanoutStatic( p, iObj, iFanout, k ) + printf( "%5d ", iFanout ); + printf( "\n" ); + } + Wln_NtkStaticFanoutStop( p ); + printf( "\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/wln/wlnObj.c b/src/base/wln/wlnObj.c new file mode 100644 index 0000000..ec37330 --- /dev/null +++ b/src/base/wln/wlnObj.c @@ -0,0 +1,151 @@ +/**CFile**************************************************************** + + FileName [wlnObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Word-level network.] + + Synopsis [Object construction procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 23, 2018.] + + Revision [$Id: wlnObj.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wln.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creating objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Wln_ObjName( Wln_Ntk_t * p, int iObj ) +{ + static char Buffer[100]; + if ( Wln_NtkHasNameId(p) && Wln_ObjNameId(p, iObj) ) + return Abc_NamStr( p->pManName, Wln_ObjNameId(p, iObj) ); + sprintf( Buffer, "n%d", iObj ); + return Buffer; +} +char * Wln_ObjConstString( Wln_Ntk_t * p, int iObj ) +{ + assert( Wln_ObjIsConst(p, iObj) ); + return Abc_NamStr( p->pManName, Wln_ObjFanin0(p, iObj) ); +} +void Wln_ObjUpdateType( Wln_Ntk_t * p, int iObj, int Type ) +{ + assert( Wln_ObjIsNone(p, iObj) ); + p->nObjs[Wln_ObjType(p, iObj)]--; + Vec_IntWriteEntry( &p->vTypes, iObj, Type ); + p->nObjs[Wln_ObjType(p, iObj)]++; +} +void Wln_ObjSetConst( Wln_Ntk_t * p, int iObj, int NameId ) +{ + assert( Wln_ObjIsConst(p, iObj) ); + Wln_ObjSetFanin( p, iObj, 0, NameId ); +} +void Wln_ObjSetSlice( Wln_Ntk_t * p, int iObj, int SliceId ) +{ + assert( Wln_ObjIsSlice(p, iObj) ); + Wln_ObjSetFanin( p, iObj, 1, SliceId ); +} +void Wln_ObjAddFanin( Wln_Ntk_t * p, int iObj, int i ) +{ + Wln_Vec_t * pVec = p->vFanins + iObj; + if ( Wln_ObjFaninNum(p, iObj) < 2 ) + pVec->Array[pVec->nSize++] = i; + else if ( Wln_ObjFaninNum(p, iObj) == 2 ) + { + int * pArray = ABC_ALLOC( int, 4 ); + pArray[0] = pVec->Array[0]; + pArray[1] = pVec->Array[1]; + pArray[2] = i; + pVec->pArray[0] = pArray; + pVec->nSize = 3; + pVec->nCap = 4; + } + else + { + if ( pVec->nSize == pVec->nCap ) + pVec->pArray[0] = ABC_REALLOC( int, pVec->pArray[0], (pVec->nCap = 2*pVec->nSize) ); + assert( pVec->nSize < pVec->nCap ); + pVec->pArray[0][pVec->nSize++] = i; + } +} +int Wln_ObjAddFanins( Wln_Ntk_t * p, int iObj, Vec_Int_t * vFanins ) +{ + int i, iFanin; + Vec_IntForEachEntry( vFanins, iFanin, i ) + Wln_ObjAddFanin( p, iObj, iFanin ); + return iObj; +} +int Wln_ObjAlloc( Wln_Ntk_t * p, int Type, int Signed, int End, int Beg ) +{ + int iObj = Vec_IntSize(&p->vTypes); + if ( iObj == Vec_IntCap(&p->vTypes) ) + { + p->vFanins = ABC_REALLOC( Wln_Vec_t, p->vFanins, 2 * iObj ); + memset( p->vFanins + iObj, 0, sizeof(Wln_Vec_t) * iObj ); + Vec_IntGrow( &p->vTypes, 2 * iObj ); + } + assert( iObj == Vec_StrSize(&p->vSigns) ); + assert( iObj == Vec_IntSize(&p->vRanges) ); + Vec_IntPush( &p->vTypes, Type ); + Vec_StrPush( &p->vSigns, (char)Signed ); + Vec_IntPush( &p->vRanges, Hash_Int2ManInsert(p->pRanges, End, Beg, 0) ); + if ( Wln_ObjIsCi(p, iObj) ) Wln_ObjSetFanin( p, iObj, 1, Vec_IntSize(&p->vCis) ), Vec_IntPush( &p->vCis, iObj ); + if ( Wln_ObjIsCo(p, iObj) ) Wln_ObjSetFanin( p, iObj, 1, Vec_IntSize(&p->vCos) ), Vec_IntPush( &p->vCos, iObj ); + if ( Wln_ObjIsFf(p, iObj) ) Vec_IntPush( &p->vFfs, iObj ); + p->nObjs[Type]++; + return iObj; +} +int Wln_ObjClone( Wln_Ntk_t * pNew, Wln_Ntk_t * p, int iObj ) +{ + return Wln_ObjAlloc( pNew, Wln_ObjType(p, iObj), Wln_ObjIsSigned(p, iObj), Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj) ); +} +int Wln_ObjCreateCo( Wln_Ntk_t * p, int iFanin ) +{ + int iCo = Wln_ObjClone( p, p, iFanin ); + Wln_ObjUpdateType( p, iCo, ABC_OPER_CO ); + Wln_ObjAddFanin( p, iCo, iFanin ); + return iCo; +} +void Wln_ObjPrint( Wln_Ntk_t * p, int iObj ) +{ + int k, iFanin, Type = Wln_ObjType(p, iObj); + printf( "Obj %6d : Type = %6s Fanins = %d : ", iObj, Abc_OperName(Type), Wln_ObjFaninNum(p, iObj) ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + printf( "%5d ", iFanin ); + printf( "\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/wln/wlnRetime.c b/src/base/wln/wlnRetime.c new file mode 100644 index 0000000..459af2d --- /dev/null +++ b/src/base/wln/wlnRetime.c @@ -0,0 +1,487 @@ +/**CFile**************************************************************** + + FileName [wlnRetime.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Word-level network.] + + Synopsis [Retiming.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 23, 2018.] + + Revision [$Id: wlnRetime.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wln.h" +#include "misc/vec/vecHsh.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Wln_Ret_t_ Wln_Ret_t; +struct Wln_Ret_t_ +{ + Wln_Ntk_t * pNtk; // static netlist + Vec_Int_t vFanins; // fanins and edge places + Vec_Int_t vFanouts; // fanouts and edge places + Vec_Int_t vEdgeLinks; // edge links + Vec_Int_t vFfClasses; // flop classes + Vec_Int_t vNodeDelays; // object delays + Vec_Int_t vPathDelays; // delays from sources to sinks + Vec_Int_t vSources; // critical sources + Vec_Int_t vSinks; // critical sinks + Vec_Int_t vFront; // retiming frontier + Vec_Int_t vMoves; // retiming moves (paired with delay) + int nClasses; // the number of flop classes + int DelayMax; // critical delay at any time +}; + +static inline int * Wln_RetFanins( Wln_Ret_t * p, int i ) { return Vec_IntEntryP( &p->vFanins, Vec_IntEntry(&p->vFanins, i) ); } +static inline int * Wln_RetFanouts( Wln_Ret_t * p, int i ) { return Vec_IntEntryP( &p->vFanouts, Vec_IntEntry(&p->vFanouts, i) ); } + +#define Wln_RetForEachFanin( p, iObj, iFanin, pLink, i ) \ + for ( i = 0; (i < Wln_ObjFaninNum(p->pNtk, iObj)) && \ + (((iFanin) = Wln_RetFanins(p, iObj)[2*i]), 1) && \ + ((pLink) = (Wln_RetFanins(p, iObj)+2*i+1)); i++ ) if ( !iFanin ) {} else + +#define Wln_RetForEachFanout( p, iObj, iFanout, pLink, i ) \ + for ( i = 0; (i < Wln_ObjRefs(p->pNtk, iObj)) && \ + (((iFanout) = Wln_RetFanouts(p, iObj)[2*i]), 1) && \ + ((pLink) = Vec_IntEntryP(&p->vFanins, Wln_RetFanouts(p, iObj)[2*i+1])); i++ ) if ( !iFanout ) {} else + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Retiming manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Wln_RetComputeFfClasses( Wln_Ntk_t * pNtk, Vec_Int_t * vClasses ) +{ + int i, k, iObj, nClasses; + Hsh_VecMan_t * p = Hsh_VecManStart( 10 ); + Vec_Int_t * vFlop = Vec_IntAlloc( 6 ); + Vec_IntFill( vClasses, Wln_NtkObjNum(pNtk), -1 ); + Wln_NtkForEachFf( pNtk, iObj, i ) + { + Vec_IntClear( vFlop ); + for ( k = 1; k <= 6; k++ ) + Vec_IntPush( vFlop, Wln_ObjFanin(pNtk, iObj, k) ); + Vec_IntWriteEntry( vClasses, iObj, Hsh_VecManAdd(p, vFlop) ); + } + nClasses = Hsh_VecSize( p ); + Hsh_VecManStop( p ); + Vec_IntFree( vFlop ); + printf( "Detected %d flop classes.\n", nClasses ); + return nClasses; +} +Wln_Ret_t * Wln_RetAlloc( Wln_Ntk_t * pNtk ) +{ + Wln_Ret_t * p; int k, iObj, iFanin; + Vec_Int_t * vRefsCopy = Vec_IntAlloc(0); + p = ABC_CALLOC( Wln_Ret_t, 1 ); + p->pNtk = pNtk; + Wln_NtkCreateRefs( pNtk ); + Wln_NtkStartFaninMap( pNtk, &p->vFanins, 2 ); + Wln_NtkStartFanoutMap( pNtk, &p->vFanouts, &pNtk->vRefs, 2 ); + ABC_SWAP( Vec_Int_t, *vRefsCopy, pNtk->vRefs ); + Wln_NtkCleanRefs( pNtk ); + Vec_IntGrow( &p->vEdgeLinks, 10*Wln_NtkFfNum(pNtk) ); + Vec_IntPushTwo( &p->vEdgeLinks, -1, -1 ); + Wln_NtkForEachObj( pNtk, iObj ) + Wln_ObjForEachFanin( pNtk, iObj, iFanin, k ) + { + int * pFanins = Wln_RetFanins( p, iObj ); + int * pFanouts = Wln_RetFanouts( p, iFanin ); + int Index = Wln_ObjRefsInc( pNtk, iFanin ); + pFanins[2*k+0] = iFanin; + pFanins[2*k+1] = Wln_ObjIsFf(pNtk, iFanin) ? Vec_IntSize(&p->vEdgeLinks) : 0; + pFanouts[2*Index+0] = iObj; + pFanouts[2*Index+1] = Vec_IntEntry(&p->vFanins, iObj) + 2*k + 1; + if ( Wln_ObjIsFf(pNtk, iFanin) ) + Vec_IntPushTwo( &p->vEdgeLinks, 0, iFanin ); + } + // double-check the current number of fanouts added + Wln_NtkForEachObj( pNtk, iObj ) + assert( Wln_ObjRefs(pNtk, iObj) == Vec_IntEntry(vRefsCopy, iObj) ); + Vec_IntFree( vRefsCopy ); + // other data + p->nClasses = Wln_RetComputeFfClasses( pNtk, &p->vFfClasses ); + ABC_SWAP( Vec_Int_t, p->vNodeDelays, pNtk->vInstIds ); + Vec_IntGrow( &p->vSources, 1000 ); + Vec_IntGrow( &p->vSinks, 1000 ); + Vec_IntGrow( &p->vFront, 1000 ); + Vec_IntGrow( &p->vMoves, 1000 ); + return p; +} +void Wln_RetFree( Wln_Ret_t * p ) +{ + ABC_FREE( p->vFanins.pArray ); + ABC_FREE( p->vFanouts.pArray ); + ABC_FREE( p->vEdgeLinks.pArray ); + ABC_FREE( p->vFfClasses.pArray ); + ABC_FREE( p->vNodeDelays.pArray ); + ABC_FREE( p->vPathDelays.pArray ); + ABC_FREE( p->vSources.pArray ); + ABC_FREE( p->vSinks.pArray ); + ABC_FREE( p->vFront.pArray ); + ABC_FREE( p->vMoves.pArray ); + ABC_FREE( p ); +} +int Wln_RetMemUsage( Wln_Ret_t * p ) +{ + int Mem = sizeof(Wln_Ret_t); + Mem += 4 * p->vFanins.nCap; + Mem += 4 * p->vFanouts.nCap; + Mem += 4 * p->vEdgeLinks.nCap; + Mem += 4 * p->vFfClasses.nCap; + Mem += 4 * p->vNodeDelays.nCap; + Mem += 4 * p->vPathDelays.nCap; + Mem += 4 * p->vSources.nCap; + Mem += 4 * p->vSinks.nCap; + Mem += 4 * p->vFront.nCap; + Mem += 4 * p->vMoves.nCap; + return Mem; +} + +/**Function************************************************************* + + Synopsis [Delay propagation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_RetMarkChanges_rec( Wln_Ret_t * p, int iObj ) +{ + int k, iFanout, * pLink, * pDelay = Vec_IntEntryP( &p->vPathDelays, iObj ); + if ( *pDelay < 0 ) + return; + *pDelay = -1; + Wln_RetForEachFanout( p, iObj, iFanout, pLink, k ) + if ( !pLink[0] ) + Wln_RetMarkChanges_rec( p, iFanout ); +} +int Wln_RetPropDelay_rec( Wln_Ret_t * p, int iObj ) +{ + int k, iFanin, * pLink, * pDelay = Vec_IntEntryP( &p->vPathDelays, iObj ); + if ( *pDelay >= 0 ) + return *pDelay; + Wln_RetForEachFanin( p, iObj, iFanin, pLink, k ) + if ( pLink[0] ) + *pDelay = Abc_MaxInt(*pDelay, 0); + else + *pDelay = Abc_MaxInt(*pDelay, Wln_RetPropDelay_rec(p, iFanin)); + *pDelay += Vec_IntEntry( &p->vNodeDelays, iObj ); + return *pDelay; +} +int Wln_RetPropDelay( Wln_Ret_t * p, Vec_Int_t * vFront ) +{ + int i, iObj, DelayMax = 0; + if ( vFront ) + { + Vec_IntForEachEntry( vFront, iObj, i ) + Wln_RetMarkChanges_rec( p, iObj ); + } + else + { + Vec_IntFill( &p->vPathDelays, Wln_NtkObjNum(p->pNtk), -1 ); + Wln_NtkForEachCi( p->pNtk, iObj, i ) + Vec_IntWriteEntry( &p->vPathDelays, iObj, 0 ); + } + Vec_IntClear( &p->vSinks ); + Wln_NtkForEachObj( p->pNtk, iObj ) + if ( !Wln_ObjIsCo(p->pNtk, iObj) ) + { + int Delay = Wln_RetPropDelay_rec(p, iObj); + if ( DelayMax == Delay ) + Vec_IntPush( &p->vSinks, iObj ); + else if ( DelayMax < Delay ) + { + DelayMax = Delay; + Vec_IntFill( &p->vSinks, 1, iObj ); + } + } + return DelayMax; +} + +void Wln_RetFindSources_rec( Wln_Ret_t * p, int iObj ) +{ + int k, iFanin, * pLink, FaninDelay, fTerm = 1; + if ( Wln_ObjIsCi(p->pNtk, iObj) || Wln_ObjCheckTravId(p->pNtk, iObj) ) + return; + FaninDelay = Vec_IntEntry( &p->vPathDelays, iObj ) - Vec_IntEntry( &p->vNodeDelays, iObj ); + Wln_RetForEachFanin( p, iObj, iFanin, pLink, k ) + { + if ( !pLink[0] ) + continue; + fTerm = 0; + if ( Vec_IntEntry(&p->vPathDelays, iFanin) == FaninDelay ) + Wln_RetFindSources_rec( p, iFanin ); + } + if ( fTerm ) + Vec_IntPush( &p->vSources, iObj ); +} +void Wln_RetFindSources( Wln_Ret_t * p ) +{ + int i, iObj; + Vec_IntClear( &p->vSources ); + Wln_NtkIncrementTravId( p->pNtk ); + Vec_IntForEachEntry( &p->vSinks, iObj, i ) + Wln_RetFindSources_rec( p, iObj ); +} + +/**Function************************************************************* + + Synopsis [Retimability check.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Wln_RetHeadToTail( Wln_Ret_t * p, int * pHead ) +{ + int * pLink; + assert( pHead[0] ); + pLink = Vec_IntEntryP( &p->vEdgeLinks, pHead[0] ); + if ( pLink[0] == 0 ) + return pHead; + return Wln_RetHeadToTail( p, pLink ); +} + +static inline int Wln_RetCheckForwardOne( Wln_Ret_t * p, int iObj ) +{ + int k, iFanin, * pLink, iFlop, Class = -1; + Wln_RetForEachFanin( p, iObj, iFanin, pLink, k ) + { + if ( !pLink[0] ) + return 0; + iFlop = Vec_IntEntry( &p->vEdgeLinks, pLink[0] + 1 ); + assert( Wln_ObjIsFf( p->pNtk, iFlop ) ); + if ( Class == -1 ) + Class = Vec_IntEntry( &p->vFfClasses, iFlop ); + else if ( Class != Vec_IntEntry( &p->vFfClasses, iFlop ) ) + return 0; + } + return 1; +} +int Wln_RetCheckForward( Wln_Ret_t * p, Vec_Int_t * vSet ) +{ + int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + if ( !Wln_RetCheckForwardOne( p, iObj ) ) + return 0; + return 1; +} + +static inline int Wln_RetCheckBackwardOne( Wln_Ret_t * p, int iObj ) +{ + int k, iFanin, * pLink, iFlop, Class = -1; + Wln_RetForEachFanout( p, iObj, iFanin, pLink, k ) + { + if ( !pLink[0] ) + return 0; + pLink = Wln_RetHeadToTail( p, pLink ); + iFlop = Vec_IntEntry( &p->vEdgeLinks, pLink[0] + 1 ); + assert( Wln_ObjIsFf( p->pNtk, iFlop ) ); + if ( Class == -1 ) + Class = Vec_IntEntry( &p->vFfClasses, iFlop ); + else if ( Class != Vec_IntEntry( &p->vFfClasses, iFlop ) ) + return 0; + } + return 1; +} +int Wln_RetCheckBackward( Wln_Ret_t * p, Vec_Int_t * vSet ) +{ + int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + if ( !Wln_RetCheckBackwardOne( p, iObj ) ) + return 0; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Moving flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Wln_RetRemoveOneFanin( Wln_Ret_t * p, int iObj ) +{ + int k, iFanin, * pLink, iFlop, iFlop1 = -1; + int * pFanins = Wln_RetFanins( p, iObj ); + Wln_RetForEachFanin( p, iObj, iFanin, pLink, k ) + { + assert( pLink[0] ); + pFanins[2*k+1] = Vec_IntEntry( &p->vEdgeLinks, pLink[0] ); + iFlop = Vec_IntEntry( &p->vEdgeLinks, pLink[0] + 1 ); + assert( Wln_ObjIsFf( p->pNtk, iFlop ) ); + if ( iFlop1 == -1 ) + iFlop1 = iFlop; + } + return iFlop1; +} +int Wln_RetRemoveOneFanout( Wln_Ret_t * p, int iObj ) +{ + int k, iFanin, * pLink, iFlop, iFlop1 = -1; + //int * pFanins = Wln_RetFanins( p, iObj ); + Wln_RetForEachFanout( p, iObj, iFanin, pLink, k ) + { + assert( pLink[0] ); + pLink = Wln_RetHeadToTail( p, pLink ); + iFlop = Vec_IntEntry( &p->vEdgeLinks, pLink[0] + 1 ); + pLink[0] = 0; + assert( Wln_ObjIsFf( p->pNtk, iFlop ) ); + if ( iFlop1 == -1 ) + iFlop1 = iFlop; + } + return iFlop1; +} +void Wln_RetInsertOneFanin( Wln_Ret_t * p, int iObj, int iFlop ) +{ + int k, iFanin, * pLink; + int * pFanins = Wln_RetFanins( p, iObj ); + assert( Wln_ObjIsFf( p->pNtk, iFlop ) ); + Wln_RetForEachFanin( p, iObj, iFanin, pLink, k ) + { + int iHead = pFanins[2*k+1]; + pFanins[2*k+1] = Vec_IntSize(&p->vEdgeLinks); + Vec_IntPushTwo( &p->vEdgeLinks, iHead, iFlop ); + } +} +void Wln_RetInsertOneFanout( Wln_Ret_t * p, int iObj, int iFlop ) +{ + int k, iFanin, * pLink; + assert( Wln_ObjIsFf( p->pNtk, iFlop ) ); + Wln_RetForEachFanout( p, iObj, iFanin, pLink, k ) + { + if ( pLink[0] ) + pLink = Wln_RetHeadToTail( p, pLink ); + pLink = Vec_IntEntryP( &p->vEdgeLinks, pLink[0] ); + assert( pLink[0] == 0 ); + pLink[0] = Vec_IntSize(&p->vEdgeLinks); + Vec_IntPushTwo( &p->vEdgeLinks, 0, iFlop ); + } +} +void Wln_RetRetimeForward( Wln_Ret_t * p, Vec_Int_t * vSet ) +{ + int i, iObj, iFlop; + Vec_IntForEachEntry( vSet, iObj, i ) + { + iFlop = Wln_RetRemoveOneFanin( p, iObj ); + Wln_RetInsertOneFanout( p, iObj, iFlop ); + } +} +void Wln_RetRetimeBackward( Wln_Ret_t * p, Vec_Int_t * vSet ) +{ + int i, iObj, iFlop; + Vec_IntForEachEntry( vSet, iObj, i ) + { + iFlop = Wln_RetRemoveOneFanout( p, iObj ); + Wln_RetInsertOneFanin( p, iObj, iFlop ); + } +} +void Wln_RetAddToMoves( Wln_Ret_t * p, Vec_Int_t * vSet, int Delay, int fForward ) +{ + int i, iObj; + if ( vSet == NULL ) + { + Vec_IntPushTwo( &p->vMoves, 0, Delay ); + return; + } + Vec_IntForEachEntry( vSet, iObj, i ) + { + int NameId = Vec_IntEntry( &p->pNtk->vNameIds, iObj ); + Vec_IntPushTwo( &p->vMoves, fForward ? NameId : -NameId, Delay ); + } +} + +/**Function************************************************************* + + Synopsis [Retiming computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Wln_NtkRetime( Wln_Ntk_t * pNtk ) +{ + Wln_Ret_t * p = Wln_RetAlloc( pNtk ); + Vec_Int_t * vSources = &p->vSources; + Vec_Int_t * vSinks = &p->vSinks; + Vec_Int_t * vFront = &p->vFront; + Vec_Int_t * vMoves = Vec_IntAlloc(0); + p->DelayMax = Wln_RetPropDelay( p, NULL ); + Wln_RetFindSources( p ); + Wln_RetAddToMoves( p, NULL, p->DelayMax, 0 ); + while ( Vec_IntSize(vSources) || Vec_IntSize(vSinks) ) + { + int fForward = Vec_IntSize(vSources) && Wln_RetCheckForward( p, vSources ); + int fBackward = Vec_IntSize(vSinks) && Wln_RetCheckBackward( p, vSinks ); + if ( !fForward && !fBackward ) + { + printf( "Cannot retime forward and backward.\n" ); + break; + } + Vec_IntSort( vSources, 0 ); + Vec_IntSort( vSinks, 0 ); + if ( Vec_IntTwoCountCommon(vSources, vSinks) ) + { + printf( "Cannot reduce delay by retiming.\n" ); + break; + } + Vec_IntClear( vFront ); + if ( (fForward && !fBackward) || (fForward && fBackward && Vec_IntSize(vSources) < Vec_IntSize(vSinks)) ) + Wln_RetRetimeForward( p, vSources ), Vec_IntAppend( vFront, vSources ), fForward = 1, fBackward = 0; + else + Wln_RetRetimeBackward( p, vSinks ), Vec_IntAppend( vFront, vSources ), fForward = 0, fBackward = 1; + p->DelayMax = Wln_RetPropDelay( p, vFront ); + Wln_RetAddToMoves( p, vFront, p->DelayMax, fForward ); + Wln_RetFindSources( p ); + if ( 2*Vec_IntSize(&p->vEdgeLinks) > Vec_IntCap(&p->vEdgeLinks) ) + Vec_IntGrow( &p->vEdgeLinks, 4*Vec_IntSize(&p->vEdgeLinks) ); + } + ABC_SWAP( Vec_Int_t, *vMoves, p->vMoves ); + Wln_RetFree( p ); + return vMoves; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/base/wln/wlnWriteVer.c b/src/base/wln/wlnWriteVer.c new file mode 100644 index 0000000..1c37e31 --- /dev/null +++ b/src/base/wln/wlnWriteVer.c @@ -0,0 +1,494 @@ +/**CFile**************************************************************** + + FileName [wlnWriteVer.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Word-level network.] + + Synopsis [Writing Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 23, 2018.] + + Revision [$Id: wlnWriteVer.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "wln.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_WriteTableOne( FILE * pFile, int nFans, int nOuts, word * pTable, int Id ) +{ + int m, nMints = (1<<nFans); +// Abc_TtPrintHexArrayRev( stdout, pTable, nMints ); printf( "\n" ); + assert( nOuts > 0 && nOuts <= 64 && (64 % nOuts) == 0 ); + fprintf( pFile, "module table%d(ind, val);\n", Id ); + fprintf( pFile, " input [%d:0] ind;\n", nFans-1 ); + fprintf( pFile, " output [%d:0] val;\n", nOuts-1 ); + fprintf( pFile, " reg [%d:0] val;\n", nOuts-1 ); + fprintf( pFile, " always @(ind)\n" ); + fprintf( pFile, " begin\n" ); + fprintf( pFile, " case (ind)\n" ); + for ( m = 0; m < nMints; m++ ) + fprintf( pFile, " %d\'h%x: val = %d\'h%x;\n", nFans, m, nOuts, (unsigned)((pTable[(nOuts * m) >> 6] >> ((nOuts * m) & 63)) & Abc_Tt6Mask(nOuts)) ); + fprintf( pFile, " endcase\n" ); + fprintf( pFile, " end\n" ); + fprintf( pFile, "endmodule\n" ); + fprintf( pFile, "\n" ); +} +void Wln_WriteTables( FILE * pFile, Wln_Ntk_t * p ) +{ + Vec_Int_t * vNodes; + word * pTable; + int i, iObj; + if ( p->vTables == NULL || Vec_PtrSize(p->vTables) == 0 ) + return; + // map tables into their nodes + vNodes = Vec_IntStart( Vec_PtrSize(p->vTables) ); + Wln_NtkForEachObj( p, iObj ) + if ( Wln_ObjType(p, iObj) == ABC_OPER_TABLE ) + Vec_IntWriteEntry( vNodes, Wln_ObjFanin1(p, iObj), iObj ); + // write tables + Vec_PtrForEachEntry( word *, p->vTables, pTable, i ) + { + int iNode = Vec_IntEntry( vNodes, i ); + int iFanin = Wln_ObjFanin0( p, iNode ); + Wln_WriteTableOne( pFile, Wln_ObjRange(p, iFanin), Wln_ObjRange(p, iNode), pTable, i ); + } + Vec_IntFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [This was used to add POs to each node except PIs and MUXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_WriteAddPos( Wln_Ntk_t * p ) +{ + int iObj; + Wln_NtkForEachObj( p, iObj ) + if ( !Wln_ObjIsCio(p, iObj) ) + Wln_ObjCreateCo( p, iObj ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wln_WriteVerIntVec( FILE * pFile, Wln_Ntk_t * p, Vec_Int_t * vVec, int Start ) +{ + char * pName; + int LineLength = Start; + int NameCounter = 0; + int AddedLength, i, iObj; + Vec_IntForEachEntry( vVec, iObj, i ) + { + pName = Wln_ObjName( p, iObj ); + // get the line length after this name is written + AddedLength = strlen(pName) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > 70 ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = Start; + NameCounter = 0; + } + fprintf( pFile, " %s%s", pName, (i==Vec_IntSize(vVec)-1)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } +} +void Wln_WriteVerInt( FILE * pFile, Wln_Ntk_t * p ) +{ + int k, j, iObj, iFanin; + char Range[100]; + fprintf( pFile, "module %s ( ", p->pName ); + fprintf( pFile, "\n " ); + if ( Wln_NtkCiNum(p) > 0 ) + { + Wln_WriteVerIntVec( pFile, p, &p->vCis, 3 ); + fprintf( pFile, ",\n " ); + } + if ( Wln_NtkCoNum(p) > 0 ) + Wln_WriteVerIntVec( pFile, p, &p->vCos, 3 ); + fprintf( pFile, " );\n" ); + Wln_NtkForEachObj( p, iObj ) + { + int End = Wln_ObjRangeEnd(p, iObj); + int Beg = Wln_ObjRangeBeg(p, iObj); + int nDigits = Abc_Base10Log(Abc_AbsInt(End)+1) + Abc_Base10Log(Abc_AbsInt(Beg)+1) + (int)(End < 0) + (int)(Beg < 0); + sprintf( Range, "%s[%d:%d]%*s", (!p->fSmtLib && Wln_ObjIsSigned(p, iObj)) ? "signed ":" ", End, Beg, 8-nDigits, "" ); + fprintf( pFile, " " ); + if ( Wln_ObjIsCi(p, iObj) ) + fprintf( pFile, "input " ); + else if ( Wln_ObjIsCo(p, iObj) ) + fprintf( pFile, "output " ); + else + fprintf( pFile, " " ); + if ( Wln_ObjIsCio(p, iObj) ) + { + fprintf( pFile, "wire %s %s ;\n", Range, Wln_ObjName(p, iObj) ); + if ( Wln_ObjIsCi(p, iObj) ) + continue; + fprintf( pFile, " assign " ); + fprintf( pFile, "%-16s = %s ;\n", Wln_ObjName(p, iObj), Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + continue; + } + if ( Wln_ObjType(p, iObj) == ABC_OPER_SEL_NMUX || Wln_ObjType(p, iObj) == ABC_OPER_SEL_SEL ) + fprintf( pFile, "reg %s ", Range ); + else + fprintf( pFile, "wire %s ", Range ); + if ( Wln_ObjType(p, iObj) == ABC_OPER_TABLE ) + { + // wire [3:0] s4972; table0 s4972_Index(s4971, s4972); + fprintf( pFile, "%s ; table%d", Wln_ObjName(p, iObj), Wln_ObjFanin1(p, iObj) ); + fprintf( pFile, " s%d_Index(%s, ", iObj, Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + fprintf( pFile, "%s)", Wln_ObjName(p, iObj) ); + } + else if ( Wln_ObjIsConst(p, iObj) ) + fprintf( pFile, "%-16s = %s", Wln_ObjName(p, iObj), Wln_ObjConstString(p, iObj) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_ROTR || Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_ROTL ) + { + // wire [27:0] s4960 = (s57 >> 17) | (s57 << 11); + int Num0 = Wln_ObjFanin1(p, iObj); + int Num1 = Wln_ObjRange(p, iObj) - Num0; + assert( Num0 > 0 && Num0 < Wln_ObjRange(p, iObj) ); + fprintf( pFile, "%-16s = ", Wln_ObjName(p, iObj) ); + if ( Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_ROTR ) + fprintf( pFile, "(%s >> %d) | (%s << %d)", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), Num0, Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), Num1 ); + else + fprintf( pFile, "(%s << %d) | (%s >> %d)", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), Num0, Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), Num1 ); + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SEL_NMUX ) + { + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + fprintf( pFile, " " ); + fprintf( pFile, "always @( " ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + fprintf( pFile, "%s%s", k ? " or ":"", Wln_ObjName(p, Wln_ObjFanin(p, iObj, k)) ); + fprintf( pFile, " )\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "begin\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "case ( %s )\n", Wln_ObjName(p, Wln_ObjFanin(p, iObj, 0)) ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + { + if ( !k ) continue; + fprintf( pFile, " " ); + fprintf( pFile, "%d : %s = ", k-1, Wln_ObjName(p, iObj) ); + fprintf( pFile, "%s ;\n", Wln_ObjName(p, Wln_ObjFanin(p, iObj, k)) ); + } + fprintf( pFile, " " ); + fprintf( pFile, "endcase\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "end\n" ); + continue; + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SEL_SEL ) + { + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + fprintf( pFile, " " ); + fprintf( pFile, "always @( " ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + fprintf( pFile, "%s%s", k ? " or ":"", Wln_ObjName(p, Wln_ObjFanin(p, iObj, k)) ); + fprintf( pFile, " )\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "begin\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "case ( %s )\n", Wln_ObjName(p, Wln_ObjFanin(p, iObj, 0)) ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + { + if ( !k ) continue; + fprintf( pFile, " " ); + fprintf( pFile, "%d\'b", Wln_ObjFaninNum(p, iObj)-1 ); + for ( j = Wln_ObjFaninNum(p, iObj)-1; j > 0; j-- ) + fprintf( pFile, "%d", (int)(j==k) ); + fprintf( pFile, " : %s = ", Wln_ObjName(p, iObj) ); + fprintf( pFile, "%s ;\n", Wln_ObjName(p, Wln_ObjFanin(p, iObj, k)) ); + } + fprintf( pFile, " " ); + fprintf( pFile, "default" ); + fprintf( pFile, " : %s = ", Wln_ObjName(p, iObj) ); + fprintf( pFile, "%d\'b", Wln_ObjRange(p, iObj) ); + for ( j = Wln_ObjRange(p, iObj)-1; j >= 0; j-- ) + fprintf( pFile, "%d", 0 ); + fprintf( pFile, " ;\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "endcase\n" ); + fprintf( pFile, " " ); + fprintf( pFile, "end\n" ); + continue; + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SEL_DEC ) + { + int nRange = Wln_ObjRange(p, Wln_ObjFanin0(p, iObj)); + assert( (1 << nRange) == Wln_ObjRange(p, iObj) ); + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + for ( k = 0; k < Wln_ObjRange(p, iObj); k++ ) + { + fprintf( pFile, " " ); + fprintf( pFile, "wire " ); + fprintf( pFile, "%s_", Wln_ObjName(p, iObj) ); + for ( j = 0; j < nRange; j++ ) + fprintf( pFile, "%d", (k >> (nRange-1-j)) & 1 ); + fprintf( pFile, " = " ); + for ( j = 0; j < nRange; j++ ) + fprintf( pFile, "%s%s%s[%d]", + j ? " & ":"", ((k >> (nRange-1-j)) & 1) ? " ":"~", + Wln_ObjName(p, Wln_ObjFanin(p, iObj, 0)), nRange-1-j ); + fprintf( pFile, " ;\n" ); + } + fprintf( pFile, " " ); + fprintf( pFile, "assign %s = { ", Wln_ObjName(p, iObj) ); + for ( k = Wln_ObjRange(p, iObj)-1; k >= 0; k-- ) + { + fprintf( pFile, "%s%s_", k < Wln_ObjRange(p, iObj)-1 ? ", ":"", Wln_ObjName(p, iObj) ); + for ( j = 0; j < nRange; j++ ) + fprintf( pFile, "%d", (k >> (nRange-1-j)) & 1 ); + } + fprintf( pFile, " } ;\n" ); + continue; + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_ADDSUB ) + { + // out = mode ? a+b+cin : a-b-cin + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + fprintf( pFile, " " ); + fprintf( pFile, "assign " ); + fprintf( pFile, "%s = %s ? %s + %s + %s : %s - %s - %s ;\n", + Wln_ObjName(p, iObj), Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), + Wln_ObjName(p, Wln_ObjFanin2(p, iObj)), Wln_ObjName(p, Wln_ObjFanin(p, iObj,3)), Wln_ObjName(p, Wln_ObjFanin1(p, iObj)), + Wln_ObjName(p, Wln_ObjFanin2(p, iObj)), Wln_ObjName(p, Wln_ObjFanin(p, iObj,3)), Wln_ObjName(p, Wln_ObjFanin1(p, iObj)) + ); + continue; + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RAMR || Wln_ObjType(p, iObj) == ABC_OPER_RAMW ) + { + if ( 1 ) + { + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + fprintf( pFile, " " ); + fprintf( pFile, "%s (", Wln_ObjType(p, iObj) == ABC_OPER_RAMR ? "ABC_READ" : "ABC_WRITE" ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + fprintf( pFile, " .%s(%s),", k==0 ? "mem_in" : (k==1 ? "addr": "data"), Wln_ObjName(p, iFanin) ); + fprintf( pFile, " .%s(%s) ) ;\n", Wln_ObjType(p, iObj) == ABC_OPER_RAMR ? "data" : "mem_out", Wln_ObjName(p, iObj) ); + continue; + } + else + { + int nBitsMem = Wln_ObjRange(p, Wln_ObjFanin(p, iObj, 0) ); + //int nBitsAddr = Wln_ObjRange(p, Wln_ObjFanin(p, iObj, 1) ); + int nBitsDat = Wln_ObjType(p, iObj) == ABC_OPER_RAMR ? Wln_ObjRange(p, iObj) : Wln_ObjRange(p, Wln_ObjFanin(p, iObj, 2)); + int Depth = nBitsMem / nBitsDat; + assert( nBitsMem % nBitsDat == 0 ); + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + fprintf( pFile, " " ); + fprintf( pFile, "%s_%d (", Wln_ObjType(p, iObj) == ABC_OPER_RAMR ? "CPL_MEM_READ" : "CPL_MEM_WRITE", Depth ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + fprintf( pFile, " .%s(%s),", k==0 ? "mem_data_in" : (k==1 ? "addr_in": "data_in"), Wln_ObjName(p, iFanin) ); + fprintf( pFile, " .%s(%s) ) ;\n", "data_out", Wln_ObjName(p, iObj) ); + continue; + } + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_DFFRSE ) + { + fprintf( pFile, "%s ;\n", Wln_ObjName(p, iObj) ); + continue; + } + else + { + fprintf( pFile, "%-16s = ", Wln_ObjName(p, iObj) ); + if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_BUF ) + fprintf( pFile, "%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_MUX ) + { + fprintf( pFile, "%s ? ", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + fprintf( pFile, "%s : ", Wln_ObjName(p, Wln_ObjFanin1(p, iObj)) ); + fprintf( pFile, "%s", Wln_ObjName(p, Wln_ObjFanin2(p, iObj)) ); + } + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_MIN ) + fprintf( pFile, "-%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_INV ) + fprintf( pFile, "~%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_LOGIC_NOT ) + fprintf( pFile, "!%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RED_AND ) + fprintf( pFile, "&%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RED_OR ) + fprintf( pFile, "|%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RED_XOR ) + fprintf( pFile, "^%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RED_NAND ) + fprintf( pFile, "~&%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RED_NOR ) + fprintf( pFile, "~|%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_RED_NXOR ) + fprintf( pFile, "~^%s", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SLICE ) + fprintf( pFile, "%s [%d:%d]", Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SIGNEXT ) + fprintf( pFile, "{ {%d{%s[%d]}}, %s }", Wln_ObjRange(p, iObj) - Wln_ObjRange(p, Wln_ObjFanin0(p, iObj)), Wln_ObjName(p, Wln_ObjFanin0(p, iObj)), Wln_ObjRange(p, Wln_ObjFanin0(p, iObj)) - 1, Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ZEROPAD ) + fprintf( pFile, "{ {%d{1\'b0}}, %s }", Wln_ObjRange(p, iObj) - Wln_ObjRange(p, Wln_ObjFanin0(p, iObj)), Wln_ObjName(p, Wln_ObjFanin0(p, iObj)) ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_CONCAT ) + { + fprintf( pFile, "{" ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + fprintf( pFile, " %s%s", Wln_ObjName(p, Wln_ObjFanin(p, iObj, k)), k == Wln_ObjFaninNum(p, iObj)-1 ? "":"," ); + fprintf( pFile, " }" ); + } + else + { + fprintf( pFile, "%s ", Wln_ObjName(p, Wln_ObjFanin(p, iObj, 0)) ); + if ( Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_R ) + fprintf( pFile, ">>" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_RA ) + fprintf( pFile, ">>>" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_L ) + fprintf( pFile, "<<" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_SHIFT_LA ) + fprintf( pFile, "<<<" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_AND ) + fprintf( pFile, "&" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_OR ) + fprintf( pFile, "|" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_XOR ) + fprintf( pFile, "^" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_NAND ) + fprintf( pFile, "~&" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_NOR ) + fprintf( pFile, "~|" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_BIT_NXOR ) + fprintf( pFile, "~^" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_LOGIC_IMPL ) + fprintf( pFile, "=>" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_LOGIC_AND ) + fprintf( pFile, "&&" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_LOGIC_OR ) + fprintf( pFile, "||" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_LOGIC_XOR ) + fprintf( pFile, "^^" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_COMP_EQU ) + fprintf( pFile, "==" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_COMP_NOTEQU ) + fprintf( pFile, "!=" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_COMP_LESS ) + fprintf( pFile, "<" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_COMP_MORE ) + fprintf( pFile, ">" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_COMP_LESSEQU ) + fprintf( pFile, "<=" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_COMP_MOREEQU ) + fprintf( pFile, ">=" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_ADD ) + fprintf( pFile, "+" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_SUB ) + fprintf( pFile, "-" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_MUL ) + fprintf( pFile, "*" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_DIV ) + fprintf( pFile, "/" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_REM ) + fprintf( pFile, "%%" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_MOD ) + fprintf( pFile, "%%" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_POW ) + fprintf( pFile, "**" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_SQRT ) + fprintf( pFile, "@" ); + else if ( Wln_ObjType(p, iObj) == ABC_OPER_ARI_SQUARE ) + fprintf( pFile, "#" ); + else + { + //assert( 0 ); + printf( "Failed to write node \"%s\" with unknown operator type (%d).\n", Wln_ObjName(p, iObj), Wln_ObjType(p, iObj) ); + fprintf( pFile, "???\n" ); + continue; + } + fprintf( pFile, " %s", Wln_ObjName(p, Wln_ObjFanin(p, iObj, 1)) ); + if ( Wln_ObjFaninNum(p, iObj) == 3 && Wln_ObjType(p, iObj) == ABC_OPER_ARI_ADD ) + fprintf( pFile, " + %s", Wln_ObjName(p, Wln_ObjFanin(p, iObj, 2)) ); + } + } + fprintf( pFile, " ;%s\n", (p->fSmtLib && Wln_ObjIsSigned(p, iObj)) ? " // signed SMT-LIB operator" : "" ); + } + iFanin = 0; + // write DFFs in the end + fprintf( pFile, "\n" ); + Wln_NtkForEachFf( p, iObj, j ) + { + char * pInNames[8] = {"d", "clk", "reset", "set", "enable", "async", "sre", "init"}; + fprintf( pFile, " " ); + fprintf( pFile, "%s (", "ABC_DFFRSE" ); + Wln_ObjForEachFanin( p, iObj, iFanin, k ) + if ( iFanin ) fprintf( pFile, " .%s(%s),", pInNames[k], Wln_ObjName(p, iFanin) ); + fprintf( pFile, " .%s(%s) ) ;\n", "q", Wln_ObjName(p, iObj) ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "endmodule\n\n" ); +} +void Wln_WriteVer( Wln_Ntk_t * p, char * pFileName ) +{ + FILE * pFile; + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Wln_WriteVer(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", p->pName, Extra_TimeStamp() ); + fprintf( pFile, "\n" ); + Wln_WriteTables( pFile, p ); +// if ( fAddCos ) +// Wln_WriteAddPos( p ); + Wln_WriteVerInt( pFile, p ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/cudd/cuddReorder.c b/src/bdd/cudd/cuddReorder.c index ded4385..a68cef2 100644 --- a/src/bdd/cudd/cuddReorder.c +++ b/src/bdd/cudd/cuddReorder.c @@ -480,7 +480,7 @@ cuddDynamicAllocNode( node = table->nextFree; table->nextFree = node->next; - node->Id = 0; + //node->Id = 0; return (node); } /* end of cuddDynamicAllocNode */ diff --git a/src/bdd/extrab/extraBdd.h b/src/bdd/extrab/extraBdd.h index e7a65a9..d5dfc85 100644 --- a/src/bdd/extrab/extraBdd.h +++ b/src/bdd/extrab/extraBdd.h @@ -206,6 +206,44 @@ extern DdNode * extraBddTuples( DdManager * dd, DdNode * bVarsK, DdNode * b #define ABC_PRB(dd,f) printf("%s = ", #f); Extra_bddPrint(dd,f); printf("\n") #endif +/*=== extraMaxMin.c ==============================================================*/ + +/* maximal/minimimal */ +extern DdNode * Extra_zddMaximal (DdManager *dd, DdNode *S); +extern DdNode * extraZddMaximal (DdManager *dd, DdNode *S); +extern DdNode * Extra_zddMinimal (DdManager *dd, DdNode *S); +extern DdNode * extraZddMinimal (DdManager *dd, DdNode *S); +/* maximal/minimal of the union of two sets of subsets */ +extern DdNode * Extra_zddMaxUnion (DdManager *dd, DdNode *S, DdNode *T); +extern DdNode * extraZddMaxUnion (DdManager *dd, DdNode *S, DdNode *T); +extern DdNode * Extra_zddMinUnion (DdManager *dd, DdNode *S, DdNode *T); +extern DdNode * extraZddMinUnion (DdManager *dd, DdNode *S, DdNode *T); +/* dot/cross products */ +extern DdNode * Extra_zddDotProduct (DdManager *dd, DdNode *S, DdNode *T); +extern DdNode * extraZddDotProduct (DdManager *dd, DdNode *S, DdNode *T); +extern DdNode * Extra_zddCrossProduct (DdManager *dd, DdNode *S, DdNode *T); +extern DdNode * extraZddCrossProduct (DdManager *dd, DdNode *S, DdNode *T); +extern DdNode * Extra_zddMaxDotProduct (DdManager *dd, DdNode *S, DdNode *T); +extern DdNode * extraZddMaxDotProduct (DdManager *dd, DdNode *S, DdNode *T); + +/*=== extraBddSet.c ==============================================================*/ + +/* subset/supset operations */ +extern DdNode * Extra_zddSubSet (DdManager *dd, DdNode *X, DdNode *Y); +extern DdNode * extraZddSubSet (DdManager *dd, DdNode *X, DdNode *Y); +extern DdNode * Extra_zddSupSet (DdManager *dd, DdNode *X, DdNode *Y); +extern DdNode * extraZddSupSet (DdManager *dd, DdNode *X, DdNode *Y); +extern DdNode * Extra_zddNotSubSet (DdManager *dd, DdNode *X, DdNode *Y); +extern DdNode * extraZddNotSubSet (DdManager *dd, DdNode *X, DdNode *Y); +extern DdNode * Extra_zddNotSupSet (DdManager *dd, DdNode *X, DdNode *Y); +extern DdNode * extraZddNotSupSet (DdManager *dd, DdNode *X, DdNode *Y); +extern DdNode * Extra_zddMaxNotSupSet (DdManager *dd, DdNode *X, DdNode *Y); +extern DdNode * extraZddMaxNotSupSet (DdManager *dd, DdNode *X, DdNode *Y); +/* check whether the empty combination belongs to the set of subsets */ +extern int Extra_zddEmptyBelongs (DdManager *dd, DdNode* zS); +/* check whether the set consists of one subset only */ +extern int Extra_zddIsOneSubset (DdManager *dd, DdNode* zS); + /*=== extraBddKmap.c ================================================================*/ /* displays the Karnaugh Map of a function */ diff --git a/src/bdd/extrab/extraBddMaxMin.c b/src/bdd/extrab/extraBddMaxMin.c new file mode 100644 index 0000000..22d2b00 --- /dev/null +++ b/src/bdd/extrab/extraBddMaxMin.c @@ -0,0 +1,1067 @@ +/**CFile*********************************************************************** + + FileName [zMaxMin.c] + + PackageName [extra] + + Synopsis [Experimental version of some ZDD operators.] + + Description [External procedures included in this module: + <ul> + <li> Extra_zddMaximal(); + <li> Extra_zddMinimal(); + <li> Extra_zddMaxUnion(); + <li> Extra_zddMinUnion(); + <li> Extra_zddDotProduct(); + <li> Extra_zddCrossProduct(); + <li> Extra_zddMaxDotProduct(); + </ul> + Internal procedures included in this module: + <ul> + <li> extraZddMaximal(); + <li> extraZddMinimal(); + <li> extraZddMaxUnion(); + <li> extraZddMinUnion(); + <li> extraZddDotProduct(); + <li> extraZddCrossProduct(); + <li> extraZddMaxDotProduct(); + </ul> + StaTc procedures included in this module: + <ul> + </ul> + + DotProduct and MaxDotProduct were introduced + by O.Coudert to solve problems arising in two-level planar routing + See O. Coudert, C.-J. R. Shi. Exact Multi-Layer Topological Planar + Routing. Proc. of IEEE Custom Integrated Circuit Conference '96, + pp. 179-182. + ] + + SeeAlso [] + + Author [Alan Mishchenko] + + Copyright [] + + ReviSon [$zMaxMin.c, v.1.2, November 26, 2000, alanmi $] + +******************************************************************************/ + +#include "extraBdd.h" + +ABC_NAMESPACE_IMPL_START + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaTcStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* StaTc Function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaTcEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported Functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Computes the maximal of a set represented by its ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [Extra_zddMinimal] + +******************************************************************************/ +DdNode * +Extra_zddMaximal( + DdManager * dd, + DdNode * S) +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraZddMaximal(dd, S); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddMaximal */ + + +/**Function******************************************************************** + + Synopsis [Computes the minimal of a set represented by its ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [Extra_zddMaximal] + +******************************************************************************/ +DdNode * +Extra_zddMinimal( + DdManager * dd, + DdNode * S) +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraZddMinimal(dd, S); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddMinimal */ + + +/**Function******************************************************************** + + Synopsis [Computes the maximal of the union of two sets represented by ZDDs.] + + Description [] + + SideEffects [] + + SeeAlso [Extra_zddMaximal Extra_zddMimimal Extra_zddMinUnion] + +******************************************************************************/ +DdNode * +Extra_zddMaxUnion( + DdManager * dd, + DdNode * S, + DdNode * T) +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraZddMaxUnion(dd, S, T); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddMaxUnion */ + + +/**Function******************************************************************** + + Synopsis [Computes the minimal of the union of two sets represented by ZDDs.] + + Description [] + + SideEffects [] + + SeeAlso [Extra_zddMaximal Extra_zddMimimal Extra_zddMaxUnion] + +******************************************************************************/ +DdNode * +Extra_zddMinUnion( + DdManager * dd, + DdNode * S, + DdNode * T) +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraZddMinUnion(dd, S, T); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddMinUnion */ + + +/**Function******************************************************************** + + Synopsis [Computes the dot product of two sets of subsets represented by ZDDs.] + + Description [The dot product is defined as a set of pair-wise unions of subsets + belonging to the arguments.] + + SideEffects [] + + SeeAlso [Extra_zddCrossProduct] + +******************************************************************************/ +DdNode * +Extra_zddDotProduct( + DdManager * dd, + DdNode * S, + DdNode * T) +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraZddDotProduct(dd, S, T); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddDotProduct */ + + +/**Function******************************************************************** + + Synopsis [Computes the cross product of two sets of subsets represented by ZDDs.] + + Description [The cross product is defined as a set of pair-wise intersections of subsets + belonging to the arguments.] + + SideEffects [] + + SeeAlso [Extra_zddDotProduct] + +******************************************************************************/ +DdNode * +Extra_zddCrossProduct( + DdManager * dd, + DdNode * S, + DdNode * T) +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraZddCrossProduct(dd, S, T); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddCrossProduct */ + + +/**Function******************************************************************** + + Synopsis [Computes the maximal of the DotProduct of the union of two sets represented by ZDDs.] + + Description [] + + SideEffects [] + + SeeAlso [Extra_zddDotProduct Extra_zddMaximal Extra_zddMinCrossProduct] + +******************************************************************************/ +DdNode * +Extra_zddMaxDotProduct( + DdManager * dd, + DdNode * S, + DdNode * T) +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraZddMaxDotProduct(dd, S, T); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddMaxDotProduct */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal Functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddMaximal.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraZddMaximal( + DdManager * dd, + DdNode * zSet) +{ + DdNode *zRes; + statLine(dd); + + /* consider terminal cases */ + if ( zSet == z0 || zSet == z1 ) + return zSet; + + /* check cache */ + zRes = cuddCacheLookup1Zdd(dd, extraZddMaximal, zSet); + if (zRes) + return(zRes); + else + { + DdNode *zSet0, *zSet1, *zRes0, *zRes1; + + /* compute maximal for subsets without the top-most element */ + zSet0 = extraZddMaximal(dd, cuddE(zSet)); + if ( zSet0 == NULL ) + return NULL; + cuddRef( zSet0 ); + + /* compute maximal for subsets with the top-most element */ + zSet1 = extraZddMaximal(dd, cuddT(zSet)); + if ( zSet1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + return NULL; + } + cuddRef( zSet1 ); + + /* remove subsets without this element covered by subsets with this element */ + zRes0 = extraZddNotSubSet(dd, zSet0, zSet1); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + Cudd_RecursiveDerefZdd(dd, zSet1); + return NULL; + } + cuddRef( zRes0 ); + Cudd_RecursiveDerefZdd(dd, zSet0); + + /* subset with this element remains unchanged */ + zRes1 = zSet1; + + /* create the new node */ + zRes = cuddZddGetNode( dd, zSet->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + + /* insert the result into cache */ + cuddCacheInsert1(dd, extraZddMaximal, zSet, zRes); + return zRes; + } +} /* end of extraZddMaximal */ + + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddMinimal.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraZddMinimal( + DdManager * dd, + DdNode * zSet) +{ + DdNode *zRes; + statLine(dd); + + /* consider terminal cases */ + if ( zSet == z0 ) + return zSet; + /* the empty combinaTon, if present, is the only minimal combinaTon */ + if ( Extra_zddEmptyBelongs(dd, zSet) ) + return z1; + + /* check cache */ + zRes = cuddCacheLookup1Zdd(dd, extraZddMinimal, zSet); + if (zRes) + return(zRes); + else + { + DdNode *zSet0, *zSet1, *zRes0, *zRes1; + + /* compute minimal for subsets without the top-most element */ + zSet0 = extraZddMinimal(dd, cuddE(zSet)); + if ( zSet0 == NULL ) + return NULL; + cuddRef( zSet0 ); + + /* compute minimal for subsets with the top-most element */ + zSet1 = extraZddMinimal(dd, cuddT(zSet)); + if ( zSet1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + return NULL; + } + cuddRef( zSet1 ); + + /* subset without this element remains unchanged */ + zRes0 = zSet0; + + /* remove subsets with this element that contain subsets without this element */ + zRes1 = extraZddNotSupSet(dd, zSet1, zSet0); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + Cudd_RecursiveDerefZdd(dd, zSet1); + return NULL; + } + cuddRef( zRes1 ); + Cudd_RecursiveDerefZdd(dd, zSet1); + + /* create the new node */ + zRes = cuddZddGetNode( dd, zSet->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + + /* insert the result into cache */ + cuddCacheInsert1(dd, extraZddMinimal, zSet, zRes); + return zRes; + } +} /* end of extraZddMinimal */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddMaxUnion.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraZddMaxUnion( + DdManager * dd, + DdNode * S, + DdNode * T) +{ + DdNode *zRes; + int TopS, TopT; + statLine(dd); + + /* consider terminal cases */ + if ( S == z0 ) + return T; + if ( T == z0 ) + return S; + if ( S == T ) + return S; + if ( S == z1 ) + return T; + if ( T == z1 ) + return S; + + /* the operation is commutative - normalize the problem */ + TopS = dd->permZ[S->index]; + TopT = dd->permZ[T->index]; + + if ( TopS > TopT || (TopS == TopT && S > T) ) + return extraZddMaxUnion(dd, T, S); + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddMaxUnion, S, T); + if (zRes) + return zRes; + else + { + DdNode *zSet0, *zSet1, *zRes0, *zRes1; + + if ( TopS == TopT ) + { + /* compute maximal for subsets without the top-most element */ + zSet0 = extraZddMaxUnion(dd, cuddE(S), cuddE(T) ); + if ( zSet0 == NULL ) + return NULL; + cuddRef( zSet0 ); + + /* compute maximal for subsets with the top-most element */ + zSet1 = extraZddMaxUnion(dd, cuddT(S), cuddT(T) ); + if ( zSet1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + return NULL; + } + cuddRef( zSet1 ); + } + else /* if ( TopS < TopT ) */ + { + /* compute maximal for subsets without the top-most element */ + zSet0 = extraZddMaxUnion(dd, cuddE(S), T ); + if ( zSet0 == NULL ) + return NULL; + cuddRef( zSet0 ); + + /* subset with this element is just the cofactor of S */ + zSet1 = cuddT(S); + cuddRef( zSet1 ); + } + + /* remove subsets without this element covered by subsets with this element */ + zRes0 = extraZddNotSubSet(dd, zSet0, zSet1); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + Cudd_RecursiveDerefZdd(dd, zSet1); + return NULL; + } + cuddRef( zRes0 ); + Cudd_RecursiveDerefZdd(dd, zSet0); + + /* subset with this element remains unchanged */ + zRes1 = zSet1; + + /* create the new node */ + zRes = cuddZddGetNode( dd, S->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddMaxUnion, S, T, zRes); + return zRes; + } +} /* end of extraZddMaxUnion */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddMinUnion.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraZddMinUnion( + DdManager * dd, + DdNode * S, + DdNode * T) +{ + DdNode *zRes; + int TopS, TopT; + statLine(dd); + + /* consider terminal cases */ + if ( S == z0 ) + return T; + if ( T == z0 ) + return S; + if ( S == T ) + return S; + /* the empty combination, if present, is the only minimal combination */ + if ( Extra_zddEmptyBelongs(dd, S) || Extra_zddEmptyBelongs(dd, T) ) + return z1; + + /* the operation is commutative - normalize the problem */ + TopS = dd->permZ[S->index]; + TopT = dd->permZ[T->index]; + + if ( TopS > TopT || (TopS == TopT && S > T) ) + return extraZddMinUnion(dd, T, S); + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddMinUnion, S, T); + if (zRes) + return(zRes); + else + { + DdNode *zSet0, *zSet1, *zRes0, *zRes1; + if ( TopS == TopT ) + { + /* compute maximal for subsets without the top-most element */ + zSet0 = extraZddMinUnion(dd, cuddE(S), cuddE(T) ); + if ( zSet0 == NULL ) + return NULL; + cuddRef( zSet0 ); + + /* compute maximal for subsets with the top-most element */ + zSet1 = extraZddMinUnion(dd, cuddT(S), cuddT(T) ); + if ( zSet1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + return NULL; + } + cuddRef( zSet1 ); + } + else /* if ( TopS < TopT ) */ + { + /* compute maximal for subsets without the top-most element */ + zSet0 = extraZddMinUnion(dd, cuddE(S), T ); + if ( zSet0 == NULL ) + return NULL; + cuddRef( zSet0 ); + + /* subset with this element is just the cofactor of S */ + zSet1 = cuddT(S); + cuddRef( zSet1 ); + } + + /* subset without this element remains unchanged */ + zRes0 = zSet0; + + /* remove subsets with this element that contain subsets without this element */ + zRes1 = extraZddNotSupSet(dd, zSet1, zSet0); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + Cudd_RecursiveDerefZdd(dd, zSet1); + return NULL; + } + cuddRef( zRes1 ); + Cudd_RecursiveDerefZdd(dd, zSet1); + + /* create the new node */ + zRes = cuddZddGetNode( dd, S->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddMinUnion, S, T, zRes); + return zRes; + } +} /* end of extraZddMinUnion */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddDotProduct.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraZddDotProduct( + DdManager * dd, + DdNode * S, + DdNode * T) +{ + DdNode *zRes; + int TopS, TopT; + statLine(dd); + + /* consider terminal cases */ + if ( S == z0 || T == z0 ) + return z0; + if ( S == z1 ) + return T; + if ( T == z1 ) + return S; + + /* the operation is commutative - normalize the problem */ + TopS = dd->permZ[S->index]; + TopT = dd->permZ[T->index]; + + if ( TopS > TopT || (TopS == TopT && S > T) ) + return extraZddDotProduct(dd, T, S); + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddDotProduct, S, T); + if (zRes) + return zRes; + else + { + DdNode *zSet0, *zSet1, *zRes0, *zRes1, *zTemp; + if ( TopS == TopT ) + { + /* compute the union of two cofactors of T (T0+T1) */ + zTemp = cuddZddUnion(dd, cuddE(T), cuddT(T) ); + if ( zTemp == NULL ) + return NULL; + cuddRef( zTemp ); + + /* compute DotProduct with the top element for subsets (S1, T0+T1) */ + zSet0 = extraZddDotProduct(dd, cuddT(S), zTemp ); + if ( zSet0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zTemp); + return NULL; + } + cuddRef( zSet0 ); + Cudd_RecursiveDerefZdd(dd, zTemp); + + /* compute DotProduct with the top element for subsets (S0, T1) */ + zSet1 = extraZddDotProduct(dd, cuddE(S), cuddT(T) ); + if ( zSet1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + return NULL; + } + cuddRef( zSet1 ); + + /* compute the union of these two partial results (zSet0 + zSet1) */ + zRes1 = cuddZddUnion(dd, zSet0, zSet1 ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + Cudd_RecursiveDerefZdd(dd, zSet1); + return NULL; + } + cuddRef( zRes1 ); + Cudd_RecursiveDerefZdd(dd, zSet0); + Cudd_RecursiveDerefZdd(dd, zSet1); + + /* compute DotProduct for subsets without the top-most element */ + zRes0 = extraZddDotProduct(dd, cuddE(S), cuddE(T) ); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddRef( zRes0 ); + } + else /* if ( TopS < TopT ) */ + { + /* compute DotProduct with the top element for subsets (S1, T) */ + zRes1 = extraZddDotProduct(dd, cuddT(S), T ); + if ( zRes1 == NULL ) + return NULL; + cuddRef( zRes1 ); + + /* compute DotProduct for subsets without the top-most element */ + zRes0 = extraZddDotProduct(dd, cuddE(S), T ); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddRef( zRes0 ); + } + + /* create the new node */ + zRes = cuddZddGetNode( dd, S->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddDotProduct, S, T, zRes); + return zRes; + } +} /* end of extraZddDotProduct */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddCrossProduct.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraZddCrossProduct( + DdManager * dd, + DdNode * S, + DdNode * T) +{ + DdNode *zRes; + int TopS, TopT; + statLine(dd); + + /* consider terminal cases */ + if ( S == z0 || T == z0 ) + return z0; + if ( S == z1 || T == z1 ) + return z1; + + /* the operation is commutative - normalize the problem */ + TopS = dd->permZ[S->index]; + TopT = dd->permZ[T->index]; + + if ( TopS > TopT || (TopS == TopT && S > T) ) + return extraZddCrossProduct(dd, T, S); + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddCrossProduct, S, T); + if (zRes) + return zRes; + else + { + DdNode *zSet0, *zSet1, *zRes0, *zRes1, *zTemp; + + if ( TopS == TopT ) + { + /* compute the union of two cofactors of T (T0+T1) */ + zTemp = cuddZddUnion(dd, cuddE(T), cuddT(T) ); + if ( zTemp == NULL ) + return NULL; + cuddRef( zTemp ); + + /* compute CrossProduct without the top element for subsets (S0, T0+T1) */ + zSet0 = extraZddCrossProduct(dd, cuddE(S), zTemp ); + if ( zSet0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zTemp); + return NULL; + } + cuddRef( zSet0 ); + Cudd_RecursiveDerefZdd(dd, zTemp); + + /* compute CrossProduct without the top element for subsets (S1, T0) */ + zSet1 = extraZddCrossProduct(dd, cuddT(S), cuddE(T) ); + if ( zSet1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + return NULL; + } + cuddRef( zSet1 ); + + /* compute the union of these two partial results (zSet0 + zSet1) */ + zRes0 = cuddZddUnion(dd, zSet0, zSet1 ); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + Cudd_RecursiveDerefZdd(dd, zSet1); + return NULL; + } + cuddRef( zRes0 ); + Cudd_RecursiveDerefZdd(dd, zSet0); + Cudd_RecursiveDerefZdd(dd, zSet1); + + /* compute CrossProduct for subsets with the top-most element */ + zRes1 = extraZddCrossProduct(dd, cuddT(S), cuddT(T) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes0); + return NULL; + } + cuddRef( zRes1 ); + + /* create the new node */ + zRes = cuddZddGetNode( dd, S->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + else /* if ( TopS < TopT ) */ + { + /* compute CrossProduct without the top element (S0, T) */ + zSet0 = extraZddCrossProduct(dd, cuddE(S), T ); + if ( zSet0 == NULL ) + return NULL; + cuddRef( zSet0 ); + + /* compute CrossProduct without the top element (S1, T) */ + zSet1 = extraZddCrossProduct(dd, cuddT(S), T ); + if ( zSet1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + return NULL; + } + cuddRef( zSet1 ); + + /* compute the union of these two partial results (zSet0 + zSet1) */ + zRes = cuddZddUnion(dd, zSet0, zSet1 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + Cudd_RecursiveDerefZdd(dd, zSet1); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd(dd, zSet0); + Cudd_RecursiveDerefZdd(dd, zSet1); + cuddDeref( zRes ); + } + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddCrossProduct, S, T, zRes); + return zRes; + } +} /* end of extraZddCrossProduct */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddMaxDotProduct.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraZddMaxDotProduct( + DdManager * dd, + DdNode * S, + DdNode * T) +{ + DdNode *zRes; + int TopS, TopT; + statLine(dd); + + /* consider terminal cases */ + if ( S == z0 || T == z0 ) + return z0; + if ( S == z1 ) + return T; + if ( T == z1 ) + return S; + + /* the operation is commutative - normalize the problem */ + TopS = dd->permZ[S->index]; + TopT = dd->permZ[T->index]; + + if ( TopS > TopT || (TopS == TopT && S > T) ) + return extraZddMaxDotProduct(dd, T, S); + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddMaxDotProduct, S, T); + if (zRes) + return zRes; + else + { + DdNode *zSet0, *zSet1, *zRes0, *zRes1, *zTemp; + if ( TopS == TopT ) + { + /* compute the union of two cofactors of T (T0+T1) */ + zTemp = extraZddMaxUnion(dd, cuddE(T), cuddT(T) ); + if ( zTemp == NULL ) + return NULL; + cuddRef( zTemp ); + + /* compute MaxDotProduct with the top element for subsets (S1, T0+T1) */ + zSet0 = extraZddMaxDotProduct(dd, cuddT(S), zTemp ); + if ( zSet0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zTemp); + return NULL; + } + cuddRef( zSet0 ); + Cudd_RecursiveDerefZdd(dd, zTemp); + + /* compute MaxDotProduct with the top element for subsets (S0, T1) */ + zSet1 = extraZddMaxDotProduct(dd, cuddE(S), cuddT(T) ); + if ( zSet1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + return NULL; + } + cuddRef( zSet1 ); + + /* compute the union of these two partial results (zSet0 + zSet1) */ + zRes1 = extraZddMaxUnion(dd, zSet0, zSet1 ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zSet0); + Cudd_RecursiveDerefZdd(dd, zSet1); + return NULL; + } + cuddRef( zRes1 ); + Cudd_RecursiveDerefZdd(dd, zSet0); + Cudd_RecursiveDerefZdd(dd, zSet1); + + /* compute MaxDotProduct for subsets without the top-most element */ + zRes0 = extraZddMaxDotProduct(dd, cuddE(S), cuddE(T) ); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddRef( zRes0 ); + } + else /* if ( TopS < TopT ) */ + { + /* compute MaxDotProduct with the top element for subsets (S1, T) */ + zRes1 = extraZddMaxDotProduct(dd, cuddT(S), T ); + if ( zRes1 == NULL ) + return NULL; + cuddRef( zRes1 ); + + /* compute MaxDotProduct for subsets without the top-most element */ + zRes0 = extraZddMaxDotProduct(dd, cuddE(S), T ); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddRef( zRes0 ); + } + + /* remove subsets without this element covered by subsets with this element */ + zRes0 = extraZddNotSubSet(dd, zTemp = zRes0, zRes1); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zTemp); + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddRef( zRes0 ); + Cudd_RecursiveDerefZdd(dd, zTemp); + + /* create the new node */ + zRes = cuddZddGetNode( dd, S->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddMaxDotProduct, S, T, zRes); + return zRes; + } +} /* end of extraZddMaxDotProduct */ + +/*---------------------------------------------------------------------------*/ +/* Definition of staTc Functions */ +/*---------------------------------------------------------------------------*/ + +ABC_NAMESPACE_IMPL_END diff --git a/src/bdd/extrab/extraBddMisc.c b/src/bdd/extrab/extraBddMisc.c index 335f675..4200386 100644 --- a/src/bdd/extrab/extraBddMisc.c +++ b/src/bdd/extrab/extraBddMisc.c @@ -2723,8 +2723,8 @@ DdNode * Extra_bddTuples( if ( K > nVars ) return NULL; - /* the second argument in the recursive call stannds for <n>; - /* reate the first argument, which stands for <k> + /* the second argument in the recursive call stands for <n>; + * create the first argument, which stands for <k> * as when we are talking about the tuple of <k> out of <n> */ for ( i = 0; i < nVars-K; i++ ) VarsK = cuddT( VarsK ); diff --git a/src/bdd/extrab/extraBddSet.c b/src/bdd/extrab/extraBddSet.c new file mode 100644 index 0000000..882c474 --- /dev/null +++ b/src/bdd/extrab/extraBddSet.c @@ -0,0 +1,941 @@ +/**CFile*********************************************************************** + + FileName [zSubSet.c] + + PackageName [extra] + + Synopsis [Experimental version of some ZDD operators.] + + Description [External procedures included in this module: + <ul> + <li> Extra_zddSubSet(); + <li> Extra_zddSupSet(); + <li> Extra_zddNotSubSet(); + <li> Extra_zddNotSupSet(); + <li> Extra_zddMaxNotSupSet(); + <li> Extra_zddEmptyBelongs(); + <li> Extra_zddIsOneSubset(); + </ul> + Internal procedures included in this module: + <ul> + <li> extraZddSubSet(); + <li> extraZddSupSet(); + <li> extraZddNotSubSet(); + <li> extraZddNotSupSet(); + <li> extraZddMaxNotSupSet(); + </ul> + Static procedures included in this module: + <ul> + </ul> + + SubSet, SupSet, NotSubSet, NotSupSet were introduced + by O.Coudert to solve problems arising in two-level SOP + minimization. See O. Coudert, "Two-Level Logic Minimization: + An Overview", Integration. Vol. 17, No. 2, pp. 97-140, Oct 1994. + ] + + SeeAlso [] + + Author [Alan Mishchenko] + + Copyright [] + + Revision [$zSubSet.c, v.1.2, November 16, 2000, alanmi $] + +******************************************************************************/ + +#include "extraBdd.h" + +ABC_NAMESPACE_IMPL_START + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Computes subsets in X that are contained in some of the subsets of Y.] + + Description [] + + SideEffects [] + + SeeAlso [Extra_zddNotSubSet, Extra_zddSupSet, Extra_zddNotSupSet] + +******************************************************************************/ +DdNode * +Extra_zddSubSet( + DdManager * dd, + DdNode * X, + DdNode * Y) +{ + DdNode *res; + int autoDynZ; + + autoDynZ = dd->autoDynZ; + dd->autoDynZ = 0; + + do { + dd->reordered = 0; + res = extraZddSubSet(dd, X, Y); + } while (dd->reordered == 1); + dd->autoDynZ = autoDynZ; + return(res); + +} /* end of Extra_zddSubSet */ + + +/**Function******************************************************************** + + Synopsis [Computes subsets in X that contain some of the subsets of Y.] + + Description [] + + SideEffects [] + + SeeAlso [Extra_zddSubSet, Extra_zddNotSubSet, Extra_zddNotSupSet] + +******************************************************************************/ +DdNode * +Extra_zddSupSet( + DdManager * dd, + DdNode * X, + DdNode * Y) +{ + DdNode *res; + int autoDynZ; + + autoDynZ = dd->autoDynZ; + dd->autoDynZ = 0; + + do { + dd->reordered = 0; + res = extraZddSupSet(dd, X, Y); + } while (dd->reordered == 1); + dd->autoDynZ = autoDynZ; + return(res); + +} /* end of Extra_zddSupSet */ + +/**Function******************************************************************** + + Synopsis [Computes subsets in X that are not contained in any of the subsets of Y.] + + Description [] + + SideEffects [] + + SeeAlso [Extra_zddSubSet, Extra_zddSupSet, Extra_zddNotSupSet] + +******************************************************************************/ +DdNode * +Extra_zddNotSubSet( + DdManager * dd, + DdNode * X, + DdNode * Y) +{ + DdNode *res; + int autoDynZ; + + autoDynZ = dd->autoDynZ; + dd->autoDynZ = 0; + + do { + dd->reordered = 0; + res = extraZddNotSubSet(dd, X, Y); + } while (dd->reordered == 1); + dd->autoDynZ = autoDynZ; + return(res); + +} /* end of Extra_zddNotSubSet */ + + +/**Function******************************************************************** + + Synopsis [Computes subsets in X that do not contain any of the subsets of Y.] + + Description [] + + SideEffects [] + + SeeAlso [Extra_zddSubSet, Extra_zddSupSet, Extra_zddNotSubSet] + +******************************************************************************/ +DdNode * +Extra_zddNotSupSet( + DdManager * dd, + DdNode * X, + DdNode * Y) +{ + DdNode *res; + int autoDynZ; + + autoDynZ = dd->autoDynZ; + dd->autoDynZ = 0; + + do { + dd->reordered = 0; + res = extraZddNotSupSet(dd, X, Y); + } while (dd->reordered == 1); + dd->autoDynZ = autoDynZ; + return(res); + +} /* end of Extra_zddNotSupSet */ + + + +/**Function******************************************************************** + + Synopsis [Computes the maximal of subsets in X not contained in any of the subsets of Y.] + + Description [] + + SideEffects [] + + SeeAlso [Extra_zddSubSet, Extra_zddSupSet, Extra_zddSubSet, Extra_zddNotSupSet] + +******************************************************************************/ +DdNode * +Extra_zddMaxNotSupSet( + DdManager * dd, + DdNode * X, + DdNode * Y) +{ + DdNode *res; + int autoDynZ; + + autoDynZ = dd->autoDynZ; + dd->autoDynZ = 0; + + do { + dd->reordered = 0; + res = extraZddMaxNotSupSet(dd, X, Y); + } while (dd->reordered == 1); + dd->autoDynZ = autoDynZ; + return(res); + +} /* end of Extra_zddMaxNotSupSet */ + + +/**Function******************************************************************** + + Synopsis [Returns 1 if ZDD contains the empty combination; 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +Extra_zddEmptyBelongs( + DdManager *dd, + DdNode* zS ) +{ + while ( zS->index != CUDD_MAXINDEX ) + zS = cuddE( zS ); + return (int)( zS == z1 ); + +} /* end of Extra_zddEmptyBelongs */ + + +/**Function******************************************************************** + + Synopsis [Returns 1 if the set is empty or consists of one subset only.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +Extra_zddIsOneSubset( + DdManager * dd, + DdNode * zS ) +{ + while ( zS->index != CUDD_MAXINDEX ) + { + assert( cuddT(zS) != z0 ); + if ( cuddE(zS) != z0 ) + return 0; + zS = cuddT( zS ); + } + return (int)( zS == z1 ); + +} /* end of Extra_zddEmptyBelongs */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddSubSet.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode* extraZddSubSet( DdManager *dd, DdNode *X, DdNode *Y ) +{ + DdNode *zRes; + statLine(dd); + /* any comb is a subset of itself */ + if ( X == Y ) + return X; + /* if X is empty, the result is empty */ + if ( X == z0 ) + return z0; + /* combs in X are notsubsets of non-existant combs in Y */ + if ( Y == z0 ) + return z0; + /* the empty comb is contained in all combs of Y */ + if ( X == z1 ) + return z1; + /* only {()} is the subset of {()} */ + if ( Y == z1 ) /* check whether the empty combination is present in X */ + return ( Extra_zddEmptyBelongs( dd, X )? z1: z0 ); + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddSubSet, X, Y); + if (zRes) + return(zRes); + else + { + DdNode *zRes0, *zRes1, *zTemp; + int TopLevelX = dd->permZ[ X->index ]; + int TopLevelY = dd->permZ[ Y->index ]; + + if ( TopLevelX < TopLevelY ) + { + /* compute combs of X without var that are notsubsets of combs with Y */ + zRes = extraZddSubSet( dd, cuddE( X ), Y ); + if ( zRes == NULL ) return NULL; + } + else if ( TopLevelX == TopLevelY ) + { + /* merge combs of Y with and without var */ + zTemp = cuddZddUnion( dd, cuddE( Y ), cuddT( Y ) ); + if ( zTemp == NULL ) + return NULL; + cuddRef( zTemp ); + + /* compute combs of X without var that are notsubsets of combs is Temp */ + zRes0 = extraZddSubSet( dd, cuddE( X ), zTemp ); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + return NULL; + } + cuddRef( zRes0 ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + + /* combs of X with var that are notsubsets of combs in Y with var */ + zRes1 = extraZddSubSet( dd, cuddT( X ), cuddT( Y ) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + /* compose Res0 and Res1 with the given ZDD variable */ + zRes = cuddZddGetNode( dd, X->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + else /* if ( TopLevelX > TopLevelY ) */ + { + /* merge combs of Y with and without var */ + zTemp = cuddZddUnion( dd, cuddE( Y ), cuddT( Y ) ); + if ( zTemp == NULL ) return NULL; + cuddRef( zTemp ); + + /* compute combs that are notsubsets of Temp */ + zRes = extraZddSubSet( dd, X, zTemp ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + cuddDeref( zRes ); + } + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddSubSet, X, Y, zRes); + return zRes; + } +} /* end of extraZddSubSet */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddSupSet.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode* extraZddSupSet( DdManager *dd, DdNode *X, DdNode *Y ) +{ + DdNode *zRes; + statLine(dd); + /* any comb is a superset of itself */ + if ( X == Y ) + return X; + /* no comb in X is superset of non-existing combs */ + if ( Y == z0 ) + return z0; + /* any comb in X is the superset of the empty comb */ + if ( Extra_zddEmptyBelongs( dd, Y ) ) + return X; + /* if X is empty, the result is empty */ + if ( X == z0 ) + return z0; + /* if X is the empty comb (and Y does not contain it!), return empty */ + if ( X == z1 ) + return z0; + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddSupSet, X, Y); + if (zRes) + return(zRes); + else + { + DdNode *zRes0, *zRes1, *zTemp; + int TopLevelX = dd->permZ[ X->index ]; + int TopLevelY = dd->permZ[ Y->index ]; + + if ( TopLevelX < TopLevelY ) + { + /* combinations of X without label that are supersets of combinations with Y */ + zRes0 = extraZddSupSet( dd, cuddE( X ), Y ); + if ( zRes0 == NULL ) return NULL; + cuddRef( zRes0 ); + + /* combinations of X with label that are supersets of combinations with Y */ + zRes1 = extraZddSupSet( dd, cuddT( X ), Y ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + /* compose Res0 and Res1 with the given ZDD variable */ + zRes = cuddZddGetNode( dd, X->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + else if ( TopLevelX == TopLevelY ) + { + /* combs of X without var that are supersets of combs of Y without var */ + zRes0 = extraZddSupSet( dd, cuddE( X ), cuddE( Y ) ); + if ( zRes0 == NULL ) return NULL; + cuddRef( zRes0 ); + + /* merge combs of Y with and without var */ + zTemp = cuddZddUnion( dd, cuddE( Y ), cuddT( Y ) ); + if ( zTemp == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zTemp ); + + /* combs of X with label that are supersets of combs in Temp */ + zRes1 = extraZddSupSet( dd, cuddT( X ), zTemp ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + return NULL; + } + cuddRef( zRes1 ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + + /* compose Res0 and Res1 with the given ZDD variable */ + zRes = cuddZddGetNode( dd, X->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + else /* if ( TopLevelX > TopLevelY ) */ + { + /* combs of X that are supersets of combs of Y without label */ + zRes = extraZddSupSet( dd, X, cuddE( Y ) ); + if ( zRes == NULL ) return NULL; + } + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddSupSet, X, Y, zRes); + return zRes; + } +} /* end of extraZddSupSet */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddNotSubSet.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode* extraZddNotSubSet( DdManager *dd, DdNode *X, DdNode *Y ) +{ + DdNode *zRes; + statLine(dd); + /* any comb is a subset of itself */ + if ( X == Y ) + return z0; + /* combs in X are notsubsets of non-existant combs in Y */ + if ( Y == z0 ) + return X; + /* only {()} is the subset of {()} */ + if ( Y == z1 ) /* remove empty combination from X */ + return cuddZddDiff( dd, X, z1 ); + /* if X is empty, the result is empty */ + if ( X == z0 ) + return z0; + /* the empty comb is contained in all combs of Y */ + if ( X == z1 ) + return z0; + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddNotSubSet, X, Y); + if (zRes) + return(zRes); + else + { + DdNode *zRes0, *zRes1, *zTemp; + int TopLevelX = dd->permZ[ X->index ]; + int TopLevelY = dd->permZ[ Y->index ]; + + if ( TopLevelX < TopLevelY ) + { + /* compute combs of X without var that are notsubsets of combs with Y */ + zRes0 = extraZddNotSubSet( dd, cuddE( X ), Y ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + /* combs of X with var cannot be subsets of combs without var in Y */ + zRes1 = cuddT( X ); + + /* compose Res0 and Res1 with the given ZDD variable */ + zRes = cuddZddGetNode( dd, X->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddDeref( zRes0 ); + } + else if ( TopLevelX == TopLevelY ) + { + /* merge combs of Y with and without var */ + zTemp = cuddZddUnion( dd, cuddE( Y ), cuddT( Y ) ); + if ( zTemp == NULL ) + return NULL; + cuddRef( zTemp ); + + /* compute combs of X without var that are notsubsets of combs is Temp */ + zRes0 = extraZddNotSubSet( dd, cuddE( X ), zTemp ); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + return NULL; + } + cuddRef( zRes0 ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + + /* combs of X with var that are notsubsets of combs in Y with var */ + zRes1 = extraZddNotSubSet( dd, cuddT( X ), cuddT( Y ) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + /* compose Res0 and Res1 with the given ZDD variable */ + zRes = cuddZddGetNode( dd, X->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + else /* if ( TopLevelX > TopLevelY ) */ + { + /* merge combs of Y with and without var */ + zTemp = cuddZddUnion( dd, cuddE( Y ), cuddT( Y ) ); + if ( zTemp == NULL ) + return NULL; + cuddRef( zTemp ); + + /* compute combs that are notsubsets of Temp */ + zRes = extraZddNotSubSet( dd, X, zTemp ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + cuddDeref( zRes ); + } + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddNotSubSet, X, Y, zRes); + return zRes; + } +} /* end of extraZddNotSubSet */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddNotSupSet.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode* extraZddNotSupSet( DdManager *dd, DdNode *X, DdNode *Y ) +{ + DdNode *zRes; + statLine(dd); + /* any comb is a superset of itself */ + if ( X == Y ) + return z0; + /* no comb in X is superset of non-existing combs */ + if ( Y == z0 ) + return X; + /* any comb in X is the superset of the empty comb */ + if ( Extra_zddEmptyBelongs( dd, Y ) ) + return z0; + /* if X is empty, the result is empty */ + if ( X == z0 ) + return z0; + /* if X is the empty comb (and Y does not contain it!), return it */ + if ( X == z1 ) + return z1; + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddNotSupSet, X, Y); + if (zRes) + return(zRes); + else + { + DdNode *zRes0, *zRes1, *zTemp; + int TopLevelX = dd->permZ[ X->index ]; + int TopLevelY = dd->permZ[ Y->index ]; + + if ( TopLevelX < TopLevelY ) + { + /* combinations of X without label that are supersets of combinations of Y */ + zRes0 = extraZddNotSupSet( dd, cuddE( X ), Y ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + /* combinations of X with label that are supersets of combinations of Y */ + zRes1 = extraZddNotSupSet( dd, cuddT( X ), Y ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + /* compose Res0 and Res1 with the given ZDD variable */ + zRes = cuddZddGetNode( dd, X->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + else if ( TopLevelX == TopLevelY ) + { + /* combs of X without var that are not supersets of combs of Y without var */ + zRes0 = extraZddNotSupSet( dd, cuddE( X ), cuddE( Y ) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + /* merge combs of Y with and without var */ + zTemp = cuddZddUnion( dd, cuddE( Y ), cuddT( Y ) ); + if ( zTemp == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zTemp ); + + /* combs of X with label that are supersets of combs in Temp */ + zRes1 = extraZddNotSupSet( dd, cuddT( X ), zTemp ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + return NULL; + } + cuddRef( zRes1 ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + + /* compose Res0 and Res1 with the given ZDD variable */ + zRes = cuddZddGetNode( dd, X->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + else /* if ( TopLevelX > TopLevelY ) */ + { + /* combs of X that are supersets of combs of Y without label */ + zRes = extraZddNotSupSet( dd, X, cuddE( Y ) ); + if ( zRes == NULL ) return NULL; + } + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddNotSupSet, X, Y, zRes); + return zRes; + } +} /* end of extraZddNotSupSet */ + + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddMaxNotSupSet.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode* extraZddMaxNotSupSet( DdManager *dd, DdNode *X, DdNode *Y ) +{ + DdNode *zRes; + statLine(dd); + /* any comb is a superset of itself */ + if ( X == Y ) + return z0; + /* no comb in X is superset of non-existing combs */ + if ( Y == z0 ) + return extraZddMaximal( dd, X ); + /* any comb in X is the superset of the empty comb */ + if ( Extra_zddEmptyBelongs( dd, Y ) ) + return z0; + /* if X is empty, the result is empty */ + if ( X == z0 ) + return z0; + /* if X is the empty comb (and Y does not contain it!), return it */ + if ( X == z1 ) + return z1; + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddMaxNotSupSet, X, Y); + if (zRes) + return(zRes); + else + { + DdNode *zRes0, *zRes1, *zTemp; + int TopLevelX = dd->permZ[ X->index ]; + int TopLevelY = dd->permZ[ Y->index ]; + + if ( TopLevelX < TopLevelY ) + { + /* combinations of X without label that are supersets of combinations with Y */ + zRes0 = extraZddMaxNotSupSet( dd, cuddE( X ), Y ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + /* combinations of X with label that are supersets of combinations with Y */ + zRes1 = extraZddMaxNotSupSet( dd, cuddT( X ), Y ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + /* ---------------------------------------------------- */ + /* remove subsets without this element covered by subsets with this element */ + zRes0 = extraZddNotSubSet(dd, zTemp = zRes0, zRes1); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zTemp); + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddRef( zRes0 ); + Cudd_RecursiveDerefZdd(dd, zTemp); + /* ---------------------------------------------------- */ + + /* compose Res0 and Res1 with the given ZDD variable */ + zRes = cuddZddGetNode( dd, X->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + else if ( TopLevelX == TopLevelY ) + { + /* combs of X without var that are supersets of combs of Y without var */ + zRes0 = extraZddMaxNotSupSet( dd, cuddE( X ), cuddE( Y ) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + /* merge combs of Y with and without var */ + zTemp = cuddZddUnion( dd, cuddE( Y ), cuddT( Y ) ); + if ( zTemp == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zTemp ); + + /* combs of X with label that are supersets of combs in Temp */ + zRes1 = extraZddMaxNotSupSet( dd, cuddT( X ), zTemp ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + return NULL; + } + cuddRef( zRes1 ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + + /* ---------------------------------------------------- */ + /* remove subsets without this element covered by subsets with this element */ + zRes0 = extraZddNotSubSet(dd, zTemp = zRes0, zRes1); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zTemp); + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddRef( zRes0 ); + Cudd_RecursiveDerefZdd(dd, zTemp); + /* ---------------------------------------------------- */ + + /* compose Res0 and Res1 with the given ZDD variable */ + zRes = cuddZddGetNode( dd, X->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + else /* if ( TopLevelX > TopLevelY ) */ + { + /* combs of X that are supersets of combs of Y without label */ + zRes = extraZddMaxNotSupSet( dd, X, cuddE( Y ) ); + if ( zRes == NULL ) return NULL; + } + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddMaxNotSupSet, X, Y, zRes); + return zRes; + } +} /* end of extraZddMaxNotSupSet */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +ABC_NAMESPACE_IMPL_END diff --git a/src/bdd/extrab/module.make b/src/bdd/extrab/module.make index 62b578f..cee5ac8 100644 --- a/src/bdd/extrab/module.make +++ b/src/bdd/extrab/module.make @@ -2,7 +2,9 @@ SRC += src/bdd/extrab/extraBddAuto.c \ src/bdd/extrab/extraBddCas.c \ src/bdd/extrab/extraBddImage.c \ src/bdd/extrab/extraBddKmap.c \ + src/bdd/extrab/extraBddMaxMin.c \ src/bdd/extrab/extraBddMisc.c \ + src/bdd/extrab/extraBddSet.c \ src/bdd/extrab/extraBddSymm.c \ src/bdd/extrab/extraBddThresh.c \ src/bdd/extrab/extraBddTime.c \ diff --git a/src/map/amap/amapLib.c b/src/map/amap/amapLib.c index b6350fe..26ef639 100644 --- a/src/map/amap/amapLib.c +++ b/src/map/amap/amapLib.c @@ -242,8 +242,11 @@ Amap_Gat_t * Amap_LibFindGate( Amap_Lib_t * p, unsigned uTruth ) Amap_Gat_t * pGate; int i; Vec_PtrForEachEntry( Amap_Gat_t *, p->vSorted, pGate, i ) + { + if (( pGate == NULL ) || ( pGate->pFunc == NULL )) continue; if ( pGate->nPins <= 5 && pGate->pFunc[0] == uTruth ) return pGate; + } return NULL; } diff --git a/src/map/amap/amapLiberty.c b/src/map/amap/amapLiberty.c index 13b18df..d5d2d72 100644 --- a/src/map/amap/amapLiberty.c +++ b/src/map/amap/amapLiberty.c @@ -209,6 +209,26 @@ int Amap_LibertyCellIsFlop( Amap_Tree_t * p, Amap_Item_t * pCell ) /**Function************************************************************* + Synopsis [Returns cell's function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Amap_LibertyCellIsDontUse( Amap_Tree_t * p, Amap_Item_t * pCell ) +{ + Amap_Item_t * pAttr; + Amap_ItemForEachChild( p, pCell, pAttr ) + if ( !Amap_LibertyCompare(p, pAttr->Key, "dont_use") ) + return 1; + return 0; +} + +/**Function************************************************************* + Synopsis [Returns pin's function.] Description [] @@ -414,6 +434,12 @@ int Amap_LibertyPrintGenlib( Amap_Tree_t * p, char * pFileName, int fVerbose ) printf( "Amap_LibertyPrintGenlib() skipped sequential cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) ); continue; } + if ( Amap_LibertyCellIsDontUse(p, pCell) ) + { + if ( fVerbose ) + printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" due to dont_use attribute.\n", Amap_LibertyGetString(p, pCell->Head) ); + continue; + } Counter = Amap_LibertyCellCountOutputs( p, pCell ); if ( Counter == 0 ) { @@ -498,6 +524,12 @@ Vec_Str_t * Amap_LibertyPrintGenlibStr( Amap_Tree_t * p, int fVerbose ) printf( "Amap_LibertyPrintGenlib() skipped sequential cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) ); continue; } + if ( Amap_LibertyCellIsDontUse(p, pCell) ) + { + if ( fVerbose ) + printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" due to dont_use attribute.\n", Amap_LibertyGetString(p, pCell->Head) ); + continue; + } Counter = Amap_LibertyCellCountOutputs( p, pCell ); if ( Counter == 0 ) { diff --git a/src/map/if/ifTune.c b/src/map/if/ifTune.c index d1ed7ab..13e45f4 100644 --- a/src/map/if/ifTune.c +++ b/src/map/if/ifTune.c @@ -622,10 +622,10 @@ sat_solver * Ifn_ManSatBuild( Ifn_Ntk_t * p, Vec_Int_t ** pvPiVars, Vec_Int_t ** sat_solver * pSat = NULL; *pvPiVars = *pvPoVars = NULL; p1 = Ifn_ManStrFindModel( p ); -// Gia_AigerWrite( p1, "satbuild.aig", 0, 0 ); +// Gia_AigerWrite( p1, "satbuild.aig", 0, 0, 0 ); p2 = Ifn_ManStrFindCofactors( p->nInps, p1 ); Gia_ManStop( p1 ); -// Gia_AigerWrite( p2, "satbuild2.aig", 0, 0 ); +// Gia_AigerWrite( p2, "satbuild2.aig", 0, 0, 0 ); pSat = Ifn_ManStrFindSolver( p2, pvPiVars, pvPoVars ); Gia_ManStop( p2 ); return pSat; diff --git a/src/map/scl/sclLiberty.c b/src/map/scl/sclLiberty.c index fc06bc4..cd28a60 100644 --- a/src/map/scl/sclLiberty.c +++ b/src/map/scl/sclLiberty.c @@ -629,6 +629,14 @@ int Scl_LibertyReadCellIsFlop( Scl_Tree_t * p, Scl_Item_t * pCell ) return 1; return 0; } +int Scl_LibertyReadCellIsDontUse( Scl_Tree_t * p, Scl_Item_t * pCell ) +{ + Scl_Item_t * pAttr; + Scl_ItemForEachChild( p, pCell, pAttr ) + if ( !Scl_LibertyCompare(p, pAttr->Key, "dont_use") ) + return 1; + return 0; +} char * Scl_LibertyReadCellArea( Scl_Tree_t * p, Scl_Item_t * pCell ) { Scl_Item_t * pArea; @@ -704,6 +712,11 @@ Vec_Str_t * Scl_LibertyReadGenlibStr( Scl_Tree_t * p, int fVerbose ) if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped sequential cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) ); continue; } + if ( Scl_LibertyReadCellIsDontUse(p, pCell) ) + { + if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" due to dont_use attribute.\n", Scl_LibertyReadString(p, pCell->Head) ); + continue; + } if ( Scl_LibertyReadCellIsThreeState(p, pCell) ) { if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped three-state cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) ); @@ -1417,7 +1430,7 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos Vec_Wrd_t * vTruth; char * pFormula, * pName; int i, k, Counter, nOutputs, nCells; - int nSkipped[3] = {0}; + int nSkipped[4] = {0}; // read delay-table templates vTemples = Scl_LibertyReadTemplates( p ); @@ -1451,6 +1464,12 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos nSkipped[0]++; continue; } + if ( Scl_LibertyReadCellIsDontUse(p, pCell) ) + { + if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" due to dont_use attribute.\n", Scl_LibertyReadString(p, pCell->Head) ); + nSkipped[3]++; + continue; + } if ( Scl_LibertyReadCellIsThreeState(p, pCell) ) { if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped three-state cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) ); @@ -1473,6 +1492,8 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos { if ( Scl_LibertyReadCellIsFlop(p, pCell) ) continue; + if ( Scl_LibertyReadCellIsDontUse(p, pCell) ) + continue; if ( Scl_LibertyReadCellIsThreeState(p, pCell) ) continue; if ( (Counter = Scl_LibertyReadCellOutputNum(p, pCell)) == 0 ) @@ -1640,8 +1661,8 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos { printf( "Library \"%s\" from \"%s\" has %d cells ", Scl_LibertyReadString(p, Scl_LibertyRoot(p)->Head), p->pFileName, nCells ); - printf( "(%d skipped: %d seq; %d tri-state; %d no func). ", - nSkipped[0]+nSkipped[1]+nSkipped[2], nSkipped[0], nSkipped[1], nSkipped[2] ); + printf( "(%d skipped: %d seq; %d tri-state; %d no func; %d dont_use). ", + nSkipped[0]+nSkipped[1]+nSkipped[2], nSkipped[0], nSkipped[1], nSkipped[2], nSkipped[3] ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } return vOut; diff --git a/src/misc/extra/extraUtilMaj.c b/src/misc/extra/extraUtilMaj.c index 3787593..8bdb081 100644 --- a/src/misc/extra/extraUtilMaj.c +++ b/src/misc/extra/extraUtilMaj.c @@ -370,7 +370,7 @@ int Gem_Enumerate( int nVars, int fDump, int fVerbose ) if ( Gem_FuncReduce( p, f, i, j ) ) return Gem_ManFree( p ); } - printf( "Finished (functions = %10d) ", v, p->nObjs ); + printf( "Finished (functions = %10d) ", p->nObjs ); Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); if ( fDump ) Vec_MemDumpTruthTables( p->vTtMem, "enum", nVars ); Gem_ManFree( p ); diff --git a/src/misc/extra/extraUtilPath.c b/src/misc/extra/extraUtilPath.c index c7231a0..165f402 100644 --- a/src/misc/extra/extraUtilPath.c +++ b/src/misc/extra/extraUtilPath.c @@ -98,7 +98,7 @@ void Abc_EnumeratePathsTest() { int nSize = 2; Gia_Man_t * pGia = Abc_EnumeratePaths( nSize ); - Gia_AigerWrite( pGia, "testpath.aig", 0, 0 ); + Gia_AigerWrite( pGia, "testpath.aig", 0, 0, 0 ); Gia_ManStop( pGia ); } @@ -353,7 +353,7 @@ void Abc_GraphDeriveGiaDump( Vec_Wec_t * vNodes, Vec_Int_t * vEdges, int Size ) char pFileName[100]; Gia_Man_t * pGia = Abc_GraphDeriveGia( vNodes, vEdges ); sprintf( pFileName, "grid_%dx%d_e%03d.aig", Size, Size, Vec_IntSize(vEdges)/2 ); - Gia_AigerWrite( pGia, pFileName, 0, 0 ); + Gia_AigerWrite( pGia, pFileName, 0, 0, 0 ); Gia_ManStop( pGia ); printf( "Finished dumping AIG into file \"%s\".\n", pFileName ); } diff --git a/src/misc/extra/extraUtilPerm.c b/src/misc/extra/extraUtilPerm.c index b077a7a..3e8505f 100644 --- a/src/misc/extra/extraUtilPerm.c +++ b/src/misc/extra/extraUtilPerm.c @@ -269,7 +269,7 @@ int Abc_ZddDiff( Abc_ZddMan * p, int a, int b ) else r0 = Abc_ZddDiff( p, A->False, B->False ), r1 = Abc_ZddDiff( p, A->True, B->True ), - r = Abc_ZddUniqueCreate( p, A->Var, A->True, r0 ); + r = Abc_ZddUniqueCreate( p, A->Var, r1, r0 ); return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_DIFF, r ); } int Abc_ZddUnion( Abc_ZddMan * p, int a, int b ) diff --git a/src/misc/util/abc_global.h b/src/misc/util/abc_global.h index 14523ab..c27b907 100644 --- a/src/misc/util/abc_global.h +++ b/src/misc/util/abc_global.h @@ -357,6 +357,9 @@ static inline void Abc_Print( int level, const char * format, ... ) { extern ABC_DLL int Abc_FrameIsBridgeMode(); va_list args; + extern unsigned enable_dbg_outs; + if ( !enable_dbg_outs ) + return; if ( ! Abc_FrameIsBridgeMode() ){ if ( level == ABC_ERROR ) diff --git a/src/misc/util/utilBridge.c b/src/misc/util/utilBridge.c index f988b65..ecf8765 100644 --- a/src/misc/util/utilBridge.c +++ b/src/misc/util/utilBridge.c @@ -551,7 +551,7 @@ void Gia_ManFromBridgeTest( char * pFileName ) fclose ( pFile ); Gia_ManPrintStats( p, NULL ); - Gia_AigerWrite( p, "temp.aig", 0, 0 ); + Gia_AigerWrite( p, "temp.aig", 0, 0, 0 ); Gia_ManToBridgeAbsNetlistTest( "par_.dump", p, BRIDGE_ABS_NETLIST ); Gia_ManStop( p ); diff --git a/src/misc/util/utilTruth.h b/src/misc/util/utilTruth.h index bc6ad0d..3d3f80b 100644 --- a/src/misc/util/utilTruth.h +++ b/src/misc/util/utilTruth.h @@ -1154,6 +1154,10 @@ static inline int Abc_Tt6HasVar( word t, int iVar ) { return ((t >> (1<<iVar)) & s_Truths6Neg[iVar]) != (t & s_Truths6Neg[iVar]); } +static inline int Abc_Tt6XorVar( word t, int iVar ) +{ + return ((t >> (1<<iVar)) & s_Truths6Neg[iVar]) == ~(t & s_Truths6Neg[iVar]); +} static inline int Abc_TtHasVar( word * t, int nVars, int iVar ) { assert( iVar < nVars ); @@ -3106,6 +3110,20 @@ static inline int Abc_Tt4Check( int t ) SeeAlso [] ***********************************************************************/ +static inline int Abc_Tt6VarsAreSymmetric( word t, int iVar, int jVar ) +{ + word * s_PMasks = s_PPMasks[iVar][jVar]; + int shift = (1 << jVar) - (1 << iVar); + assert( iVar < jVar ); + return ((t & s_PMasks[1]) << shift) == (t & s_PMasks[2]); +} +static inline int Abc_Tt6VarsAreAntiSymmetric( word t, int iVar, int jVar ) +{ + word * s_PMasks = s_PPMasks[iVar][jVar]; + int shift = (1 << jVar) + (1 << iVar); + assert( iVar < jVar ); + return ((t & (s_PMasks[1] >> (1 << iVar))) << shift) == (t & (s_PMasks[2] << (1 << iVar))); +} static inline int Abc_TtVarsAreSymmetric( word * pTruth, int nVars, int i, int j, word * pCof0, word * pCof1 ) { int nWords = Abc_TtWordNum( nVars ); @@ -3116,6 +3134,16 @@ static inline int Abc_TtVarsAreSymmetric( word * pTruth, int nVars, int i, int j Abc_TtCofactor0( pCof1, nWords, j ); return Abc_TtEqual( pCof0, pCof1, nWords ); } +static inline int Abc_TtVarsAreAntiSymmetric( word * pTruth, int nVars, int i, int j, word * pCof0, word * pCof1 ) +{ + int nWords = Abc_TtWordNum( nVars ); + assert( i < nVars && j < nVars ); + Abc_TtCofactor0p( pCof0, pTruth, nWords, i ); + Abc_TtCofactor1p( pCof1, pTruth, nWords, i ); + Abc_TtCofactor0( pCof0, nWords, j ); + Abc_TtCofactor1( pCof1, nWords, j ); + return Abc_TtEqual( pCof0, pCof1, nWords ); +} static inline int Abc_TtIsFullySymmetric( word * pTruth, int nVars ) { int m, v, Polar = 0, Seen = 0; diff --git a/src/misc/vec/vecMem.h b/src/misc/vec/vecMem.h index 72b653b..c2bd06f 100644 --- a/src/misc/vec/vecMem.h +++ b/src/misc/vec/vecMem.h @@ -341,10 +341,24 @@ static int * Vec_MemHashLookup( Vec_Mem_t * p, word * pEntry ) return pSpot; return pSpot; } +static void Vec_MemHashProfile( Vec_Mem_t * p ) +{ + int e; + for ( e = 0; e < 1000; e++ ) + { + int Count = 0; + int * pSpot = Vec_IntEntryP( p->vTable, e ); + for ( ; *pSpot != -1; pSpot = Vec_IntEntryP(p->vNexts, *pSpot) ) + Count++; + printf( "%d ", Count ); + } + printf( "\n" ); +} static void Vec_MemHashResize( Vec_Mem_t * p ) { word * pEntry; int i, * pSpot; + //Vec_MemHashProfile( p ); Vec_IntFill( p->vTable, Abc_PrimeCudd(2 * Vec_IntSize(p->vTable)), -1 ); Vec_IntClear( p->vNexts ); Vec_MemForEachEntry( p, pEntry, i ) diff --git a/src/opt/dau/dau.h b/src/opt/dau/dau.h index 260d8c7..82e9b83 100644 --- a/src/opt/dau/dau.h +++ b/src/opt/dau/dau.h @@ -60,6 +60,7 @@ typedef enum { typedef struct Dss_Man_t_ Dss_Man_t; typedef struct Abc_TtHieMan_t_ Abc_TtHieMan_t; +typedef unsigned(*TtCanonicizeFunc)(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag); //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// @@ -80,6 +81,12 @@ extern unsigned Abc_TtCanonicize( word * pTruth, int nVars, char * pCanonPe extern unsigned Abc_TtCanonicizePerm( word * pTruth, int nVars, char * pCanonPerm ); extern unsigned Abc_TtCanonicizePhase( word * pTruth, int nVars ); extern int Abc_TtCountOnesInCofsSimple( word * pTruth, int nVars, int * pStore ); +extern unsigned Abc_TtCanonicizeHie(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int fExact ); +extern Abc_TtHieMan_t * Abc_TtHieManStart( int nVars, int nLevels ); +extern void Abc_TtHieManStop(Abc_TtHieMan_t * p ); +extern unsigned Abc_TtCanonicizeWrap(TtCanonicizeFunc func, Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag); +extern unsigned Abc_TtCanonicizeAda(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int iThres); +extern unsigned Abc_TtCanonicizeHie(Abc_TtHieMan_t * p, word * pTruthInit, int nVars, char * pCanonPerm, int fExact); /*=== dauCount.c ==========================================================*/ extern int Abc_TtCountOnesInCofsQuick( word * pTruth, int nVars, int * pStore ); /*=== dauDsd.c ==========================================================*/ diff --git a/src/opt/dau/dauCanon.c b/src/opt/dau/dauCanon.c index 918c7ce..357da50 100644 --- a/src/opt/dau/dauCanon.c +++ b/src/opt/dau/dauCanon.c @@ -64,11 +64,11 @@ static inline int Abc_TtCompare1VarCofs( word * pTruth, int nWords, int iVar ) return Cof0 < Cof1 ? -1 : 1; return 0; } - if ( iVar <= 5 ) - { + if ( iVar <= 5 ) + { word Cof0, Cof1; - int w, shift = (1 << iVar); - for ( w = 0; w < nWords; w++ ) + int w, shift = (1 << iVar); + for ( w = 0; w < nWords; w++ ) { Cof0 = pTruth[w] & s_Truths6Neg[iVar]; Cof1 = (pTruth[w] >> shift) & s_Truths6Neg[iVar]; @@ -76,18 +76,18 @@ static inline int Abc_TtCompare1VarCofs( word * pTruth, int nWords, int iVar ) return Cof0 < Cof1 ? -1 : 1; } return 0; - } - // if ( iVar > 5 ) - { + } + // if ( iVar > 5 ) + { word * pLimit = pTruth + nWords; - int i, iStep = Abc_TtWordNum(iVar); + int i, iStep = Abc_TtWordNum(iVar); assert( nWords >= 2 ); - for ( ; pTruth < pLimit; pTruth += 2*iStep ) - for ( i = 0; i < iStep; i++ ) + for ( ; pTruth < pLimit; pTruth += 2*iStep ) + for ( i = 0; i < iStep; i++ ) if ( pTruth[i] != pTruth[i + iStep] ) return pTruth[i] < pTruth[i + iStep] ? -1 : 1; return 0; - } + } } static inline int Abc_TtCompare1VarCofsRev( word * pTruth, int nWords, int iVar ) { @@ -99,11 +99,11 @@ static inline int Abc_TtCompare1VarCofsRev( word * pTruth, int nWords, int iVar return Cof0 < Cof1 ? -1 : 1; return 0; } - if ( iVar <= 5 ) - { + if ( iVar <= 5 ) + { word Cof0, Cof1; - int w, shift = (1 << iVar); - for ( w = nWords - 1; w >= 0; w-- ) + int w, shift = (1 << iVar); + for ( w = nWords - 1; w >= 0; w-- ) { Cof0 = pTruth[w] & s_Truths6Neg[iVar]; Cof1 = (pTruth[w] >> shift) & s_Truths6Neg[iVar]; @@ -111,18 +111,18 @@ static inline int Abc_TtCompare1VarCofsRev( word * pTruth, int nWords, int iVar return Cof0 < Cof1 ? -1 : 1; } return 0; - } - // if ( iVar > 5 ) - { + } + // if ( iVar > 5 ) + { word * pLimit = pTruth + nWords; - int i, iStep = Abc_TtWordNum(iVar); + int i, iStep = Abc_TtWordNum(iVar); assert( nWords >= 2 ); - for ( pLimit -= 2*iStep; pLimit >= pTruth; pLimit -= 2*iStep ) - for ( i = iStep - 1; i >= 0; i-- ) + for ( pLimit -= 2*iStep; pLimit >= pTruth; pLimit -= 2*iStep ) + for ( i = iStep - 1; i >= 0; i-- ) if ( pLimit[i] != pLimit[i + iStep] ) return pLimit[i] < pLimit[i + iStep] ? -1 : 1; return 0; - } + } } */ @@ -142,35 +142,35 @@ static inline int Abc_TtCheckEqual2VarCofs( word * pTruth, int nWords, int iVar, assert( Num1 < Num2 && Num2 < 4 ); if ( nWords == 1 ) return ((pTruth[0] >> (Num2 * (1 << iVar))) & s_CMasks6[iVar]) == ((pTruth[0] >> (Num1 * (1 << iVar))) & s_CMasks6[iVar]); - if ( iVar <= 4 ) - { - int w, shift = (1 << iVar); - for ( w = 0; w < nWords; w++ ) + if ( iVar <= 4 ) + { + int w, shift = (1 << iVar); + for ( w = 0; w < nWords; w++ ) if ( ((pTruth[w] >> Num2 * shift) & s_CMasks6[iVar]) != ((pTruth[w] >> Num1 * shift) & s_CMasks6[iVar]) ) return 0; return 1; - } - if ( iVar == 5 ) - { + } + if ( iVar == 5 ) + { unsigned * pTruthU = (unsigned *)pTruth; unsigned * pLimitU = (unsigned *)(pTruth + nWords); assert( nWords >= 2 ); - for ( ; pTruthU < pLimitU; pTruthU += 4 ) + for ( ; pTruthU < pLimitU; pTruthU += 4 ) if ( pTruthU[Num2] != pTruthU[Num1] ) return 0; return 1; - } - // if ( iVar > 5 ) - { + } + // if ( iVar > 5 ) + { word * pLimit = pTruth + nWords; - int i, iStep = Abc_TtWordNum(iVar); + int i, iStep = Abc_TtWordNum(iVar); assert( nWords >= 4 ); - for ( ; pTruth < pLimit; pTruth += 4*iStep ) - for ( i = 0; i < iStep; i++ ) + for ( ; pTruth < pLimit; pTruth += 4*iStep ) + for ( i = 0; i < iStep; i++ ) if ( pTruth[i+Num2*iStep] != pTruth[i+Num1*iStep] ) return 0; return 1; - } + } } /**Function************************************************************* @@ -195,11 +195,11 @@ static inline int Abc_TtCompare2VarCofs( word * pTruth, int nWords, int iVar, in return Cof1 < Cof2 ? -1 : 1; return 0; } - if ( iVar <= 4 ) - { + if ( iVar <= 4 ) + { word Cof1, Cof2; - int w, shift = (1 << iVar); - for ( w = 0; w < nWords; w++ ) + int w, shift = (1 << iVar); + for ( w = 0; w < nWords; w++ ) { Cof1 = (pTruth[w] >> Num1 * shift) & s_CMasks6[iVar]; Cof2 = (pTruth[w] >> Num2 * shift) & s_CMasks6[iVar]; @@ -207,30 +207,30 @@ static inline int Abc_TtCompare2VarCofs( word * pTruth, int nWords, int iVar, in return Cof1 < Cof2 ? -1 : 1; } return 0; - } - if ( iVar == 5 ) - { + } + if ( iVar == 5 ) + { unsigned * pTruthU = (unsigned *)pTruth; unsigned * pLimitU = (unsigned *)(pTruth + nWords); assert( nWords >= 2 ); - for ( ; pTruthU < pLimitU; pTruthU += 4 ) + for ( ; pTruthU < pLimitU; pTruthU += 4 ) if ( pTruthU[Num1] != pTruthU[Num2] ) return pTruthU[Num1] < pTruthU[Num2] ? -1 : 1; return 0; - } - // if ( iVar > 5 ) - { + } + // if ( iVar > 5 ) + { word * pLimit = pTruth + nWords; - int i, iStep = Abc_TtWordNum(iVar); + int i, iStep = Abc_TtWordNum(iVar); int Offset1 = Num1*iStep; int Offset2 = Num2*iStep; assert( nWords >= 4 ); - for ( ; pTruth < pLimit; pTruth += 4*iStep ) - for ( i = 0; i < iStep; i++ ) + for ( ; pTruth < pLimit; pTruth += 4*iStep ) + for ( i = 0; i < iStep; i++ ) if ( pTruth[i + Offset1] != pTruth[i + Offset2] ) return pTruth[i + Offset1] < pTruth[i + Offset2] ? -1 : 1; return 0; - } + } } static inline int Abc_TtCompare2VarCofsRev( word * pTruth, int nWords, int iVar, int Num1, int Num2 ) { @@ -243,11 +243,11 @@ static inline int Abc_TtCompare2VarCofsRev( word * pTruth, int nWords, int iVar, return Cof1 < Cof2 ? -1 : 1; return 0; } - if ( iVar <= 4 ) - { + if ( iVar <= 4 ) + { word Cof1, Cof2; - int w, shift = (1 << iVar); - for ( w = nWords - 1; w >= 0; w-- ) + int w, shift = (1 << iVar); + for ( w = nWords - 1; w >= 0; w-- ) { Cof1 = (pTruth[w] >> Num1 * shift) & s_CMasks6[iVar]; Cof2 = (pTruth[w] >> Num2 * shift) & s_CMasks6[iVar]; @@ -255,30 +255,30 @@ static inline int Abc_TtCompare2VarCofsRev( word * pTruth, int nWords, int iVar, return Cof1 < Cof2 ? -1 : 1; } return 0; - } - if ( iVar == 5 ) - { + } + if ( iVar == 5 ) + { unsigned * pTruthU = (unsigned *)pTruth; unsigned * pLimitU = (unsigned *)(pTruth + nWords); assert( nWords >= 2 ); - for ( pLimitU -= 4; pLimitU >= pTruthU; pLimitU -= 4 ) + for ( pLimitU -= 4; pLimitU >= pTruthU; pLimitU -= 4 ) if ( pLimitU[Num1] != pLimitU[Num2] ) return pLimitU[Num1] < pLimitU[Num2] ? -1 : 1; return 0; - } - // if ( iVar > 5 ) - { + } + // if ( iVar > 5 ) + { word * pLimit = pTruth + nWords; - int i, iStep = Abc_TtWordNum(iVar); + int i, iStep = Abc_TtWordNum(iVar); int Offset1 = Num1*iStep; int Offset2 = Num2*iStep; assert( nWords >= 4 ); - for ( pLimit -= 4*iStep; pLimit >= pTruth; pLimit -= 4*iStep ) - for ( i = iStep - 1; i >= 0; i-- ) + for ( pLimit -= 4*iStep; pLimit >= pTruth; pLimit -= 4*iStep ) + for ( i = iStep - 1; i >= 0; i-- ) if ( pLimit[i + Offset1] != pLimit[i + Offset2] ) return pLimit[i + Offset1] < pLimit[i + Offset2] ? -1 : 1; return 0; - } + } } /**Function************************************************************* @@ -292,13 +292,24 @@ static inline int Abc_TtCompare2VarCofsRev( word * pTruth, int nWords, int iVar, SeeAlso [] ***********************************************************************/ -#define DO_SMALL_TRUTHTABLE 0 +void Abc_TtNormalizeSmallTruth(word * pTruth, int nVars) +{ + if (nVars < 6) { + int shift, bits = (1 << nVars); + word base = *pTruth = *pTruth & ((((word)1) << bits) - 1); + for (shift = bits; shift < 64; shift += bits) + *pTruth |= base << shift; + } +} -static inline void Abc_TtNormalizeSmallTruth(word * pTruth, int nVars) +inline void Abc_TtVerifySmallTruth(word * pTruth, int nVars) { -#if DO_SMALL_TRUTHTABLE - if (nVars < 6) - *pTruth &= (1ULL << (1 << nVars)) - 1; +#ifndef NDEBUG + if (nVars < 6) { + word nTruth = *pTruth; + Abc_TtNormalizeSmallTruth(&nTruth, nVars); + assert(*pTruth == nTruth); + } #endif } @@ -306,7 +317,7 @@ static inline int Abc_TtCountOnesInTruth( word * pTruth, int nVars ) { int nWords = Abc_TtWordNum( nVars ); int k, Counter = 0; - Abc_TtNormalizeSmallTruth(pTruth, nVars); + Abc_TtVerifySmallTruth(pTruth, nVars); for ( k = 0; k < nWords; k++ ) if ( pTruth[k] ) Counter += Abc_TtCountOnes( pTruth[k] ); @@ -318,7 +329,7 @@ static inline void Abc_TtCountOnesInCofs( word * pTruth, int nVars, int * pStore int i, k, Counter, nWords; if ( nVars <= 6 ) { - Abc_TtNormalizeSmallTruth(pTruth, nVars); + Abc_TtVerifySmallTruth(pTruth, nVars); for ( i = 0; i < nVars; i++ ) pStore[i] = Abc_TtCountOnes( pTruth[0] & s_Truths6Neg[i] ); return; @@ -1154,83 +1165,92 @@ unsigned Abc_TtCanonicizePhase( word * pTruth, int nVars ) struct Abc_TtHieMan_t_ { - int nLastLevel, nWords; - Vec_Mem_t * vTtMem[TT_MAX_LEVELS]; // truth table memory and hash tables - Vec_Int_t * vRepres[TT_MAX_LEVELS]; // pointers to the representatives from the last hierarchical level - int vTruthId[TT_MAX_LEVELS]; + int nLastLevel, nWords; + Vec_Mem_t * vTtMem[TT_MAX_LEVELS]; // truth table memory and hash tables + Vec_Int_t * vRepres[TT_MAX_LEVELS]; // pointers to the representatives from the last hierarchical level + int vTruthId[TT_MAX_LEVELS]; }; Abc_TtHieMan_t * Abc_TtHieManStart(int nVars, int nLevels) { - Abc_TtHieMan_t * p = NULL; - int i; - if (nLevels > TT_MAX_LEVELS) return p; - p = ABC_CALLOC(Abc_TtHieMan_t, 1); - p->nLastLevel = nLevels - 1; - p->nWords = Abc_TtWordNum(nVars); - for (i = 0; i < nLevels; i++) - { - p->vTtMem[i] = Vec_MemAlloc(p->nWords, 12); - Vec_MemHashAlloc(p->vTtMem[i], 10000); - p->vRepres[i] = Vec_IntAlloc(1); - } - return p; + Abc_TtHieMan_t * p = NULL; + int i; + if (nLevels > TT_MAX_LEVELS) return p; + p = ABC_CALLOC(Abc_TtHieMan_t, 1); + p->nLastLevel = nLevels - 1; + p->nWords = Abc_TtWordNum(nVars); + for (i = 0; i < nLevels; i++) + { + p->vTtMem[i] = Vec_MemAlloc(p->nWords, 12); + Vec_MemHashAlloc(p->vTtMem[i], 10000); + p->vRepres[i] = Vec_IntAlloc(1); + } + return p; } void Abc_TtHieManStop(Abc_TtHieMan_t * p) { - int i; - for (i = 0; i <= p->nLastLevel; i++) - { - Vec_MemHashFree(p->vTtMem[i]); - Vec_MemFreeP(&p->vTtMem[i]); - Vec_IntFree(p->vRepres[i]); - } - ABC_FREE(p); + int i; + for (i = 0; i <= p->nLastLevel; i++) + { + Vec_MemHashFree(p->vTtMem[i]); + Vec_MemFreeP(&p->vTtMem[i]); + Vec_IntFree(p->vRepres[i]); + } + ABC_FREE(p); } int Abc_TtHieRetrieveOrInsert(Abc_TtHieMan_t * p, int level, word * pTruth, word * pResult) { - int i, iSpot, truthId; - word * pRepTruth; - if (level < 0) level += p->nLastLevel + 1; - if (level < 0 || level > p->nLastLevel) return -1; - iSpot = *Vec_MemHashLookup(p->vTtMem[level], pTruth); - if (iSpot == -1) { - p->vTruthId[level] = Vec_MemHashInsert(p->vTtMem[level], pTruth); - if (level < p->nLastLevel) return 0; - iSpot = p->vTruthId[level]; - } - // return the class representative - if (level < p->nLastLevel) - truthId = Vec_IntEntry(p->vRepres[level], iSpot); - else - truthId = iSpot; - for (i = 0; i < level; i++) - Vec_IntSetEntry(p->vRepres[i], p->vTruthId[i], truthId); - - pRepTruth = Vec_MemReadEntry(p->vTtMem[p->nLastLevel], truthId); - if (level < p->nLastLevel) { - Abc_TtCopy(pResult, pRepTruth, p->nWords, 0); - return 1; - } - assert(Abc_TtEqual(pTruth, pRepTruth, p->nWords)); - if (pTruth != pResult) - Abc_TtCopy(pResult, pRepTruth, p->nWords, 0); - return 0; + int i, iSpot, truthId; + word * pRepTruth; + if (!p) return -1; + if (level < 0) level += p->nLastLevel + 1; + if (level < 0 || level > p->nLastLevel) return -1; + iSpot = *Vec_MemHashLookup(p->vTtMem[level], pTruth); + if (iSpot == -1) { + p->vTruthId[level] = Vec_MemHashInsert(p->vTtMem[level], pTruth); + if (level < p->nLastLevel) return 0; + iSpot = p->vTruthId[level]; + } + // return the class representative + if (level < p->nLastLevel) + truthId = Vec_IntEntry(p->vRepres[level], iSpot); + else + truthId = iSpot; + for (i = 0; i < level; i++) + Vec_IntSetEntry(p->vRepres[i], p->vTruthId[i], truthId); + + pRepTruth = Vec_MemReadEntry(p->vTtMem[p->nLastLevel], truthId); + if (level < p->nLastLevel) { + Abc_TtCopy(pResult, pRepTruth, p->nWords, 0); + return 1; + } + assert(Abc_TtEqual(pTruth, pRepTruth, p->nWords)); + if (pTruth != pResult) + Abc_TtCopy(pResult, pRepTruth, p->nWords, 0); + return 0; } unsigned Abc_TtCanonicizeHie( Abc_TtHieMan_t * p, word * pTruthInit, int nVars, char * pCanonPerm, int fExact ) { int fNaive = 1; int pStore[17]; - static word pTruth[1024]; + //static word pTruth[1024]; + word * pTruth = pTruthInit; unsigned uCanonPhase = 0; int nOnes, nWords = Abc_TtWordNum( nVars ); int i, k; assert( nVars <= 16 ); - Abc_TtCopy( pTruth, pTruthInit, nWords, 0 ); + // handle constant + if ( nVars == 0 ) + { + Abc_TtClear( pTruthInit, nWords ); + return 0; + } + + //Abc_TtCopy( pTruth, pTruthInit, nWords, 0 ); for ( i = 0; i < nVars; i++ ) pCanonPerm[i] = i; @@ -1258,7 +1278,7 @@ unsigned Abc_TtCanonicizeHie( Abc_TtHieMan_t * p, word * pTruthInit, int nVars, pStore[i] = nOnes - pStore[i]; } // check cache - if (Abc_TtHieRetrieveOrInsert(p, 1, pTruth, pTruthInit) > 0) return 0; + if (Abc_TtHieRetrieveOrInsert(p, 1, pTruth, pTruthInit) > 0) return 0; // normalize permutation { @@ -1282,7 +1302,7 @@ unsigned Abc_TtCanonicizeHie( Abc_TtHieMan_t * p, word * pTruthInit, int nVars, } } // check cache - if (Abc_TtHieRetrieveOrInsert(p, 2, pTruth, pTruthInit) > 0) return 0; + if (Abc_TtHieRetrieveOrInsert(p, 2, pTruth, pTruthInit) > 0) return 0; // iterate TT permutations for tied variables for ( k = 0; k < 5; k++ ) @@ -1301,7 +1321,7 @@ unsigned Abc_TtCanonicizeHie( Abc_TtHieMan_t * p, word * pTruthInit, int nVars, break; } // check cache - if (Abc_TtHieRetrieveOrInsert(p, 3, pTruth, pTruthInit) > 0) return 0; + if (Abc_TtHieRetrieveOrInsert(p, 3, pTruth, pTruthInit) > 0) return 0; // perform exact NPN using groups if ( fExact ) { @@ -1343,7 +1363,7 @@ unsigned Abc_TtCanonicizeHie( Abc_TtHieMan_t * p, word * pTruthInit, int nVars, } } // update cache - Abc_TtHieRetrieveOrInsert(p, 4, pTruth, pTruthInit); + Abc_TtHieRetrieveOrInsert(p, 4, pTruth, pTruthInit); return 0; } @@ -1362,26 +1382,26 @@ SeeAlso [] typedef struct TiedGroup_ { - char iStart; // index of Abc_TgMan_t::pPerm - char nGVars; // the number of variables in the group - char fPhased; // if the phases of the variables are determined + char iStart; // index of Abc_TgMan_t::pPerm + char nGVars; // the number of variables in the group + char fPhased; // if the phases of the variables are determined } TiedGroup; typedef struct Abc_TgMan_t_ { - word *pTruth; - int nVars; // the number of variables - int nGVars; // the number of variables in groups ( symmetric variables purged ) - int nGroups; // the number of tied groups - unsigned uPhase; // phase of each variable and the function - char pPerm[16]; // permutation of variables, symmetric variables purged, for grouping - char pPermT[16]; // permutation of variables, symmetric variables expanded, actual transformation for pTruth - char pPermTRev[16]; // reverse permutation of pPermT - signed char pPermDir[16]; // for generating the next permutation - TiedGroup pGroup[16]; // tied groups - // symemtric group attributes - char symPhase[16]; // phase type of symemtric groups - signed char symLink[17]; // singly linked list, indicate the variables in symemtric groups + word *pTruth; + int nVars; // the number of variables + int nGVars; // the number of variables in groups ( symmetric variables purged ) + int nGroups; // the number of tied groups + unsigned uPhase; // phase of each variable and the function + char pPerm[16]; // permutation of variables, symmetric variables purged, for grouping + char pPermT[16]; // permutation of variables, symmetric variables expanded, actual transformation for pTruth + char pPermTRev[16]; // reverse permutation of pPermT + signed char pPermDir[16]; // for generating the next permutation + TiedGroup pGroup[16]; // tied groups + // symemtric group attributes + char symPhase[16]; // phase type of symemtric groups + signed char symLink[17]; // singly linked list, indicate the variables in symemtric groups } Abc_TgMan_t; #if !defined(NDEBUG) && !defined(CANON_VERIFY) @@ -1402,59 +1422,58 @@ SeeAlso [] // Johnson¨CTrotter algorithm static int Abc_NextPermSwapC(char * pData, signed char * pDir, int size) { - int i, j, k = -1; - for (i = 0; i < size; i++) - { - j = i + pDir[i]; - if (j >= 0 && j < size && pData[i] > pData[j] && (k < 0 || pData[i] > pData[k])) - k = i; - } - if (k < 0) k = 0; - - for (i = 0; i < size; i++) - if (pData[i] > pData[k]) - pDir[i] = -pDir[i]; - - j = k + pDir[k]; - return j < k ? j : k; + int i, j, k = -1; + for (i = 0; i < size; i++) + { + j = i + pDir[i]; + if (j >= 0 && j < size && pData[i] > pData[j] && (k < 0 || pData[i] > pData[k])) + k = i; + } + if (k < 0) k = 0; + + for (i = 0; i < size; i++) + if (pData[i] > pData[k]) + pDir[i] = -pDir[i]; + + j = k + pDir[k]; + return j < k ? j : k; } -typedef unsigned(*TtCanonicizeFunc)(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag); unsigned Abc_TtCanonicizeWrap(TtCanonicizeFunc func, Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag) { - int nWords = Abc_TtWordNum(nVars); - unsigned uCanonPhase1, uCanonPhase2; - char pCanonPerm2[16]; - static word pTruth2[1024]; - - if (Abc_TtCountOnesInTruth(pTruth, nVars) != (1 << (nVars - 1))) - return func(p, pTruth, nVars, pCanonPerm, flag); - Abc_TtCopy(pTruth2, pTruth, nWords, 1); - Abc_TtNormalizeSmallTruth(pTruth2, nVars); - uCanonPhase1 = func(p, pTruth, nVars, pCanonPerm, flag); - uCanonPhase2 = func(p, pTruth2, nVars, pCanonPerm2, flag); - if (Abc_TtCompareRev(pTruth, pTruth2, nWords) <= 0) - return uCanonPhase1; - Abc_TtCopy(pTruth, pTruth2, nWords, 0); - memcpy(pCanonPerm, pCanonPerm2, nVars); - return uCanonPhase2; + int nWords = Abc_TtWordNum(nVars); + unsigned uCanonPhase1, uCanonPhase2; + char pCanonPerm2[16]; + static word pTruth2[1024]; + + Abc_TtNormalizeSmallTruth(pTruth, nVars); + if (Abc_TtCountOnesInTruth(pTruth, nVars) != nWords * 32) + return func(p, pTruth, nVars, pCanonPerm, flag); + Abc_TtCopy(pTruth2, pTruth, nWords, 1); + uCanonPhase1 = func(p, pTruth, nVars, pCanonPerm, flag); + uCanonPhase2 = func(p, pTruth2, nVars, pCanonPerm2, flag); + if (Abc_TtCompareRev(pTruth, pTruth2, nWords) <= 0) + return uCanonPhase1; + Abc_TtCopy(pTruth, pTruth2, nWords, 0); + memcpy(pCanonPerm, pCanonPerm2, nVars); + return uCanonPhase2; } word gpVerCopy[1024]; static int Abc_TtCannonVerify(word* pTruth, int nVars, char * pCanonPerm, unsigned uCanonPhase) { #ifdef CANON_VERIFY - int nWords = Abc_TtWordNum(nVars); - char pCanonPermCopy[16]; - static word pCopy2[1024]; - Abc_TtCopy(pCopy2, pTruth, nWords, 0); - memcpy(pCanonPermCopy, pCanonPerm, sizeof(char) * nVars); - Abc_TtImplementNpnConfig(pCopy2, nVars, pCanonPermCopy, uCanonPhase); - Abc_TtNormalizeSmallTruth(pCopy2, nVars); - return Abc_TtEqual(gpVerCopy, pCopy2, nWords); + int nWords = Abc_TtWordNum(nVars); + char pCanonPermCopy[16]; + static word pCopy2[1024]; + Abc_TtVerifySmallTruth(pTruth, nVars); + Abc_TtCopy(pCopy2, pTruth, nWords, 0); + memcpy(pCanonPermCopy, pCanonPerm, sizeof(char) * nVars); + Abc_TtImplementNpnConfig(pCopy2, nVars, pCanonPermCopy, uCanonPhase); + return Abc_TtEqual(gpVerCopy, pCopy2, nWords); #else - return 1; + return 1; #endif } @@ -1472,44 +1491,44 @@ SeeAlso [] static void Abc_TginitMan(Abc_TgMan_t * pMan, word * pTruth, int nVars) { - int i; - pMan->pTruth = pTruth; - pMan->nVars = pMan->nGVars = nVars; - pMan->uPhase = 0; - for (i = 0; i < nVars; i++) - { - pMan->pPerm[i] = i; - pMan->pPermT[i] = i; - pMan->pPermTRev[i] = i; - pMan->symPhase[i] = 1; - } + int i; + pMan->pTruth = pTruth; + pMan->nVars = pMan->nGVars = nVars; + pMan->uPhase = 0; + for (i = 0; i < nVars; i++) + { + pMan->pPerm[i] = i; + pMan->pPermT[i] = i; + pMan->pPermTRev[i] = i; + pMan->symPhase[i] = 1; + } } static inline void Abc_TgManCopy(Abc_TgMan_t* pDst, word* pDstTruth, Abc_TgMan_t* pSrc) { - *pDst = *pSrc; - Abc_TtCopy(pDstTruth, pSrc->pTruth, Abc_TtWordNum(pSrc->nVars), 0); - pDst->pTruth = pDstTruth; + *pDst = *pSrc; + Abc_TtCopy(pDstTruth, pSrc->pTruth, Abc_TtWordNum(pSrc->nVars), 0); + pDst->pTruth = pDstTruth; } static inline int Abc_TgCannonVerify(Abc_TgMan_t* pMan) { - return Abc_TtCannonVerify(pMan->pTruth, pMan->nVars, pMan->pPermT, pMan->uPhase); + return Abc_TtCannonVerify(pMan->pTruth, pMan->nVars, pMan->pPermT, pMan->uPhase); } void Abc_TgExpendSymmetry(Abc_TgMan_t * pMan, char * pPerm, char * pDest); static void CheckConfig(Abc_TgMan_t * pMan) { #ifndef NDEBUG - int i; - char pPermE[16]; - Abc_TgExpendSymmetry(pMan, pMan->pPerm, pPermE); - for (i = 0; i < pMan->nVars; i++) - { - assert(pPermE[i] == pMan->pPermT[i]); - assert(pMan->pPermTRev[(int)pMan->pPermT[i]] == i); - } - assert(Abc_TgCannonVerify(pMan)); + int i; + char pPermE[16]; + Abc_TgExpendSymmetry(pMan, pMan->pPerm, pPermE); + for (i = 0; i < pMan->nVars; i++) + { + assert(pPermE[i] == pMan->pPermT[i]); + assert(pMan->pPermTRev[(int)pMan->pPermT[i]] == i); + } + assert(Abc_TgCannonVerify(pMan)); #endif } @@ -1527,84 +1546,84 @@ SeeAlso [] static inline void Abc_TgFlipVar(Abc_TgMan_t* pMan, int iVar) { - int nWords = Abc_TtWordNum(pMan->nVars); - int ivp = pMan->pPermTRev[iVar]; - Abc_TtFlip(pMan->pTruth, nWords, ivp); - pMan->uPhase ^= 1 << ivp; + int nWords = Abc_TtWordNum(pMan->nVars); + int ivp = pMan->pPermTRev[iVar]; + Abc_TtFlip(pMan->pTruth, nWords, ivp); + pMan->uPhase ^= 1 << ivp; } static inline void Abc_TgFlipSymGroupByVar(Abc_TgMan_t* pMan, int iVar) { - for (; iVar >= 0; iVar = pMan->symLink[iVar]) - if (pMan->symPhase[iVar]) - Abc_TgFlipVar(pMan, iVar); + for (; iVar >= 0; iVar = pMan->symLink[iVar]) + if (pMan->symPhase[iVar]) + Abc_TgFlipVar(pMan, iVar); } static inline void Abc_TgFlipSymGroup(Abc_TgMan_t* pMan, int idx) { - Abc_TgFlipSymGroupByVar(pMan, pMan->pPerm[idx]); + Abc_TgFlipSymGroupByVar(pMan, pMan->pPerm[idx]); } static inline void Abc_TgClearSymGroupPhase(Abc_TgMan_t* pMan, int iVar) { - for (; iVar >= 0; iVar = pMan->symLink[iVar]) - pMan->symPhase[iVar] = 0; + for (; iVar >= 0; iVar = pMan->symLink[iVar]) + pMan->symPhase[iVar] = 0; } static void Abc_TgImplementPerm(Abc_TgMan_t* pMan, const char *pPermDest) { - int i, nVars = pMan->nVars; - char *pPerm = pMan->pPermT; - char *pRev = pMan->pPermTRev; - unsigned uPhase = pMan->uPhase & (1 << nVars); - - for (i = 0; i < nVars; i++) - pRev[(int)pPerm[i]] = i; - for (i = 0; i < nVars; i++) - pPerm[i] = pRev[(int)pPermDest[i]]; - for (i = 0; i < nVars; i++) - pRev[(int)pPerm[i]] = i; - - Abc_TtImplementNpnConfig(pMan->pTruth, nVars, pRev, 0); - Abc_TtNormalizeSmallTruth(pMan->pTruth, nVars); - - for (i = 0; i < nVars; i++) - { - if (pMan->uPhase & (1 << pPerm[i])) - uPhase |= (1 << i); - pPerm[i] = pPermDest[i]; - pRev[(int)pPerm[i]] = i; - } - pMan->uPhase = uPhase; + int i, nVars = pMan->nVars; + char *pPerm = pMan->pPermT; + char *pRev = pMan->pPermTRev; + unsigned uPhase = pMan->uPhase & (1 << nVars); + + for (i = 0; i < nVars; i++) + pRev[(int)pPerm[i]] = i; + for (i = 0; i < nVars; i++) + pPerm[i] = pRev[(int)pPermDest[i]]; + for (i = 0; i < nVars; i++) + pRev[(int)pPerm[i]] = i; + + Abc_TtImplementNpnConfig(pMan->pTruth, nVars, pRev, 0); +// Abc_TtVerifySmallTruth(pMan->pTruth, nVars); + + for (i = 0; i < nVars; i++) + { + if (pMan->uPhase & (1 << pPerm[i])) + uPhase |= (1 << i); + pPerm[i] = pPermDest[i]; + pRev[(int)pPerm[i]] = i; + } + pMan->uPhase = uPhase; } static void Abc_TgSwapAdjacentSymGroups(Abc_TgMan_t* pMan, int idx) { - int iVar, jVar, ix; - char pPermNew[16]; - assert(idx < pMan->nGVars - 1); - iVar = pMan->pPerm[idx]; - jVar = pMan->pPerm[idx + 1]; - pMan->pPerm[idx] = jVar; - pMan->pPerm[idx + 1] = iVar; - ABC_SWAP(char, pMan->pPermDir[idx], pMan->pPermDir[idx + 1]); - if (pMan->symLink[iVar] >= 0 || pMan->symLink[jVar] >= 0) - { - Abc_TgExpendSymmetry(pMan, pMan->pPerm, pPermNew); - Abc_TgImplementPerm(pMan, pPermNew); - return; - } - // plain variable swap - ix = pMan->pPermTRev[iVar]; - assert(pMan->pPermT[ix] == iVar && pMan->pPermT[ix + 1] == jVar); - Abc_TtSwapAdjacent(pMan->pTruth, Abc_TtWordNum(pMan->nVars), ix); - pMan->pPermT[ix] = jVar; - pMan->pPermT[ix + 1] = iVar; - pMan->pPermTRev[iVar] = ix + 1; - pMan->pPermTRev[jVar] = ix; - if (((pMan->uPhase >> ix) & 1) != ((pMan->uPhase >> (ix + 1)) & 1)) - pMan->uPhase ^= 1 << ix | 1 << (ix + 1); - assert(Abc_TgCannonVerify(pMan)); + int iVar, jVar, ix; + char pPermNew[16]; + assert(idx < pMan->nGVars - 1); + iVar = pMan->pPerm[idx]; + jVar = pMan->pPerm[idx + 1]; + pMan->pPerm[idx] = jVar; + pMan->pPerm[idx + 1] = iVar; + ABC_SWAP(char, pMan->pPermDir[idx], pMan->pPermDir[idx + 1]); + if (pMan->symLink[iVar] >= 0 || pMan->symLink[jVar] >= 0) + { + Abc_TgExpendSymmetry(pMan, pMan->pPerm, pPermNew); + Abc_TgImplementPerm(pMan, pPermNew); + return; + } + // plain variable swap + ix = pMan->pPermTRev[iVar]; + assert(pMan->pPermT[ix] == iVar && pMan->pPermT[ix + 1] == jVar); + Abc_TtSwapAdjacent(pMan->pTruth, Abc_TtWordNum(pMan->nVars), ix); + pMan->pPermT[ix] = jVar; + pMan->pPermT[ix + 1] = iVar; + pMan->pPermTRev[iVar] = ix + 1; + pMan->pPermTRev[jVar] = ix; + if (((pMan->uPhase >> ix) & 1) != ((pMan->uPhase >> (ix + 1)) & 1)) + pMan->uPhase ^= 1 << ix | 1 << (ix + 1); + assert(Abc_TgCannonVerify(pMan)); } /**Function************************************************************* @@ -1623,33 +1642,33 @@ static word pSymCopy[1024]; static int Abc_TtIsSymmetric(word * pTruth, int nVars, int iVar, int jVar, int fPhase) { - int rv; - int nWords = Abc_TtWordNum(nVars); - Abc_TtCopy(pSymCopy, pTruth, nWords, 0); - Abc_TtSwapVars(pSymCopy, nVars, iVar, jVar); - rv = Abc_TtEqual(pTruth, pSymCopy, nWords) * 2; - if (!fPhase) return rv; - Abc_TtFlip(pSymCopy, nWords, iVar); - Abc_TtFlip(pSymCopy, nWords, jVar); - return rv + Abc_TtEqual(pTruth, pSymCopy, nWords); + int rv; + int nWords = Abc_TtWordNum(nVars); + Abc_TtCopy(pSymCopy, pTruth, nWords, 0); + Abc_TtSwapVars(pSymCopy, nVars, iVar, jVar); + rv = Abc_TtEqual(pTruth, pSymCopy, nWords) * 2; + if (!fPhase) return rv; + Abc_TtFlip(pSymCopy, nWords, iVar); + Abc_TtFlip(pSymCopy, nWords, jVar); + return rv + Abc_TtEqual(pTruth, pSymCopy, nWords); } static int Abc_TtIsSymmetricHigh(Abc_TgMan_t * pMan, int iVar, int jVar, int fPhase) { - int rv, iv, jv, n; - int nWords = Abc_TtWordNum(pMan->nVars); - Abc_TtCopy(pSymCopy, pMan->pTruth, nWords, 0); - for (n = 0, iv = iVar, jv = jVar; iv >= 0 && jv >= 0; iv = pMan->symLink[iv], jv = pMan->symLink[jv], n++) - Abc_TtSwapVars(pSymCopy, pMan->nVars, iv, jv); - assert(iv < 0 && jv < 0); // two symmetric groups must have the same size - rv = Abc_TtEqual(pMan->pTruth, pSymCopy, nWords) * 2; - if (!fPhase) return rv; - for (iv = iVar, jv = jVar; iv >= 0 && jv >= 0; iv = pMan->symLink[iv], jv = pMan->symLink[jv]) - { - if (pMan->symPhase[iv]) Abc_TtFlip(pSymCopy, nWords, iv); - if (pMan->symPhase[jv]) Abc_TtFlip(pSymCopy, nWords, jv); - } - return rv + Abc_TtEqual(pMan->pTruth, pSymCopy, nWords); + int rv, iv, jv, n; + int nWords = Abc_TtWordNum(pMan->nVars); + Abc_TtCopy(pSymCopy, pMan->pTruth, nWords, 0); + for (n = 0, iv = iVar, jv = jVar; iv >= 0 && jv >= 0; iv = pMan->symLink[iv], jv = pMan->symLink[jv], n++) + Abc_TtSwapVars(pSymCopy, pMan->nVars, iv, jv); + assert(iv < 0 && jv < 0); // two symmetric groups must have the same size + rv = Abc_TtEqual(pMan->pTruth, pSymCopy, nWords) * 2; + if (!fPhase) return rv; + for (iv = iVar, jv = jVar; iv >= 0 && jv >= 0; iv = pMan->symLink[iv], jv = pMan->symLink[jv]) + { + if (pMan->symPhase[iv]) Abc_TtFlip(pSymCopy, nWords, iv); + if (pMan->symPhase[jv]) Abc_TtFlip(pSymCopy, nWords, jv); + } + return rv + Abc_TtEqual(pMan->pTruth, pSymCopy, nWords); } /**Function************************************************************* @@ -1658,7 +1677,7 @@ Synopsis [Create groups by cofactor signatures] Description [Similar to Abc_TtSemiCanonicize. Use stable insertion sort to keep the order of the variables in the groups. - Defer permutation. ] + Defer permutation. ] SideEffects [] @@ -1668,53 +1687,53 @@ SeeAlso [] static void Abc_TgCreateGroups(Abc_TgMan_t * pMan) { - int pStore[17]; - int i, j, nOnes; - int nVars = pMan->nVars, nWords = Abc_TtWordNum(nVars); - TiedGroup * pGrp = pMan->pGroup; - assert(nVars <= 16); - // normalize polarity - nOnes = Abc_TtCountOnesInTruth(pMan->pTruth, nVars); - if (nOnes > (1 << (nVars - 1))) - { - Abc_TtNot(pMan->pTruth, nWords); - nOnes = (1 << nVars) - nOnes; - pMan->uPhase |= (1 << nVars); - } - // normalize phase - Abc_TtCountOnesInCofs(pMan->pTruth, nVars, pStore); - pStore[nVars] = nOnes; - for (i = 0; i < nVars; i++) - { - if (pStore[i] >= nOnes - pStore[i]) - continue; - Abc_TtFlip(pMan->pTruth, nWords, i); - pMan->uPhase |= (1 << i); - pStore[i] = nOnes - pStore[i]; - } - - // sort variables - for (i = 1; i < nVars; i++) - { - int a = pStore[i]; char aa = pMan->pPerm[i]; - for (j = i; j > 0 && pStore[j - 1] > a; j--) - pStore[j] = pStore[j - 1], pMan->pPerm[j] = pMan->pPerm[j - 1]; - pStore[j] = a; pMan->pPerm[j] = aa; - } - // group variables -// Abc_SortIdxC(pStore, pMan->pPerm, nVars); - pGrp[0].iStart = 0; - pGrp[0].fPhased = pStore[0] * 2 != nOnes; - for (i = j = 1; i < nVars; i++) - { - if (pStore[i] == pStore[i - 1]) continue; - pGrp[j].iStart = i; - pGrp[j].fPhased = pStore[i] * 2 != nOnes; - pGrp[j - 1].nGVars = i - pGrp[j - 1].iStart; - j++; - } - pGrp[j - 1].nGVars = i - pGrp[j - 1].iStart; - pMan->nGroups = j; + int pStore[17]; + int i, j, nOnes; + int nVars = pMan->nVars, nWords = Abc_TtWordNum(nVars); + TiedGroup * pGrp = pMan->pGroup; + assert(nVars <= 16); + // normalize polarity + nOnes = Abc_TtCountOnesInTruth(pMan->pTruth, nVars); + if (nOnes > nWords * 32) + { + Abc_TtNot(pMan->pTruth, nWords); + nOnes = nWords * 64 - nOnes; + pMan->uPhase |= (1 << nVars); + } + // normalize phase + Abc_TtCountOnesInCofs(pMan->pTruth, nVars, pStore); + pStore[nVars] = nOnes; + for (i = 0; i < nVars; i++) + { + if (pStore[i] >= nOnes - pStore[i]) + continue; + Abc_TtFlip(pMan->pTruth, nWords, i); + pMan->uPhase |= (1 << i); + pStore[i] = nOnes - pStore[i]; + } + + // sort variables + for (i = 1; i < nVars; i++) + { + int a = pStore[i]; char aa = pMan->pPerm[i]; + for (j = i; j > 0 && pStore[j - 1] > a; j--) + pStore[j] = pStore[j - 1], pMan->pPerm[j] = pMan->pPerm[j - 1]; + pStore[j] = a; pMan->pPerm[j] = aa; + } + // group variables +// Abc_SortIdxC(pStore, pMan->pPerm, nVars); + pGrp[0].iStart = 0; + pGrp[0].fPhased = pStore[0] * 2 != nOnes; + for (i = j = 1; i < nVars; i++) + { + if (pStore[i] == pStore[i - 1]) continue; + pGrp[j].iStart = i; + pGrp[j].fPhased = pStore[i] * 2 != nOnes; + pGrp[j - 1].nGVars = i - pGrp[j - 1].iStart; + j++; + } + pGrp[j - 1].nGVars = i - pGrp[j - 1].iStart; + pMan->nGroups = j; } /**Function************************************************************* @@ -1731,135 +1750,135 @@ SeeAlso [] static int Abc_TgGroupSymmetry(Abc_TgMan_t * pMan, TiedGroup * pGrp, int doHigh) { - int i, j, iVar, jVar, nsym = 0; - int fDone[16], scnt[16], stype[16]; - signed char *symLink = pMan->symLink; -// char * symPhase = pMan->symPhase; - int nGVars = pGrp->nGVars; - char * pVars = pMan->pPerm + pGrp->iStart; - int modified; - - for (i = 0; i < nGVars; i++) - fDone[i] = 0, scnt[i] = 1; - - do { - modified = 0; - for (i = 0; i < nGVars - 1; i++) - { - iVar = pVars[i]; - if (iVar < 0 || fDone[i]) continue; -// if (!pGrp->fPhased && !Abc_TtHasVar(pMan->pTruth, pMan->nVars, iVar)) continue; - // Mark symmetric variables/groups - for (j = i + 1; j < nGVars; j++) - { - jVar = pVars[j]; - if (jVar < 0 || scnt[j] != scnt[i]) // || pMan->symPhase[jVar] != pMan->symPhase[iVar]) - stype[j] = 0; - else if (scnt[j] == 1) - stype[j] = Abc_TtIsSymmetric(pMan->pTruth, pMan->nVars, iVar, jVar, !pGrp->fPhased); - else - stype[j] = Abc_TtIsSymmetricHigh(pMan, iVar, jVar, !pGrp->fPhased); - } - fDone[i] = 1; - // Merge symmetric groups - for (j = i + 1; j < nGVars; j++) - { - int ii; - jVar = pVars[j]; - switch (stype[j]) - { - case 1: // E-Symmetry - Abc_TgFlipSymGroupByVar(pMan, jVar); - // fallthrough - case 2: // NE-Symmetry - pMan->symPhase[iVar] += pMan->symPhase[jVar]; - break; - case 3: // multiform Symmetry - Abc_TgClearSymGroupPhase(pMan, jVar); - break; - default: // case 0: No Symmetry - continue; - } - - for (ii = iVar; symLink[ii] >= 0; ii = symLink[ii]) - ; - symLink[ii] = jVar; - pVars[j] = -1; - scnt[i] += scnt[j]; - modified = 1; - fDone[i] = 0; - nsym++; - } - } -// if (++order > 3) printf("%d", order); - } while (doHigh && modified); - - return nsym; + int i, j, iVar, jVar, nsym = 0; + int fDone[16], scnt[16], stype[16]; + signed char *symLink = pMan->symLink; +// char * symPhase = pMan->symPhase; + int nGVars = pGrp->nGVars; + char * pVars = pMan->pPerm + pGrp->iStart; + int modified; + + for (i = 0; i < nGVars; i++) + fDone[i] = 0, scnt[i] = 1; + + do { + modified = 0; + for (i = 0; i < nGVars - 1; i++) + { + iVar = pVars[i]; + if (iVar < 0 || fDone[i]) continue; +// if (!pGrp->fPhased && !Abc_TtHasVar(pMan->pTruth, pMan->nVars, iVar)) continue; + // Mark symmetric variables/groups + for (j = i + 1; j < nGVars; j++) + { + jVar = pVars[j]; + if (jVar < 0 || scnt[j] != scnt[i]) // || pMan->symPhase[jVar] != pMan->symPhase[iVar]) + stype[j] = 0; + else if (scnt[j] == 1) + stype[j] = Abc_TtIsSymmetric(pMan->pTruth, pMan->nVars, iVar, jVar, !pGrp->fPhased); + else + stype[j] = Abc_TtIsSymmetricHigh(pMan, iVar, jVar, !pGrp->fPhased); + } + fDone[i] = 1; + // Merge symmetric groups + for (j = i + 1; j < nGVars; j++) + { + int ii; + jVar = pVars[j]; + switch (stype[j]) + { + case 1: // E-Symmetry + Abc_TgFlipSymGroupByVar(pMan, jVar); + // fallthrough + case 2: // NE-Symmetry + pMan->symPhase[iVar] += pMan->symPhase[jVar]; + break; + case 3: // multiform Symmetry + Abc_TgClearSymGroupPhase(pMan, jVar); + break; + default: // case 0: No Symmetry + continue; + } + + for (ii = iVar; symLink[ii] >= 0; ii = symLink[ii]) + ; + symLink[ii] = jVar; + pVars[j] = -1; + scnt[i] += scnt[j]; + modified = 1; + fDone[i] = 0; + nsym++; + } + } +// if (++order > 3) printf("%d", order); + } while (doHigh && modified); + + return nsym; } static void Abc_TgPurgeSymmetry(Abc_TgMan_t * pMan, int doHigh) { - int i, j, k, sum = 0, nVars = pMan->nVars; - signed char *symLink = pMan->symLink; - char gcnt[16] = { 0 }; - char * pPerm = pMan->pPerm; - - for (i = 0; i <= nVars; i++) - symLink[i] = -1; - - // purge unsupported variables - if (!pMan->pGroup[0].fPhased) - { - int iVar = pMan->nVars; - for (j = 0; j < pMan->pGroup[0].nGVars; j++) - { - int jVar = pPerm[j]; - assert(jVar >= 0); - if (!Abc_TtHasVar(pMan->pTruth, nVars, jVar)) - { - symLink[jVar] = symLink[iVar]; - symLink[iVar] = jVar; - pPerm[j] = -1; - gcnt[0]++; - } - } - } - - for (k = 0; k < pMan->nGroups; k++) - gcnt[k] += Abc_TgGroupSymmetry(pMan, pMan->pGroup + k, doHigh); - - for (i = 0; i < nVars && pPerm[i] >= 0; i++) - ; - for (j = i + 1; ; i++, j++) - { - while (j < nVars && pPerm[j] < 0) j++; - if (j >= nVars) break; - pPerm[i] = pPerm[j]; - } - for (k = 0; k < pMan->nGroups; k++) - { - pMan->pGroup[k].nGVars -= gcnt[k]; - pMan->pGroup[k].iStart -= sum; - sum += gcnt[k]; - } - if (pMan->pGroup[0].nGVars == 0) - { - pMan->nGroups--; - memmove(pMan->pGroup, pMan->pGroup + 1, sizeof(TiedGroup) * pMan->nGroups); - assert(pMan->pGroup[0].iStart == 0); - } - pMan->nGVars -= sum; + int i, j, k, sum = 0, nVars = pMan->nVars; + signed char *symLink = pMan->symLink; + char gcnt[16] = { 0 }; + char * pPerm = pMan->pPerm; + + for (i = 0; i <= nVars; i++) + symLink[i] = -1; + + // purge unsupported variables + if (!pMan->pGroup[0].fPhased) + { + int iVar = pMan->nVars; + for (j = 0; j < pMan->pGroup[0].nGVars; j++) + { + int jVar = pPerm[j]; + assert(jVar >= 0); + if (!Abc_TtHasVar(pMan->pTruth, nVars, jVar)) + { + symLink[jVar] = symLink[iVar]; + symLink[iVar] = jVar; + pPerm[j] = -1; + gcnt[0]++; + } + } + } + + for (k = 0; k < pMan->nGroups; k++) + gcnt[k] += Abc_TgGroupSymmetry(pMan, pMan->pGroup + k, doHigh); + + for (i = 0; i < nVars && pPerm[i] >= 0; i++) + ; + for (j = i + 1; ; i++, j++) + { + while (j < nVars && pPerm[j] < 0) j++; + if (j >= nVars) break; + pPerm[i] = pPerm[j]; + } + for (k = 0; k < pMan->nGroups; k++) + { + pMan->pGroup[k].nGVars -= gcnt[k]; + pMan->pGroup[k].iStart -= sum; + sum += gcnt[k]; + } + if (pMan->pGroup[0].nGVars == 0) + { + pMan->nGroups--; + memmove(pMan->pGroup, pMan->pGroup + 1, sizeof(TiedGroup) * pMan->nGroups); + assert(pMan->pGroup[0].iStart == 0); + } + pMan->nGVars -= sum; } void Abc_TgExpendSymmetry(Abc_TgMan_t * pMan, char * pPerm, char * pDest) { - int i = 0, j, k; - for (j = 0; j < pMan->nGVars; j++) - for (k = pPerm[j]; k >= 0; k = pMan->symLink[k]) - pDest[i++] = k; - for (k = pMan->symLink[pMan->nVars]; k >= 0; k = pMan->symLink[k]) - pDest[i++] = k; - assert(i == pMan->nVars); + int i = 0, j, k; + for (j = 0; j < pMan->nGVars; j++) + for (k = pPerm[j]; k >= 0; k = pMan->symLink[k]) + pDest[i++] = k; + for (k = pMan->symLink[pMan->nVars]; k >= 0; k = pMan->symLink[k]) + pDest[i++] = k; + assert(i == pMan->nVars); } @@ -1876,130 +1895,130 @@ SeeAlso [] ***********************************************************************/ static int Abc_TgSymGroupPerm(Abc_TgMan_t* pMan, int idx, TiedGroup* pTGrp) { - word* pTruth = pMan->pTruth; - static word pCopy[1024]; - static word pBest[1024]; - int Config = 0; - int nWords = Abc_TtWordNum(pMan->nVars); - Abc_TgMan_t tgManCopy, tgManBest; - int fSwapOnly = pTGrp->fPhased; - - CheckConfig(pMan); - if (fSwapOnly) - { - Abc_TgManCopy(&tgManCopy, pCopy, pMan); - Abc_TgSwapAdjacentSymGroups(&tgManCopy, idx); - CheckConfig(&tgManCopy); - if (Abc_TtCompareRev(pTruth, pCopy, nWords) < 0) - { - Abc_TgManCopy(pMan, pTruth, &tgManCopy); - return 4; - } - return 0; - } - - // save two copies - Abc_TgManCopy(&tgManCopy, pCopy, pMan); - Abc_TgManCopy(&tgManBest, pBest, pMan); - // PXY - // 001 - Abc_TgFlipSymGroup(&tgManCopy, idx); - CheckConfig(&tgManCopy); - if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) - Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 1; - // PXY - // 011 - Abc_TgFlipSymGroup(&tgManCopy, idx + 1); - CheckConfig(&tgManCopy); - if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) - Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 3; - // PXY - // 010 - Abc_TgFlipSymGroup(&tgManCopy, idx); - CheckConfig(&tgManCopy); - if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) - Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 2; - // PXY - // 110 - Abc_TgSwapAdjacentSymGroups(&tgManCopy, idx); - CheckConfig(&tgManCopy); - if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) - Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 6; - // PXY - // 111 - Abc_TgFlipSymGroup(&tgManCopy, idx + 1); - CheckConfig(&tgManCopy); - if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) - Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 7; - // PXY - // 101 - Abc_TgFlipSymGroup(&tgManCopy, idx); - CheckConfig(&tgManCopy); - if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) - Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 5; - // PXY - // 100 - Abc_TgFlipSymGroup(&tgManCopy, idx + 1); - CheckConfig(&tgManCopy); - if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) - Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 4; - // PXY - // 000 - Abc_TgSwapAdjacentSymGroups(&tgManCopy, idx); - CheckConfig(&tgManCopy); - assert(Abc_TtEqual(pTruth, pCopy, nWords)); - if (Config == 0) - return 0; - assert(Abc_TtCompareRev(pTruth, pBest, nWords) == 1); - Abc_TgManCopy(pMan, pTruth, &tgManBest); - return Config; + word* pTruth = pMan->pTruth; + static word pCopy[1024]; + static word pBest[1024]; + int Config = 0; + int nWords = Abc_TtWordNum(pMan->nVars); + Abc_TgMan_t tgManCopy, tgManBest; + int fSwapOnly = pTGrp->fPhased; + + CheckConfig(pMan); + if (fSwapOnly) + { + Abc_TgManCopy(&tgManCopy, pCopy, pMan); + Abc_TgSwapAdjacentSymGroups(&tgManCopy, idx); + CheckConfig(&tgManCopy); + if (Abc_TtCompareRev(pTruth, pCopy, nWords) < 0) + { + Abc_TgManCopy(pMan, pTruth, &tgManCopy); + return 4; + } + return 0; + } + + // save two copies + Abc_TgManCopy(&tgManCopy, pCopy, pMan); + Abc_TgManCopy(&tgManBest, pBest, pMan); + // PXY + // 001 + Abc_TgFlipSymGroup(&tgManCopy, idx); + CheckConfig(&tgManCopy); + if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) + Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 1; + // PXY + // 011 + Abc_TgFlipSymGroup(&tgManCopy, idx + 1); + CheckConfig(&tgManCopy); + if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) + Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 3; + // PXY + // 010 + Abc_TgFlipSymGroup(&tgManCopy, idx); + CheckConfig(&tgManCopy); + if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) + Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 2; + // PXY + // 110 + Abc_TgSwapAdjacentSymGroups(&tgManCopy, idx); + CheckConfig(&tgManCopy); + if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) + Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 6; + // PXY + // 111 + Abc_TgFlipSymGroup(&tgManCopy, idx + 1); + CheckConfig(&tgManCopy); + if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) + Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 7; + // PXY + // 101 + Abc_TgFlipSymGroup(&tgManCopy, idx); + CheckConfig(&tgManCopy); + if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) + Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 5; + // PXY + // 100 + Abc_TgFlipSymGroup(&tgManCopy, idx + 1); + CheckConfig(&tgManCopy); + if (Abc_TtCompareRev(pBest, pCopy, nWords) == 1) + Abc_TgManCopy(&tgManBest, pBest, &tgManCopy), Config = 4; + // PXY + // 000 + Abc_TgSwapAdjacentSymGroups(&tgManCopy, idx); + CheckConfig(&tgManCopy); + assert(Abc_TtEqual(pTruth, pCopy, nWords)); + if (Config == 0) + return 0; + assert(Abc_TtCompareRev(pTruth, pBest, nWords) == 1); + Abc_TgManCopy(pMan, pTruth, &tgManBest); + return Config; } static int Abc_TgPermPhase(Abc_TgMan_t* pMan, int iVar) { - static word pCopy[1024]; - int nWords = Abc_TtWordNum(pMan->nVars); - int ivp = pMan->pPermTRev[iVar]; - Abc_TtCopy(pCopy, pMan->pTruth, nWords, 0); - Abc_TtFlip(pCopy, nWords, ivp); - if (Abc_TtCompareRev(pMan->pTruth, pCopy, nWords) == 1) - { - Abc_TtCopy(pMan->pTruth, pCopy, nWords, 0); - pMan->uPhase ^= 1 << ivp; - return 16; - } - return 0; + static word pCopy[1024]; + int nWords = Abc_TtWordNum(pMan->nVars); + int ivp = pMan->pPermTRev[iVar]; + Abc_TtCopy(pCopy, pMan->pTruth, nWords, 0); + Abc_TtFlip(pCopy, nWords, ivp); + if (Abc_TtCompareRev(pMan->pTruth, pCopy, nWords) == 1) + { + Abc_TtCopy(pMan->pTruth, pCopy, nWords, 0); + pMan->uPhase ^= 1 << ivp; + return 16; + } + return 0; } static void Abc_TgSimpleEnumeration(Abc_TgMan_t * pMan) { - int i, j, k; - int pGid[16]; - - for (k = j = 0; j < pMan->nGroups; j++) - for (i = 0; i < pMan->pGroup[j].nGVars; i++, k++) - pGid[k] = j; - assert(k == pMan->nGVars); - - for (k = 0; k < 5; k++) - { - int fChanges = 0; - for (i = pMan->nGVars - 2; i >= 0; i--) - if (pGid[i] == pGid[i + 1]) - fChanges |= Abc_TgSymGroupPerm(pMan, i, pMan->pGroup + pGid[i]); - for (i = 1; i < pMan->nGVars - 1; i++) - if (pGid[i] == pGid[i + 1]) - fChanges |= Abc_TgSymGroupPerm(pMan, i, pMan->pGroup + pGid[i]); - - for (i = pMan->nVars - 1; i >= 0; i--) - if (pMan->symPhase[i]) - fChanges |= Abc_TgPermPhase(pMan, i); - for (i = 1; i < pMan->nVars; i++) - if (pMan->symPhase[i]) - fChanges |= Abc_TgPermPhase(pMan, i); - if (!fChanges) break; - } - assert(Abc_TgCannonVerify(pMan)); + int i, j, k; + int pGid[16]; + + for (k = j = 0; j < pMan->nGroups; j++) + for (i = 0; i < pMan->pGroup[j].nGVars; i++, k++) + pGid[k] = j; + assert(k == pMan->nGVars); + + for (k = 0; k < 5; k++) + { + int fChanges = 0; + for (i = pMan->nGVars - 2; i >= 0; i--) + if (pGid[i] == pGid[i + 1]) + fChanges |= Abc_TgSymGroupPerm(pMan, i, pMan->pGroup + pGid[i]); + for (i = 1; i < pMan->nGVars - 1; i++) + if (pGid[i] == pGid[i + 1]) + fChanges |= Abc_TgSymGroupPerm(pMan, i, pMan->pGroup + pGid[i]); + + for (i = pMan->nVars - 1; i >= 0; i--) + if (pMan->symPhase[i]) + fChanges |= Abc_TgPermPhase(pMan, i); + for (i = 1; i < pMan->nVars; i++) + if (pMan->symPhase[i]) + fChanges |= Abc_TgPermPhase(pMan, i); + if (!fChanges) break; + } + assert(Abc_TgCannonVerify(pMan)); } /**Function************************************************************* @@ -2016,194 +2035,198 @@ SeeAlso [] // enumeration time = exp((cost-27.12)*0.59) static int Abc_TgEnumerationCost(Abc_TgMan_t * pMan) { - int cSym = 0; - double cPerm = 0.0; - TiedGroup * pGrp = 0; - int i, j, n; - if (pMan->nGroups == 0) return 0; - - for (i = 0; i < pMan->nGroups; i++) - { - pGrp = pMan->pGroup + i; - n = pGrp->nGVars; - if (n > 1) - cPerm += 0.92 + log(n) / 2 + n * (log(n) - 1); - } - if (pMan->pGroup->fPhased) - n = 0; - else - { - char * pVars = pMan->pPerm; - n = pMan->pGroup->nGVars; - for (i = 0; i < n; i++) - for (j = pVars[i]; j >= 0; j = pMan->symLink[j]) - cSym++; - } - // coefficients computed by linear regression - return pMan->nVars + n * 1.09 + cPerm * 1.65 + 0.5; -// return (rv > 60 ? 100000000 : 0) + n * 1000000 + cSym * 10000 + cPerm * 100 + 0.5; + int cSym = 0; + double cPerm = 0.0; + TiedGroup * pGrp = 0; + int i, j, n; + if (pMan->nGroups == 0) return 0; + + for (i = 0; i < pMan->nGroups; i++) + { + pGrp = pMan->pGroup + i; + n = pGrp->nGVars; + if (n > 1) + cPerm += 0.92 + log(n) / 2 + n * (log(n) - 1); + } + if (pMan->pGroup->fPhased) + n = 0; + else + { + char * pVars = pMan->pPerm; + n = pMan->pGroup->nGVars; + for (i = 0; i < n; i++) + for (j = pVars[i]; j >= 0; j = pMan->symLink[j]) + cSym++; + } + // coefficients computed by linear regression + return pMan->nVars + n * 1.09 + cPerm * 1.65 + 0.5; +// return (rv > 60 ? 100000000 : 0) + n * 1000000 + cSym * 10000 + cPerm * 100 + 0.5; } static int Abc_TgIsInitPerm(char * pData, signed char * pDir, int size) { - int i; - if (pDir[0] != -1) return 0; - for (i = 1; i < size; i++) - if (pDir[i] != -1 || pData[i] < pData[i - 1]) - return 0; - return 1; + int i; + if (pDir[0] != -1) return 0; + for (i = 1; i < size; i++) + if (pDir[i] != -1 || pData[i] < pData[i - 1]) + return 0; + return 1; } static void Abc_TgFirstPermutation(Abc_TgMan_t * pMan) { - int i; - for (i = 0; i < pMan->nGVars; i++) - pMan->pPermDir[i] = -1; + int i; + for (i = 0; i < pMan->nGVars; i++) + pMan->pPermDir[i] = -1; #ifndef NDEBUG - for (i = 0; i < pMan->nGroups; i++) - { - TiedGroup * pGrp = pMan->pGroup + i; - int nGvars = pGrp->nGVars; - char * pVars = pMan->pPerm + pGrp->iStart; - signed char * pDirs = pMan->pPermDir + pGrp->iStart; - assert(Abc_TgIsInitPerm(pVars, pDirs, nGvars)); - } + for (i = 0; i < pMan->nGroups; i++) + { + TiedGroup * pGrp = pMan->pGroup + i; + int nGvars = pGrp->nGVars; + char * pVars = pMan->pPerm + pGrp->iStart; + signed char * pDirs = pMan->pPermDir + pGrp->iStart; + assert(Abc_TgIsInitPerm(pVars, pDirs, nGvars)); + } #endif } static int Abc_TgNextPermutation(Abc_TgMan_t * pMan) { - int i, j, nGvars; - TiedGroup * pGrp; - char * pVars; - signed char * pDirs; - for (i = 0; i < pMan->nGroups; i++) - { - pGrp = pMan->pGroup + i; - nGvars = pGrp->nGVars; - if (nGvars == 1) continue; - pVars = pMan->pPerm + pGrp->iStart; - pDirs = pMan->pPermDir + pGrp->iStart; - j = Abc_NextPermSwapC(pVars, pDirs, nGvars); - if (j >= 0) - { - Abc_TgSwapAdjacentSymGroups(pMan, j + pGrp->iStart); - return 1; - } - Abc_TgSwapAdjacentSymGroups(pMan, pGrp->iStart); - assert(Abc_TgIsInitPerm(pVars, pDirs, nGvars)); - } - return 0; + int i, j, nGvars; + TiedGroup * pGrp; + char * pVars; + signed char * pDirs; + for (i = 0; i < pMan->nGroups; i++) + { + pGrp = pMan->pGroup + i; + nGvars = pGrp->nGVars; + if (nGvars == 1) continue; + pVars = pMan->pPerm + pGrp->iStart; + pDirs = pMan->pPermDir + pGrp->iStart; + j = Abc_NextPermSwapC(pVars, pDirs, nGvars); + if (j >= 0) + { + Abc_TgSwapAdjacentSymGroups(pMan, j + pGrp->iStart); + return 1; + } + Abc_TgSwapAdjacentSymGroups(pMan, pGrp->iStart); + assert(Abc_TgIsInitPerm(pVars, pDirs, nGvars)); + } + return 0; } static inline unsigned grayCode(unsigned a) { return a ^ (a >> 1); } -static int grayFlip(unsigned a, int n) +static int grayFlip(unsigned a) { - unsigned d = grayCode(a) ^ grayCode(a + 1); - int i; - for (i = 0; i < n; i++) - if (d == 1U << i) return i; - assert(0); - return -1; -} + int i; + for (i = 0, a++; ; i++) + if (a & (1 << i)) return i; + } static inline void Abc_TgSaveBest(Abc_TgMan_t * pMan, Abc_TgMan_t * pBest) { - if (Abc_TtCompare(pBest->pTruth, pMan->pTruth, Abc_TtWordNum(pMan->nVars)) == 1) - Abc_TgManCopy(pBest, pBest->pTruth, pMan); + if (Abc_TtCompare(pBest->pTruth, pMan->pTruth, Abc_TtWordNum(pMan->nVars)) == 1) + Abc_TgManCopy(pBest, pBest->pTruth, pMan); } static void Abc_TgPhaseEnumeration(Abc_TgMan_t * pMan, Abc_TgMan_t * pBest) { - char pFGrps[16]; - TiedGroup * pGrp = pMan->pGroup; - int i, j, n = pGrp->nGVars; - - Abc_TgSaveBest(pMan, pBest); - if (pGrp->fPhased) return; - - // sort by symPhase - for (i = 0; i < n; i++) - { - char iv = pMan->pPerm[i]; - for (j = i; j > 0 && pMan->symPhase[(int)pFGrps[j-1]] > pMan->symPhase[(int)iv]; j--) - pFGrps[j] = pFGrps[j - 1]; - pFGrps[j] = iv; - } - - for (i = 0; i < (1 << n) - 1; i++) - { - Abc_TgFlipSymGroupByVar(pMan, pFGrps[grayFlip(i, n)]); - Abc_TgSaveBest(pMan, pBest); - } + char pFGrps[16]; + TiedGroup * pGrp = pMan->pGroup; + int i, j, n = pGrp->nGVars; + + Abc_TgSaveBest(pMan, pBest); + if (pGrp->fPhased) return; + + // sort by symPhase + for (i = 0; i < n; i++) + { + char iv = pMan->pPerm[i]; + for (j = i; j > 0 && pMan->symPhase[(int)pFGrps[j-1]] > pMan->symPhase[(int)iv]; j--) + pFGrps[j] = pFGrps[j - 1]; + pFGrps[j] = iv; + } + + for (i = 0; i < (1 << n) - 1; i++) + { + Abc_TgFlipSymGroupByVar(pMan, pFGrps[grayFlip(i)]); + Abc_TgSaveBest(pMan, pBest); + } } static void Abc_TgFullEnumeration(Abc_TgMan_t * pWork, Abc_TgMan_t * pBest) { -// static word pCopy[1024]; -// Abc_TgMan_t tgManCopy; -// Abc_TgManCopy(&tgManCopy, pCopy, pMan); - - Abc_TgFirstPermutation(pWork); - do Abc_TgPhaseEnumeration(pWork, pBest); - while (Abc_TgNextPermutation(pWork)); - pBest->uPhase |= 1U << 30; +// static word pCopy[1024]; +// Abc_TgMan_t tgManCopy; +// Abc_TgManCopy(&tgManCopy, pCopy, pMan); + + Abc_TgFirstPermutation(pWork); + do Abc_TgPhaseEnumeration(pWork, pBest); + while (Abc_TgNextPermutation(pWork)); + pBest->uPhase |= 1 << 30; } unsigned Abc_TtCanonicizeAda(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int iThres) { - int nWords = Abc_TtWordNum(nVars); - unsigned fExac = 0, fHash = 1U << 29; - static word pCopy[1024]; - Abc_TgMan_t tgMan, tgManCopy; - int iCost; - const int MaxCost = 84; // maximun posible cost for function with 16 inputs - const int doHigh = iThres / 100, iEnumThres = iThres % 100; + int nWords = Abc_TtWordNum(nVars); + unsigned fExac = 0, fHash = 1 << 29; + static word pCopy[1024]; + Abc_TgMan_t tgMan, tgManCopy; + int iCost; + const int MaxCost = 84; // maximun posible cost for function with 16 inputs + const int doHigh = iThres / 100, iEnumThres = iThres % 100; + + // handle constant + if ( nVars == 0 ) { + Abc_TtClear( pTruth, nWords ); + return 0; + } + Abc_TtVerifySmallTruth(pTruth, nVars); #ifdef CANON_VERIFY - Abc_TtCopy(gpVerCopy, pTruth, nWords, 0); + Abc_TtCopy(gpVerCopy, pTruth, nWords, 0); #endif - assert(nVars <= 16); - if (p && Abc_TtHieRetrieveOrInsert(p, -5, pTruth, pTruth) > 0) return fHash; - Abc_TginitMan(&tgMan, pTruth, nVars); - Abc_TgCreateGroups(&tgMan); - if (p && Abc_TtHieRetrieveOrInsert(p, -4, pTruth, pTruth) > 0) return fHash; - Abc_TgPurgeSymmetry(&tgMan, doHigh); - - Abc_TgExpendSymmetry(&tgMan, tgMan.pPerm, pCanonPerm); - Abc_TgImplementPerm(&tgMan, pCanonPerm); - assert(Abc_TgCannonVerify(&tgMan)); - - if (p == NULL) { - if (iEnumThres > MaxCost || Abc_TgEnumerationCost(&tgMan) < iEnumThres) { - Abc_TgManCopy(&tgManCopy, pCopy, &tgMan); - Abc_TgFullEnumeration(&tgManCopy, &tgMan); - } - else - Abc_TgSimpleEnumeration(&tgMan); - } - else { - iCost = Abc_TgEnumerationCost(&tgMan); - if (iCost < iEnumThres) fExac = 1U << 30; - if (Abc_TtHieRetrieveOrInsert(p, -3, pTruth, pTruth) > 0) return fHash + fExac; - Abc_TgManCopy(&tgManCopy, pCopy, &tgMan); - Abc_TgSimpleEnumeration(&tgMan); - if (Abc_TtHieRetrieveOrInsert(p, -2, pTruth, pTruth) > 0) return fHash + fExac; - if (fExac) { - Abc_TgManCopy(&tgMan, pTruth, &tgManCopy); - Abc_TgFullEnumeration(&tgManCopy, &tgMan); - } - Abc_TtHieRetrieveOrInsert(p, -1, pTruth, pTruth); - } - memcpy(pCanonPerm, tgMan.pPermT, sizeof(char) * nVars); + assert(nVars <= 16); + if (p && Abc_TtHieRetrieveOrInsert(p, -5, pTruth, pTruth) > 0) return fHash; + Abc_TginitMan(&tgMan, pTruth, nVars); + Abc_TgCreateGroups(&tgMan); + if (p && Abc_TtHieRetrieveOrInsert(p, -4, pTruth, pTruth) > 0) return fHash; + Abc_TgPurgeSymmetry(&tgMan, doHigh); + + Abc_TgExpendSymmetry(&tgMan, tgMan.pPerm, pCanonPerm); + Abc_TgImplementPerm(&tgMan, pCanonPerm); + assert(Abc_TgCannonVerify(&tgMan)); + + if (p == NULL) { + if (iEnumThres > MaxCost || Abc_TgEnumerationCost(&tgMan) < iEnumThres) { + Abc_TgManCopy(&tgManCopy, pCopy, &tgMan); + Abc_TgFullEnumeration(&tgManCopy, &tgMan); + } + else + Abc_TgSimpleEnumeration(&tgMan); + } + else { + iCost = Abc_TgEnumerationCost(&tgMan); + if (iCost < iEnumThres) fExac = 1 << 30; + if (Abc_TtHieRetrieveOrInsert(p, -3, pTruth, pTruth) > 0) return fHash + fExac; + Abc_TgManCopy(&tgManCopy, pCopy, &tgMan); + Abc_TgSimpleEnumeration(&tgMan); + if (Abc_TtHieRetrieveOrInsert(p, -2, pTruth, pTruth) > 0) return fHash + fExac; + if (fExac) { + Abc_TgManCopy(&tgMan, pTruth, &tgManCopy); + Abc_TgFullEnumeration(&tgManCopy, &tgMan); + } + Abc_TtHieRetrieveOrInsert(p, -1, pTruth, pTruth); + } + memcpy(pCanonPerm, tgMan.pPermT, sizeof(char) * nVars); #ifdef CANON_VERIFY - if (!Abc_TgCannonVerify(&tgMan)) - printf("Canonical form verification failed!\n"); + if (!Abc_TgCannonVerify(&tgMan)) + printf("Canonical form verification failed!\n"); #endif - return tgMan.uPhase; + return tgMan.uPhase; } //////////////////////////////////////////////////////////////////////// diff --git a/src/opt/dau/dauGia.c b/src/opt/dau/dauGia.c index 424ec53..eebfa9a 100644 --- a/src/opt/dau/dauGia.c +++ b/src/opt/dau/dauGia.c @@ -449,6 +449,10 @@ int Dsm_ManTruthToGia( void * p, word * pTruth, Vec_Int_t * vLeaves, Vec_Int_t * Abc_TtCopy( pTruthCopy, pTruth, Abc_TtWordNum(Vec_IntSize(vLeaves)), 0 ); m_Calls++; assert( Vec_IntSize(vLeaves) <= DAU_DSD_MAX_VAR ); + if ( Vec_IntSize(vLeaves) == 0 ) + return (int)(pTruth[0] & 1); + if ( Vec_IntSize(vLeaves) == 1 ) + return Abc_LitNotCond( Vec_IntEntry(vLeaves, 0), (int)(pTruth[0] & 1) ); // collect delay information if ( fDelayBalance && fUseMuxes ) { diff --git a/src/opt/dau/dauNpn.c b/src/opt/dau/dauNpn.c index d8c1911..b57ade6 100644 --- a/src/opt/dau/dauNpn.c +++ b/src/opt/dau/dauNpn.c @@ -21,6 +21,7 @@ #include "dauInt.h" #include "misc/util/utilTruth.h" #include "misc/extra/extra.h" +#include "bool/lucky/lucky.h" ABC_NAMESPACE_IMPL_START @@ -122,6 +123,7 @@ void Dau_TruthEnum() { FILE * pFile = fopen( pFileName, "wb" ); int RetValue = fwrite( pTable, 8, nSizeW, pFile ); + RetValue = 0; fclose( pFile ); ABC_FREE( pTable ); } @@ -144,31 +146,42 @@ unsigned * Dau_ReadFile( char * pFileName, int nSizeW ) abctime clk = Abc_Clock(); FILE * pFile = fopen( pFileName, "rb" ); unsigned * p = (unsigned *)ABC_CALLOC(word, nSizeW); - int RetValue = fread( p, sizeof(word), nSizeW, pFile ); - fclose( pFile ); + int RetValue = pFile ? fread( p, sizeof(word), nSizeW, pFile ) : 0; + RetValue = 0; + if ( pFile ) + { + printf( "Finished reading file \"%s\".\n", pFileName ); + fclose( pFile ); + } + else + printf( "Cannot open input file \"%s\".\n", pFileName ); Abc_PrintTime( 1, "File reading", Abc_Clock() - clk ); return p; } -void Dau_AddFunction( word tCur, int nVars, unsigned * pTable, Vec_Int_t * vNpns ) +int Dau_AddFunction( word tCur, int nVars, unsigned * pTable, Vec_Int_t * vNpns, Vec_Int_t * vNpns_ ) { int Digit = (1 << nVars)-1; word tMask = Abc_Tt6Mask( 1 << nVars ); word tNorm = (tCur >> Digit) & 1 ? ~tCur : tCur; unsigned t = (unsigned)(tNorm & tMask); - unsigned tRep = pTable[t]; - unsigned tRep2 = pTable[tRep & 0x7FFFFFFF]; + unsigned tRep = pTable[t] & 0x7FFFFFFF; + unsigned tRep2 = pTable[tRep]; assert( ((tNorm >> Digit) & 1) == 0 ); if ( (tRep2 >> 31) == 0 ) // first time { Vec_IntPush( vNpns, tRep2 ); - pTable[tRep & 0x7FFFFFFF] = tRep2 | (1 << 31); + if ( Abc_TtSupportSize(&tCur, nVars) < nVars ) + Vec_IntPush( vNpns_, tRep2 ); + pTable[tRep] = tRep2 | (1 << 31); + return tRep2; } - + return 0; } void Dau_NetworkEnum() { abctime clk = Abc_Clock(); int Limit = 2; + int UseTwo = 0; #ifdef USE4VARS int nVars = 4; int nSizeW = 1 << 14; @@ -178,146 +191,626 @@ void Dau_NetworkEnum() int nSizeW = 1 << 30; char * pFileName = "tableW30.data"; #endif - unsigned * pTable = Dau_ReadFile( pFileName, nSizeW ); - Vec_Int_t * vNpns = Vec_IntAlloc( 1000 ); - int i, v, g, k, m, Entry, Count = 1, iPrev = 0, iLast = 1; + unsigned * pTable = Dau_ReadFile( pFileName, nSizeW ); + Vec_Wec_t * vNpns = Vec_WecStart( 32 ); + Vec_Wec_t * vNpns_ = Vec_WecStart( 32 ); + int i, v, u, g, k, m, n, Res, Entry; unsigned Inv = (unsigned)Abc_Tt6Mask(1 << (nVars-1)); + // create constant function and buffer/inverter function pTable[0] |= (1 << 31); pTable[Inv] |= (1 << 31); - Vec_IntPushTwo( vNpns, 0, Inv ); - Vec_IntForEachEntryStart( vNpns, Entry, i, 1 ) + Vec_IntPushTwo( Vec_WecEntry(vNpns, 0), 0, Inv ); + Vec_IntPushTwo( Vec_WecEntry(vNpns_, 0), 0, Inv ); + printf("Nodes = %2d. New = %6d. Total = %6d. New = %6d. Total = %6d. ", + 0, Vec_IntSize(Vec_WecEntry(vNpns, 0)), Vec_WecSizeSize(vNpns), + Vec_IntSize(Vec_WecEntry(vNpns_, 0)), Vec_WecSizeSize(vNpns_) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + // numerate other functions based on how many nodes they have + for ( n = 1; n < 32; n++ ) { - word uTruth = (((word)Entry) << 32) | (word)Entry; - int nSupp = Abc_TtSupportSize( &uTruth, nVars ); - //printf( "Exploring function %4d with %d vars: ", i, nSupp ); - //printf( " %04x\n", (int)uTruth ); - //Dau_DsdPrintFromTruth( &uTruth, 4 ); - for ( v = 0; v < nSupp; v++ ) + Vec_Int_t * vFuncsN2 = n > 1 ? Vec_WecEntry( vNpns, n-2 ) : NULL; + Vec_Int_t * vFuncsN1 = Vec_WecEntry( vNpns, n-1 ); + Vec_Int_t * vFuncsN = Vec_WecEntry( vNpns, n ); + Vec_Int_t * vFuncsN_ = Vec_WecEntry( vNpns_,n ); + Vec_IntForEachEntry( vFuncsN1, Entry, i ) { - word tGate, tCur; - word Cof0 = Abc_Tt6Cofactor0( uTruth, nVars-1-v ); - word Cof1 = Abc_Tt6Cofactor1( uTruth, nVars-1-v ); - for ( g = 0; g < Limit; g++ ) + word uTruth = (((word)Entry) << 32) | (word)Entry; + int nSupp = Abc_TtSupportSize( &uTruth, nVars ); + assert( nSupp == 6 || !Abc_Tt6HasVar(uTruth, nVars-1-nSupp) ); + //printf( "Exploring function %4d with %d vars: ", i, nSupp ); + //printf( " %04x\n", (int)uTruth ); + //Dau_DsdPrintFromTruth( &uTruth, 4 ); + for ( v = 0; v < nSupp; v++ ) { - if ( nSupp < nVars ) + word tGate, tCur; + word Cof0 = Abc_Tt6Cofactor0( uTruth, nVars-1-v ); + word Cof1 = Abc_Tt6Cofactor1( uTruth, nVars-1-v ); + for ( g = 0; g < Limit; g++ ) { - if ( g == 0 ) + if ( nSupp < nVars ) { - tGate = s_Truths6[nVars-1-v] & s_Truths6[nVars-1-nSupp]; - tCur = (tGate & Cof1) | (~tGate & Cof0); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); - - tCur = (tGate & Cof0) | (~tGate & Cof1); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); + if ( g == 0 ) + { + tGate = s_Truths6[nVars-1-v] & s_Truths6[nVars-1-nSupp]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + } + else + { + tGate = s_Truths6[nVars-1-v] ^ s_Truths6[nVars-1-nSupp]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + } + } + } + for ( g = 0; g < Limit; g++ ) + { + // add one cross bar + for ( k = 0; k < nSupp; k++ ) if ( k != v ) + { + if ( g == 0 ) + { + tGate = s_Truths6[nVars-1-v] & s_Truths6[nVars-1-k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + + tGate = s_Truths6[nVars-1-v] & ~s_Truths6[nVars-1-k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + } + else + { + tGate = s_Truths6[nVars-1-v] ^ s_Truths6[nVars-1-k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + } } - else + } + for ( g = 0; g < Limit; g++ ) + { + // add two cross bars + for ( k = 0; k < nSupp; k++ ) if ( k != v ) + for ( m = k+1; m < nSupp; m++ ) if ( m != v ) { - tGate = s_Truths6[nVars-1-v] ^ s_Truths6[nVars-1-nSupp]; - tCur = (tGate & Cof1) | (~tGate & Cof0); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); + if ( g == 0 ) + { + tGate = s_Truths6[nVars-1-m] & s_Truths6[nVars-1-k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + + tGate = s_Truths6[nVars-1-m] & ~s_Truths6[nVars-1-k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + + tGate = ~s_Truths6[nVars-1-m] & s_Truths6[nVars-1-k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + + tGate = ~s_Truths6[nVars-1-m] & ~s_Truths6[nVars-1-k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + } + else + { + tGate = s_Truths6[nVars-1-m] ^ s_Truths6[nVars-1-k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + } } } } - for ( g = 0; g < Limit; g++ ) + } + if ( UseTwo && vFuncsN2 ) + Vec_IntForEachEntry( vFuncsN2, Entry, i ) + { + word uTruth = (((word)Entry) << 32) | (word)Entry; + int nSupp = Abc_TtSupportSize( &uTruth, nVars ); + assert( nSupp == 6 || !Abc_Tt6HasVar(uTruth, nVars-1-nSupp) ); + //printf( "Exploring function %4d with %d vars: ", i, nSupp ); + //printf( " %04x\n", (int)uTruth ); + //Dau_DsdPrintFromTruth( &uTruth, 4 ); + for ( v = 0; v < nSupp; v++ ) +// for ( u = v+1; u < nSupp; u++ ) if ( u != v ) + for ( u = 0; u < nSupp; u++ ) if ( u != v ) { + word tGate1, tGate2, tCur; + word Cof0 = Abc_Tt6Cofactor0( uTruth, nVars-1-v ); + word Cof1 = Abc_Tt6Cofactor1( uTruth, nVars-1-v ); + + word Cof00 = Abc_Tt6Cofactor0( Cof0, nVars-1-u ); + word Cof01 = Abc_Tt6Cofactor1( Cof0, nVars-1-u ); + word Cof10 = Abc_Tt6Cofactor0( Cof1, nVars-1-u ); + word Cof11 = Abc_Tt6Cofactor1( Cof1, nVars-1-u ); + + tGate1 = s_Truths6[nVars-1-v] & s_Truths6[nVars-1-u]; + tGate2 = s_Truths6[nVars-1-v] ^ s_Truths6[nVars-1-u]; + + Cof0 = (tGate2 & Cof00) | (~tGate2 & Cof01); + Cof1 = (tGate2 & Cof10) | (~tGate2 & Cof11); + + tCur = (tGate1 & Cof1) | (~tGate1 & Cof0); + Res = Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + if ( Res ) + printf( "Found function %d\n", Res ); + + tCur = (tGate1 & Cof0) | (~tGate1 & Cof1); + Res = Dau_AddFunction( tCur, nVars, pTable, vFuncsN, vFuncsN_ ); + if ( Res ) + printf( "Found function %d\n", Res ); + } + } + printf("Nodes = %2d. New = %6d. Total = %6d. New = %6d. Total = %6d. ", + n, Vec_IntSize(vFuncsN), Vec_WecSizeSize(vNpns), Vec_IntSize(vFuncsN_), Vec_WecSizeSize(vNpns_) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + fflush(stdout); + if ( Vec_IntSize(vFuncsN) == 0 ) + break; + } +// printf( "Functions with 7 nodes:\n" ); +// Vec_IntForEachEntry( Vec_WecEntry(vNpns_,7), Entry, i ) +// printf( "%04x ", Entry ); +// printf( "\n" ); + + Vec_WecFree( vNpns ); + Vec_WecFree( vNpns_ ); + ABC_FREE( pTable ); + Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); + fflush(stdout); +} +void Dau_NetworkEnumTest() +{ + //Dau_TruthEnum(); + Dau_NetworkEnum(); +} + + + +/**Function************************************************************* + + Synopsis [Count the number of symmetric pairs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dau_CountSymms( word t, int nVars ) +{ + word Cof0, Cof1; + int i, j, nPairs = 0; + for ( i = 0; i < nVars; i++ ) + for ( j = i+1; j < nVars; j++ ) + nPairs += Abc_TtVarsAreSymmetric(&t, nVars, i, j, &Cof0, &Cof1); + return nPairs; +} +int Dau_CountSymms2( word t, int nVars ) +{ + word Cof0, Cof1; + int i, j, SymVars = 0; + for ( i = 0; i < nVars; i++ ) + for ( j = i+1; j < nVars; j++ ) + if ( Abc_TtVarsAreSymmetric(&t, nVars, i, j, &Cof0, &Cof1) ) + SymVars |= (1 << j); + return SymVars; +} +int Dau_CountCompl1( word t, int v, int nVars ) +{ + word tNew = Abc_Tt6Flip(t, v); + int k; + if ( tNew == ~t ) + return 1; + for ( k = 0; k < nVars; k++ ) if ( k != v ) + if ( tNew == Abc_Tt6Flip(t, k) ) + return 1; + return 0; +} +int Dau_CountCompl( word t, int nVars ) +{ + int i, nPairs = 0; + for ( i = 0; i < nVars; i++ ) + nPairs += Dau_CountCompl1(t, i, nVars); + return nPairs; +} + +/**Function************************************************************* + + Synopsis [Performs exact canonicization of semi-canonical classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Dau_ExactNpnForClasses( Vec_Mem_t * vTtMem, Vec_Int_t * vNodSup, int nVars, int nInputs ) +{ + Vec_Wrd_t * vCanons = Vec_WrdStart( Vec_IntSize(vNodSup) ); + word pAuxWord[1024], pAuxWord1[1024]; + word uTruth; int i, Entry; + permInfo * pi = setPermInfoPtr(nVars); + Vec_IntForEachEntry( vNodSup, Entry, i ) + { + if ( (Entry & 0xF) > nVars ) + continue; + uTruth = *Vec_MemReadEntry( vTtMem, i ); + simpleMinimal(&uTruth, pAuxWord, pAuxWord1, pi, nVars); + Vec_WrdWriteEntry( vCanons, i, uTruth ); + } + freePermInfoPtr(pi); + return vCanons; +} +void Dau_ExactNpnPrint( Vec_Mem_t * vTtMem, Vec_Int_t * vNodSup, int nVars, int nInputs, int nNodesMax ) +{ + abctime clk = Abc_Clock(); int n, nTotal = 0; + Vec_Wrd_t * vCanons = Dau_ExactNpnForClasses( vTtMem, vNodSup, nVars, nInputs ); + Vec_Mem_t * vTtMem2 = Vec_MemAlloc( Vec_MemEntrySize(vTtMem), 10 ); + Vec_MemHashAlloc( vTtMem2, 1<<10 ); + Abc_PrintTime( 1, "Exact NPN computation time", Abc_Clock() - clk ); + printf( "Final results:\n" ); + for ( n = 0; n <= nNodesMax; n++ ) + { + int i, Entry, Entry2, nEntries2, Counter = 0, Counter2 = 0; + Vec_IntForEachEntry( vNodSup, Entry, i ) + { + if ( (Entry & 0xF) > nVars || (Entry >> 16) != n ) + continue; + Counter++; + nEntries2 = Vec_MemEntryNum(vTtMem2); + Entry2 = Vec_MemHashInsert( vTtMem2, Vec_WrdEntryP(vCanons, i) ); + if ( nEntries2 == Vec_MemEntryNum(vTtMem2) ) // found in the table - not new + continue; + Counter2++; + } + nTotal += Counter2; + printf( "Nodes = %2d. ", n ); + printf( "Semi-canonical = %8d. ", Counter ); + printf( "Canonical = %8d. ", Counter2 ); + printf( "Total = %8d.", nTotal ); + printf( "\n" ); + } + Vec_MemHashFree( vTtMem2 ); + Vec_MemFreeP( &vTtMem2 ); + Vec_WrdFree( vCanons ); + fflush(stdout); +} + +/**Function************************************************************* + + Synopsis [Saving hash tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dau_TablesSave( int nInputs, int nVars, Vec_Mem_t * vTtMem, Vec_Int_t * vNodSup, int nFronts, abctime clk ) +{ + FILE * pFile; + char FileName[100]; + int i, nWords = Abc_TtWordNum(nInputs); + // NPN classes + sprintf( FileName, "npn%d%d.ttd", nInputs, nVars ); + pFile = fopen( FileName, "wb" ); + for ( i = 0; i < Vec_MemEntryNum(vTtMem); i++ ) + fwrite( Vec_MemReadEntry(vTtMem, i), 8, nWords, pFile ); + fwrite( Vec_IntArray(vNodSup), 4, Vec_IntSize(vNodSup), pFile ); + fclose( pFile ); +// printf( "Dumped files with %10d classes after exploring %10d frontiers.\n", +// Vec_IntSize(vNodSup), nFronts ); + printf( "Dumped file \"%s\" with %10d classes after exploring %10d frontiers. ", + FileName, Vec_IntSize(vNodSup), nFronts ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + fflush(stdout); +} + +/**Function************************************************************* + + Synopsis [Dump functions by the number of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dau_DumpFuncs( Vec_Mem_t * vTtMem, Vec_Int_t * vNodSup, int nVars, int nMax ) +{ + FILE * pFile[20]; + int Counters[20] = {0}; + int n, i; + assert( nVars == 4 || nVars == 5 ); + for ( n = 0; n <= nMax; n++ ) + { + char FileName[100]; + sprintf( FileName, "func%d_min%d.tt", nVars, n ); + pFile[n] = fopen( FileName, "wb" ); + } + for ( i = 0; i < Vec_MemEntryNum(vTtMem); i++ ) + { + word * pTruth = Vec_MemReadEntry( vTtMem, i ); + int NodSup = Vec_IntEntry( vNodSup, i ); + if ( (NodSup & 0xF) != nVars ) + continue; + Counters[NodSup >> 16]++; + if ( nVars == 4 ) + fprintf( pFile[NodSup >> 16], "%04x\n", (int)(0xFFFF & pTruth[0]) ); + else if ( nVars == 5 ) + fprintf( pFile[NodSup >> 16], "%08x\n", (int)(0xFFFFFFFF & pTruth[0]) ); + } + for ( n = 0; n <= nMax; n++ ) + { + printf( "Dumped %8d %d-node %d-input functions into file.\n", Counters[n], n, nVars ); + fclose( pFile[n] ); + } +} + +/**Function************************************************************* + + Synopsis [Function enumeration.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dau_CountFuncs( Vec_Int_t * vNodSup, int iStart, int iStop, int nVars ) +{ + int i, Entry, Count = 0; + Vec_IntForEachEntryStartStop( vNodSup, Entry, i, iStart, iStop ) + Count += ((Entry & 0xF) <= nVars); + return Count; +} +int Dau_PrintStats( int nNodes, int nInputs, int nVars, Vec_Int_t * vNodSup, int iStart, int iStop, word nSteps, int Count2, abctime clk ) +{ + int nNew; + printf("N =%2d | ", nNodes ); + printf("C =%12.0f ", (double)(iword)nSteps ); + printf("New%d =%10d ", nInputs, iStop-iStart ); + printf("All%d =%10d | ", nInputs, iStop ); + printf("New%d =%8d ", nVars, nNew = Dau_CountFuncs(vNodSup, iStart, iStop, nVars) ); + printf("All%d =%8d ", nVars, Dau_CountFuncs(vNodSup, 0, iStop, nVars) ); + printf("Two =%6d ", Count2 ); + //Abc_PrintTime( 1, "T", Abc_Clock() - clk ); + Abc_Print(1, "%9.2f sec\n", 1.0*(Abc_Clock() - clk)/(CLOCKS_PER_SEC)); + fflush(stdout); + return nNew; +} + + +int Dau_InsertFunction( Abc_TtHieMan_t * pMan, word * pCur, int nNodes, int nInputs, int nVars0, int nVars, + Vec_Mem_t * vTtMem, Vec_Int_t * vNodSup, int nFronts, abctime clk ) +{ + int DumpDelta = 1000000; + char Perm[16] = {0}; + int nVarsNew = Abc_TtMinBase( pCur, NULL, nVars, nInputs ); + //unsigned Phase = Abc_TtCanonicizeHie( pMan, pCur, nVarsNew, Perm, 1 ); + unsigned Phase = Abc_TtCanonicizeWrap( Abc_TtCanonicizeAda, pMan, pCur, nVarsNew, Perm, 99 ); + int nEntries = Vec_MemEntryNum(vTtMem); + int Entry = Vec_MemHashInsert( vTtMem, pCur ); + if ( nEntries == Vec_MemEntryNum(vTtMem) ) // found in the table - not new + return 0; + Entry = 0; + Phase = 0; + // this is a new class + Vec_IntPush( vNodSup, (nNodes << 16) | nVarsNew ); + assert( Vec_MemEntryNum(vTtMem) == Vec_IntSize(vNodSup) ); + if ( Vec_IntSize(vNodSup) % DumpDelta == 0 ) + Dau_TablesSave( nInputs, nVars0, vTtMem, vNodSup, nFronts, clk ); + return 1; +} +void Dau_FunctionEnum( int nInputs, int nVars, int nNodeMax, int fUseTwo, int fReduce, int fVerbose ) +{ + abctime clk = Abc_Clock(); + int nWords = Abc_TtWordNum(nInputs); word nSteps = 0; + Abc_TtHieMan_t * pMan = Abc_TtHieManStart( nInputs, 5 ); + Vec_Mem_t * vTtMem = Vec_MemAlloc( nWords, 16 ); + Vec_Int_t * vNodSup = Vec_IntAlloc( 1 << 16 ); + int v, u, k, m, n, Entry, nNew, Limit[32] = {1, 2}; + word Truth[4] = {0}; + assert( nVars >= 3 && nVars <= nInputs && nInputs <= 6 ); + Vec_MemHashAlloc( vTtMem, 1<<16 ); + // add constant 0 + Vec_MemHashInsert( vTtMem, Truth ); + Vec_IntPush( vNodSup, 0 ); // nodes=0, supp=0 + // add buffer/inverter + Abc_TtIthVar( Truth, 0, nInputs ); + Abc_TtNot( Truth, nWords ); + Vec_MemHashInsert( vTtMem, Truth ); + Vec_IntPush( vNodSup, 1 ); // nodes=0, supp=1 + Dau_PrintStats( 0, nInputs, nVars, vNodSup, 0, 2, nSteps, 0, clk ); + // numerate other functions based on how many nodes they have + for ( n = 1; n <= nNodeMax; n++ ) + { + int Count2 = 0; + int fExpand = !(fReduce && n == nNodeMax); + for ( Entry = Limit[n-1]; Entry < Limit[n]; Entry++ ) + { + word * pTruth = Vec_MemReadEntry( vTtMem, Entry ); + int NodSup = Vec_IntEntry(vNodSup, Entry); + int nSupp = 0xF & NodSup; + int SymVars = Dau_CountSymms2( pTruth[0], nSupp ); + assert( n-1 == (NodSup >> 16) ); + assert( !Abc_Tt6HasVar(*pTruth, nSupp) ); + //printf( "Exploring function %4d with %d vars: ", i, nSupp ); + //printf( " %04x\n", (int)uTruth ); + //Dau_DsdPrintFromTruth( &uTruth, 4 ); + for ( v = 0; v < nSupp; v++ ) if ( (SymVars & (1 << v)) == 0 ) + { + word tGate, tCur; + word Cof0 = Abc_Tt6Cofactor0( *pTruth, v ); + word Cof1 = Abc_Tt6Cofactor1( *pTruth, v ); + // add one extra variable to support + if ( nSupp < nInputs && fExpand ) + { + tGate = s_Truths6[v] & s_Truths6[nSupp]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp+1, vTtMem, vNodSup, Entry, clk ); + + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp+1, vTtMem, vNodSup, Entry, clk ); + + + tGate = s_Truths6[v] ^ s_Truths6[nSupp]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp+1, vTtMem, vNodSup, Entry, clk ); + + nSteps += 3; + } // add one cross bar - for ( k = 0; k < nSupp; k++ ) if ( k != v ) + if ( fExpand ) + for ( k = 0; k < nSupp; k++ ) if ( k != v && ((SymVars & (1 << k)) == 0 || k == v+1) ) { - if ( g == 0 ) - { - tGate = s_Truths6[nVars-1-v] & s_Truths6[nVars-1-k]; - tCur = (tGate & Cof1) | (~tGate & Cof0); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); + tGate = s_Truths6[v] & s_Truths6[k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); - tCur = (tGate & Cof0) | (~tGate & Cof1); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); - tGate = s_Truths6[nVars-1-v] & ~s_Truths6[nVars-1-k]; - tCur = (tGate & Cof1) | (~tGate & Cof0); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); + tGate = s_Truths6[v] & ~s_Truths6[k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); - tCur = (tGate & Cof0) | (~tGate & Cof1); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); - } - else - { - tGate = s_Truths6[nVars-1-v] ^ s_Truths6[nVars-1-k]; - tCur = (tGate & Cof1) | (~tGate & Cof0); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); - } + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); + + + tGate = s_Truths6[v] ^ s_Truths6[k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); + + nSteps += 5; } - } - for ( g = 0; g < Limit; g++ ) - { // add two cross bars - for ( k = 0; k < nSupp; k++ ) if ( k != v ) - for ( m = k+1; m < nSupp; m++ ) if ( m != v ) + for ( k = 0; k < nSupp; k++ ) if ( k != v )//&& ((SymVars & (1 << k)) == 0) ) + for ( m = k+1; m < nSupp; m++ ) if ( m != v )//&& ((SymVars & (1 << m)) == 0 || m == k+1) ) { - if ( g == 0 ) - { - tGate = s_Truths6[nVars-1-m] & s_Truths6[nVars-1-k]; - tCur = (tGate & Cof1) | (~tGate & Cof0); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); + tGate = s_Truths6[m] & s_Truths6[k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); - tCur = (tGate & Cof0) | (~tGate & Cof1); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); - tGate = s_Truths6[nVars-1-m] & ~s_Truths6[nVars-1-k]; - tCur = (tGate & Cof1) | (~tGate & Cof0); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); + tGate = s_Truths6[m] & ~s_Truths6[k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); - tCur = (tGate & Cof0) | (~tGate & Cof1); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); - tGate = ~s_Truths6[nVars-1-m] & s_Truths6[nVars-1-k]; - tCur = (tGate & Cof1) | (~tGate & Cof0); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); + tGate = ~s_Truths6[m] & s_Truths6[k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); - tCur = (tGate & Cof0) | (~tGate & Cof1); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); - tGate = ~s_Truths6[nVars-1-m] & ~s_Truths6[nVars-1-k]; - tCur = (tGate & Cof1) | (~tGate & Cof0); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); + tGate = ~s_Truths6[m] & ~s_Truths6[k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); - tCur = (tGate & Cof0) | (~tGate & Cof1); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); - } - else - { - tGate = s_Truths6[nVars-1-m] ^ s_Truths6[nVars-1-k]; - tCur = (tGate & Cof1) | (~tGate & Cof0); - Dau_AddFunction( tCur, nVars, pTable, vNpns ); - } + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); + + + tGate = s_Truths6[m] ^ s_Truths6[k]; + tCur = (tGate & Cof1) | (~tGate & Cof0); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); + + tGate = s_Truths6[m] ^ s_Truths6[k]; + tCur = (tGate & Cof0) | (~tGate & Cof1); + Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); + + nSteps += 10; } } - } - if ( i == iLast ) + } + if ( fUseTwo && n > 2 && fExpand ) + for ( Entry = Limit[n-2]; Entry < Limit[n-1]; Entry++ ) { - //printf("Finished %d nodes with %d functions.\n", Count++, Vec_IntSize(vNpns) ); - iPrev = iLast; - iLast = Vec_IntSize(vNpns)-1; - printf("Finished %2d nodes with %6d functions out of %6d. ", Count++, iLast - iPrev, Vec_IntSize(vNpns) ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - fflush(stdout); + word * pTruth = Vec_MemReadEntry( vTtMem, Entry ); + int NodSup = Vec_IntEntry(vNodSup, Entry); + int nSupp = 0xF & NodSup; int g1, g2; + assert( n-2 == (NodSup >> 16) ); + assert( !Abc_Tt6HasVar(*pTruth, nSupp) ); + for ( v = 0; v < nSupp; v++ ) + for ( u = 0; u < nSupp; u++ ) if ( u != v ) + { + word Cof0 = Abc_Tt6Cofactor0( *pTruth, v ); + word Cof1 = Abc_Tt6Cofactor1( *pTruth, v ); + + word Cof00 = Abc_Tt6Cofactor0( Cof0, u ); + word Cof01 = Abc_Tt6Cofactor1( Cof0, u ); + word Cof10 = Abc_Tt6Cofactor0( Cof1, u ); + word Cof11 = Abc_Tt6Cofactor1( Cof1, u ); + + word tGates[5], tCur; + tGates[0] = s_Truths6[v] & s_Truths6[u]; + tGates[1] = s_Truths6[v] & ~s_Truths6[u]; + tGates[2] = ~s_Truths6[v] & s_Truths6[u]; + tGates[3] = s_Truths6[v] | s_Truths6[u]; + tGates[4] = s_Truths6[v] ^ s_Truths6[u]; + + for ( g1 = 0; g1 < 5; g1++ ) + for ( g2 = g1+1; g2 < 5; g2++ ) + { + Cof0 = (tGates[g1] & Cof01) | (~tGates[g1] & Cof00); + Cof1 = (tGates[g1] & Cof11) | (~tGates[g1] & Cof10); + + tCur = (tGates[g2] & Cof1) | (~tGates[g2] & Cof0); + Count2 += Dau_InsertFunction( pMan, &tCur, n, nInputs, nVars, nSupp, vTtMem, vNodSup, Entry, clk ); + } + } } + Limit[n+1] = Vec_IntSize(vNodSup); + nNew = Dau_PrintStats( n, nInputs, nVars, vNodSup, Limit[n], Limit[n+1], nSteps, Count2, clk ); + if ( nNew == 0 ) + break; } - Vec_IntFree( vNpns ); - ABC_FREE( pTable ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Dau_TablesSave( nInputs, nVars, vTtMem, vNodSup, Vec_IntSize(vNodSup), clk ); + Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); + //Dau_DumpFuncs( vTtMem, vNodSup, nVars, nNodeMax ); + //Dau_ExactNpnPrint( vTtMem, vNodSup, nVars, nInputs, n ); + Abc_TtHieManStop( pMan ); + Vec_MemHashFree( vTtMem ); + Vec_MemFreeP( &vTtMem ); + Vec_IntFree( vNodSup ); fflush(stdout); } -void Dau_NetworkEnumTest() -{ - //Dau_TruthEnum(); - Dau_NetworkEnum(); -} - //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// - ABC_NAMESPACE_IMPL_END diff --git a/src/opt/dau/dauNpn2.c b/src/opt/dau/dauNpn2.c new file mode 100644 index 0000000..bca65ad --- /dev/null +++ b/src/opt/dau/dauNpn2.c @@ -0,0 +1,507 @@ +/**CFile**************************************************************** + + FileName [dau.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware unmapping.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: dau.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dauInt.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Dtt_Man_t_ Dtt_Man_t; +struct Dtt_Man_t_ +{ + int nVars; // variable number + int nPerms; // number of permutations + int nComps; // number of complementations + int * pPerms; // permutations + int * pComps; // complementations + word * pPres; // function marks + Vec_Int_t * vFanins; // node fanins + Vec_Int_t * vTruths; // node truth tables + Vec_Int_t * vConfigs; // configurations + Vec_Int_t * vClasses; // node NPN classes + Vec_Int_t * vTruthNpns; // truth tables of the classes + Vec_Wec_t * vFunNodes; // nodes by NPN class + Vec_Int_t * vTemp; // temporary + Vec_Int_t * vTemp2; // temporary + unsigned FunMask; // function mask + unsigned CmpMask; // function mask + unsigned BinMask; // hash mask + unsigned * pBins; // hash bins + Vec_Int_t * vUsedBins; // used bins + int Counts[32]; // node counts + int nClasses; // count of classes + unsigned * pTable; // mapping of funcs into their classes + int * pNodes; // the number of nodes in min-node network + int * pTimes; // the number of different min-node networks + char * pVisited; // visited classes + Vec_Int_t * vVisited; // the number of visited classes +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Dau_ReadFile2( char * pFileName, int nSizeW ) +{ + abctime clk = Abc_Clock(); + FILE * pFile = fopen( pFileName, "rb" ); + unsigned * p = (unsigned *)ABC_CALLOC(word, nSizeW); + int RetValue = pFile ? fread( p, sizeof(word), nSizeW, pFile ) : 0; + RetValue = 0; + if ( pFile ) + { + printf( "Finished reading file \"%s\".\n", pFileName ); + fclose( pFile ); + } + else + printf( "Cannot open input file \"%s\".\n", pFileName ); + Abc_PrintTime( 1, "File reading", Abc_Clock() - clk ); + return p; +} +void Dtt_ManRenum( int nVars, unsigned * pTable, int * pnClasses ) +{ + unsigned i, Limit = 1 << ((1 << nVars)-1), Count = 0; + for ( i = 0; i < Limit; i++ ) + if ( pTable[i] == i ) + pTable[i] = Count++; + else + { + assert( pTable[i] < i ); + pTable[i] = pTable[pTable[i]]; + } + printf( "The total number of NPN classes = %d.\n", Count ); + *pnClasses = Count; +} +unsigned * Dtt_ManLoadClasses( int nVars, int * pnClasses ) +{ + unsigned * pTable = NULL; + if ( nVars == 4 ) + pTable = Dau_ReadFile2( "tableW14.data", 1 << 14 ); + else if ( nVars == 5 ) + pTable = Dau_ReadFile2( "tableW30.data", 1 << 30 ); + else assert( 0 ); + Dtt_ManRenum( nVars, pTable, pnClasses ); + return pTable; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dtt_ManAddVisited( Dtt_Man_t * p, unsigned Truth2, int n ) +{ + unsigned Truth = Truth2 & p->CmpMask ? ~Truth2 : Truth2; + unsigned Class = p->pTable[Truth & p->FunMask]; + assert( Class < (unsigned)p->nClasses ); + if ( p->pNodes[Class] < n ) + return; + assert( p->pNodes[Class] == n ); + if ( p->pVisited[Class] ) + return; + p->pVisited[Class] = 1; + Vec_IntPush( p->vVisited, Class ); +} +void Dtt_ManProcessVisited( Dtt_Man_t * p ) +{ + int i, Class; + Vec_IntForEachEntry( p->vVisited, Class, i ) + { + assert( p->pVisited[Class] ); + p->pVisited[Class] = 0; + p->pTimes[Class]++; + } + Vec_IntClear( p->vVisited ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dtt_Man_t * Dtt_ManAlloc( int nVars, int fMulti ) +{ + Dtt_Man_t * p = ABC_CALLOC( Dtt_Man_t, 1 ); + p->nVars = nVars; + p->nPerms = Extra_Factorial( nVars ); + p->nComps = 1 << nVars; + p->pPerms = Extra_PermSchedule( nVars ); + p->pComps = Extra_GreyCodeSchedule( nVars ); + p->pPres = ABC_CALLOC( word, 1 << (p->nComps - 7) ); + p->vFanins = Vec_IntAlloc( 2*617000 ); + p->vTruths = Vec_IntAlloc( 617000 ); + p->vConfigs = Vec_IntAlloc( 617000 ); + p->vClasses = Vec_IntAlloc( 617000 ); + p->vTruthNpns = Vec_IntAlloc( 617000 ); + p->vFunNodes = Vec_WecStart( 16 ); + p->vTemp = Vec_IntAlloc( 4000 ); + p->vTemp2 = Vec_IntAlloc( 4000 ); + p->FunMask = nVars == 5 ? ~0 : (nVars == 4 ? 0xFFFF : 0xFF); + p->CmpMask = nVars == 5 ? 1 << 31 : (nVars == 4 ? 1 << 15 : 1 << 7); + p->BinMask = 0x3FFF; + p->pBins = ABC_FALLOC( unsigned, p->BinMask + 1 ); + p->vUsedBins = Vec_IntAlloc( 4000 ); + if ( !fMulti ) return p; + p->pTable = Dtt_ManLoadClasses( p->nVars, &p->nClasses ); + p->pNodes = ABC_CALLOC( int, p->nClasses ); + p->pTimes = ABC_CALLOC( int, p->nClasses ); + p->pVisited = ABC_CALLOC( char, p->nClasses ); + p->vVisited = Vec_IntAlloc( 1000 ); + return p; +} +void Dtt_ManFree( Dtt_Man_t * p ) +{ + Vec_IntFreeP( &p->vVisited ); + ABC_FREE( p->pTable ); + ABC_FREE( p->pNodes ); + ABC_FREE( p->pTimes ); + ABC_FREE( p->pVisited ); + Vec_IntFreeP( &p->vFanins ); + Vec_IntFreeP( &p->vTruths ); + Vec_IntFreeP( &p->vConfigs ); + Vec_IntFreeP( &p->vClasses ); + Vec_IntFreeP( &p->vTruthNpns ); + Vec_WecFreeP( &p->vFunNodes ); + Vec_IntFreeP( &p->vTemp ); + Vec_IntFreeP( &p->vTemp2 ); + Vec_IntFreeP( &p->vUsedBins ); + ABC_FREE( p->pPerms ); + ABC_FREE( p->pComps ); + ABC_FREE( p->pPres ); + ABC_FREE( p->pBins ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Collect representatives of the same class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dtt_ManHashKey( Dtt_Man_t * p, unsigned Truth ) +{ + static unsigned s_P[4] = { 1699, 5147, 7103, 8147 }; + unsigned char * pD = (unsigned char*)&Truth; + return pD[0] * s_P[0] + pD[1] * s_P[1] + pD[2] * s_P[2] + pD[3] * s_P[3]; +} +int Dtt_ManCheckHash( Dtt_Man_t * p, unsigned Truth ) +{ + unsigned Hash = Dtt_ManHashKey(p, Truth); + unsigned * pSpot = p->pBins + (Hash & p->BinMask); + for ( ; ~*pSpot; Hash++, pSpot = p->pBins + (Hash & p->BinMask) ) + if ( *pSpot == Truth ) // equal + return 0; + Vec_IntPush( p->vUsedBins, pSpot - p->pBins ); + *pSpot = Truth; + return 1; +} +Vec_Int_t * Dtt_ManCollect( Dtt_Man_t * p, unsigned Truth, Vec_Int_t * vFuns ) +{ + int i, k, Entry; + word tCur = ((word)Truth << 32) | (word)Truth; + Vec_IntClear( vFuns ); + for ( i = 0; i < p->nPerms; i++ ) + { + for ( k = 0; k < p->nComps; k++ ) + { +// unsigned tTemp = (unsigned)(tCur & 1 ? ~tCur : tCur); + unsigned tTemp = (unsigned)(tCur & p->CmpMask ? ~tCur : tCur); + if ( Dtt_ManCheckHash( p, tTemp ) ) + Vec_IntPush( vFuns, tTemp ); + tCur = Abc_Tt6Flip( tCur, p->pComps[k] ); + } + tCur = Abc_Tt6SwapAdjacent( tCur, p->pPerms[i] ); + } + assert( tCur == (((word)Truth << 32) | (word)Truth) ); + // clean hash table + Vec_IntForEachEntry( p->vUsedBins, Entry, i ) + p->pBins[Entry] = ~0; + Vec_IntClear( p->vUsedBins ); + //printf( "%d ", Vec_IntSize(vFuns) ); + return vFuns; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dtt_ManGetFun( Dtt_Man_t * p, unsigned tFun ) +{ + tFun = tFun & p->CmpMask ? ~tFun : tFun; + return Abc_TtGetBit( p->pPres, tFun & p->FunMask ); +} +static inline void Dtt_ManSetFun( Dtt_Man_t * p, unsigned tFun ) +{ + tFun = tFun & p->CmpMask ? ~tFun : tFun; + //assert( !Dtt_ManGetFun(p, fFun & p->FunMask ); + Abc_TtSetBit( p->pPres, tFun & p->FunMask ); +} +void Dtt_ManAddFunction( Dtt_Man_t * p, int n, int FanI, int FanJ, int Type, unsigned Truth ) +{ + Vec_Int_t * vFuncs = Dtt_ManCollect( p, Truth, p->vTemp2 ); + unsigned Min = Vec_IntFindMin( vFuncs ); + int i, nObjs = Vec_IntSize(p->vFanins)/2; + int nNodesI = 0xF & (Vec_IntEntry(p->vConfigs, FanI) >> 3); + int nNodesJ = 0xF & (Vec_IntEntry(p->vConfigs, FanJ) >> 3); + int nNodes = nNodesI + nNodesJ + 1; + assert( nObjs == Vec_IntSize(p->vTruths) ); + assert( nObjs == Vec_IntSize(p->vConfigs) ); + assert( nObjs == Vec_IntSize(p->vClasses) ); + Vec_WecPush( p->vFunNodes, n, nObjs ); + Vec_IntPushTwo( p->vFanins, FanI, FanJ ); + Vec_IntPush( p->vTruths, Truth ); + Vec_IntPush( p->vConfigs, (nNodes << 3) | Type ); + Vec_IntPush( p->vClasses, Vec_IntSize(p->vTruthNpns) ); + Vec_IntPush( p->vTruthNpns, Min ); + Vec_IntForEachEntry( vFuncs, Min, i ) + Dtt_ManSetFun( p, Min ); + assert( nNodes < 32 ); + p->Counts[nNodes]++; + + if ( p->pTable == NULL ) + return; + Truth = Truth & p->CmpMask ? ~Truth : Truth; + Truth &= p->FunMask; + assert( p->pNodes[p->pTable[Truth]] == 0 ); + p->pNodes[p->pTable[Truth]] = n; +} + +int Dtt_PrintStats( int nNodes, int nVars, Vec_Wec_t * vFunNodes, word nSteps, abctime clk, int fDelay, word nMultis ) +{ + int nNew = Vec_IntSize(Vec_WecEntry(vFunNodes, nNodes)); + printf("%c =%2d | ", fDelay ? 'D':'N', nNodes ); + printf("C =%12.0f | ", (double)(iword)nSteps ); + printf("New%d =%10d ", nVars, nNew + (int)(nNodes==0) ); + printf("All%d =%10d | ", nVars, Vec_WecSizeSize(vFunNodes)+1 ); + printf("Multi =%10d | ", (int)nMultis ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + //Abc_Print(1, "%9.2f sec\n", 1.0*(Abc_Clock() - clk)/(CLOCKS_PER_SEC)); + fflush(stdout); + return nNew; +} +void Dtt_PrintDistrib( Dtt_Man_t * p ) +{ + int i; + printf( "NPN classes for each node count (N):\n" ); + for ( i = 0; i < 32; i++ ) + if ( p->Counts[i] ) + printf( "N = %2d : NPN = %6d\n", i, p->Counts[i] ); +} +void Dtt_PrintMulti2( Dtt_Man_t * p ) +{ + int i, n; + for ( n = 0; n <= 7; n++ ) + { + printf( "n=%d : ", n); + for ( i = 0; i < p->nClasses; i++ ) + if ( p->pNodes[i] == n ) + printf( "%d ", p->pTimes[i] ); + printf( "\n" ); + } +} +void Dtt_PrintMulti1( Dtt_Man_t * p ) +{ + int i, n, Entry, Count, Prev; + for ( n = 0; n < 16; n++ ) + { + Vec_Int_t * vTimes = Vec_IntAlloc( 100 ); + Vec_Int_t * vUsed = Vec_IntAlloc( 100 ); + for ( i = 0; i < p->nClasses; i++ ) + if ( p->pNodes[i] == n ) + Vec_IntPush( vTimes, p->pTimes[i] ); + if ( Vec_IntSize(vTimes) == 0 ) + { + Vec_IntFree(vTimes); + Vec_IntFree(vUsed); + break; + } + Vec_IntSort( vTimes, 0 ); + Count = 1; + Prev = Vec_IntEntry( vTimes, 0 ); + Vec_IntForEachEntryStart( vTimes, Entry, i, 1 ) + if ( Prev == Entry ) + Count++; + else + { + assert( Prev < Entry ); + Vec_IntPushTwo( vUsed, Prev, Count ); + Count = 1; + Prev = Entry; + } + if ( Count > 0 ) + Vec_IntPushTwo( vUsed, Prev, Count ); + printf( "n=%d : ", n); + Vec_IntForEachEntryDouble( vUsed, Prev, Entry, i ) + printf( "%d=%d ", Prev, Entry ); + printf( "\n" ); + Vec_IntFree( vTimes ); + Vec_IntFree( vUsed ); + } +} +void Dtt_PrintMulti( Dtt_Man_t * p ) +{ + int n, Counts[13][11] = {{0}}; + for ( n = 0; n < 13; n++ ) + { + int i, Total = 0, Count = 0; + for ( i = 0; i < p->nClasses; i++ ) + if ( p->pNodes[i] == n ) + { + int Log = Abc_Base2Log(p->pTimes[i]); + assert( Log < 11 ); + if ( p->pTimes[i] < 2 ) + Counts[n][0]++; + else + Counts[n][Log]++; + Total += p->pTimes[i]; + Count++; + } + if ( Count == 0 ) + break; + printf( "n=%2d : ", n ); + printf( "All = %7d ", Count ); + printf( "Ave = %6.2f ", 1.0*Total/Count ); + for ( i = 0; i < 11; i++ ) + if ( Counts[n][i] ) + printf( "%6d", Counts[n][i] ); + else + printf( "%6s", "" ); + printf( "\n" ); + } +} +void Dtt_EnumerateLf( int nVars, int nNodeMax, int fDelay, int fMulti, int fVerbose ) +{ + abctime clk = Abc_Clock(); word nSteps = 0, nMultis = 0; + Dtt_Man_t * p = Dtt_ManAlloc( nVars, fMulti ); int n, i, j; + // constant zero class + Vec_IntPushTwo( p->vFanins, 0, 0 ); + Vec_IntPush( p->vTruths, 0 ); + Vec_IntPush( p->vConfigs, 0 ); + Vec_IntPush( p->vClasses, Vec_IntSize(p->vTruthNpns) ); + Vec_IntPush( p->vTruthNpns, 0 ); + Dtt_ManSetFun( p, 0 ); + // buffer class + Vec_WecPush( p->vFunNodes, 0, Vec_IntSize(p->vFanins)/2 ); + Vec_IntPushTwo( p->vFanins, 0, 0 ); + Vec_IntPush( p->vTruths, (unsigned)s_Truths6[0] ); + Vec_IntPush( p->vConfigs, 0 ); + Vec_IntPush( p->vClasses, Vec_IntSize(p->vTruthNpns) ); + Vec_IntPush( p->vTruthNpns, (unsigned)s_Truths6[0] ); + for ( i = 0; i < nVars; i++ ) + Dtt_ManSetFun( p, (unsigned)s_Truths6[i] ); + p->Counts[0] = 2; + // enumerate + Dtt_PrintStats(0, nVars, p->vFunNodes, nSteps, clk, fDelay, 0); + for ( n = 1; n <= nNodeMax; n++ ) + { + for ( i = 0, j = n - 1; i < n; i++, j = j - 1 + fDelay ) if ( i <= j ) + { + Vec_Int_t * vFaninI = Vec_WecEntry( p->vFunNodes, i ); + Vec_Int_t * vFaninJ = Vec_WecEntry( p->vFunNodes, j ); + int k, i0, j0, EntryI, EntryJ; + Vec_IntForEachEntry( vFaninI, EntryI, i0 ) + { + unsigned TruthI = Vec_IntEntry(p->vTruths, EntryI); + Vec_Int_t * vFuns = Dtt_ManCollect( p, TruthI, p->vTemp ); + int Start = i == j ? i0 : 0; + Vec_IntForEachEntryStart( vFaninJ, EntryJ, j0, Start ) + { + unsigned Truth, TruthJ = Vec_IntEntry(p->vTruths, EntryJ); + Vec_IntForEachEntry( vFuns, Truth, k ) + { + if ( !Dtt_ManGetFun(p, TruthJ & Truth) ) + Dtt_ManAddFunction( p, n, EntryI, EntryJ, 0, TruthJ & Truth ); + if ( !Dtt_ManGetFun(p, TruthJ & ~Truth) ) + Dtt_ManAddFunction( p, n, EntryI, EntryJ, 1, TruthJ & ~Truth ); + if ( !Dtt_ManGetFun(p, ~TruthJ & Truth) ) + Dtt_ManAddFunction( p, n, EntryI, EntryJ, 2, ~TruthJ & Truth ); + if ( !Dtt_ManGetFun(p, TruthJ | Truth) ) + Dtt_ManAddFunction( p, n, EntryI, EntryJ, 3, TruthJ | Truth ); + if ( !Dtt_ManGetFun(p, TruthJ ^ Truth) ) + Dtt_ManAddFunction( p, n, EntryI, EntryJ, 4, TruthJ ^ Truth ); + nSteps += 5; + + if ( p->pTable ) Dtt_ManAddVisited( p, TruthJ & Truth, n ); + if ( p->pTable ) Dtt_ManAddVisited( p, TruthJ & ~Truth, n ); + if ( p->pTable ) Dtt_ManAddVisited( p, ~TruthJ & Truth, n ); + if ( p->pTable ) Dtt_ManAddVisited( p, TruthJ | Truth, n ); + if ( p->pTable ) Dtt_ManAddVisited( p, TruthJ ^ Truth, n ); + } + nMultis++; + if ( p->pTable ) Dtt_ManProcessVisited( p ); + } + } + } + if ( Dtt_PrintStats(n, nVars, p->vFunNodes, nSteps, clk, fDelay, nMultis) == 0 ) + break; + } + if ( fDelay ) + Dtt_PrintDistrib( p ); + if ( p->pTable ) + Dtt_PrintMulti( p ); + Dtt_ManFree( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/src/opt/dau/module.make b/src/opt/dau/module.make index efc34a1..5feb104 100644 --- a/src/opt/dau/module.make +++ b/src/opt/dau/module.make @@ -8,4 +8,5 @@ SRC += src/opt/dau/dauCanon.c \ src/opt/dau/dauMerge.c \ src/opt/dau/dauNonDsd.c \ src/opt/dau/dauNpn.c \ + src/opt/dau/dauNpn2.c \ src/opt/dau/dauTree.c diff --git a/src/proof/abs/absGla.c b/src/proof/abs/absGla.c index 698d415..bd6b8c7 100644 --- a/src/proof/abs/absGla.c +++ b/src/proof/abs/absGla.c @@ -1430,7 +1430,7 @@ void Ga2_GlaDumpAbsracted( Ga2_Man_t * p, int fVerbose ) // dump abstraction map Vec_IntFreeP( &p->pGia->vGateClasses ); p->pGia->vGateClasses = Ga2_ManAbsTranslate( p ); - Gia_AigerWrite( p->pGia, pFileName, 0, 0 ); + Gia_AigerWrite( p->pGia, pFileName, 0, 0, 0 ); } else if ( p->pPars->fDumpVabs ) { @@ -1443,7 +1443,7 @@ void Ga2_GlaDumpAbsracted( Ga2_Man_t * p, int fVerbose ) vGateClasses = Ga2_ManAbsTranslate( p ); pAbs = Gia_ManDupAbsGates( p->pGia, vGateClasses ); Gia_ManCleanValue( p->pGia ); - Gia_AigerWrite( pAbs, pFileName, 0, 0 ); + Gia_AigerWrite( pAbs, pFileName, 0, 0, 0 ); Gia_ManStop( pAbs ); Vec_IntFreeP( &vGateClasses ); } @@ -1563,7 +1563,7 @@ int Gia_ManPerformGla( Gia_Man_t * pAig, Abs_Par_t * pPars ) Vec_IntWriteEntry( pAig->vGateClasses, i, 1 ); Gia_ManForEachRo( pAig, pObj, i ) Vec_IntWriteEntry( pAig->vGateClasses, Gia_ObjId(pAig, pObj), 1 ); - Gia_AigerWrite( pAig, pFileName, 0, 0 ); + Gia_AigerWrite( pAig, pFileName, 0, 0, 0 ); Vec_IntFree( pAig->vGateClasses ); pAig->vGateClasses = vMap; if ( p->pPars->fVerbose ) diff --git a/src/proof/abs/absGlaOld.c b/src/proof/abs/absGlaOld.c index 70bd2e9..45ed139 100644 --- a/src/proof/abs/absGlaOld.c +++ b/src/proof/abs/absGlaOld.c @@ -1619,7 +1619,7 @@ void Gia_GlaDumpAbsracted( Gla_Man_t * p, int fVerbose ) pAbs = Gia_ManDupAbsGates( p->pGia0, vGateClasses ); Vec_IntFreeP( &vGateClasses ); // write into file - Gia_AigerWrite( pAbs, pFileName, 0, 0 ); + Gia_AigerWrite( pAbs, pFileName, 0, 0, 0 ); Gia_ManStop( pAbs ); } diff --git a/src/proof/abs/absVta.c b/src/proof/abs/absVta.c index 01680a3..597e4b7 100644 --- a/src/proof/abs/absVta.c +++ b/src/proof/abs/absVta.c @@ -1439,7 +1439,7 @@ void Gia_VtaDumpAbsracted( Vta_Man_t * p, int fVerbose ) pAbs = Gia_ManDupAbsGates( p->pGia, p->pGia->vGateClasses ); Vec_IntFreeP( &p->pGia->vGateClasses ); // send it out - Gia_AigerWrite( pAbs, pFileName, 0, 0 ); + Gia_AigerWrite( pAbs, pFileName, 0, 0, 0 ); Gia_ManStop( pAbs ); } diff --git a/src/proof/acec/acecCore.c b/src/proof/acec/acecCore.c index 1a575fb..033fbc3 100644 --- a/src/proof/acec/acecCore.c +++ b/src/proof/acec/acecCore.c @@ -527,7 +527,7 @@ int Acec_Solve( Gia_Man_t * pGia0, Gia_Man_t * pGia1, Acec_ParCec_t * pPars ) if ( fDumpMiter ) { Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "acec_miter.aig" ); - Gia_AigerWrite( pMiter, "acec_miter.aig", 0, 0 ); + Gia_AigerWrite( pMiter, "acec_miter.aig", 0, 0, 0 ); } status = Cec_ManVerify( pMiter, pCecPars ); ABC_SWAP( Abc_Cex_t *, pGia0->pCexComb, pMiter->pCexComb ); diff --git a/src/proof/acec/acecOrder.c b/src/proof/acec/acecOrder.c index 93ef7f1..4eb79fe 100644 --- a/src/proof/acec/acecOrder.c +++ b/src/proof/acec/acecOrder.c @@ -173,7 +173,7 @@ Vec_Int_t * Gia_PolynFindOrder( Gia_Man_t * pGia, Vec_Int_t * vFadds, Vec_Int_t { Gia_Man_t * pNew; pNew = Gia_ManDupAndCones( pGia, Vec_IntArray(vLeft), Vec_IntSize(vLeft), 0 ); - Gia_AigerWrite( pNew, "leftover.aig", 0, 0 ); + Gia_AigerWrite( pNew, "leftover.aig", 0, 0, 0 ); printf( "Leftover AIG with %d nodes is dumped into file \"%s\".\n", Gia_ManAndNum(pNew), "leftover.aig" ); Gia_ManStop( pNew ); } diff --git a/src/proof/cec/cecCec.c b/src/proof/cec/cecCec.c index be6df65..ee45aa6 100644 --- a/src/proof/cec/cecCec.c +++ b/src/proof/cec/cecCec.c @@ -392,7 +392,7 @@ int Cec_ManVerify( Gia_Man_t * pInit, Cec_ParCec_t * pPars ) { ABC_FREE( pNew->pReprs ); ABC_FREE( pNew->pNexts ); - Gia_AigerWrite( pNew, "gia_cec_undecided.aig", 0, 0 ); + Gia_AigerWrite( pNew, "gia_cec_undecided.aig", 0, 0, 0 ); Abc_Print( 1, "The result is written into file \"%s\".\n", "gia_cec_undecided.aig" ); } if ( pPars->TimeLimit && (Abc_Clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit ) diff --git a/src/proof/cec/cecCore.c b/src/proof/cec/cecCore.c index 250cb69..b952965 100644 --- a/src/proof/cec/cecCore.c +++ b/src/proof/cec/cecCore.c @@ -407,7 +407,7 @@ p->timeSim += Abc_Clock() - clk; } pSrm = Cec_ManFraSpecReduction( p ); -// Gia_AigerWrite( pSrm, "gia_srm.aig", 0, 0 ); +// Gia_AigerWrite( pSrm, "gia_srm.aig", 0, 0, 0 ); if ( pPars->fVeryVerbose ) Gia_ManPrintStats( pSrm, NULL ); @@ -493,7 +493,7 @@ p->timeSat += Abc_Clock() - clk; Abc_Print( 1, "Increasing conflict limit to %d.\n", pParsSat->nBTLimit ); if ( fOutputResult ) { - Gia_AigerWrite( p->pAig, "gia_cec_temp.aig", 0, 0 ); + Gia_AigerWrite( p->pAig, "gia_cec_temp.aig", 0, 0, 0 ); Abc_Print( 1,"The result is written into file \"%s\".\n", "gia_cec_temp.aig" ); } } diff --git a/src/proof/cec/cecCorr.c b/src/proof/cec/cecCorr.c index 3bff4d3..fdc6029 100644 --- a/src/proof/cec/cecCorr.c +++ b/src/proof/cec/cecCorr.c @@ -1196,7 +1196,7 @@ Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) pNew = Gia_ManCorrReduce( pAig ); pNew = Gia_ManSeqCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); - //Gia_AigerWrite( pNew, "reduced.aig", 0, 0 ); + //Gia_AigerWrite( pNew, "reduced.aig", 0, 0, 0 ); } // report the results if ( pPars->fVerbose ) diff --git a/src/proof/cec/cecSeq.c b/src/proof/cec/cecSeq.c index f39fb2a..81420e0 100644 --- a/src/proof/cec/cecSeq.c +++ b/src/proof/cec/cecSeq.c @@ -401,14 +401,14 @@ int Cec_ManSeqSemiformal( Gia_Man_t * pAig, Cec_ParSmf_t * pPars ) } // write equivalence classes - Gia_AigerWrite( pAig, "gore.aig", 0, 0 ); + Gia_AigerWrite( pAig, "gore.aig", 0, 0, 0 ); // reduce the model pReduce = Gia_ManSpecReduce( pAig, 0, 0, 1, 0, 0 ); if ( pReduce ) { pReduce = Gia_ManSeqStructSweep( pAux = pReduce, 1, 1, 0 ); Gia_ManStop( pAux ); - Gia_AigerWrite( pReduce, "gsrm.aig", 0, 0 ); + Gia_AigerWrite( pReduce, "gsrm.aig", 0, 0, 0 ); // Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", "gsrm.aig" ); // Gia_ManPrintStatsShort( pReduce ); Gia_ManStop( pReduce ); diff --git a/src/proof/cec/cecSolve.c b/src/proof/cec/cecSolve.c index ee9b8e7..02f14b7 100644 --- a/src/proof/cec/cecSolve.c +++ b/src/proof/cec/cecSolve.c @@ -742,7 +742,7 @@ clk2 = Abc_Clock(); if ( status == -1 ) { Gia_Man_t * pTemp = Gia_ManDupDfsCone( pAig, pObj ); - Gia_AigerWrite( pTemp, "gia_hard.aig", 0, 0 ); + Gia_AigerWrite( pTemp, "gia_hard.aig", 0, 0, 0 ); Gia_ManStop( pTemp ); Abc_Print( 1, "Dumping hard cone into file \"%s\".\n", "gia_hard.aig" ); } diff --git a/src/proof/cec/cecSynth.c b/src/proof/cec/cecSynth.c index 6e5fd22..9465858 100644 --- a/src/proof/cec/cecSynth.c +++ b/src/proof/cec/cecSynth.c @@ -309,7 +309,7 @@ int Cec_SequentialSynthesisPart( Gia_Man_t * p, Cec_ParSeq_t * pPars ) { pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, NULL ); sprintf( Buffer, "part%03d.aig", i ); - Gia_AigerWrite( pTemp, Buffer, 0, 0 ); + Gia_AigerWrite( pTemp, Buffer, 0, 0, 0 ); Abc_Print( 1, "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp) ); Gia_ManStop( pTemp ); diff --git a/src/proof/pdr/pdrCore.c b/src/proof/pdr/pdrCore.c index 21c713b..4e206b9 100644 --- a/src/proof/pdr/pdrCore.c +++ b/src/proof/pdr/pdrCore.c @@ -1427,6 +1427,7 @@ int Pdr_ManSolve( Aig_Man_t * pAig, Pdr_Par_t * pPars ) char * pFileName = Extra_FileNameGenericAppend(p->pAig->pName, "_inv.pla"); Abc_FrameSetInv( Pdr_ManDeriveInfinityClauses( p, RetValue!=1 ) ); Pdr_ManDumpClauses( p, pFileName, RetValue==1 ); + printf( "Dumped inductive invariant in file \"%s\".\n", pFileName ); } else if ( RetValue == 1 ) Abc_FrameSetInv( Pdr_ManDeriveInfinityClauses( p, RetValue!=1 ) ); diff --git a/src/sat/bmc/bmc.h b/src/sat/bmc/bmc.h index 71a3359..12439fa 100644 --- a/src/sat/bmc/bmc.h +++ b/src/sat/bmc/bmc.h @@ -58,6 +58,7 @@ struct Bmc_EsPar_t_ int fOrderNodes; int fEnumSols; int fFewerVars; + int RuntimeLim; int fVerbose; char * pTtStr; }; @@ -76,6 +77,7 @@ static inline void Bmc_EsParSetDefault( Bmc_EsPar_t * pPars ) pPars->fOrderNodes = 0; pPars->fEnumSols = 0; pPars->fFewerVars = 0; + pPars->RuntimeLim = 0; pPars->fVerbose = 1; } @@ -186,6 +188,7 @@ struct Bmc_ParFf_t_ int fNonStrict; int fBasic; int fFfOnly; + int fCheckUntest; int fDump; int fDumpDelay; int fDumpUntest; diff --git a/src/sat/bmc/bmcBmcAnd.c b/src/sat/bmc/bmcBmcAnd.c index 04d4435..b9c2db2 100644 --- a/src/sat/bmc/bmcBmcAnd.c +++ b/src/sat/bmc/bmcBmcAnd.c @@ -711,7 +711,7 @@ int Gia_ManBmcPerform_Unr( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ) if ( pPars->fDumpFrames ) { p->pFrames = Gia_ManCleanup( p->pFrames ); - Gia_AigerWrite( p->pFrames, "frames.aig", 0, 0 ); + Gia_AigerWrite( p->pFrames, "frames.aig", 0, 0, 0 ); printf( "Dumped unfolded frames into file \"frames.aig\".\n" ); Gia_ManStop( p->pFrames ); } @@ -793,7 +793,7 @@ int Gia_ManBmcPerform_old_cnf( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ) Gia_ManPrintStats( p->pFrames, NULL ); if ( pPars->fDumpFrames ) { - Gia_AigerWrite( p->pFrames, "frames.aig", 0, 0 ); + Gia_AigerWrite( p->pFrames, "frames.aig", 0, 0, 0 ); printf( "Dumped unfolded frames into file \"frames.aig\".\n" ); } for ( f = 0; f < nFramesMax; f++ ) @@ -977,7 +977,7 @@ int Gia_ManBmcPerformInt( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ) Gia_ManPrintStats( p->pFrames, NULL ); if ( pPars->fDumpFrames ) { - Gia_AigerWrite( p->pFrames, "frames.aig", 0, 0 ); + Gia_AigerWrite( p->pFrames, "frames.aig", 0, 0, 0 ); printf( "Dumped unfolded frames into file \"frames.aig\".\n" ); } if ( pPars->fUseOldCnf ) diff --git a/src/sat/bmc/bmcCexDepth.c b/src/sat/bmc/bmcCexDepth.c index 38b57d5..f0883f9 100644 --- a/src/sat/bmc/bmcCexDepth.c +++ b/src/sat/bmc/bmcCexDepth.c @@ -110,7 +110,7 @@ Gia_Man_t * Bmc_CexTarget( Gia_Man_t * p, int nFrames ) Gia_ManPrintStats( pNew, NULL ); pTemp = Gia_ManDupAppendCones( p, &pNew, 1, 1 ); Gia_ManStop( pNew ); - Gia_AigerWrite( pTemp, "miter3.aig", 0, 0 ); + Gia_AigerWrite( pTemp, "miter3.aig", 0, 0, 0 ); return pTemp; } @@ -308,7 +308,7 @@ Gia_Man_t * Bmc_CexBuildNetwork2Test( Gia_Man_t * p, Abc_Cex_t * pCex, int nFram Vec_PtrPush( vCones, pNew ); } pNew = Gia_ManDupAppendCones( p, (Gia_Man_t **)Vec_PtrArray(vCones), Vec_PtrSize(vCones), 1 ); - Gia_AigerWrite( pNew, "miter2.aig", 0, 0 ); + Gia_AigerWrite( pNew, "miter2.aig", 0, 0, 0 ); //Bmc_CexDumpAogStats( pNew, Abc_Clock() - clk ); Vec_PtrForEachEntry( Gia_Man_t *, vCones, pTemp, i ) Gia_ManStop( pTemp ); diff --git a/src/sat/bmc/bmcCexMin2.c b/src/sat/bmc/bmcCexMin2.c index b851460..b39b8ee 100644 --- a/src/sat/bmc/bmcCexMin2.c +++ b/src/sat/bmc/bmcCexMin2.c @@ -334,7 +334,7 @@ Abc_Cex_t * Gia_ManCexMin( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrameStart, int printf( "%3d : ", iFrameStart ); Gia_ManPrintStats( pNew, NULL ); if ( fVerbose ) - Gia_AigerWrite( pNew, "temp.aig", 0, 0 ); + Gia_AigerWrite( pNew, "temp.aig", 0, 0, 0 ); Gia_ManStop( pNew ); } else // CEX min @@ -345,7 +345,7 @@ Abc_Cex_t * Gia_ManCexMin( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrameStart, int printf( "%3d : ", f ); Gia_ManPrintStats( pNew, NULL ); if ( fVerbose ) - Gia_AigerWrite( pNew, "temp.aig", 0, 0 ); + Gia_AigerWrite( pNew, "temp.aig", 0, 0, 0 ); Gia_ManStop( pNew ); } } diff --git a/src/sat/bmc/bmcCexTools.c b/src/sat/bmc/bmcCexTools.c index 9c80b27..5a29c8b 100644 --- a/src/sat/bmc/bmcCexTools.c +++ b/src/sat/bmc/bmcCexTools.c @@ -173,7 +173,7 @@ void Bmc_CexPerformUnrollingTest( Gia_Man_t * p, Abc_Cex_t * pCex ) abctime clk = Abc_Clock(); pNew = Bmc_CexPerformUnrolling( p, pCex ); Gia_ManPrintStats( pNew, NULL ); - Gia_AigerWrite( pNew, "unroll.aig", 0, 0 ); + Gia_AigerWrite( pNew, "unroll.aig", 0, 0, 0 ); //Bmc_CexDumpAogStats( pNew, Abc_Clock() - clk ); Gia_ManStop( pNew ); printf( "CE-induced network is written into file \"unroll.aig\".\n" ); @@ -285,7 +285,7 @@ void Bmc_CexBuildNetworkTest( Gia_Man_t * p, Abc_Cex_t * pCex ) abctime clk = Abc_Clock(); pNew = Bmc_CexBuildNetwork( p, pCex ); Gia_ManPrintStats( pNew, NULL ); - Gia_AigerWrite( pNew, "unate.aig", 0, 0 ); + Gia_AigerWrite( pNew, "unate.aig", 0, 0, 0 ); //Bmc_CexDumpAogStats( pNew, Abc_Clock() - clk ); Gia_ManStop( pNew ); printf( "CE-induced network is written into file \"unate.aig\".\n" ); diff --git a/src/sat/bmc/bmcEco.c b/src/sat/bmc/bmcEco.c index 9d30fc0..b42d527 100644 --- a/src/sat/bmc/bmcEco.c +++ b/src/sat/bmc/bmcEco.c @@ -291,7 +291,7 @@ void Bmc_EcoMiterTest() Vec_IntPush( vFans, Gia_ObjId(pOld, pObj) ); pMiter = Bmc_EcoMiter( pGold, pOld, vFans ); Vec_IntFree( vFans ); - Gia_AigerWrite( pMiter, "eco_miter.aig", 0, 0 ); + Gia_AigerWrite( pMiter, "eco_miter.aig", 0, 0, 0 ); // find the patch RetValue = Bmc_EcoPatch( pMiter, Gia_ManCiNum(pGold), Gia_ManCoNum(pGold) ); if ( RetValue == 1 ) diff --git a/src/sat/bmc/bmcFault.c b/src/sat/bmc/bmcFault.c index 0f63fa6..28d8a0c 100644 --- a/src/sat/bmc/bmcFault.c +++ b/src/sat/bmc/bmcFault.c @@ -22,6 +22,7 @@ #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" #include "aig/gia/giaAig.h" +#include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START @@ -58,6 +59,7 @@ void Gia_ParFfSetDefault( Bmc_ParFf_t * p ) p->nIterCheck = 0; p->fBasic = 0; p->fFfOnly = 0; + p->fCheckUntest = 0; p->fDump = 0; p->fDumpUntest = 0; p->fVerbose = 0; @@ -476,6 +478,7 @@ Gia_Man_t * Gia_ManFOFUnfold( Gia_Man_t * p, Vec_Int_t * vMap ) Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iCtrl0, iCtrl1, iCtrl2, iCtrl3, iMuxA, iMuxB, iFuncVars = 0; + int VarLimit = 4 * Gia_ManAndNum(p); pNew = Gia_ManStart( 9 * Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); @@ -484,22 +487,22 @@ Gia_Man_t * Gia_ManFOFUnfold( Gia_Man_t * p, Vec_Int_t * vMap ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachAnd( p, pObj, i ) { - if ( Vec_IntEntry(vMap, iFuncVars++) ) + if ( Vec_IntEntry(vMap, iFuncVars++) && iFuncVars < VarLimit ) iCtrl0 = Gia_ManAppendCi(pNew); else iCtrl0 = 0, Gia_ManAppendCi(pNew); - if ( Vec_IntEntry(vMap, iFuncVars++) ) + if ( Vec_IntEntry(vMap, iFuncVars++) && iFuncVars < VarLimit ) iCtrl1 = Gia_ManAppendCi(pNew); else iCtrl1 = 0, Gia_ManAppendCi(pNew); - if ( Vec_IntEntry(vMap, iFuncVars++) ) + if ( Vec_IntEntry(vMap, iFuncVars++) && iFuncVars < VarLimit ) iCtrl2 = Gia_ManAppendCi(pNew); else iCtrl2 = 0, Gia_ManAppendCi(pNew); - if ( Vec_IntEntry(vMap, iFuncVars++) ) + if ( Vec_IntEntry(vMap, iFuncVars++) && iFuncVars < VarLimit ) iCtrl3 = Gia_ManAppendCi(pNew); else iCtrl3 = 0, Gia_ManAppendCi(pNew); @@ -751,7 +754,7 @@ Gia_Man_t * Gia_ManFormulaUnfold( Gia_Man_t * p, char * pForm, int fFfOnly ) Gia_ManStop( pTemp ); assert( Gia_ManPiNum(pNew) == Gia_ManCiNum(p) + nPars * (fFfOnly ? Count : Gia_ManAndNum(p)) ); // if ( fUseFaults ) -// Gia_AigerWrite( pNew, "newfault.aig", 0, 0 ); +// Gia_AigerWrite( pNew, "newfault.aig", 0, 0, 0 ); return pNew; } @@ -1257,7 +1260,7 @@ int Gia_ManFaultPrepare( Gia_Man_t * p, Gia_Man_t * pG, Bmc_ParFf_t * pPars, int p1 = Gia_ManFOFUnfold( p, vMap ); if ( pPars->Algo != 1 ) p0 = Gia_ManDeriveDup( pG, Gia_ManCiNum(p1) - Gia_ManCiNum(pG) ); -// Gia_AigerWrite( p1, "newfault.aig", 0, 0 ); +// Gia_AigerWrite( p1, "newfault.aig", 0, 0, 0 ); // printf( "Dumped circuit with fault parameters into file \"newfault.aig\".\n" ); // create miter @@ -1441,6 +1444,19 @@ void Gia_ManFaultTest( Gia_Man_t * p, Gia_Man_t * pG, Bmc_ParFf_t * pPars ) return; } + printf( "Options: " ); + printf( "Untestable faults = %s. ", pPars->fCheckUntest || pPars->fDumpDelay ? "yes": "no" ); + if ( pPars->nCardConstr ) + printf( "Using %sstrict cardinality %d. ", pPars->fNonStrict ? "non-" : "", pPars->nCardConstr ); + if ( pPars->fFfOnly ) + printf( "Faults at FF outputs only = yes. " ); + if ( pPars->nTimeOut ) + printf( "Runtime limit = %d sec. ", pPars->nTimeOut ); + if ( p != pG && pG->pSpec ) + printf( "Golden model = %s. ", pG->pSpec ); + printf( "Verbose = %s. ", pPars->fVerbose ? "yes": "no" ); + printf( "\n" ); + // select algorithm if ( pPars->Algo == 0 ) nFuncVars = Gia_ManCiNum(p); @@ -1565,7 +1581,7 @@ finish: // dump the test suite if ( pPars->fDump ) { - char * pFileName = "tests.txt"; + char * pFileName = p->pSpec ? Extra_FileNameGenericAppend(p->pSpec, "_tests.txt") : "tests.txt"; if ( pPars->fDumpDelay && pPars->Algo == 1 ) { Gia_ManDumpTestsDelay( vTests, Iter, pFileName, p ); @@ -1579,7 +1595,7 @@ finish: } // compute untestable faults - if ( Iter && (p != pG || pPars->fDumpUntest) ) + if ( Iter && (p != pG || pPars->fDumpUntest || pPars->fCheckUntest) ) { abctime clkTotal = Abc_Clock(); // restart the SAT solver @@ -1680,7 +1696,7 @@ finish: if ( pPars->fDumpUntest && status == l_True ) { abctime clk = Abc_Clock(); - char * pFileName = "untest.txt"; + char * pFileName = p->pSpec ? Extra_FileNameGenericAppend(p->pSpec, "_untest.txt") : "untest.txt"; int nUntests = Gia_ManDumpUntests( pM, pCnf, pSat, nFuncVars, pFileName, pPars->fVerbose ); if ( p == pG ) printf( "Dumped %d untestable multiple faults into file \"%s\". ", nUntests, pFileName ); diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index 4f2c8db..08571a3 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -500,6 +500,8 @@ Exa_Man_t * Exa_ManAlloc( Bmc_EsPar_t * pPars, word * pTruth ) p->vInfo = Exa_ManTruthTables( p ); p->pSat = bmcg_sat_solver_start(); bmcg_sat_solver_set_nvars( p->pSat, p->iVar ); + if ( pPars->RuntimeLim ) + bmcg_sat_solver_set_runtime_limit( p->pSat, Abc_Clock() + pPars->RuntimeLim * CLOCKS_PER_SEC ); return p; } void Exa_ManFree( Exa_Man_t * p ) @@ -572,6 +574,59 @@ static inline int Exa_ManEval( Exa_Man_t * p ) SeeAlso [] ***********************************************************************/ +void Exa_ManDumpBlif( Exa_Man_t * p, int fCompl ) +{ + char Buffer[1000]; + char FileName[1000]; + FILE * pFile; + int i, k, iVar; + if ( fCompl ) + Abc_TtNot( p->pTruth, p->nWords ); + Extra_PrintHexadecimalString( Buffer, (unsigned *)p->pTruth, p->nVars ); + if ( fCompl ) + Abc_TtNot( p->pTruth, p->nWords ); + sprintf( FileName, "%s_%d_%d.blif", Buffer, 2, p->nNodes ); + pFile = fopen( FileName, "wb" ); + fprintf( pFile, "# Realization of the %d-input function %s using %d two-input gates:\n", p->nVars, Buffer, p->nNodes ); + fprintf( pFile, ".model %s_%d_%d\n", Buffer, 2, p->nNodes ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < p->nVars; i++ ) + fprintf( pFile, " %c", 'a'+i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".outputs F\n" ); + for ( i = p->nObjs - 1; i >= p->nVars; i-- ) + { + int iVarStart = 1 + 3*(i - p->nVars); + int Val1 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart); + int Val2 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+1); + int Val3 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+2); + + fprintf( pFile, ".names" ); + for ( k = 1; k >= 0; k-- ) + { + iVar = Exa_ManFindFanin( p, i, k ); + if ( iVar >= 0 && iVar < p->nVars ) + fprintf( pFile, " %c", 'a'+iVar ); + else + fprintf( pFile, " %02d", iVar ); + } + if ( i == p->nObjs - 1 ) + fprintf( pFile, " F\n" ); + else + fprintf( pFile, " %02d\n", i ); + if ( i == p->nObjs - 1 && fCompl ) + fprintf( pFile, "00 1\n" ); + if ( (i == p->nObjs - 1 && fCompl) ^ Val1 ) + fprintf( pFile, "01 1\n" ); + if ( (i == p->nObjs - 1 && fCompl) ^ Val2 ) + fprintf( pFile, "10 1\n" ); + if ( (i == p->nObjs - 1 && fCompl) ^ Val3 ) + fprintf( pFile, "11 1\n" ); + } + fprintf( pFile, ".end\n\n" ); + fclose( pFile ); + printf( "Solution was dumped into file \"%s\".\n", FileName ); +} void Exa_ManPrintSolution( Exa_Man_t * p, int fCompl ) { int i, k, iVar; @@ -775,10 +830,18 @@ void Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ) printf( "The problem has no solution.\n" ); break; } + if ( status == GLUCOSE_UNDEC ) + { + printf( "The problem timed out after %d sec.\n", pPars->RuntimeLim ); + break; + } iMint = Exa_ManEval( p ); } if ( iMint == -1 ) + { Exa_ManPrintSolution( p, fCompl ); + Exa_ManDumpBlif( p, fCompl ); + } Exa_ManFree( p ); Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); } @@ -915,6 +978,8 @@ static Exa3_Man_t * Exa3_ManAlloc( Bmc_EsPar_t * pPars, word * pTruth ) p->vUsed3 = Vec_BitStart( (1 << p->pPars->nVars) * p->pPars->nNodes * p->nObjs * p->nObjs * p->nObjs ); p->pSat = bmcg_sat_solver_start(); bmcg_sat_solver_set_nvars( p->pSat, p->iVar ); + if ( pPars->RuntimeLim ) + bmcg_sat_solver_set_runtime_limit( p->pSat, Abc_Clock() + pPars->RuntimeLim * CLOCKS_PER_SEC ); return p; } static void Exa3_ManFree( Exa3_Man_t * p ) @@ -1267,15 +1332,17 @@ void Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ) status = bmcg_sat_solver_solve( p->pSat, NULL, 0 ); if ( pPars->fVerbose && (!pPars->fUseIncr || i % 100 == 0) ) Exa3_ManPrint( p, i, iMint, Abc_Clock() - clkTotal ); - if ( status == GLUCOSE_UNSAT ) + if ( status == GLUCOSE_UNSAT || status == GLUCOSE_UNDEC ) break; iMint = Exa3_ManEval( p ); } - if ( pPars->fVerbose ) + if ( pPars->fVerbose && status != GLUCOSE_UNDEC ) Exa3_ManPrint( p, i, iMint, Abc_Clock() - clkTotal ); if ( iMint == -1 ) Exa3_ManPrintSolution( p, fCompl ); - else + else if ( status == GLUCOSE_UNDEC ) + printf( "The problem timed out after %d sec.\n", pPars->RuntimeLim ); + else printf( "The problem has no solution.\n" ); printf( "Added = %d. Tried = %d. ", p->nUsed[1], p->nUsed[0] ); Exa3_ManFree( p ); diff --git a/src/sat/bmc/bmcUnroll.c b/src/sat/bmc/bmcUnroll.c index 0ad9271..1051393 100644 --- a/src/sat/bmc/bmcUnroll.c +++ b/src/sat/bmc/bmcUnroll.c @@ -489,8 +489,8 @@ void Unr_ManTest( Gia_Man_t * pGia, int nFrames ) Gia_ManPrintStats( pFrames0, NULL ); Gia_ManPrintStats( pFrames1, NULL ); -Gia_AigerWrite( pFrames0, "frames0.aig", 0, 0 ); -Gia_AigerWrite( pFrames1, "frames1.aig", 0, 0 ); +Gia_AigerWrite( pFrames0, "frames0.aig", 0, 0, 0 ); +Gia_AigerWrite( pFrames1, "frames1.aig", 0, 0, 0 ); Gia_ManStop( pFrames0 ); Gia_ManStop( pFrames1 ); |