diff --git a/.gitignore b/.gitignore index c745dfb57..cbb424152 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,4 @@ tags /cmake /cscope +abc.history diff --git a/Makefile b/Makefile index 1da42b778..ef92eb3e4 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ MODULES := \ $(wildcard src/ext*) \ src/base/abc src/base/abci src/base/cmd src/base/io src/base/main src/base/exor \ src/base/ver src/base/wlc src/base/wln src/base/acb src/base/bac src/base/cba src/base/pla src/base/test \ - src/map/mapper src/map/mio src/map/super src/map/if \ + src/map/mapper src/map/mio src/map/super src/map/if src/map/if/acd \ src/map/amap src/map/cov src/map/scl src/map/mpm \ src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/nm \ src/misc/vec src/misc/hash src/misc/tim src/misc/bzlib src/misc/zlib \ @@ -152,7 +152,7 @@ ifdef ABC_USE_LIBSTDCXX endif $(info $(MSG_PREFIX)Using CFLAGS=$(CFLAGS)) -CXXFLAGS += $(CFLAGS) +CXXFLAGS += $(CFLAGS) -std=c++11 SRC := GARBAGE := core core.* *.stackdump ./tags $(PROG) arch_flags diff --git a/abclib.dsp b/abclib.dsp index 7433c5139..06802171f 100644 --- a/abclib.dsp +++ b/abclib.dsp @@ -3527,6 +3527,10 @@ SOURCE=.\src\map\if\ifDec16.c # End Source File # Begin Source File +SOURCE=.\src\map\if\ifDec66.c +# End Source File +# Begin Source File + SOURCE=.\src\map\if\ifDec75.c # End Source File # Begin Source File @@ -3591,6 +3595,10 @@ SOURCE=.\src\map\if\ifTune.c # End Source File # Begin Source File +SOURCE=.\src\map\if\acd\ac_wrapper.cpp +# End Source File +# Begin Source File + SOURCE=.\src\map\if\ifUtil.c # End Source File # End Group @@ -4903,6 +4911,10 @@ SOURCE=.\src\aig\gia\giaBidec.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaBound.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaCCof.c # End Source File # Begin Source File @@ -5627,6 +5639,10 @@ SOURCE=.\src\proof\cec\cecPat.c # End Source File # Begin Source File +SOURCE=.\src\proof\cec\cecProve.c +# End Source File +# Begin Source File + SOURCE=.\src\proof\cec\cecSat.c # End Source File # Begin Source File diff --git a/src/aig/aig/aigOper.c b/src/aig/aig/aigOper.c index 4fe2cd8c4..d6f02a6e0 100644 --- a/src/aig/aig/aigOper.c +++ b/src/aig/aig/aigOper.c @@ -453,7 +453,7 @@ Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ) Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 ) { int i; - assert( vNodes1->nSize > 0 && vNodes1->nSize > 0 ); + assert( vNodes1->nSize > 0 && vNodes2->nSize > 0 ); assert( vNodes1->nSize == vNodes2->nSize ); for ( i = 0; i < vNodes1->nSize; i++ ) vNodes1->pArray[i] = Aig_Not( Aig_Exor( p, (Aig_Obj_t *)vNodes1->pArray[i], (Aig_Obj_t *)vNodes2->pArray[i] ) ); diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index d4edc1237..ca413f31d 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -241,6 +241,9 @@ struct Gia_Man_t_ Vec_Int_t vSuppVars; // used variables Vec_Int_t vVarMap; // used variables Gia_Dat_t * pUData; + // retiming data + Vec_Str_t * vStopsF; + Vec_Str_t * vStopsB; }; @@ -1250,6 +1253,7 @@ 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, int fWriteNewLine ); +extern void Gia_AigerWriteS( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine, int fSkipComment ); 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 ); @@ -1527,7 +1531,8 @@ extern void Gia_ManPrintStatsMiter( Gia_Man_t * p, int fVerbose ) extern void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs ); extern void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ); extern void Gia_ManPrintNpnClasses( Gia_Man_t * p ); -extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ); +extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb, int fAssign, int fReverse ); +extern void Gia_ManDumpVerilogNand( Gia_Man_t * p, char * pFileName ); /*=== giaMem.c ===========================================================*/ extern Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ); extern void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ); @@ -1786,6 +1791,39 @@ extern void Tas_ManSatPrintStats( Tas_Man_t * p ); extern int Tas_ManSolve( Tas_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ); extern int Tas_ManSolveArray( Tas_Man_t * p, Vec_Ptr_t * vObjs ); +/*=== giaBound.c ===========================================================*/ +typedef struct Bnd_Man_t_ Bnd_Man_t; + +extern Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl, int fVerbose ); +extern void Bnd_ManStop(); + +// getter +extern int Bnd_ManGetNInternal(); +extern int Bnd_ManGetNExtra(); + +//for fraig +extern void Bnd_ManMap( int iLit, int id, int spec ); +extern void Bnd_ManMerge( int id1, int id2, int phaseDiff ); +extern void Bnd_ManFinalizeMappings(); +extern void Bnd_ManPrintMappings(); +extern Gia_Man_t* Bnd_ManStackGias( Gia_Man_t *pSpec, Gia_Man_t *pImpl ); +extern int Bnd_ManCheckCoMerged( Gia_Man_t *p ); + +// for eco +extern int Bnd_ManCheckBound( Gia_Man_t *p, int fVerbose ); +extern void Bnd_ManFindBound( Gia_Man_t *p, Gia_Man_t *pImpl ); +extern Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t *p ); +extern Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t *p ); +extern Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPatch ); +extern Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ); +extern Gia_Man_t* Bnd_ManGenPatched2( Gia_Man_t *pImpl, Gia_Man_t *pPatch, int fSkiptStrash, int fVerbose ); +extern void Bnd_ManSetEqOut( int eq ); +extern void Bnd_ManSetEqRes( int eq ); +extern void Bnd_ManPrintStats(); + +// util +extern Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec_Bit_t* vEI_phase, Vec_Bit_t* vEO_phase ); + ABC_NAMESPACE_HEADER_END diff --git a/src/aig/gia/giaAiger.c b/src/aig/gia/giaAiger.c index e3967e0ed..de94c4602 100644 --- a/src/aig/gia/giaAiger.c +++ b/src/aig/gia/giaAiger.c @@ -1217,7 +1217,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, int fWriteNewLine ) +void Gia_AigerWriteS( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine, int fSkipComment ) { int fVerbose = XAIG_VERBOSE; FILE * pFile; @@ -1557,8 +1557,10 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int // 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" ); + if ( !fSkipComment ) { + 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 ); if ( p != pInit ) { @@ -1567,6 +1569,22 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int } } +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine ) +{ + Gia_AigerWriteS( pInit, pFileName, fWriteSymbols, fCompact, fWriteNewLine, 0 ); +} + /**Function************************************************************* Synopsis [Writes the AIG in the binary AIGER format.] diff --git a/src/aig/gia/giaBound.c b/src/aig/gia/giaBound.c new file mode 100644 index 000000000..f7811967d --- /dev/null +++ b/src/aig/gia/giaBound.c @@ -0,0 +1,1374 @@ +#include "gia.h" +#include "misc/tim/tim.h" +#include "misc/vec/vecWec.h" +#include "proof/cec/cec.h" + + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Bnd_Man_t_ Bnd_Man_t; + +struct Bnd_Man_t_ +{ + int nBI; + int nBO; + int nBI_miss; + int nBO_miss; + int nInternal; + int nExtra; + int nMerged_spec; + int nMerged_impl; + + int nNode_spec; + int nNode_impl; + int nNode_patch; + int nNode_patched; + + int fVerbose; + + int combLoop_spec; + int combLoop_impl; + int eq_out; + int eq_res; + int nChoice_spec; + int nChoice_impl; + int feedthrough; + + int maxNumClass; + + Vec_Ptr_t* vBmiter2Spec; + Vec_Ptr_t* vBmiter2Impl; + Vec_Bit_t* vSpec2Impl_phase; // TODO: record all phases + + Vec_Int_t* vImpl2Bmiter; + Vec_Int_t* vSpec2Bmiter; + + Vec_Int_t* vBI; + Vec_Int_t* vBO; + Vec_Int_t* vEI_spec; + Vec_Int_t* vEO_spec; + Vec_Int_t* vEI_impl; + Vec_Int_t* vEO_impl; + Vec_Bit_t* vEI_phase; + Vec_Bit_t* vEO_phase; + +}; + +Bnd_Man_t* pBnd = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +void Bnd_ManSetEqOut( int eq ) { pBnd -> eq_out = eq;} +void Bnd_ManSetEqRes( int eq ) { pBnd -> eq_res = eq;} + +Vec_Int_t* Bnd_ManSpec2Impl( int id ) { return (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Impl, Vec_IntEntry( pBnd->vSpec2Bmiter, id ) ); } +int Bnd_ManSpec2ImplNum( int id ) { return Vec_IntSize( (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Impl, Vec_IntEntry( pBnd->vSpec2Bmiter, id ) ) ); } + +Vec_Int_t* Bnd_ManImpl2Spec( int id ) { return (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Spec, Vec_IntEntry( pBnd->vImpl2Bmiter, id ) ); } +int Bnd_ManImpl2SpecNum( int id ) { return Vec_IntSize( (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Spec, Vec_IntEntry( pBnd->vImpl2Bmiter, id ) ) ); } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl, int fVerbose ) +{ + int i; + Bnd_Man_t* p = ABC_CALLOC( Bnd_Man_t, 1 ); + + p -> maxNumClass = Gia_ManCiNum( pSpec ) + Gia_ManAndNotBufNum(pSpec) + Gia_ManAndNum(pImpl) + 2 + Gia_ManCoNum(pSpec) * 2; + // one for constant node and one for dummy + + p -> vBmiter2Spec = Vec_PtrAlloc( p -> maxNumClass ); + p -> vBmiter2Impl = Vec_PtrAlloc( p -> maxNumClass ); + Vec_PtrFill( p -> vBmiter2Spec, p -> maxNumClass, 0 ); + Vec_PtrFill( p -> vBmiter2Impl, p -> maxNumClass, 0 ); + for( i = 0; i < Vec_PtrSize( p -> vBmiter2Impl ); i ++ ) + { + Vec_PtrSetEntry( p -> vBmiter2Spec, i, Vec_IntAlloc(1) ); + Vec_PtrSetEntry( p -> vBmiter2Impl, i, Vec_IntAlloc(1) ); + } + + p -> vSpec2Impl_phase = Vec_BitAlloc( Gia_ManObjNum(pSpec) ); + Vec_BitFill( p -> vSpec2Impl_phase, Gia_ManObjNum(pSpec), 0 ); + + p -> vImpl2Bmiter = Vec_IntAlloc( Gia_ManObjNum(pImpl) ); + Vec_IntFill( p -> vImpl2Bmiter, Gia_ManObjNum(pImpl), p -> maxNumClass - 1 ); + p -> vSpec2Bmiter = Vec_IntAlloc( Gia_ManObjNum(pSpec) ); + Vec_IntFill( p -> vSpec2Bmiter, Gia_ManObjNum(pSpec), p -> maxNumClass - 1); + + p -> vBI = Vec_IntAlloc(16); + p -> vBO = Vec_IntAlloc(16); + p -> vEI_spec = Vec_IntAlloc(16); + p -> vEO_spec = Vec_IntAlloc(16); + p -> vEI_impl = Vec_IntAlloc(16); + p -> vEO_impl = Vec_IntAlloc(16); + p -> vEI_phase = Vec_BitAlloc(16); + p -> vEO_phase = Vec_BitAlloc(16); + + p -> nNode_spec = Gia_ManAndNum(pSpec) - Gia_ManBufNum(pSpec); + p -> nNode_impl = Gia_ManAndNum(pImpl); + p -> nNode_patch = 0; + p -> nNode_patched = 0; + + p -> fVerbose = fVerbose; + + p -> combLoop_spec = 0; + p -> combLoop_impl = 0; + p -> eq_out = 0; + p -> eq_res = 0; + + p -> nChoice_spec = 0; + p -> nChoice_impl = 0; + p -> feedthrough = 0; + + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bnd_ManStop() +{ + assert(pBnd); + + Vec_PtrFree( pBnd-> vBmiter2Spec ); + Vec_PtrFree( pBnd-> vBmiter2Impl ); + Vec_BitFree( pBnd-> vSpec2Impl_phase ); + Vec_IntFree( pBnd-> vImpl2Bmiter ); + Vec_IntFree( pBnd-> vSpec2Bmiter ); + + Vec_IntFree( pBnd->vBI ); + Vec_IntFree( pBnd->vBO ); + Vec_IntFree( pBnd->vEI_spec ); + Vec_IntFree( pBnd->vEO_spec ); + Vec_IntFree( pBnd->vEI_impl ); + Vec_IntFree( pBnd->vEO_impl ); + Vec_BitFree( pBnd->vEI_phase ); + Vec_BitFree( pBnd->vEO_phase ); + + ABC_FREE( pBnd ); +} + +int Bnd_ManGetNInternal() { assert(pBnd); return pBnd -> nInternal; } +int Bnd_ManGetNExtra() { assert(pBnd); return pBnd -> nExtra; } + +void Bnd_ManMap( int iLit, int id, int spec ) +{ + + if ( spec ) + { + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry( pBnd -> vBmiter2Spec, iLit >> 1), id ); + Vec_BitSetEntry( pBnd -> vSpec2Impl_phase, id, iLit & 1 ); + } + else + { + assert( (iLit & 1) == 0 ); + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry( pBnd -> vBmiter2Impl, iLit >> 1), id ); + } +} + +void Bnd_ManMerge( int id_repr, int id_obj, int phaseDiff ) +{ + + + Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; + Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; + Vec_Bit_t* vSpec2Impl_phase = pBnd -> vSpec2Impl_phase; + int id, i; + + Vec_Int_t *vIds_spec_repr, *vIds_impl_repr, *vIds_spec_obj, *vIds_impl_obj; + + vIds_spec_repr = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, id_repr ); + vIds_impl_repr = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, id_repr ); + vIds_spec_obj = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, id_obj ); + vIds_impl_obj = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, id_obj ); + + Vec_IntForEachEntry( vIds_spec_obj, id, i ) + { + Vec_IntPush(vIds_spec_repr, id); + } + Vec_IntForEachEntry( vIds_impl_obj, id, i ) + { + Vec_IntPush(vIds_impl_repr, id); + } + + // handle spec2impl phase + if ( phaseDiff ) + { + Vec_IntForEachEntry( vIds_spec_obj, id, i ) + { + Vec_BitSetEntry( vSpec2Impl_phase, id, !Vec_BitEntry(vSpec2Impl_phase, id) ); + // printf( "spec id %d's phase set to %d\n", id, Vec_BitEntry(vSpec2Impl_phase, id) ); + } + } + + Vec_IntClear(vIds_spec_obj); + Vec_IntClear(vIds_impl_obj); + +} +void Bnd_ManFinalizeMappings() +{ + + Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; + Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; + + Vec_Int_t *vSpec, *vImpl; + int i, j, id; + + pBnd -> nMerged_impl = 0; + pBnd -> nMerged_spec = 0; + + + for( i = 0; i < Vec_PtrSize(vBmiter2Spec); i++ ) + { + vSpec = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, i ); + vImpl = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, i ); + + Vec_IntForEachEntry( vSpec, id, j ) + { + // vSpec2Bmiter + Vec_IntSetEntry( pBnd->vSpec2Bmiter, id, i ); + } + + Vec_IntForEachEntry( vImpl, id, j ) + { + // vImpl2Bmiter + Vec_IntSetEntry( pBnd->vImpl2Bmiter, id, i ); + } + + // count number of nodes merged into the same circuit + if ( Vec_IntSize(vSpec) != 0 ) + { + pBnd->nMerged_spec += Vec_IntSize(vSpec) - 1; + } + if ( Vec_IntSize(vImpl) != 0 ) + { + pBnd->nMerged_impl += Vec_IntSize(vImpl) - 1; + } + } + +} +void Bnd_ManPrintMappings() +{ + Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; + Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; + Vec_Int_t* vIds_spec, *vIds_impl; + int k, id; + for( int j=0; j < Vec_PtrSize(vBmiter2Spec); j++ ) + { + printf("node %d: ", j); + vIds_spec = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, j); + vIds_impl = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, j); + Vec_IntForEachEntry(vIds_spec, id, k) + printf("%d ", id); + printf("| "); + Vec_IntForEachEntry(vIds_impl, id, k) + printf("%d ", id); + printf("\n"); + } + +} + +void Bnd_ManPrintBound() +{ + + // printf("%d nodes merged in spec\n", pBnd ->nMerged_spec - Vec_IntSize(pBnd->vBI) - Vec_IntSize(pBnd->vBO) ); + // printf("%d nodes merged in impl\n", pBnd ->nMerged_impl ); + printf("BI spec:\t"); Vec_IntPrint(pBnd -> vBI); + printf("BO spec:\t"); Vec_IntPrint(pBnd -> vBO); + printf("EI spec:\t"); Vec_IntPrint(pBnd -> vEI_spec); + printf("EI impl:\t"); Vec_IntPrint(pBnd -> vEI_impl); + printf("EI phase:\t"); Vec_BitPrint(pBnd -> vEI_phase); + printf("EO spec:\t"); Vec_IntPrint(pBnd -> vEO_spec); + printf("EO impl:\t"); Vec_IntPrint(pBnd -> vEO_impl); + printf("EO phase:\t"); Vec_BitPrint(pBnd -> vEO_phase); +} + +void Bnd_ManPrintStats() +{ + Bnd_Man_t* p = pBnd; + + + printf("\nSTATS\n"); + + int warning = 0; + if ( p->nChoice_spec > 0 ) + { + warning = 1; + printf("WARNING: multiple equiv nodes on the boundary of spec\n"); + } + if ( p->nChoice_impl > 0 ) + { + warning = 1; + printf("WARNING: multiple equiv nodes on the boundary of impl\n"); + } + + printf("The outsides of spec and impl are %sEQ.\n", p->eq_out ? "" : "NOT " ); + printf("The patched impl is %sEQ. to spec (and impl)\n", p->eq_res ? "" : "NOT " ); + + // #internal + // nBI, nBO + // nBI_miss, nBO_miss + // nEI, nEO, nExtra + // #spec, #impl, #patched + // combLoop_spec, combLoop_impl + // #choice_impl + // #choice_spec + // #feedthrough + // warning (may be neq) + // eq_out, eq_res + + printf("\nRESULT\n"); + printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + p->nInternal, + p->nBI, p->nBO, + p->nBI_miss, p->nBO_miss, + Vec_IntSize(p->vEI_spec), Vec_IntSize(p->vEO_spec), p->nExtra, + p->nNode_spec, p->nNode_impl, p->nNode_patched, + p->combLoop_spec, p->combLoop_impl, + p->nChoice_impl, + p->nChoice_spec, + warning, + p->eq_out, p->eq_res + ); + + printf("#Choice Spec\t%d\n", p->nChoice_spec); + printf("#Choice Impl\t%d\n", p->nChoice_impl); + + + +} + +/**Function************************************************************* + + Synopsis [] + + Description [check if the given boundary is valid. Return 0 if + the boundary is invalid. Return k if the boundary is valid and + there're k boundary inputs. + Can be called even if Bnd_Man_t is not created] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bnd_ManCheckBound( Gia_Man_t * p, int fVerbose ) +{ + int i; + Gia_Obj_t *pObj; + int valid = 1; + int nBI = 0, nBO = 0, nInternal = 0; + + if ( fVerbose ) printf( "Checking boundary... \n"); + + Vec_Int_t *vPath; + vPath = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( vPath, Gia_ManObjNum(p), 0 ); + int path; + + Gia_ManForEachObjReverse1( p , pObj, i ) + { + if ( Gia_ObjIsCo( pObj ) ) + { + Vec_IntSetEntry( vPath, Gia_ObjId( p, pObj ), 1 ); + } + + path = Vec_IntEntry( vPath, Gia_ObjId(p, pObj) ); + // printf("path = %d\n", path); + + if ( path >= 8 ) + { + valid = 0; + printf("there're more than 2 bufs in a path\n"); + break; + } + + + if( Gia_ObjIsBuf( pObj ) ) + { + Vec_IntSetEntry( vPath, Gia_ObjId( p, Gia_ObjFanin0( pObj ) ), Vec_IntEntry( vPath, Gia_ObjId(p, Gia_ObjFanin0( pObj ) ) ) | path << 1 ); + if ( path == 1 ) // boundary input + { + // TODO: record BIs here since they may not be in the first n buffers + nBO ++; + } + } + else if ( Gia_ObjFaninNum( p, pObj ) >= 1 ) + { + Vec_IntSetEntry( vPath, Gia_ObjId( p, Gia_ObjFanin0( pObj ) ), Vec_IntEntry( vPath, Gia_ObjId(p, Gia_ObjFanin0( pObj ) ) ) | path ); + if ( Gia_ObjFaninNum( p, pObj ) >= 2 ) + { + assert( Gia_ObjFaninNum( p, pObj ) <= 2 ); + Vec_IntSetEntry( vPath, Gia_ObjId( p, Gia_ObjFanin1( pObj ) ), Vec_IntEntry( vPath, Gia_ObjId(p, Gia_ObjFanin1( pObj ) ) ) | path ); + } + if ( path == 2 ) // inside boundary + { + // TODO: record BIs here since they may not be in the first n buffers + nInternal ++; + } + } + else // PI or const, check validity + { + if ( (Vec_IntEntry( vPath, Gia_ObjId(p, pObj) ) | 5) != 5 ) + { + valid = 0; + printf("incorrect buf number at pi %d\n", Vec_IntEntry(vPath, Gia_ObjId(p, pObj)) ); + break; + } + } + } + + nBI = Gia_ManBufNum(p) - nBO; + + if ( !valid ) + { + printf("invalid boundary\n"); + return 0; + } + else if ( nBI == 0 ) + { + printf("no boundary\n"); + return 0; + } + else + { + if ( fVerbose ) + { + printf("valid boundary ("); + printf("#BI = %d\t#BO = %d\t", nBI, Gia_ManBufNum(p)- nBI); + printf("#Internal = %d)\n", nInternal ); + } + if ( pBnd ) + { + pBnd -> nBI = nBI; + pBnd -> nBO = nBO; + pBnd -> nInternal = nInternal; + } + return nBI; + } +} + + +int Bnd_CheckFlagRec( Gia_Man_t *p, Gia_Obj_t *pObj, Vec_Int_t* vFlag ) +{ + int id = Gia_ObjId(p, pObj); + if ( Vec_IntEntry(vFlag, id) == 1 ) return 1; + if ( Vec_IntEntry(vFlag, id) == 2 ) return 0; + + Vec_IntSetEntry(vFlag, id, 1); + + int ret = 1; + for( int i = 0; i < Gia_ObjFaninNum(p, pObj); i++ ) + { + if ( !Bnd_CheckFlagRec( p, Gia_ObjFanin(pObj, i), vFlag ) ) + { + ret = 0; + break; + } + } + return ret; + +} + +/**Function************************************************************* + + Synopsis [] + + Description [check if combnational loop exist in the extended boundary] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bnd_ManCheckExtBound( Gia_Man_t * p, Vec_Int_t *vEI, Vec_Int_t *vEO ) +{ + Vec_Int_t *vFlag = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( vFlag, Gia_ManObjNum(p), 0 ); + int success = 1; + int i, id; + + Vec_IntForEachEntry( vEO, id, i ) + { + Vec_IntSetEntry( vFlag, id, 2 ); + } + + Vec_IntForEachEntry( vEI, id, i ) + { + if ( Vec_IntEntry(vFlag, id) == 2 ) continue; // BI connected to BO directly + + if ( !Bnd_CheckFlagRec( p, Gia_ManObj(p, id), vFlag ) ) + { + success = 0; + break; + } + } + + + Vec_IntFree(vFlag); + return success; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [find the extended boundary in spec + and compute the corresponding boundary in impl] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) +{ + Vec_Int_t *vFlag; + Vec_Ptr_t *vQ; + Gia_Obj_t *pObj; + int i, j, id, cnt; + + Vec_Int_t *vAI = Vec_IntAlloc(16); + Vec_Int_t *vAO = Vec_IntAlloc(16); + + Vec_Bit_t *vSpec2Impl_phase = pBnd -> vSpec2Impl_phase; + Vec_Int_t *vBI = pBnd -> vBI; + Vec_Int_t *vBO = pBnd -> vBO; + Vec_Int_t *vEI_spec = pBnd -> vEI_spec; + Vec_Int_t *vEO_spec = pBnd -> vEO_spec; + Vec_Int_t *vEI_impl = pBnd -> vEI_impl; + Vec_Int_t *vEO_impl = pBnd -> vEO_impl; + Vec_Bit_t *vEI_phase = pBnd -> vEI_phase; + Vec_Bit_t *vEO_phase = pBnd -> vEO_phase; + + + // prepare to compute extended boundary + vQ = Vec_PtrAlloc(16); + vFlag = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( vFlag, Gia_ManObjNum(p), 0 ); + + Gia_ManStaticFanoutStart(p); + + // save bo, bi + cnt = 0; + Gia_ManForEachBuf(p, pObj, i) + { + if ( cnt < pBnd -> nBI ) + { + Vec_IntPush( vBI, Gia_ObjId(p, Gia_ObjFanin0(pObj) ) ); + } + else + { + Vec_IntPush( vBO, Gia_ObjId(p, pObj) ); + } + cnt++; + } + + // compute EO, travse with flag 1 + Vec_IntForEachEntry( vBO, id, i ) + { + if ( Bnd_ManSpec2ImplNum(id) == 0 ) // BO not matched + { + Vec_PtrPush( vQ, Gia_ManObj(p, id) ); + } + else + { + Vec_IntPush(vEO_spec, id); + } + } + if ( pBnd -> fVerbose ) printf("%d BO doesn't match. ", Vec_PtrSize(vQ) ); + pBnd -> nBO_miss = Vec_PtrSize(vQ); + + int cnt_extra = - Vec_PtrSize(vQ); + while( Vec_PtrSize(vQ) > 0 ) + { + pObj = (Gia_Obj_t *)Vec_PtrPop(vQ); + id = Gia_ObjId( p, pObj ); + + if ( Vec_IntEntry( vFlag, id ) == 1 ) continue; + Vec_IntSetEntry( vFlag, id, 1 ); + + // printf("%d\n", id); + + if ( Bnd_ManSpec2ImplNum(id) != 0 ) // matched + { + Vec_IntPush( vEO_spec, id ); + Vec_IntPush( vAO, id ); + } + else + { + for( j = 0; j < Gia_ObjFanoutNum(p, pObj); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanout(p, pObj, j) ); + // printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanout(p1, pObj, j) ) ); + } + } + } + // printf("%d AO found with %d extra nodes\n", Vec_IntSize(vAO) , cnt_extra ); + if ( pBnd -> fVerbose ) printf("%d AO found\n", Vec_IntSize(vAO) ); + + + // mark TFOC of BO with flag 1 to prevent them from being selected into EI + // stop at CO + Vec_IntForEachEntry( pBnd -> vBO, id, i ) + { + Vec_PtrPush( vQ, Gia_ManObj(p, id) ); + } + Vec_IntForEachEntry( vFlag, id, i ) + { + Vec_IntSetEntry( vFlag, id, 0 ); + } + while( Vec_PtrSize(vQ) > 0 ) + { + pObj = (Gia_Obj_t *)Vec_PtrPop(vQ); + id = Gia_ObjId( p, pObj ); + + if ( Vec_IntEntry( vFlag, id ) == 1 ) continue; + Vec_IntSetEntry( vFlag, id, 1 ); + + for( j = 0; j < Gia_ObjFanoutNum(p, pObj); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanout(p, pObj, j) ); + } + } + + + + // compute EI, traverse with flag 2 + + // add unmatched BI to queue + Vec_IntForEachEntry( vBI, id, i ) + { + if ( Bnd_ManSpec2ImplNum(id) == 0 ) // BO not matched + { + Vec_PtrPush( vQ, Gia_ManObj(p, id) ); + } + else + { + Vec_IntPush(vEI_spec, id); + } + } + if ( pBnd -> fVerbose ) printf("%d BI doesn't match. ", Vec_PtrSize(vQ) ); + pBnd -> nBI_miss = Vec_PtrSize(vQ); + cnt_extra -= Vec_PtrSize(vQ); + + // add AO to queue + Vec_IntForEachEntry( vAO, id, i ) + { + Vec_PtrPush( vQ, Gia_ManObj(p, id) ); + } + + // set flag 2 for BO + Vec_IntForEachEntry( vBO, id, i ) + { + Vec_IntSetEntry( vFlag, id, 2 ); + } + + // traverse down from AI and unmatched BI + while( Vec_PtrSize(vQ) > 0 ) + { + pObj = (Gia_Obj_t *)Vec_PtrPop(vQ); + id = Gia_ObjId( p, pObj ); + + if ( Vec_IntEntry( vFlag, id ) == 2 ) continue; + cnt_extra ++; + + // printf("%d\n", id); + + if ( Vec_IntEntry(vFlag, id) != 1 && Bnd_ManSpec2ImplNum(id) != 0 ) // matched + { + Vec_IntPush( vEI_spec, id ); + Vec_IntPush( vAI, id ); + } + else + { + for( j = 0; j < Gia_ObjFaninNum(p, pObj); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanin(pObj, j) ); + // printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanout(p1, pObj, j) ) ); + } + } + + Vec_IntSetEntry( vFlag, id, 2 ); + } + if ( pBnd -> fVerbose ) printf("%d AI found with %d extra nodes in total\n", Vec_IntSize(vAI) , cnt_extra ); + pBnd -> nExtra = cnt_extra; + + + // gen vEI_impl, vEO_impl, vEI_phase, vEO_phase + Vec_IntForEachEntry( vEI_spec, id, i ) + { + Vec_IntPush( vEI_impl, Vec_IntEntry( Bnd_ManSpec2Impl(id) , 0 ) ); + Vec_BitPush( vEI_phase, Vec_BitEntry( vSpec2Impl_phase, id ) ); + } + Vec_IntForEachEntry( vEO_spec, id, i ) + { + Vec_IntPush( vEO_impl, Vec_IntEntry( Bnd_ManSpec2Impl(id), 0 ) ); + Vec_BitPush( vEO_phase, Vec_BitEntry( vSpec2Impl_phase, id ) ); + } + + + // count number of choice of boundary + Vec_IntForEachEntry( vEO_spec, id, i ) + { + pBnd -> nChoice_impl += Bnd_ManSpec2ImplNum( id ) - 1; + } + Vec_IntForEachEntry( vEO_impl, id, i ) + { + pBnd -> nChoice_spec += Bnd_ManImpl2SpecNum( id ) - 1; + } + + // print + if ( pBnd -> fVerbose ) + { + printf("#EI = %d\t#EO = %d\t#Extra Node = %d\n", Vec_IntSize(vEI_spec) , Vec_IntSize(vEO_spec), cnt_extra ); + Bnd_ManPrintBound(); + } + + // check boundary has comb loop + if ( !Bnd_ManCheckExtBound( p, vEI_spec, vEO_spec ) ) + { + + printf("Combinational loop exist\n"); + pBnd -> combLoop_spec = 1; + + } + + + // clean up + Vec_IntFree(vAI); + Vec_IntFree(vAO); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [create circuit with the boundary changed to CI/CO] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec_Bit_t* vEI_phase, Vec_Bit_t* vEO_phase ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + Vec_Int_t * vValue; + int i, id, lit; + + // check if the boundary has loop (EO cannot be in the TFC of EI ) + if ( !Bnd_ManCheckExtBound( p, vEI, vEO ) ) + { + printf("Combinational loop exist\n"); + pBnd -> combLoop_impl = 1; + return 0; + } + + // initialize + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew -> pName = ABC_ALLOC( char, strlen(p->pName)+10); + sprintf( pNew -> pName, "%s_out", p -> pName ); + Gia_ManHashStart( pNew ); + Gia_ManFillValue(p); + Gia_ManConst0(p) -> Value = 0; + + + // record the original value for eo + vValue = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( vValue, Gia_ManObjNum(p), -1 ); + + // create ci for ci and eo + Gia_ManForEachCi( p, pObj, i ) + { + pObj -> Value = Gia_ManAppendCi( pNew ); + } + Vec_IntForEachEntry( vEO, id, i ) + { + if( Gia_ManObj(p, id) -> Value != ~0 ) + { + Vec_IntSetEntry( vValue, id, Gia_ManObj(p, id) -> Value ); + } + Gia_ManObj( p, id ) -> Value = Gia_ManAppendCi(pNew); + if ( vEO_phase && Vec_BitEntry( vEO_phase, i ) ) + { + Gia_ManObj( p, id ) -> Value ^= 1; + } + } + + // add aig nodes + Gia_ManForEachAnd(p, pObj, i) + { + if ( pObj -> Value != ~0 ) continue; + pObj -> Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + + // create co for co and ei + Gia_ManForEachCo(p, pObj, i) + { + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Vec_IntForEachEntry( vEI, id, i ) + { + pObj = Gia_ManObj(p, id); + // lit = Gia_ManObj(p, id)->Value; + if ( Gia_ObjIsAnd(pObj) ) lit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + { + assert(Gia_ObjIsCi(pObj) || Gia_ObjIsConst0(pObj)); + if ( Vec_IntEntry(vValue, id) != -1 ) + { + lit = Vec_IntEntry( vValue, id ); // EI at PI and EI merged with EO + } + else { + lit = pObj -> Value; // EI at PI + } + } + if ( vEI_phase && Vec_BitEntry( vEI_phase, i ) ) lit ^= 1; + Gia_ManAppendCo( pNew, lit ); + } + + // clean up + Vec_IntFree( vValue ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; + +} + +Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t* p ) +{ + if ( pBnd -> fVerbose ) printf("Generating spec_out with given boundary.\n"); + Gia_Man_t *pNew = Bnd_ManCutBoundary( p, pBnd->vEI_spec, pBnd->vEO_spec, 0, 0 ); + return pNew; +} +Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t* p) +{ + if ( pBnd -> fVerbose ) printf("Generating impl_out with given boundary.\n"); + Gia_Man_t *pNew = Bnd_ManCutBoundary( p, pBnd->vEI_impl, pBnd->vEO_impl, pBnd->vEI_phase, pBnd->vEO_phase ); + if (!pNew) pBnd -> combLoop_impl = 1; + return pNew; +} + +void Bnd_AddNodeRec( Gia_Man_t *p, Gia_Man_t *pNew, Gia_Obj_t *pObj, int fSkipStrash ) +{ + // TODO does this mean constant zero node? + if ( pObj -> Value != ~0 ) return; + + for( int i = 0; i < Gia_ObjFaninNum(p, pObj); i++ ) + { + Bnd_AddNodeRec( p, pNew, Gia_ObjFanin(pObj, i), fSkipStrash ); + } + + if ( Gia_ObjIsAnd(pObj) ) + { + if ( fSkipStrash ) + { + if ( Gia_ObjIsBuf(pObj) ) pObj -> Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else pObj -> Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + else + { + pObj -> Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + } + else + { + assert( Gia_ObjIsCo(pObj) ); + // if ( Gia_ObjIsCi(pObj) ) printf("Ci with value ~0 encountered (id = %d)\n", Gia_ObjId(p, pObj) ); + pObj -> Value = Gia_ObjFanin0Copy(pObj); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [perform ECO directly (not used)] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPatch ) +{ + + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, id, cnt; + Vec_Int_t *vBI_patch, *vBO_patch; + + pBnd -> nNode_patch = Gia_ManAndNotBufNum( pPatch ); + + pNew = Gia_ManStart( Gia_ManObjNum(pOut) + Gia_ManObjNum( pSpec ) + Gia_ManObjNum(pPatch) ); + pNew -> pName = ABC_ALLOC( char, strlen(pOut->pName)+3); + sprintf( pNew -> pName, "%s_p", pOut -> pName ); + Gia_ManHashStart( pNew ); + Gia_ManFillValue(pOut); + Gia_ManFillValue(pSpec); + Gia_ManFillValue(pPatch); + Gia_ManConst0(pOut)->Value = 0; + Gia_ManConst0(pSpec)->Value = 0; + Gia_ManConst0(pPatch)->Value = 0; + + // get bi and bo in patch + cnt = 0; + vBI_patch = Vec_IntAlloc(16); + vBO_patch = Vec_IntAlloc(16); + Gia_ManForEachBuf( pPatch, pObj, i ) + { + if ( cnt < pBnd -> nBI ) + { + Vec_IntPush( vBI_patch, Gia_ObjId( pPatch, pObj ) ); + } + else + { + + Vec_IntPush( vBO_patch, Gia_ObjId( pPatch, pObj ) ); + } + cnt ++; + } + assert( Vec_IntSize( vBI_patch ) == Vec_IntSize(pBnd->vBI) ); + assert( Vec_IntSize( vBO_patch ) == Vec_IntSize(pBnd->vBO) ); + + + // add Impl (real) PI + for ( i = 0; i < Gia_ManCiNum(pSpec); i++ ) + { + pObj = Gia_ManCi(pOut, i); + pObj -> Value = Gia_ManAppendCi( pNew ); + } + + // add Impl EI to CI + // printf("adding EI to CI in Impl\n"); + for ( i = 0; i < Vec_IntSize( pBnd -> vEI_spec ); i++ ) + { + pObj = Gia_ManCo(pOut, i + Gia_ManCoNum(pSpec) ); + Bnd_AddNodeRec( pOut, pNew, pObj, 0 ); + + // set Spec EI + Gia_ManObj( pSpec, Vec_IntEntry(pBnd -> vEI_spec, i) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Spec BI to EI + // printf("adding BI to EI in Spec\n"); + Vec_IntForEachEntry( pBnd -> vBI, id, i ) + { + pObj = Gia_ManObj( pSpec, id ); + Bnd_AddNodeRec( pSpec, pNew, pObj, 0 ); + + // set patch bi + Gia_ManObj( pPatch, Vec_IntEntry( vBI_patch, i) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Patch BO to BI + // printf("adding BO to BI in Patch\n"); + Vec_IntForEachEntry( vBO_patch, id, i ) + { + pObj = Gia_ManObj( pPatch, id ); + Bnd_AddNodeRec( pPatch, pNew, pObj, 0 ); + + // set spec bo + Gia_ManObj( pSpec, Vec_IntEntry( pBnd -> vBO, i) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Spec EO to BO + // printf("adding EO to BO in Spec\n"); + Vec_IntForEachEntry( pBnd -> vEO_spec, id, i ) + { + pObj = Gia_ManObj( pSpec, id ); + Bnd_AddNodeRec( pSpec, pNew, pObj, 0 ); + + // set impl EO (PI) + Gia_ManCi( pOut, i + Gia_ManCiNum(pSpec) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Impl (real) PO to EO + // printf("adding CO to EO in Impl\n"); + for ( i = 0; i < Gia_ManCoNum(pSpec); i++ ) + { + pObj = Gia_ManCo( pOut, i ); + Bnd_AddNodeRec( pOut, pNew, pObj, 0 ); + Gia_ManAppendCo( pNew, pObj->Value ); + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + + // clean up + Vec_IntFree( vBI_patch ); + Vec_IntFree( vBO_patch ); + Gia_ManHashStop( pNew ); + + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + pBnd -> nNode_patched = Gia_ManAndNum( pNew ); + + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [recover bounadry] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ) +{ + + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, id; + + pNew = Gia_ManStart( Gia_ManObjNum(pOut) + Gia_ManObjNum( pSpec ) ); + pNew -> pName = ABC_ALLOC( char, strlen(pOut->pName)+3); + sprintf( pNew -> pName, "%s_p", pOut -> pName ); + + Gia_ManFillValue(pOut); + Gia_ManFillValue(pSpec); + Gia_ManConst0(pOut)->Value = 0; + Gia_ManConst0(pSpec)->Value = 0; + + + // add Impl (real) PI + for ( i = 0; i < Gia_ManCiNum(pSpec); i++ ) + { + pObj = Gia_ManCi(pOut, i); + pObj -> Value = Gia_ManAppendCi( pNew ); + } + + // add Impl EI to CI + // printf("adding EI to CI in Impl\n"); + for ( i = 0; i < Vec_IntSize( pBnd -> vEI_spec ); i++ ) + { + pObj = Gia_ManCo(pOut, i + Gia_ManCoNum(pSpec) ); + Bnd_AddNodeRec( pOut, pNew, pObj, 1 ); + + // set Spec EI + Gia_ManObj( pSpec, Vec_IntEntry(pBnd -> vEI_spec, i) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Spec EO to EI + // add BI -> BO -> EO to maintain the order of bufs + // Vec_IntForEachEntry( pBnd -> vBI, id, i ) + // { + // pObj = Gia_ManObj( pSpec, id ); + // Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + // } + // Vec_IntForEachEntry( pBnd -> vBO, id, i ) + // { + // pObj = Gia_ManObj( pSpec, id ); + // Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + // } + Gia_ManForEachBuf( pSpec, pObj, i ) + { + Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + } + Vec_IntForEachEntry( pBnd -> vEO_spec, id, i ) + { + pObj = Gia_ManObj( pSpec, id ); + Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + + // set impl EO (PI) + Gia_ManCi( pOut, i + Gia_ManCiNum(pSpec) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Impl (real) PO to EO + // printf("adding CO to EO in Impl\n"); + for ( i = 0; i < Gia_ManCoNum(pSpec); i++ ) + { + pObj = Gia_ManCo( pOut, i ); + Bnd_AddNodeRec( pOut, pNew, pObj, 1 ); + Gia_ManAppendCo( pNew, pObj->Value ); + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + + // clean up + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + pBnd -> nNode_patched = Gia_ManAndNum( pNew ); + + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [perform eco with recovered boundary. + bnd_man is not used] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t* Bnd_ManGenPatched2( Gia_Man_t *pImpl, Gia_Man_t *pPatch, int fSkipStrash, int fVerbose ) +{ + + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, nBI, nBI_patch, cnt; + Vec_Int_t* vLit; + + + // check boundary first + nBI = Bnd_ManCheckBound( pImpl, fVerbose ); + nBI_patch = Bnd_ManCheckBound( pPatch, fVerbose ); + if ( 0 == nBI_patch || Gia_ManBufNum(pImpl) != Gia_ManBufNum(pPatch) || nBI != nBI_patch ) + { + Abc_Print( -1, "Abc_CommandAbc9StrEco(): The given boundary is invalid.\n" ); + return 0; + } + + // prepare new network + pNew = Gia_ManStart( Gia_ManObjNum(pImpl) + Gia_ManObjNum( pPatch ) ); + pNew -> pName = ABC_ALLOC( char, strlen(pImpl->pName)+3); + sprintf( pNew -> pName, "%s_p", pImpl -> pName ); + if ( !fSkipStrash ) + { + Gia_ManHashAlloc( pNew ); + } + Gia_ManFillValue(pImpl); + Gia_ManFillValue(pPatch); + Gia_ManConst0(pImpl)->Value = 0; + Gia_ManConst0(pPatch)->Value = 0; + + vLit = Vec_IntAlloc( Gia_ManBufNum(pImpl) ); + + // add Impl (real) CI + Gia_ManForEachCi( pImpl, pObj, i ) + { + pObj -> Value = Gia_ManAppendCi( pNew ); + } + + // add Impl BI to CI + cnt = 0; + Gia_ManForEachBuf( pImpl, pObj, i ) + { + Bnd_AddNodeRec( pImpl, pNew, pObj, fSkipStrash ); + Vec_IntPush( vLit, pObj -> Value ); + cnt ++; + if ( cnt >= nBI ) break; + } + + // set BI in patch + // add patch BO to BI + cnt = 0; + Gia_ManForEachBuf( pPatch, pObj, i ) + { + if ( cnt < nBI ) + { + pObj -> Value = Vec_IntEntry( vLit, cnt ); + } + else + { + Bnd_AddNodeRec( pPatch, pNew, pObj, fSkipStrash ); + Vec_IntPush( vLit, pObj -> Value ); + } + cnt ++; + if ( cnt == nBI ) Vec_IntClear( vLit ); + } + + // set BO in impl + cnt = 0; + Gia_ManForEachBuf( pImpl, pObj, i ) + { + cnt ++; + if ( cnt <= nBI) continue; + pObj -> Value = Vec_IntEntry( vLit, cnt-nBI-1 ); + } + + // add impl CO to BO + Gia_ManForEachCo( pImpl, pObj, i ) + { + Bnd_AddNodeRec( pImpl, pNew, pObj, fSkipStrash ); + Gia_ManAppendCo( pNew, pObj -> Value ); + } + + // clean up + if ( !fSkipStrash ) + { + Gia_ManHashStop( pNew ); + } + Vec_IntFree( vLit ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + return pNew; +} + + +Gia_Man_t* Bnd_ManStackGias( Gia_Man_t *pSpec, Gia_Man_t *pImpl ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + + int i, iLit; + if ( Gia_ManBufNum(pSpec) == 0 ) { + printf( "The spec AIG should have a boundary.\n" ); + return NULL; + } + if ( Gia_ManBufNum(pImpl) != 0 ) { + printf( "The impl AIG should have no boundary.\n" ); + return NULL; + } + + assert( Gia_ManBufNum(pSpec) > 0 ); + assert( Gia_ManBufNum(pImpl) == 0 ); + assert( Gia_ManRegNum(pSpec) == 0 ); + assert( Gia_ManRegNum(pImpl) == 0 ); + assert( Gia_ManCiNum(pSpec) == Gia_ManCiNum(pImpl) ); + assert( Gia_ManCoNum(pSpec) == Gia_ManCoNum(pImpl) ); + + pNew = Gia_ManStart( Gia_ManObjNum(pSpec) + Gia_ManObjNum(pImpl) ); + pNew->pName = ABC_ALLOC( char, strlen(pSpec->pName) + 10 ); + sprintf( pNew->pName, "%s_stack", pSpec->pName ); + + Gia_ManHashStart( pNew ); + Gia_ManConst0(pSpec)->Value = 0; + Gia_ManConst0(pImpl)->Value = 0; + + for( int i = 0; i < Gia_ManCiNum(pSpec); i++ ) + { + int iLit = Gia_ManCi(pSpec, i)->Value = Gia_ManCi(pImpl, i) -> Value = Gia_ManAppendCi(pNew); + + pObj = Gia_ManCi(pSpec, i); + Bnd_ManMap( iLit, Gia_ObjId( pSpec, pObj ), 1 ); + + pObj = Gia_ManCi(pImpl, i); + Bnd_ManMap( iLit, Gia_ObjId( pImpl, pObj) , 0 ); + } + + // record the corresponding impl node of each lit + Gia_ManForEachAnd( pImpl, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( pBnd ) Bnd_ManMap( pObj -> Value, Gia_ObjId(pImpl, pObj), 0 ); + } + + Vec_Int_t* vFlag = Vec_IntAlloc( Gia_ManObjNum( pSpec ) ); + Vec_IntFill( vFlag, Gia_ManObjNum(pSpec), 0 ); + int count = 0; + Gia_ManForEachBuf( pSpec, pObj, i ) + { + if ( count < pBnd -> nBI ) + { + // it's BI, don't record buf + Vec_IntSetEntry( vFlag, Gia_ObjId( pSpec, pObj ), 1 ); + } + else + { + // it's BO, don't record buf's fanin + Vec_IntSetEntry( vFlag, Gia_ObjId( pSpec, Gia_ObjFanin0( pObj ) ), 1 ); + } + count++; + } + + // record hashed equivalent nodes + Gia_ManForEachAnd( pSpec, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Vec_IntEntry( vFlag, Gia_ObjId( pSpec, pObj ) ) == 0 ) + { + Bnd_ManMap( pObj -> Value, Gia_ObjId(pSpec, pObj), 1 ); + } + } + Vec_IntFree( vFlag ); + + Gia_ManForEachCo( pImpl, pObj, i ) + { + iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManForEachCo( pSpec, pObj, i ) + { + iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + + // miter + // Gia_ManForEachCo( pImpl, pObj, i ) + // { + // iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(Gia_ManCo(pSpec,i)) ); + // Gia_ManAppendCo( pNew, iLit ); + // } + + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +int Bnd_ManCheckCoMerged( Gia_Man_t* p ) +{ + int nCO = Gia_ManCoNum(p)/2; + + Gia_Obj_t* pObj1; + Gia_Obj_t* pObj2; + + for ( int i = 0; i < nCO; i++ ) + { + pObj1 = Gia_ManCo(p, i); + pObj2 = Gia_ManCo(p, i + nCO); + if ( Gia_ObjFaninLit0p(p, pObj1) != Gia_ObjFaninLit0p(p, pObj2) ) return 0; + } + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/aig/gia/giaDeep.c b/src/aig/gia/giaDeep.c index b58169f42..8d563726f 100644 --- a/src/aig/gia/giaDeep.c +++ b/src/aig/gia/giaDeep.c @@ -55,6 +55,7 @@ Gia_Man_t * Gia_ManDeepSynOne( int nNoImpr, int TimeOut, int nAnds, int Seed, in Abc_Random(0); for ( i = 0; i < IterMax; i++ ) { + char * pCompress2rs = "balance -l; resub -K 6 -l; rewrite -l; resub -K 6 -N 2 -l; refactor -l; resub -K 8 -l; balance -l; resub -K 8 -N 2 -l; rewrite -l; resub -K 10 -l; rewrite -z -l; resub -K 10 -N 2 -l; balance -l; resub -K 12 -l; refactor -z -l; resub -K 12 -N 2 -l; rewrite -z -l; balance -l"; unsigned Rand = Abc_Random(0); int fDch = Rand & 1; //int fCom = (Rand >> 1) & 3; @@ -62,16 +63,16 @@ Gia_Man_t * Gia_ManDeepSynOne( int nNoImpr, int TimeOut, int nAnds, int Seed, in int fFx = (Rand >> 2) & 1; int KLut = fUseTwo ? 2 + (i % 5) : 3 + (i % 4); int fChange = 0; - char Command[1000]; - char * pComp = NULL; + char Command[2000]; + char pComp[1000]; if ( fCom == 3 ) - pComp = "; &put; compress2rs; compress2rs; compress2rs; &get"; + sprintf( pComp, "; &put; %s; %s; %s; &get", pCompress2rs, pCompress2rs, pCompress2rs ); else if ( fCom == 2 ) - pComp = "; &put; compress2rs; compress2rs; &get"; + sprintf( pComp, "; &put; %s; %s; &get", pCompress2rs, pCompress2rs ); else if ( fCom == 1 ) - pComp = "; &put; compress2rs; &get"; + sprintf( pComp, "; &put; %s; &get", pCompress2rs ); else if ( fCom == 0 ) - pComp = "; &dc2"; + sprintf( pComp, "; &dc2" ); sprintf( Command, "&dch%s; &if -a -K %d; &mfs -e -W 20 -L 20%s%s", fDch ? " -f" : "", KLut, fFx ? "; &fx; &st" : "", pComp ); if ( Abc_FrameIsBatchMode() ) diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index 6dee2c26f..92eb2ac89 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -30,6 +30,9 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// + +extern Bnd_Man_t* pBnd; + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -788,6 +791,11 @@ Gia_Man_t * Gia_ManDupWithAttributes( Gia_Man_t * p ) pNew->vConfigs = Vec_IntDup( p->vConfigs ); if ( p->pCellStr ) pNew->pCellStr = Abc_UtilStrsav( p->pCellStr ); + // copy names if present + if ( p->vNamesIn ) + pNew->vNamesIn = Vec_PtrDupStr( p->vNamesIn ); + if ( p->vNamesOut ) + pNew->vNamesOut = Vec_PtrDupStr( p->vNamesOut ); return pNew; } Gia_Man_t * Gia_ManDupRemovePis( Gia_Man_t * p, int nRemPis ) @@ -5669,7 +5677,7 @@ Gia_Man_t * Gia_ManDupAddFlop( Gia_Man_t * p ) ***********************************************************************/ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) { - Vec_Int_t * vLits; + // Vec_Int_t * vLits; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iLit; @@ -5687,7 +5695,7 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) assert( Gia_ManRegNum(p2) == 0 ); assert( Gia_ManCiNum(p1) == Gia_ManCiNum(p2) ); assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); - vLits = Vec_IntAlloc( Gia_ManBufNum(p1) ); + // vLits = Vec_IntAlloc( Gia_ManBufNum(p1) ); if ( fVerbose ) printf( "Creating a boundary miter with %d inputs, %d outputs, and %d buffers.\n", Gia_ManCiNum(p1), Gia_ManCoNum(p1), Gia_ManBufNum(p1) ); @@ -5697,28 +5705,124 @@ Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) Gia_ManHashStart( pNew ); Gia_ManConst0(p1)->Value = 0; Gia_ManConst0(p2)->Value = 0; - Gia_ManForEachCi( p1, pObj, i ) - pObj->Value = Gia_ManCi(p2, i)->Value = Gia_ManAppendCi( pNew ); - Gia_ManForEachAnd( p2, pObj, i ) - pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - Gia_ManForEachAnd( p1, pObj, i ) { - pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - if ( Gia_ObjIsBuf(pObj) ) - Vec_IntPush( vLits, pObj->Value ); + + + for( int i = 0; i < Gia_ManCiNum(p1); i++ ) + { + int iLit = Gia_ManCi(p1, i)->Value = Gia_ManCi(p2, i) -> Value = Gia_ManAppendCi(pNew); + + pObj = Gia_ManCi(p1, i); + if ( pBnd ) Bnd_ManMap( iLit, Gia_ObjId( p1, pObj ), 1 ); + + pObj = Gia_ManCi(p2, i); + if ( pBnd ) Bnd_ManMap( iLit, Gia_ObjId( p2, pObj) , 0 ); + } + + // record the corresponding impl node of each lit + Gia_ManForEachAnd( p2, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( pBnd ) Bnd_ManMap( pObj -> Value, Gia_ObjId(p2, pObj), 0 ); + } + + // record hashed equivalent nodes + Gia_ManForEachAnd( p1, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( pBnd ) Bnd_ManMap( pObj -> Value, Gia_ObjId(p1, pObj), 1 ); + } + Gia_ManForEachCo( p2, pObj, i ) - Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + { + iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } Gia_ManForEachCo( p1, pObj, i ) - Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); - Vec_IntForEachEntry( vLits, iLit, i ) - Gia_ManAppendCo( pNew, iLit ); - Vec_IntFree( vLits ); + { + iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + + // Vec_IntForEachEntry( vLits, iLit, i ) + // Gia_ManAppendCo( pNew, iLit ); + // Vec_IntFree( vLits ); Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } +/**Function************************************************************* + Synopsis [Duplicates AIG while putting objects in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManImplFromBMiter( Gia_Man_t * p, int nPo, int nBInput ) +{ + Gia_Man_t * pNew, *pTemp; + Gia_Obj_t * pObj, *pObj2; + int i; + int nBoundI = 0, nBoundO = 0; + int nExtra; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + // pNew->pName = Abc_UtilStrsav( p->pName ); + // pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + + // add po of impl + Gia_ManForEachCo( p, pObj, i ) + { + if ( i < nPo ) + { + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + } + } + nExtra = Gia_ManAndNum( pNew ); + + // add boundary as buf + Gia_ManForEachCo( p, pObj, i ) + { + if ( i >= 2 * nPo ) + { + pObj2 = Gia_ObjFanin0(pObj); + if (~pObj2->Value) // visited boundary + { + if ( i >= 2 * nPo + nBInput ) + { + nBoundO ++; + } + else nBoundI ++; + } + + Gia_ManDupOrderDfs_rec( pNew, p, pObj2 ); + Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + } + } + nExtra = Gia_ManAndNum( pNew ) - nExtra - Gia_ManBufNum( pNew ); + + Gia_ManForEachCi( p, pObj, i ) + if ( !~pObj->Value ) + pObj->Value = Gia_ManAppendCi(pNew); + assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); + + Gia_ManDupRemapCis( pNew, p ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + + printf( "synthesized implementation:\n" ); + printf( "\t%d / %d input boundary recovered.\n", nBoundI, nBInput ); + printf( "\t%d / %d output boundary recovered.\n", nBoundO, Gia_ManCoNum(p)-2*nPo-nBInput ); + printf( "\t%d / %d unused nodes in the box.\n", nExtra, Gia_ManAndNum(pNew) - Gia_ManBufNum( pNew ) ); + + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaEquiv.c b/src/aig/gia/giaEquiv.c index 1c3aa4311..aec9d39ca 100644 --- a/src/aig/gia/giaEquiv.c +++ b/src/aig/gia/giaEquiv.c @@ -715,6 +715,30 @@ Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fS return pNew; } +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Obj_t * Gia_MakeRandomChoice( Gia_Man_t * p, int iRepr ) +{ + int iTemp, Rand, Count = 0; + Gia_ClassForEachObj( p, iRepr, iTemp ) + Count++; + Rand = rand() % Count; + Count = 0; + Gia_ClassForEachObj( p, iRepr, iTemp ) + if ( Count++ == Rand ) + break; + return Gia_ManObj(p, iTemp); +} + /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] @@ -735,7 +759,7 @@ void Gia_ManEquivReduce2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, if ( fDiveIn && (pRepr = Gia_ManEquivRepr(p, pObj, 1, 0)) ) { int iTemp, iRepr = Gia_ObjId(p, pRepr); - Gia_Obj_t * pRepr2 = Gia_ManObj( p, Vec_IntEntry(vMap, iRepr) ); + Gia_Obj_t * pRepr2 = vMap ? Gia_ManObj( p, Vec_IntEntry(vMap, iRepr) ) : Gia_MakeRandomChoice(p, iRepr); Gia_ManEquivReduce2_rec( pNew, p, pRepr2, vMap, 0 ); Gia_ClassForEachObj( p, iRepr, iTemp ) { @@ -751,12 +775,13 @@ void Gia_ManEquivReduce2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Gia_ManEquivReduce2_rec( pNew, p, Gia_ObjFanin1(pObj), vMap, 1 ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } -Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p ) +Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p, int fRandom ) { Vec_Int_t * vMap; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; + if ( fRandom ) srand(time(NULL)); if ( !p->pReprs && p->pSibls ) { int * pMap = ABC_FALLOC( int, Gia_ManObjNum(p) ); @@ -789,7 +814,7 @@ Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p ) break; if ( i == Gia_ManObjNum(p) ) return Gia_ManDup( p ); - vMap = Gia_ManChoiceMinLevel( p ); + vMap = fRandom ? NULL : Gia_ManChoiceMinLevel( p ); Gia_ManSetPhase( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); @@ -805,7 +830,7 @@ Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); - Vec_IntFree( vMap ); + Vec_IntFreeP( &vMap ); return pNew; } diff --git a/src/aig/gia/giaFx.c b/src/aig/gia/giaFx.c index 032ae5fc4..c20241ed1 100644 --- a/src/aig/gia/giaFx.c +++ b/src/aig/gia/giaFx.c @@ -150,6 +150,13 @@ Vec_Wrd_t * Gia_ManComputeTruths( Gia_Man_t * p, int nCutSize, int nLutNum, int // collect and sort fanins vLeaves.nCap = vLeaves.nSize = Gia_ObjLutSize( p, i ); vLeaves.pArray = Gia_ObjLutFanins( p, i ); + if( !Vec_IntCheckUniqueSmall(&vLeaves) ) + { + Vec_IntUniqify(&vLeaves); + Vec_IntWriteEntry(p->vMapping, Vec_IntEntry(p->vMapping, i), vLeaves.nSize); + for ( k = 0; k < vLeaves.nSize; k++ ) + Vec_IntWriteEntry(p->vMapping, Vec_IntEntry(p->vMapping, i) + 1 + k, vLeaves.pArray[k]); + } assert( Vec_IntCheckUniqueSmall(&vLeaves) ); Vec_IntSelectSort( Vec_IntArray(&vLeaves), Vec_IntSize(&vLeaves) ); if ( !fReverse ) diff --git a/src/aig/gia/giaIso3.c b/src/aig/gia/giaIso3.c index bcd73c36f..b526676d3 100644 --- a/src/aig/gia/giaIso3.c +++ b/src/aig/gia/giaIso3.c @@ -177,7 +177,7 @@ Vec_Wec_t * Gia_Iso4Gia( Gia_Man_t * p ) Vec_WecForEachLevel( vLevs, vLevel, l ) { Gia_Obj_t * pObj; int i; - int RandC[2] = { (int)Abc_Random(0), (int)Abc_Random(0) }; + unsigned RandC[2] = { Abc_Random(0), Abc_Random(0) }; if ( l == 0 ) { Gia_ManForEachObjVec( vLevel, p, pObj, i ) diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index e8f9bca32..f2d403ded 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -156,6 +156,8 @@ void Gia_ManStop( Gia_Man_t * p ) Vec_IntErase( &p->vHash ); Vec_IntErase( &p->vHTable ); Vec_IntErase( &p->vRefs ); + Vec_StrFreeP( &p->vStopsF ); + Vec_StrFreeP( &p->vStopsB ); ABC_FREE( p->pData2 ); ABC_FREE( p->pTravIds ); ABC_FREE( p->pPlacement ); @@ -1252,7 +1254,7 @@ void Gia_ManDfsSlacksPrint( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -void Gia_ManWriteNamesInter( FILE * pFile, char c, int n, int Start, int Skip, int nRegs ) +void Gia_ManWriteNamesInter( FILE * pFile, char c, int n, int Start, int Skip, int nRegs, int fReverse ) { int Length = Start, i, fFirst = 1; char pName[100]; @@ -1291,7 +1293,7 @@ void Gia_ManDumpModuleName( FILE * pFile, char * pName ) else fprintf( pFile, "_" ); } -void Gia_ManDumpInterface( Gia_Man_t * p, FILE * pFile ) +void Gia_ManDumpInterface2( Gia_Man_t * p, FILE * pFile ) { int fPrintClk = 0; fprintf( pFile, "module " ); @@ -1316,15 +1318,14 @@ void Gia_ManDumpInterface( Gia_Man_t * p, FILE * pFile ) fprintf( pFile, "_inst" ); fprintf( pFile, " (\n " ); - Gia_ManWriteNamesInter( pFile, 'i', Gia_ManCiNum(p), 4, 4, Gia_ManRegNum(p) ); + Gia_ManWriteNamesInter( pFile, 'i', Gia_ManCiNum(p), 4, 4, Gia_ManRegNum(p), 0 ); fprintf( pFile, ",\n " ); - Gia_ManWriteNamesInter( pFile, 'o', Gia_ManCoNum(p), 4, 4, Gia_ManRegNum(p) ); + Gia_ManWriteNamesInter( pFile, 'o', Gia_ManCoNum(p), 4, 4, Gia_ManRegNum(p), 0 ); fprintf( pFile, "\n );\n\n" ); fprintf( pFile, "endmodule\n\n" ); } - /**Function************************************************************* Synopsis [Compute arrival/required times.] @@ -1386,16 +1387,17 @@ char * Gia_ObjGetDumpName( Vec_Ptr_t * vNames, char c, int i, int d ) sprintf( pBuffer, "%c%0*d%c", c, d, i, c ); return pBuffer; } -void Gia_ManWriteNames( FILE * pFile, char c, int n, Vec_Ptr_t * vNames, int Start, int Skip, Vec_Bit_t * vObjs ) +void Gia_ManWriteNames( FILE * pFile, char c, int n, Vec_Ptr_t * vNames, int Start, int Skip, Vec_Bit_t * vObjs, int fReverse ) { int Digits = Abc_Base10Log( n ); int Length = Start, i, fFirst = 1; char * pName; for ( i = 0; i < n; i++ ) { - if ( vObjs && !Vec_BitEntry(vObjs, i) ) + int k = fReverse ? n-1-i : i; + if ( vObjs && !Vec_BitEntry(vObjs, k) ) continue; - pName = Gia_ObjGetDumpName( vNames, c, i, Digits ); + pName = Gia_ObjGetDumpName( vNames, c, k, Digits ); Length += strlen(pName) + 2; if ( Length > 60 ) { @@ -1407,7 +1409,32 @@ void Gia_ManWriteNames( FILE * pFile, char c, int n, Vec_Ptr_t * vNames, int Sta fFirst = 0; } } -void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ) +void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb, int fAssign, int fReverse ) +{ + if ( fInterComb ) + { + if ( fAssign ) { + extern void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ); + Gia_ManDumpInterfaceAssign( p, pFileName ); + } + else { + extern void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ); + Gia_ManDumpInterface( p, pFileName ); + } + } + else + { + if ( fAssign ) { + extern void Gia_ManDumpVerilogNoInterAssign( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ); + Gia_ManDumpVerilogNoInterAssign( p, pFileName, vObjs, fVerBufs, fInter ); + } + else { + extern void Gia_ManDumpVerilogNoInter( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ); + Gia_ManDumpVerilogNoInter( p, pFileName, vObjs, fVerBufs, fInter ); + } + } +} +void Gia_ManDumpVerilogNoInter( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ) { Gia_Obj_t * pObj; Vec_Bit_t * vInvs, * vUsed; @@ -1423,7 +1450,7 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int } if ( fInter || nRegs ) - Gia_ManDumpInterface( p, pFile ); + Gia_ManDumpInterface2( p, pFile ); //Gia_ManSetRegNum( p, 0 ); p->nRegs = 0; @@ -1438,26 +1465,26 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int if ( fVerBufs ) { fprintf( pFile, " (\n " ); - Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 4, 4, NULL ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 4, 4, NULL, 0 ); fprintf( pFile, ",\n " ); - Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL ); + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL, 0 ); fprintf( pFile, "\n );\n\n" ); fprintf( pFile, " input " ); - Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " output " ); - Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); Gia_ManForEachPi( p, pObj, i ) @@ -1477,32 +1504,32 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int else { fprintf( pFile, " (\n " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL, 0 ); fprintf( pFile, ",\n " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL, 0 ); fprintf( pFile, "\n );\n\n" ); fprintf( pFile, " input " ); - Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " output " ); - Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vUsed) ) { fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vInvs) ) { fprintf( pFile, " wire " ); - Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); fprintf( pFile, ";\n\n" ); } @@ -1587,6 +1614,682 @@ void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int Gia_ManSetRegNum( p, nRegs ); } +void Gia_ManDumpVerilogNoInterAssign( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ) +{ + Gia_Obj_t * pObj; + Vec_Bit_t * vInvs, * vUsed; + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + int i, k, iObj, nRegs = Gia_ManRegNum(p); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + + if ( fInter || nRegs ) + Gia_ManDumpInterface2( p, pFile ); + //Gia_ManSetRegNum( p, 0 ); + p->nRegs = 0; + + vInvs = Gia_ManGenUsed( p, 0 ); + vUsed = Gia_ManGenUsed( p, 1 ); + + //fprintf( pFile, "// This Verilog file is written by ABC on %s\n\n", Extra_TimeStamp() ); + + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + + if ( fVerBufs ) + { + fprintf( pFile, " (\n " ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 4, 4, NULL, 0 ); + fprintf( pFile, ",\n " ); + + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL, 0 ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, " input " ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " output " ); + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + Gia_ManForEachPi( p, pObj, i ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(NULL, 'a', i, nDigitsI) ); + } + fprintf( pFile, "\n" ); + + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'y', i, nDigitsO) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + } + fprintf( pFile, "\n" ); + } + else + { + fprintf( pFile, " (\n " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL, 0 ); + fprintf( pFile, ",\n " ); + + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL, 0 ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, " input " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " output " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vUsed) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vInvs) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( vObjs ) + { + fprintf( pFile, " wire " ); + Vec_IntForEachEntry( vObjs, iObj, i ) + fprintf( pFile, " t_%d%s", i, i==Vec_IntSize(vObjs)-1 ? "" : "," ); + fprintf( pFile, ";\n\n" ); + Vec_IntForEachEntry( vObjs, iObj, i ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', iObj, nDigits) ); + fprintf( pFile, " t_%d;\n", i ); + } + fprintf( pFile, "\n" ); + } + + // input inverters + Gia_ManForEachPi( p, pObj, i ) + { + if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + if ( Vec_BitEntry(vInvs, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + } + + // internal nodes and their inverters + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + int fSkip = 0; + if ( vObjs ) + { + Vec_IntForEachEntry( vObjs, iObj, k ) + if ( iObj == i ) + break; + if ( k < Vec_IntSize(vObjs) ) + fSkip = 1; + } + if ( !fSkip ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + fprintf( pFile, " %s &", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0(pObj, i), nDigits) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC1(pObj)? 'i':'n'), Gia_ObjFaninId1(pObj, i), nDigits) ); + } + if ( Vec_BitEntry(vInvs, i) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); + fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + } + } + + // output drivers + fprintf( pFile, "\n" ); + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " assign %s = ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d;\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); + } + + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); + + Vec_BitFree( vInvs ); + Vec_BitFree( vUsed ); + + Gia_ManSetRegNum( p, nRegs ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintOneName( FILE * pFile, char * pName, int Size ) +{ + int i; + for ( i = 0; i < Size; i++ ) + fprintf( pFile, "%c", pName[i] ); +} +int Gia_ManCountSymbs( char * pName ) +{ + int i; + for ( i = 0; pName[i]; i++ ) + if ( pName[i] == '[' ) + break; + return i; +} +int Gia_ManReadRangeNum( char * pName, int Size ) +{ + if ( pName[Size] == 0 ) + return -1; + assert( pName[Size] == '[' ); + return atoi(pName+Size+1); +} +Vec_Int_t * Gia_ManCountSymbsAll( Vec_Ptr_t * vNames ) +{ + char * pNameLast = (char *)Vec_PtrEntry(vNames, 0), * pName; + int i, nSymbsLast = Gia_ManCountSymbs(pNameLast); + Vec_Int_t * vArray = Vec_IntAlloc( Vec_PtrSize(vNames) * 2 ); + Vec_IntPush( vArray, 0 ); + Vec_IntPush( vArray, nSymbsLast ); + Vec_PtrForEachEntryStart( char *, vNames, pName, i, 1 ) + { + int nSymbs = Gia_ManCountSymbs(pName); + if ( nSymbs == nSymbsLast && !strncmp(pName, pNameLast, nSymbsLast) ) + continue; + Vec_IntPush( vArray, i ); + Vec_IntPush( vArray, nSymbs ); + pNameLast = pName; + nSymbsLast = nSymbs; + } + return vArray; +} +void Gia_ManDumpIoList( Gia_Man_t * p, FILE * pFile, int fOuts, int fReverse ) +{ + Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; + if ( vNames == NULL ) + fprintf( pFile, "_%c_", fOuts ? 'o' : 'i' ); + else + { + Vec_Int_t * vArray = Gia_ManCountSymbsAll( vNames ); + int iName, Size, i; + Vec_IntForEachEntryDouble( vArray, iName, Size, i ) + { + if ( fReverse ) + { + iName = Vec_IntEntry(vArray, Vec_IntSize(vArray)-2-i); + Size = Vec_IntEntry(vArray, Vec_IntSize(vArray)-1-i); + } + if ( i ) fprintf( pFile, ", " ); + Gia_ManPrintOneName( pFile, (char *)Vec_PtrEntry(vNames, iName), Size ); + } + Vec_IntFree( vArray ); + } +} +void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts ) +{ + Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; + if ( p->vNamesOut == NULL ) + fprintf( pFile, "%s [%d:0] _%c_;\n", fOuts ? "output" : "input", fOuts ? Gia_ManPoNum(p)-1 : Gia_ManPiNum(p)-1, fOuts ? 'o' : 'i' ); + else + { + Vec_Int_t * vArray = Gia_ManCountSymbsAll( vNames ); + int iName, Size, i; + Vec_IntForEachEntryDouble( vArray, iName, Size, i ) + { + int iNameNext = Vec_IntSize(vArray) > i+2 ? Vec_IntEntry(vArray, i+2) : Vec_PtrSize(vNames); + char * pName = (char *)Vec_PtrEntry(vNames, iName); + char * pNameLast = (char *)Vec_PtrEntry(vNames, iNameNext-1); + assert( !strncmp(pName, pNameLast, Size) ); + int NumBeg = Gia_ManReadRangeNum( pName, Size ); + int NumEnd = Gia_ManReadRangeNum( pNameLast, Size ); + fprintf( pFile, " %s ", fOuts ? "output" : "input" ); + if ( NumBeg != -1 && iName < iNameNext-1 ) + fprintf( pFile, "[%d:%d] ", NumEnd, NumBeg ); + Gia_ManPrintOneName( pFile, pName, Size ); + fprintf( pFile, ";\n" ); + } + Vec_IntFree( vArray ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ) +{ + Gia_Obj_t * pObj; + Vec_Bit_t * vInvs, * vUsed; + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + int i; + + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + + vInvs = Gia_ManGenUsed( p, 0 ); + vUsed = Gia_ManGenUsed( p, 1 ); + + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_wrapper" ); + fprintf( pFile, " ( " ); + Gia_ManDumpIoList( p, pFile, 0, 0 ); + fprintf( pFile, ", " ); + Gia_ManDumpIoList( p, pFile, 1, 0 ); + fprintf( pFile, " );\n\n" ); + Gia_ManDumpIoRanges( p, pFile, 0 ); + Gia_ManDumpIoRanges( p, pFile, 1 ); + fprintf( pFile, "\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " assign { " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL, 1 ); + fprintf( pFile, " } = { " ); + Gia_ManDumpIoList( p, pFile, 0, 1 ); + fprintf( pFile, " };\n\n" ); + + fprintf( pFile, " assign { " ); + Gia_ManDumpIoList( p, pFile, 1, 1 ); + fprintf( pFile, " } = { " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL, 1 ); + fprintf( pFile, " };\n\n" ); + + if ( Vec_BitCount(vUsed) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vInvs) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); + fprintf( pFile, ";\n\n" ); + } + + // input inverters + Gia_ManForEachCi( p, pObj, i ) + { + if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + if ( Vec_BitEntry(vInvs, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " not ( %s,", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + } + + // internal nodes and their inverters + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + fprintf( pFile, " and ( %s,", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + fprintf( pFile, " %s,", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0(pObj, i), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC1(pObj)? 'i':'n'), Gia_ObjFaninId1(pObj, i), nDigits) ); + if ( Vec_BitEntry(vInvs, i) ) + { + fprintf( pFile, " not ( %s,", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + } + } + + // output drivers + fprintf( pFile, "\n" ); + Gia_ManForEachCo( p, pObj, i ) + { + fprintf( pFile, " buf ( %s, ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d );\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s );\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); + } + + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); + + Vec_BitFree( vInvs ); + Vec_BitFree( vUsed ); +} +void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ) +{ + Gia_Obj_t * pObj; + Vec_Bit_t * vInvs, * vUsed; + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + int i; + + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + + vInvs = Gia_ManGenUsed( p, 0 ); + vUsed = Gia_ManGenUsed( p, 1 ); + + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_wrapper" ); + fprintf( pFile, " ( " ); + Gia_ManDumpIoList( p, pFile, 0, 0 ); + fprintf( pFile, ", " ); + Gia_ManDumpIoList( p, pFile, 1, 0 ); + fprintf( pFile, " );\n\n" ); + Gia_ManDumpIoRanges( p, pFile, 0 ); + Gia_ManDumpIoRanges( p, pFile, 1 ); + fprintf( pFile, "\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " assign { " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL, 1 ); + fprintf( pFile, " } = { " ); + Gia_ManDumpIoList( p, pFile, 0, 1 ); + fprintf( pFile, " };\n\n" ); + + fprintf( pFile, " assign { " ); + Gia_ManDumpIoList( p, pFile, 1, 1 ); + fprintf( pFile, " } = { " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL, 1 ); + fprintf( pFile, " };\n\n" ); + + if ( Vec_BitCount(vUsed) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vInvs) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); + fprintf( pFile, ";\n\n" ); + } + + // input inverters + Gia_ManForEachCi( p, pObj, i ) + { + if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + if ( Vec_BitEntry(vInvs, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + } + + // internal nodes and their inverters + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + fprintf( pFile, " %s &", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0(pObj, i), nDigits) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC1(pObj)? 'i':'n'), Gia_ObjFaninId1(pObj, i), nDigits) ); + if ( Vec_BitEntry(vInvs, i) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); + fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + } + } + + // output drivers + fprintf( pFile, "\n" ); + Gia_ManForEachCo( p, pObj, i ) + { + fprintf( pFile, " assign %s = ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d;\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); + } + + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); + + Vec_BitFree( vInvs ); + Vec_BitFree( vUsed ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDumpNandLit( FILE * pFile, int nIns, int Lit, int nDigits ) +{ + if ( Lit == 0 ) + fprintf( pFile, "1\'b0" ); + else if ( Lit == 1 ) + fprintf( pFile, "1\'b1" ); + else if ( Abc_Lit2Var(Lit) <= nIns ) + fprintf( pFile, "%cn%0*d", (char)(Abc_LitIsCompl(Lit)? '~':' '), nDigits, Abc_Lit2Var(Lit) ); + else + fprintf( pFile, "%cn%0*d", (char)(Abc_LitIsCompl(Lit)? ' ':'~'), nDigits, Abc_Lit2Var(Lit) ); +} +void Gia_ManDumpVerilogNand( Gia_Man_t * p, char * pFileName ) +{ + Gia_Obj_t * pObj; int i, nPis = Gia_ManPiNum(p); + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + assert( Gia_ManRegNum(p) == 0 ); + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_wrapper" ); + fprintf( pFile, " ( " ); + if ( p->vNamesIn ) { + Gia_ManDumpIoList( p, pFile, 0, 0 ); + fprintf( pFile, ", " ); + Gia_ManDumpIoList( p, pFile, 1, 0 ); + fprintf( pFile, " );\n\n" ); + Gia_ManDumpIoRanges( p, pFile, 0 ); + Gia_ManDumpIoRanges( p, pFile, 1 ); + } + else { + fprintf( pFile, "\n " ); + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, "%s, ", Gia_ObjGetDumpName(NULL, 'x', i, nDigitsI) ); + fprintf( pFile, "\n " ); + Gia_ManForEachPo( p, pObj, i ) + fprintf( pFile, "%s%s ", Gia_ObjGetDumpName(NULL, 'z', i, nDigitsO), i < Gia_ManPoNum(p)-1 ? ",":"" ); + fprintf( pFile, "\n);\n\n" ); + fprintf( pFile, " input" ); + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, " %s%s", Gia_ObjGetDumpName(NULL, 'x', i, nDigitsI), i < Gia_ManPiNum(p)-1 ? ",":"" ); + fprintf( pFile, ";\n" ); + fprintf( pFile, " output" ); + Gia_ManForEachPo( p, pObj, i ) + fprintf( pFile, " %s%s", Gia_ObjGetDumpName(NULL, 'z', i, nDigitsO), i < Gia_ManPoNum(p)-1 ? ",":"" ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, "\n" ); + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, " wire n%0*d = %s;\n", nDigits, i+1, p->vNamesIn ? (char *)Vec_PtrEntry(p->vNamesIn, i) : Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + fprintf( pFile, " wire n%0*d = ~(", nDigits, i ); + Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit0(pObj, i), nDigits ); + fprintf( pFile, " & " ); + Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit1(pObj, i), nDigits ); + fprintf( pFile, ");\n" ); + } + fprintf( pFile, "\n" ); + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " assign %s = ", p->vNamesOut ? (char *)Vec_PtrEntry(p->vNamesOut, i) : Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit0p(p, pObj), nDigits ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Generate hierarchical design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_FreeMany( Gia_Man_t ** pGias, int nGias ) +{ + int i; + for ( i = 0; i < nGias; i++ ) + Gia_ManStopP( &pGias[i] ); +} +void Gia_GenSandwich( char ** pFNames, int nFNames, char * pFileName ) +{ + FILE * pFile = NULL; + Gia_Man_t * pGias[16] = {0}; + int i, k; + assert( nFNames <= 16 ); + for ( i = 0; i < nFNames; i++ ) + { + FILE * pFile = fopen( pFNames[i], "rb" ); + if ( pFile == NULL ) { + printf( "Cannot open input file \"%s\".\n", pFNames[i] ); + Gia_FreeMany( pGias, nFNames ); + return; + } + fclose( pFile ); + pGias[i] = Gia_AigerRead( pFNames[i], 0, 0, 0 ); + if ( pGias[i] == NULL ) { + printf( "Failed to read an AIG from file \"%s\".\n", pFNames[i] ); + Gia_FreeMany( pGias, nFNames ); + return; + } + } + for ( i = 0; i < nFNames-1; i++ ) + if ( Gia_ManPoNum(pGias[i]) < Gia_ManPiNum(pGias[i+1]) ) { + printf( "AIG in file \"%s\" has fewer outputs than inputs of AIG in file \"%s\".\n", pFNames[i], pFNames[i+1] ); + Gia_FreeMany( pGias, nFNames ); + return; + } + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + Gia_FreeMany( pGias, nFNames ); + return; + } + fprintf( pFile, "\n" ); + for ( i = 0; i < nFNames; i++ ) + fprintf( pFile, "`include \"%s\"\n", Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v") ); + fprintf( pFile, "\n" ); + fprintf( pFile, "module sandwich ( in, out );\n" ); + fprintf( pFile, " input [%3d:0] in;\n", Gia_ManPiNum(pGias[0])-1 ); + fprintf( pFile, " output [%3d:0] out;\n", Gia_ManPoNum(pGias[nFNames-1])-1 ); + fprintf( pFile, " wire [%3d:0] tmp0 = in;\n", Gia_ManPiNum(pGias[0])-1 ); + for ( i = 0; i < nFNames; i++ ) { + fprintf( pFile, " wire [%3d:0] tmp%d; ", Gia_ManPoNum(pGias[i])-1, i+1 ); + Gia_ManDumpModuleName( pFile, pGias[i]->pName ); + fprintf( pFile, "_wrapper" ); + for ( k = strlen(pGias[i]->pName); k < 24; k++ ) + fprintf( pFile, " " ); + fprintf( pFile, " i%d ( tmp%d, tmp%d );\n", i+1, i, i+1 ); + } + fprintf( pFile, " assign out = tmp%d;\n", nFNames ); + fprintf( pFile, "endmodule\n" ); + fclose( pFile ); + for ( i = 0; i < nFNames; i++ ) { + Vec_PtrFreeFree( pGias[i]->vNamesIn ); pGias[i]->vNamesIn = NULL; + Vec_PtrFreeFree( pGias[i]->vNamesOut ); pGias[i]->vNamesOut = NULL; + Gia_ManDumpVerilog( pGias[i], Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v"), NULL, 0, 0, 1, 0, 0 ); + printf( "Dumped Verilog file \"%s\"\n", Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v") ); + } + Gia_FreeMany( pGias, nFNames ); + printf( "Dumped hierarchical design into file \"%s\"\n", pFileName ); +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/aig/gia/giaMini.c b/src/aig/gia/giaMini.c index c0473fea3..2fce5d0d4 100644 --- a/src/aig/gia/giaMini.c +++ b/src/aig/gia/giaMini.c @@ -1228,6 +1228,127 @@ void Gia_MiniAigGenerateFromFile() Mini_AigStop( p ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Gia_ManRetimableF( Gia_Man_t * p, int * pRst, int * pSet, int * pEna ) +{ + Vec_Str_t * vStops = Vec_StrStart( Gia_ManObjNum(p) ); + Vec_Int_t * vTemps = Vec_IntStartFull( 3*Gia_ManObjNum(p) ); + Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i; + char * pStops = Vec_StrArray(vStops); + assert( Gia_ManRegNum(p) > 0 ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRo) + 0, pRst[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRo) + 1, pSet[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRo) + 2, pEna[i] ); + } + Gia_ManForEachAnd( p, pObj, i ) { + int * pFan0 = Vec_IntEntryP( vTemps, 3*Gia_ObjFaninId0(pObj, i) ); + int * pFan1 = Vec_IntEntryP( vTemps, 3*Gia_ObjFaninId1(pObj, i) ); + int * pNode = Vec_IntEntryP( vTemps, 3*i ); + pStops[i] = (char)1; + if ( pFan0[0] != -1 && pFan0[0] == pFan1[0] && pFan0[1] == pFan1[1] && pFan0[2] == pFan1[2] ) + pStops[i] = (char)0, pNode[0] = pFan0[0], pNode[1] = pFan0[1], pNode[2] = pFan0[2]; + } + Vec_IntFree( vTemps ); + return vStops; +} +Vec_Str_t * Gia_ManRetimableB( Gia_Man_t * p, int * pRst, int * pSet, int * pEna ) +{ + Vec_Str_t * vStops = Vec_StrStart( Gia_ManObjNum(p) ); + Vec_Int_t * vTemps = Vec_IntStartFull( 3*Gia_ManObjNum(p) ); + Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i, n, iFanout; + char * pStops = Vec_StrArray(vStops); + assert( Gia_ManRegNum(p) > 0 ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRi) + 0, pRst[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRi) + 1, pSet[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRi) + 2, pEna[i] ); + } + Gia_ManStaticFanoutStart( p ); + Gia_ManForEachAndReverse( p, pObj, i ) { + int * pFan0 = Vec_IntEntryP( vTemps, 3*Gia_ObjFanoutId(p, i, 0) ); + int * pNode = Vec_IntEntryP( vTemps, 3*i ); + pStops[i] = (char)1; + if ( pFan0[0] == -1 ) + continue; + Gia_ObjForEachFanoutStaticId( p, i, iFanout, n ) { + int * pFan1 = Vec_IntEntryP( vTemps, 3*iFanout ); + if ( pFan1[0] == -1 || pFan0[0] != pFan1[0] || pFan0[1] != pFan1[1] || pFan0[2] != pFan1[2] ) + break; + } + if ( n < Gia_ObjFanoutNum(p, pObj) ) + continue; + pStops[i] = (char)0, pNode[0] = pFan0[0], pNode[1] = pFan0[1], pNode[2] = pFan0[2]; + } + Gia_ManStaticFanoutStop( p ); + Vec_IntFree( vTemps ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { + if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(pRst[i]))) ) pStops[Abc_Lit2Var(pRst[i])] = 1; + if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(pSet[i]))) ) pStops[Abc_Lit2Var(pSet[i])] = 1; + if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(pEna[i]))) ) pStops[Abc_Lit2Var(pEna[i])] = 1; + } + return vStops; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameRemapLits( int * pLits, int nLits, Vec_Int_t * vMap ) +{ + for ( int i = 0; i < nLits; i++ ) + pLits[i] = Abc_Lit2LitL( Vec_IntArray(vMap), pLits[i] ); +} +void Abc_FrameSetRetimingData( Abc_Frame_t * pAbc, int * pRst, int * pSet, int * pEna, int nRegs ) +{ + Gia_Man_t * pGia; + int * pRstNew = ABC_CALLOC( int, nRegs ); + int * pSetNew = ABC_CALLOC( int, nRegs ); + int * pEnaNew = ABC_CALLOC( int, nRegs ); + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + pGia = Abc_FrameReadGia( pAbc ); + if ( pGia == NULL ) + printf( "Current network in ABC framework is not defined.\n" ); + else { + assert( nRegs == Gia_ManRegNum(pGia) ); + memmove( pRstNew, pRst, sizeof(int)*nRegs ); + memmove( pSetNew, pSet, sizeof(int)*nRegs ); + memmove( pEnaNew, pEna, sizeof(int)*nRegs ); + } + if ( pAbc->vCopyMiniAig == NULL ) + printf( "Mapping of MiniAig nodes is not available.\n" ); + else { + Abc_FrameRemapLits( pRstNew, nRegs, pAbc->vCopyMiniAig ); + Abc_FrameRemapLits( pSetNew, nRegs, pAbc->vCopyMiniAig ); + Abc_FrameRemapLits( pEnaNew, nRegs, pAbc->vCopyMiniAig ); + } + assert( pGia->vStopsF == NULL ); + assert( pGia->vStopsB == NULL ); + pGia->vStopsF = Gia_ManRetimableF( pGia, pRstNew, pSetNew, pEnaNew ); + pGia->vStopsB = Gia_ManRetimableB( pGia, pRstNew, pSetNew, pEnaNew ); + ABC_FREE( pRstNew ); + ABC_FREE( pSetNew ); + ABC_FREE( pEnaNew ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaSif.c b/src/aig/gia/giaSif.c index db7629fb3..c52ab4dd9 100644 --- a/src/aig/gia/giaSif.c +++ b/src/aig/gia/giaSif.c @@ -490,13 +490,16 @@ int Gia_ManSifCheckIter( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, i } int Gia_ManSifCheckPeriod( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period, int * pIters ) { - Gia_Obj_t * pObj; int i, Id, nSize = nLutSize+1; + Gia_Obj_t * pObj; int i, Id, Stop, nSize = nLutSize+1; assert( Gia_ManRegNum(p) > 0 ); Gia_ManForEachCiId( p, Id, i ) Vec_IntWriteEntry( vCuts, Id*nSize, 1 ); Gia_ManForEachCiId( p, Id, i ) Vec_IntWriteEntry( vCuts, Id*nSize+1, Id << 8 ); Vec_IntFill( vTimes, Gia_ManObjNum(p), -Period ); + if ( p->vStopsF ) + Vec_StrForEachEntry( p->vStopsF, Stop, i ) + if ( Stop ) Vec_IntWriteEntry( vTimes, i, 0 ); Vec_IntWriteEntry( vTimes, 0, 0 ); Gia_ManForEachPi( p, pObj, i ) Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), 0 ); @@ -510,6 +513,10 @@ int Gia_ManSifCheckPeriod( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, Gia_ManForEachObj( p, pObj, i ) if ( Vec_IntEntry(vTimes, Gia_ObjId(p, pObj)) > 2*Period ) return 0; + if ( p->vStopsB ) + Vec_StrForEachEntry( p->vStopsB, Stop, i ) + if ( Stop && Vec_IntEntry(vTimes, i) > Period ) + return 0; } return 0; } diff --git a/src/aig/gia/giaStoch.c b/src/aig/gia/giaStoch.c index b6c3c101f..fc65c80bb 100644 --- a/src/aig/gia/giaStoch.c +++ b/src/aig/gia/giaStoch.c @@ -60,32 +60,35 @@ ABC_NAMESPACE_IMPL_START SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_StochProcessOne( Gia_Man_t * p, char * pScript, int Rand, int TimeSecs ) +Gia_Man_t * Gia_StochProcessSingle( Gia_Man_t * p, char * pScript, int Rand, int TimeSecs ) { - Gia_Man_t * pNew; - char FileName[100], Command[1000]; - sprintf( FileName, "%06x.aig", Rand ); - Gia_AigerWrite( p, FileName, 0, 0, 0 ); - sprintf( Command, "./abc -q \"&read %s; %s; &write %s\"", FileName, pScript, FileName ); -#if defined(__wasm) - if ( 1 ) -#else - if ( system( (char *)Command ) ) -#endif + Gia_Man_t * pTemp, * pNew = Gia_ManDup( p ); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(p) ); + if ( Abc_FrameIsBatchMode() ) { - fprintf( stderr, "The following command has returned non-zero exit status:\n" ); - fprintf( stderr, "\"%s\"\n", (char *)Command ); - fprintf( stderr, "Sorry for the inconvenience.\n" ); - fflush( stdout ); - unlink( FileName ); - return Gia_ManDup(p); - } - pNew = Gia_AigerRead( FileName, 0, 0, 0 ); - unlink( FileName ); - if ( pNew && Gia_ManAndNum(pNew) < Gia_ManAndNum(p) ) - return pNew; - Gia_ManStopP( &pNew ); - return Gia_ManDup(p); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return NULL; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return NULL; + } + Abc_FrameSetBatchMode( 0 ); + } + pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + if ( Gia_ManAndNum(pNew) > Gia_ManAndNum(pTemp) ) + { + Gia_ManStop( pNew ); + pNew = Gia_ManDup( pTemp ); + } + return pNew; } void Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int fVerbose ) { @@ -96,7 +99,7 @@ void Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int Vec_IntPush( vRands, Abc_Random(0) % 0x1000000 ); Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { - pNew = Gia_StochProcessOne( pGia, pScript, Vec_IntEntry(vRands, i), TimeSecs ); + pNew = Gia_StochProcessSingle( pGia, pScript, Vec_IntEntry(vRands, i), TimeSecs ); Gia_ManStop( pGia ); Vec_PtrWriteEntry( vGias, i, pNew ); } @@ -135,6 +138,30 @@ typedef struct Gia_StochThData_t_ int fWorking; } Gia_StochThData_t; +Gia_Man_t * Gia_StochProcessOne( Gia_Man_t * p, char * pScript, int Rand, int TimeSecs ) +{ + Gia_Man_t * pNew; + char FileName[100], Command[1000]; + sprintf( FileName, "%06x.aig", Rand ); + Gia_AigerWrite( p, FileName, 0, 0, 0 ); + sprintf( Command, "./abc -q \"&read %s; %s; &write %s\"", FileName, pScript, FileName ); + if ( system( (char *)Command ) ) + { + fprintf( stderr, "The following command has returned non-zero exit status:\n" ); + fprintf( stderr, "\"%s\"\n", (char *)Command ); + fprintf( stderr, "Sorry for the inconvenience.\n" ); + fflush( stdout ); + unlink( FileName ); + return Gia_ManDup(p); + } + pNew = Gia_AigerRead( FileName, 0, 0, 0 ); + unlink( FileName ); + if ( pNew && Gia_ManAndNum(pNew) < Gia_ManAndNum(p) ) + return pNew; + Gia_ManStopP( &pNew ); + return Gia_ManDup(p); +} + void * Gia_StochWorkerThread( void * pArg ) { Gia_StochThData_t * pThData = (Gia_StochThData_t *)pArg; diff --git a/src/aig/gia/giaSupps.c b/src/aig/gia/giaSupps.c index 96721d66b..894e26b7d 100644 --- a/src/aig/gia/giaSupps.c +++ b/src/aig/gia/giaSupps.c @@ -572,6 +572,10 @@ int Supp_FindNextDiv( Supp_Man_t * p, int Pair ) iDiv1 = iDiv1 == -1 ? ABC_INFINITY : iDiv1; iDiv2 = iDiv2 == -1 ? ABC_INFINITY : iDiv2; iDiv = Abc_MinInt( iDiv1, iDiv2 ); + // return -1 if the pair cannot be distinguished by any divisor + // in this case the original resub problem has no solution + if ( iDiv == ABC_INFINITY ) + return -1; assert( iDiv >= 0 && iDiv < Vec_IntSize(p->vCands) ); return iDiv; } @@ -582,6 +586,8 @@ int Supp_ManRandomSolution( Supp_Man_t * p, int iSet, int fVerbose ) { int Pair = Supp_ComputePair( p, iSet ); int iDiv = Supp_FindNextDiv( p, Pair ); + if ( iDiv == -1 ) + return -1; iSet = Supp_ManSubsetAdd( p, iSet, iDiv, fVerbose ); if ( Supp_SetFuncNum(p, iSet) > 0 ) Vec_IntPush( p->vTempSets, iSet ); @@ -883,6 +889,10 @@ Vec_Int_t * Supp_ManCompute( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * { Supp_ManAddPatternsFunc( p, i ); iSet = Supp_ManRandomSolution( p, 0, fVeryVerbose ); + if ( iSet == -1 ) { + Supp_ManDelete( p ); + return NULL; + } for ( r = 0; r < p->nRounds; r++ ) { if ( fVeryVerbose ) @@ -898,6 +908,10 @@ Vec_Int_t * Supp_ManCompute( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * iBest = iSet; } iSet = Supp_ManReconstruct( p, fVeryVerbose ); + if ( iSet == -1 ) { + Supp_ManDelete( p ); + return NULL; + } } if ( fVeryVerbose ) printf( "Matrix size %d.\n", Vec_PtrSize(p->vMatrix) ); diff --git a/src/aig/gia/giaUtil.c b/src/aig/gia/giaUtil.c index dfddc6931..69a6e7235 100644 --- a/src/aig/gia/giaUtil.c +++ b/src/aig/gia/giaUtil.c @@ -3161,6 +3161,119 @@ void Gia_ManPrintArray( Gia_Man_t * p ) printf( "};\n" ); } + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_GetMValue( int i, int nIns, int Mint, unsigned Truth ) +{ + assert( i >= 0 && i < 16 ); + if ( i < nIns ) + return (Mint >> i) & 1; + if ( i == nIns ) + { + if ( Mint < (1 << nIns) ) + return (Truth >> Mint) & 1; + else + return ((Truth >> (Mint-(1 << nIns))) & 1) == 0; + } + else + return 1; +} +void Gia_ManTestProblem() +{ + unsigned Truth = 0xFE; + int i, j, k, c, nIns = 3, nAux = 3; + int nTotal = nIns + 1 + nAux; + int nPairs = nTotal * (nTotal - 1) / 2; + int nMints = (1 << (nIns+1)); + int M[64][100] = {{0}}; + float Value[64] = {0}; + float Solution[100] = {0}; + assert( nMints <= 64 ); + assert( nPairs <= 100 ); + // 7 nodes: 3 inputs + 1 output + 3 aux + // 7*6/2 = 21 pairs + // 16 minterms + for ( k = 0; k < nMints; k++ ) + { + for ( i = c = 0; i < nTotal; i++ ) + for ( j = i+1; j < nTotal; j++ ) + { + int iVal = Gia_GetMValue( i, nIns, k, Truth ); + int jVal = Gia_GetMValue( j, nIns, k, Truth ); + M[k][c++] = iVal == jVal ? 1 : -1; + } + Value[k] = k < (1 << nIns) ? -1 : 1; + assert( c == nPairs ); + } + + for ( k = 0; k < nMints; k++ ) + { + for ( c = 0; c < nPairs; c++ ) + printf( "%2d ", M[k][c] ); + printf( "%3f\n", Value[k] ); + } + + // solve + float Delta = 0.02; + for ( i = 0; i < 100; i++ ) + { + float Error = 0; + for ( k = 0; k < nMints; k++ ) + Error += Value[k] > 0 ? Value[k] : -Value[k]; + printf( "Round %3d : Error = %5f ", i, Error ); + for ( c = 0; c < nPairs; c++ ) + printf( "%2f ", Solution[c] ); + printf( "\n" ); + + //if ( Error < 1 ) + // Delta /= 10; + + for ( c = 0; c < nPairs; c++ ) + { + int Count = 0; + for ( k = 0; k < nMints; k++ ) + if ( (M[k][c] > 0 && Value[k] > 0) || (M[k][c] < 0 && Value[k] < 0) ) + Count++; + else + Count--; + if ( Count == 0 ) + continue; + printf( "Count = %3d ", Count ); + if ( Count > 0 ) + { + printf( "Increasing %d by %f\n", c, Delta ); + Solution[c] += Delta; + for ( k = 0; k < nMints; k++ ) + if ( M[k][c] > 0 ) + Value[k] -= Delta; + else + Value[k] -= Delta; + } + else + { + printf( "Reducing %d by %f\n", c, Delta ); + Solution[c] -= Delta; + for ( k = 0; k < nMints; k++ ) + if ( M[k][c] > 0 ) + Value[k] += Delta; + else + Value[k] += Delta; + } + } + } +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/module.make b/src/aig/gia/module.make index 236d43b32..9e5ae3a57 100644 --- a/src/aig/gia/module.make +++ b/src/aig/gia/module.make @@ -109,4 +109,5 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaTsim.c \ src/aig/gia/giaTtopt.cpp \ src/aig/gia/giaUnate.c \ - src/aig/gia/giaUtil.c + src/aig/gia/giaUtil.c \ + src/aig/gia/giaBound.c \ No newline at end of file diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 5cf7a0f59..58131f185 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -841,7 +841,7 @@ extern ABC_DLL void Abc_NtkPrintFanioNew( FILE * pFile, Abc_Ntk_t extern ABC_DLL void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode ); extern ABC_DLL void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ); extern ABC_DLL void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ); -extern ABC_DLL void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fVerbose ); +extern ABC_DLL void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fOutputs, int fVerbose ); extern ABC_DLL void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ); extern ABC_DLL void Abc_NtkPrintSkews( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintAll ); extern ABC_DLL void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj ); diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index f0fa728c2..0146f6a73 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -139,6 +139,7 @@ static int Abc_CommandTestDec ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandTestNpn ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestRPO ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestTruth ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRunSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -164,6 +165,7 @@ static int Abc_CommandAllExact ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandTestExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMajGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandOrchestrate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAIGAugmentation ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -217,6 +219,7 @@ static int Abc_CommandInter ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandBb2Wb ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandOutdec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandNodeDup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandWrap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestColor ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -402,6 +405,7 @@ static int Abc_CommandAbc9Write ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9WriteLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Ps ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9PFan ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Pms ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9PSig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Status ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9MuxProfile ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -540,6 +544,7 @@ static int Abc_CommandAbc9PoPart ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9GroupProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9MultiProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SplitProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SplitSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Bmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SBmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -595,6 +600,9 @@ static int Abc_CommandAbc9Cfs ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9ProdAdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9AddFlop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenHie ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9BRecover ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9StrEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -842,14 +850,18 @@ Gia_Man_t * Abc_FrameGetGia( Abc_Frame_t * pAbc ) ***********************************************************************/ void Abc_Init( Abc_Frame_t * pAbc ) { + Cmd_CommandAdd( pAbc, "Printing", "ps", Abc_CommandPrintStats, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_stats", Abc_CommandPrintStats, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_exdc", Abc_CommandPrintExdc, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_io", Abc_CommandPrintIo, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_latch", Abc_CommandPrintLatch, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "pfan", Abc_CommandPrintFanio, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_fanio", Abc_CommandPrintFanio, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_mffc", Abc_CommandPrintMffc, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "pf", Abc_CommandPrintFactor, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "psu", Abc_CommandPrintSupport, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_supp", Abc_CommandPrintSupport, 0 ); #ifdef ABC_USE_CUDD Cmd_CommandAdd( pAbc, "Printing", "print_mint", Abc_CommandPrintMint, 0 ); @@ -858,6 +870,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Printing", "print_unate", Abc_CommandPrintUnate, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_auto", Abc_CommandPrintAuto, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_kmap", Abc_CommandPrintKMap, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "pg", Abc_CommandPrintGates, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_gates", Abc_CommandPrintGates, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_sharing", Abc_CommandPrintSharing, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_xcut", Abc_CommandPrintXCut, 0 ); @@ -871,9 +884,12 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 ); Cmd_CommandAdd( pAbc, "Printing", "show_cut", Abc_CommandShowCut, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "clp", Abc_CommandCollapse, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "collapse", Abc_CommandCollapse, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "satclp", Abc_CommandSatClp, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "st", Abc_CommandStrash, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "b", Abc_CommandBalance, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "balance", Abc_CommandBalance, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "mux_struct", Abc_CommandMuxStruct, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "multi", Abc_CommandMulti, 1 ); @@ -903,6 +919,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "testnpn", Abc_CommandTestNpn, 0 ); Cmd_CommandAdd( pAbc, "LogiCS", "testrpo", Abc_CommandTestRPO, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "testtruth", Abc_CommandTestTruth, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "runsat", Abc_CommandRunSat, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "runeco", Abc_CommandRunEco, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "rungen", Abc_CommandRunGen, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "xec", Abc_CommandRunTest, 0 ); @@ -919,6 +936,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "faultclasses", Abc_CommandFaultClasses, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "exact", Abc_CommandExact, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "orchestrate", Abc_CommandOrchestrate, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "aigaug", Abc_CommandAIGAugmentation, 1 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_start", Abc_CommandBmsStart, 0 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_stop", Abc_CommandBmsStop, 0 ); @@ -982,6 +1000,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "bb2wb", Abc_CommandBb2Wb, 0 ); Cmd_CommandAdd( pAbc, "Various", "outdec", Abc_CommandOutdec, 1 ); Cmd_CommandAdd( pAbc, "Various", "nodedup", Abc_CommandNodeDup, 1 ); + Cmd_CommandAdd( pAbc, "Various", "wrap", Abc_CommandWrap, 0 ); Cmd_CommandAdd( pAbc, "Various", "testcolor", Abc_CommandTestColor, 0 ); Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 ); // Cmd_CommandAdd( pAbc, "Various", "qbf_solve", Abc_CommandTest, 0 ); @@ -1165,6 +1184,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&wlut", Abc_CommandAbc9WriteLut, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&ps", Abc_CommandAbc9Ps, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&pfan", Abc_CommandAbc9PFan, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&pms", Abc_CommandAbc9Pms, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&psig", Abc_CommandAbc9PSig, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&status", Abc_CommandAbc9Status, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&profile", Abc_CommandAbc9MuxProfile, 0 ); @@ -1303,6 +1323,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&gprove", Abc_CommandAbc9GroupProve, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&mprove", Abc_CommandAbc9MultiProve, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&splitprove", Abc_CommandAbc9SplitProve, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sprove", Abc_CommandAbc9SProve, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&splitsat", Abc_CommandAbc9SplitSat, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmc", Abc_CommandAbc9Bmc, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmcs", Abc_CommandAbc9SBmc, 0 ); @@ -1364,6 +1385,9 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&prodadd", Abc_CommandAbc9ProdAdd, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&addflop", Abc_CommandAbc9AddFlop, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmiter", Abc_CommandAbc9BMiter, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&gen_hie", Abc_CommandAbc9GenHie, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&brecover", Abc_CommandAbc9BRecover, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&str_eco", Abc_CommandAbc9StrEco, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); { @@ -2000,14 +2024,16 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; int fListNodes; int fProfile; + int fOutputs; int fVerbose; // set defaults fListNodes = 0; fProfile = 1; + fOutputs = 0; fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "npvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "npovh" ) ) != EOF ) { switch ( c ) { @@ -2017,6 +2043,9 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'p': fProfile ^= 1; break; + case 'o': + fOutputs ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -2057,14 +2086,15 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } // process all COs - Abc_NtkPrintLevel( stdout, pNtk, fProfile, fListNodes, fVerbose ); + Abc_NtkPrintLevel( stdout, pNtk, fProfile, fListNodes, fOutputs, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: print_level [-npvh] \n" ); + Abc_Print( -2, "usage: print_level [-npovh] \n" ); Abc_Print( -2, "\t prints information about node level and cone size\n" ); Abc_Print( -2, "\t-n : toggles printing nodes by levels [default = %s]\n", fListNodes? "yes": "no" ); Abc_Print( -2, "\t-p : toggles printing level profile [default = %s]\n", fProfile? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles printing output levels [default = %s]\n", fOutputs? "yes": "no" ); Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tnode : (optional) one node to consider\n"); @@ -7154,6 +7184,94 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRunSat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pFile = NULL; + char * pFileCnf = NULL; + int c, i, fWalk = 0, fKissat = 0, nIters = 10, fVerbose = 0; + abctime clk; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ikwvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'k': + fKissat ^= 1; + break; + case 'w': + fWalk ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( fKissat + fWalk != 1 ) { + printf( "Exactly one SAT solver should be selected.\n" ); + return 1; + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + pFileCnf = argv[globalUtilOptind]; + pFile = fopen( pFileCnf, "rb" ); + if ( pFile == NULL ) { + printf( "The file \"%s\" cannot be found.\n", pFileCnf ); + return 1; + } + fclose( pFile ); + clk = Abc_Clock(); + for ( i = 0; i < nIters; i++ ) { + char pCommand[1000]; + if ( fKissat ) + sprintf( pCommand, "kissat -q --seed=%d %s", i, pFileCnf ); + else if ( fWalk ) + sprintf( pCommand, "walk -s%d %s", i, pFileCnf ); + if (system(pCommand) == -1) { + fprintf(stdout, "Command \"%s\" did not succeed.\n", pCommand); + return 0; + } + } + printf( "Performed %d iterations of SAT solving. ", nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return 0; + +usage: + Abc_Print( -2, "usage: runsat [-I num] [-kwvh] \n" ); + Abc_Print( -2, "\t performs randomized iterations of SAT solving\n" ); + Abc_Print( -2, "\t-I num : the number of iterations [default = %d]\n", nIters ); + Abc_Print( -2, "\t-k : toggle using Kissat (binary name \"kissat\") [default = %s]\n", fKissat? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle using WalkSat (binary name \"walk\") [default = %s]\n", fWalk? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -7538,6 +7656,169 @@ usage: } +/**Function************************************************************* + + Synopsis [] + + Description [AIG RTL Augmentation] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAIGAugmentation( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; + int c, RetValue; + int nNodeSizeMax; + int nConeSizeMax; + int fUpdateLevel; + int fUseZeros_rwr; + int fUseZeros_ref; + int fUseDcs; + int fVerbose; + int RS_CUT_MIN = 4; + int RS_CUT_MAX = 16; + + int fPrecompute; + int fPlaceEnable; + int nNodesMax; + int nCutsMax; + int nLevelsOdc; + int fVeryVerbose; + int Rand_Seed; + //int sOpsOrder; + size_t NtkSize; + char *DecisionFile = NULL; + Vec_Int_t *DecisionMask; + Vec_Int_t *pGain_rwr; + Vec_Int_t *pGain_res; + Vec_Int_t *pGain_ref; + //FILE *maskFile; + extern void Rwr_Precompute(); + extern int Abc_NtkOrchRand( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_rwr, Vec_Int_t **pGain_res,Vec_Int_t **pGain_ref, Vec_Int_t **DecisionMask, char *DecisionFile, int Rand_Seed, int fUseZeros_rwr, int fUseZeros_ref, int fPlaceEnable, int nCutsMax, int nNodesMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose, int nNodeSizeMax, int nConeSizeMax, int fUseDcs ); + // set defaults + nNodeSizeMax = 10; + nConeSizeMax = 16; + fUpdateLevel = 1; + fUseZeros_rwr = 0; + fUseZeros_ref = 0; + fUseDcs = 0; + fVerbose = 0; + fVeryVerbose = 0; + fPlaceEnable = 0; + fPrecompute = 0; + nCutsMax = 8; + nNodesMax = 1; + nLevelsOdc = 0; + Rand_Seed = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "zZdsh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + case 'z': + fUseZeros_rwr ^= 1; + break; + case 'Z': + fUseZeros_ref ^= 1; + break; + case 'd': + if ( globalUtilOptind >= argc ) + { + goto usage; + } + DecisionFile = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 's': + if ( globalUtilOptind >= argc ) + { + goto usage; + } + Rand_Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + } + } + if ( fPrecompute ) + { + Rwr_Precompute(); + return 0; + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( nCutsMax < RS_CUT_MIN || nCutsMax > RS_CUT_MAX ) + { + Abc_Print( -1, "Can only compute cuts for %d <= K <= %d.\n", RS_CUT_MIN, RS_CUT_MAX ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + if ( nNodeSizeMax > 15 ) + { + Abc_Print( -1, "The cone size cannot exceed 15.\n" ); + return 1; + } + + if ( fUseDcs && nNodeSizeMax >= nConeSizeMax ) + { + Abc_Print( -1, "For don't-care to work, containing cone should be larger than collapsed node.\n" ); + return 1; + } + NtkSize = Abc_NtkObjNumMax(pNtk); + + DecisionMask = Vec_IntAlloc(1); + for (int i=0; inSize, DecisionList->pArray[0]); + if ( RetValue == -1 ) + { + Abc_FrameReplaceCurrentNetwork( pAbc, pDup ); + printf( "An error occurred during computation. The original network is restored.\n" ); + } + else + { + Abc_NtkDelete( pDup ); + if ( RetValue == 0 ) + { + Abc_Print( 0, "Orchestration evaluation for RL has failed.\n" ); + return 1; + } + } + // Vec_IntPrint(pGain_rwr); + return 0; + +usage: + Abc_Print( -2, "usage: aigaug [-s ] [-d ][-zZdsh]\n" ); + Abc_Print( -2, "\t performs technology-independent AIG random synthesis (node level) for RTL augmentation\n" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements for rwr for aigaug [default = %s]\n", fUseZeros_rwr? "yes": "no" ); + Abc_Print( -2, "\t-Z : toggle using zero-cost replacements for ref for aigaug [default = %s]\n", fUseZeros_ref? "yes": "no" ); + Abc_Print( -2, "\t-d : record random synthesis decision made during augmentation [required filename; e.g., test.csv]\n"); + Abc_Print( -2, "\t-s : set the random seed for random augmentation\n"); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tExample : read i10.aig;st;aigaug -s 1 -d test.csv;write i10_arg_1.aig;cec i10.aig i10_arg_1.aig\n"); + return 1; +} @@ -9037,11 +9318,12 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) extern void Exa_ManExactSynthesis4( Bmc_EsPar_t * pPars ); extern void Exa_ManExactSynthesis5( Bmc_EsPar_t * pPars ); extern void Exa_ManExactSynthesis6( Bmc_EsPar_t * pPars, char * pFileName ); - int c, fKissat = 0, fKissat2 = 0; + extern void Exa_ManExactSynthesis7( Bmc_EsPar_t * pPars, int GateSize ); + int c, fKissat = 0, fKissat2 = 0, fUseNands = 0, GateSize = 0; Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INTadconugklvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INTGabdconugklvh" ) ) != EOF ) { switch ( c ) { @@ -9078,9 +9360,23 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->RuntimeLim < 0 ) goto usage; break; + case 'G': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" ); + goto usage; + } + GateSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( GateSize < 0 ) + goto usage; + break; case 'a': pPars->fOnlyAnd ^= 1; break; + case 'b': + fUseNands ^= 1; + break; case 'd': pPars->fDynConstr ^= 1; break; @@ -9128,7 +9424,7 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Truth table should be given on the command line.\n" ); return 1; } - if ( (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) + if ( pPars->nVars >= 2 && (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) { Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (pPars->nVars-2)), strlen(pPars->pTtStr) ); return 1; @@ -9143,7 +9439,9 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Function should not have more than 10 inputs.\n" ); return 1; } - if ( fKissat ) + if ( fUseNands ) + Exa_ManExactSynthesis7( pPars, GateSize ); + else if ( fKissat ) Exa_ManExactSynthesis4( pPars ); else if ( fKissat2 ) Exa_ManExactSynthesis5( pPars ); @@ -9154,12 +9452,14 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: twoexact [-INT ] [-adconugklvh] \n" ); + Abc_Print( -2, "usage: twoexact [-INTG ] [-abdconugklvh] \n" ); Abc_Print( -2, "\t exact synthesis of multi-input function using two-input gates\n" ); Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", pPars->nVars ); Abc_Print( -2, "\t-N : the number of two-input nodes [default = %d]\n", pPars->nNodes ); Abc_Print( -2, "\t-T : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); + Abc_Print( -2, "\t-G : the largest allowed gate size (NANDs only) [default = %d]\n", GateSize ); Abc_Print( -2, "\t-a : toggle using only AND-gates (without XOR-gates) [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); + Abc_Print( -2, "\t-b : toggle using only NAND-gates [default = %s]\n", fUseNands ? "yes" : "no" ); Abc_Print( -2, "\t-d : toggle using dynamic constraint addition [default = %s]\n", pPars->fDynConstr ? "yes" : "no" ); Abc_Print( -2, "\t-c : toggle dumping CNF into a file [default = %s]\n", pPars->fDumpCnf ? "yes" : "no" ); Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); @@ -14192,6 +14492,67 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandWrap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char * pFileName = NULL, * pFileName2 = NULL; + FILE * pFile = NULL, * pFile2 = NULL; + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( 1,"Two file names are expected on the command line.\n" ); + return 0; + } + pFileName = argv[globalUtilOptind]; + pFileName2 = argv[globalUtilOptind+1]; + pFile = fopen( pFileName, "rb" ); + pFile2 = fopen( pFileName2, "wb" ); + if ( pFile && pFile2 ) + { + char Buffer[1000]; + while ( fgets( Buffer, 1000, pFile ) != NULL ) + { + if ( Buffer[strlen(Buffer)-1] == '\n' ) + Buffer[strlen(Buffer)-1] = 0; + if ( Buffer[strlen(Buffer)-1] == '\r' ) + Buffer[strlen(Buffer)-1] = 0; + fprintf( pFile2, " printf(\"%s\\n\");\n", Buffer ); + } + } + if ( pFile ) fclose(pFile); + if ( pFile2 ) fclose(pFile2); + return 0; + +usage: + Abc_Print( -2, "usage: wrap [-h] \n" ); + Abc_Print( -2, "\t wrapping lines\n" ); + Abc_Print( -2, "\t : input text file\n"); + Abc_Print( -2, "\t : output text file\n"); + return 1; + +} + /**Function************************************************************* Synopsis [] @@ -14445,7 +14806,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } */ - + //Gia_ManTestProblem(); return 0; usage: Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] \n" ); @@ -19180,7 +19541,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) If_ManSetDefaultPars( pPars ); pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyuojiktncvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYUZDEWSJqaflepmrsdbgxyuojiktncvh" ) ) != EOF ) { switch ( c ) { @@ -19296,6 +19657,30 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nAndDelay < 0 ) goto usage; break; + case 'U': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-U\" should be followed by a positive integer 3, 4, 5, or 6.\n" ); + goto usage; + } + pPars->nLutDecSize = atoi(argv[globalUtilOptind]); + pPars->fUserLut2D = 1; + globalUtilOptind++; + if ( pPars->nLutDecSize < 3 || pPars->nLutDecSize > 6 ) + goto usage; + break; + case 'Z': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Z\" should be followed by a positive integer 3, 4, 5, or 6.\n" ); + goto usage; + } + pPars->nLutDecSize = atoi(argv[globalUtilOptind]); + pPars->fUserLutDec = 1; + globalUtilOptind++; + if ( pPars->nLutDecSize < 3 || pPars->nLutDecSize > 6 ) + goto usage; + break; case 'D': if ( globalUtilOptind >= argc ) { @@ -19343,6 +19728,21 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } break; + case 'J': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by string.\n" ); + goto usage; + } + pPars->pLutStruct = argv[globalUtilOptind]; + pPars->fEnableStructN = 1; + globalUtilOptind++; + if ( strlen(pPars->pLutStruct) != 2 && strlen(pPars->pLutStruct) != 3 ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by a 2-char string (e.g. \"44\" or \"66\" \").\n" ); + goto usage; + } + break; case 'q': pPars->fPreprocess ^= 1; break; @@ -19520,10 +19920,36 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "This feature only works for [6;16]-LUTs.\n" ); return 1; } - pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16; + if ( pPars->fEnableStructN ) + { + pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheckXX; + } + else + { + pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16; + } pPars->fCutMin = 1; } + if ( pPars->fUserLutDec || pPars->fUserLut2D ) + { + if ( pPars->nLutDecSize == 0 ) + { + Abc_Print( -1, "LUT decomposition size (%d) must be set.\n", pPars->nLutDecSize ); + return 1; + } + if ( pPars->nLutDecSize >= pPars->nLutSize ) + { + Abc_Print( -1, "LUT size (%d) must be greater than the LUT decomposition size (%d).\n", pPars->nLutSize, pPars->nLutDecSize ); + return 1; + } + if ( pPars->nLutSize < 4 || pPars->nLutSize > 11 ) + { + Abc_Print( -1, "This feature only works for [4;11]-LUTs.\n" ); + return 1; + } + } + // enable truth table computation if cut minimization is selected if ( pPars->fCutMin ) { @@ -19540,7 +19966,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pLutLib = NULL; } // modify for delay optimization - if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut ) + if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec || pPars->fUserLut2D ) { pPars->fTruth = 1; pPars->fCutMin = 1; @@ -19686,7 +20112,7 @@ usage: sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); - Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" ); + Abc_Print( -2, "usage: if [-KCFAGRNTXYUZ num] [-DEW float] [-SJ str] [-qarlepmsdbgxyuojiktncvh]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); @@ -19698,10 +20124,13 @@ usage: Abc_Print( -2, "\t-T num : the type of LUT structures [default = any]\n" ); Abc_Print( -2, "\t-X num : delay of AND-gate in LUT library units [default = %d]\n", pPars->nAndDelay ); Abc_Print( -2, "\t-Y num : area of AND-gate in LUT library units [default = %d]\n", pPars->nAndArea ); + Abc_Print( -2, "\t-U num : the number of LUT inputs for delay-driven LUT decomposition [default = not used]\n" ); + Abc_Print( -2, "\t-Z num : the number of LUT inputs for delay-driven LUT decomposition [default = not used]\n" ); Abc_Print( -2, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); Abc_Print( -2, "\t-W float : sets wire delay between adjects LUTs [default = %f]\n", pPars->WireDelay ); Abc_Print( -2, "\t-S str : string representing the LUT structure [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" ); + Abc_Print( -2, "\t-J str : string representing the LUT structure (new method) [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" ); Abc_Print( -2, "\t-q : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); Abc_Print( -2, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" ); @@ -31802,16 +32231,21 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) char * pFileName; char ** pArgvNew; int c, nArgcNew; - int fUnique = 0; + int fUnique = 0; int fVerilog = 0; + int fVerNand = 0; int fInter = 0; + int fInterComb = 0; + int fAssign = 0; int fVerBufs = 0; int fMiniAig = 0; int fMiniLut = 0; int fWriteNewLine = 0; + int fReverse = 0; + int fSkipComment = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "upibmlnvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "upqicabmlnrsvh" ) ) != EOF ) { switch ( c ) { @@ -31821,9 +32255,18 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'p': fVerilog ^= 1; break; + case 'q': + fVerNand ^= 1; + break; case 'i': fInter ^= 1; break; + case 'c': + fInterComb ^= 1; + break; + case 'a': + fAssign ^= 1; + break; case 'b': fVerBufs ^= 1; break; @@ -31836,6 +32279,12 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'n': fWriteNewLine ^= 1; break; + case 'r': + fReverse ^= 1; + break; + case 's': + fSkipComment ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -31864,26 +32313,33 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_AigerWriteSimple( pGia, pFileName ); Gia_ManStop( pGia ); } + else if ( fVerNand ) + Gia_ManDumpVerilogNand( pAbc->pGia, pFileName ); else if ( fVerilog ) - Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL, fVerBufs, fInter ); + Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL, fVerBufs, fInter, fInterComb, fAssign, fReverse ); else if ( fMiniAig ) Gia_ManWriteMiniAig( pAbc->pGia, pFileName ); else if ( fMiniLut ) Gia_ManWriteMiniLut( pAbc->pGia, pFileName ); else - Gia_AigerWrite( pAbc->pGia, pFileName, 0, 0, fWriteNewLine ); + Gia_AigerWriteS( pAbc->pGia, pFileName, 0, 0, fWriteNewLine, fSkipComment ); return 0; usage: - Abc_Print( -2, "usage: &w [-upibmlnvh] \n" ); + Abc_Print( -2, "usage: &w [-upqicabmlnsvh] \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-q : toggle writing Verilog with NAND-gates [default = %s]\n", fVerNand? "yes" : "no" ); Abc_Print( -2, "\t-i : toggle writing the interface module in Verilog [default = %s]\n", fInter? "yes" : "no" ); + Abc_Print( -2, "\t-c : toggle writing the interface module in Verilog [default = %s]\n", fInterComb? "yes" : "no" ); + Abc_Print( -2, "\t-a : toggle writing the interface module with assign-statements [default = %s]\n", fAssign? "yes" : "no" ); Abc_Print( -2, "\t-b : toggle writing additional buffers in Verilog [default = %s]\n", fVerBufs? "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-n : toggle writing \'\\n\' after \'c\' in the AIGER file [default = %s]\n", fWriteNewLine? "yes": "no" ); + //Abc_Print( -2, "\t-r : toggle reversing the order of input/output bits [default = %s]\n", fReverse? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle skipping the timestamp in the output file [default = %s]\n", fSkipComment? "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 : the file name\n"); @@ -32113,6 +32569,57 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Pms( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Gia_Obj_t * pObj; + int c, nSat = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9PFan(): There is no AIG.\n" ); + return 1; + } + printf( "Status of %d outputs of the miter: ", Gia_ManPoNum(pAbc->pGia) ); + Gia_ManForEachPo( pAbc->pGia, pObj, c ) + { + printf( "%d", c ); + if ( pAbc->pGia->vNamesOut ) + printf( "(%s)", (char *)Vec_PtrEntry(pAbc->pGia->vNamesOut, c) ); + printf( "=%s ", Gia_ObjFaninLit0p(pAbc->pGia, pObj) == 0 ? "unsat":"sat" ); + nSat += Gia_ObjFaninLit0p(pAbc->pGia, pObj) != 0; + } + printf( "\n" ); + printf( "Total sat = %d. Total unsat = %d.\n", nSat, Gia_ManPoNum(pAbc->pGia)-nSat ); + return 0; + +usage: + Abc_Print( -2, "usage: &pms [-h]\n" ); + Abc_Print( -2, "\t prints miter status after SAT sweeping\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -34124,11 +34631,11 @@ usage: ***********************************************************************/ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) { - int c, fOutputs = 0, nWords = 4, fTruth = 0, fVerbose = 0; + int c, fOutputs = 0, nWords = 4, fTruth = 0, fReverse = 0, fVerbose = 0; char ** pArgvNew; int nArgcNew; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Wtovh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Wtrovh" ) ) != EOF ) { switch ( c ) { @@ -34146,6 +34653,9 @@ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) case 't': fTruth ^= 1; break; + case 'r': + fReverse ^= 1; + break; case 'o': fOutputs ^= 1; break; @@ -34176,7 +34686,7 @@ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); - pAbc->pGia->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(pAbc->pGia) ); + pAbc->pGia->vSimsPi = fReverse ? Vec_WrdStartTruthTablesRev( Gia_ManCiNum(pAbc->pGia) ) : Vec_WrdStartTruthTables( Gia_ManCiNum(pAbc->pGia) ); Vec_WrdFreeP( &pAbc->pGia->vSimsPo ); pAbc->pGia->vSimsPo = Gia_ManSimPatSimOut( pAbc->pGia, pAbc->pGia->vSimsPi, 1 ); return 0; @@ -34219,10 +34729,11 @@ int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &sim_read [-W num] [-tovh] \n" ); + Abc_Print( -2, "usage: &sim_read [-W num] [-trovh] \n" ); Abc_Print( -2, "\t reads simulation patterns from file\n" ); Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", nWords ); Abc_Print( -2, "\t-t : toggle creating exhaustive simulation info [default = %s]\n", fTruth? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle reversing MSB and LSB input variables [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-o : toggle reading output information [default = %s]\n", fOutputs? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -37782,7 +38293,7 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) int fCbs = 1, approxLim = 600, subBatchSz = 1, adaRecycle = 500, nMaxNodes = 0; Cec4_ManSetParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "JWRILDCNPMrmdckngxysopwvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "JWRILDCNPMrmdckngxysopwqvh" ) ) != EOF ) { switch ( c ) { @@ -37935,6 +38446,9 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'w': pPars->fVeryVerbose ^= 1; break; + case 'q': + pPars->fBMiterInfo ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -37999,6 +38513,7 @@ usage: Abc_Print( -2, "\t-o : toggle using the old SAT sweeper [default = %s]\n", fUseIvy? "yes": "no" ); Abc_Print( -2, "\t-p : toggle trying to prove when running the old SAT sweeper [default = %s]\n", fUseProve? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing even more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-q : toggle printing additional information for boundary miters [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -43644,14 +44159,14 @@ usage: ***********************************************************************/ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p ); + extern Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p, int fRandom ); Gia_Man_t * pTemp; Dch_Pars_t Pars, * pPars = &Pars; - int c, fMinLevel = 0, fEquiv = 0; + int c, fMinLevel = 0, fEquiv = 0, fRandom = 0; // set defaults Dch_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfremgcxyvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfremngcxyvh" ) ) != EOF ) { switch ( c ) { @@ -43709,6 +44224,9 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fMinLevel ^= 1; break; + case 'n': + fRandom ^= 1; + break; case 'g': pPars->fUseGia ^= 1; break; @@ -43753,14 +44271,14 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) { pTemp = Gia_ManPerformDch( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); - if ( fMinLevel ) - pTemp = Gia_ManEquivReduce2( pAbc->pGia ); + if ( fMinLevel || fRandom ) + pTemp = Gia_ManEquivReduce2( pAbc->pGia, fRandom ); } Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &dch [-WCS num] [-sptfremgcxyvh]\n" ); + Abc_Print( -2, "usage: &dch [-WCS num] [-sptfremngcxyvh]\n" ); Abc_Print( -2, "\t computes structural choices using a new approach\n" ); Abc_Print( -2, "\t-W num : the max number of simulation words [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); @@ -43771,7 +44289,8 @@ usage: Abc_Print( -2, "\t-f : toggle using lighter logic synthesis [default = %s]\n", pPars->fLightSynth? "yes": "no" ); Abc_Print( -2, "\t-r : toggle skipping choices with redundant support [default = %s]\n", pPars->fSkipRedSupp? "yes": "no" ); Abc_Print( -2, "\t-e : toggle computing and merging equivalences [default = %s]\n", fEquiv? "yes": "no" ); - Abc_Print( -2, "\t-m : toggle minimizing logic level after merging equivalences [default = %s]\n", fMinLevel? "yes": "no" ); + Abc_Print( -2, "\t-m : toggle minimizing logic level after merging equivalences [default = %s]\n", fRandom? "yes": "no" ); + Abc_Print( -2, "\t-n : toggle selecting random choices while merging equivalences [default = %s]\n", fMinLevel? "yes": "no" ); Abc_Print( -2, "\t-g : toggle using GIA to prove equivalences [default = %s]\n", pPars->fUseGia? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using circuit-based SAT vs. MiniSat [default = %s]\n", pPars->fUseCSat? "yes": "no" ); Abc_Print( -2, "\t-x : toggle using new choice computation [default = %s]\n", pPars->fUseNew? "yes": "no" ); @@ -46136,6 +46655,113 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9SProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fVerbose, int fVeryVerbose, int fSilent ); + int c, nProcs = 5, nTimeOut = 3, nTimeOut2 = 10, nTimeOut3 = 100, fVerbose = 0, fVeryVerbose = 0, fSilent = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "PTUWsvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by a positive integer.\n" ); + goto usage; + } + nProcs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nProcs <= 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" ); + goto usage; + } + nTimeOut = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nTimeOut <= 0 ) + goto usage; + break; + case 'U': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-U\" should be followed by a positive integer.\n" ); + goto usage; + } + nTimeOut2 = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nTimeOut2 <= 0 ) + goto usage; + break; + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" ); + goto usage; + } + nTimeOut3 = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nTimeOut3 <= 0 ) + goto usage; + break; + case 's': + fSilent ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9SProve(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) == 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9SProve(): The problem is combinational.\n" ); + return 1; + } + pAbc->Status = Cec_GiaProveTest( pAbc->pGia, nProcs, nTimeOut, nTimeOut2, nTimeOut3, fVerbose, fVeryVerbose, fSilent ); + Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); + return 0; + +usage: + Abc_Print( -2, "usage: &sprove [-PTUW num] [-svwh]\n" ); + Abc_Print( -2, "\t proves CEC problem by case-splitting\n" ); + Abc_Print( -2, "\t-P num : the number of concurrent processes [default = %d]\n", nProcs ); + Abc_Print( -2, "\t-T num : runtime limit in seconds per subproblem [default = %d]\n", nTimeOut ); + Abc_Print( -2, "\t-U num : runtime limit in seconds per subproblem [default = %d]\n", nTimeOut2 ); + Abc_Print( -2, "\t-W num : runtime limit in seconds per subproblem [default = %d]\n", nTimeOut3 ); + Abc_Print( -2, "\t-s : enable silent computation (no reporting) [default = %s]\n", fSilent? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing more verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -51559,11 +52185,21 @@ int Abc_CommandAbc9BMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) char * FileName = NULL; FILE * pFile = NULL; int c, fVerbose = 0; + int bi = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + // TODO: use a flag to block Bnd_Man + while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) { switch ( c ) { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + bi = atoi(argv[globalUtilOptind++]); + break; case 'v': fVerbose ^= 1; break; @@ -51608,14 +52244,430 @@ int Abc_CommandAbc9BMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &bmiter [-vh] \n" ); + Abc_Print( -2, "usage: &bmiter -I [-vh] \n" ); Abc_Print( -2, "\t creates the boundary miter\n" ); + Abc_Print( -2, "\t-I : number of boundary inputs\n" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the implementation file\n"); return 1; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9GenHie( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_GenSandwich( char ** pFNames, int nFNames, char * pFileName ); + char * pFileName = (char *)"sandwich.v"; + int c, fVerbose = 0; + char ** pArgvNew; + int nArgcNew; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a file name.\n" ); + goto usage; + } + pFileName = argv[globalUtilOptind++]; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew < 1 ) + { + Abc_Print( -1, "Abc_CommandAbc9GenHie(): At least one AIG file should be given on the command line.\n" ); + return 0; + } + Gia_GenSandwich( pArgvNew, nArgcNew, pFileName ); + return 0; +usage: + Abc_Print( -2, "usage: &gen_hie [-F ] [-vh] ... \n" ); + Abc_Print( -2, "\t generates a hierarchical design in Verilog\n" ); + Abc_Print( -2, "\t-F : the output file name (optional) [default = \"sandwich.v\"]\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the AIG files for the instance modules\n"); + Abc_Print( -2, "\t (the PO count of should not be less than the PI count of )\n"); + return 1;} + +extern Bnd_Man_t* pBnd; +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9BRecover( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); + extern void Cec4_ManSetParams( Cec_ParFra_t * pPars ); + extern Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ); + Gia_Man_t *pSpec, *pImpl_out = 0, *pSpec_out = 0, *pMiter, *pPatched = 0, *pTemp, *pBmiter; + char * FileName = NULL; + FILE * pFile = NULL; + int c, fVerbose = 0, success = 1, fEq = 1, fEqOut = 1; + + // params + Gps_Par_t Pars, * pPars = &Pars; + memset( pPars, 0, sizeof(Gps_Par_t) ); + Cec_ParCec_t ParsCec, *pParsCec = &ParsCec; + Cec_ManCecSetDefaultParams( pParsCec ); + Cec_ParFra_t ParsFra, *pParsFra = &ParsFra; + Cec4_ManSetParams( pParsFra ); + pParsFra -> fBMiterInfo = 1; + + // parse options + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vhCkeo" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + pParsFra->fVerbose ^= 1; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pParsFra->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParsFra->nBTLimit < 0 ) + goto usage; + break; + case 'k': + pParsFra ->fUseCones ^= 1; + break; + case 'e': + fEq ^= 1; + break; + case 'o': + fEqOut ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9BRecover(): There is no AIG.\n" ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + { + printf("%d\n", argc-globalUtilOptind); + Abc_Print( -1, "Abc_CommandAbc9BRecover(): AIG should be given on the command line.\n" ); + return 0; + } + + // read spec + FileName = argv[globalUtilOptind]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pSpec = Gia_AigerRead( FileName, 0, 1, 0 ); + if ( pSpec == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9BRecover(): Cannot read the file name on the command line.\n" ); + return 0; + } + if ( Gia_ManBufNum(pSpec) == 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9BRecover(): The given spec should be hierarchical.\n" ); + Gia_ManStop(pSpec); + return 0; + } + + // start boundary manager + pBnd = Bnd_ManStart( pSpec, pAbc->pGia, fVerbose ); + + // check boundary + if ( 0 == Bnd_ManCheckBound( pSpec, fVerbose ) ) + { + Abc_Print( -1, "Abc_CommandAbc9BRecover(): The given spec has invalid boundary.\n" ); + success = 0; + } + + if ( success ) + { + // create bmiter, run fraig, record mapping + pBmiter = Bnd_ManStackGias( pSpec, pAbc->pGia ); + pTemp = Cec4_ManSimulateTest( pBmiter, pParsFra ); + + // every output should be equivalent + // else, terminate the command (TODO?) + if ( !Bnd_ManCheckCoMerged( pTemp ) ) + { + Abc_Print( -1, "Abc_CommandAbc9BRecover(): The given spec and impl cannot be proved equivalent.\n" ); + success = 0; + } + + Gia_ManStop(pBmiter); + Gia_ManStop(pTemp); + } + + if ( success ) + { + // find + Bnd_ManFindBound( pSpec, pAbc->pGia ); + + // create spec_out and + pSpec_out = Bnd_ManGenSpecOut( pSpec ); + if ( !pSpec_out ) success = 0; + pImpl_out = Bnd_ManGenImplOut( pAbc->pGia ); + if ( !pImpl_out ) success = 0; + + // Gia_AigerWrite( pSpec_out, "spec_out.aig", 0, 0, 0 ); + // Gia_AigerWrite( pImpl_out, "impl_out.aig", 0, 0, 0 ); + // Gia_ManPrintStats( pSpec_out, pPars ); + // Gia_ManPrintStats( pImpl_out, pPars ); + + if ( !success ) + { + printf("Abc_CommandAbc9BRecover(): The generated boundary is invalid. The circuit is not changed.\n"); + } + } + + if ( success ) + { + + // check if spec_out and imnpl_out are equivalent + if ( fVerbose ) + { + if ( fEqOut ) + { + printf("Checking the equivalence of spec_out and impl_out\n"); + pMiter = Gia_ManMiter( pSpec_out, pImpl_out, 0, 1, 0, 0, 0 ); + Bnd_ManSetEqOut( Cec_ManVerify( pMiter, pParsCec ) ); + Gia_ManStop( pMiter ); + } + else + { + printf("Skip checking the equivalence of spec_out and impl_out\n"); + } + } + + // generate patched impl + if ( fVerbose ) printf("Generating patched impl\n"); + pPatched = Bnd_ManGenPatched1( pImpl_out, pSpec ); + + // // generate patched spec just for debugging + // printf("Generating patched spec\n"); + // pTemp = Bnd_ManGenPatched( pSpec_out, pAbc->pGia, pPatch ); + // printf("Checking the equivalence of patched spec and patched impl\n"); + // pMiter = Gia_ManMiter( pTemp, pPatched, 0, 1, 0, 0, 0 ); + // Cec_ManVerify( pMiter, pParsCec ); + // Gia_ManStop( pMiter ); + // printf("Checking the equivalence of patched spec and patch\n"); + // pMiter = Gia_ManMiter( pTemp, pPatch, 0, 1, 0, 0, 0 ); + // Cec_ManVerify( pMiter, pParsCec ); + // Gia_ManStop( pMiter ); + + // Gia_ManStop( pTemp ); + + // check if patched is equiv to spec + if ( fVerbose ) + { + if ( fEq ) printf("Checking the equivalence of patched impl and spec\n"); + else printf("Skip checking the equivalence of patched impl and spec\n"); + } + if ( fEq ) + { + pMiter = Gia_ManMiter( pSpec, pPatched, 0, 1, 0, 0, 0 ); + success = Cec_ManVerify( pMiter, pParsCec ); + Bnd_ManSetEqRes( success ); + if ( !success ) + { + printf("Failed. The generated AIG is not equivalent.\n"); + } + Gia_ManStop( pMiter ); + } + + } + + if ( fVerbose ) Bnd_ManPrintStats(); + + Gia_ManStop( pSpec ); + if ( pSpec_out ) Gia_ManStop( pSpec_out ); + if ( pImpl_out ) Gia_ManStop( pImpl_out ); + if ( success ) + { + if ( fEq ) printf("Success. The generated hierarchical impl is equivalent. (box size: %d -> %d)\n", Bnd_ManGetNInternal(), Bnd_ManGetNInternal() + Bnd_ManGetNExtra() ); + else printf("Success. But the equivalence in unknown (box size: %d -> %d)\n", Bnd_ManGetNInternal(), Bnd_ManGetNInternal() + Bnd_ManGetNExtra() ); + } + if (pPatched) Abc_FrameUpdateGia( pAbc, pPatched ); + Bnd_ManStop(); + + return 0; + +usage: + Abc_Print( -2, "usage: &brecover -I [-vh] \n" ); + Abc_Print( -2, "\t recover boundary using SAT-Sweeping\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t-k : toggle using logic cones in the SAT solver [default = %s]\n", pParsFra->fUseCones? "yes": "no" ); + Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pParsFra->nBTLimit ); + Abc_Print( -2, "\t-e : toggle checking the equivalence of the result [default = %s]\n", fEq? "yes": "no" ); + Abc_Print( -2, "\t-o : toggle checking the equivalence of the outsides in verbose [default = %s]\n", fEqOut? "yes": "no" ); + Abc_Print( -2, "\t : the implementation aig. (should be equivalent to spec)\n"); + Abc_Print( -2, "\t : the modified spec. (should be a hierarchical AIG)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +int Abc_CommandAbc9StrEco( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); + extern void Cec4_ManSetParams( Cec_ParFra_t * pPars ); + Gia_Man_t *pMiter, *pPatch, *pPatched; + char * FileName = NULL; + FILE * pFile = NULL; + int c, success = 1; + int fVerbose = 0, fSkipStrash = 0; + + // params + Gps_Par_t Pars, * pPars = &Pars; + memset( pPars, 0, sizeof(Gps_Par_t) ); + Cec_ParCec_t ParsCec, *pParsCec = &ParsCec; + Cec_ManCecSetDefaultParams( pParsCec ); + Cec_ParFra_t ParsFra, *pParsFra = &ParsFra; + Cec4_ManSetParams( pParsFra ); + pParsFra -> fBMiterInfo = 1; + + // parse options + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vsh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 's': + fSkipStrash ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9StrEco(): There is no AIG.\n" ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + { + printf("%d\n", argc-globalUtilOptind); + Abc_Print( -1, "Abc_CommandAbc9StrEco(): AIG should be given on the command line.\n" ); + return 0; + } + + // read patch + FileName = argv[globalUtilOptind]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pPatch = Gia_AigerRead( FileName, 0, 1, 0 ); + if ( pPatch == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9StrEco(): Cannot read the file name on the command line.\n" ); + return 0; + } + + // generate patched impl + if ( fVerbose ) printf("Generating patched impl\n"); + pPatched = Bnd_ManGenPatched2( pAbc->pGia, pPatch, fSkipStrash, fVerbose ); + + if ( pPatched ) + { + // check if patched is equiv to patch + if ( fVerbose ) printf("Checking the equivalence of patched impl and patch\n"); + pMiter = Gia_ManMiter( pPatch, pPatched, 0, 1, 0, 0, 0 ); + success = Cec_ManVerify( pMiter, pParsCec ); + if( !success ) + { + printf("Failed. The patched circuit is not equivalent.\n"); + } + Gia_ManStop( pMiter ); + Abc_FrameUpdateGia( pAbc, pPatched ); + } + + Gia_ManStop( pPatch ); + if ( success ) + { + printf("Success. The patched circuit is equivalent.\n"); + } + + return 0; + +usage: + Abc_Print( -2, "usage: &str_eco -I [-vh] \n" ); + Abc_Print( -2, "\t SAT-sweeping-based ECO\n" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles skipping structural hash [default = %s]\n", fSkipStrash? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the implementation aig. (should be equivalent to spec)\n"); + Abc_Print( -2, "\t : the modified spec. (should be a hierarchical AIG)\n"); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c index 491e2c140..8c4ac1448 100644 --- a/src/base/abci/abcIf.c +++ b/src/base/abci/abcIf.c @@ -116,7 +116,7 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk); // update timing info to reflect logic level - if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib) && pNtk->pManTime ) + if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fUserLutDec || pPars->fUserLut2D ) && pNtk->pManTime ) { int c; if ( pNtk->AndGateDelay == 0.0 ) @@ -426,6 +426,127 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC return Abc_NodeBuildFromMiniInt( pMan, p->vArray, If_CutLeaveNum(pCut) ); } +/**Function************************************************************* + Synopsis [Implements decomposed LUT-structure of the cut.] + Description [] + + SideEffects [] + SeeAlso [] + ***********************************************************************/ +void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, If_Obj_t * pIfObj, Vec_Int_t * vCover, Abc_Obj_t * pNodeTop ) +{ + extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); + assert( !pIfMan->pPars->fUseTtPerm ); + + // get the truth table + word * pTruth = If_CutTruthW(pIfMan, pCutBest); + int v; + If_Obj_t * pIfLeaf; + + if ( pCutBest->nLeaves <= pIfMan->pPars->nLutDecSize ) + { + /* add fanins */ + If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, v ) + Abc_ObjAddFanin( pNodeTop, (Abc_Obj_t *)If_ObjCopy( pIfLeaf ) ); + + pNodeTop->Level = Abc_ObjLevelNew( pNodeTop ); + + pNodeTop->pData = Kit_TruthToHop( (Hop_Man_t *)pNtkNew->pManFunc, (unsigned *)pTruth, If_CutLeaveNum(pCutBest), vCover ); + return; + } + + // get the delay profile + unsigned delayProfile = pCutBest->decDelay; + + // perform LUT-decomposition and return the LUT-structure + unsigned char decompArray[92]; + int val; + if ( pIfMan->pPars->fUserLutDec ) + { + val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); + } + else + { + val = acd2_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); + } + assert( val == 0 ); + + // convert the LUT-structure into a set of logic nodes in Abc_Ntk_t + unsigned char bytes_check = decompArray[0]; + assert( bytes_check <= 92 ); + + int byte_p = 2; + unsigned char i, j, k, num_fanins, num_words, num_bytes; + int level, fanin; + word *tt; + Abc_Obj_t *pNewNodes[5]; + + /* create intermediate LUTs */ + assert( decompArray[1] <= 6 ); + Abc_Obj_t * pFanin; + for ( i = 0; i < decompArray[1]; ++i ) + { + if ( i < decompArray[1] - 1 ) + { + pNewNodes[i] = Abc_NtkCreateNode( pNtkNew ); + } + else + { + pNewNodes[i] = pNodeTop; + } + num_fanins = decompArray[byte_p++]; + level = 0; + for ( j = 0; j < num_fanins; ++j ) + { + fanin = (int)decompArray[byte_p++]; + if ( fanin < If_CutLeaveNum(pCutBest) ) + { + pFanin = (Abc_Obj_t *)If_ObjCopy( If_CutLeaf(pIfMan, pCutBest, fanin) ); + } + else + { + assert( fanin - If_CutLeaveNum(pCutBest) < i ); + pFanin = pNewNodes[fanin - If_CutLeaveNum(pCutBest)]; + } + Abc_ObjAddFanin( pNewNodes[i], pFanin ); + level = Abc_MaxInt( level, Abc_ObjLevel(pFanin) ); + } + + pNewNodes[i]->Level = level + (int)(Abc_ObjFaninNum(pNewNodes[i]) > 0); + + /* extract the truth table */ + tt = pIfMan->puTempW; + num_words = ( num_fanins <= 6 ) ? 1 : ( 1 << ( num_fanins - 6 ) ); + num_bytes = ( num_fanins <= 3 ) ? 1 : ( 1 << ( Abc_MinInt( (int)num_fanins, 6 ) - 3 ) ); + for ( j = 0; j < num_words; ++j ) + { + tt[j] = 0; + for ( k = 0; k < num_bytes; ++k ) + { + tt[j] |= ( (word)(decompArray[byte_p++]) ) << ( k << 3 ); + } + } + + /* extend truth table if size < 5 */ + assert( num_fanins != 1 ); + if ( num_fanins == 2 ) + { + tt[0] |= tt[0] << 4; + } + while ( num_bytes < 4 ) + { + tt[0] |= tt[0] << ( num_bytes << 3 ); + num_bytes <<= 1; + } + + /* add node data */ + pNewNodes[i]->pData = Kit_TruthToHop( (Hop_Man_t *)pNtkNew->pManFunc, (unsigned *)tt, (int) num_fanins, vCover ); + } + + /* check correct read */ + assert( byte_p == decompArray[0] ); +} + /**Function************************************************************* Synopsis [Derive one node after FPGA mapping.] @@ -464,13 +585,19 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t pNodeNew = Abc_NtkCreateNode( pNtkNew ); // if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays ) if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm && - !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize ) + !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserLutDec && !pIfMan->pPars->fUserLut2D && !pIfMan->pPars->fUserRecLib && + !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize ) If_CutRotatePins( pIfMan, pCutBest ); if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) { If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i ) Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); } + else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D ) + { + If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) + Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover); + } else { If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) @@ -524,6 +651,11 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj ); } + else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D ) + { + extern void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vMemory, Abc_Obj_t * pNodeTop ); + Abc_DecRecordToHop( pNtkNew, pIfMan, pCutBest, pIfObj, vCover, pNodeNew ); + } else { extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); diff --git a/src/base/abci/abcMiter.c b/src/base/abci/abcMiter.c index 6086fc616..6077a20c2 100644 --- a/src/base/abci/abcMiter.c +++ b/src/base/abci/abcMiter.c @@ -789,6 +789,7 @@ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial, int fVer pNtkFrames->pName = Extra_UtilStrsav(Buffer); // map the constant nodes Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkFrames); + // create new latches (or their initial values) and remember them in the new latches if ( !fInitial ) { diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c index 9de88980d..0676a7d0e 100644 --- a/src/base/abci/abcNtbdd.c +++ b/src/base/abci/abcNtbdd.c @@ -237,7 +237,7 @@ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * { Abc_Obj_t * pNodeNew, * pNodeNew0, * pNodeNew1, * pNodeNewC; assert( !Cudd_IsComplement(bFunc) ); - assert( b1 == a1 ); + //assert( b1 == a1 ); if ( bFunc == a1 ) return Abc_NtkCreateNodeConst1(pNtkNew); if ( bFunc == a0 ) diff --git a/src/base/abci/abcOrchestration.c b/src/base/abci/abcOrchestration.c index fe83891ec..af36939dd 100644 --- a/src/base/abci/abcOrchestration.c +++ b/src/base/abci/abcOrchestration.c @@ -198,7 +198,7 @@ Rwr_ManAddTimeCuts( pManRwr, Abc_Clock() - clk ); pManRwr->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); - printf("nNodes: %d\n", nNodes); + //printf("nNodes: %d\n", nNodes); if ( pGain_rw ) *pGain_rw = Vec_IntAlloc(1); pProgress = Extra_ProgressBarStart( stdout, nNodes ); @@ -489,7 +489,7 @@ int Abc_NtkRefactor3( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_ref, int nNodeSizeMax, Abc_NtkStartReverseLevels( pNtk, 0 ); pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); - printf("nNodes: %d\n", nNodes); + //printf("nNodes: %d\n", nNodes); if (pGain_ref) *pGain_ref = Vec_IntAlloc(1); pProgress = Extra_ProgressBarStart( stdout, nNodes ); @@ -605,7 +605,7 @@ int Abc_NtkResubstitute3( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_res, int nCutMax, // resynthesize each node once pManRes->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); - printf("nNodes: %d\n", nNodes); + //printf("nNodes: %d\n", nNodes); if (pGain_res) *pGain_res = Vec_IntAlloc(1); pProgress = Extra_ProgressBarStart( stdout, nNodes ); @@ -2732,7 +2732,7 @@ Rwr_ManAddTimeCuts( pManRwr, Abc_Clock() - clk ); pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); - printf("nNodes: %d\n", nNodes); + //printf("nNodes: %d\n", nNodes); if (pGain_res) *pGain_res = Vec_IntAlloc(1); if (pGain_ref) *pGain_ref = Vec_IntAlloc(1); if (pGain_rwr) *pGain_rwr = Vec_IntAlloc(1); @@ -5318,6 +5318,319 @@ s_ResubTime = Abc_Clock() - clkStart; return 1; } +// orchestration with sudo random decision list +int Abc_NtkOrchRand( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_rwr, Vec_Int_t **pGain_res,Vec_Int_t **pGain_ref, Vec_Int_t **DecisionMask, char * DecisionFile, int Rand_Seed, int fUseZeros_rwr, int fUseZeros_ref, int fPlaceEnable, int nCutMax, int nStepsMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose, int nNodeSizeMax, int nConeSizeMax, int fUseDcs ) +{ + extern int Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); + ProgressBar * pProgress; + // For resub + Abc_ManRes_t * pManRes; + Abc_ManCut_t * pManCutRes; + Odc_Man_t * pManOdc = NULL; + Dec_Graph_t * pFFormRes; + Vec_Ptr_t * vLeaves; + // For rewrite + Cut_Man_t * pManCutRwr; + Rwr_Man_t * pManRwr; + Dec_Graph_t * pGraph; + // For refactor + Abc_ManRef_t * pManRef; + Abc_ManCut_t * pManCutRef; + Dec_Graph_t * pFFormRef; + Vec_Ptr_t * vFanins; + + Abc_Obj_t * pNode; + FILE *fpt; + abctime clk, clkStart = Abc_Clock(); + int i, nNodes, nNodes_after, nGain, fCompl; + int RetValue = 1; + int ops_rwr = 0; + int ops_res = 0; + int ops_ref = 0; + int ops_null = 0; + int Valid_Len = 0; + //Vec_Int_t *Valid_Ops; + + //clock_t begin= clock(); + assert( Abc_NtkIsStrash(pNtk) ); + + // cleanup the AIG + Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc); + + // start the managers resub + pManCutRes = Abc_NtkManCutStart( nCutMax, 100000, 100000, 100000 ); + pManRes = Abc_ManResubStart( nCutMax, ABC_RS_DIV1_MAX ); + if ( nLevelsOdc > 0 ) + pManOdc = Abc_NtkDontCareAlloc( nCutMax, nLevelsOdc, fVerbose, fVeryVerbose ); + // start the managers refactor + pManCutRef = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, 1000 ); + pManRef = Abc_NtkManRefStart_1( nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose ); + pManRef->vLeaves = Abc_NtkManCutReadCutLarge( pManCutRef ); + // start the managers rewrite + pManRwr = Rwr_ManStart( 0 ); + if ( pManRwr == NULL ) + return 0; + + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Abc_NtkStartReverseLevels( pNtk, 0 ); + + // 'Resub only' + + if ( Abc_NtkLatchNum(pNtk) ) { + Abc_NtkForEachLatch(pNtk, pNode, i) + pNode->pNext = (Abc_Obj_t *)pNode->pData; + } + + // cut manager for rewrite +clk = Abc_Clock(); + pManCutRwr = Abc_NtkStartCutManForRewrite( pNtk ); +Rwr_ManAddTimeCuts( pManRwr, Abc_Clock() - clk ); + pNtk->pManCut = pManCutRwr; + + if ( fVeryVerbose ) + Rwr_ScoresClean( pManRwr ); + + // resynthesize each node once + // resub + pManRes->nNodesBeg = Abc_NtkNodeNum(pNtk); + // rewrite + pManRwr->nNodesBeg = Abc_NtkNodeNum(pNtk); + // refactor + pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk); + +//clock_t resyn_end=clock(); +//double resyn_time_spent = (double)(resyn_end-begin)/CLOCKS_PER_SEC; +//printf("time %f\n", resyn_time_spent); + nNodes = Abc_NtkObjNumMax(pNtk); + //printf("nNodes: %d\n", nNodes); + //for(int i=0; i < nNodes; i++){printf("mask check: %d\n", (*DecisionMask)->pArray[i]);} + //printf("mask size:%d", (**DecisionMask).nSize); + if (pGain_res) *pGain_res = Vec_IntAlloc(1); + if (pGain_ref) *pGain_ref = Vec_IntAlloc(1); + if (pGain_rwr) *pGain_rwr = Vec_IntAlloc(1); + Vec_Int_t *Valid_Ops = Vec_IntAlloc(1); + + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + fpt = fopen(DecisionFile, "w"); + + Abc_NtkForEachNode( pNtk, pNode, i ) + { + //printf("Ochestration id: %d\n", pNode->Id); + int iterNode = pNode->Id; + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // skip the constant node +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + // skip persistant nodes + if ( Abc_NodeIsPersistant(pNode) ) + { + //fprintf(fpt, "%d, %s, %d\n", pNode->Id, "None" , -99); + Vec_IntPush((*pGain_res), -99); + Vec_IntPush((*pGain_ref), -99); + Vec_IntPush((*pGain_rwr), -99); + continue; + } + // skip the nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + { + //fprintf(fpt, "%d, %s, %d\n", pNode->Id,"None", -99); + Vec_IntPush((*pGain_res), -99); + Vec_IntPush((*pGain_ref), -99); + Vec_IntPush((*pGain_rwr), -99); + continue; + } +clk = Abc_Clock(); + +// Generate random operation +// check transformability of all three operations + Vec_IntPush( (Valid_Ops), -1); + nGain = Rwr_NodeRewrite( pManRwr, pManCutRwr, pNode, fUpdateLevel, fUseZeros_rwr, fPlaceEnable ); + Vec_IntPush( (*pGain_rwr), nGain); + if (nGain > 0 || (nGain == 0 && fUseZeros_rwr)) + { + Vec_IntPush( (Valid_Ops), 0); + } + vLeaves = Abc_NodeFindCut( pManCutRes, pNode, 0 ); + pManRes->timeCut += Abc_Clock() - clk; + if ( pManOdc ) + { +clk = Abc_Clock(); + Abc_NtkDontCareClear( pManOdc ); + Abc_NtkDontCareCompute( pManOdc, pNode, vLeaves, pManRes->pCareSet ); +pManRes->timeTruth += Abc_Clock() - clk; + } +clk = Abc_Clock(); + pFFormRes = Abc_ManResubEval( pManRes, pNode, vLeaves, nStepsMax, fUpdateLevel, fVerbose ); +pManRes->timeRes += Abc_Clock() - clk; + Vec_IntPush((*pGain_res), pManRes->nLastGain); + if (pManRes->nLastGain > 0) + { + if ( pFFormRes != NULL ){ + Vec_IntPush( (Valid_Ops), 1); + } + } + + vFanins = Abc_NodeFindCut( pManCutRef, pNode, fUseDcs ); +pManRef->timeCut += Abc_Clock() - clk; +clk = Abc_Clock(); + pFFormRef = Abc_NodeRefactor_1( pManRef, pNode, vFanins, fUpdateLevel, fUseZeros_ref, fUseDcs, fVerbose ); +pManRef->timeRes += Abc_Clock() - clk; + + Vec_IntPush((*pGain_ref), pManRef->nLastGain); + if (pManRef->nLastGain > 0 || (pManRef->nLastGain ==0 && fUseZeros_ref)) + { + if ( pFFormRef != NULL ){ + Vec_IntPush( (Valid_Ops), 2); + } + } + Valid_Len = (Valid_Ops)->nSize; + //printf("The length of valid operations: %d\n", Valid_Len); + +//Pick a random operations from valid ones +if (Rand_Seed == -1) +{ + srand(time(NULL)); +} +else +{ + srand(Rand_Seed); +} + +int r = rand() % Valid_Len; + + if ((Valid_Ops)->pArray[r] == -1){ + (*DecisionMask)->pArray[iterNode] = -1; + ops_null++; + Vec_IntZero(Valid_Ops); // reset updates + continue; + } + else if ((Valid_Ops->pArray[r]) == 0){ + // apply rewrite + pGraph = (Dec_Graph_t *)Rwr_ManReadDecs(pManRwr); + fCompl = Rwr_ManReadCompl(pManRwr); + if ( fPlaceEnable ) + Abc_AigUpdateReset( (Abc_Aig_t *)pNtk->pManFunc ); + if ( fCompl ) Dec_GraphComplement( pGraph ); +clk = Abc_Clock(); + Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain ); +Rwr_ManAddTimeUpdate( pManRwr, Abc_Clock() - clk ); + if ( fCompl ) Dec_GraphComplement( pGraph ); + (*DecisionMask)->pArray[iterNode] = 0; + ops_rwr++; + Vec_IntZero(Valid_Ops); // reset updates + continue; + } + else if ((Valid_Ops->pArray[r] == 1)){ + // apply res + pManRes->nTotalGain += pManRes->nLastGain; +clk = Abc_Clock(); + Dec_GraphUpdateNetwork( pNode, pFFormRes, fUpdateLevel, pManRes->nLastGain ); +pManRes->timeNtk += Abc_Clock() - clk; + Dec_GraphFree( pFFormRes ); + (*DecisionMask)->pArray[iterNode] = 1; + ops_res++; + Vec_IntZero(Valid_Ops); // reset updates + continue; + } + else if ((Valid_Ops->pArray[r] == 2)){ +clk = Abc_Clock(); + if ( !Dec_GraphUpdateNetwork( pNode, pFFormRef, fUpdateLevel, pManRef->nLastGain ) ) + { + Dec_GraphFree( pFFormRef ); + RetValue = -1; + break; + } +pManRef->timeNtk += Abc_Clock() - clk; + Dec_GraphFree( pFFormRef ); + (*DecisionMask)->pArray[iterNode] = 2; + ops_ref++; + Vec_IntZero(Valid_Ops); // reset updates + continue; + } + } + //fwrite((**DecisionMask).pArray, sizeof(int), sizeof((**DecisionMask).pArray), fpt); + for (int i = 0; i < (nNodes); i++){ + fprintf(fpt, "%d\n", (*DecisionMask)->pArray[i]);} + fclose(fpt); +/* + printf("size of vector %d\n", Valid_Len); + printf("Nodes with rewrite: %d\n", ops_rwr); + printf("Nodes with resub: %d\n", ops_res); + printf("Nodes with refactor: %d\n", ops_ref); + printf("Nodes without updates: %d\n", ops_null); +*/ + Extra_ProgressBarStop( pProgress ); +// Rewrite +Rwr_ManAddTimeTotal( pManRwr, Abc_Clock() - clkStart ); + pManRwr->nNodesEnd = Abc_NtkNodeNum(pNtk); + +// Resub +pManRes->timeTotal = Abc_Clock() - clkStart; + pManRes->nNodesEnd = Abc_NtkNodeNum(pNtk); + +// Refactor +pManRef->timeTotal = Abc_Clock() - clkStart; + pManRef->nNodesEnd = Abc_NtkNodeNum(pNtk); + + // print statistics + if ( fVerbose ){ + Abc_ManResubPrint( pManRes ); + Rwr_ManPrintStats( pManRwr ); + Abc_NtkManRefPrintStats_1( pManRef ); + } + if ( fVeryVerbose ) + Rwr_ScoresReport( pManRwr ); + // delete the managers + // resub + Abc_ManResubStop( pManRes ); + Abc_NtkManCutStop( pManCutRes ); + // rewrite + Rwr_ManStop( pManRwr ); + Cut_ManStop( pManCutRwr ); + pNtk->pManCut = NULL; + // refactor + Abc_NtkManCutStop( pManCutRef ); + Abc_NtkManRefStop_1( pManRef ); + + if ( pManOdc ) Abc_NtkDontCareFree( pManOdc ); + + // clean the data field + Abc_NtkForEachObj( pNtk, pNode, i ) + pNode->pData = NULL; + + if ( Abc_NtkLatchNum(pNtk) ) { + Abc_NtkForEachLatch(pNtk, pNode, i) + pNode->pData = pNode->pNext, pNode->pNext = NULL; + } + + // put the nodes into the DFS order and reassign their IDs + Abc_NtkReassignIds( pNtk ); +// Abc_AigCheckFaninOrder( pNtk->pManFunc ); + + // fix the levels + if ( fUpdateLevel ) + Abc_NtkStopReverseLevels( pNtk ); + else + Abc_NtkLevel( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkOchestraction: The network check has failed.\n" ); + return 0; + } + nNodes_after = Abc_NtkObjNumMax(pNtk); + //printf("nNodes after optimization: %d\n", nNodes_after); +//s_ResubTime = Abc_Clock() - clkStart; +//clock_t end=clock(); +//double time_spent = (double)(end-begin)/CLOCKS_PER_SEC; +//printf("time %f\n", time_spent); + return 1; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c index 7b566b79d..636665249 100644 --- a/src/base/abci/abcPrint.c +++ b/src/base/abci/abcPrint.c @@ -224,6 +224,37 @@ float Abc_NtkGetArea( Abc_Ntk_t * pNtk ) return Counter; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Abc_NtkGetAreaSpecial( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; int i, Count = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( !strncmp( Mio_GateReadName((Mio_Gate_t*)pObj->pData), "mm", 2 ) ) + Count++; + return 1.0*Count/Abc_NtkNodeNum(pNtk); +} +float Abc_NtkGetAreaSpecial2( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; int i; + float Count = 0, CountAll = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) { + if ( !strncmp( Mio_GateReadName((Mio_Gate_t*)pObj->pData), "mm", 2 ) ) + Count += Mio_GateReadArea((Mio_Gate_t*)pObj->pData); + CountAll += Mio_GateReadArea((Mio_Gate_t*)pObj->pData); + } + return 1.0*Count/CountAll; +} + /**Function************************************************************* Synopsis [Print the vital stats of the network.] @@ -360,7 +391,7 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum if ( fPrintMem ) Abc_Print( 1," mem =%5.2f MB", Abc_NtkMemory(pNtk)/(1<<20) ); Abc_Print( 1,"\n" ); - +/* // print the statistic into a file if ( fDumpResult ) { @@ -374,6 +405,8 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum fprintf( pTable, "\n" ); fclose( pTable ); } +*/ + /* { FILE * pTable; @@ -389,21 +422,6 @@ void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDum } */ -/* - // print the statistic into a file - { - FILE * pTable; - pTable = fopen( "ucsb/stats.txt", "a+" ); -// fprintf( pTable, "%s ", pNtk->pSpec ); - fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); -// fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); -// fprintf( pTable, "%.0f ", Abc_NtkGetMappedArea(pNtk) ); -// fprintf( pTable, "%.2f ", Abc_NtkDelayTrace(pNtk) ); - fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ - /* // print the statistic into a file { @@ -1210,11 +1228,19 @@ char * Abc_NodeGetPrintName( Abc_Obj_t * pObj ) } return Abc_ObjName(nPos == 1 ? pFanout : pObj); } -void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fVerbose ) +void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fOutputs, int fVerbose ) { Abc_Obj_t * pNode; int i, k, Length; - + if ( fOutputs ) + { + Abc_NtkLevel(pNtk); + printf( "Outputs by level: " ); + Abc_NtkForEachCo( pNtk, pNode, k ) + printf( "%d=%d ", k, Abc_ObjFanin0(pNode)->Level ); + printf( "\n" ); + return; + } if ( fListNodes ) { int nLevels; diff --git a/src/base/acb/acbTest.c b/src/base/acb/acbTest.c index c664eadaf..c22d4b55b 100644 --- a/src/base/acb/acbTest.c +++ b/src/base/acb/acbTest.c @@ -421,8 +421,8 @@ Gia_Man_t * Acb_NtkGiaDeriveMiter( Gia_Man_t * pOne, Gia_Man_t * pTwo, int Type { for ( i = 0; i < Gia_ManCoNum(pOne); i += 2 ) { - int pLitsF[2] = { (int)Gia_ManCo(pOne, i)->Value, (int)Gia_ManCo(pOne, i+1)->Value }; - int pLitsS[2] = { (int)Gia_ManCo(pTwo, i)->Value, (int)Gia_ManCo(pTwo, i+1)->Value }; + unsigned pLitsF[2] = { Gia_ManCo(pOne, i)->Value, Gia_ManCo(pOne, i+1)->Value }; + unsigned pLitsS[2] = { Gia_ManCo(pTwo, i)->Value, Gia_ManCo(pTwo, i+1)->Value }; Gia_ManAppendCo( pNew, pLitsF[0] ); Gia_ManAppendCo( pNew, pLitsS[0] ); } @@ -431,8 +431,8 @@ Gia_Man_t * Acb_NtkGiaDeriveMiter( Gia_Man_t * pOne, Gia_Man_t * pTwo, int Type { for ( i = 0; i < Gia_ManCoNum(pOne); i += 2 ) { - int pLitsF[2] = { (int)Gia_ManCo(pOne, i)->Value, (int)Gia_ManCo(pOne, i+1)->Value }; - int pLitsS[2] = { (int)Gia_ManCo(pTwo, i)->Value, (int)Gia_ManCo(pTwo, i+1)->Value }; + unsigned pLitsF[2] = { Gia_ManCo(pOne, i)->Value, Gia_ManCo(pOne, i+1)->Value }; + unsigned pLitsS[2] = { Gia_ManCo(pTwo, i)->Value, Gia_ManCo(pTwo, i+1)->Value }; Gia_ManAppendCo( pNew, pLitsF[1] ); Gia_ManAppendCo( pNew, pLitsS[1] ); } diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index d2acec097..c8dd44325 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -22,6 +22,7 @@ #include #else #include +#include #endif #include "base/abc/abc.h" @@ -36,6 +37,7 @@ ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// static int CmdCommandTime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandSleep ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandEcho ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandQuit ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandAbcrc ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -54,8 +56,11 @@ static int CmdCommandScanDir ( Abc_Frame_t * pAbc, int argc, char ** argv static int CmdCommandRenameFiles ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandLs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandScrGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#else +static int CmdCommandScrGenLinux ( Abc_Frame_t * pAbc, int argc, char ** argv ); #endif static int CmdCommandVersion ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandSGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandSis ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandMvsis ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandCapo ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -86,6 +91,7 @@ void Cmd_Init( Abc_Frame_t * pAbc ) Cmd_HistoryRead( pAbc ); Cmd_CommandAdd( pAbc, "Basic", "time", CmdCommandTime, 0 ); + Cmd_CommandAdd( pAbc, "Basic", "sleep", CmdCommandSleep, 0 ); Cmd_CommandAdd( pAbc, "Basic", "echo", CmdCommandEcho, 0 ); Cmd_CommandAdd( pAbc, "Basic", "quit", CmdCommandQuit, 0 ); Cmd_CommandAdd( pAbc, "Basic", "abcrc", CmdCommandAbcrc, 0 ); @@ -104,8 +110,11 @@ void Cmd_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Basic", "renamefiles", CmdCommandRenameFiles, 0 ); Cmd_CommandAdd( pAbc, "Basic", "ls", CmdCommandLs, 0 ); Cmd_CommandAdd( pAbc, "Basic", "scrgen", CmdCommandScrGen, 0 ); +#else + Cmd_CommandAdd( pAbc, "Basic", "scrgen", CmdCommandScrGenLinux, 0 ); #endif Cmd_CommandAdd( pAbc, "Basic", "version", CmdCommandVersion, 0 ); + Cmd_CommandAdd( pAbc, "Basic", "sgen", CmdCommandSGen, 0 ); Cmd_CommandAdd( pAbc, "Various", "sis", CmdCommandSis, 1 ); Cmd_CommandAdd( pAbc, "Various", "mvsis", CmdCommandMvsis, 1 ); @@ -221,6 +230,65 @@ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) return 1; } +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandSleep( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + abctime clkStop; + char * pFileName = NULL; + int c, nSecs = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nSecs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSecs < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc == globalUtilOptind + 1 ) { + FILE * pFile = NULL; + pFileName = argv[globalUtilOptind]; + while ( (pFile = fopen(pFileName, "rb")) == NULL ); + if ( pFile != NULL ) + fclose( pFile ); + } + + clkStop = Abc_Clock() + nSecs * CLOCKS_PER_SEC; + while ( Abc_Clock() < clkStop ); + return 0; + + usage: + fprintf( pAbc->Err, "usage: sleep [-N ] [-h] \n" ); + fprintf( pAbc->Err, "\t puts ABC to sleep for some time\n" ); + fprintf( pAbc->Err, "\t-N num : time duration in seconds [default = %d]\n", nSecs ); + fprintf( pAbc->Err, "\t-h : toggle printing the command usage\n" ); + fprintf( pAbc->Err, "\t : (optional) waiting begins after the file is created\n" ); + return 1; +} /**Function******************************************************************** Synopsis [] @@ -1628,11 +1696,11 @@ int CmdCommandScrGen( Abc_Frame_t * pAbc, int argc, char **argv ) int nFileNameMax, nFileNameCur; int Counter = 0; int fUseCurrent; - char c; + int c; fUseCurrent = 0; Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "FDCWch") ) != EOF ) + while ( (c = Extra_UtilGetopt(argc, argv, "FRCWch") ) != EOF ) { switch (c) { @@ -1645,7 +1713,7 @@ int CmdCommandScrGen( Abc_Frame_t * pAbc, int argc, char **argv ) pFileStr = argv[globalUtilOptind]; globalUtilOptind++; break; - case 'D': + case 'R': if ( globalUtilOptind >= argc ) { fprintf( pAbc->Err, "Command line switch \"-D\" should be followed by a string.\n" ); @@ -1795,7 +1863,7 @@ int CmdCommandScrGen( Abc_Frame_t * pAbc, int argc, char **argv ) Line[c] = '/'; fprintf( pFile, "%s", Line ); } - fprintf( pFile, "\n", Line ); + fprintf( pFile, "\n" ); } while( _findnext( hFile, &c_file ) == 0 ); _findclose( hFile ); @@ -1815,17 +1883,178 @@ int CmdCommandScrGen( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; usage: - fprintf( pAbc->Err, "usage: scrgen -F -D -C -W -ch\n" ); + fprintf( pAbc->Err, "usage: scrgen -F -R -C -W -ch\n" ); fprintf( pAbc->Err, "\t generates script for running ABC\n" ); fprintf( pAbc->Err, "\t-F str : the name of the script file [default = \"test.s\"]\n" ); - fprintf( pAbc->Err, "\t-D str : the directory to read files from [default = current]\n" ); + fprintf( pAbc->Err, "\t-R str : the directory to read files from [default = current]\n" ); fprintf( pAbc->Err, "\t-C str : the sequence of commands to run [default = \"ps\"]\n" ); fprintf( pAbc->Err, "\t-W str : the directory to write the resulting files [default = no writing]\n" ); fprintf( pAbc->Err, "\t-c : toggle placing file in current/target dir [default = %s]\n", fUseCurrent? "current": "target" ); fprintf( pAbc->Err, "\t-h : print the command usage\n\n"); - fprintf( pAbc->Err, "\tExample : scrgen -F test1.s -D a/in -C \"ps; st; ps\" -W a/out\n" ); + fprintf( pAbc->Err, "\tExample : scrgen -F test1.s -R a/in -C \"ps; st; ps\" -W a/out\n" ); return 1; } + +#else + +Vec_Ptr_t * CmdReturnFileNames( char * pDirStr ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( 100 ); + struct dirent **namelist; + int num_files = scandir(pDirStr, &namelist, NULL, alphasort); + if (num_files == -1) { + printf("Error opening directory.\n"); + return NULL; + } + for (int i = 0; i < num_files; i++) { + char * pExt = strstr(namelist[i]->d_name, "."); + if ( !pExt || !strcmp(pExt, ".") || !strcmp(pExt, "..") || !strcmp(pExt, ".s") || !strcmp(pExt, ".txt") ) + continue; + Vec_PtrPush( vRes, Abc_UtilStrsav(namelist[i]->d_name) ); + free(namelist[i]); + } + free(namelist); + return vRes; +} + +int CmdCommandScrGenLinux( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Vec_Ptr_t * vNames = NULL; + FILE * pFile = NULL; + char * pFileStr = (char *)"test.s"; + char * pDirStr = (char *)"."; + char * pComStr = (char *)"ps"; + char * pWriteStr = NULL; + char * pWriteExt = NULL; + char Line[2000], * pName; + int nFileNameMax; + int fBatch = 0; + int c, k; + + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "FRCWEbh") ) != EOF ) + { + switch (c) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pAbc->Err, "Command line switch \"-F\" should be followed by a string.\n" ); + goto usage; + } + pFileStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + fprintf( pAbc->Err, "Command line switch \"-D\" should be followed by a string.\n" ); + goto usage; + } + pDirStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pAbc->Err, "Command line switch \"-C\" should be followed by a string.\n" ); + goto usage; + } + pComStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'W': + if ( globalUtilOptind >= argc ) + { + fprintf( pAbc->Err, "Command line switch \"-W\" should be followed by a string.\n" ); + goto usage; + } + pWriteStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'E': + if ( globalUtilOptind >= argc ) + { + fprintf( pAbc->Err, "Command line switch \"-E\" should be followed by a string.\n" ); + goto usage; + } + pWriteExt = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'b': + fBatch ^= 1; + break; + default: + goto usage; + } + } + pFile = fopen( pFileStr, "w" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file %s.\n", pFileStr ); + return 0; + } + vNames = CmdReturnFileNames( pDirStr ); + if ( !vNames || !Vec_PtrSize(vNames) ) + { + if ( vNames ) + printf( "It looks like the directory \"%s\" does not contain any relevant files.\n", pDirStr ); + Vec_PtrFreeP(&vNames); + return 0; + } + nFileNameMax = 0; + Vec_PtrForEachEntry( char *, vNames, pName, k ) + if ( nFileNameMax < strlen(pName) ) + nFileNameMax = strlen(pName); + { + int fAndSpace = pComStr[0] == '&'; + fprintf( pFile, "# Script file produced by ABC on %s\n", Extra_TimeStamp() ); + fprintf( pFile, "# Command line was: scrgen -F %s -D %s -C \"%s\"%s%s%s%s\n", + pFileStr, pDirStr, pComStr, + pWriteStr?" -W ":"", pWriteStr?pWriteStr:"", + pWriteExt?" -E ":"", pWriteExt?pWriteExt:"" ); + Vec_PtrForEachEntry( char *, vNames, pName, k ) { + char * pExt = strstr(pName, "."); + if ( !pExt || !strcmp(pExt, ".") || !strcmp(pExt, "..") || !strcmp(pExt, ".s") || !strcmp(pExt, ".txt") ) + continue; + sprintf( Line, "%s%sread %s%s%-*s ; %s", fBatch ? "./abc -q \"":"", fAndSpace ? "&" : "", pDirStr?pDirStr:"", pDirStr?"/":"", nFileNameMax, pName, pComStr ); + for ( c = (int)strlen(Line)-1; c >= 0; c-- ) + if ( Line[c] == '\\' ) + Line[c] = '/'; + fprintf( pFile, "%s", Line ); + if ( pWriteStr ) + { + char * pFNameOut = pWriteExt ? Extra_FileNameGenericAppend(pName, pWriteExt) : pName; + sprintf( Line, " ; %swrite %s/%-*s", fAndSpace ? "&" : "", pWriteStr, nFileNameMax, pFNameOut ); + for ( c = (int)strlen(Line)-1; c >= 0; c-- ) + if ( Line[c] == '\\' ) + Line[c] = '/'; + fprintf( pFile, "%s", Line ); + } + if ( fBatch ) + fprintf( pFile, "\"" ); + fprintf( pFile, "\n" ); + } + } + fclose( pFile ); + printf( "Script file \"%s\" with command lines for %d files.\n", pFileStr, Vec_PtrSize(vNames) ); + Vec_PtrFreeFree( vNames ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: scrgen -F -R -C -W -E -bh\n" ); + fprintf( pAbc->Err, "\t generates script for running ABC\n" ); + fprintf( pAbc->Err, "\t-F str : the name of the script file [default = \"test.s\"]\n" ); + fprintf( pAbc->Err, "\t-R str : the directory to read files from [default = current]\n" ); + fprintf( pAbc->Err, "\t-C str : the sequence of commands to run [default = \"ps\"]\n" ); + fprintf( pAbc->Err, "\t-W str : the directory to write the resulting files [default = no writing]\n" ); + fprintf( pAbc->Err, "\t-E str : the output files extension (with \".\") [default = the same as input files]\n" ); + fprintf( pAbc->Err, "\t-b : toggles adding batch mode support [default = %s]\n", fBatch? "yes": "no" ); + fprintf( pAbc->Err, "\t-h : print the command usage\n\n"); + fprintf( pAbc->Err, "\tExample : scrgen -F test1.s -R a/in -C \"ps; st; ps\" -W a/out -E .blif\n" ); + return 1; +} + #endif @@ -2385,18 +2614,18 @@ usage: ***********************************************************************/ int CmdCommandStarter( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores ); + extern void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores, int fVerbose ); FILE * pFile; char * pFileName; char * pCommand = NULL; int c, nCores = 3; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NCvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PCvh" ) ) != EOF ) { switch ( c ) { - case 'N': + case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); @@ -2443,13 +2672,13 @@ int CmdCommandStarter( Abc_Frame_t * pAbc, int argc, char ** argv ) } fclose( pFile ); // run commands - Cmd_RunStarter( pFileName, pAbc->sBinary, pCommand, nCores ); + Cmd_RunStarter( pFileName, pAbc->sBinary, pCommand, nCores, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: starter [-N num] [-C cmd] [-vh] \n" ); + Abc_Print( -2, "usage: starter [-P num] [-C cmd] [-vh] \n" ); Abc_Print( -2, "\t runs command lines listed in concurrently on CPUs\n" ); - Abc_Print( -2, "\t-N num : the number of concurrent jobs including the controller [default = %d]\n", nCores ); + Abc_Print( -2, "\t-P num : the number of concurrent jobs including the controller [default = %d]\n", nCores ); Abc_Print( -2, "\t-C cmd : (optional) ABC command line to execute on benchmarks in \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"); @@ -2606,6 +2835,79 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CmdCommandSGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Cmd_CommandSGen( Abc_Frame_t * pAbc, int nParts, int nIters, int fVerbose ); + int c, nParts = 10; + int nIters = 10; + int fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NIvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nParts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nParts < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a string (possibly in quotes).\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( Abc_FrameReadNtk(pAbc) == NULL ) + { + Abc_Print( -2, "There is no current network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(Abc_FrameReadNtk(pAbc)) ) + { + Abc_Print( -2, "The current network is not an AIG.\n" ); + return 1; + } + Cmd_CommandSGen( pAbc, nParts, nIters, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: sgen [-N num] [-I num] [-vh]\n" ); + Abc_Print( -2, "\t experiment with script generation\n" ); + Abc_Print( -2, "\t-N num : the number of commands to use [default = %d]\n", nParts ); + Abc_Print( -2, "\t-I num : the number of iterations to perform [default = %d]\n", nIters ); + 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; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/cmd/cmdStarter.c b/src/base/cmd/cmdStarter.c index ffb2b7522..bfbe5533d 100644 --- a/src/base/cmd/cmdStarter.c +++ b/src/base/cmd/cmdStarter.c @@ -44,7 +44,7 @@ ABC_NAMESPACE_IMPL_START #ifndef ABC_USE_PTHREADS -void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores ) {} +void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores, int fVerbose ) {} #else // pthreads are used @@ -104,7 +104,7 @@ void * Abc_RunThread( void * pCommand ) SeeAlso [] ***********************************************************************/ -void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores ) +void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores, int fVerbose ) { FILE * pFile, * pFileTemp; pthread_t * pThreadIds; @@ -204,8 +204,10 @@ void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCor } else BufferCopy = Abc_UtilStrsav( Buffer ); - fprintf( stdout, "Calling: %s\n", (char *)BufferCopy ); - fflush( stdout ); + if ( fVerbose ) { + fprintf( stdout, "Calling: %s\n", (char *)BufferCopy ); + fflush( stdout ); + } // wait till there is an empty thread while ( 1 ) diff --git a/src/base/cmd/cmdUtils.c b/src/base/cmd/cmdUtils.c index 0759ca9c5..e8e28078f 100644 --- a/src/base/cmd/cmdUtils.c +++ b/src/base/cmd/cmdUtils.c @@ -836,6 +836,70 @@ void Gia_ManKissatCall( Abc_Frame_t * pAbc, char * pFileName, char * pArgs, int } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Cmd_GenScript( char ** pComms, int nComms, int nParts ) +{ + static char pScript[1000]; int c; + pScript[0] = 0; + for ( c = 0; c < nParts; c++ ) { + strcat( pScript, pComms[rand() % nComms] ); + strcat( pScript, "; " ); + } + strcat( pScript, "print_stats" ); + return pScript; +} +void Cmd_CommandSGen( Abc_Frame_t * pAbc, int nParts, int nIters, int fVerbose ) +{ + Abc_Ntk_t * pCopy = Abc_NtkDup( Abc_FrameReadNtk(pAbc) ); + Abc_Ntk_t * pBest = Abc_NtkDup( Abc_FrameReadNtk(pAbc) ); + Abc_Ntk_t * pCur = NULL; int i; + char * pComms[6] = { "balance", "rewrite", "rewrite -z", "refactor", "refactor -z", "resub" }; + srand( time(NULL) ); + for ( i = 0; i < nIters; i++ ) + { + char * pScript = Cmd_GenScript( pComms, 6, nParts ); + Abc_FrameSetCurrentNetwork( pAbc, Abc_NtkDup(pCopy) ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(pAbc, pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(pAbc, pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + Abc_FrameSetBatchMode( 0 ); + return; + } + Abc_FrameSetBatchMode( 0 ); + } + pCur = Abc_FrameReadNtk(pAbc); + if ( Abc_NtkNodeNum(pCur) < Abc_NtkNodeNum(pBest) ) { + Abc_Obj_t * pObj; int k; + Abc_NtkForEachObj( pBest, pObj, k ) + pObj->fMarkA = pObj->fMarkB = pObj->fMarkC = 0; + Abc_NtkDelete( pBest ); + pBest = Abc_NtkDup( pCur ); + } + } + Abc_FrameSetCurrentNetwork( pAbc, pBest ); + Abc_NtkDelete( pCopy ); +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/base/io/io.c b/src/base/io/io.c index 9fe2c39d8..5bb80dba6 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -53,6 +53,7 @@ static int IoCommandReadInit ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadPla ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadPlaMo ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadTruth ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadCnf ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadStatus ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadGig ( Abc_Frame_t * pAbc, int argc, char **argv ); @@ -126,6 +127,7 @@ void Io_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "I/O", "read_pla", IoCommandReadPla, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_plamo", IoCommandReadPlaMo, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_truth", IoCommandReadTruth, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_cnf", IoCommandReadCnf, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_verilog", IoCommandReadVerilog, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_status", IoCommandReadStatus, 0 ); Cmd_CommandAdd( pAbc, "I/O", "&read_gig", IoCommandReadGig, 0 ); @@ -278,6 +280,18 @@ int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } // read the file using the corresponding file reader + if ( strstr(pFileName, ".") && !strcmp(strstr(pFileName, "."), ".s") ) + { + char Command[1000]; + assert( strlen(pFileName) < 980 ); + sprintf( Command, "source -x %s", pFileName ); + if ( Cmd_CommandExecute( pAbc, Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return 1; + } + return 0; + } pNtk = Io_Read( pFileName, Io_ReadFileType(pFileName), fCheck, fBarBufs ); if ( pNtk == NULL ) return 0; @@ -1524,6 +1538,80 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadCnf( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Vec_Ptr_t * Io_FileReadCnf( char * pFileName, int fMulti ); + FILE * pFile; + Abc_Ntk_t * pNtk; + Vec_Ptr_t * vSops; + int fMulti = 0; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) + { + switch ( c ) + { + case 'm': + fMulti ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + goto usage; + + pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) + { + printf( "The file \"%s\" cannot be found.\n", argv[globalUtilOptind] ); + return 1; + } + else + fclose( pFile ); + vSops = Io_FileReadCnf( argv[globalUtilOptind], fMulti ); + if ( Vec_PtrSize(vSops) == 0 ) + { + Vec_PtrFreeFree( vSops ); + fprintf( pAbc->Err, "Reading CNF file has failed.\n" ); + return 1; + } + pNtk = Abc_NtkCreateWithNodes( vSops ); + Vec_PtrFreeFree( vSops ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Deriving the network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + Abc_FrameClearVerifStatus( pAbc ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_cnf [-mh] \n" ); + fprintf( pAbc->Err, "\t creates network with one node\n" ); + fprintf( pAbc->Err, "\t-m : toggles generating multi-output network [default = %s]\n", fMulti? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : file name with the truth table\n" ); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c index eef80efa3..eee2dda53 100644 --- a/src/base/io/ioUtil.c +++ b/src/base/io/ioUtil.c @@ -920,6 +920,116 @@ void Io_TransformSF2PLA( char * pNameIn, char * pNameOut ) ABC_FREE( pBuffer ); } +/**Function************************************************************* + + Synopsis [Reads CNF from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Io_ConvertNumsToSop( Vec_Wec_t * vNums, int nVars ) +{ + Vec_Ptr_t * vSops = Vec_PtrAlloc(1); + Vec_Int_t * vLevel; int i, k, Num; + int nSize = (nVars + 3)*Vec_WecSize(vNums); + char * pStr = ABC_ALLOC( char, nSize+1 ); + memset( pStr, '-', nSize ); + pStr[nSize] = 0; + Vec_WecForEachLevel( vNums, vLevel, i ) + { + char * pCube = pStr + (nVars + 3)*i; + Vec_IntForEachEntry( vLevel, Num, k ) + pCube[Abc_Lit2Var(Num)] = '0' + Abc_LitIsCompl(Num); + pCube[nVars+0] = ' '; + pCube[nVars+1] = '0'; + pCube[nVars+2] = '\n'; + } + Vec_PtrPush( vSops, pStr ); + return vSops; +} +Vec_Ptr_t * Io_ConvertNumsToSopMulti( Vec_Wec_t * vNums, int nVars ) +{ + Vec_Ptr_t * vSops = Vec_PtrAlloc( Vec_WecSize(vNums) ); + Vec_Int_t * vLevel; int i, k, Num; + Vec_WecForEachLevel( vNums, vLevel, i ) + { + char * pCube = ABC_ALLOC( char, nVars + 4 ); + memset( pCube, '-', nVars ); + Vec_IntForEachEntry( vLevel, Num, k ) + pCube[Abc_Lit2Var(Num)] = '0' + Abc_LitIsCompl(Num); + pCube[nVars+0] = ' '; + pCube[nVars+1] = '0'; + pCube[nVars+2] = '\n'; + pCube[nVars+3] = '\0'; + Vec_PtrPush( vSops, pCube ); + } + return vSops; +} +Vec_Ptr_t * Io_FileReadCnf( char * pFileName, int fMulti ) +{ + Vec_Ptr_t * vSops = NULL; + Vec_Wec_t * vNums = Vec_WecAlloc( 100 ); + Vec_Int_t * vLevel; + char * pThis, pLine[10000]; + int nVars = -1, nClas = -1; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + while ( fgets( pLine, 10000, pFile ) ) + { + if ( pLine[0] == 'c' ) + continue; + if ( pLine[0] == 'p' ) + { + pThis = strtok(pLine+1, " \t\n\r"); + if ( strcmp(pThis, "cnf") ) + { + Vec_PtrFree( vSops ); + Vec_WecFree( vNums ); + fclose( pFile ); + printf( "Wrong file format.\n" ); + return NULL; + } + pThis = strtok(NULL, " \t\n\r"); + nVars = atoi(pThis); + pThis = strtok(NULL, " \t\n\r"); + nClas = atoi(pThis); + continue; + } + pThis = strtok(pLine, " \t\n\r"); + if ( pThis == NULL ) + continue; + vLevel = Vec_WecPushLevel( vNums ); + while ( pThis ) { + int fComp, Temp = atoi(pThis); + if ( Temp == 0 ) + break; + fComp = Temp < 0; + Temp = Temp < 0 ? -Temp : Temp; + Temp -= 1; + assert( Temp < nVars ); + Vec_IntPush( vLevel, Abc_Var2Lit(Temp, fComp) ); + pThis = strtok(NULL, " \t\n\r"); + } + } + fclose( pFile ); + if ( nClas != Vec_WecSize(vNums) ) + printf( "Warning: The number of clauses (%d) listed is different from the actual number (%d).\n", nClas, Vec_WecSize(vNums) ); + //Vec_WecPrint( vNums, 0 ); + if ( fMulti ) + vSops = Io_ConvertNumsToSopMulti(vNums, nVars); + else + vSops = Io_ConvertNumsToSop(vNums, nVars); + Vec_WecFree( vNums ); + return vSops; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/main/abcapis.h b/src/base/main/abcapis.h index d34306baf..30494f77c 100644 --- a/src/base/main/abcapis.h +++ b/src/base/main/abcapis.h @@ -106,6 +106,9 @@ extern ABC_DLL int * Abc_FrameReadBoxes( Abc_Frame_t * pAbc ); extern ABC_DLL int Abc_FrameReadProbStatus( Abc_Frame_t * pAbc ); extern ABC_DLL void * Abc_FrameReadCex( Abc_Frame_t * pAbc ); +// procedure to set retiming data +extern ABC_DLL void Abc_FrameSetRetimingData( Abc_Frame_t * pAbc, int * pRst, int * pSet, int * pEna, int nRegs ); + // procedure to return sequential equivalences extern ABC_DLL int * Abc_FrameReadMiniAigEquivClasses( Abc_Frame_t * pAbc ); diff --git a/src/base/wlc/wlc.c b/src/base/wlc/wlc.c index 3ba9be96d..91656efc8 100644 --- a/src/base/wlc/wlc.c +++ b/src/base/wlc/wlc.c @@ -677,7 +677,7 @@ Gia_Man_t * Wlc_ManGenTree( int nInputs, int Value, int nBits, int fVerbose ) ***********************************************************************/ Gia_Man_t * Wlc_ManGenProd( int nInputs, int fVerbose ) { - extern void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); + extern void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds, int fVerbose ); extern void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); Vec_Int_t * vIns = Vec_IntAlloc( 2*nInputs ); Gia_Man_t * pTemp, * pNew; @@ -693,7 +693,7 @@ Gia_Man_t * Wlc_ManGenProd( int nInputs, int fVerbose ) // Vec_IntPush( vIns, Vec_IntEntry(vIns, i) ); Gia_ManHashAlloc( pNew ); - Wlc_BlastBooth( pNew, Vec_IntArray(vIns), Vec_IntArray(vIns)+nInputs, nInputs, nInputs, NULL, 0, 0, &vProds ); + Wlc_BlastBooth( pNew, Vec_IntArray(vIns), Vec_IntArray(vIns)+nInputs, nInputs, nInputs, NULL, 0, 0, &vProds, 0 ); //Wlc_BlastMultiplier3( pNew, Vec_IntArray(vIns), Vec_IntArray(vIns)+nInputs, nInputs, nInputs, NULL, 0, 0, &vProds ); //Vec_WecPrint( vProds, 0 ); Wlc_ManGenTreeOne( pNew, vProds, 1, fVerbose ); diff --git a/src/base/wlc/wlc.h b/src/base/wlc/wlc.h index 0b3bed6c0..ac4743338 100644 --- a/src/base/wlc/wlc.h +++ b/src/base/wlc/wlc.h @@ -448,7 +448,7 @@ extern void Wlc_NtkDeleteSim( Vec_Ptr_t * p ); extern int Wlc_StdinProcessSmt( Abc_Frame_t * pAbc, char * pCmd ); /*=== wlcReadVer.c ========================================================*/ extern char * Wlc_PrsConvertInitValues( Wlc_Ntk_t * p ); -extern Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr ); +extern Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr, int fInter ); /*=== wlcUif.c ========================================================*/ extern Vec_Int_t * Wlc_NtkCollectAddMult( Wlc_Ntk_t * p, Wlc_BstPar_t * pPar, int * pCountA, int * CountM ); extern int Wlc_NtkPairIsUifable( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Wlc_Obj_t * pObj2 ); diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c index 4ec1a4902..d3b2b3a05 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -1050,7 +1050,7 @@ void Wlc_BlastReduceMatrix2( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Int_t * v } -void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ) +void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds, int fVerbose ) { Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB ); Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB ); @@ -1064,13 +1064,17 @@ void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA } if ( fSigned ) { - Vec_WecPush( vProds, nArgA, 1 ); - Vec_WecPush( vLevels, nArgA, 0 ); + Vec_WecPush( vProds, nArgB-1, 1 ); + Vec_WecPush( vLevels, nArgB-1, 0 ); + + Vec_WecPush( vProds, nArgA-1, 1 ); + Vec_WecPush( vLevels, nArgA-1, 0 ); Vec_WecPush( vProds, nArgA+nArgB-1, 1 ); Vec_WecPush( vLevels, nArgA+nArgB-1, 0 ); } - + if ( fVerbose ) + Vec_WecPrint( vProds, 0 ); if ( pvProds ) *pvProds = Vec_WecDup(vProds); else @@ -1117,7 +1121,7 @@ void Wlc_BlastDecoder( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, Vec_IntPush( vRes, iMint ); } } -void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ) +void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds, int fVerbose ) { Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB + 3 ); Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB + 3 ); @@ -1194,7 +1198,10 @@ void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int Vec_WecPush( vProds, k, Neg ); Vec_WecPush( vLevels, k, 0 ); } - //Vec_WecPrint( vProds, 0 ); + //Vec_WecShrink( vProds, nArgA + nArgB ); + //Vec_WecShrink( vLevels, nArgA + nArgB ); + if ( fVerbose ) + Vec_WecPrint( vProds, 0 ); //Wlc_BlastPrintMatrix( pNew, vProds, 1 ); //printf( "Cutoff ID for partial products = %d.\n", Gia_ManObjNum(pNew) ); if ( pvProds ) @@ -1832,9 +1839,9 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) if ( Wlc_NtkCountConstBits(pArg0, nRangeMax) < Wlc_NtkCountConstBits(pArg1, nRangeMax) ) ABC_SWAP( int *, pArg0, pArg1 ); if ( pPar->fBooth ) - Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned, pPar->fCla, NULL ); + Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned, pPar->fCla, NULL, pParIn->fVerbose ); else if ( pPar->fCla ) - Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes, Wlc_ObjIsSignedFanin01(p, pObj), pPar->fCla, NULL ); + Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes, Wlc_ObjIsSignedFanin01(p, pObj), pPar->fCla, NULL, pParIn->fVerbose ); else Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned ); //Wlc_BlastMultiplierC( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned ); @@ -2667,6 +2674,71 @@ Vec_Int_t * Wlc_ComputePerm( Wlc_Ntk_t * pNtk, int nPis ) return vPerm; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Wlc_TransferPioNames( Wlc_Ntk_t * p, Gia_Man_t * pNew ) +{ + int fSkipBitRange = 0; + Wlc_Obj_t * pObj; int i, k; + Vec_PtrFreeP( &pNew->vNamesIn ); + Vec_PtrFreeP( &pNew->vNamesOut ); + pNew->vNamesIn = Vec_PtrAlloc( Gia_ManPiNum(pNew) ); + pNew->vNamesOut = Vec_PtrAlloc( Gia_ManPoNum(pNew) ); + // create input names + Wlc_NtkForEachCi( p, pObj, i ) + if ( Wlc_ObjIsPi(pObj) ) + { + char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); + int 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, pObj->Beg < pObj->End ? pObj->Beg+k : pObj->Beg-k ); + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); + //printf( "Writing %s\n", Buffer ); + } + } + // add real primary outputs + Wlc_NtkForEachCo( p, pObj, i ) + if ( Wlc_ObjIsPo(pObj) ) + { + char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); + int nRange = Wlc_ObjRange( pObj ); + 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, pObj->Beg < pObj->End ? pObj->Beg+k : pObj->Beg-k ); + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); + } + } + if ( Vec_PtrSize(pNew->vNamesIn) != Gia_ManPiNum(pNew) ) + printf( "The number of input bits (%d) does not match the number of primary inputs (%d) in the current AIG.\n", Vec_PtrSize(pNew->vNamesIn), Gia_ManPiNum(pNew) ); + if ( Vec_PtrSize(pNew->vNamesOut) != Gia_ManPoNum(pNew) ) + printf( "The number of output bits (%d) does not match the number of primary inputs (%d) in the current AIG.\n", Vec_PtrSize(pNew->vNamesOut), Gia_ManPoNum(pNew) ); + if ( Vec_PtrSize(pNew->vNamesIn) != Gia_ManPiNum(pNew) || Vec_PtrSize(pNew->vNamesOut) != Gia_ManPoNum(pNew) ) + { + Vec_PtrFreeP( &pNew->vNamesIn ); + Vec_PtrFreeP( &pNew->vNamesOut ); + } + else + printf( "Successfully transferred the primary input/output names from the word-level design to the current AIG.\n" ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c index 13192a1eb..d15a7723b 100644 --- a/src/base/wlc/wlcCom.c +++ b/src/base/wlc/wlcCom.c @@ -149,14 +149,16 @@ void Wlc_SetNtk( Abc_Frame_t * pAbc, Wlc_Ntk_t * pNtk ) ******************************************************************************/ int Abc_CommandReadWlc( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Wlc_TransferPioNames( Wlc_Ntk_t * p, Gia_Man_t * pNew ); FILE * pFile; Wlc_Ntk_t * pNtk = NULL; char * pFileName = NULL; int fOldParser = 0; int fPrintTree = 0; + int fInter = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "opvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "opivh" ) ) != EOF ) { switch ( c ) { @@ -166,6 +168,9 @@ int Abc_CommandReadWlc( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'p': fPrintTree ^= 1; break; + case 'i': + fInter ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -193,8 +198,12 @@ int Abc_CommandReadWlc( Abc_Frame_t * pAbc, int argc, char ** argv ) fclose( pFile ); // perform reading - if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) - pNtk = Wlc_ReadVer( pFileName, NULL ); + if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) + { + pNtk = Wlc_ReadVer( pFileName, NULL, fInter ); + if ( fInter && pAbc->pGia ) + Wlc_TransferPioNames( pNtk, pAbc->pGia ); + } else if ( !strcmp( Extra_FileNameExtension(pFileName), "smt" ) || !strcmp( Extra_FileNameExtension(pFileName), "smt2" ) ) pNtk = Wlc_ReadSmt( pFileName, fOldParser, fPrintTree ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "ndr" ) ) @@ -207,10 +216,11 @@ int Abc_CommandReadWlc( Abc_Frame_t * pAbc, int argc, char ** argv ) Wlc_AbcUpdateNtk( pAbc, pNtk ); return 0; usage: - Abc_Print( -2, "usage: %%read [-opvh] \n" ); + Abc_Print( -2, "usage: %%read [-opivh] \n" ); Abc_Print( -2, "\t reads word-level design from Verilog file\n" ); Abc_Print( -2, "\t-o : toggle using old SMT-LIB parser [default = %s]\n", fOldParser? "yes": "no" ); Abc_Print( -2, "\t-p : toggle printing parse SMT-LIB tree [default = %s]\n", fPrintTree? "yes": "no" ); + Abc_Print( -2, "\t-i : toggle reading interface only [default = %s]\n", fInter? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; diff --git a/src/base/wlc/wlcReadVer.c b/src/base/wlc/wlcReadVer.c index aff3eae8a..f31528ea6 100644 --- a/src/base/wlc/wlcReadVer.c +++ b/src/base/wlc/wlcReadVer.c @@ -951,7 +951,7 @@ int Wlc_PrsReadDeclaration( Wlc_Prs_t * p, char * pStart ) } return 1; } -int Wlc_PrsDerive( Wlc_Prs_t * p ) +int Wlc_PrsDerive( Wlc_Prs_t * p, int fInter ) { Wlc_Obj_t * pObj; char * pStart, * pName; @@ -1031,6 +1031,8 @@ startword: while ( (pName = Wlc_PrsStrtok( NULL, "(,)" )) ) { pName = Wlc_PrsSkipSpaces( pName ); + if ( fInter && Wlc_PrsStrCmp( pName, "wire" ) ) + return 0; if ( Wlc_PrsStrCmp( pName, "input" ) || Wlc_PrsStrCmp( pName, "output" ) || Wlc_PrsStrCmp( pName, "wire" ) ) { if ( !Wlc_PrsReadDeclaration( p, pName ) ) @@ -1095,12 +1097,16 @@ startword: // these are read as part of the interface else if ( Wlc_PrsStrCmp( pStart, "input" ) || Wlc_PrsStrCmp( pStart, "output" ) || Wlc_PrsStrCmp( pStart, "wire" ) || Wlc_PrsStrCmp( pStart, "reg" ) ) { + if ( fInter && (Wlc_PrsStrCmp( pStart, "wire" ) || Wlc_PrsStrCmp( pStart, "reg" )) ) + return 0; if ( !Wlc_PrsReadDeclaration( p, pStart ) ) return 0; } else if ( Wlc_PrsStrCmp( pStart, "assign" ) ) { int Type, NameId, fFound, XValue = 0; + if ( fInter ) + return 0; pStart += strlen("assign"); // read name pStart = Wlc_PrsFindName( pStart, &pName ); @@ -1159,6 +1165,8 @@ startword: { // THIS IS A HACK to detect always statement representing combinational MUX int NameId, NameIdOut = -1, fFound, nValues, fDefaultFound = 0; + if ( fInter ) + return 0; // find control pStart = Wlc_PrsFindWord( pStart, "case", &fFound ); if ( pStart == NULL ) @@ -1682,7 +1690,7 @@ startword: } return 1; } -Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr ) +Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr, int fInter ) { Wlc_Prs_t * p; Wlc_Ntk_t * pNtk = NULL; @@ -1696,8 +1704,23 @@ Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr ) if ( !Wlc_PrsPrepare( p ) ) goto finish; // parse models - if ( !Wlc_PrsDerive( p ) ) + if ( !Wlc_PrsDerive( p, fInter ) ) + { + if ( fInter ) + { + printf( "Finished deriving interface for module \"%s\".\n", p->pNtk->pName ); + pNtk = p->pNtk; p->pNtk = NULL; + pNtk->pSpec = Abc_UtilStrsav( pFileName ); + if ( Vec_IntSize(&pNtk->vNameIds) == 0 ) + { + Vec_Int_t * vTemp = Vec_IntStartNatural( Wlc_NtkObjNumMax(pNtk) ); + pNtk->vNameIds = *vTemp, Vec_IntZero(vTemp); + Vec_IntFree( vTemp ); + } + return pNtk; + } goto finish; + } // derive topological order if ( p->pNtk ) { @@ -1728,7 +1751,7 @@ finish: void Io_ReadWordTest( char * pFileName ) { Gia_Man_t * pNew; - Wlc_Ntk_t * pNtk = Wlc_ReadVer( pFileName, NULL ); + Wlc_Ntk_t * pNtk = Wlc_ReadVer( pFileName, NULL, 0 ); if ( pNtk == NULL ) return; Wlc_WriteVer( pNtk, "test.v", 0, 0 ); diff --git a/src/base/wln/wlnBlast.c b/src/base/wln/wlnBlast.c index 776cdd902..c3281a2e0 100644 --- a/src/base/wln/wlnBlast.c +++ b/src/base/wln/wlnBlast.c @@ -69,7 +69,7 @@ void Rtl_NtkBlastNode( Gia_Man_t * pNew, int Type, int nIns, Vec_Int_t * vDatas, extern int Wlc_BlastAdder( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int Carry ); // result is in pAdd0 extern void Wlc_BlastSubtract( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int Carry ); // result is in pAdd0 extern int Wlc_NtkCountConstBits( int * pArray, int nSize ); - extern void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); + extern void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds, int fVerbose ); extern void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla, Vec_Wec_t ** pvProds ); extern void Wlc_BlastZeroCondition( Gia_Man_t * pNew, int * pDiv, int nDiv, Vec_Int_t * vRes ); extern void Wlc_BlastDividerTop( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes, int fNonRest ); @@ -303,7 +303,7 @@ void Rtl_NtkBlastNode( Gia_Man_t * pNew, int Type, int nIns, Vec_Int_t * vDatas, if ( Wlc_NtkCountConstBits(Vec_IntArray(vArg0), Vec_IntSize(vArg0)) < Wlc_NtkCountConstBits(Vec_IntArray(vArg1), Vec_IntSize(vArg1)) ) ABC_SWAP( Vec_Int_t, *vArg0, *vArg1 ) if ( fBooth ) - Wlc_BlastBooth( pNew, Vec_IntArray(vArg0), Vec_IntArray(vArg1), Vec_IntSize(vArg0), Vec_IntSize(vArg1), vRes, fSigned, fCla, NULL ); + Wlc_BlastBooth( pNew, Vec_IntArray(vArg0), Vec_IntArray(vArg1), Vec_IntSize(vArg0), Vec_IntSize(vArg1), vRes, fSigned, fCla, NULL, 0 ); else Wlc_BlastMultiplier3( pNew, Vec_IntArray(vArg0), Vec_IntArray(vArg1), Vec_IntSize(vArg0), Vec_IntSize(vArg1), vRes, fSigned, fCla, NULL ); if ( nRange > Vec_IntSize(vRes) ) diff --git a/src/base/wln/wlnCom.c b/src/base/wln/wlnCom.c index 06e4392c9..d24fec48c 100644 --- a/src/base/wln/wlnCom.c +++ b/src/base/wln/wlnCom.c @@ -92,7 +92,7 @@ void Wln_End( Abc_Frame_t * pAbc ) ******************************************************************************/ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fVerbose ); + extern Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fVerbose ); extern Rtl_Lib_t * Wln_ReadSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fCollapse, int fVerbose ); FILE * pFile; @@ -102,11 +102,12 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv ) int fBlast = 0; int fInvert = 0; int fTechMap = 1; + int fLibInDir = 0; int fSkipStrash = 0; int fCollapse = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "TDbismcvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "TDbismlcvh" ) ) != EOF ) { switch ( c ) { @@ -140,6 +141,9 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fTechMap ^= 1; break; + case 'l': + fLibInDir ^= 1; + break; case 'c': fCollapse ^= 1; break; @@ -174,11 +178,11 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pNew = NULL; if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) - pNew = Wln_BlastSystemVerilog( pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fVerbose ); + pNew = Wln_BlastSystemVerilog( pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fVerbose ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "sv" ) ) - pNew = Wln_BlastSystemVerilog( pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fVerbose ); + pNew = Wln_BlastSystemVerilog( pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fVerbose ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "rtlil" ) ) - pNew = Wln_BlastSystemVerilog( pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fVerbose ); + pNew = Wln_BlastSystemVerilog( pFileName, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fVerbose ); else { printf( "Abc_CommandYosys(): Unknown file extension.\n" ); @@ -204,7 +208,7 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv ) } return 0; usage: - Abc_Print( -2, "usage: %%yosys [-T ] [-D ] [-bismcvh] \n" ); + Abc_Print( -2, "usage: %%yosys [-T ] [-D ] [-bismlcvh] \n" ); Abc_Print( -2, "\t reads Verilog or SystemVerilog using Yosys\n" ); Abc_Print( -2, "\t-T : specify the top module name (default uses \"-auto-top\")\n" ); Abc_Print( -2, "\t-D : specify defines to be used by Yosys (default \"not used\")\n" ); @@ -212,6 +216,7 @@ usage: Abc_Print( -2, "\t-i : toggle inverting the outputs (useful for miters) [default = %s]\n", fInvert? "yes": "no" ); Abc_Print( -2, "\t-s : toggle no structural hashing during bit-blasting [default = %s]\n", fSkipStrash? "no strash": "strash" ); Abc_Print( -2, "\t-m : toggle using \"techmap\" to blast operators [default = %s]\n", fTechMap? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle looking for \"techmap.v\" in the current directory [default = %s]\n", fLibInDir? "yes": "no" ); Abc_Print( -2, "\t-c : toggle collapsing design hierarchy using Yosys [default = %s]\n", fCollapse? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); diff --git a/src/base/wln/wlnRtl.c b/src/base/wln/wlnRtl.c index becbee493..f7364bded 100644 --- a/src/base/wln/wlnRtl.c +++ b/src/base/wln/wlnRtl.c @@ -171,7 +171,7 @@ Rtl_Lib_t * Wln_ReadSystemVerilog( char * pFileName, char * pTopModule, char * p unlink( pFileTemp ); return pNtk; } -Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fVerbose ) +Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fVerbose ) { Gia_Man_t * pGia = NULL; char Command[1000]; @@ -187,7 +187,7 @@ Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char * pFileName, pTopModule ? "-top " : "-auto-top", pTopModule ? pTopModule : "", - fTechMap ? "techmap; setundef -zero; " : "", pFileTemp ); + fTechMap ? (fLibInDir ? "techmap -map techmap.v; setundef -zero; " : "techmap; setundef -zero; ") : "", pFileTemp ); if ( fVerbose ) printf( "%s\n", Command ); if ( !Wln_ConvertToRtl(Command, pFileTemp) ) diff --git a/src/map/if/acd/ac_decomposition.hpp b/src/map/if/acd/ac_decomposition.hpp new file mode 100644 index 000000000..d8a44b1d5 --- /dev/null +++ b/src/map/if/acd/ac_decomposition.hpp @@ -0,0 +1,1501 @@ +/**C++File************************************************************** + + FileName [ac_decomposition.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Ashenhurst-Curtis decomposition.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alessandro Tempia Calvino] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - November 20, 2023.] + +***********************************************************************/ +/*! + \file ac_decomposition.hpp + \brief Ashenhurst-Curtis decomposition + + \author Alessandro Tempia Calvino +*/ + +#ifndef _ACD_H_ +#define _ACD_H_ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_constructors.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_operations.hpp" +#include "kitty_operators.hpp" +#include "kitty_static_tt.hpp" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace acd +{ + +/*! \brief Parameters for ac_decomposition */ +struct ac_decomposition_params +{ + /*! \brief LUT size for decomposition (3 < num < 7). */ + uint32_t lut_size{ 6 }; + + /*! \brief Maximum size of the free set (1 < num < 6). */ + uint32_t max_free_set_vars{ 4 }; + + /*! \brief Perform only support reducing (2-level) decompositions. */ + bool support_reducing_only{ true }; + + /*! \brief Use the first feasible decomposition found. */ + bool use_first{ false }; + + /*! \brief If decomposition with delay profile fails, try without. */ + bool try_no_late_arrival{ false }; +}; + +/*! \brief Statistics for ac_decomposition */ +struct ac_decomposition_stats +{ + uint32_t num_luts{ 0 }; + uint32_t num_edges{ 0 }; + uint32_t num_levels{ 0 }; +}; + +struct ac_decomposition_result +{ + kitty::dynamic_truth_table tt; + std::vector support; +}; + +class ac_decomposition_impl +{ +private: + struct encoding_column + { + uint64_t column[2]; + uint32_t cost; + uint32_t index; + float sort_cost; + }; + +private: + static constexpr uint32_t max_num_vars = 11; + using STT = kitty::static_truth_table; + +public: + explicit ac_decomposition_impl( uint32_t num_vars, ac_decomposition_params const& ps, ac_decomposition_stats* pst = nullptr ) + : num_vars( num_vars ), ps( ps ), pst( pst ) + { + std::iota( permutations.begin(), permutations.end(), 0 ); + } + + /*! \brief Runs ACD using late arriving variables */ + int run( word* ptt, unsigned delay_profile ) + { + /* truth table is too large for the settings */ + if ( num_vars > max_num_vars ) + { + return -1; + } + + uint32_t late_arriving = __builtin_popcount( delay_profile ); + + /* relax maximum number of free set variables if a function has more variables */ + if ( num_vars > ps.max_free_set_vars + ps.lut_size ) + { + ps.max_free_set_vars = num_vars - ps.lut_size; + } + if ( late_arriving > ps.max_free_set_vars ) + { + return -1; /* on average avoiding this computation leads to better quality */ + // ps.max_free_set_vars = late_arriving; + } + + /* return a high cost if too many late arriving variables */ + if ( late_arriving > ps.lut_size - 1 ) + { + return -1; + } + + /* convert to static TT */ + init_truth_table( ptt ); + + /* permute late arriving variables to be the least significant */ + reposition_late_arriving_variables( delay_profile, late_arriving ); + + /* run ACD trying different bound sets and free sets */ + if ( !find_decomposition( delay_profile, late_arriving ) ) + { + return -1; + } + + /* return number of levels */ + return delay_profile == 0 ? 2 : 1; + } + + int compute_decomposition() + { + if ( best_multiplicity == UINT32_MAX ) + return -1; + + /* compute isets */ + std::vector isets = compute_isets(); + + generate_support_minimization_encodings(); + + /* solves exactly only for small multiplicities */ + if ( best_multiplicity <= 4u ) + solve_min_support_exact( isets ); + else + solve_min_support_heuristic( isets ); + + /* unfeasible decomposition */ + assert( !best_bound_sets.empty() ); + + return 0; + } + + unsigned get_profile() + { + unsigned profile = 0; + + if ( best_free_set > num_vars ) + return -1; + + for ( uint32_t i = 0; i < best_free_set; ++i ) + { + profile |= 1 << permutations[i]; + } + + return profile; + } + + void get_decomposition( unsigned char* decompArray ) + { + if ( best_free_set > num_vars ) + return; + + generate_decomposition(); + get_decomposition_abc( decompArray ); + } + +private: + bool find_decomposition( unsigned& delay_profile, uint32_t late_arriving ) + { + best_multiplicity = UINT32_MAX; + best_free_set = UINT32_MAX; + uint32_t best_cost = UINT32_MAX; + uint32_t offset = static_cast( late_arriving ); + uint32_t start = std::max( offset, 1u ); + + /* perform only support reducing decomposition */ + if ( ps.support_reducing_only ) + { + start = std::max( start, num_vars - ps.lut_size ); + } + + /* array of functions to compute the column multiplicity */ + std::function column_multiplicity_fn[5] = { + [this]( STT const& tt ) { return column_multiplicity<1u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity<2u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity<3u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity5<4u>( tt ); }, + [this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } }; + + /* find a feasible AC decomposition */ + // for ( uint32_t i = std::min( ps.lut_size - 1, ps.max_free_set_vars); i >= start; --i ) + for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) + { + auto ret_tuple = enumerate_iset_combinations( i, offset, column_multiplicity_fn[i - 1] ); + uint32_t multiplicity = std::get<2>( ret_tuple ); + + /* additional cost if not support reducing */ + uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; + + /* check for feasible solution that improves the cost */ + if ( multiplicity <= ( 1 << ( ps.lut_size - i ) ) && multiplicity + additional_cost < best_cost && multiplicity <= 16 ) + { + best_tt = std::get<0>( ret_tuple ); + permutations = std::get<1>( ret_tuple ); + best_multiplicity = multiplicity; + best_cost = multiplicity + additional_cost; + best_free_set = i; + + if ( !ps.use_first && multiplicity > 2 ) + { + continue; + } + } + + break; + } + + if ( best_multiplicity == UINT32_MAX && ( !ps.try_no_late_arrival || late_arriving == 0 ) ) + return false; + + /* try without the delay profile */ + if ( best_multiplicity == UINT32_MAX ) + { + delay_profile = 0; + if ( ps.support_reducing_only ) + { + start = std::max( 1u, num_vars - ps.lut_size ); + } + + for ( uint32_t i = start; i <= ps.lut_size - 1 && i <= ps.max_free_set_vars; ++i ) + { + auto ret_tuple = enumerate_iset_combinations( i, 0, column_multiplicity_fn[i - 1] ); + uint32_t multiplicity = std::get<2>( ret_tuple ); + + /* additional cost if not support reducing */ + uint32_t additional_cost = ( num_vars - i > ps.lut_size ) ? 128 : 0; + + /* check for feasible solution that improves the cost */ + if ( multiplicity <= ( 1 << ( ps.lut_size - i ) ) && multiplicity + additional_cost < best_cost && multiplicity <= 16 ) + { + best_tt = std::get<0>( ret_tuple ); + permutations = std::get<1>( ret_tuple ); + best_multiplicity = multiplicity; + best_cost = multiplicity + additional_cost; + best_free_set = i; + + if ( !ps.use_first && multiplicity > 2 ) + { + continue; + } + } + + break; + } + } + + if ( best_multiplicity == UINT32_MAX ) + return false; + + /* estimation on number of LUTs */ + if ( pst ) + { + pst->num_luts = best_multiplicity <= 2 ? 2 : best_multiplicity <= 4 ? 3 + : best_multiplicity <= 8 ? 4 + : 5; + } + + return true; + } + + void init_truth_table( word* ptt ) + { + uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) ); + + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + best_tt._bits[i] = ptt[i]; + } + + // local_extend_to( best_tt, num_vars ); + } + + template + uint32_t column_multiplicity( STT const& tt ) + { + uint64_t multiplicity_set[4] = { 0u, 0u, 0u, 0u }; + uint32_t multiplicity = 0; + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t constexpr masks_bits[] = { 0x0, 0x3, 0xF, 0x3F }; + uint64_t constexpr masks_idx[] = { 0x0, 0x0, 0x0, 0x3 }; + + /* supports up to 64 values of free set (256 for |FS| == 3)*/ + static_assert( free_set_size <= 3, "Wrong free set size for method used, expected le 3" ); + + /* extract iset functions */ + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t cof = tt._bits[i]; + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + multiplicity_set[( cof >> 6 ) & masks_idx[free_set_size]] |= UINT64_C( 1 ) << ( cof & masks_bits[free_set_size] ); + cof >>= ( 1u << free_set_size ); + } + } + + multiplicity = __builtin_popcountl( multiplicity_set[0] ); + + if ( free_set_size == 3 ) + { + multiplicity += __builtin_popcountl( multiplicity_set[1] ); + multiplicity += __builtin_popcountl( multiplicity_set[2] ); + multiplicity += __builtin_popcountl( multiplicity_set[3] ); + } + + return multiplicity; + } + + template + uint32_t column_multiplicity5( STT const& tt ) + { + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; + + static_assert( free_set_size == 5 || free_set_size == 4, "Wrong free set size for method used, expected of 4 or 5" ); + + uint32_t size = 0; + uint64_t prev = -1; + std::array multiplicity_set; + + /* extract iset functions */ + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t cof = tt._bits[i]; + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint64_t fs_fn = cof & masks[free_set_size]; + if ( fs_fn != prev ) + { + multiplicity_set[size++] = static_cast( fs_fn ); + prev = fs_fn; + } + cof >>= ( 1u << free_set_size ); + } + } + + std::sort( multiplicity_set.begin(), multiplicity_set.begin() + size ); + + /* count unique */ + uint32_t multiplicity = 1; + for ( auto i = 1u; i < size; ++i ) + { + multiplicity += multiplicity_set[i] != multiplicity_set[i - 1] ? 1 : 0; + } + + return multiplicity; + } + + uint32_t column_multiplicity2( STT const& tt, uint32_t free_set_size ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t cofactors[4]; + uint32_t size = 0; + + /* extract iset functions */ + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t k; + for ( k = 0; k < size; ++k ) + { + if ( fs_fn == cofactors[k] ) + break; + } + if ( k == 2 ) + return 3; + if ( k == size ) + cofactors[size++] = fs_fn; + sub >>= shift; + } + } + + return size; + } + + inline bool combinations_offset_next( uint32_t k, uint32_t offset, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) + { + uint32_t i; + + for ( i = k - 1; pComb[i] == num_vars - k + i; --i ) + { + if ( i == offset ) + return false; + } + + /* move vars */ + uint32_t var_old = pComb[i]; + uint32_t pos_new = pInvPerm[var_old + 1]; + std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); + std::swap( pComb[i], pComb[pos_new] ); + swap_inplace_local( tt, i, pos_new ); + + for ( uint32_t j = i + 1; j < k; j++ ) + { + var_old = pComb[j]; + pos_new = pInvPerm[pComb[j - 1] + 1]; + std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); + std::swap( pComb[j], pComb[pos_new] ); + swap_inplace_local( tt, j, pos_new ); + } + + return true; + } + + template + std::tuple, uint32_t> enumerate_iset_combinations( uint32_t free_set_size, uint32_t offset, Fn&& fn ) + { + STT tt = best_tt; + + /* TT with best cost */ + STT local_best_tt = tt; + uint32_t best_cost = ( 1 << ( ps.lut_size - free_set_size ) ) + 1; + + assert( free_set_size >= offset ); + + /* special case */ + if ( free_set_size == offset ) + { + best_cost = fn( tt ); + return { tt, permutations, best_cost }; + } + + /* works up to 16 input truth tables */ + assert( num_vars <= 16 ); + + /* Search for column multiplicity of 2 */ + if ( free_set_size == ps.lut_size - 1 ) + { + return enumerate_iset_combinations2( free_set_size, offset ); + } + + /* init combinations */ + uint32_t pComb[16], pInvPerm[16], bestPerm[16]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* early bail-out conditions */ + uint32_t bail_multiplicity = 2; + if ( best_multiplicity < UINT32_MAX ) + { + bail_multiplicity = ( best_multiplicity >> 1 ) + ( best_multiplicity & 1 ); + } + + /* enumerate combinations */ + do + { + uint32_t cost = fn( tt ); + if ( cost < best_cost ) + { + local_best_tt = tt; + best_cost = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + bestPerm[i] = pComb[i]; + } + + if ( best_cost <= bail_multiplicity ) + { + break; + } + } + } while ( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + + std::array res_perm; + + if ( best_cost > ( 1 << ( ps.lut_size - free_set_size ) ) ) + { + return std::make_tuple( local_best_tt, res_perm, UINT32_MAX ); + } + + for ( uint32_t i = 0; i < num_vars; ++i ) + { + res_perm[i] = permutations[bestPerm[i]]; + } + + return std::make_tuple( local_best_tt, res_perm, best_cost ); + } + + inline std::tuple, uint32_t> enumerate_iset_combinations2( uint32_t free_set_size, uint32_t offset ) + { + STT tt = best_tt; + + /* TT with best cost */ + STT local_best_tt = tt; + uint32_t best_cost = ( 1 << ( ps.lut_size - free_set_size ) ) + 1; + + assert( free_set_size >= offset ); + + /* init combinations */ + uint32_t pComb[16], pInvPerm[16]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + std::array res_perm; + + do + { + uint32_t cost = column_multiplicity2( tt, free_set_size ); + if ( cost <= 2 ) + { + local_best_tt = tt; + best_cost = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + res_perm[i] = permutations[pComb[i]]; + } + return std::make_tuple( local_best_tt, res_perm, best_cost ); + } + } while ( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + + return std::make_tuple( local_best_tt, res_perm, UINT32_MAX ); + } + + std::vector compute_isets( bool verbose = false ) + { + /* construct isets involved in multiplicity */ + uint32_t isets_support = num_vars - best_free_set; + std::vector isets( best_multiplicity ); + + /* construct isets */ + std::unordered_map column_to_iset; + STT tt = best_tt; + uint32_t offset = 0; + uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; + + auto it = std::begin( tt ); + for ( auto i = 0u; i < num_blocks; ++i ) + { + for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) + { + uint64_t val = *it & masks[best_free_set]; + + auto el = column_to_iset.find( val ); + if ( el != column_to_iset.end() ) + { + isets[el->second]._bits[i / ( 1u << best_free_set )] |= UINT64_C( 1 ) << ( j + offset ); + } + else + { + isets[column_to_iset.size()]._bits[i / ( 1u << best_free_set )] |= UINT64_C( 1 ) << ( j + offset ); + column_to_iset[val] = column_to_iset.size(); + } + + *it >>= ( 1u << best_free_set ); + } + + offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; + ++it; + } + + /* extend isets to cover the whole truth table */ + for ( STT& iset : isets ) + { + local_extend_to( iset, isets_support ); + } + + /* save free_set functions */ + std::vector free_set_tts( best_multiplicity ); + + for ( auto const& pair : column_to_iset ) + { + free_set_tts[pair.second]._bits[0] = pair.first; + local_extend_to( free_set_tts[pair.second], best_free_set ); + } + + /* print isets and free set*/ + if ( verbose ) + { + std::cout << "iSets\n"; + uint32_t i = 0; + for ( auto iset : isets ) + { + kitty::print_hex( iset ); + std::cout << " of func "; + kitty::print_hex( free_set_tts[i++] ); + std::cout << "\n"; + } + } + + best_free_set_tts = std::move( free_set_tts ); + + return isets; + } + + void generate_decomposition() + { + dec_result.clear(); + + uint32_t num_edges = 0; + for ( uint32_t i = 0; i < best_bound_sets.size(); ++i ) + { + ac_decomposition_result dec; + auto tt = best_bound_sets[i]; + auto care = best_care_sets[i]; + + /* compute and minimize support for bound set variables */ + uint32_t k = 0; + for ( uint32_t j = 0; j < num_vars - best_free_set; ++j ) + { + if ( !kitty::has_var( tt, care, j ) ) + { + /* fix truth table */ + adjust_truth_table_on_dc( tt, care, tt.num_vars(), j ); + continue; + } + + if ( k < j ) + { + kitty::swap_inplace( tt, k, j ); + kitty::swap_inplace( care, k, j ); + } + dec.support.push_back( permutations[best_free_set + j] ); + ++k; + } + + dec.tt = kitty::shrink_to( tt, dec.support.size() ); + dec_result.push_back( dec ); + num_edges += dec.support.size() > 1 ? dec.support.size() : 0; + } + + /* compute the decomposition for the top-level LUT */ + compute_top_lut_decomposition(); + + if ( pst ) + { + pst->num_luts = dec_result.size(); + pst->num_edges = num_edges + dec_result.back().support.size(); + } + } + + void compute_top_lut_decomposition() + { + uint32_t top_vars = best_bound_sets.size() + best_free_set; + assert( top_vars <= ps.lut_size ); + + /* extend bound set functions with free_set_size LSB vars */ + kitty::dynamic_truth_table tt( top_vars ); + + /* compute support */ + dec_result.emplace_back(); + for ( uint32_t i = 0; i < best_free_set; ++i ) + { + dec_result.back().support.push_back( permutations[i] ); + } + + /* create functions for bound set */ + std::vector bound_set_vars; + auto res_it = dec_result.begin(); + uint32_t offset = 0; + for ( uint32_t i = 0; i < best_bound_sets.size(); ++i ) + { + bound_set_vars.emplace_back( top_vars ); + kitty::create_nth_var( bound_set_vars[i], best_free_set + i ); + + /* add bound-set variables to the support, remove buffers (shared set) */ + if ( res_it->support.size() == 1 ) + { + dec_result.back().support.push_back( res_it->support.front() ); + /* it is a NOT */ + if ( ( res_it->tt._bits[0] & 1 ) == 1 ) + { + bound_set_vars[i] = ~bound_set_vars[i]; + } + dec_result.erase( res_it ); + ++offset; + } + else + { + dec_result.back().support.push_back( num_vars + i - offset ); + ++res_it; + } + } + + /* create composition function */ + for ( uint32_t i = 0; i < best_free_set_tts.size(); ++i ) + { + kitty::dynamic_truth_table free_set_tt = kitty::shrink_to( best_free_set_tts[i], top_vars ); + + /* find MUX assignments */ + for ( uint32_t j = 0; j < bound_set_vars.size(); ++j ) + { + /* AND with ONSET or OFFSET */ + if ( ( ( best_iset_onset[j] >> i ) & 1 ) ) + { + free_set_tt &= bound_set_vars[j]; + } + else if ( ( ( best_iset_offset[j] >> i ) & 1 ) ) + { + free_set_tt &= ~bound_set_vars[j]; + } + } + + tt |= free_set_tt; + } + + /* add top-level LUT to result */ + dec_result.back().tt = tt; + } + + inline void reposition_late_arriving_variables( unsigned delay_profile, uint32_t late_arriving ) + { + uint32_t k = 0; + for ( uint32_t i = 0; i < late_arriving; ++i ) + { + while ( ( ( delay_profile >> k ) & 1 ) == 0 ) + ++k; + + if ( permutations[i] == k ) + { + ++k; + continue; + } + + std::swap( permutations[i], permutations[k] ); + swap_inplace_local( best_tt, i, k ); + ++k; + } + } + + template + void print_perm( Iterator begin, uint32_t free_set ) + { + std::cout << "["; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + if ( i == free_set ) + { + std::cout << ", "; + } + std::cout << *begin << " "; + ++begin; + } + std::cout << "]\n"; + } + + void generate_support_minimization_encodings() + { + uint32_t count = 0; + + /* enable don't cares only if not a power of 2 */ + uint32_t num_combs = 2; + if ( __builtin_popcount( best_multiplicity ) == 1 ) + { + uint32_t num_combs_exact[4] = { 1, 3, 35, 6435 }; + for ( uint32_t i = 0; i < 4; ++i ) + { + if ( ( best_multiplicity >> i ) == 2u ) + { + num_combs = num_combs_exact[i]; + } + } + support_minimization_encodings = std::vector>( num_combs ); + generate_support_minimization_encodings_rec( 0, 0, 0, count ); + } + else if ( best_multiplicity > 8 ) + { + /* combinations are 2^(mu - 1) */ + num_combs = 1u << ( best_multiplicity - 1 ); + support_minimization_encodings = std::vector>( num_combs ); + generate_support_minimization_encodings_rec( 0, 0, 0, count ); + } + else + { + /* combinations are 2*3^(mu - 1) */ + for ( uint32_t i = 1; i < best_multiplicity; ++i ) + { + num_combs = ( num_combs << 1 ) + num_combs; + } + support_minimization_encodings = std::vector>( num_combs ); + generate_support_minimization_encodings_rec( 0, 0, 0, count ); + } + + assert( count == num_combs ); + } + + template + void generate_support_minimization_encodings_rec( uint32_t onset, uint32_t offset, uint32_t var, uint32_t& count ) + { + if ( var == best_multiplicity ) + { + if ( equal_size_partition ) + { + /* sets must be equally populated */ + if ( __builtin_popcount( onset ) != __builtin_popcount( offset ) ) + { + return; + } + } + + support_minimization_encodings[count][0] = onset; + support_minimization_encodings[count][1] = offset; + ++count; + return; + } + + /* var in DCSET */ + if ( enable_dcset ) + { + generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + } + + /* move var in ONSET */ + onset |= 1 << var; + generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + onset &= ~( 1 << var ); + + /* remove symmetries */ + if ( var == 0 ) + { + return; + } + + /* move var in OFFSET */ + offset |= 1 << var; + generate_support_minimization_encodings_rec( onset, offset, var + 1, count ); + offset &= ~( 1 << var ); + } + + void solve_min_support_exact( std::vector const& isets ) + { + std::vector matrix; + matrix.reserve( support_minimization_encodings.size() ); + best_bound_sets.clear(); + + /* create covering matrix */ + if ( !create_covering_matrix( isets, matrix, false ) ) + { + return; + } + + /* solve the covering problem */ + std::array solution = covering_solve_exact( matrix ); + + /* check for failed decomposition */ + if ( solution[0] == UINT32_MAX ) + { + return; + } + + /* compute best bound sets */ + uint32_t num_luts = 1 + solution[5]; + uint32_t num_levels = 2; + uint32_t num_edges = best_free_set + solution[5]; + uint32_t isets_support = num_vars - best_free_set; + best_care_sets.clear(); + best_iset_onset.clear(); + best_iset_offset.clear(); + for ( uint32_t i = 0; i < solution[5]; ++i ) + { + STT tt; + STT care; + + const uint32_t onset = support_minimization_encodings[matrix[solution[i]].index][0]; + const uint32_t offset = support_minimization_encodings[matrix[solution[i]].index][1]; + for ( uint32_t j = 0; j < best_multiplicity; ++j ) + { + if ( ( ( onset >> j ) & 1 ) ) + { + tt |= isets[j]; + } + if ( ( ( offset >> j ) & 1 ) ) + { + care |= isets[j]; + } + } + + care |= tt; + num_edges += matrix[solution[i]].cost & ( ( 1 << isets_support ) - 1 ); + + best_bound_sets.push_back( tt ); + best_care_sets.push_back( care ); + best_iset_onset.push_back( onset ); + best_iset_offset.push_back( offset ); + } + + if ( pst ) + { + pst->num_luts = num_luts; + pst->num_levels = num_levels; + pst->num_edges = num_edges; + } + } + + void solve_min_support_heuristic( std::vector const& isets ) + { + std::vector matrix; + matrix.reserve( support_minimization_encodings.size() ); + best_bound_sets.clear(); + + /* create covering matrix */ + if ( !create_covering_matrix( isets, matrix, true ) ) + { + return; + } + + /* solve the covering problem: heuristic pass + local search */ + std::array solution = covering_solve_heuristic( matrix ); + + /* check for failed decomposition */ + if ( solution[0] == UINT32_MAX ) + { + return; + } + + /* improve solution with local search */ + while ( covering_improve( matrix, solution ) ) + ; + + /* compute best bound sets */ + uint32_t num_luts = 1 + solution[5]; + uint32_t num_levels = 2; + uint32_t num_edges = best_free_set + solution[5]; + uint32_t isets_support = num_vars - best_free_set; + best_care_sets.clear(); + best_iset_onset.clear(); + best_iset_offset.clear(); + for ( uint32_t i = 0; i < solution[5]; ++i ) + { + STT tt; + STT care; + + const uint32_t onset = support_minimization_encodings[matrix[solution[i]].index][0]; + const uint32_t offset = support_minimization_encodings[matrix[solution[i]].index][1]; + for ( uint32_t j = 0; j < best_multiplicity; ++j ) + { + if ( ( ( onset >> j ) & 1 ) ) + { + tt |= isets[j]; + } + if ( ( ( offset >> j ) & 1 ) ) + { + care |= isets[j]; + } + } + + care |= tt; + num_edges += matrix[solution[i]].cost & ( ( 1 << isets_support ) - 1 ); + + best_bound_sets.push_back( tt ); + best_care_sets.push_back( care ); + best_iset_onset.push_back( onset ); + best_iset_offset.push_back( offset ); + } + + if ( pst ) + { + pst->num_luts = num_luts; + pst->num_levels = num_levels; + pst->num_edges = num_edges; + } + } + + template + bool create_covering_matrix( std::vector const& isets, std::vector& matrix, bool sort ) + { + assert( best_multiplicity <= 16 ); + uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; + uint32_t iset_support = num_vars - best_free_set; + + /* insert dichotomies */ + for ( uint32_t i = 0; i < support_minimization_encodings.size(); ++i ) + { + uint32_t const onset = support_minimization_encodings[i][0]; + uint32_t const offset = support_minimization_encodings[i][1]; + + uint32_t ones_onset = __builtin_popcount( onset ); + uint32_t ones_offset = __builtin_popcount( offset ); + + /* filter columns that do not distinguish pairs */ + if ( ones_onset == 0 || ones_offset == 0 || ones_onset == best_multiplicity || ones_offset == best_multiplicity ) + { + continue; + } + + /* compute function and distinguishable seed dichotomies */ + uint64_t column[2] = { 0, 0 }; + STT tt; + STT care; + uint32_t pair_pointer = 0; + for ( uint32_t j = 0; j < best_multiplicity; ++j ) + { + auto onset_shift = ( onset >> j ); + auto offset_shift = ( offset >> j ); + if ( ( onset_shift & 1 ) ) + { + tt |= isets[j]; + } + + if ( ( offset_shift & 1 ) ) + { + care |= isets[j]; + } + + /* compute included seed dichotomies */ + for ( uint32_t k = j + 1; k < best_multiplicity; ++k ) + { + /* if are in diffent sets */ + if ( ( ( ( onset_shift & ( offset >> k ) ) | ( ( onset >> k ) & offset_shift ) ) & 1 ) ) + { + column[pair_pointer >> 6u] |= UINT64_C( 1 ) << ( pair_pointer & 0x3F ); + } + + ++pair_pointer; + } + } + + care |= tt; + + /* compute cost */ + uint32_t cost = 0; + for ( uint32_t j = 0; j < iset_support; ++j ) + { + cost += has_var_support( tt, care, iset_support, j ) ? 1 : 0; + // if ( !has_var_support( tt, care, iset_support, j ) ) + // { + // /* adjust truth table and care set */ + // adjust_truth_table_on_dc( tt, care, iset_support, j ); + // continue; + // } + // ++cost; + } + + /* discard solutions with support over LUT size */ + if ( cost > ps.lut_size ) + continue; + + /* buffers have zero cost */ + if ( cost == 1 ) + cost = 0; + + float sort_cost = 0; + if ( UseHeuristic ) + { + sort_cost = 1.0f / ( __builtin_popcountl( column[0] ) + __builtin_popcountl( column[1] ) ); + } + else + { + sort_cost = cost + ( ( combinations - __builtin_popcountl( column[0] + __builtin_popcountl( column[1] ) ) ) << num_vars ); + } + + /* insert */ + matrix.emplace_back( encoding_column{ { column[0], column[1] }, cost, i, sort_cost } ); + } + + if ( !sort ) + { + return true; + } + + if ( UseHeuristic ) + { + std::sort( matrix.begin(), matrix.end(), [&]( encoding_column const& a, encoding_column const& b ) { + return a.cost < b.cost; + } ); + } + else + { + std::sort( matrix.begin(), matrix.end(), [&]( encoding_column const& a, encoding_column const& b ) { + return a.sort_cost < b.sort_cost; + } ); + } + + return true; + } + + std::array covering_solve_exact( std::vector& matrix ) + { + /* last value of res contains the size of the bound set */ + std::array res = { UINT32_MAX }; + uint32_t best_cost = UINT32_MAX; + uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; + + assert( best_multiplicity <= 4 ); + + /* determine the number of needed loops*/ + if ( best_multiplicity <= 2 ) + { + res[5] = 1; + res[0] = 0; + } + else if ( best_multiplicity <= 4 ) + { + res[5] = 2; + for ( uint32_t i = 0; i < matrix.size() - 1; ++i ) + { + for ( uint32_t j = 1; j < matrix.size(); ++j ) + { + /* filter by cost */ + if ( matrix[i].cost + matrix[j].cost >= best_cost ) + continue; + + /* check validity */ + if ( __builtin_popcountl( matrix[i].column[0] | matrix[j].column[0] ) + __builtin_popcountl( matrix[i].column[1] | matrix[j].column[1] ) == combinations ) + { + res[0] = i; + res[1] = j; + best_cost = matrix[i].cost + matrix[j].cost; + } + } + } + } + + return res; + } + + std::array covering_solve_heuristic( std::vector& matrix ) + { + /* last value of res contains the size of the bound set */ + std::array res = { UINT32_MAX }; + uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; + uint64_t column0 = 0, column1 = 0; + + uint32_t best = 0; + float best_cost = std::numeric_limits::max(); + for ( uint32_t i = 0; i < matrix.size(); ++i ) + { + if ( matrix[i].sort_cost < best_cost ) + { + best = i; + best_cost = matrix[i].sort_cost; + } + } + + /* select */ + column0 = matrix[best].column[0]; + column1 = matrix[best].column[1]; + std::swap( matrix[0], matrix[best] ); + + /* get max number of BS's */ + uint32_t iter = 1; + + while ( iter < ps.lut_size - best_free_set && __builtin_popcountl( column0 ) + __builtin_popcountl( column1 ) != combinations ) + { + /* select column that minimizes the cost */ + best = 0; + best_cost = std::numeric_limits::max(); + for ( uint32_t i = iter; i < matrix.size(); ++i ) + { + float local_cost = 1.0f / ( __builtin_popcountl( matrix[i].column[0] & ~column0 ) + __builtin_popcountl( matrix[i].column[1] & ~column1 ) ); + if ( local_cost < best_cost ) + { + best = i; + best_cost = local_cost; + } + } + + column0 |= matrix[best].column[0]; + column1 |= matrix[best].column[1]; + std::swap( matrix[iter], matrix[best] ); + ++iter; + } + + if ( __builtin_popcountl( column0 ) + __builtin_popcountl( column1 ) == combinations ) + { + for ( uint32_t i = 0; i < iter; ++i ) + { + res[i] = i; + } + res[5] = iter; + } + + return res; + } + + bool covering_improve( std::vector const& matrix, std::array& solution ) + { + /* performs one iteration of local search */ + uint32_t best_cost = 0, local_cost = 0; + uint32_t num_elements = solution[5]; + uint32_t combinations = ( best_multiplicity * ( best_multiplicity - 1 ) ) / 2; + bool improved = false; + + /* compute current cost */ + for ( uint32_t i = 0; i < num_elements; ++i ) + { + best_cost += matrix[solution[i]].cost; + } + + uint64_t column0, column1; + for ( uint32_t i = 0; i < num_elements; ++i ) + { + /* remove element i */ + local_cost = 0; + column0 = 0; + column1 = 0; + for ( uint32_t j = 0; j < num_elements; ++j ) + { + if ( j == i ) + continue; + local_cost += matrix[solution[j]].cost; + column0 |= matrix[solution[j]].column[0]; + column1 |= matrix[solution[j]].column[1]; + } + + /* search for a better replecemnts */ + for ( uint32_t j = 0; j < matrix.size(); ++j ) + { + if ( __builtin_popcount( column0 | matrix[j].column[0] ) + __builtin_popcount( column1 | matrix[j].column[1] ) != combinations ) + continue; + if ( local_cost + matrix[j].cost < best_cost ) + { + solution[i] = j; + best_cost = local_cost + matrix[j].cost; + improved = true; + } + } + } + + return improved; + } + + void adjust_truth_table_on_dc( STT& tt, STT& care, uint32_t real_num_vars, uint32_t var_index ) + { + assert( var_index < real_num_vars ); + assert( tt.num_vars() == care.num_vars() ); + + const uint32_t num_blocks = real_num_vars <= 6 ? 1 : ( 1 << ( real_num_vars - 6 ) ); + if ( real_num_vars <= 6 || var_index < 6 ) + { + auto it_tt = std::begin( tt._bits ); + auto it_care = std::begin( care._bits ); + while ( it_tt != std::begin( tt._bits ) + num_blocks ) + { + uint64_t new_bits = *it_tt & *it_care; + *it_tt = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) | + ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] ); + *it_care = ( *it_care | ( *it_care >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index]; + *it_care = *it_care | ( *it_care << ( uint64_t( 1 ) << var_index ) ); + + ++it_tt; + ++it_care; + } + return; + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < static_cast( num_blocks ); i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + tt._bits[i + j] = ( tt._bits[i + j] & care._bits[i + j] ) | ( tt._bits[i + j + step] & care._bits[i + j + step] ); + tt._bits[i + j + step] = tt._bits[i + j]; + care._bits[i + j] = care._bits[i + j] | care._bits[i + j + step]; + care._bits[i + j + step] = care._bits[i + j]; + } + } + } + + void local_extend_to( STT& tt, uint32_t real_num_vars ) + { + if ( real_num_vars < 6 ) + { + auto mask = *tt.begin(); + + for ( auto i = real_num_vars; i < num_vars; ++i ) + { + mask |= ( mask << ( 1 << i ) ); + } + + std::fill( tt.begin(), tt.end(), mask ); + } + else + { + uint32_t num_blocks = ( 1u << ( real_num_vars - 6 ) ); + auto it = tt.begin(); + while ( it != tt.end() ) + { + it = std::copy( tt.cbegin(), tt.cbegin() + num_blocks, it ); + } + } + } + + bool has_var_support( const STT& tt, const STT& care, uint32_t real_num_vars, uint8_t var_index ) + { + assert( var_index < real_num_vars ); + assert( real_num_vars <= tt.num_vars() ); + assert( tt.num_vars() == care.num_vars() ); + + const uint32_t num_blocks = real_num_vars <= 6 ? 1 : ( 1 << ( real_num_vars - 6 ) ); + if ( real_num_vars <= 6 || var_index < 6 ) + { + auto it_tt = std::begin( tt._bits ); + auto it_care = std::begin( care._bits ); + while ( it_tt != std::begin( tt._bits ) + num_blocks ) + { + if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & kitty::detail::projections_neg[var_index] & ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 ) + { + return true; + } + ++it_tt; + ++it_care; + } + + return false; + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < num_blocks; i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + if ( ( ( tt._bits[i + j] ^ tt._bits[i + j + step] ) & care._bits[i + j] & care._bits[i + j + step] ) != 0 ) + { + return true; + } + } + } + + return false; + } + + void swap_inplace_local( STT& tt, uint8_t var_index1, uint8_t var_index2 ) + { + if ( var_index1 == var_index2 ) + { + return; + } + + if ( var_index1 > var_index2 ) + { + std::swap( var_index1, var_index2 ); + } + + const uint32_t num_blocks = num_vars <= 6 ? 1 : 1 << ( num_vars - 6 ); + + if ( num_vars <= 6 ) + { + const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + tt._bits[0] = ( tt._bits[0] & pmask[0] ) | ( ( tt._bits[0] & pmask[1] ) << shift ) | ( ( tt._bits[0] & pmask[2] ) >> shift ); + } + else if ( var_index2 <= 5 ) + { + const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + std::transform( std::begin( tt._bits ), std::begin( tt._bits ) + num_blocks, std::begin( tt._bits ), + [shift, &pmask]( uint64_t word ) { + return ( word & pmask[0] ) | ( ( word & pmask[1] ) << shift ) | ( ( word & pmask[2] ) >> shift ); + } ); + } + else if ( var_index1 <= 5 ) /* in this case, var_index2 > 5 */ + { + const auto step = 1 << ( var_index2 - 6 ); + const auto shift = 1 << var_index1; + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = decltype( step ){ 0 }; i < step; ++i ) + { + const auto low_to_high = ( *( it + i ) & kitty::detail::projections[var_index1] ) >> shift; + const auto high_to_low = ( *( it + i + step ) << shift ) & kitty::detail::projections[var_index1]; + *( it + i ) = ( *( it + i ) & ~kitty::detail::projections[var_index1] ) | high_to_low; + *( it + i + step ) = ( *( it + i + step ) & kitty::detail::projections[var_index1] ) | low_to_high; + } + it += 2 * step; + } + } + else + { + const auto step1 = 1 << ( var_index1 - 6 ); + const auto step2 = 1 << ( var_index2 - 6 ); + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = 0; i < step2; i += 2 * step1 ) + { + for ( auto j = 0; j < step1; ++j ) + { + std::swap( *( it + i + j + step1 ), *( it + i + j + step2 ) ); + } + } + it += 2 * step2; + } + } + } + + /* Decomposition format for ABC + * + * The record is an array of unsigned chars where: + * - the first unsigned char entry stores the number of unsigned chars in the record + * - the second entry stores the number of LUTs + * After this, several sub-records follow, each representing one LUT as follows: + * - an unsigned char entry listing the number of fanins + * - a list of fanins, from the LSB to the MSB of the truth table. The N inputs of the original function + * have indexes from 0 to N-1, followed by the internal signals in a topological order + * - the LUT truth table occupying 2^(M-3) bytes, where M is the fanin count of the LUT, from the LSB to the MSB. + * A 2-input LUT, which takes 4 bits, should be stretched to occupy 8 bits (one unsigned char) + * A 0- or 1-input LUT can be represented similarly but it is not expected that such LUTs will be represented + */ + void get_decomposition_abc( unsigned char* decompArray ) + { + unsigned char* pArray = decompArray; + unsigned char bytes = 2; + + /* write number of LUTs */ + pArray++; + *pArray++ = dec_result.size(); + + /* write LUTs */ + for ( ac_decomposition_result const& lut : dec_result ) + { + /* write fanin size*/ + *pArray++ = lut.support.size(); + ++bytes; + + /* write support */ + for ( uint32_t i : lut.support ) + { + *pArray++ = (unsigned char)i; + ++bytes; + } + + /* write truth table */ + uint32_t tt_num_bytes = ( lut.tt.num_vars() <= 3 ) ? 1 : ( 1 << ( lut.tt.num_vars() - 3 ) ); + tt_num_bytes = std::min( tt_num_bytes, 8u ); + for ( uint32_t i = 0; i < lut.tt.num_blocks(); ++i ) + { + for ( uint32_t j = 0; j < tt_num_bytes; ++j ) + { + *pArray++ = (unsigned char)( ( lut.tt._bits[i] >> ( 8 * j ) ) & 0xFF ); + ++bytes; + } + } + } + + /* write numBytes */ + *decompArray = bytes; + } + +private: + uint32_t best_multiplicity{ UINT32_MAX }; + uint32_t best_free_set{ UINT32_MAX }; + STT best_tt; + std::vector best_bound_sets; + std::vector best_care_sets; + std::vector best_free_set_tts; + std::vector best_iset_onset; + std::vector best_iset_offset; + std::vector dec_result; + + std::vector> support_minimization_encodings; + + uint32_t num_vars; + ac_decomposition_params ps; + ac_decomposition_stats* pst; + std::array permutations; +}; + +} // namespace acd + +ABC_NAMESPACE_CXX_HEADER_END + +#endif // _ACD_H_ \ No newline at end of file diff --git a/src/map/if/acd/ac_wrapper.cpp b/src/map/if/acd/ac_wrapper.cpp new file mode 100644 index 000000000..ad923edd2 --- /dev/null +++ b/src/map/if/acd/ac_wrapper.cpp @@ -0,0 +1,168 @@ +/**C++File************************************************************** + + FileName [ac_wrapper.cpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Ashenhurst-Curtis decomposition.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alessandro Tempia Calvino] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - November 20, 2023.] + +***********************************************************************/ + +#include "ac_wrapper.h" +#include "ac_decomposition.hpp" +#include "acd66.hpp" +#include "acdXX.hpp" + +ABC_NAMESPACE_IMPL_START + +int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ) +{ + using namespace acd; + + ac_decomposition_params ps; + ps.lut_size = lutSize; + ps.use_first = false; + ps.try_no_late_arrival = static_cast( try_no_late_arrival ); + ac_decomposition_stats st; + + ac_decomposition_impl acd( nVars, ps, &st ); + int val = acd.run( pTruth, *pdelay ); + + if ( val < 0 ) + { + *pdelay = 0; + return -1; + } + + *pdelay = acd.get_profile(); + *cost = st.num_luts; + + return val; +} + +int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ) +{ + using namespace acd; + + ac_decomposition_params ps; + ps.lut_size = lutSize; + ps.use_first = true; + ac_decomposition_stats st; + + ac_decomposition_impl acd( nVars, ps, &st ); + acd.run( pTruth, *pdelay ); + int val = acd.compute_decomposition(); + + if ( val < 0 ) + { + *pdelay = 0; + return -1; + } + + *pdelay = acd.get_profile(); + acd.get_decomposition( decomposition ); + return 0; +} + +int acd2_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ) +{ + using namespace acd; + + acdXX_params ps; + ps.lut_size = lutSize; + ps.max_shared_vars = lutSize - 2; + acdXX_impl acd( nVars, ps ); + int val = acd.run( pTruth, *pdelay ); + + if ( val == 0 ) + { + *pdelay = 0; + return -1; + } + + acd.compute_decomposition(); + *pdelay = acd.get_profile(); + *cost = 2; + + return val; +} + +int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ) +{ + using namespace acd; + + acdXX_params ps; + ps.lut_size = lutSize; + ps.max_shared_vars = lutSize - 2; + acdXX_impl acd( nVars, ps ); + acd.run( pTruth, *pdelay ); + int val = acd.compute_decomposition(); + + if ( val != 0 ) + { + *pdelay = 0; + return -1; + } + + *pdelay = acd.get_profile(); + + acd.get_decomposition( decomposition ); + return 0; +} + +inline int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition ) +{ + using namespace acd; + acd66_impl acd( nVars, true, false ); + + if ( acd.run( pTruth ) == 0 ) + return 0; + if ( decomposition == NULL ) + return 1; + int val = acd.compute_decomposition(); + if ( val != 0 ) + { + return 0; + } + acd.get_decomposition( decomposition ); + + return 1; +} + +int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition ) +{ + using namespace acd; + + if ( lutSize == 6 ) + { + return acd66_decompose( pTruth, nVars, decomposition ); + } + + acdXX_params ps; + ps.lut_size = lutSize; + ps.max_shared_vars = lutSize - 2; + acdXX_impl acd( nVars, ps ); + + if ( acd.run( pTruth ) == 0 ) + return 0; + if ( decomposition == NULL ) + return 1; + int val = acd.compute_decomposition(); + if ( val != 0 ) + { + return 0; + } + acd.get_decomposition( decomposition ); + + return 1; +} + +ABC_NAMESPACE_IMPL_END diff --git a/src/map/if/acd/ac_wrapper.h b/src/map/if/acd/ac_wrapper.h new file mode 100644 index 000000000..edb45ca7f --- /dev/null +++ b/src/map/if/acd/ac_wrapper.h @@ -0,0 +1,44 @@ +/**C++File************************************************************** + + FileName [ac_wrapper.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Ashenhurst-Curtis decomposition.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alessandro Tempia Calvino] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - November 20, 2023.] + +***********************************************************************/ + +#pragma once +#ifndef __ACD_WRAPPER_H_ +#define __ACD_WRAPPER_H_ + +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +//# define __builtin_popcountl __popcnt64 // the compiler does not find __popcnt64 +# define __builtin_popcountl __popcnt +#endif + +#include "misc/util/abc_global.h" +#include "map/if/if.h" + +ABC_NAMESPACE_HEADER_START + +int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); +int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); +int acd2_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); +int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); + +int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition ); + +ABC_NAMESPACE_HEADER_END + +#endif \ No newline at end of file diff --git a/src/map/if/acd/acd66.hpp b/src/map/if/acd/acd66.hpp new file mode 100644 index 000000000..109512986 --- /dev/null +++ b/src/map/if/acd/acd66.hpp @@ -0,0 +1,1233 @@ +/**C++File************************************************************** + + FileName [acd66.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Ashenhurst-Curtis decomposition.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alessandro Tempia Calvino] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - Feb 8, 2024.] + +***********************************************************************/ +/*! + \file acd66.hpp + \brief Ashenhurst-Curtis decomposition for "66" cascade + + \author Alessandro Tempia Calvino +*/ + +#ifndef _ACD66_H_ +#define _ACD66_H_ +#pragma once + +#include +#include +#include +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_constructors.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_operations.hpp" +#include "kitty_operators.hpp" +#include "kitty_static_tt.hpp" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace acd +{ + +class acd66_impl +{ +private: + static constexpr uint32_t max_num_vars = 11; + using STT = kitty::static_truth_table; + using LTT = kitty::static_truth_table<6>; + +public: + explicit acd66_impl( uint32_t const num_vars, bool multiple_shared_set = false, bool const verify = false ) + : num_vars( num_vars ), multiple_ss( multiple_shared_set ), verify( verify ) + { + std::iota( permutations.begin(), permutations.end(), 0 ); + } + + /*! \brief Runs ACD 66 */ + bool run( word* ptt ) + { + assert( num_vars > 6 ); + + /* truth table is too large for the settings */ + if ( num_vars > max_num_vars || num_vars > 11 ) + { + return false; + } + + /* convert to static TT */ + init_truth_table( ptt ); + + /* run ACD trying different bound sets and free sets */ + return find_decomposition(); + } + + /*! \brief Runs ACD 66 */ + int run( word* ptt, unsigned delay_profile ) + { + assert( num_vars > 6 ); + + /* truth table is too large for the settings */ + if ( num_vars > max_num_vars || num_vars > 11 ) + { + return false; + } + + uint32_t late_arriving = __builtin_popcount( delay_profile ); + + /* too many late arriving variables */ + if ( late_arriving > 5 ) + return 0; + + /* convert to static TT */ + init_truth_table( ptt ); + best_tt = start_tt; + + /* permute late arriving variables to be the least significant */ + reposition_late_arriving_variables( delay_profile, late_arriving ); + + /* run ACD trying different bound sets and free sets */ + return find_decomposition_offset( late_arriving ) ? ( delay_profile == 0 ? 2 : 1 ) : 0; + } + + int compute_decomposition() + { + if ( best_multiplicity == UINT32_MAX ) + return -1; + + compute_decomposition_impl(); + + if ( verify && !verify_impl() ) + { + return 1; + } + + return 0; + } + + uint32_t get_num_edges() + { + if ( bs_support_size == UINT32_MAX ) + { + return num_vars + 1 + num_shared_vars; + } + + /* real value after support minimization */ + return bs_support_size + best_free_set + 1 + num_shared_vars; + } + + /* contains a 1 for FS variables */ + unsigned get_profile() + { + unsigned profile = 0; + + if ( best_multiplicity == UINT32_MAX ) + return -1; + + if ( bs_support_size == UINT32_MAX ) + { + for ( uint32_t i = 0; i < best_free_set; ++i ) + { + profile |= 1 << permutations[i]; + } + } + else + { + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + profile |= 1 << permutations[bs_support[i] + best_free_set]; + } + profile = ~profile & ( ( 1u << num_vars ) - 1 ); + } + + return profile; + } + + void get_decomposition( unsigned char* decompArray ) + { + if ( bs_support_size == UINT32_MAX ) + return; + + get_decomposition_abc( decompArray ); + } + +private: + bool find_decomposition() + { + best_multiplicity = UINT32_MAX; + best_free_set = UINT32_MAX; + + /* use multiple shared set variables */ + if ( multiple_ss ) + { + return find_decomposition_bs_multi_ss( num_vars - 6 ); + } + + uint32_t max_free_set = num_vars == 11 ? 5 : 4; + + /* find ACD "66" for different number of variables in the free set */ + for ( uint32_t i = num_vars - 6; i <= max_free_set; ++i ) + { + if ( find_decomposition_bs( i ) ) + return true; + } + + best_multiplicity = UINT32_MAX; + return false; + } + + bool find_decomposition_offset( uint32_t offset ) + { + best_multiplicity = UINT32_MAX; + best_free_set = UINT32_MAX; + + /* use multiple shared set variables */ + if ( multiple_ss ) + { + return find_decomposition_bs_offset_multi_ss( std::max( num_vars - 6, offset ), offset ); + } + + uint32_t max_free_set = ( num_vars == 11 || offset == 5 ) ? 5 : 4; + + /* find ACD "66" for different number of variables in the free set */ + for ( uint32_t i = std::max( num_vars - 6, offset ); i <= max_free_set; ++i ) + { + if ( find_decomposition_bs_offset( i, offset ) ) + return true; + } + + best_multiplicity = UINT32_MAX; + return false; + } + + void init_truth_table( word* ptt ) + { + uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) ); + + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + start_tt._bits[i] = ptt[i]; + } + + local_extend_to( start_tt, num_vars ); + } + + uint32_t column_multiplicity( STT const& tt, uint32_t const free_set_size ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const limit = free_set_size < 5 ? 4 : 2; + uint32_t cofactors[4]; + uint32_t size = 0; + + /* extract iset functions */ + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t k; + for ( k = 0; k < size; ++k ) + { + if ( fs_fn == cofactors[k] ) + break; + } + if ( k == limit ) + return 5; + if ( k == size ) + cofactors[size++] = fs_fn; + sub >>= shift; + } + } + + return size; + } + + uint32_t column_multiplicity2( STT const& tt, uint32_t const free_set_size, uint32_t const limit ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t cofactors[32]; + uint32_t size = 0; + + /* extract iset functions */ + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t k; + for ( k = 0; k < size; ++k ) + { + if ( fs_fn == cofactors[k] ) + break; + } + if ( k == limit ) + return limit + 1; + if ( k == size ) + cofactors[size++] = fs_fn; + sub >>= shift; + } + } + + return size; + } + + inline bool combinations_next( uint32_t k, uint32_t offset, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) + { + uint32_t i; + + for ( i = k - 1; pComb[i] == num_vars - k + i; --i ) + { + if ( i == offset ) + return false; + } + + /* move vars */ + uint32_t var_old = pComb[i]; + uint32_t pos_new = pInvPerm[var_old + 1]; + std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); + std::swap( pComb[i], pComb[pos_new] ); + swap_inplace_local( tt, i, pos_new ); + + for ( uint32_t j = i + 1; j < k; j++ ) + { + var_old = pComb[j]; + pos_new = pInvPerm[pComb[j - 1] + 1]; + std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); + std::swap( pComb[j], pComb[pos_new] ); + swap_inplace_local( tt, j, pos_new ); + } + + return true; + } + + inline bool combinations_next_simple( uint32_t k, uint32_t* pComb, uint32_t* pInvPerm, uint32_t size ) + { + uint32_t i; + + for ( i = k - 1; pComb[i] == size - k + i; --i ) + { + if ( i == 0 ) + return false; + } + + /* move vars */ + uint32_t var_old = pComb[i]; + uint32_t pos_new = pInvPerm[var_old + 1]; + std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); + std::swap( pComb[i], pComb[pos_new] ); + + for ( uint32_t j = i + 1; j < k; j++ ) + { + var_old = pComb[j]; + pos_new = pInvPerm[pComb[j - 1] + 1]; + std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); + std::swap( pComb[j], pComb[pos_new] ); + } + + return true; + } + + bool find_decomposition_bs( uint32_t free_set_size ) + { + STT tt = start_tt; + + /* works up to 16 input truth tables */ + assert( num_vars <= 16 ); + + /* init combinations */ + uint32_t pComb[16], pInvPerm[16]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + best_free_set = free_set_size; + do + { + uint32_t cost = column_multiplicity( tt, free_set_size ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + return true; + } + else if ( cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set( tt ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, res, num_vars - 1 ); + std::swap( permutations[res], permutations[num_vars - 1] ); + num_shared_vars = 1; + return true; + } + } + } while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) ); + + return false; + } + + bool find_decomposition_bs_offset( uint32_t free_set_size, uint32_t offset ) + { + STT tt = best_tt; + + /* works up to 16 input truth tables */ + assert( num_vars <= 16 ); + best_free_set = free_set_size; + + /* special case */ + if ( free_set_size == offset ) + { + uint32_t cost = column_multiplicity( tt, free_set_size ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + return true; + } + else if ( cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set( tt ); + + if ( res >= 0 ) + { + best_tt = tt; + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, res, num_vars - 1 ); + std::swap( permutations[res], permutations[num_vars - 1] ); + num_shared_vars = 1; + return true; + } + } + return false; + } + + /* init combinations */ + uint32_t pComb[16], pInvPerm[16]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + do + { + uint32_t cost = column_multiplicity( tt, free_set_size ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + return true; + } + else if ( cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set( tt ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, res, num_vars - 1 ); + std::swap( permutations[res], permutations[num_vars - 1] ); + num_shared_vars = 1; + return true; + } + } + } while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + + return false; + } + + bool find_decomposition_bs_multi_ss( uint32_t free_set_size ) + { + STT tt = start_tt; + + /* works up to 16 input truth tables */ + assert( num_vars <= 16 ); + + /* init combinations */ + uint32_t pComb[16], pInvPerm[16], shared_set[4]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + best_free_set = free_set_size; + do + { + uint32_t cost = column_multiplicity2( tt, free_set_size, 1 << ( 6 - free_set_size ) ); + if ( cost <= 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + return true; + } + + uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2 + : cost <= 16 ? 3 + : cost <= 32 ? 4 + : 5; + if ( ss_vars_needed + free_set_size < 6 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set_multi( tt, ss_vars_needed, shared_set ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + /* move shared variables as the most significative ones */ + for ( int32_t i = res - 1; i >= 0; --i ) + { + swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i ); + std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] ); + } + num_shared_vars = res; + return true; + } + } + } while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) ); + + best_multiplicity = UINT32_MAX; + return false; + } + + bool find_decomposition_bs_offset_multi_ss( uint32_t free_set_size, uint32_t offset ) + { + STT tt = best_tt; + + /* works up to 16 input truth tables */ + assert( num_vars <= 16 ); + best_free_set = free_set_size; + uint32_t shared_set[4]; + + /* special case */ + if ( free_set_size == offset ) + { + uint32_t cost = column_multiplicity2( tt, free_set_size, 1 << ( 6 - free_set_size ) ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + return true; + } + + uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2 + : cost <= 16 ? 3 + : cost <= 32 ? 4 + : 5; + + if ( ss_vars_needed + free_set_size < 6 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set_multi( tt, ss_vars_needed, shared_set ); + + if ( res >= 0 ) + { + best_tt = tt; + /* move shared variables as the most significative ones */ + for ( int32_t i = res - 1; i >= 0; --i ) + { + swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i ); + std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] ); + } + num_shared_vars = res; + return true; + } + } + + best_multiplicity = UINT32_MAX; + return false; + } + + /* init combinations */ + uint32_t pComb[16], pInvPerm[16]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + do + { + uint32_t cost = column_multiplicity2( tt, free_set_size, 1 << ( 6 - free_set_size ) ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + return true; + } + + uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2 + : cost <= 16 ? 3 + : cost <= 32 ? 4 + : 5; + + if ( ss_vars_needed + free_set_size < 6 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set_multi( tt, ss_vars_needed, shared_set ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + /* move shared variables as the most significative ones */ + for ( int32_t i = res - 1; i >= 0; --i ) + { + swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i ); + std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] ); + } + num_shared_vars = res; + return true; + } + } + } while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + + best_multiplicity = UINT32_MAX; + return false; + } + + bool check_shared_var( STT const& tt, uint32_t free_set_size, uint32_t shared_var ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t cofactors[2][4]; + uint32_t size[2] = { 0, 0 }; + uint32_t shared_var_shift = shared_var - free_set_size; + + /* extract iset functions */ + uint32_t iteration_counter = 0; + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t p = ( iteration_counter >> shared_var_shift ) & 1; + uint32_t k; + for ( k = 0; k < size[p]; ++k ) + { + if ( fs_fn == cofactors[p][k] ) + break; + } + if ( k == 2 ) + return false; + if ( k == size[p] ) + cofactors[p][size[p]++] = fs_fn; + sub >>= shift; + ++iteration_counter; + } + } + + return true; + } + + inline int check_shared_set( STT const& tt ) + { + /* find one shared set variable */ + for ( uint32_t i = best_free_set; i < num_vars; ++i ) + { + /* check the multiplicity of cofactors */ + if ( check_shared_var( tt, best_free_set, i ) ) + { + return i; + } + } + + return -1; + } + + bool check_shared_var_combined( STT const& tt, uint32_t free_set_size, uint32_t shared_vars[6], uint32_t num_shared_vars ) + { + assert( free_set_size <= 5 ); + assert( num_shared_vars <= 4 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t cofactors[16][2]; + uint32_t size[16] = { 0 }; + + /* extract iset functions */ + uint32_t iteration_counter = 0; + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < ( 64 >> free_set_size ); ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t p = 0; + for ( uint32_t k = 0; k < num_shared_vars; ++k ) + { + p |= ( ( iteration_counter >> shared_vars[k] ) & 1 ) << k; + } + + uint32_t k; + for ( k = 0; k < size[p]; ++k ) + { + if ( fs_fn == cofactors[p][k] ) + break; + } + if ( k == 2 ) + return false; + if ( k == size[p] ) + cofactors[p][size[p]++] = fs_fn; + sub >>= shift; + ++iteration_counter; + } + } + + return true; + } + + inline int check_shared_set_multi( STT const& tt, uint32_t target_num_ss, uint32_t* res_shared ) + { + /* init combinations */ + uint32_t pComb[6], pInvPerm[6]; + + /* search for a feasible shared set */ + for ( uint32_t i = target_num_ss; i < 6 - best_free_set; ++i ) + { + for ( uint32_t i = 0; i < 6; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + do + { + /* check for combined shared set */ + if ( check_shared_var_combined( tt, best_free_set, pComb, i ) ) + { + for ( uint32_t j = 0; j < i; ++j ) + { + res_shared[j] = pComb[j]; + } + /* sort vars */ + std::sort( res_shared, res_shared + i ); + return i; + } + } while ( combinations_next_simple( i, pComb, pInvPerm, num_vars - best_free_set ) ); + } + + return -1; + } + + void compute_decomposition_impl( bool verbose = false ) + { + /* construct isets involved in multiplicity */ + LTT composition; + LTT bs; + LTT bs_dc; + + /* construct isets */ + uint32_t offset = 0; + uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << best_free_set; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const num_groups = 1 << num_shared_vars; + uint32_t const next_group = 1 << ( num_vars - best_free_set - num_shared_vars ); + + uint64_t fs_fun[32] = { 0 }; + uint64_t dc_mask = ( ( UINT64_C( 1 ) << next_group ) - 1 ); + + uint32_t group_index = 0; + uint32_t set_index = 0; + fs_fun[0] = best_tt._bits[0] & mask; + bool set_dc = true; + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t cof = best_tt._bits[i]; + for ( auto j = 0; j < ( 64 >> best_free_set ); ++j ) + { + uint64_t val = cof & mask; + /* move to next block */ + if ( set_index == next_group ) + { + if ( set_dc ) + { + /* only one cofactor can be found in the group --> encoding can be 0 or 1 */ + fs_fun[group_index + 1] = fs_fun[group_index]; + bs_dc._bits |= dc_mask; + } + /* set don't care */ + set_dc = true; + group_index += 2; + set_index = 0; + fs_fun[group_index] = val; + dc_mask <<= next_group; + } + /* gather encoding */ + if ( val != fs_fun[group_index] ) + { + bs._bits |= UINT64_C( 1 ) << ( j + offset ); + fs_fun[group_index + 1] = val; + set_dc = false; // two cofactors are present + } + cof >>= shift; + ++set_index; + } + offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F; + } + + if ( set_dc ) + { + /* only one cofactor can be found in the group --> encoding can be 0 or 1 */ + fs_fun[group_index + 1] = fs_fun[group_index]; + bs_dc._bits |= dc_mask; + } + + /* create composition function */ + for ( uint32_t i = 0; i < 2 * num_groups; ++i ) + { + composition._bits |= fs_fun[i] << ( i * shift ); + } + + /* minimize support BS */ + LTT care; + bs_support_size = 0; + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; + care._bits = masks[num_vars - best_free_set] & ~bs_dc._bits; + for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) + { + if ( !has_var6( bs, care, i ) ) + { + adjust_truth_table_on_dc( bs, care, i ); + continue; + } + + if ( bs_support_size < i ) + { + kitty::swap_inplace( bs, bs_support_size, i ); + } + + bs_support[bs_support_size] = i; + ++bs_support_size; + } + + /* assign functions */ + dec_funcs[0] = bs._bits; + dec_funcs[1] = composition._bits; + + /* print functions */ + if ( verbose ) + { + LTT f; + f._bits = dec_funcs[0]; + std::cout << "BS function : "; + kitty::print_hex( f ); + std::cout << "\n"; + f._bits = dec_funcs[1]; + std::cout << "Composition function: "; + kitty::print_hex( f ); + std::cout << "\n"; + } + } + + template + void local_extend_to( TT_type& tt, uint32_t real_num_vars ) + { + if ( real_num_vars < 6 ) + { + auto mask = *tt.begin(); + + for ( auto i = real_num_vars; i < num_vars; ++i ) + { + mask |= ( mask << ( 1 << i ) ); + } + + std::fill( tt.begin(), tt.end(), mask ); + } + else + { + uint32_t num_blocks = ( 1u << ( real_num_vars - 6 ) ); + auto it = tt.begin(); + while ( it != tt.end() ) + { + it = std::copy( tt.cbegin(), tt.cbegin() + num_blocks, it ); + } + } + } + + inline void reposition_late_arriving_variables( unsigned delay_profile, uint32_t late_arriving ) + { + uint32_t k = 0; + for ( uint32_t i = 0; i < late_arriving; ++i ) + { + while ( ( ( delay_profile >> k ) & 1 ) == 0 ) + ++k; + + if ( permutations[i] == k ) + { + ++k; + continue; + } + + std::swap( permutations[i], permutations[k] ); + swap_inplace_local( best_tt, i, k ); + ++k; + } + } + + void swap_inplace_local( STT& tt, uint8_t var_index1, uint8_t var_index2 ) + { + if ( var_index1 == var_index2 ) + { + return; + } + + if ( var_index1 > var_index2 ) + { + std::swap( var_index1, var_index2 ); + } + + assert( num_vars > 6 ); + const uint32_t num_blocks = 1 << ( num_vars - 6 ); + + if ( var_index2 <= 5 ) + { + const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + std::transform( std::begin( tt._bits ), std::begin( tt._bits ) + num_blocks, std::begin( tt._bits ), + [shift, &pmask]( uint64_t word ) { + return ( word & pmask[0] ) | ( ( word & pmask[1] ) << shift ) | ( ( word & pmask[2] ) >> shift ); + } ); + } + else if ( var_index1 <= 5 ) /* in this case, var_index2 > 5 */ + { + const auto step = 1 << ( var_index2 - 6 ); + const auto shift = 1 << var_index1; + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = decltype( step ){ 0 }; i < step; ++i ) + { + const auto low_to_high = ( *( it + i ) & kitty::detail::projections[var_index1] ) >> shift; + const auto high_to_low = ( *( it + i + step ) << shift ) & kitty::detail::projections[var_index1]; + *( it + i ) = ( *( it + i ) & ~kitty::detail::projections[var_index1] ) | high_to_low; + *( it + i + step ) = ( *( it + i + step ) & kitty::detail::projections[var_index1] ) | low_to_high; + } + it += 2 * step; + } + } + else + { + const auto step1 = 1 << ( var_index1 - 6 ); + const auto step2 = 1 << ( var_index2 - 6 ); + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = 0; i < step2; i += 2 * step1 ) + { + for ( auto j = 0; j < step1; ++j ) + { + std::swap( *( it + i + j + step1 ), *( it + i + j + step2 ) ); + } + } + it += 2 * step2; + } + } + } + + inline bool has_var6( const LTT& tt, const LTT& care, uint8_t var_index ) + { + if ( ( ( ( tt._bits >> ( uint64_t( 1 ) << var_index ) ) ^ tt._bits ) & kitty::detail::projections_neg[var_index] & ( care._bits >> ( uint64_t( 1 ) << var_index ) ) & care._bits ) != 0 ) + { + return true; + } + + return false; + } + + void adjust_truth_table_on_dc( LTT& tt, LTT& care, uint32_t var_index ) + { + uint64_t new_bits = tt._bits & care._bits; + tt._bits = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) | + ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] ); + care._bits = ( care._bits | ( care._bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index]; + care._bits = care._bits | ( care._bits << ( uint64_t( 1 ) << var_index ) ); + } + + /* Decomposition format for ABC + * + * The record is an array of unsigned chars where: + * - the first unsigned char entry stores the number of unsigned chars in the record + * - the second entry stores the number of LUTs + * After this, several sub-records follow, each representing one LUT as follows: + * - an unsigned char entry listing the number of fanins + * - a list of fanins, from the LSB to the MSB of the truth table. The N inputs of the original function + * have indexes from 0 to N-1, followed by the internal signals in a topological order + * - the LUT truth table occupying 2^(M-3) bytes, where M is the fanin count of the LUT, from the LSB to the MSB. + * A 2-input LUT, which takes 4 bits, should be stretched to occupy 8 bits (one unsigned char) + * A 0- or 1-input LUT can be represented similarly but it is not expected that such LUTs will be represented + */ + void get_decomposition_abc( unsigned char* decompArray ) + { + unsigned char* pArray = decompArray; + unsigned char bytes = 2; + + /* write number of LUTs */ + pArray++; + *pArray = 2; + pArray++; + + /* write BS LUT */ + /* write fanin size */ + *pArray = bs_support_size; + pArray++; + ++bytes; + + /* write support */ + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + *pArray = (unsigned char)permutations[bs_support[i] + best_free_set]; + pArray++; + ++bytes; + } + + /* write truth table */ + uint32_t tt_num_bytes = ( bs_support_size <= 3 ) ? 1 : ( 1 << ( bs_support_size - 3 ) ); + for ( uint32_t i = 0; i < tt_num_bytes; ++i ) + { + *pArray = (unsigned char)( ( dec_funcs[0] >> ( 8 * i ) ) & 0xFF ); + pArray++; + ++bytes; + } + + /* write top LUT */ + /* write fanin size */ + uint32_t support_size = best_free_set + 1 + num_shared_vars; + *pArray = support_size; + pArray++; + ++bytes; + + /* write support */ + for ( uint32_t i = 0; i < best_free_set; ++i ) + { + *pArray = (unsigned char)permutations[i]; + pArray++; + ++bytes; + } + + *pArray = (unsigned char)num_vars; + pArray++; + ++bytes; + + for ( uint32_t i = 0; i < num_shared_vars; ++i ) + { + *pArray = (unsigned char)permutations[num_vars - num_shared_vars + i]; + pArray++; + ++bytes; + } + + /* write truth table */ + tt_num_bytes = ( support_size <= 3 ) ? 1 : ( 1 << ( support_size - 3 ) ); + for ( uint32_t i = 0; i < tt_num_bytes; ++i ) + { + *pArray = (unsigned char)( ( dec_funcs[1] >> ( 8 * i ) ) & 0xFF ); + pArray++; + ++bytes; + } + + /* write numBytes */ + *decompArray = bytes; + } + + bool verify_impl() + { + /* create PIs */ + STT pis[max_num_vars]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + kitty::create_nth_var( pis[i], permutations[i] ); + } + + /* BS function patterns */ + STT bsi[6]; + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + bsi[i] = pis[best_free_set + bs_support[i]]; + } + + /* compute first function */ + STT bsf_sim; + for ( uint32_t i = 0u; i < ( 1 << num_vars ); ++i ) + { + uint32_t pattern = 0u; + for ( auto j = 0; j < bs_support_size; ++j ) + { + pattern |= get_bit( bsi[j], i ) << j; + } + if ( ( dec_funcs[0] >> pattern ) & 1 ) + { + set_bit( bsf_sim, i ); + } + } + + /* compute first function */ + STT top_sim; + for ( uint32_t i = 0u; i < ( 1 << num_vars ); ++i ) + { + uint32_t pattern = 0u; + for ( auto j = 0; j < best_free_set; ++j ) + { + pattern |= get_bit( pis[j], i ) << j; + } + pattern |= get_bit( bsf_sim, i ) << best_free_set; + + /* shared variables */ + for ( auto j = 0u; j < num_shared_vars; ++j ) + { + pattern |= get_bit( pis[num_vars - num_shared_vars + j], i ) << ( best_free_set + 1 + j ); + } + + if ( ( dec_funcs[1] >> pattern ) & 1 ) + { + set_bit( top_sim, i ); + } + } + + for ( uint32_t i = 0; i < ( 1 << ( num_vars - 6 ) ); ++i ) + { + if ( top_sim._bits[i] != start_tt._bits[i] ) + { + /* convert to dynamic_truth_table */ + // report_tt( bsf_sim ); + std::cout << "Found incorrect decomposition\n"; + report_tt( top_sim ); + std::cout << " instead_of\n"; + report_tt( start_tt ); + return false; + } + } + + return true; + } + + uint32_t get_bit( const STT& tt, uint64_t index ) + { + return ( tt._bits[index >> 6] >> ( index & 0x3f ) ) & 0x1; + } + + void set_bit( STT& tt, uint64_t index ) + { + tt._bits[index >> 6] |= uint64_t( 1 ) << ( index & 0x3f ); + } + + void report_tt( STT const& stt ) + { + kitty::dynamic_truth_table tt( num_vars ); + + std::copy( std::begin( stt._bits ), std::begin( stt._bits ) + ( 1 << ( num_vars - 6 ) ), std::begin( tt ) ); + kitty::print_hex( tt ); + std::cout << "\n"; + } + +private: + uint32_t best_multiplicity{ UINT32_MAX }; + uint32_t best_free_set{ UINT32_MAX }; + uint32_t bs_support_size{ UINT32_MAX }; + uint32_t num_shared_vars{ 0 }; + STT best_tt; + STT start_tt; + uint64_t dec_funcs[2]; + uint32_t bs_support[6]; + + uint32_t const num_vars; + bool const multiple_ss; + bool const verify; + std::array permutations; +}; + +} // namespace acd + +ABC_NAMESPACE_CXX_HEADER_END + +#endif // _ACD66_H_ \ No newline at end of file diff --git a/src/map/if/acd/acdXX.hpp b/src/map/if/acd/acdXX.hpp new file mode 100644 index 000000000..e43404ea9 --- /dev/null +++ b/src/map/if/acd/acdXX.hpp @@ -0,0 +1,1258 @@ +/**C++File************************************************************** + + FileName [acd66.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Ashenhurst-Curtis decomposition.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alessandro Tempia Calvino] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - Apr 10, 2024.] + +***********************************************************************/ +/*! + \file acdXX.hpp + \brief Ashenhurst-Curtis decomposition for "XX" cascade + + \author Alessandro Tempia Calvino +*/ + +#ifndef _ACDXX_H_ +#define _ACDXX_H_ +#pragma once + +#include +#include +#include +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_constructors.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_operations.hpp" +#include "kitty_operators.hpp" +#include "kitty_static_tt.hpp" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace acd +{ + +struct acdXX_params +{ + /* Nymber of inputs of the LUT */ + uint32_t lut_size{ 6 }; + + /* Maximum number of variables in the shared set */ + uint32_t max_shared_vars{ 4 }; + + /* Run verification */ + bool verify{ false }; +}; + +class acdXX_impl +{ +private: + static constexpr uint32_t max_num_vars = 11; + using STT = kitty::static_truth_table; + using LTT = kitty::static_truth_table<6>; + +public: + explicit acdXX_impl( uint32_t const num_vars, acdXX_params const& ps = {} ) + : num_vars( num_vars ), ps( ps ) + { + std::iota( permutations.begin(), permutations.end(), 0 ); + } + + /*! \brief Runs ACD XX */ + bool run( word* ptt ) + { + assert( num_vars > 4 ); + + /* truth table is too large for the settings */ + if ( num_vars > max_num_vars || num_vars >= 2 * ps.lut_size ) + { + return false; + } + + /* saturate the maximum number of shared variables */ + ps.max_shared_vars = std::min( ps.max_shared_vars, ps.lut_size - 2 ); + + /* convert to static TT */ + init_truth_table( ptt ); + + /* run ACD trying different bound sets and free sets */ + return find_decomposition(); + } + + /*! \brief Runs ACD XX */ + int run( word* ptt, unsigned delay_profile ) + { + assert( num_vars > 4 ); + + /* truth table is too large for the settings */ + if ( num_vars > max_num_vars || num_vars >= 2 * ps.lut_size ) + { + return 0; + } + + uint32_t late_arriving = __builtin_popcount( delay_profile ); + + /* too many late arriving variables */ + if ( late_arriving >= ps.lut_size ) + return 0; + + /* saturate the maximum number of shared variables */ + ps.max_shared_vars = std::min( ps.max_shared_vars, ps.lut_size - 2 ); + + /* convert to static TT */ + init_truth_table( ptt ); + best_tt = start_tt; + + /* permute late arriving variables to be the least significant */ + reposition_late_arriving_variables( delay_profile, late_arriving ); + + /* run ACD trying different bound sets and free sets */ + return find_decomposition_offset( late_arriving ) ? ( delay_profile == 0 ? 2 : 1 ) : 0; + } + + int compute_decomposition() + { + if ( best_multiplicity == UINT32_MAX ) + return -1; + + compute_decomposition_impl(); + + if ( ps.verify && !verify_impl() ) + { + return 1; + } + + return 0; + } + + uint32_t get_num_edges() + { + if ( bs_support_size == UINT32_MAX ) + { + return num_vars + 1 + num_shared_vars; + } + + /* real value after support minimization */ + return bs_support_size + best_free_set + 1 + num_shared_vars; + } + + /* contains a 1 for FS variables */ + unsigned get_profile() + { + unsigned profile = 0; + + if ( best_multiplicity == UINT32_MAX ) + return -1; + + if ( bs_support_size == UINT32_MAX ) + { + for ( uint32_t i = 0; i < best_free_set; ++i ) + { + profile |= 1 << permutations[i]; + } + } + else + { + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + profile |= 1 << permutations[bs_support[i] + best_free_set]; + } + profile = ~profile & ( ( 1u << num_vars ) - 1 ); + } + + return profile; + } + + void get_decomposition( unsigned char* decompArray ) + { + if ( bs_support_size == UINT32_MAX ) + return; + + get_decomposition_abc( decompArray ); + } + +private: + bool find_decomposition() + { + best_multiplicity = UINT32_MAX; + best_free_set = UINT32_MAX; + + /* use multiple shared set variables */ + if ( ps.max_shared_vars > 1 ) + { + return find_decomposition_bs_multi_ss( num_vars - ps.lut_size ); + } + + uint32_t max_free_set = num_vars == ( 2 * ps.lut_size - 1 ) ? ps.lut_size - 1 : ps.lut_size - 1 - ps.max_shared_vars; + + /* find ACD "XX" for different number of variables in the free set */ + for ( uint32_t i = num_vars - ps.lut_size; i <= max_free_set; ++i ) + { + if ( find_decomposition_bs( i ) ) + return true; + } + + best_multiplicity = UINT32_MAX; + return false; + } + + bool find_decomposition_offset( uint32_t offset ) + { + best_multiplicity = UINT32_MAX; + best_free_set = UINT32_MAX; + + /* use multiple shared set variables */ + if ( ps.max_shared_vars > 1 ) + { + return find_decomposition_bs_offset_multi_ss( std::max( num_vars - ps.lut_size, offset ), offset ); + } + + uint32_t max_free_set = ( num_vars == ( 2 * ps.lut_size - 1 ) || ( offset == ps.lut_size - 1 ) ) ? ps.lut_size - 1 : ps.lut_size - 1 - ps.max_shared_vars; + + /* find ACD "66" for different number of variables in the free set */ + for ( uint32_t i = std::max( num_vars - 6, offset ); i <= max_free_set; ++i ) + { + if ( find_decomposition_bs_offset( i, offset ) ) + return true; + } + + best_multiplicity = UINT32_MAX; + return false; + } + + void init_truth_table( word* ptt ) + { + uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) ); + + for ( uint32_t i = 0; i < num_blocks; ++i ) + { + start_tt._bits[i] = ptt[i]; + } + + local_extend_to( start_tt, num_vars ); + } + + uint32_t column_multiplicity( STT const& tt, uint32_t const free_set_size ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const limit = ( ps.max_shared_vars == 0 || free_set_size == ( ps.lut_size - 1 ) ) ? 2 : 4; + uint32_t const inner_loop_max = ( num_vars < 6 ? ( 1 << num_vars ) : 64 ) >> free_set_size; + uint32_t cofactors[4]; + uint32_t size = 0; + + /* extract iset functions */ + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < inner_loop_max; ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t k; + for ( k = 0; k < size; ++k ) + { + if ( fs_fn == cofactors[k] ) + break; + } + if ( k == limit ) + return 5; + if ( k == size ) + cofactors[size++] = fs_fn; + sub >>= shift; + } + } + + return size; + } + + uint32_t column_multiplicity2( STT const& tt, uint32_t const free_set_size, uint32_t const limit ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const inner_loop_max = ( num_vars < 6 ? ( 1 << num_vars ) : 64 ) >> free_set_size; + uint32_t cofactors[32]; + uint32_t size = 0; + + /* extract iset functions */ + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < inner_loop_max; ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t k; + for ( k = 0; k < size; ++k ) + { + if ( fs_fn == cofactors[k] ) + break; + } + if ( k == limit ) + return 64; + if ( k == size ) + cofactors[size++] = fs_fn; + sub >>= shift; + } + } + + return size; + } + + inline bool combinations_next( uint32_t k, uint32_t offset, uint32_t* pComb, uint32_t* pInvPerm, STT& tt ) + { + uint32_t i; + + for ( i = k - 1; pComb[i] == num_vars - k + i; --i ) + { + if ( i == offset ) + return false; + } + + /* move vars */ + uint32_t var_old = pComb[i]; + uint32_t pos_new = pInvPerm[var_old + 1]; + std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); + std::swap( pComb[i], pComb[pos_new] ); + swap_inplace_local( tt, i, pos_new ); + + for ( uint32_t j = i + 1; j < k; j++ ) + { + var_old = pComb[j]; + pos_new = pInvPerm[pComb[j - 1] + 1]; + std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); + std::swap( pComb[j], pComb[pos_new] ); + swap_inplace_local( tt, j, pos_new ); + } + + return true; + } + + inline bool combinations_next_simple( uint32_t k, uint32_t* pComb, uint32_t* pInvPerm, uint32_t size ) + { + uint32_t i; + + for ( i = k - 1; pComb[i] == size - k + i; --i ) + { + if ( i == 0 ) + return false; + } + + /* move vars */ + uint32_t var_old = pComb[i]; + uint32_t pos_new = pInvPerm[var_old + 1]; + std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] ); + std::swap( pComb[i], pComb[pos_new] ); + + for ( uint32_t j = i + 1; j < k; j++ ) + { + var_old = pComb[j]; + pos_new = pInvPerm[pComb[j - 1] + 1]; + std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] ); + std::swap( pComb[j], pComb[pos_new] ); + } + + return true; + } + + bool find_decomposition_bs( uint32_t free_set_size ) + { + STT tt = start_tt; + + /* works up to 11 input truth tables */ + assert( num_vars <= 11 ); + + /* init combinations */ + uint32_t pComb[11], pInvPerm[11]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + best_free_set = free_set_size; + do + { + uint32_t cost = column_multiplicity( tt, free_set_size ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + return true; + } + else if ( ps.max_shared_vars > 0 && cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set( tt ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, res, num_vars - 1 ); + std::swap( permutations[res], permutations[num_vars - 1] ); + num_shared_vars = 1; + return true; + } + } + } while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) ); + + return false; + } + + bool find_decomposition_bs_offset( uint32_t free_set_size, uint32_t offset ) + { + STT tt = best_tt; + best_free_set = free_set_size; + + /* special case */ + if ( free_set_size == offset ) + { + uint32_t cost = column_multiplicity( tt, free_set_size ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + return true; + } + else if ( ps.max_shared_vars > 0 && cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set( tt ); + + if ( res >= 0 ) + { + best_tt = tt; + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, res, num_vars - 1 ); + std::swap( permutations[res], permutations[num_vars - 1] ); + num_shared_vars = 1; + return true; + } + } + return false; + } + + /* init combinations */ + uint32_t pComb[11], pInvPerm[11]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + do + { + uint32_t cost = column_multiplicity( tt, free_set_size ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + return true; + } + else if ( ps.max_shared_vars > 0 && cost <= 4 && free_set_size < 5 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set( tt ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + /* move shared variable as the most significative one */ + swap_inplace_local( best_tt, res, num_vars - 1 ); + std::swap( permutations[res], permutations[num_vars - 1] ); + num_shared_vars = 1; + return true; + } + } + } while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + + return false; + } + + bool find_decomposition_bs_multi_ss( uint32_t free_set_size ) + { + STT tt = start_tt; + + /* init combinations */ + uint32_t pComb[11], pInvPerm[11], shared_set[4]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + uint32_t limit = std::min( 1 << ( ps.lut_size - free_set_size ), 1 << ( ps.max_shared_vars + 1 ) ); + + /* enumerate combinations */ + best_free_set = free_set_size; + do + { + uint32_t cost = column_multiplicity2( tt, free_set_size, limit ); + if ( cost <= 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + return true; + } + + uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2 + : cost <= 16 ? 3 + : cost <= 32 ? 4 + : 5; + if ( ss_vars_needed + free_set_size < ps.lut_size ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set_multi( tt, ss_vars_needed, shared_set ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pComb[i]; + } + /* move shared variables as the most significative ones */ + for ( int32_t i = res - 1; i >= 0; --i ) + { + swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i ); + std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] ); + } + num_shared_vars = res; + return true; + } + } + } while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) ); + + best_multiplicity = UINT32_MAX; + return false; + } + + bool find_decomposition_bs_offset_multi_ss( uint32_t free_set_size, uint32_t offset ) + { + STT tt = best_tt; + + /* works up to 11 input truth tables */ + assert( num_vars <= 11 ); + best_free_set = free_set_size; + uint32_t shared_set[4]; + + uint32_t limit = std::min( 1 << ( ps.lut_size - free_set_size ), 1 << ( ps.max_shared_vars + 1 ) ); + + /* special case */ + if ( free_set_size == offset ) + { + uint32_t cost = column_multiplicity2( tt, free_set_size, limit ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + return true; + } + + uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2 + : cost <= 16 ? 3 + : cost <= 32 ? 4 + : 5; + + if ( ss_vars_needed + free_set_size < 6 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set_multi( tt, ss_vars_needed, shared_set ); + + if ( res >= 0 ) + { + best_tt = tt; + /* move shared variables as the most significative ones */ + for ( int32_t i = res - 1; i >= 0; --i ) + { + swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i ); + std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] ); + } + num_shared_vars = res; + return true; + } + } + + best_multiplicity = UINT32_MAX; + return false; + } + + /* init combinations */ + uint32_t pComb[11], pInvPerm[11]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + /* enumerate combinations */ + do + { + uint32_t cost = column_multiplicity2( tt, free_set_size, limit ); + if ( cost == 2 ) + { + best_tt = tt; + best_multiplicity = cost; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + return true; + } + + uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2 + : cost <= 16 ? 3 + : cost <= 32 ? 4 + : 5; + + if ( ss_vars_needed + free_set_size < 6 ) + { + /* look for a shared variable */ + best_multiplicity = cost; + int res = check_shared_set_multi( tt, ss_vars_needed, shared_set ); + + if ( res >= 0 ) + { + best_tt = tt; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + pInvPerm[i] = permutations[pComb[i]]; + } + for ( uint32_t i = 0; i < num_vars; ++i ) + { + permutations[i] = pInvPerm[i]; + } + /* move shared variables as the most significative ones */ + for ( int32_t i = res - 1; i >= 0; --i ) + { + swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i ); + std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] ); + } + num_shared_vars = res; + return true; + } + } + } while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) ); + + best_multiplicity = UINT32_MAX; + return false; + } + + bool check_shared_var( STT const& tt, uint32_t free_set_size, uint32_t shared_var ) + { + assert( free_set_size <= 5 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const inner_loop_max = ( num_vars < 6 ? ( 1 << num_vars ) : 64 ) >> free_set_size; + uint32_t cofactors[2][4]; + uint32_t size[2] = { 0, 0 }; + uint32_t shared_var_shift = shared_var - free_set_size; + + /* extract iset functions */ + uint32_t iteration_counter = 0; + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < inner_loop_max; ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t p = ( iteration_counter >> shared_var_shift ) & 1; + uint32_t k; + for ( k = 0; k < size[p]; ++k ) + { + if ( fs_fn == cofactors[p][k] ) + break; + } + if ( k == 2 ) + return false; + if ( k == size[p] ) + cofactors[p][size[p]++] = fs_fn; + sub >>= shift; + ++iteration_counter; + } + } + + return true; + } + + inline int check_shared_set( STT const& tt ) + { + /* find one shared set variable */ + for ( uint32_t i = best_free_set; i < num_vars; ++i ) + { + /* check the multiplicity of cofactors */ + if ( check_shared_var( tt, best_free_set, i ) ) + { + return i; + } + } + + return -1; + } + + bool check_shared_var_combined( STT const& tt, uint32_t free_set_size, uint32_t shared_vars[6], uint32_t num_shared_vars ) + { + assert( free_set_size <= 5 ); + assert( num_shared_vars <= 4 ); + + uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << free_set_size; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const inner_loop_max = ( num_vars < 6 ? ( 1 << num_vars ) : 64 ) >> free_set_size; + uint32_t cofactors[16][2]; + uint32_t size[16] = { 0 }; + + /* extract iset functions */ + uint32_t iteration_counter = 0; + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t sub = tt._bits[i]; + for ( auto j = 0; j < inner_loop_max; ++j ) + { + uint32_t fs_fn = static_cast( sub & mask ); + uint32_t p = 0; + for ( uint32_t k = 0; k < num_shared_vars; ++k ) + { + p |= ( ( iteration_counter >> shared_vars[k] ) & 1 ) << k; + } + + uint32_t k; + for ( k = 0; k < size[p]; ++k ) + { + if ( fs_fn == cofactors[p][k] ) + break; + } + if ( k == 2 ) + return false; + if ( k == size[p] ) + cofactors[p][size[p]++] = fs_fn; + sub >>= shift; + ++iteration_counter; + } + } + + return true; + } + + inline int check_shared_set_multi( STT const& tt, uint32_t target_num_ss, uint32_t* res_shared ) + { + /* init combinations */ + uint32_t pComb[6], pInvPerm[6]; + uint32_t max_shared_vars = std::min( ps.lut_size - best_free_set - 1, ps.max_shared_vars ); + + /* search for a feasible shared set */ + for ( uint32_t i = target_num_ss; i <= max_shared_vars; ++i ) + { + for ( uint32_t i = 0; i < 6; ++i ) + { + pComb[i] = pInvPerm[i] = i; + } + + do + { + /* check for combined shared set */ + if ( check_shared_var_combined( tt, best_free_set, pComb, i ) ) + { + for ( uint32_t j = 0; j < i; ++j ) + { + res_shared[j] = pComb[j]; + } + /* sort vars */ + std::sort( res_shared, res_shared + i ); + return i; + } + } while ( combinations_next_simple( i, pComb, pInvPerm, num_vars - best_free_set ) ); + } + + return -1; + } + + void compute_decomposition_impl( bool verbose = false ) + { + /* construct isets involved in multiplicity */ + LTT composition; + LTT bs; + LTT bs_dc; + + /* construct isets */ + uint32_t offset = 0; + uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1; + uint64_t const shift = UINT64_C( 1 ) << best_free_set; + uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1; + uint32_t const num_groups = 1 << num_shared_vars; + uint32_t const next_group = 1 << ( num_vars - best_free_set - num_shared_vars ); + uint32_t const inner_loop_max = ( num_vars < 6 ? ( 1 << num_vars ) : 64 ) >> best_free_set; + + uint64_t fs_fun[32] = { 0 }; + uint64_t dc_mask = ( ( UINT64_C( 1 ) << next_group ) - 1 ); + + uint32_t group_index = 0; + uint32_t set_index = 0; + fs_fun[0] = best_tt._bits[0] & mask; + bool set_dc = true; + for ( auto i = 0u; i < num_blocks; ++i ) + { + uint64_t cof = best_tt._bits[i]; + for ( auto j = 0; j < inner_loop_max; ++j ) + { + uint64_t val = cof & mask; + /* move to next block */ + if ( set_index == next_group ) + { + if ( set_dc ) + { + /* only one cofactor can be found in the group --> encoding can be 0 or 1 */ + fs_fun[group_index + 1] = fs_fun[group_index]; + bs_dc._bits |= dc_mask; + } + /* set don't care */ + set_dc = true; + group_index += 2; + set_index = 0; + fs_fun[group_index] = val; + dc_mask <<= next_group; + } + /* gather encoding */ + if ( val != fs_fun[group_index] ) + { + bs._bits |= UINT64_C( 1 ) << ( j + offset ); + fs_fun[group_index + 1] = val; + set_dc = false; // two cofactors are present + } + cof >>= shift; + ++set_index; + } + offset = ( offset + inner_loop_max ) & 0x3F; + } + + if ( set_dc ) + { + /* only one cofactor can be found in the group --> encoding can be 0 or 1 */ + fs_fun[group_index + 1] = fs_fun[group_index]; + bs_dc._bits |= dc_mask; + } + + /* create composition function */ + for ( uint32_t i = 0; i < 2 * num_groups; ++i ) + { + composition._bits |= fs_fun[i] << ( i * shift ); + } + + /* minimize support BS */ + LTT care; + bs_support_size = 0; + uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX }; + care._bits = masks[num_vars - best_free_set] & ~bs_dc._bits; + for ( uint32_t i = 0; i < num_vars - best_free_set; ++i ) + { + if ( !has_var6( bs, care, i ) ) + { + adjust_truth_table_on_dc( bs, care, i ); + continue; + } + + if ( bs_support_size < i ) + { + kitty::swap_inplace( bs, bs_support_size, i ); + } + + bs_support[bs_support_size] = i; + ++bs_support_size; + } + + /* assign functions */ + dec_funcs[0] = bs._bits; + dec_funcs[1] = composition._bits; + + /* print functions */ + if ( verbose ) + { + LTT f; + f._bits = dec_funcs[0]; + std::cout << "BS function : "; + kitty::print_hex( f ); + std::cout << "\n"; + f._bits = dec_funcs[1]; + std::cout << "Composition function: "; + kitty::print_hex( f ); + std::cout << "\n"; + } + } + + template + void local_extend_to( TT_type& tt, uint32_t real_num_vars ) + { + if ( real_num_vars < 6 ) + { + auto mask = *tt.begin(); + + for ( auto i = real_num_vars; i < num_vars; ++i ) + { + mask |= ( mask << ( 1 << i ) ); + } + + std::fill( tt.begin(), tt.end(), mask ); + } + else + { + uint32_t num_blocks = ( 1u << ( real_num_vars - 6 ) ); + auto it = tt.begin(); + while ( it != tt.end() ) + { + it = std::copy( tt.cbegin(), tt.cbegin() + num_blocks, it ); + } + } + } + + inline void reposition_late_arriving_variables( unsigned delay_profile, uint32_t late_arriving ) + { + uint32_t k = 0; + for ( uint32_t i = 0; i < late_arriving; ++i ) + { + while ( ( ( delay_profile >> k ) & 1 ) == 0 ) + ++k; + + if ( permutations[i] == k ) + { + ++k; + continue; + } + + std::swap( permutations[i], permutations[k] ); + swap_inplace_local( best_tt, i, k ); + ++k; + } + } + + void swap_inplace_local( STT& tt, uint8_t var_index1, uint8_t var_index2 ) + { + if ( var_index1 == var_index2 ) + { + return; + } + + if ( var_index1 > var_index2 ) + { + std::swap( var_index1, var_index2 ); + } + + const uint32_t num_blocks = num_vars <= 6 ? 1 : 1 << ( num_vars - 6 ); + + if ( num_vars <= 6 ) + { + const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + tt._bits[0] = ( tt._bits[0] & pmask[0] ) | ( ( tt._bits[0] & pmask[1] ) << shift ) | ( ( tt._bits[0] & pmask[2] ) >> shift ); + } + else if ( var_index2 <= 5 ) + { + const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + std::transform( std::begin( tt._bits ), std::begin( tt._bits ) + num_blocks, std::begin( tt._bits ), + [shift, &pmask]( uint64_t word ) { + return ( word & pmask[0] ) | ( ( word & pmask[1] ) << shift ) | ( ( word & pmask[2] ) >> shift ); + } ); + } + else if ( var_index1 <= 5 ) /* in this case, var_index2 > 5 */ + { + const auto step = 1 << ( var_index2 - 6 ); + const auto shift = 1 << var_index1; + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = decltype( step ){ 0 }; i < step; ++i ) + { + const auto low_to_high = ( *( it + i ) & kitty::detail::projections[var_index1] ) >> shift; + const auto high_to_low = ( *( it + i + step ) << shift ) & kitty::detail::projections[var_index1]; + *( it + i ) = ( *( it + i ) & ~kitty::detail::projections[var_index1] ) | high_to_low; + *( it + i + step ) = ( *( it + i + step ) & kitty::detail::projections[var_index1] ) | low_to_high; + } + it += 2 * step; + } + } + else + { + const auto step1 = 1 << ( var_index1 - 6 ); + const auto step2 = 1 << ( var_index2 - 6 ); + auto it = std::begin( tt._bits ); + while ( it != std::begin( tt._bits ) + num_blocks ) + { + for ( auto i = 0; i < step2; i += 2 * step1 ) + { + for ( auto j = 0; j < step1; ++j ) + { + std::swap( *( it + i + j + step1 ), *( it + i + j + step2 ) ); + } + } + it += 2 * step2; + } + } + } + + inline bool has_var6( const LTT& tt, const LTT& care, uint8_t var_index ) + { + if ( ( ( ( tt._bits >> ( uint64_t( 1 ) << var_index ) ) ^ tt._bits ) & kitty::detail::projections_neg[var_index] & ( care._bits >> ( uint64_t( 1 ) << var_index ) ) & care._bits ) != 0 ) + { + return true; + } + + return false; + } + + void adjust_truth_table_on_dc( LTT& tt, LTT& care, uint32_t var_index ) + { + uint64_t new_bits = tt._bits & care._bits; + tt._bits = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) | + ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] ); + care._bits = ( care._bits | ( care._bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index]; + care._bits = care._bits | ( care._bits << ( uint64_t( 1 ) << var_index ) ); + } + + /* Decomposition format for ABC + * + * The record is an array of unsigned chars where: + * - the first unsigned char entry stores the number of unsigned chars in the record + * - the second entry stores the number of LUTs + * After this, several sub-records follow, each representing one LUT as follows: + * - an unsigned char entry listing the number of fanins + * - a list of fanins, from the LSB to the MSB of the truth table. The N inputs of the original function + * have indexes from 0 to N-1, followed by the internal signals in a topological order + * - the LUT truth table occupying 2^(M-3) bytes, where M is the fanin count of the LUT, from the LSB to the MSB. + * A 2-input LUT, which takes 4 bits, should be stretched to occupy 8 bits (one unsigned char) + * A 0- or 1-input LUT can be represented similarly but it is not expected that such LUTs will be represented + */ + void get_decomposition_abc( unsigned char* decompArray ) + { + unsigned char* pArray = decompArray; + unsigned char bytes = 2; + + /* write number of LUTs */ + pArray++; + *pArray = 2; + pArray++; + + /* write BS LUT */ + /* write fanin size */ + *pArray = bs_support_size; + pArray++; + ++bytes; + + /* write support */ + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + *pArray = (unsigned char)permutations[bs_support[i] + best_free_set]; + pArray++; + ++bytes; + } + + /* write truth table */ + uint32_t tt_num_bytes = ( bs_support_size <= 3 ) ? 1 : ( 1 << ( bs_support_size - 3 ) ); + for ( uint32_t i = 0; i < tt_num_bytes; ++i ) + { + *pArray = (unsigned char)( ( dec_funcs[0] >> ( 8 * i ) ) & 0xFF ); + pArray++; + ++bytes; + } + + /* write top LUT */ + /* write fanin size */ + uint32_t support_size = best_free_set + 1 + num_shared_vars; + *pArray = support_size; + pArray++; + ++bytes; + + /* write support */ + for ( uint32_t i = 0; i < best_free_set; ++i ) + { + *pArray = (unsigned char)permutations[i]; + pArray++; + ++bytes; + } + + *pArray = (unsigned char)num_vars; + pArray++; + ++bytes; + + for ( uint32_t i = 0; i < num_shared_vars; ++i ) + { + *pArray = (unsigned char)permutations[num_vars - num_shared_vars + i]; + pArray++; + ++bytes; + } + + /* write truth table */ + tt_num_bytes = ( support_size <= 3 ) ? 1 : ( 1 << ( support_size - 3 ) ); + for ( uint32_t i = 0; i < tt_num_bytes; ++i ) + { + *pArray = (unsigned char)( ( dec_funcs[1] >> ( 8 * i ) ) & 0xFF ); + pArray++; + ++bytes; + } + + /* write numBytes */ + *decompArray = bytes; + } + + bool verify_impl() + { + /* create PIs */ + STT pis[max_num_vars]; + for ( uint32_t i = 0; i < num_vars; ++i ) + { + kitty::create_nth_var( pis[i], permutations[i] ); + } + + /* BS function patterns */ + STT bsi[6]; + for ( uint32_t i = 0; i < bs_support_size; ++i ) + { + bsi[i] = pis[best_free_set + bs_support[i]]; + } + + /* compute first function */ + STT bsf_sim; + for ( uint32_t i = 0u; i < ( 1 << num_vars ); ++i ) + { + uint32_t pattern = 0u; + for ( auto j = 0; j < bs_support_size; ++j ) + { + pattern |= get_bit( bsi[j], i ) << j; + } + if ( ( dec_funcs[0] >> pattern ) & 1 ) + { + set_bit( bsf_sim, i ); + } + } + + /* compute first function */ + STT top_sim; + for ( uint32_t i = 0u; i < ( 1 << num_vars ); ++i ) + { + uint32_t pattern = 0u; + for ( auto j = 0; j < best_free_set; ++j ) + { + pattern |= get_bit( pis[j], i ) << j; + } + pattern |= get_bit( bsf_sim, i ) << best_free_set; + + /* shared variables */ + for ( auto j = 0u; j < num_shared_vars; ++j ) + { + pattern |= get_bit( pis[num_vars - num_shared_vars + j], i ) << ( best_free_set + 1 + j ); + } + + if ( ( dec_funcs[1] >> pattern ) & 1 ) + { + set_bit( top_sim, i ); + } + } + + /* extend function */ + for ( uint32_t i = 0; i < ( 1 << ( num_vars > 6 ? num_vars - 6 : 1 ) ); ++i ) + { + if ( top_sim._bits[i] != start_tt._bits[i] ) + { + std::cout << "Found incorrect decomposition\n"; + report_tt( top_sim ); + std::cout << " instead_of\n"; + report_tt( start_tt ); + return false; + } + } + + return true; + } + + uint32_t get_bit( const STT& tt, uint64_t index ) + { + return ( tt._bits[index >> 6] >> ( index & 0x3f ) ) & 0x1; + } + + void set_bit( STT& tt, uint64_t index ) + { + tt._bits[index >> 6] |= uint64_t( 1 ) << ( index & 0x3f ); + } + + void report_tt( STT const& stt ) + { + kitty::dynamic_truth_table tt( num_vars ); + + std::copy( std::begin( stt._bits ), std::begin( stt._bits ) + ( 1 << ( num_vars > 6 ? num_vars - 6 : 0 ) ), std::begin( tt ) ); + kitty::print_hex( tt ); + std::cout << "\n"; + } + +private: + uint32_t best_multiplicity{ UINT32_MAX }; + uint32_t best_free_set{ UINT32_MAX }; + uint32_t bs_support_size{ UINT32_MAX }; + uint32_t num_shared_vars{ 0 }; + STT best_tt; + STT start_tt; + uint64_t dec_funcs[2]; + uint32_t bs_support[6]; + + uint32_t const num_vars; + acdXX_params ps; + std::array permutations; +}; + +} // namespace acd + +ABC_NAMESPACE_CXX_HEADER_END + +#endif // _ACDXX_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_algorithm.hpp b/src/map/if/acd/kitty_algorithm.hpp new file mode 100644 index 000000000..a8c71dc07 --- /dev/null +++ b/src/map/if/acd/kitty_algorithm.hpp @@ -0,0 +1,123 @@ +#ifndef _KITTY_ALGORITHM_H_ +#define _KITTY_ALGORITHM_H_ +#pragma once + +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_static_tt.hpp" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace kitty +{ + +/*! \brief Perform bitwise unary operation on truth table + + \param tt Truth table + \param op Unary operation that takes as input a word (`uint64_t`) and returns a word + + \return new constructed truth table of same type and dimensions + */ +template +TT unary_operation( const TT& tt, Fn&& op ) +{ + TT result = tt.construct(); + std::transform( tt.cbegin(), tt.cend(), result.begin(), op ); + result.mask_bits(); + return result; +} + +/*! \brief Perform bitwise binary operation on two truth tables + + The dimensions of `first` and `second` must match. This is ensured + at compile-time for static truth tables, but at run-time for dynamic + truth tables. + + \param first First truth table + \param second Second truth table + \param op Binary operation that takes as input two words (`uint64_t`) and returns a word + + \return new constructed truth table of same type and dimensions + */ +template +TT binary_operation( const TT& first, const TT& second, Fn&& op ) +{ + assert( first.num_vars() == second.num_vars() ); + + TT result = first.construct(); + std::transform( first.cbegin(), first.cend(), second.cbegin(), result.begin(), op ); + result.mask_bits(); + return result; +} + +/*! \brief Computes a predicate based on two truth tables + + The dimensions of `first` and `second` must match. This is ensured + at compile-time for static truth tables, but at run-time for dynamic + truth tables. + + \param first First truth table + \param second Second truth table + \param op Binary operation that takes as input two words (`uint64_t`) and returns a Boolean + + \return true or false based on the predicate + */ +template +bool binary_predicate( const TT& first, const TT& second, Fn&& op ) +{ + assert( first.num_vars() == second.num_vars() ); + + return std::equal( first.begin(), first.end(), second.begin(), op ); +} + +/*! \brief Assign computed values to bits + + The functor `op` computes bits which are assigned to the bits of the + truth table. + + \param tt Truth table + \param op Unary operation that takes no input and returns a word (`uint64_t`) +*/ +template +void assign_operation( TT& tt, Fn&& op ) +{ + std::generate( tt.begin(), tt.end(), op ); + tt.mask_bits(); +} + +/*! \brief Iterates through each block of a truth table + + The functor `op` is called for every block of the truth table. + + \param tt Truth table + \param op Unary operation that takes as input a word (`uint64_t`) and returns void +*/ +template +void for_each_block( const TT& tt, Fn&& op ) +{ + std::for_each( tt.cbegin(), tt.cend(), op ); +} + +/*! \brief Iterates through each block of a truth table in reverse + order + + The functor `op` is called for every block of the truth table in + reverse order. + + \param tt Truth table + \param op Unary operation that takes as input a word (`uint64_t`) and returns void +*/ +template +void for_each_block_reversed( const TT& tt, Fn&& op ) +{ + std::for_each( tt.crbegin(), tt.crend(), op ); +} + +} // namespace kitty + +ABC_NAMESPACE_CXX_HEADER_END + +#endif // _KITTY_ALGORITHM_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_constants.hpp b/src/map/if/acd/kitty_constants.hpp new file mode 100644 index 000000000..180180c42 --- /dev/null +++ b/src/map/if/acd/kitty_constants.hpp @@ -0,0 +1,96 @@ +#ifndef _KITTY_CONSTANTS_H_ +#define _KITTY_CONSTANTS_H_ +#pragma once + +#include +#include +#include // std::iota + +ABC_NAMESPACE_CXX_HEADER_START + +namespace kitty +{ + +namespace detail +{ + +static constexpr uint64_t projections[] = { + UINT64_C( 0xaaaaaaaaaaaaaaaa ), + UINT64_C( 0xcccccccccccccccc ), + UINT64_C( 0xf0f0f0f0f0f0f0f0 ), + UINT64_C( 0xff00ff00ff00ff00 ), + UINT64_C( 0xffff0000ffff0000 ), + UINT64_C( 0xffffffff00000000 ) }; + +static constexpr uint64_t projections_neg[] = { + UINT64_C( 0x5555555555555555 ), + UINT64_C( 0x3333333333333333 ), + UINT64_C( 0x0f0f0f0f0f0f0f0f ), + UINT64_C( 0x00ff00ff00ff00ff ), + UINT64_C( 0x0000ffff0000ffff ), + UINT64_C( 0x00000000ffffffff ) }; + +static constexpr uint64_t masks[] = { + UINT64_C( 0x0000000000000001 ), + UINT64_C( 0x0000000000000003 ), + UINT64_C( 0x000000000000000f ), + UINT64_C( 0x00000000000000ff ), + UINT64_C( 0x000000000000ffff ), + UINT64_C( 0x00000000ffffffff ), + UINT64_C( 0xffffffffffffffff ) }; + +static constexpr uint64_t permutation_masks[][3] = { + { UINT64_C( 0x9999999999999999 ), UINT64_C( 0x2222222222222222 ), UINT64_C( 0x4444444444444444 ) }, + { UINT64_C( 0xc3c3c3c3c3c3c3c3 ), UINT64_C( 0x0c0c0c0c0c0c0c0c ), UINT64_C( 0x3030303030303030 ) }, + { UINT64_C( 0xf00ff00ff00ff00f ), UINT64_C( 0x00f000f000f000f0 ), UINT64_C( 0x0f000f000f000f00 ) }, + { UINT64_C( 0xff0000ffff0000ff ), UINT64_C( 0x0000ff000000ff00 ), UINT64_C( 0x00ff000000ff0000 ) }, + { UINT64_C( 0xffff00000000ffff ), UINT64_C( 0x00000000ffff0000 ), UINT64_C( 0x0000ffff00000000 ) } }; + +static constexpr uint64_t ppermutation_masks[][6][3] = { + { { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x9999999999999999 ), UINT64_C( 0x2222222222222222 ), UINT64_C( 0x4444444444444444 ) }, + { UINT64_C( 0xa5a5a5a5a5a5a5a5 ), UINT64_C( 0x0a0a0a0a0a0a0a0a ), UINT64_C( 0x5050505050505050 ) }, + { UINT64_C( 0xaa55aa55aa55aa55 ), UINT64_C( 0x00aa00aa00aa00aa ), UINT64_C( 0x5500550055005500 ) }, + { UINT64_C( 0xaaaa5555aaaa5555 ), UINT64_C( 0x0000aaaa0000aaaa ), UINT64_C( 0x5555000055550000 ) }, + { UINT64_C( 0xaaaaaaaa55555555 ), UINT64_C( 0x00000000aaaaaaaa ), UINT64_C( 0x5555555500000000 ) } }, + { { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0xc3c3c3c3c3c3c3c3 ), UINT64_C( 0x0c0c0c0c0c0c0c0c ), UINT64_C( 0x3030303030303030 ) }, + { UINT64_C( 0xcc33cc33cc33cc33 ), UINT64_C( 0x00cc00cc00cc00cc ), UINT64_C( 0x3300330033003300 ) }, + { UINT64_C( 0xcccc3333cccc3333 ), UINT64_C( 0x0000cccc0000cccc ), UINT64_C( 0x3333000033330000 ) }, + { UINT64_C( 0xcccccccc33333333 ), UINT64_C( 0x00000000cccccccc ), UINT64_C( 0x3333333300000000 ) } }, + { { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0xf00ff00ff00ff00f ), UINT64_C( 0x00f000f000f000f0 ), UINT64_C( 0x0f000f000f000f00 ) }, + { UINT64_C( 0xf0f00f0ff0f00f0f ), UINT64_C( 0x0000f0f00000f0f0 ), UINT64_C( 0x0f0f00000f0f0000 ) }, + { UINT64_C( 0xf0f0f0f00f0f0f0f ), UINT64_C( 0x00000000f0f0f0f0 ), UINT64_C( 0x0f0f0f0f00000000 ) } }, + { { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0xff0000ffff0000ff ), UINT64_C( 0x0000ff000000ff00 ), UINT64_C( 0x00ff000000ff0000 ) }, + { UINT64_C( 0xff00ff0000ff00ff ), UINT64_C( 0x00000000ff00ff00 ), UINT64_C( 0x00ff00ff00000000 ) } }, + { { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) }, + { UINT64_C( 0xffff00000000ffff ), UINT64_C( 0x00000000ffff0000 ), UINT64_C( 0x0000ffff00000000 ) } } }; + +static constexpr int32_t hex_to_int[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; + +} // namespace detail + +} // namespace kitty + +ABC_NAMESPACE_CXX_HEADER_END + +#endif //_KITTY_CONSTANTS_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_constructors.hpp b/src/map/if/acd/kitty_constructors.hpp new file mode 100644 index 000000000..26ec6e483 --- /dev/null +++ b/src/map/if/acd/kitty_constructors.hpp @@ -0,0 +1,96 @@ +#ifndef _KITTY_CONSTRUCT_TT_H_ +#define _KITTY_CONSTRUCT_TT_H_ +#pragma once + +#include +#include +#include +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_static_tt.hpp" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace kitty +{ + +/*! \brief Creates truth table with number of variables + + If some truth table instance is given, one can create a truth table with the + same type by calling the `construct()` method on it. This function helps if + only the number of variables is known and the base type and uniforms the + creation of static and dynamic truth tables. Note, however, that for static + truth tables `num_vars` must be consistent to the number of variables in the + truth table type. + + \param num_vars Number of variables +*/ +template +inline TT create( unsigned num_vars ) +{ + (void)num_vars; + TT tt; + assert( tt.num_vars() == num_vars ); + return tt; +} + +/*! \cond PRIVATE */ +template<> +inline dynamic_truth_table create( unsigned num_vars ) +{ + return dynamic_truth_table( num_vars ); +} +/*! \endcond */ + +/*! \brief Constructs projections (single-variable functions) + + \param tt Truth table + \param var_index Index of the variable, must be smaller than the truth table's number of variables + \param complement If true, realize inverse projection +*/ +template +void create_nth_var( TT& tt, uint8_t var_index, bool complement = false ) +{ + if ( tt.num_vars() <= 6 ) + { + /* assign from precomputed table */ + tt._bits[0] = complement ? ~detail::projections[var_index] : detail::projections[var_index]; + + /* mask if truth table does not require all bits */ + tt.mask_bits(); + return; + } + + if ( var_index < 6 ) + { + std::fill( std::begin( tt._bits ), std::end( tt._bits ), complement ? ~detail::projections[var_index] : detail::projections[var_index] ); + } + else + { + const auto c = 1 << ( var_index - 6 ); + const auto zero = uint64_t( 0 ); + const auto one = ~zero; + auto block = uint64_t( 0u ); + + while ( block < tt.num_blocks() ) + { + for ( auto i = 0; i < c; ++i ) + { + tt._bits[block++] = complement ? one : zero; + } + for ( auto i = 0; i < c; ++i ) + { + tt._bits[block++] = complement ? zero : one; + } + } + } +} + +} // namespace kitty + +ABC_NAMESPACE_CXX_HEADER_END + +#endif // _KITTY_CONSTRUCT_TT_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_dynamic_tt.hpp b/src/map/if/acd/kitty_dynamic_tt.hpp new file mode 100644 index 000000000..2913b6674 --- /dev/null +++ b/src/map/if/acd/kitty_dynamic_tt.hpp @@ -0,0 +1,151 @@ +#ifndef _KITTY_DYNAMIC_TT_H_ +#define _KITTY_DYNAMIC_TT_H_ +#pragma once + +#include +#include +#include + +#include "kitty_constants.hpp" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace kitty +{ + +/*! Truth table in which number of variables is known at runtime. + */ +struct dynamic_truth_table +{ + /*! Standard constructor. + + The number of variables provided to the truth table can be + computed at runtime. However, once the truth table is constructed + its number of variables cannot change anymore. + + The constructor computes the number of blocks and resizes the + vector accordingly. + + \param num_vars Number of variables + */ + explicit dynamic_truth_table( uint32_t num_vars ) + : _bits( ( num_vars <= 6 ) ? 1u : ( 1u << ( num_vars - 6 ) ) ), + _num_vars( num_vars ) + { + } + + /*! Empty constructor. + + Creates an empty truth table. It has 0 variables, but no bits, i.e., it is + different from a truth table for the constant function. This constructor is + only used for convenience, if algorithms require the existence of default + constructable classes. + */ + dynamic_truth_table() : _num_vars( 0 ) {} + + /*! Constructs a new dynamic truth table instance with the same number of variables. */ + inline dynamic_truth_table construct() const + { + return dynamic_truth_table( _num_vars ); + } + + /*! Returns number of variables. + */ + inline uint32_t num_vars() const noexcept { return _num_vars; } + + /*! Returns number of blocks. + */ + inline uint32_t num_blocks() const noexcept { return _bits.size(); } + + /*! Returns number of bits. + */ + inline uint32_t num_bits() const noexcept { return uint64_t( 1 ) << _num_vars; } + + /*! \brief Begin iterator to bits. + */ + inline std::vector::iterator begin() noexcept { return _bits.begin(); } + + /*! \brief End iterator to bits. + */ + inline std::vector::iterator end() noexcept { return _bits.end(); } + + /*! \brief Begin iterator to bits. + */ + inline std::vector::const_iterator begin() const noexcept { return _bits.begin(); } + + /*! \brief End iterator to bits. + */ + inline std::vector::const_iterator end() const noexcept { return _bits.end(); } + + /*! \brief Reverse begin iterator to bits. + */ + inline std::vector::reverse_iterator rbegin() noexcept { return _bits.rbegin(); } + + /*! \brief Reverse end iterator to bits. + */ + inline std::vector::reverse_iterator rend() noexcept { return _bits.rend(); } + + /*! \brief Constant begin iterator to bits. + */ + inline std::vector::const_iterator cbegin() const noexcept { return _bits.cbegin(); } + + /*! \brief Constant end iterator to bits. + */ + inline std::vector::const_iterator cend() const noexcept { return _bits.cend(); } + + /*! \brief Constant reverse begin iterator to bits. + */ + inline std::vector::const_reverse_iterator crbegin() const noexcept { return _bits.crbegin(); } + + /*! \brief Constant teverse end iterator to bits. + */ + inline std::vector::const_reverse_iterator crend() const noexcept { return _bits.crend(); } + + /*! \brief Assign other truth table. + + This replaces the current truth table with another truth table. The truth + table type has to be complete. The vector of bits is resized accordingly. + + \param other Other truth table + */ + template + dynamic_truth_table& operator=( const TT& other ) + { + _bits.resize( other.num_blocks() ); + std::copy( other.begin(), other.end(), begin() ); + _num_vars = other.num_vars(); + + if ( _num_vars < 6 ) + { + mask_bits(); + } + + return *this; + } + + /*! Masks the number of valid truth table bits. + + If the truth table has less than 6 variables, it may not use all + the bits. This operation makes sure to zero out all non-valid + bits. + */ + inline void mask_bits() noexcept + { + if ( _num_vars < 6 ) + { + _bits[0u] &= detail::masks[_num_vars]; + } + } + + /*! \cond PRIVATE */ +public: /* fields */ + std::vector _bits; + uint32_t _num_vars; + /*! \endcond */ +}; + +} //namespace kitty + +ABC_NAMESPACE_CXX_HEADER_END + +#endif // _KITTY_DYNAMIC_TT_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_operations.hpp b/src/map/if/acd/kitty_operations.hpp new file mode 100644 index 000000000..e0292bc05 --- /dev/null +++ b/src/map/if/acd/kitty_operations.hpp @@ -0,0 +1,355 @@ +#ifndef _KITTY_OPERATIONS_TT_H_ +#define _KITTY_OPERATIONS_TT_H_ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "kitty_algorithm.hpp" +#include "kitty_constants.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_static_tt.hpp" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace kitty +{ + +/*! Inverts all bits in a truth table, based on a condition */ +template +inline TT unary_not_if( const TT& tt, bool cond ) +{ +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + const auto mask = -static_cast( cond ); +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + return unary_operation( tt, [mask]( uint64_t a ) + { return a ^ mask; } ); +} + +/*! \brief Inverts all bits in a truth table */ +template +inline TT unary_not( const TT& tt ) +{ + return unary_operation( tt, []( uint64_t a ) + { return ~a; } ); +} + +/*! \brief Bitwise AND of two truth tables */ +template + +inline TT binary_and( const TT& first, const TT& second ) +{ + return binary_operation( first, second, std::bit_and() ); +} + +/*! \brief Bitwise OR of two truth tables */ +template +inline TT binary_or( const TT& first, const TT& second ) +{ + return binary_operation( first, second, std::bit_or() ); +} + +/*! \brief Swaps two variables in a truth table + + The function swaps variable `var_index1` with `var_index2`. The + function will change `tt` in-place. If `tt` should not be changed, + one can use `swap` instead. + + \param tt Truth table + \param var_index1 First variable + \param var_index2 Second variable +*/ +template +void swap_inplace( TT& tt, uint8_t var_index1, uint8_t var_index2 ) +{ + if ( var_index1 == var_index2 ) + { + return; + } + + if ( var_index1 > var_index2 ) + { + std::swap( var_index1, var_index2 ); + } + + if ( tt.num_vars() <= 6 ) + { + const auto& pmask = detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + tt._bits[0] = ( tt._bits[0] & pmask[0] ) | ( ( tt._bits[0] & pmask[1] ) << shift ) | ( ( tt._bits[0] & pmask[2] ) >> shift ); + } + else if ( var_index2 <= 5 ) + { + const auto& pmask = detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + std::transform( std::begin( tt._bits ), std::end( tt._bits ), std::begin( tt._bits ), + [shift, &pmask]( uint64_t word ) + { + return ( word & pmask[0] ) | ( ( word & pmask[1] ) << shift ) | ( ( word & pmask[2] ) >> shift ); + } ); + } + else if ( var_index1 <= 5 ) /* in this case, var_index2 > 5 */ + { + const auto step = 1 << ( var_index2 - 6 ); + const auto shift = 1 << var_index1; + auto it = std::begin( tt._bits ); + while ( it != std::end( tt._bits ) ) + { + for ( auto i = decltype( step ){ 0 }; i < step; ++i ) + { + const auto low_to_high = ( *( it + i ) & detail::projections[var_index1] ) >> shift; + const auto high_to_low = ( *( it + i + step ) << shift ) & detail::projections[var_index1]; + *( it + i ) = ( *( it + i ) & ~detail::projections[var_index1] ) | high_to_low; + *( it + i + step ) = ( *( it + i + step ) & detail::projections[var_index1] ) | low_to_high; + } + it += 2 * step; + } + } + else + { + const auto step1 = 1 << ( var_index1 - 6 ); + const auto step2 = 1 << ( var_index2 - 6 ); + auto it = std::begin( tt._bits ); + while ( it != std::end( tt._bits ) ) + { + for ( auto i = 0; i < step2; i += 2 * step1 ) + { + for ( auto j = 0; j < step1; ++j ) + { + std::swap( *( it + i + j + step1 ), *( it + i + j + step2 ) ); + } + } + it += 2 * step2; + } + } +} + +template +inline void swap_inplace( static_truth_table& tt, uint8_t var_index1, uint8_t var_index2 ) +{ + if ( var_index1 == var_index2 ) + { + return; + } + + if ( var_index1 > var_index2 ) + { + std::swap( var_index1, var_index2 ); + } + + const auto& pmask = detail::ppermutation_masks[var_index1][var_index2]; + const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 ); + tt._bits = ( tt._bits & pmask[0] ) | ( ( tt._bits & pmask[1] ) << shift ) | ( ( tt._bits & pmask[2] ) >> shift ); +} + +/*! \brief Extends smaller truth table to larger one + + The most significant variables will not be in the functional support of the + resulting truth table, but the method is helpful to align a truth table when + being used with another one. + + \param tt Larger truth table to create + \param from Smaller truth table to copy from +*/ +template +void extend_to_inplace( TT& tt, const TTFrom& from ) +{ + assert( tt.num_vars() >= from.num_vars() ); + + if ( from.num_vars() < 6 ) + { + auto mask = *from.begin(); + + for ( auto i = from.num_vars(); i < std::min( 6, tt.num_vars() ); ++i ) + { + mask |= ( mask << ( 1 << i ) ); + } + + std::fill( tt.begin(), tt.end(), mask ); + } + else + { + auto it = tt.begin(); + while ( it != tt.end() ) + { + it = std::copy( from.cbegin(), from.cend(), it ); + } + } +} + +/*! \brief Extends smaller truth table to larger static one + + This is an out-of-place version of `extend_to_inplace` that has the truth + table as a return value. It only works for creating static truth tables. The + template parameter `NumVars` must be equal or larger to the number of + variables in `from`. + + \param from Smaller truth table to copy from +*/ +template +inline static_truth_table extend_to( const TTFrom& from ) +{ + static_truth_table tt; + extend_to_inplace( tt, from ); + return tt; +} + +/*! \brief Checks whether truth table depends on given variable index + + \param tt Truth table + \param var_index Variable index +*/ +template +bool has_var( const TT& tt, uint8_t var_index ) +{ + assert( var_index < tt.num_vars() ); + + if ( tt.num_vars() <= 6 || var_index < 6 ) + { + return std::any_of( std::begin( tt._bits ), std::end( tt._bits ), + [var_index]( uint64_t word ) + { return ( ( word >> ( uint64_t( 1 ) << var_index ) ) & detail::projections_neg[var_index] ) != + ( word & detail::projections_neg[var_index] ); } ); + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < static_cast( tt.num_blocks() ); i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + if ( tt._bits[i + j] != tt._bits[i + j + step] ) + { + return true; + } + } + } + return false; +} + +/*! \brief Checks whether truth table depends on given variable index + + \param tt Truth table + \param care Care set + \param var_index Variable index +*/ +template +bool has_var( const TT& tt, const TT& care, uint8_t var_index ) +{ + assert( var_index < tt.num_vars() ); + assert( tt.num_vars() == care.num_vars() ); + + if ( tt.num_vars() <= 6 || var_index < 6 ) + { + auto it_tt = std::begin( tt._bits ); + auto it_care = std::begin( care._bits ); + while ( it_tt != std::end( tt._bits ) ) + { + if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & detail::projections_neg[var_index] + & ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 ) + { + return true; + } + ++it_tt; + ++it_care; + } + + return false; + } + + const auto step = 1 << ( var_index - 6 ); + for ( auto i = 0u; i < static_cast( tt.num_blocks() ); i += 2 * step ) + { + for ( auto j = 0; j < step; ++j ) + { + if ( ( ( tt._bits[i + j] ^ tt._bits[i + j + step] ) & care._bits[i + j] & care._bits[i + j + step] ) != 0 ) + { + return true; + } + } + } + return false; +} + +/*! \brief Shrinks larger truth table to smaller one + + The function expects that the most significant bits, which are cut off, are + not in the functional support of the original function. Only then it is + ensured that the resulting function is equivalent. + + \param tt Smaller truth table to create + \param from Larger truth table to copy from +*/ +template +void shrink_to_inplace( TT& tt, const TTFrom& from ) +{ + assert( tt.num_vars() <= from.num_vars() ); + + std::copy( from.begin(), from.begin() + tt.num_blocks(), tt.begin() ); + + if ( tt.num_vars() < 6 ) + { + tt.mask_bits(); + } +} + +/*! \brief Shrinks larger truth table to smaller dynamic one + + This is an out-of-place version of `shrink_to` that has the truth table as a + return value. It only works for creating dynamic tables. The parameter + `num_vars` must be equal or smaller to the number of variables in `from`. + + \param from Smaller truth table to copy from +*/ +template +inline dynamic_truth_table shrink_to( const TTFrom& from, unsigned num_vars ) +{ + auto tt = create( num_vars ); + shrink_to_inplace( tt, from ); + return tt; +} + +/*! \brief Prints truth table in hexadecimal representation + + The most-significant bit will be the first character of the string. + + \param tt Truth table + \param os Output stream +*/ +template +void print_hex( const TT& tt, std::ostream& os = std::cout ) +{ + auto const chunk_size = + std::min( tt.num_vars() <= 1 ? 1 : ( tt.num_bits() >> 2 ), 16 ); + + for_each_block_reversed( tt, [&os, chunk_size]( uint64_t word ) + { + std::string chunk( chunk_size, '0' ); + + auto it = chunk.rbegin(); + while (word && it != chunk.rend()) { + auto hex = word & 0xf; + if (hex < 10) { + *it = '0' + static_cast(hex); + } else { + *it = 'a' + static_cast(hex - 10); + } + ++it; + word >>= 4; + } + os << chunk; } ); +} + +} //namespace kitty + +ABC_NAMESPACE_CXX_HEADER_END + +#endif // _KITTY_OPERATIONS_TT_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_operators.hpp b/src/map/if/acd/kitty_operators.hpp new file mode 100644 index 000000000..7ccab7ca1 --- /dev/null +++ b/src/map/if/acd/kitty_operators.hpp @@ -0,0 +1,131 @@ +#ifndef _KITTY_OPERATORS_TT_H_ +#define _KITTY_OPERATORS_TT_H_ +#pragma once + +#include +#include +#include +#include +#include + +#include "kitty_constants.hpp" +#include "kitty_dynamic_tt.hpp" +#include "kitty_static_tt.hpp" +#include "kitty_operations.hpp" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace kitty +{ + +/*! \brief Operator for unary_not */ +inline dynamic_truth_table operator~( const dynamic_truth_table& tt ) +{ + return unary_not( tt ); +} + +/*! \brief Operator for unary_not */ +template +inline static_truth_table operator~( const static_truth_table& tt ) +{ + return unary_not( tt ); +} + +/*! \brief Operator for binary_and */ +inline dynamic_truth_table operator&( const dynamic_truth_table& first, const dynamic_truth_table& second ) +{ + return binary_and( first, second ); +} + +/*! \brief Operator for binary_and */ +template +inline static_truth_table operator&( const static_truth_table& first, const static_truth_table& second ) +{ + return binary_and( first, second ); +} + +/*! \brief Operator for binary_and and assign */ +inline void operator&=( dynamic_truth_table& first, const dynamic_truth_table& second ) +{ + first = binary_and( first, second ); +} + +/*! \brief Operator for binary_and and assign */ +template +inline void operator&=( static_truth_table& first, const static_truth_table& second ) +{ + first = binary_and( first, second ); +} + +/*! \brief Operator for binary_or */ +inline dynamic_truth_table operator|( const dynamic_truth_table& first, const dynamic_truth_table& second ) +{ + return binary_or( first, second ); +} + +/*! \brief Operator for binary_or */ +template +inline static_truth_table operator|( const static_truth_table& first, const static_truth_table& second ) +{ + return binary_or( first, second ); +} + +/*! \brief Operator for binary_or and assign */ +inline void operator|=( dynamic_truth_table& first, const dynamic_truth_table& second ) +{ + first = binary_or( first, second ); +} + +/*! \brief Operator for binary_or and assign */ +template +inline void operator|=( static_truth_table& first, const static_truth_table& second ) +{ + // first = binary_or( first, second ); + /* runtime improved version */ + first._bits |= second._bits; + first.mask_bits(); +} + +/*! \brief Operator for binary_or and assign */ +template +inline void operator|=( static_truth_table& first, const static_truth_table& second ) +{ + // first = binary_or( first, second ); + /* runtime improved version */ + if ( NumVars == 7 ) + { + first._bits[0] |= second._bits[0]; + first._bits[1] |= second._bits[1]; + } + else if ( NumVars == 8 ) + { + first._bits[0] |= second._bits[0]; + first._bits[1] |= second._bits[1]; + first._bits[2] |= second._bits[2]; + first._bits[3] |= second._bits[3]; + } + else if ( NumVars == 9 ) + { + first._bits[0] |= second._bits[0]; + first._bits[1] |= second._bits[1]; + first._bits[2] |= second._bits[2]; + first._bits[3] |= second._bits[3]; + first._bits[4] |= second._bits[4]; + first._bits[5] |= second._bits[5]; + first._bits[6] |= second._bits[6]; + first._bits[7] |= second._bits[7]; + } + else + { + for ( uint32_t i = 0; i < first.num_blocks(); ++i ) + { + first._bits[i] |= second._bits[i]; + } + } +} + +} // namespace kitty + +ABC_NAMESPACE_CXX_HEADER_END + +#endif // _KITTY_OPERATORS_TT_H_ \ No newline at end of file diff --git a/src/map/if/acd/kitty_static_tt.hpp b/src/map/if/acd/kitty_static_tt.hpp new file mode 100644 index 000000000..5bb4bdac1 --- /dev/null +++ b/src/map/if/acd/kitty_static_tt.hpp @@ -0,0 +1,243 @@ +#ifndef _KITTY_STATIC_TT_H_ +#define _KITTY_STATIC_TT_H_ +#pragma once + +#include +#include + +#include "kitty_constants.hpp" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace kitty +{ + +template +struct static_truth_table; + +/*! Truth table (for up to 6 variables) in which number of variables is known at compile time. + */ +template +struct static_truth_table +{ + /*! \cond PRIVATE */ + enum + { + NumBits = uint64_t( 1 ) << NumVars + }; + /*! \endcond */ + + /*! Constructs a new static truth table instance with the same number of variables. */ + inline static_truth_table construct() const + { + return static_truth_table(); + } + + /*! Returns number of variables. + */ + inline uint32_t num_vars() const noexcept { return NumVars; } + + /*! Returns number of blocks. + */ + inline uint32_t num_blocks() const noexcept { return 1u; } + + /*! Returns number of bits. + */ + inline uint32_t num_bits() const noexcept { return NumBits; } + + /*! \brief Begin iterator to bits. + */ + inline uint64_t * begin() noexcept { return &_bits; } + + /*! \brief End iterator to bits. + */ + inline uint64_t * end() noexcept { return ( &_bits ) + 1; } + + /*! \brief Begin iterator to bits. + */ + inline const uint64_t * begin() const noexcept { return &_bits; } + + /*! \brief End iterator to bits. + */ + inline const uint64_t * end() const noexcept { return ( &_bits ) + 1; } + + /*! \brief Reverse begin iterator to bits. + */ + inline uint64_t * rbegin() noexcept { return &_bits; } + + /*! \brief Reverse end iterator to bits. + */ + inline uint64_t * rend() noexcept { return ( &_bits ) + 1; } + + /*! \brief Constant begin iterator to bits. + */ + inline const uint64_t * cbegin() const noexcept { return &_bits; } + + /*! \brief Constant end iterator to bits. + */ + inline const uint64_t * cend() const noexcept { return ( &_bits ) + 1; } + + /*! \brief Constant reverse begin iterator to bits. + */ + inline const uint64_t * crbegin() const noexcept { return &_bits; } + + /*! \brief Constant everse end iterator to bits. + */ + inline const uint64_t * crend() const noexcept { return ( &_bits ) + 1; } + + /*! \brief Assign other truth table if number of variables match. + + This replaces the current truth table with another truth table, if `other` + has the same number of variables. Otherwise, the truth table is not + changed. + + \param other Other truth table + */ + template + static_truth_table& operator=( const TT& other ) + { + if ( other.num_vars() == num_vars() ) + { + std::copy( other.begin(), other.end(), begin() ); + } + + return *this; + } + + /*! Masks the number of valid truth table bits. + + If the truth table has less than 6 variables, it may not use all + the bits. This operation makes sure to zero out all non-valid + bits. + */ + inline void mask_bits() noexcept { _bits &= detail::masks[NumVars]; } + + /*! \cond PRIVATE */ +public: /* fields */ + uint64_t _bits = 0; + /*! \endcond */ +}; + +/*! Truth table (more than 6 variables) in which number of variables is known at compile time. + */ +template +struct static_truth_table +{ + /*! \cond PRIVATE */ + enum + { + NumBlocks = ( NumVars <= 6 ) ? 1u : ( 1u << ( NumVars - 6 ) ) + }; + + enum + { + NumBits = uint64_t( 1 ) << NumVars + }; + /*! \endcond */ + + /*! Standard constructor. + + The number of variables provided to the truth table must be known + at runtime. The number of blocks will be computed as a compile + time constant. + */ + static_truth_table() + { + _bits.fill( 0 ); + } + + /*! Constructs a new static truth table instance with the same number of variables. */ + inline static_truth_table construct() const + { + return static_truth_table(); + } + + /*! Returns number of variables. + */ + inline uint32_t num_vars() const noexcept { return NumVars; } + + /*! Returns number of blocks. + */ + inline uint32_t num_blocks() const noexcept { return NumBlocks; } + + /*! Returns number of bits. + */ + inline uint32_t num_bits() const noexcept { return NumBits; } + + /*! \brief Begin iterator to bits. + */ + inline typename std::array::iterator begin() noexcept { return _bits.begin(); } + + /*! \brief End iterator to bits. + */ + inline typename std::array::iterator end() noexcept { return _bits.end(); } + + /*! \brief Begin iterator to bits. + */ + inline typename std::array::const_iterator begin() const noexcept { return _bits.begin(); } + + /*! \brief End iterator to bits. + */ + inline typename std::array::const_iterator end() const noexcept { return _bits.end(); } + + /*! \brief Reverse begin iterator to bits. + */ + inline typename std::array::reverse_iterator rbegin() noexcept { return _bits.rbegin(); } + + /*! \brief Reverse end iterator to bits. + */ + inline typename std::array::reverse_iterator rend() noexcept { return _bits.rend(); } + + /*! \brief Constant begin iterator to bits. + */ + inline typename std::array::const_iterator cbegin() const noexcept { return _bits.cbegin(); } + + /*! \brief Constant end iterator to bits. + */ + inline typename std::array::const_iterator cend() const noexcept { return _bits.cend(); } + + /*! \brief Constant reverse begin iterator to bits. + */ + inline typename std::array::const_reverse_iterator crbegin() const noexcept { return _bits.crbegin(); } + + /*! \brief Constant teverse end iterator to bits. + */ + inline typename std::array::const_reverse_iterator crend() const noexcept { return _bits.crend(); } + + /*! \brief Assign other truth table if number of variables match. + + This replaces the current truth table with another truth table, if `other` + has the same number of variables. Otherwise, the truth table is not + changed. + + \param other Other truth table + */ + template + static_truth_table& operator=( const TT& other ) + { + if ( other.num_bits() == num_bits() ) + { + std::copy( other.begin(), other.end(), begin() ); + } + + return *this; + } + + /*! Masks the number of valid truth table bits. + + We know that we will have at least 7 variables in this data + structure. + */ + inline void mask_bits() noexcept {} + + /*! \cond PRIVATE */ +public: /* fields */ + std::array _bits; + /*! \endcond */ +}; + +} //namespace kitty + +ABC_NAMESPACE_CXX_HEADER_END + +#endif // _KITTY_STATIC_TT_H_ \ No newline at end of file diff --git a/src/map/if/acd/module.make b/src/map/if/acd/module.make new file mode 100644 index 000000000..33c59e830 --- /dev/null +++ b/src/map/if/acd/module.make @@ -0,0 +1 @@ +SRC += src/map/if/acd/ac_wrapper.cpp diff --git a/src/map/if/if.h b/src/map/if/if.h index a72da9b95..723fda780 100644 --- a/src/map/if/if.h +++ b/src/map/if/if.h @@ -40,6 +40,7 @@ #include "opt/dau/dau.h" #include "misc/vec/vecHash.h" #include "misc/vec/vecWec.h" +#include "map/if/acd/ac_wrapper.h" ABC_NAMESPACE_HEADER_START @@ -112,6 +113,7 @@ struct If_Par_t_ int nStructType; // type of the structure int nAndDelay; // delay of AND-gate in LUT library units int nAndArea; // area of AND-gate in LUT library units + int nLutDecSize; // the LUT size for decomposition int fPreprocess; // preprossing int fArea; // area-oriented mapping int fFancy; // a fancy feature @@ -145,9 +147,12 @@ struct If_Par_t_ int fDeriveLuts; // enables deriving LUT structures int fDoAverage; // optimize average rather than maximum level int fHashMapping; // perform AIG hashing after mapping + int fUserLutDec; // perform Boolean decomposition during mapping + int fUserLut2D; // perform Boolean decomposition during mapping int fVerbose; // the verbosity flag int fVerboseTrace; // the verbosity flag char * pLutStruct; // LUT structure + int fEnableStructN;// LUT structure using a new method float WireDelay; // wire delay // internal parameters int fSkipCutFilter;// skip cut filter @@ -309,6 +314,7 @@ struct If_Cut_t_ unsigned fAndCut : 1; // matched with AND gate unsigned nLimit : 8; // the maximum number of leaves unsigned nLeaves : 8; // the number of leaves + unsigned decDelay: 16; // pin-to-pin decomposition delay int pLeaves[0]; }; @@ -547,10 +553,12 @@ extern int If_CutPerformCheck07( If_Man_t * p, unsigned * pTruth, in extern int If_CutPerformCheck08( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck10( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck16( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); +extern int If_CutPerformCheckXX( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck45( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck54( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck75( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern float If_CutDelayLutStruct( If_Man_t * p, If_Cut_t * pCut, char * pStr, float WireDelay ); +// extern int If_CutPerformAcd( If_Man_t * p, unsigned nVars, int lutSize, unsigned * pdelay, int use_late_arrival, unsigned * cost ); extern int If_CluCheckExt( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutRoot, char * pLut0, char * pLut1, word * pFunc0, word * pFunc1 ); extern int If_CluCheckExt3( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot, @@ -565,6 +573,10 @@ extern int If_CutSopBalancePinDelaysInt( Vec_Int_t * vCover, int * p extern int If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); extern int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ); extern int If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); +extern int If_LutDecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ); +extern int If_Lut2DecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ); +extern int If_LutDecReEval( If_Man_t * p, If_Cut_t * pCut ); +extern float If_LutDecPinRequired( If_Man_t * p, If_Cut_t * pCut, int i, float required ); /*=== ifDsd.c =============================================================*/ extern If_DsdMan_t * If_DsdManAlloc( int nVars, int nLutSize ); extern void If_DsdManAllocIsops( If_DsdMan_t * p, int nLutSize ); @@ -692,6 +704,10 @@ extern int If_ManCountSpecialPos( If_Man_t * p ); extern void If_CutTraverse( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes ); extern void If_ObjPrint( If_Obj_t * pObj ); +extern int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); +extern int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); +extern int acd2_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival ); +extern int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition ); ABC_NAMESPACE_HEADER_END diff --git a/src/map/if/ifCore.c b/src/map/if/ifCore.c index c03061af2..eed6a55e8 100644 --- a/src/map/if/ifCore.c +++ b/src/map/if/ifCore.c @@ -62,6 +62,8 @@ void If_ManSetDefaultPars( If_Par_t * pPars ) pPars->fPower = 0; pPars->fCutMin = 0; pPars->fBidec = 0; + pPars->fUserLutDec = 0; + pPars->fUserLut2D = 0; pPars->fVerbose = 0; } @@ -106,6 +108,7 @@ int If_ManPerformMappingComb( If_Man_t * p ) If_Obj_t * pObj; abctime clkTotal = Abc_Clock(); int i; + //p->vVisited2 = Vec_IntAlloc( 100 ); //p->vMarks = Vec_StrStart( If_ManObjNum(p) ); @@ -121,6 +124,7 @@ int If_ManPerformMappingComb( If_Man_t * p ) { // map for delay If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 1, "Delay" ); + // map for delay second option p->pPars->fFancy = 1; If_ManResetOriginalRefs( p ); diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c index e3d47f1c6..c9354b339 100644 --- a/src/map/if/ifCut.c +++ b/src/map/if/ifCut.c @@ -604,10 +604,6 @@ static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; - if ( pC0->Delay < pC1->Delay - p->fEpsilon ) - return -1; - if ( pC0->Delay > pC1->Delay + p->fEpsilon ) - return 1; if ( pC0->fUseless < pC1->fUseless ) return -1; if ( pC0->fUseless > pC1->fUseless ) @@ -765,7 +761,7 @@ void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut ) if ( !pCut->fUseless && (p->pPars->fUseDsd || p->pPars->pFuncCell2 || p->pPars->fUseBat || - p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || + p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUserLut2D || p->pPars->fEnableCheck07 || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->fUseDsdTune || p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u || p->pPars->fUseCheck1 || p->pPars->fUseCheck2) ) { diff --git a/src/map/if/ifDec66.c b/src/map/if/ifDec66.c new file mode 100644 index 000000000..9c486685c --- /dev/null +++ b/src/map/if/ifDec66.c @@ -0,0 +1,335 @@ +/**CFile**************************************************************** + + FileName [ifDec66.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Fast checking procedures.] + + Author [Alessandro Tempia Calvino] + + Affiliation [EPFL] + + Date [Ver. 1.0. Started - Feb 8, 2024.] + + Revision [$Id: ifDec66.c,v 1.00 2008/02/08 00:00:00 tempia Exp $] + +***********************************************************************/ + +#include "if.h" +#include "bool/kit/kit.h" +#include "misc/vec/vecMem.h" + +ABC_NAMESPACE_IMPL_START + +#define CLU_VAR_MAX 11 +#define CLU_MEM_MAX 1000 // 1 GB +#define CLU_UNUSED 0xff + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// decomposition +typedef struct If_Grp_t_ If_Grp_t; +struct If_Grp_t_ +{ + char nVars; + char nMyu; + char pVars[CLU_VAR_MAX]; +}; + +// hash table entry +typedef struct If_Hte_t_ If_Hte_t; +struct If_Hte_t_ +{ + If_Hte_t * pNext; + unsigned Group; + unsigned Counter; + word pTruth[1]; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline unsigned If_CluGrp2Uns2( If_Grp_t * pG ) +{ + char * pChar = (char *)pG; + unsigned Res = 0; + int i; + for ( i = 0; i < 8; i++ ) + Res |= ((pChar[i] & 15) << (i << 2)); + return Res; +} + +static inline void If_CluUns2Grp2( unsigned Group, If_Grp_t * pG ) +{ + char * pChar = (char *)pG; + int i; + for ( i = 0; i < 8; i++ ) + pChar[i] = ((Group >> (i << 2)) & 15); +} + +unsigned int If_CluPrimeCudd2( unsigned int p ) +{ + int i,pn; + + p--; + do { + p++; + if (p&1) { + pn = 1; + i = 3; + while ((unsigned) (i * i) <= p) { + if (p % i == 0) { + pn = 0; + break; + } + i += 2; + } + } else { + pn = 0; + } + } while (!pn); + return(p); + +} /* end of Cudd_Prime */ + +// hash table +static inline int If_CluWordNum2( int nVars ) +{ + return nVars <= 6 ? 1 : 1 << (nVars-6); +} + +int If_CluHashFindMedian2( If_Man_t * p, int t ) +{ + If_Hte_t * pEntry; + Vec_Int_t * vCounters; + int i, Max = 0, Total = 0, Half = 0; + vCounters = Vec_IntStart( 1000 ); + for ( i = 0; i < p->nTableSize[t]; i++ ) + { + for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; pEntry = pEntry->pNext ) + { + if ( Max < (int)pEntry->Counter ) + { + Max = pEntry->Counter; + Vec_IntSetEntry( vCounters, pEntry->Counter, 0 ); + } + Vec_IntAddToEntry( vCounters, pEntry->Counter, 1 ); + Total++; + } + } + for ( i = Max; i > 0; i-- ) + { + Half += Vec_IntEntry( vCounters, i ); + if ( Half > Total/2 ) + break; + } +/* + printf( "total = %d ", Total ); + printf( "half = %d ", Half ); + printf( "i = %d ", i ); + printf( "Max = %d.\n", Max ); +*/ + Vec_IntFree( vCounters ); + return Abc_MaxInt( i, 1 ); +} + +int If_CluHashKey2( word * pTruth, int nWords, int Size ) +{ + static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; + unsigned Value = 0; + int i; + if ( nWords < 4 ) + { + unsigned char * s = (unsigned char *)pTruth; + for ( i = 0; i < 8 * nWords; i++ ) + Value ^= BigPrimes[i % 7] * s[i]; + } + else + { + unsigned * s = (unsigned *)pTruth; + for ( i = 0; i < 2 * nWords; i++ ) + Value ^= BigPrimes[i % 7] * s[i]; + } + return Value % Size; +} + +unsigned * If_CluHashLookup2( If_Man_t * p, word * pTruth, int t ) +{ + If_Hte_t * pEntry, * pPrev; + int nWords, HashKey; + if ( p == NULL ) + return NULL; + nWords = If_CluWordNum2(p->pPars->nLutSize); + if ( p->pMemEntries == NULL ) + p->pMemEntries = Mem_FixedStart( sizeof(If_Hte_t) + sizeof(word) * (If_CluWordNum2(p->pPars->nLutSize) - 1) ); + if ( p->pHashTable[t] == NULL ) + { + // decide how large should be the table + int nEntriesMax1 = 4 * If_CluPrimeCudd2( Vec_PtrSize(p->vObjs) * p->pPars->nCutsMax ); + int nEntriesMax2 = (int)(((double)CLU_MEM_MAX * (1 << 20)) / If_CluWordNum2(p->pPars->nLutSize) / 8); +// int nEntriesMax2 = 10000; + // create table + p->nTableSize[t] = If_CluPrimeCudd2( Abc_MinInt(nEntriesMax1, nEntriesMax2)/2 ); + p->pHashTable[t] = ABC_CALLOC( void *, p->nTableSize[t] ); + } + // check if this entry exists + HashKey = If_CluHashKey2( pTruth, nWords, p->nTableSize[t] ); + for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[HashKey]; pEntry; pEntry = pEntry->pNext ) + if ( memcmp(pEntry->pTruth, pTruth, sizeof(word) * nWords) == 0 ) + { + pEntry->Counter++; + return &pEntry->Group; + } + // resize the hash table + if ( p->nTableEntries[t] >= 2 * p->nTableSize[t] ) + { + // collect useful entries + If_Hte_t * pPrev; + Vec_Ptr_t * vUseful = Vec_PtrAlloc( p->nTableEntries[t] ); + int i, Median = If_CluHashFindMedian2( p, t ); + for ( i = 0; i < p->nTableSize[t]; i++ ) + { + for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; ) + { + if ( (int)pEntry->Counter > Median ) + { + Vec_PtrPush( vUseful, pEntry ); + pEntry = pEntry->pNext; + } + else + { + pPrev = pEntry->pNext; + Mem_FixedEntryRecycle( p->pMemEntries, (char *)pEntry ); + pEntry = pPrev; + } + } + } + // add useful entries + memset( p->pHashTable[t], 0, sizeof(void *) * p->nTableSize[t] ); + Vec_PtrForEachEntry( If_Hte_t *, vUseful, pEntry, i ) + { + HashKey = If_CluHashKey2( pEntry->pTruth, nWords, p->nTableSize[t] ); + pPrev = ((If_Hte_t **)p->pHashTable[t])[HashKey]; + if ( pPrev == NULL || pEntry->Counter >= pPrev->Counter ) + { + pEntry->pNext = pPrev; + ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry; + } + else + { + while ( pPrev->pNext && pEntry->Counter < pPrev->pNext->Counter ) + pPrev = pPrev->pNext; + pEntry->pNext = pPrev->pNext; + pPrev->pNext = pEntry; + } + } + p->nTableEntries[t] = Vec_PtrSize( vUseful ); + Vec_PtrFree( vUseful ); + } + // create entry + p->nTableEntries[t]++; + pEntry = (If_Hte_t *)Mem_FixedEntryFetch( p->pMemEntries ); + memcpy( pEntry->pTruth, pTruth, sizeof(word) * nWords ); + pEntry->Group = CLU_UNUSED; + pEntry->Counter = 1; + // insert at the beginning +// pEntry->pNext = ((If_Hte_t **)p->pHashTable[t])[HashKey]; +// ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry; + // insert at the end + pEntry->pNext = NULL; + for ( pPrev = ((If_Hte_t **)p->pHashTable[t])[HashKey]; pPrev && pPrev->pNext; pPrev = pPrev->pNext ); + if ( pPrev == NULL ) + ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry; + else + pPrev->pNext = pEntry; + return &pEntry->Group; +} + +// returns if successful +int If_CluCheckXX( If_Man_t * p, word * pTruth0, int lutSize, int nVars, int fHashing ) +{ + If_Grp_t G1 = {0}; + unsigned * pHashed = NULL; + + if ( p && fHashing ) + { + pHashed = If_CluHashLookup2( p, pTruth0, 0 ); + if ( pHashed && *pHashed != CLU_UNUSED ) + If_CluUns2Grp2( *pHashed, &G1 ); + } + + /* new entry */ + if ( G1.nVars == 0 ) + { + G1.nVars = acdXX_decompose( pTruth0, lutSize, nVars, NULL ); + } + + if ( pHashed ) + *pHashed = If_CluGrp2Uns2( &G1 ); + + return G1.nVars; +} + +/**Function************************************************************* + + Synopsis [Performs ACD into 66 cascade.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_CutPerformCheckXX( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeaves, char * pStr ) +{ + unsigned pTruth[IF_MAX_FUNC_LUTSIZE > 5 ? 1 << (IF_MAX_FUNC_LUTSIZE - 5) : 1]; + int Length; + // stretch the truth table + memcpy( pTruth, pTruth0, sizeof(word) * Abc_TtWordNum(nVars) ); + Abc_TtStretch6( (word *)pTruth, nLeaves, p->pPars->nLutSize ); + + // if cutmin is disabled, minimize the function + if ( !p->pPars->fCutMin ) + nLeaves = Abc_TtMinBase( (word *)pTruth, NULL, nLeaves, nVars ); + + // quit if parameters are wrong + Length = strlen(pStr); + if ( Length != 2 ) + { + printf( "Wrong LUT struct (%s)\n", pStr ); + return 0; + } + + int lutSize = pStr[0] - '0'; + if ( lutSize < 3 || lutSize > 6 ) + { + printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", lutSize ); + return 0; + } + + if ( nLeaves >= 2 * lutSize ) + { + printf( "The cut size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr ); + return 0; + } + + // consider trivial case + if ( nLeaves <= lutSize ) + return 1; + + return If_CluCheckXX(p, (word*)pTruth, lutSize, nVars, 1); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/map/if/ifDelay.c b/src/map/if/ifDelay.c index cb25e767e..0f94de49a 100644 --- a/src/map/if/ifDelay.c +++ b/src/map/if/ifDelay.c @@ -411,6 +411,233 @@ int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ) return DelayMax + 2; } } + +int If_LutDecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ) +{ + pCut->fUser = 1; + pCut->Cost = pCut->nLeaves > 1 ? 1 : 0; + pCut->decDelay = 0; + if ( pCut->nLeaves == 0 ) // const + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 ); + return 0; + } + if ( pCut->nLeaves == 1 ) // variable + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 ); + return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; + } + + int LutSize = p->pPars->nLutDecSize; + int i, leaf_delay; + int DelayMax = -1, nLeafMax = 0; + unsigned uLeafMask = 0; + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + { + leaf_delay = If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; + + if ( DelayMax < leaf_delay ) + { + DelayMax = leaf_delay; + nLeafMax = 1; + uLeafMask = (1 << i); + } + else if ( DelayMax == leaf_delay ) + { + nLeafMax++; + uLeafMask |= (1 << i); + } + } + if ( If_CutLeaveNum(pCut) <= LutSize ) + { + pCut->decDelay = ( 1 << LutSize ) - 1; + return DelayMax + 1; + } + + /* compute the decomposition */ + int use_late_arrival = 0; + unsigned cost = 1; + + if ( !fFirst ) + { + if ( optDelay ) + { + /* checks based on delay: must be better than the previous best cut */ + use_late_arrival = DelayMax + 2 >= If_ObjCutBest(pObj)->Delay; + } + else + { + /* checks based on delay: look at the required time */ + use_late_arrival = DelayMax + 2 > pObj->Required + p->fEpsilon; + } + } + + /* Too many late-arriving signals */ + if ( nLeafMax == LutSize ) + { + if ( use_late_arrival ) + { + /* unfeasible decomposition */ + pCut->Cost = IF_COST_MAX; + return ABC_INFINITY; + } + else + { + /* remove critical signals as not needed */ + uLeafMask = 0; + } + } + + /* returns the delay of the decomposition */ + word *pTruth = If_CutTruthW( p, pCut ); + int val = acd_evaluate( pTruth, pCut->nLeaves, LutSize, &uLeafMask, &cost, !use_late_arrival ); + + /* not feasible decomposition */ + pCut->decDelay = uLeafMask; + if ( val < 0 ) + { + pCut->Cost = IF_COST_MAX; + return ABC_INFINITY; + } + + pCut->Cost = cost; + + return DelayMax + val; +} + +int If_Lut2DecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst ) +{ + pCut->fUser = 1; + pCut->Cost = pCut->nLeaves > 1 ? 1 : 0; + pCut->decDelay = 0; + if ( pCut->nLeaves == 0 ) // const + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 ); + return 0; + } + if ( pCut->nLeaves == 1 ) // variable + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 ); + return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; + } + + int LutSize = p->pPars->nLutDecSize; + int i, leaf_delay; + int DelayMax = -1, nLeafMax = 0; + unsigned uLeafMask = 0; + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + { + leaf_delay = If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; + + if ( DelayMax < leaf_delay ) + { + DelayMax = leaf_delay; + nLeafMax = 1; + uLeafMask = (1 << i); + } + else if ( DelayMax == leaf_delay ) + { + nLeafMax++; + uLeafMask |= (1 << i); + } + } + if ( If_CutLeaveNum(pCut) <= LutSize ) + { + pCut->decDelay = ( 1 << LutSize ) - 1; + return DelayMax + 1; + } + + /* compute the decomposition */ + int use_late_arrival = 0; + unsigned cost = 1; + + if ( !fFirst ) + { + if ( optDelay ) + { + /* checks based on delay: must be better than the previous best cut */ + use_late_arrival = DelayMax + 2 >= If_ObjCutBest(pObj)->Delay; + } + else + { + /* checks based on delay: look at the required time */ + use_late_arrival = DelayMax + 2 > pObj->Required + p->fEpsilon; + } + } + + /* Too many late-arriving signals */ + if ( nLeafMax == LutSize && use_late_arrival ) + { + /* unfeasible decomposition */ + pCut->Cost = IF_COST_MAX; + return ABC_INFINITY; + } + + if ( !use_late_arrival ) + { + uLeafMask = 0; + } + + /* returns the delay of the decomposition */ + word *pTruth = If_CutTruthW( p, pCut ); + int val = acd2_evaluate( pTruth, pCut->nLeaves, LutSize, &uLeafMask, &cost, !use_late_arrival ); + + /* not feasible decomposition */ + pCut->decDelay = uLeafMask; + if ( val < 0 ) + { + pCut->Cost = IF_COST_MAX; + return ABC_INFINITY; + } + + pCut->Cost = 2; + return DelayMax + val; +} + +int If_LutDecReEval( If_Man_t * p, If_Cut_t * pCut ) +{ + // pCut->fUser = 1; + + if ( pCut->nLeaves == 0 ) // const + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 ); + return 0; + } + if ( pCut->nLeaves == 1 ) // variable + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 ); + return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; + } + + // int LutSize = p->pPars->pLutStruct[0] - '0'; + int i, leaf_delay; + int DelayMax = -1; + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + { + leaf_delay = If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; + leaf_delay += ( ( pCut->decDelay >> i ) & 1 ) == 0 ? 2 : 1; + DelayMax = Abc_MaxInt( leaf_delay, DelayMax ); + } + + return DelayMax; +} + +float If_LutDecPinRequired( If_Man_t * p, If_Cut_t * pCut, int i, float required ) +{ + if ( pCut->nLeaves == 0 ) // const + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 ); + return required; + } + if ( pCut->nLeaves == 1 ) // variable + { + assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 ); + return 0; + } + + return ( ( pCut->decDelay >> i ) & 1 ) == 0 ? 2 : 1; +} + /* int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ) { diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index ffc1e3846..d508afd9d 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -166,7 +166,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep If_Cut_t * pCut0R, * pCut1R; int fFunc0R, fFunc1R; int i, k, v, iCutDsd, fChange; - int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || + int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUserLut2D || p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct || p->pPars->pFuncCell2 || p->pPars->fUseCheck1 || p->pPars->fUseCheck2; int fUseAndCut = (p->pPars->nAndDelay > 0) || (p->pPars->nAndArea > 0); assert( !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 0 ); @@ -208,6 +208,10 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->fUseless = 1; } } + else if ( p->pPars->fUserLutDec || p->pPars->fUserLut2D ) + { + pCut->Delay = If_LutDecReEval( p, pCut ); + } else if ( p->pPars->fDelayOptLut ) pCut->Delay = If_CutLutBalanceEval( p, pCut ); else if( p->pPars->nGateSize > 0 ) @@ -264,6 +268,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep if ( !If_CutMergeOrdered( p, pCut0, pCut1, pCut ) ) continue; } + if ( p->pPars->fUserLutDec && !fFirst && pCut->nLeaves > p->pPars->nLutDecSize ) + continue; if ( pObj->fSpec && pCut->nLeaves == (unsigned)p->pPars->nLutSize ) continue; p->nCutsMerged++; @@ -422,7 +428,17 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep else if ( p->pPars->fDsdBalance ) pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL ); else if ( p->pPars->fUserRecLib ) - pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj ); + pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj ); + else if ( p->pPars->fUserLutDec ) + { + pCut->Delay = If_LutDecEval( p, pCut, pObj, Mode == 0, fFirst ); + pCut->fUseless = pCut->Delay == ABC_INFINITY; + } + else if ( p->pPars->fUserLut2D ) + { + pCut->Delay = If_Lut2DecEval( p, pCut, pObj, Mode == 0, fFirst ); + pCut->fUseless = pCut->Delay == ABC_INFINITY; + } else if ( p->pPars->fUserSesLib ) { int Cost = 0; @@ -507,7 +523,7 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP If_Set_t * pCutSet; If_Obj_t * pTemp; If_Cut_t * pCutTemp, * pCut; - int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec; + int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec || p->pPars->fUserLutDec || p->pPars->fUserLut2D; assert( pObj->pEquiv != NULL ); // prepare diff --git a/src/map/if/ifTime.c b/src/map/if/ifTime.c index 9ceef1475..a1b51d6ad 100644 --- a/src/map/if/ifTime.c +++ b/src/map/if/ifTime.c @@ -211,6 +211,12 @@ void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, fl pLeaf->Required = IF_MIN( pLeaf->Required, Required - pLutDelays[0] ); } } + else if ( p->pPars->fUserLutDec || p->pPars->fUserLut2D ) + { + Required = ObjRequired; + If_CutForEachLeaf( p, pCut, pLeaf, i ) + pLeaf->Required = IF_MIN( pLeaf->Required, Required - If_LutDecPinRequired( p, pCut, i, ObjRequired ) ); + } else { if ( pCut->fUser ) diff --git a/src/map/if/module.make b/src/map/if/module.make index 6651d465b..bd652f35b 100644 --- a/src/map/if/module.make +++ b/src/map/if/module.make @@ -7,6 +7,7 @@ SRC += src/map/if/ifCom.c \ src/map/if/ifDec08.c \ src/map/if/ifDec10.c \ src/map/if/ifDec16.c \ + src/map/if/ifDec66.c \ src/map/if/ifDec75.c \ src/map/if/ifDelay.c \ src/map/if/ifDsd.c \ diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index 3a82280dc..6ddd60944 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -183,13 +183,15 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) int fUnit = 0; int fVerbose = 1; int fVeryVerbose = 0; + int fMerge = 0; + int fUsePrefix = 0; SC_DontUse dont_use = {0}; dont_use.dont_use_list = ABC_ALLOC(char *, argc); dont_use.size = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "SGMXdnuvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "SGMXdnuvwmph" ) ) != EOF ) { switch ( c ) { @@ -251,6 +253,12 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'w': fVeryVerbose ^= 1; break; + case 'm': + fMerge ^= 1; + break; + case 'p': + fUsePrefix ^= 1; + break; case 'h': goto usage; default: @@ -266,12 +274,20 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) if (pLib2) Abc_SclLibFree(pLib2); return 1; } - pLib = Abc_SclMergeLibraries( pLib1, pLib2 ); + pLib = Abc_SclMergeLibraries( pLib1, pLib2, fUsePrefix ); Abc_SclLibFree(pLib1); Abc_SclLibFree(pLib2); } else if ( argc == globalUtilOptind + 1 ) { // expecting one file - pLib = Scl_ReadLibraryFile( pAbc, argv[globalUtilOptind], fVerbose, fVeryVerbose, dont_use ); + SC_Lib * pLib1 = Scl_ReadLibraryFile( pAbc, argv[globalUtilOptind], fVerbose, fVeryVerbose, dont_use ); + + SC_Lib * pLib_ext = (SC_Lib *)pAbc->pLibScl; + if ( fMerge && pLib_ext != NULL && pLib1 != NULL ) { + pLib = Abc_SclMergeLibraries( pLib_ext, pLib1, fUsePrefix ); + if (pLib1) Abc_SclLibFree(pLib1); + } else { + pLib = pLib1; + } ABC_FREE(dont_use.dont_use_list); } else { @@ -308,7 +324,7 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnuvwh] [-X cell_name] \n" ); + fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnuvwmph] [-X cell_name] \n" ); fprintf( pAbc->Err, "\t reads Liberty library from file\n" ); fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew ); fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain ); @@ -319,6 +335,8 @@ usage: fprintf( pAbc->Err, "\t-u : toggle setting unit area for all cells [default = %s]\n", fUnit? "yes": "no" ); fprintf( pAbc->Err, "\t-v : toggle writing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-w : toggle writing information about skipped gates [default = %s]\n", fVeryVerbose? "yes": "no" ); + fprintf( pAbc->Err, "\t-m : toggle merging library with exisiting library [default = %s]\n", fMerge? "yes": "no" ); + fprintf( pAbc->Err, "\t-p : toggle using prefix for the cell names [default = %s]\n", fUsePrefix? "yes": "no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\t : the name of a file to read\n" ); fprintf( pAbc->Err, "\t : the name of a file to read (optional)\n" ); @@ -1136,9 +1154,9 @@ int Scl_CommandBuffer( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: fprintf( pAbc->Err, "usage: buffer [-GSN num] [-sbpcvwh]\n" ); - fprintf( pAbc->Err, "\t performs buffering and sizing and mapped network\n" ); + fprintf( pAbc->Err, "\t performs buffering and sizing on mapped network\n" ); fprintf( pAbc->Err, "\t-G : target gain percentage [default = %d]\n", pPars->GainRatio ); - fprintf( pAbc->Err, "\t-S : target slew in pisoseconds [default = %d]\n", pPars->Slew ); + fprintf( pAbc->Err, "\t-S : target slew in picoseconds [default = %d]\n", pPars->Slew ); fprintf( pAbc->Err, "\t-N : the maximum fanout count [default = %d]\n", pPars->nDegree ); fprintf( pAbc->Err, "\t-s : toggle performing only sizing [default = %s]\n", pPars->fSizeOnly? "yes": "no" ); fprintf( pAbc->Err, "\t-b : toggle using buffers instead of inverters [default = %s]\n", pPars->fAddBufs? "yes": "no" ); @@ -1604,7 +1622,7 @@ int Scl_CommandUpsize( Abc_Frame_t * pAbc, int argc, char **argv ) return 1; } - Abc_SclUpsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars ); + Abc_SclUpsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars, NULL ); return 0; usage: @@ -1781,15 +1799,15 @@ int Scl_CommandDnsize( Abc_Frame_t * pAbc, int argc, char **argv ) return 1; } - Abc_SclDnsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars ); + Abc_SclDnsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars, NULL ); return 0; usage: fprintf( pAbc->Err, "usage: dnsize [-IJNDGTX num] [-csdvwh]\n" ); fprintf( pAbc->Err, "\t selectively decreases gate sizes while maintaining delay\n" ); - fprintf( pAbc->Err, "\t-I : the number of upsizing iterations to perform [default = %d]\n", pPars->nIters ); + fprintf( pAbc->Err, "\t-I : the number of downsizing iterations to perform [default = %d]\n", pPars->nIters ); fprintf( pAbc->Err, "\t-J : the number of iterations without improvement to stop [default = %d]\n", pPars->nIterNoChange ); - fprintf( pAbc->Err, "\t-N : limit on discrete upsizing steps at a node [default = %d]\n", pPars->Notches ); + fprintf( pAbc->Err, "\t-N : limit on discrete downsizing steps at a node [default = %d]\n", pPars->Notches ); fprintf( pAbc->Err, "\t-D : delay target set by the user, in picoseconds [default = %d]\n", pPars->DelayUser ); fprintf( pAbc->Err, "\t-G : delay gap during updating, in picoseconds [default = %d]\n", pPars->DelayGap ); fprintf( pAbc->Err, "\t-T : approximate timeout in seconds [default = %d]\n", pPars->TimeOut ); diff --git a/src/map/scl/sclDnsize.c b/src/map/scl/sclDnsize.c index 19e4b30c7..35f2c8247 100644 --- a/src/map/scl/sclDnsize.c +++ b/src/map/scl/sclDnsize.c @@ -239,7 +239,7 @@ void Abc_SclDnsizePrint( SC_Man * p, int Iter, int nAttempts, int nOverlaps, int SeeAlso [] ***********************************************************************/ -void Abc_SclDnsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ) +void Abc_SclDnsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, void * pFuncFanin ) { SC_Man * p; Abc_Obj_t * pObj; @@ -261,11 +261,12 @@ void Abc_SclDnsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPa // prepare the manager; collect init stats p = Abc_SclManStart( pLib, pNtk, pPars->fUseWireLoads, pPars->fUseDept, pPars->DelayUser, pPars->BuffTreeEst ); + p->pFuncFanin = (float (*)(void *, Abc_Obj_t *, Abc_Obj_t *, int, int))pFuncFanin; p->timeTotal = Abc_Clock(); assert( p->vGatesBest == NULL ); p->vGatesBest = Vec_IntDup( p->pNtk->vGates ); - // perform upsizing + // perform downsizing vNodes = Vec_IntAlloc( 1000 ); vEvals = Vec_IntAlloc( 1000 ); vTryLater = Vec_IntAlloc( 1000 ); @@ -357,12 +358,12 @@ void Abc_SclDnsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPa SeeAlso [] ***********************************************************************/ -void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ) +void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, void * pFuncFanin ) { Abc_Ntk_t * pNtkNew = pNtk; if ( pNtk->nBarBufs2 > 0 ) pNtkNew = Abc_NtkDupDfsNoBarBufs( pNtk ); - Abc_SclDnsizePerformInt( pLib, pNtkNew, pPars ); + Abc_SclDnsizePerformInt( pLib, pNtkNew, pPars, pFuncFanin ); if ( pNtk->nBarBufs2 > 0 ) Abc_SclTransferGates( pNtk, pNtkNew ); if ( pNtk->nBarBufs2 > 0 ) diff --git a/src/map/scl/sclLib.h b/src/map/scl/sclLib.h index 08a9066a5..c08f30c09 100644 --- a/src/map/scl/sclLib.h +++ b/src/map/scl/sclLib.h @@ -748,7 +748,7 @@ extern SC_Lib * Abc_SclReadFromStr( Vec_Str_t * vOut ); extern SC_Lib * Abc_SclReadFromFile( char * pFileName ); extern void Abc_SclWriteScl( char * pFileName, SC_Lib * p ); extern void Abc_SclWriteLiberty( char * pFileName, SC_Lib * p ); -extern SC_Lib * Abc_SclMergeLibraries( SC_Lib * pLib1, SC_Lib * pLib2 ); +extern SC_Lib * Abc_SclMergeLibraries( SC_Lib * pLib1, SC_Lib * pLib2, int fUsePrefix ); /*=== sclLibUtil.c ===============================================================*/ extern void Abc_SclHashCells( SC_Lib * p ); extern int Abc_SclCellFind( SC_Lib * p, char * pName ); diff --git a/src/map/scl/sclLibScl.c b/src/map/scl/sclLibScl.c index e13a746e6..144ec7f55 100644 --- a/src/map/scl/sclLibScl.c +++ b/src/map/scl/sclLibScl.c @@ -570,7 +570,7 @@ int Abc_SclCountValidCells( SC_Lib * p ) n_valid_cells++; return n_valid_cells; } -static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p, int nExtra ) +static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p, int nExtra, int fUsePrefix ) { SC_WireLoad * pWL; SC_WireLoadSel * pWLS; @@ -624,13 +624,13 @@ static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p, int nExtra ) // Write 'cells' vector: n_valid_cells = Abc_SclCountValidCells( p ); Vec_StrPutI( vOut, n_valid_cells + nExtra ); - Abc_SclWriteLibraryCellsOnly( vOut, p, (int)(nExtra > 0) ); + Abc_SclWriteLibraryCellsOnly( vOut, p, fUsePrefix ? 1 : 0 ); } void Abc_SclWriteScl( char * pFileName, SC_Lib * p ) { Vec_Str_t * vOut; vOut = Vec_StrAlloc( 10000 ); - Abc_SclWriteLibrary( vOut, p, 0 ); + Abc_SclWriteLibrary( vOut, p, 0, 0 ); if ( Vec_StrSize(vOut) > 0 ) { FILE * pFile = fopen( pFileName, "wb" ); @@ -866,12 +866,12 @@ void Abc_SclWriteLiberty( char * pFileName, SC_Lib * p ) SeeAlso [] ***********************************************************************/ -SC_Lib * Abc_SclMergeLibraries( SC_Lib * pLib1, SC_Lib * pLib2 ) +SC_Lib * Abc_SclMergeLibraries( SC_Lib * pLib1, SC_Lib * pLib2, int fUsePrefix ) { Vec_Str_t * vOut = Vec_StrAlloc( 10000 ); int n_valid_cells2 = Abc_SclCountValidCells( pLib2 ); - Abc_SclWriteLibrary( vOut, pLib1, n_valid_cells2 ); - Abc_SclWriteLibraryCellsOnly( vOut, pLib2, 2 ); + Abc_SclWriteLibrary( vOut, pLib1, n_valid_cells2, fUsePrefix ); + Abc_SclWriteLibraryCellsOnly( vOut, pLib2, fUsePrefix ? 2 : 0 ); SC_Lib * p = Abc_SclReadFromStr( vOut ); p->pFileName = Abc_UtilStrsav( pLib1->pFileName ); p->pName = ABC_ALLOC( char, strlen(pLib1->pName) + strlen(pLib2->pName) + 10 ); diff --git a/src/map/scl/sclLiberty.c b/src/map/scl/sclLiberty.c index 98520ee96..707a8c585 100644 --- a/src/map/scl/sclLiberty.c +++ b/src/map/scl/sclLiberty.c @@ -83,7 +83,7 @@ struct Scl_Tree_t_ static inline int Scl_LibertyGlobMatch(const char * pattern, const char * string) { #ifdef _WIN32 - return PathMatchSpec(string, pattern); + return PathMatchSpec(string, pattern); // if the compiler complains, add "-lshlwapi" #else return fnmatch(pattern, string, 0) == 0; #endif @@ -281,26 +281,38 @@ static inline char * Scl_LibertyFindMatch( char * pPos, char * pEnd ) assert( *pPos == '(' || *pPos == '{' ); if ( *pPos == '(' ) { - for ( ; pPos < pEnd; pPos++ ) - { - if ( *pPos == '(' ) + ++Counter; + ++pPos; + for ( ; pPos < pEnd; pPos++ ) + { + // Invariant: Counter > 0. + if ( *pPos == '(' ) { Counter++; - if ( *pPos == ')' ) + continue; + } + else if ( *pPos == ')' ) { Counter--; - if ( Counter == 0 ) - break; + if ( Counter == 0 ) + break; + } } } else { + ++Counter; + ++pPos; for ( ; pPos < pEnd; pPos++ ) { - if ( *pPos == '{' ) + // Invariant: Counter > 0. + if ( *pPos == '{' ) { Counter++; - if ( *pPos == '}' ) + continue; + } + else if ( *pPos == '}' ) { Counter--; - if ( Counter == 0 ) - break; + if ( Counter == 0 ) + break; + } } } assert( *pPos == ')' || *pPos == '}' ); @@ -317,10 +329,14 @@ static inline Scl_Pair_t Scl_LibertyUpdateHead( Scl_Tree_t * p, Scl_Pair_t Head char * pChar; for ( pChar = pBeg; pChar < pEnd; pChar++ ) { - if ( *pChar == '\n' ) + if ( *pChar == '\n' ) { p->nLines++; - if ( Scl_LibertyCharIsSpace(*pChar) ) + // Note: Scl_LibertyCharIsSpace returns true for '\n', so we can + // continue here and save the call to Scl_LibertyCharIsSpace. continue; + } else if ( Scl_LibertyCharIsSpace(*pChar) ) { + continue; + } pLastNonSpace = pChar; if ( pFirstNonSpace == NULL ) pFirstNonSpace = pChar; diff --git a/src/map/scl/sclSize.c b/src/map/scl/sclSize.c index e09c56e67..b3bc2828d 100644 --- a/src/map/scl/sclSize.c +++ b/src/map/scl/sclSize.c @@ -270,21 +270,25 @@ void Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fPrintPath ) SeeAlso [] ***********************************************************************/ -static inline void Abc_SclTimeFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +static inline void Abc_SclTimeFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin, int k ) { SC_Pair * pArrIn = Abc_SclObjTime( p, pFanin ); SC_Pair * pSlewIn = Abc_SclObjSlew( p, pFanin ); SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); SC_Pair * pArrOut = Abc_SclObjTime( p, pObj ); // modified SC_Pair * pSlewOut = Abc_SclObjSlew( p, pObj ); // modified + if ( p->pFuncFanin ) pLoad->fall += p->pFuncFanin(p, pObj, pFanin, k, 0); + if ( p->pFuncFanin ) pLoad->rise += p->pFuncFanin(p, pObj, pFanin, k, 1); Scl_LibPinArrival( pTime, pArrIn, pSlewIn, pLoad, pArrOut, pSlewOut ); } -static inline void Abc_SclDeptFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +static inline void Abc_SclDeptFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin, int k ) { SC_Pair * pDepIn = Abc_SclObjDept( p, pFanin ); // modified SC_Pair * pSlewIn = Abc_SclObjSlew( p, pFanin ); SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); SC_Pair * pDepOut = Abc_SclObjDept( p, pObj ); + if ( p->pFuncFanin ) pLoad->fall += p->pFuncFanin(p, pObj, pFanin, k, 0); + if ( p->pFuncFanin ) pLoad->rise += p->pFuncFanin(p, pObj, pFanin, k, 1); Scl_LibPinDeparture( pTime, pDepIn, pSlewIn, pLoad, pDepOut ); } static inline void Abc_SclDeptObj( SC_Man * p, Abc_Obj_t * pObj ) @@ -298,7 +302,7 @@ static inline void Abc_SclDeptObj( SC_Man * p, Abc_Obj_t * pObj ) if ( Abc_ObjIsCo(pFanout) || Abc_ObjIsLatch(pFanout) ) continue; pTime = Scl_CellPinTime( Abc_SclObjCell(pFanout), Abc_NodeFindFanin(pFanout, pObj) ); - Abc_SclDeptFanin( p, pTime, pFanout, pObj ); + Abc_SclDeptFanin( p, pTime, pFanout, pObj, Abc_NodeFindFanin(pFanout, pObj) ); } } static inline float Abc_SclObjLoadValue( SC_Man * p, Abc_Obj_t * pObj ) @@ -368,9 +372,9 @@ void Abc_SclTimeNode( SC_Man * p, Abc_Obj_t * pObj, int fDept ) { pTime = Scl_CellPinTime( pCell, k ); if ( fDept ) - Abc_SclDeptFanin( p, pTime, pObj, pFanin ); + Abc_SclDeptFanin( p, pTime, pObj, pFanin, k ); else - Abc_SclTimeFanin( p, pTime, pObj, pFanin ); + Abc_SclTimeFanin( p, pTime, pObj, pFanin, k ); } if ( p->EstLoadMax && Value > 1 ) { diff --git a/src/map/scl/sclSize.h b/src/map/scl/sclSize.h index 3ec0d83e3..133ae6647 100644 --- a/src/map/scl/sclSize.h +++ b/src/map/scl/sclSize.h @@ -95,6 +95,7 @@ struct SC_Man_ abctime timeSize; // incremental sizing abctime timeTime; // timing update abctime timeOther; // everything else + float (*pFuncFanin)(void * p, Abc_Obj_t * pObj, Abc_Obj_t * pFanin, int iFanin, int fRise); // called to get info about the node's fanin }; //////////////////////////////////////////////////////////////////////// @@ -127,7 +128,7 @@ static inline double Abc_SclObjSlackMax( SC_Man * p, Abc_Obj_t * pObj, float static inline void Abc_SclObjDupFanin( SC_Man * p, Abc_Obj_t * pObj ) { assert( Abc_ObjIsCo(pObj) ); *Abc_SclObjTime(p, pObj) = *Abc_SclObjTime(p, Abc_ObjFanin0(pObj)); } static inline float Abc_SclObjInDrive( SC_Man * p, Abc_Obj_t * pObj ) { return Vec_FltEntry( p->vInDrive, pObj->iData ); } static inline void Abc_SclObjSetInDrive( SC_Man * p, Abc_Obj_t * pObj, float c){ Vec_FltWriteEntry( p->vInDrive, pObj->iData, c ); } - +static inline void Abc_SclManSetFaninCallBack( SC_Man * p, void * pCallBack ) { p->pFuncFanin = (float (*)(void *, Abc_Obj_t *, Abc_Obj_t *, int, int))pCallBack; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -551,7 +552,7 @@ extern int Abc_SclCheckNtk( Abc_Ntk_t * p, int fVerbose ); extern Abc_Ntk_t * Abc_SclPerformBuffering( Abc_Ntk_t * p, int DegreeR, int Degree, int fUseInvs, int fVerbose ); extern Abc_Ntk_t * Abc_SclBufPerform( Abc_Ntk_t * pNtk, int FanMin, int FanMax, int fBufPis, int fSkipDup, int fVerbose ); /*=== sclDnsize.c ===============================================================*/ -extern void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ); +extern void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, void * pFuncFanin ); /*=== sclLoad.c ===============================================================*/ extern Vec_Flt_t * Abc_SclFindWireCaps( SC_WireLoad * pWL, int nFanoutMax ); extern float Abc_SclFindWireLoad( Vec_Flt_t * vWireCaps, int nFans ); @@ -573,7 +574,7 @@ extern void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nT extern void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose ); /*=== sclUpsize.c ===============================================================*/ extern int Abc_SclCountNearCriticalNodes( SC_Man * p ); -extern void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ); +extern void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, void * pFuncFanin ); /*=== sclUtil.c ===============================================================*/ extern void Abc_SclMioGates2SclGates( SC_Lib * pLib, Abc_Ntk_t * p ); extern void Abc_SclSclGates2MioGates( SC_Lib * pLib, Abc_Ntk_t * p ); diff --git a/src/map/scl/sclUpsize.c b/src/map/scl/sclUpsize.c index 5c6307352..822278a33 100644 --- a/src/map/scl/sclUpsize.c +++ b/src/map/scl/sclUpsize.c @@ -865,7 +865,7 @@ void Abc_SclUpsizeRemoveDangling( SC_Man * p, Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -void Abc_SclUpsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ) +void Abc_SclUpsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, void * pFuncFanin ) { SC_Man * p; Vec_Int_t * vPathPos = NULL; // critical POs @@ -891,6 +891,7 @@ void Abc_SclUpsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPa pPars->Window += (Abc_NtkNodeNum(pNtk) > 40000); // prepare the manager; collect init stats p = Abc_SclManStart( pLib, pNtk, pPars->fUseWireLoads, pPars->fUseDept, 0, pPars->BuffTreeEst ); + p->pFuncFanin = (float (*)(void *, Abc_Obj_t *, Abc_Obj_t *, int, int))pFuncFanin; p->timeTotal = Abc_Clock(); assert( p->vGatesBest == NULL ); p->vGatesBest = Vec_IntDup( p->pNtk->vGates ); @@ -1024,12 +1025,12 @@ void Abc_SclUpsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPa SeeAlso [] ***********************************************************************/ -void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ) +void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, void * pFuncFanin ) { Abc_Ntk_t * pNtkNew = pNtk; if ( pNtk->nBarBufs2 > 0 ) pNtkNew = Abc_NtkDupDfsNoBarBufs( pNtk ); - Abc_SclUpsizePerformInt( pLib, pNtkNew, pPars ); + Abc_SclUpsizePerformInt( pLib, pNtkNew, pPars, pFuncFanin ); if ( pNtk->nBarBufs2 > 0 ) Abc_SclTransferGates( pNtk, pNtkNew ); if ( pNtk->nBarBufs2 > 0 ) diff --git a/src/misc/vec/vecBit.h b/src/misc/vec/vecBit.h index e41d95aa9..9b0af9d94 100644 --- a/src/misc/vec/vecBit.h +++ b/src/misc/vec/vecBit.h @@ -626,6 +626,27 @@ static inline void Vec_BitReset( Vec_Bit_t * p ) p->pArray[i] = 0; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_BitPrint( Vec_Bit_t * p ) +{ + int i, Entry; + printf( "Vector has %d entries: {", Vec_BitSize(p) ); + Vec_BitForEachEntry( p, Entry, i ) + printf( " %d", Entry ); + printf( " }\n" ); +} + ABC_NAMESPACE_HEADER_END #endif diff --git a/src/misc/vec/vecWrd.h b/src/misc/vec/vecWrd.h index aa16771ef..b0d16efe6 100644 --- a/src/misc/vec/vecWrd.h +++ b/src/misc/vec/vecWrd.h @@ -195,6 +195,32 @@ static inline Vec_Wrd_t * Vec_WrdStartTruthTables( int nVars ) } return p; } +static inline Vec_Wrd_t * Vec_WrdStartTruthTablesRev( int nVars ) +{ + Vec_Wrd_t * p; + unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + int i, k, nWords; + nWords = nVars <= 6 ? 1 : (1 << (nVars - 6)); + p = Vec_WrdStart( nWords * nVars ); + for ( i = 0; i < nVars; i++ ) + { + unsigned * pTruth = (unsigned *)(p->pArray + nWords * (nVars-1-i)); + if ( i < 5 ) + { + for ( k = 0; k < 2*nWords; k++ ) + pTruth[k] = Masks[i]; + } + else + { + for ( k = 0; k < 2*nWords; k++ ) + if ( k & (1 << (i-5)) ) + pTruth[k] = ~(unsigned)0; + else + pTruth[k] = 0; + } + } + return p; +} static inline int Vec_WrdShiftOne( Vec_Wrd_t * p, int nWords ) { int i, nObjs = p->nSize/nWords; diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index d11bca3c3..c9aa96658 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -120,6 +120,8 @@ struct Cec_ParFra_t_ int fVeryVerbose; // verbose stats int fVerbose; // verbose stats int iOutFail; // the failed output + int fBMiterInfo; // printing BMiter information + int nPO; // number of po in original design given a bmiter }; // combinational equivalence checking parameters diff --git a/src/proof/cec/cecProve.c b/src/proof/cec/cecProve.c new file mode 100644 index 000000000..b6325ea2c --- /dev/null +++ b/src/proof/cec/cecProve.c @@ -0,0 +1,341 @@ +/**CFile**************************************************************** + + FileName [cecSplit.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Cofactoring for combinational miters.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cecSplit.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "aig/gia/gia.h" +#include "aig/gia/giaAig.h" + +#include "sat/bmc/bmc.h" +#include "proof/pdr/pdr.h" +#include "proof/cec/cec.h" +#include "proof/ssw/ssw.h" + + +#ifdef ABC_USE_PTHREADS + +#ifdef _WIN32 +#include "../lib/pthread.h" +#else +#include +#include +#endif + +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Ssw_RarSimulateGia( Gia_Man_t * p, Ssw_RarPars_t * pPars ); +extern int Bmcg_ManPerform( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ); + +#ifndef ABC_USE_PTHREADS + +int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fVerbose, int fVeryVerbose, int fSilent ) { return -1; } + +#else // pthreads are used + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_GiaProveOne( Gia_Man_t * p, int iEngine, int nTimeOut, int fVerbose ) +{ + abctime clk = Abc_Clock(); + int RetValue = -1; + //abctime clkStop = nTimeOut * CLOCKS_PER_SEC + Abc_Clock(); + if ( fVerbose ) + printf( "Calling engine %d with timeout %d sec.\n", iEngine, nTimeOut ); + Abc_CexFreeP( &p->pCexSeq ); + if ( iEngine == 0 ) + { + Ssw_RarPars_t Pars, * pPars = &Pars; + Ssw_RarSetDefaultParams( pPars ); + pPars->TimeOut = nTimeOut; + pPars->fSilent = 1; + RetValue = Ssw_RarSimulateGia( p, pPars ); + } + else if ( iEngine == 1 ) + { + Saig_ParBmc_t Pars, * pPars = &Pars; + Saig_ParBmcSetDefaultParams( pPars ); + pPars->nTimeOut = nTimeOut; + pPars->fSilent = 1; + Aig_Man_t * pAig = Gia_ManToAigSimple( p ); + RetValue = Saig_ManBmcScalable( pAig, pPars ); + p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + } + else if ( iEngine == 2 ) + { + Pdr_Par_t Pars, * pPars = &Pars; + Pdr_ManSetDefaultParams( pPars ); + pPars->nTimeOut = nTimeOut; + pPars->fSilent = 1; + Aig_Man_t * pAig = Gia_ManToAigSimple( p ); + RetValue = Pdr_ManSolve( pAig, pPars ); + p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + } + else if ( iEngine == 3 ) + { + Saig_ParBmc_t Pars, * pPars = &Pars; + Saig_ParBmcSetDefaultParams( pPars ); + pPars->fUseGlucose = 1; + pPars->nTimeOut = nTimeOut; + pPars->fSilent = 1; + Aig_Man_t * pAig = Gia_ManToAigSimple( p ); + RetValue = Saig_ManBmcScalable( pAig, pPars ); + p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + } + else if ( iEngine == 4 ) + { + Pdr_Par_t Pars, * pPars = &Pars; + Pdr_ManSetDefaultParams( pPars ); + pPars->fUseAbs = 1; + pPars->nTimeOut = nTimeOut; + pPars->fSilent = 1; + Aig_Man_t * pAig = Gia_ManToAigSimple( p ); + RetValue = Pdr_ManSolve( pAig, pPars ); + p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + } + else if ( iEngine == 5 ) + { + Bmc_AndPar_t Pars, * pPars = &Pars; + memset( pPars, 0, sizeof(Bmc_AndPar_t) ); + pPars->nProcs = 1; // the number of parallel solvers + pPars->nFramesAdd = 1; // the number of additional frames + pPars->fNotVerbose = 1; // silent + pPars->nTimeOut = nTimeOut; // timeout in seconds + RetValue = Bmcg_ManPerform( p, pPars ); + } + else assert( 0 ); + //while ( Abc_Clock() < clkStop ); + if ( fVerbose ) { + printf( "Engine %d finished and %ssolved the problem. ", iEngine, RetValue != -1 ? " " : "not " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + return RetValue; +} +Gia_Man_t * Cec_GiaScorrOld( Gia_Man_t * p ) +{ + Ssw_Pars_t Pars, * pPars = &Pars; + Ssw_ManSetDefaultParams( pPars ); + Aig_Man_t * pAig = Gia_ManToAigSimple( p ); + Aig_Man_t * pAig2 = Ssw_SignalCorrespondence( pAig, pPars ); + Gia_Man_t * pGia2 = Gia_ManFromAigSimple( pAig2 ); + Aig_ManStop( pAig2 ); + Aig_ManStop( pAig ); + return pGia2; +} +Gia_Man_t * Cec_GiaScorrNew( Gia_Man_t * p ) +{ + Cec_ParCor_t Pars, * pPars = &Pars; + Cec_ManCorSetDefaultParams( pPars ); + pPars->nBTLimit = 100; + pPars->nLevelMax = 100; + pPars->fVerbose = 0; + pPars->fUseCSat = 1; + return Cec_ManLSCorrespondence( p, pPars ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +#define PAR_THR_MAX 8 +typedef struct Par_ThData_t_ +{ + Gia_Man_t * p; + int iEngine; + int fWorking; + int nTimeOut; + int Result; + int fVerbose; +} Par_ThData_t; +void * Cec_GiaProveWorkerThread( void * pArg ) +{ + Par_ThData_t * pThData = (Par_ThData_t *)pArg; + volatile int * pPlace = &pThData->fWorking; + while ( 1 ) + { + while ( *pPlace == 0 ); + assert( pThData->fWorking ); + if ( pThData->p == NULL ) + { + pthread_exit( NULL ); + assert( 0 ); + return NULL; + } + pThData->Result = Cec_GiaProveOne( pThData->p, pThData->iEngine, pThData->nTimeOut, pThData->fVerbose ); + pThData->fWorking = 0; + } + assert( 0 ); + return NULL; +} +void Cec_GiaInitThreads( Par_ThData_t * ThData, int nProcs, Gia_Man_t * p, int nTimeOut, int fVerbose, pthread_t * WorkerThread ) +{ + int i, status; + assert( nProcs <= PAR_THR_MAX ); + for ( i = 0; i < nProcs; i++ ) + { + ThData[i].p = Gia_ManDup(p); + ThData[i].iEngine = i; + ThData[i].nTimeOut = nTimeOut; + ThData[i].fWorking = 0; + ThData[i].Result = -1; + ThData[i].fVerbose = fVerbose; + if ( !WorkerThread ) + continue; + status = pthread_create( WorkerThread + i, NULL,Cec_GiaProveWorkerThread, (void *)(ThData + i) ); assert( status == 0 ); + } + for ( i = 0; i < nProcs; i++ ) + ThData[i].fWorking = 1; +} +int Cec_GiaWaitThreads( Par_ThData_t * ThData, int nProcs, Gia_Man_t * p, int RetValue, int * pRetEngine ) +{ + int i; + for ( i = 0; i < nProcs; i++ ) + { + if ( RetValue == -1 && !ThData[i].fWorking && ThData[i].Result != -1 ) { + RetValue = ThData[i].Result; + *pRetEngine = i; + if ( !p->pCexSeq && ThData[i].p->pCexSeq ) + p->pCexSeq = Abc_CexDup( ThData[i].p->pCexSeq, -1 ); + } + if ( ThData[i].fWorking ) + i = -1; + } + return RetValue; +} + +int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fVerbose, int fVeryVerbose, int fSilent ) +{ + abctime clkScorr = 0, clkTotal = Abc_Clock(); + Par_ThData_t ThData[PAR_THR_MAX]; + pthread_t WorkerThread[PAR_THR_MAX]; + int i, RetValue = -1, RetEngine = -2; + Abc_CexFreeP( &p->pCexComb ); + Abc_CexFreeP( &p->pCexSeq ); + if ( !fSilent && fVerbose ) + printf( "Solving verification problem with the following parameters:\n" ); + if ( !fSilent && fVerbose ) + printf( "Processes = %d TimeOut = %d sec Verbose = %d.\n", nProcs, nTimeOut, fVerbose ); + fflush( stdout ); + + assert( nProcs == 3 || nProcs == 5 ); + Cec_GiaInitThreads( ThData, nProcs, p, nTimeOut, fVerbose, WorkerThread ); + + // meanwhile, perform scorr + Gia_Man_t * pScorr = Cec_GiaScorrNew( p ); + clkScorr = Abc_Clock() - clkTotal; + if ( Gia_ManAndNum(pScorr) == 0 ) + RetValue = 1, RetEngine = -1; + + RetValue = Cec_GiaWaitThreads( ThData, nProcs, p, RetValue, &RetEngine ); + if ( RetValue == -1 ) + { + abctime clkScorr2, clkStart = Abc_Clock(); + if ( !fSilent && fVerbose ) { + printf( "Reduced the miter from %d to %d nodes. ", Gia_ManAndNum(p), Gia_ManAndNum(pScorr) ); + Abc_PrintTime( 1, "Time", clkScorr ); + } + Cec_GiaInitThreads( ThData, nProcs, pScorr, nTimeOut2, fVerbose, NULL ); + + // meanwhile, perform scorr + if ( Gia_ManAndNum(pScorr) < 100000 ) + { + Gia_Man_t * pScorr2 = Cec_GiaScorrOld( pScorr ); + clkScorr2 = Abc_Clock() - clkStart; + if ( Gia_ManAndNum(pScorr2) == 0 ) + RetValue = 1; + + RetValue = Cec_GiaWaitThreads( ThData, nProcs, p, RetValue, &RetEngine ); + if ( RetValue == -1 ) + { + if ( !fSilent && fVerbose ) { + printf( "Reduced the miter from %d to %d nodes. ", Gia_ManAndNum(pScorr), Gia_ManAndNum(pScorr2) ); + Abc_PrintTime( 1, "Time", clkScorr2 ); + } + Cec_GiaInitThreads( ThData, nProcs, pScorr2, nTimeOut3, fVerbose, NULL ); + + RetValue = Cec_GiaWaitThreads( ThData, nProcs, p, RetValue, &RetEngine ); + // do something else + } + Gia_ManStop( pScorr2 ); + } + } + Gia_ManStop( pScorr ); + + // stop threads + for ( i = 0; i < nProcs; i++ ) + { + ThData[i].p = NULL; + ThData[i].fWorking = 1; + } + if ( !fSilent ) + { + printf( "Problem \"%s\" is ", p->pSpec ); + if ( RetValue == 0 ) + printf( "SAT (solved by %d).", RetEngine ); + else if ( RetValue == 1 ) + printf( "UNSAT (solved by %d).", RetEngine ); + else if ( RetValue == -1 ) + printf( "UNDECIDED." ); + else assert( 0 ); + printf( " " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); + fflush( stdout ); + } + return RetValue; +} + +#endif // pthreads are used + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/cec/cecSatG2.c b/src/proof/cec/cecSatG2.c index 281deb0e9..b198c7ffe 100644 --- a/src/proof/cec/cecSatG2.c +++ b/src/proof/cec/cecSatG2.c @@ -219,6 +219,7 @@ void Cec4_ManSetParams( Cec_ParFra_t * pPars ) pPars->nSatVarMax = 1000; // the max number of SAT variables before recycling SAT solver pPars->nCallsRecycle = 500; // calls to perform before recycling SAT solver pPars->nGenIters = 100; // pattern generation iterations + pPars->fBMiterInfo = 0; // printing BMiter information } /**Function************************************************************* @@ -1781,8 +1782,10 @@ void Gia_ManRemoveWrongChoices( Gia_Man_t * p ) } //Abc_Print( 1, "Removed %d wrong choices.\n", Counter ); } + int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** ppNew, int fSimOnly ) { + Cec4_Man_t * pMan = Cec4_ManCreate( p, pPars ); Gia_Obj_t * pObj, * pRepr; int i, fSimulate = 1; @@ -1878,8 +1881,16 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p if ( pRepr == NULL ) continue; } + int id_obj = Gia_ObjId( p, pObj ); + int id_repr = Gia_ObjId( p, pRepr ); + if ( Abc_Lit2Var(pObj->Value) == Abc_Lit2Var(pRepr->Value) ) { + if ( pPars->fBMiterInfo ) + { + Bnd_ManMerge( id_repr, id_obj, pObj->fPhase ^ pRepr->fPhase ); + } + assert( (pObj->Value ^ pRepr->Value) == (pObj->fPhase ^ pRepr->fPhase) ); Gia_ObjSetProved( p, i ); if ( Gia_ObjId(p, pRepr) == 0 ) @@ -1887,8 +1898,26 @@ int Cec4_ManPerformSweeping( Gia_Man_t * p, Cec_ParFra_t * pPars, Gia_Man_t ** p continue; } if ( Cec4_ManSweepNode(pMan, i, Gia_ObjId(p, pRepr)) && Gia_ObjProved(p, i) ) + { + if (pPars->fBMiterInfo){ + + Bnd_ManMerge( id_repr, id_obj, pObj->fPhase ^ pRepr->fPhase ); + // printf( "proven %d merged into %d (phase : %d)\n", Gia_ObjId(p, pObj), Gia_ObjId(p,pRepr), pObj->fPhase ^ pRepr -> fPhase ); + + } pObj->Value = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); + + + } } + + if ( pPars->fBMiterInfo ) + { + // print + Bnd_ManFinalizeMappings(); + // Bnd_ManPrintMappings(); + } + if ( p->iPatsPi > 0 ) { abctime clk2 = Abc_Clock(); @@ -1937,6 +1966,7 @@ Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ) { Gia_Man_t * pNew = NULL; Cec4_ManPerformSweeping( p, pPars, &pNew, 0 ); + return pNew; } void Cec4_ManSimulateTest2( Gia_Man_t * p, int nConfs, int fVerbose ) diff --git a/src/proof/cec/module.make b/src/proof/cec/module.make index ed3dac110..ed8deba98 100644 --- a/src/proof/cec/module.make +++ b/src/proof/cec/module.make @@ -6,6 +6,7 @@ SRC += src/proof/cec/cecCec.c \ src/proof/cec/cecIso.c \ src/proof/cec/cecMan.c \ src/proof/cec/cecPat.c \ + src/proof/cec/cecProve.c \ src/proof/cec/cecSat.c \ src/proof/cec/cecSatG.c \ src/proof/cec/cecSatG2.c \ diff --git a/src/proof/pdr/pdrCore.c b/src/proof/pdr/pdrCore.c index 14bf89970..225b6b34a 100644 --- a/src/proof/pdr/pdrCore.c +++ b/src/proof/pdr/pdrCore.c @@ -1354,7 +1354,7 @@ int Pdr_ManSolveInt( Pdr_Man_t * p ) { if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); - if ( p->timeToStop && Abc_Clock() > p->timeToStop ) + if ( p->timeToStop && Abc_Clock() > p->timeToStop && !p->pPars->fSilent ) Abc_Print( 1, "Reached timeout (%d seconds) in frame %d.\n", p->pPars->nTimeOut, iFrame ); else if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC ) Abc_Print( 1, "Reached gap timeout (%d seconds) in frame %d.\n", p->pPars->nTimeOutGap, iFrame ); @@ -1379,7 +1379,7 @@ int Pdr_ManSolveInt( Pdr_Man_t * p ) { if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); - if ( p->timeToStop && Abc_Clock() > p->timeToStop ) + if ( p->timeToStop && Abc_Clock() > p->timeToStop && !p->pPars->fSilent ) Abc_Print( 1, "Reached timeout (%d seconds) in frame %d.\n", p->pPars->nTimeOut, iFrame ); else if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC ) Abc_Print( 1, "Reached gap timeout (%d seconds) in frame %d.\n", p->pPars->nTimeOutGap, iFrame ); diff --git a/src/proof/ssw/sswRarity.c b/src/proof/ssw/sswRarity.c index 1b7cab23d..679d30666 100644 --- a/src/proof/ssw/sswRarity.c +++ b/src/proof/ssw/sswRarity.c @@ -1040,8 +1040,10 @@ int Ssw_RarSimulate( Aig_Man_t * pAig, Ssw_RarPars_t * pPars ) Abc_Print( 1, "Simulated %d frames for %d rounds with %d restarts.\n", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart ); pAig->pSeqModel = Ssw_RarDeriveCex( p, r * p->pPars->nFrames + f, p->iFailPo, p->iFailPat, pPars->fVerbose ); // print final report - Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", pAig->pSeqModel->iPo, pAig->pName, pAig->pSeqModel->iFrame ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); + if ( !pPars->fSilent ) { + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", pAig->pSeqModel->iPo, pAig->pName, pAig->pSeqModel->iFrame ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); + } goto finish; } timeLastSolved = Abc_Clock(); diff --git a/src/sat/bmc/bmcBmcG.c b/src/sat/bmc/bmcBmcG.c index af141d303..e6205b19c 100644 --- a/src/sat/bmc/bmcBmcG.c +++ b/src/sat/bmc/bmcBmcG.c @@ -421,9 +421,11 @@ int Bmcg_ManPerformOne( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ) break; } p->timeOth = Abc_Clock() - clkStart - p->timeUnf - p->timeCnf - p->timeSmp - p->timeSat; - if ( RetValue == -1 && !pPars->fNotVerbose ) - printf( "No output failed in %d frames. ", f + (k < pPars->nFramesAdd ? k+1 : 0) ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + if ( !pPars->fNotVerbose ) { + if ( RetValue == -1 && !pPars->fNotVerbose ) + printf( "No output failed in %d frames. ", f + (k < pPars->nFramesAdd ? k+1 : 0) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + } Bmcg_ManPrintTime( p ); Bmcg_ManStop( p ); return RetValue; diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index 7a895950c..4d35c7de1 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -3728,10 +3728,170 @@ void Exa_ManExactSynthesis6( Bmc_EsPar_t * pPars, char * pFileName ) if ( pMini ) Mini_AigStop( pMini ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Exa7_AddClause( FILE * pFile, int * pLits, int nLits ) +{ + int i, k = 0; + for ( i = 0; i < nLits; i++ ) { + if ( pLits[i] == 1 ) + return 0; + else if ( pLits[i] == 0 ) + continue; + else + pLits[k++] = pLits[i]; + } + nLits = k; + assert( nLits > 0 ); + if ( pFile ) + { + for ( i = 0; i < nLits; i++ ) + fprintf( pFile, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i]) ); + fprintf( pFile, "0\n" ); + } + if ( 0 ) + { + for ( i = 0; i < nLits; i++ ) + fprintf( stdout, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i])-1 ); + fprintf( stdout, "\n" ); + } + return 1; +} +static inline int Exa7_AddClause4( FILE * pFile, int Lit0, int Lit1, int Lit2, int Lit3 ) +{ + int pLits[4] = { Lit0, Lit1, Lit2, Lit3 }; + return Exa7_AddClause( pFile, pLits, 4 ); +} +int Exa7_GetVar( int n, int i, int j, int m ) +{ + return 1 + n*n*m + n*i + j; +} +int Exa7_ManGenCnf( char * pFileName, word * pTruth, int nVars, int nNodes, int GateSize ) +{ + int m, n, v, k, nV = nVars + nNodes, nMints = 1 << nVars, nClas = 0; + int pVars[32] = {0}; assert( nVars + nNodes + 1 < 32 ); + FILE * pFile = fopen( pFileName, "wb" ); + fputs( "p cnf \n", pFile ); + for ( m = 0; m < nMints; m++ ) + { + for ( v = 0; v < nVars; v++ ) + nClas += Exa7_AddClause4( pFile, Abc_Var2Lit(Exa7_GetVar(nV, v, v, m), ((m >> v)&1)==0), 0, 0, 0 ); + nClas += Exa7_AddClause4( pFile, Abc_Var2Lit(Exa7_GetVar(nV, nV-1, nV-1, m), ((pTruth[0] >> m)&1)==0), 0, 0, 0 ); + for ( n = nVars; n < nV; n++ ) + { + int iValNode = Exa7_GetVar(nV, n, n, m); + for ( v = 0; v < n; v++ ) + { + int iParVar = Exa7_GetVar(nV, v, n, 0); // v < n + int iFanVar = Exa7_GetVar(nV, n, v, m); + int iValFan = Exa7_GetVar(nV, v, v, m); + // iFanVar = ~iParVar | iValFan + nClas += Exa7_AddClause4( pFile, Abc_Var2Lit(iFanVar, 1), Abc_Var2Lit(iParVar, 1), Abc_Var2Lit(iValFan, 0), 0 ); + nClas += Exa7_AddClause4( pFile, Abc_Var2Lit(iFanVar, 0), Abc_Var2Lit(iParVar, 0), 0, 0 ); + nClas += Exa7_AddClause4( pFile, Abc_Var2Lit(iFanVar, 0), Abc_Var2Lit(iValFan, 1), 0, 0 ); + // iParVar & ~iValFan => iValNode + nClas += Exa7_AddClause4( pFile, Abc_Var2Lit(iParVar, 1), Abc_Var2Lit(iValFan, 0), Abc_Var2Lit(iValNode, 0), 0 ); + pVars[v] = Abc_Var2Lit(iFanVar, 1); + } + pVars[v] = Abc_Var2Lit(iValNode, 1); + // (iFanVar0 & iFanVar1 & iFanVar2) => ~iValNode + nClas += Exa7_AddClause( pFile, pVars, n+1 ); + } + } + for ( n = nVars; n < nV; n++ ) { + for ( v = 0; v < n; v++ ) + pVars[v] = Abc_Var2Lit(Exa7_GetVar(nV, v, n, 0), 0); // v < n + nClas += Exa7_AddClause( pFile, pVars, n ); + if ( GateSize ) { + int Total = 1 << n, Limit = GateSize + 1; + for ( m = 0; m < Total; m++ ) + { + if ( Abc_TtCountOnes((word)m) != Limit ) + continue; + for ( k = v = 0; v < n; v++ ) + if ( (m >> v) & 1 ) + pVars[k++] = Abc_Var2Lit(Exa7_GetVar(nV, v, n, 0), 1); + assert( k == Limit ); + nClas += Exa7_AddClause( pFile, pVars, Limit ); + } + } + } + rewind( pFile ); + fprintf( pFile, "p cnf %d %d", nMints * nV * nV, nClas ); + fclose( pFile ); + return nClas; +} +void Exa_ManDumpVerilog( Vec_Int_t * vValues, int nVars, int nNodes, int GateSize, word * pTruth ) +{ + FILE * pFile; + char Buffer[1000]; + char FileName[1100]; + int v, n, k, nV = nVars+nNodes; + Extra_PrintHexadecimalString( Buffer, (unsigned *)pTruth, nVars ); + sprintf( FileName, "func%s_%d_%d.v", Buffer, GateSize, nNodes ); + pFile = fopen( FileName, "wb" ); + fprintf( pFile, "// Realization of the %d-input function %s using %d NAND gates:\n", nVars, Buffer, nNodes ); + fprintf( pFile, "module func%s_%d_%d ( input", Buffer, GateSize, nNodes ); + for ( v = 0; v < nVars; v++ ) + fprintf( pFile, " %c,", 'a'+v ); + fprintf( pFile, " output out );\n" ); + for ( n = nVars; n < nV; n++ ) { + int nFans = 0; + for ( v = 0; v < n; v++ ) + nFans += Vec_IntEntry(vValues, Exa7_GetVar(nV, v, n, 0)); + fprintf( pFile, " wire %c = ~(", 'a'+n ); + for ( k = v = 0; v < n; v++ ) + if ( Vec_IntEntry(vValues, Exa7_GetVar(nV, v, n, 0)) ) + fprintf( pFile, "%c%s", 'a'+v, ++k < nFans ? " & ":"" ); + fprintf( pFile, ");\n" ); + } + fprintf( pFile, " assign out = %c;\n", 'a'+nV-1 ); + fprintf( pFile, "endmodule\n\n" ); + fclose( pFile ); + printf( "Solution was dumped into file \"%s\".\n", FileName ); +} +void Exa_ManExactSynthesis7( Bmc_EsPar_t * pPars, int GateSize ) +{ + abctime clkTotal = Abc_Clock(); + int v, n, nMints = 1 << pPars->nVars; + int nV = pPars->nVars + pPars->nNodes; + word pTruth[16]; Abc_TtReadHex( pTruth, pPars->pTtStr ); + Vec_Int_t * vValues = NULL; + char * pFileNameIn = "_temp_.cnf"; + char * pFileNameOut = "_temp_out.cnf"; + int nClas = Exa7_ManGenCnf( pFileNameIn, pTruth, pPars->nVars, pPars->nNodes, GateSize ); + if ( pPars->fVerbose ) + printf( "CNF with %d variables and %d clauses was dumped into file \"%s\".\n", nMints * nV * nV, nClas, pFileNameIn ); + vValues = Exa4_ManSolve( pFileNameIn, pFileNameOut, pPars->RuntimeLim, pPars->fVerbose ); + if ( pPars->fVerbose && vValues ) { + printf( " " ); + for ( n = 0; n < nV; n++ ) + printf( "%2d ", n ); + printf( "\n" ); + for ( n = pPars->nVars; n < nV; n++, printf("\n") ) { + printf( "%2d : ", n ); + for ( v = 0; v < n; v++ ) + printf( " %c ", Vec_IntEntry(vValues, Exa7_GetVar(nV, v, n, 0)) ? '1':'.' ); // v < n + } + } + if ( vValues ) + Exa_ManDumpVerilog( vValues, pPars->nVars, pPars->nNodes, GateSize, pTruth ); + Vec_IntFreeP( &vValues ); + Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// - ABC_NAMESPACE_IMPL_END diff --git a/src/sat/bsat2/Alg.h b/src/sat/bsat2/Alg.h index 3e0745f1d..87004fce8 100644 --- a/src/sat/bsat2/Alg.h +++ b/src/sat/bsat2/Alg.h @@ -21,7 +21,9 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Alg_h #define Minisat_Alg_h -#include "Vec.h" +#include "sat/bsat2/Vec.h" + +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -81,4 +83,6 @@ static inline void append(const vec& from, vec& to){ copy(from, to, true); //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Alloc.h b/src/sat/bsat2/Alloc.h index 9a65cf0cd..1bf5784fc 100644 --- a/src/sat/bsat2/Alloc.h +++ b/src/sat/bsat2/Alloc.h @@ -21,8 +21,10 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Alloc_h #define Minisat_Alloc_h -#include "XAlloc.h" -#include "Vec.h" +#include "sat/bsat2/XAlloc.h" +#include "sat/bsat2/Vec.h" + +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -136,4 +138,6 @@ RegionAllocator::alloc(int size) //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Dimacs.h b/src/sat/bsat2/Dimacs.h index f26f152be..0e7ad925a 100644 --- a/src/sat/bsat2/Dimacs.h +++ b/src/sat/bsat2/Dimacs.h @@ -23,8 +23,10 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include -#include "ParseUtils.h" -#include "SolverTypes.h" +#include "sat/bsat2/ParseUtils.h" +#include "sat/bsat2/SolverTypes.h" + +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -86,4 +88,6 @@ static void parse_DIMACS(gzFile input_stream, Solver& S) { //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Heap.h b/src/sat/bsat2/Heap.h index e5b4ddb56..ae50c4b57 100644 --- a/src/sat/bsat2/Heap.h +++ b/src/sat/bsat2/Heap.h @@ -21,7 +21,9 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Heap_h #define Minisat_Heap_h -#include "Vec.h" +#include "sat/bsat2/Vec.h" + +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -146,4 +148,6 @@ class Heap { //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/IntTypes.h b/src/sat/bsat2/IntTypes.h index 1c011e83a..fdcd3d9f7 100644 --- a/src/sat/bsat2/IntTypes.h +++ b/src/sat/bsat2/IntTypes.h @@ -44,4 +44,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA //================================================================================================= +#include + #endif diff --git a/src/sat/bsat2/MainSat.cpp b/src/sat/bsat2/MainSat.cpp index 1f61f9eec..855466263 100644 --- a/src/sat/bsat2/MainSat.cpp +++ b/src/sat/bsat2/MainSat.cpp @@ -23,11 +23,13 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include "misc/zlib/zlib.h" -#include "System.h" -#include "ParseUtils.h" -#include "Options.h" -#include "Dimacs.h" -#include "Solver.h" +#include "sat/bsat2/System.h" +#include "sat/bsat2/ParseUtils.h" +#include "sat/bsat2/Options.h" +#include "sat/bsat2/Dimacs.h" +#include "sat/bsat2/Solver.h" + +ABC_NAMESPACE_IMPL_START using namespace Minisat; @@ -195,3 +197,6 @@ extern "C" int MainSat(int argc, char** argv) exit(0); } } + + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/bsat2/MainSimp.cpp b/src/sat/bsat2/MainSimp.cpp index 4a8909210..2d0ad109e 100644 --- a/src/sat/bsat2/MainSimp.cpp +++ b/src/sat/bsat2/MainSimp.cpp @@ -27,11 +27,13 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #endif -#include "System.h" -#include "ParseUtils.h" -#include "Options.h" -#include "Dimacs.h" -#include "SimpSolver.h" +#include "sat/bsat2/System.h" +#include "sat/bsat2/ParseUtils.h" +#include "sat/bsat2/Options.h" +#include "sat/bsat2/Dimacs.h" +#include "sat/bsat2/SimpSolver.h" + +ABC_NAMESPACE_IMPL_START using namespace Minisat; @@ -204,3 +206,6 @@ extern "C" int MainSimp(int argc, char** argv) exit(0); } } + + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/bsat2/Map.h b/src/sat/bsat2/Map.h index 1dd22a06d..374e76c9b 100644 --- a/src/sat/bsat2/Map.h +++ b/src/sat/bsat2/Map.h @@ -20,8 +20,10 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Map_h #define Minisat_Map_h -#include "IntTypes.h" -#include "Vec.h" +#include "sat/bsat2/IntTypes.h" +#include "sat/bsat2/Vec.h" + +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -190,4 +192,6 @@ class Map { //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Options.cpp b/src/sat/bsat2/Options.cpp index b30cff0e5..a0a3817d8 100644 --- a/src/sat/bsat2/Options.cpp +++ b/src/sat/bsat2/Options.cpp @@ -17,9 +17,11 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************************************/ -#include "Sort.h" -#include "Options.h" -#include "ParseUtils.h" +#include "sat/bsat2/Sort.h" +#include "sat/bsat2/Options.h" +#include "sat/bsat2/ParseUtils.h" + +ABC_NAMESPACE_IMPL_START using namespace Minisat; @@ -43,10 +45,12 @@ int Minisat::parseOptions(int& argc, char** argv, bool strict) } if (!parsed_ok) + { if (strict && match(argv[i], "-")) { fprintf(stderr, "ERROR! Unknown flag \"%s\". Use '--%shelp' for help.\n", argv[i], Option::getHelpPrefixString()); return 0; } // exit(0); else argv[j++] = argv[i]; + } } } @@ -91,3 +95,5 @@ int Minisat::printUsageAndExit (int argc, char** argv, bool verbose) return 0; } + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/bsat2/Options.h b/src/sat/bsat2/Options.h index 439cb8f21..00d46d352 100644 --- a/src/sat/bsat2/Options.h +++ b/src/sat/bsat2/Options.h @@ -25,9 +25,11 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include -#include "IntTypes.h" -#include "Vec.h" -#include "ParseUtils.h" +#include "sat/bsat2/IntTypes.h" +#include "sat/bsat2/Vec.h" +#include "sat/bsat2/ParseUtils.h" + +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -60,7 +62,7 @@ class Option struct OptionLt { bool operator()(const Option* x, const Option* y) { int test1 = strcmp(x->category, y->category); - return test1 < 0 || test1 == 0 && strcmp(x->type_name, y->type_name) < 0; + return test1 < 0 || ( test1 == 0 && strcmp(x->type_name, y->type_name) < 0 ); } }; @@ -384,4 +386,6 @@ class BoolOption : public Option //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/ParseUtils.h b/src/sat/bsat2/ParseUtils.h index 8e0f9c890..b7325f174 100644 --- a/src/sat/bsat2/ParseUtils.h +++ b/src/sat/bsat2/ParseUtils.h @@ -26,6 +26,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "misc/zlib/zlib.h" +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { //------------------------------------------------------------------------------------------------- @@ -119,4 +121,6 @@ static bool eagerMatch(B& in, const char* str) { //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Queue.h b/src/sat/bsat2/Queue.h index 11b429115..8ff65b87b 100644 --- a/src/sat/bsat2/Queue.h +++ b/src/sat/bsat2/Queue.h @@ -21,7 +21,9 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Queue_h #define Minisat_Queue_h -#include "Vec.h" +#include "sat/bsat2/Vec.h" + +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -66,4 +68,6 @@ public: //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/SimpSolver.cpp b/src/sat/bsat2/SimpSolver.cpp index 5a7a006c2..c07ec5b97 100644 --- a/src/sat/bsat2/SimpSolver.cpp +++ b/src/sat/bsat2/SimpSolver.cpp @@ -18,9 +18,11 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************************************/ -#include "Sort.h" -#include "SimpSolver.h" -#include "System.h" +#include "sat/bsat2/Sort.h" +#include "sat/bsat2/SimpSolver.h" +#include "sat/bsat2/System.h" + +ABC_NAMESPACE_IMPL_START using namespace Minisat; @@ -228,10 +230,12 @@ bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, vec& ou if (var(qs[i]) != v){ for (j = 0; j < ps.size(); j++) if (var(ps[j]) == var(qs[i])) + { if (ps[j] == ~qs[i]) return false; else goto next; + } out_clause.push(qs[i]); } next:; @@ -262,10 +266,12 @@ bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, int& size) if (var(__qs[i]) != v){ for (int j = 0; j < ps.size(); j++) if (var(__ps[j]) == var(__qs[i])) + { if (__ps[j] == ~__qs[i]) return false; else goto next; + } size++; } next:; @@ -718,3 +724,5 @@ void SimpSolver::garbageCollect() ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size); to.moveTo(ca); } + +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/sat/bsat2/SimpSolver.h b/src/sat/bsat2/SimpSolver.h index e24b0e430..ad02c6dff 100644 --- a/src/sat/bsat2/SimpSolver.h +++ b/src/sat/bsat2/SimpSolver.h @@ -21,9 +21,10 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_SimpSolver_h #define Minisat_SimpSolver_h -#include "Queue.h" -#include "Solver.h" +#include "sat/bsat2/Queue.h" +#include "sat/bsat2/Solver.h" +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -194,4 +195,6 @@ inline lbool SimpSolver::solveLimited (const vec& assumps, bool do_simp, bo //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Solver.cpp b/src/sat/bsat2/Solver.cpp index 0f8b415a9..602692a8b 100644 --- a/src/sat/bsat2/Solver.cpp +++ b/src/sat/bsat2/Solver.cpp @@ -20,8 +20,10 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include -#include "Sort.h" -#include "Solver.h" +#include "sat/bsat2/Sort.h" +#include "sat/bsat2/Solver.h" + +ABC_NAMESPACE_IMPL_START using namespace Minisat; @@ -209,7 +211,7 @@ void Solver::cancelUntil(int level) { for (int c = trail.size()-1; c >= trail_lim[level]; c--){ Var x = var(trail[c]); assigns [x] = l_Undef; - if (phase_saving > 1 || (phase_saving == 1) && c > trail_lim.last()) + if (phase_saving > 1 || ((phase_saving == 1) && c > trail_lim.last())) polarity[x] = sign(trail[c]); insertVarOrder(x); } qhead = trail_lim[level]; @@ -657,7 +659,7 @@ lbool Solver::search(int nof_conflicts) }else{ // NO CONFLICT - if (nof_conflicts >= 0 && conflictC >= nof_conflicts || !withinBudget()){ + if ( (nof_conflicts >= 0 && conflictC >= nof_conflicts) || !withinBudget()){ // Reached bound on number of conflicts: progress_estimate = progressEstimate(); cancelUntil(0); @@ -922,3 +924,5 @@ void Solver::garbageCollect() ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size); to.moveTo(ca); } + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/bsat2/Solver.h b/src/sat/bsat2/Solver.h index fc0bb4ba2..9c9a30ee3 100644 --- a/src/sat/bsat2/Solver.h +++ b/src/sat/bsat2/Solver.h @@ -21,12 +21,13 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Solver_h #define Minisat_Solver_h -#include "Vec.h" -#include "Heap.h" -#include "Alg.h" -#include "Options.h" -#include "SolverTypes.h" +#include "sat/bsat2/Vec.h" +#include "sat/bsat2/Heap.h" +#include "sat/bsat2/Alg.h" +#include "sat/bsat2/Options.h" +#include "sat/bsat2/SolverTypes.h" +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -370,4 +371,6 @@ inline void Solver::toDimacs (const char* file, Lit p, Lit q, Lit r){ ve //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/SolverTypes.h b/src/sat/bsat2/SolverTypes.h index f34deca1c..64fbe980e 100644 --- a/src/sat/bsat2/SolverTypes.h +++ b/src/sat/bsat2/SolverTypes.h @@ -24,11 +24,13 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include -#include "IntTypes.h" -#include "Alg.h" -#include "Vec.h" -#include "Map.h" -#include "Alloc.h" +#include "sat/bsat2/IntTypes.h" +#include "sat/bsat2/Alg.h" +#include "sat/bsat2/Vec.h" +#include "sat/bsat2/Map.h" +#include "sat/bsat2/Alloc.h" + +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -404,4 +406,6 @@ inline void Clause::strengthen(Lit p) //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/Sort.h b/src/sat/bsat2/Sort.h index cc96486d8..7ce99ea46 100644 --- a/src/sat/bsat2/Sort.h +++ b/src/sat/bsat2/Sort.h @@ -21,11 +21,12 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #ifndef Minisat_Sort_h #define Minisat_Sort_h -#include "Vec.h" +#include "sat/bsat2/Vec.h" //================================================================================================= // Some sorting algorithms for vec's +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -95,4 +96,6 @@ template void sort(vec& v) { //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/System.cpp b/src/sat/bsat2/System.cpp index c2d6259e2..2c64e7fea 100644 --- a/src/sat/bsat2/System.cpp +++ b/src/sat/bsat2/System.cpp @@ -18,13 +18,15 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************************************/ -#include "System.h" +#include "sat/bsat2/System.h" #if defined(__linux__) #include #include +ABC_NAMESPACE_IMPL_START + using namespace Minisat; // TODO: split the memory reading functions into two: one for reading high-watermark of RSS, and @@ -72,24 +74,40 @@ double Minisat::memUsedPeak() { double peak = memReadPeak() / 1024; return peak == 0 ? memUsed() : peak; } +ABC_NAMESPACE_IMPL_END + #elif defined(__FreeBSD__) +ABC_NAMESPACE_IMPL_START + double Minisat::memUsed(void) { struct rusage ru; getrusage(RUSAGE_SELF, &ru); return (double)ru.ru_maxrss / 1024; } double MiniSat::memUsedPeak(void) { return memUsed(); } +ABC_NAMESPACE_IMPL_END #elif defined(__APPLE__) #include +ABC_NAMESPACE_IMPL_START + double Minisat::memUsed(void) { malloc_statistics_t t; malloc_zone_statistics(NULL, &t); return (double)t.max_size_in_use / (1024*1024); } +ABC_NAMESPACE_IMPL_END + #else + +ABC_NAMESPACE_IMPL_START + double Minisat::memUsed() { return 0; } double Minisat::memUsedPeak() { return 0; } + +ABC_NAMESPACE_IMPL_END + #endif + diff --git a/src/sat/bsat2/System.h b/src/sat/bsat2/System.h index d776c880c..f5ed5fa13 100644 --- a/src/sat/bsat2/System.h +++ b/src/sat/bsat2/System.h @@ -22,13 +22,15 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #define Minisat_System_h #if defined(__linux__) -#include +//#include #endif -#include "IntTypes.h" +#include "sat/bsat2/IntTypes.h" //------------------------------------------------------------------------------------------------- +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { static inline double cpuTime(void); // CPU-time in seconds. @@ -37,24 +39,35 @@ extern double memUsedPeak(); // Peak-memory in mega bytes (returns 0 for } +ABC_NAMESPACE_CXX_HEADER_END + //------------------------------------------------------------------------------------------------- // Implementation of inline functions: #if defined(_MSC_VER) || defined(__MINGW32__) #include +ABC_NAMESPACE_CXX_HEADER_START + static inline double Minisat::cpuTime(void) { return (double)clock() / CLOCKS_PER_SEC; } +ABC_NAMESPACE_CXX_HEADER_END + #else #include #include #include +ABC_NAMESPACE_CXX_HEADER_START + static inline double Minisat::cpuTime(void) { struct rusage ru; getrusage(RUSAGE_SELF, &ru); return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; } -#endif +ABC_NAMESPACE_CXX_HEADER_END + +#endif + #endif diff --git a/src/sat/bsat2/Vec.h b/src/sat/bsat2/Vec.h index 5eea6174b..6937d7256 100644 --- a/src/sat/bsat2/Vec.h +++ b/src/sat/bsat2/Vec.h @@ -24,8 +24,10 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include -#include "IntTypes.h" -#include "XAlloc.h" +#include "sat/bsat2/IntTypes.h" +#include "sat/bsat2/XAlloc.h" + +ABC_NAMESPACE_CXX_HEADER_START namespace Minisat { @@ -91,7 +93,6 @@ public: void moveTo(vec& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; } }; - template void vec::capacity(int min_cap) { if (cap >= min_cap) return; @@ -131,4 +132,6 @@ void vec::clear(bool dealloc) { //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/XAlloc.h b/src/sat/bsat2/XAlloc.h index 33741e332..3e9e39674 100644 --- a/src/sat/bsat2/XAlloc.h +++ b/src/sat/bsat2/XAlloc.h @@ -24,6 +24,10 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include #include +#include + +ABC_NAMESPACE_CXX_HEADER_START + namespace Minisat { //================================================================================================= @@ -46,4 +50,6 @@ static inline void* xrealloc(void *ptr, size_t size) //================================================================================================= } +ABC_NAMESPACE_CXX_HEADER_END + #endif diff --git a/src/sat/bsat2/module.make b/src/sat/bsat2/module.make index ddd11b1b9..87cdc11ca 100644 --- a/src/sat/bsat2/module.make +++ b/src/sat/bsat2/module.make @@ -1,6 +1,4 @@ SRC += src/sat/bsat2/AbcApi.cpp \ - src/sat/bsat2/MainSat.cpp \ - src/sat/bsat2/MainSimp.cpp \ src/sat/bsat2/Options.cpp \ src/sat/bsat2/SimpSolver.cpp \ src/sat/bsat2/Solver.cpp \ diff --git a/src/sat/glucose/AbcGlucose.cpp b/src/sat/glucose/AbcGlucose.cpp index cbaedbe62..d6f4c454d 100644 --- a/src/sat/glucose/AbcGlucose.cpp +++ b/src/sat/glucose/AbcGlucose.cpp @@ -885,7 +885,7 @@ Vec_Int_t * Glucose_SolverFromAig( Gia_Man_t * p, SimpSolver& s ) lits->push( toLit(*pLit) ), s.addVar( *pLit >> 1 ); s.addClause(*lits); } - Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums,pCnf->nVars); + Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums, Gia_ManObjNum(p)); printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Cnf_DataFree(pCnf); @@ -899,7 +899,7 @@ Vec_Int_t * Glucose_SolverFromAig2( Gia_Man_t * p, SimpSolver& S ) for ( int i = 0; i < pCnf->nClauses; i++ ) if ( !glucose_solver_addclause( &S, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) ) assert( 0 ); - Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums,pCnf->nVars); + Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums, Gia_ManObjNum(p)); //printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); //Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Cnf_DataFree(pCnf); diff --git a/src/sat/glucose/Glucose.cpp b/src/sat/glucose/Glucose.cpp index cfb388de6..d878e0d17 100644 --- a/src/sat/glucose/Glucose.cpp +++ b/src/sat/glucose/Glucose.cpp @@ -1124,7 +1124,7 @@ lbool Solver::search(int nof_conflicts) return l_False; } // Perform clause database reduction ! - if(conflicts>=curRestart* nbclausesbeforereduce) + if(conflicts>=curRestart* nbclausesbeforereduce && learnts.size()>0) { assert(learnts.size()>0); diff --git a/src/sat/glucose2/AbcGlucose2.cpp b/src/sat/glucose2/AbcGlucose2.cpp index 0e4871187..6201779cb 100644 --- a/src/sat/glucose2/AbcGlucose2.cpp +++ b/src/sat/glucose2/AbcGlucose2.cpp @@ -903,7 +903,7 @@ Vec_Int_t * Glucose_SolverFromAig( Gia_Man_t * p, SimpSolver& s ) lits->push( toLit(*pLit) ), s.addVar( *pLit >> 1 ); s.addClause(*lits); } - Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums,pCnf->nVars); + Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums, Gia_ManObjNum(p)); printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Cnf_DataFree(pCnf); @@ -917,7 +917,7 @@ Vec_Int_t * Glucose_SolverFromAig2( Gia_Man_t * p, SimpSolver& S ) for ( int i = 0; i < pCnf->nClauses; i++ ) if ( !glucose2_solver_addclause( &S, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) ) assert( 0 ); - Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums,pCnf->nVars); + Vec_Int_t * vCnfIds = Vec_IntAllocArrayCopy(pCnf->pVarNums, Gia_ManObjNum(p)); //printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); //Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Cnf_DataFree(pCnf);