diff --git a/.github/scripts/abcexe.vcxproj b/.github/scripts/abcexe.vcxproj index 817e0809ef..9500210171 100644 --- a/.github/scripts/abcexe.vcxproj +++ b/.github/scripts/abcexe.vcxproj @@ -33,6 +33,7 @@ Level3 4146;4334;4996;4703;%(DisableSpecificWarnings) + 4013 true true true diff --git a/.github/scripts/abclib.vcxproj.template b/.github/scripts/abclib.vcxproj.template index 77498528db..9b21d325f2 100644 --- a/.github/scripts/abclib.vcxproj.template +++ b/.github/scripts/abclib.vcxproj.template @@ -32,6 +32,7 @@ Level3 4146;4334;4996;4703;%(DisableSpecificWarnings) + 4013 true true true diff --git a/.gitignore b/.gitignore index 7236839d31..e2e5e555c3 100644 --- a/.gitignore +++ b/.gitignore @@ -8,11 +8,14 @@ ReleaseExt/ _/ _TEST/ +tools/ +temp/ lib/abc* lib/m114* lib/bip* docs/ .cache/ +.vscode/ src/ext* src/xxx/ @@ -62,4 +65,4 @@ tags /cmake /cscope -abc.history \ No newline at end of file +abc.history diff --git a/Makefile b/Makefile index eeff20d24d..8a8058500e 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ MODULES := \ 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/if/acd \ - src/map/amap src/map/cov src/map/scl src/map/mpm \ + src/map/amap src/map/cov src/map/scl src/map/mpm src/map/emap \ 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 \ src/misc/mem src/misc/bar src/misc/bbl src/misc/parse src/misc/btor \ @@ -185,32 +185,32 @@ DEP := $(OBJ:.o=.d) %.o: %.c @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< - $(VERBOSE)$(CC) -c $(OPTFLAGS) $(INCLUDES) $(CFLAGS) $< -o $@ + $(VERBOSE)$(CC) -c $(OPTFLAGS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $< -o $@ %.o: %.cc @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< - $(VERBOSE)$(CXX) -c $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< -o $@ + $(VERBOSE)$(CXX) -c $(OPTFLAGS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS) $< -o $@ %.o: %.cpp @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< - $(VERBOSE)$(CXX) -c $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< -o $@ + $(VERBOSE)$(CXX) -c $(OPTFLAGS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS) $< -o $@ %.d: %.c @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< - $(VERBOSE)$(ABCSRC)/depends.sh "$(CC)" `dirname $*.c` $(OPTFLAGS) $(INCLUDES) $(CFLAGS) $< > $@ + $(VERBOSE)$(ABCSRC)/depends.sh "$(CC)" `dirname $*.c` $(OPTFLAGS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $< > $@ %.d: %.cc @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< - $(VERBOSE)$(ABCSRC)/depends.sh "$(CXX)" `dirname $*.cc` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< > $@ + $(VERBOSE)$(ABCSRC)/depends.sh "$(CXX)" `dirname $*.cc` $(OPTFLAGS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS) $< > $@ %.d: %.cpp @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< - $(VERBOSE)$(ABCSRC)/depends.sh "$(CXX)" `dirname $*.cpp` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< > $@ + $(VERBOSE)$(ABCSRC)/depends.sh "$(CXX)" `dirname $*.cpp` $(OPTFLAGS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS) $< > $@ ifndef ABC_MAKE_NO_DEPS -include $(DEP) diff --git a/abclib.dsp b/abclib.dsp index 321b851dfc..9a01de2b19 100644 --- a/abclib.dsp +++ b/abclib.dsp @@ -443,6 +443,10 @@ SOURCE=.\src\base\abci\abcResub.c # End Source File # Begin Source File +SOURCE=.\src\base\abci\abcRmInverters.c +# End Source File +# Begin Source File + SOURCE=.\src\base\abci\abcRewrite.c # End Source File # Begin Source File @@ -4194,6 +4198,26 @@ SOURCE=.\src\opt\sbd\sbdWin.c # PROP Default_Filter "" # Begin Source File +SOURCE=.\src\opt\eslim\areaEngine.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\areaEngine.hpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\cadicalSolver.hpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\delayEngine.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\delayEngine.hpp +# End Source File +# Begin Source File + SOURCE=.\src\opt\eslim\eSLIM.cpp # End Source File # Begin Source File @@ -4202,6 +4226,14 @@ SOURCE=.\src\opt\eslim\eSLIM.h # End Source File # Begin Source File +SOURCE=.\src\opt\eslim\eslimCirMan.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\eslimCirMan.hpp +# End Source File +# Begin Source File + SOURCE=.\src\opt\eslim\eSLIMMan.hpp # End Source File # Begin Source File @@ -4214,11 +4246,31 @@ SOURCE=.\src\opt\eslim\relationGeneration.hpp # End Source File # Begin Source File -SOURCE=.\src\opt\eslim\satInterfaces.hpp +SOURCE=.\src\opt\eslim\relationSynthesiser.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\relationSynthesiser.hpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\selectionStrategies.hpp # End Source File # Begin Source File -SOURCE=.\src\opt\eslim\selectionStrategy.hpp +SOURCE=.\src\opt\eslim\subcircuit.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\subcircuit.hpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\synthesisEngines.hpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\tabooList.hpp # End Source File # Begin Source File @@ -4226,7 +4278,7 @@ SOURCE=.\src\opt\eslim\utils.hpp # End Source File # Begin Source File -SOURCE=.\src\opt\eslim\synthesisEngine.hpp +SOURCE=.\src\opt\eslim\windowMan.hpp # End Source File # End Group # End Group @@ -4753,6 +4805,22 @@ SOURCE=.\src\map\mpm\mpmTruth.c SOURCE=.\src\map\mpm\mpmUtil.c # End Source File # End Group +# Begin Group "emap" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\emap\emap.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\emap\emap.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\emap\emapCore.c +# End Source File +# End Group # End Group # Begin Group "misc" @@ -6617,6 +6685,18 @@ SOURCE=.\src\proof\cec\cecCorr.c # End Source File # Begin Source File +SOURCE=.\src\proof\cec\cecCorrDyn.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecCorrIncr.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecCorrIncrSim.c +# End Source File +# Begin Source File + SOURCE=.\src\proof\cec\cecInt.h # End Source File # Begin Source File diff --git a/src/aig/gia/gia.h b/src/aig/gia/gia.h index 6fddcac96b..7cc583cbbe 100644 --- a/src/aig/gia/gia.h +++ b/src/aig/gia/gia.h @@ -30,6 +30,7 @@ #include #include #include +#include #include "misc/vec/vec.h" #include "misc/vec/vecWec.h" @@ -45,6 +46,35 @@ ABC_NAMESPACE_HEADER_START #define GIA_NONE 0x1FFFFFFF #define GIA_VOID 0x0FFFFFFF +// Multi-origin tracking: small-buffer optimization with overflow +#ifndef GIA_ORIGINS_INLINE +#define GIA_ORIGINS_INLINE 4 // number of inline origin slots (configurable at compile time) +#endif + +typedef union { + struct { + int origins[GIA_ORIGINS_INLINE]; // -1 = unused slot + } inl; + struct { + int sentinel; // INT_MIN marks overflow mode + int count; // number of origins in overflow array + int * overflow; // heap-allocated origin array + } ovf; +} Gia_OriginsEntry_t; + +#define GIA_ORIGINS_STRIDE ((int)(sizeof(Gia_OriginsEntry_t) / sizeof(int))) +#define GIA_ORIGINS_SENTINEL INT_MIN + +// Compile-time checks: inline slots must cover the overflow header +// (sentinel + count + pointer; minimum 4 ints on 64-bit), and must +// not exceed the hardcoded initial overflow capacity of 8. +#if GIA_ORIGINS_INLINE < 4 +# error "GIA_ORIGINS_INLINE must be >= 4 (overflow header needs sentinel+count+ptr, min 4 ints on 64-bit)" +#endif +#if GIA_ORIGINS_INLINE > 7 +# error "GIA_ORIGINS_INLINE must be <= 7 (initial overflow capacity is 8)" +#endif + //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// @@ -190,6 +220,8 @@ struct Gia_Man_t_ Vec_Int_t * vIdsOrig; // original object IDs Vec_Int_t * vIdsEquiv; // original object IDs proved equivalent Vec_Int_t * vEquLitIds; // original object IDs proved equivalent + Vec_Int_t * vOrigins; // per-object origin mapping (from "y" extension) + int nOriginsMax; // max origins per object (0 = unlimited) Vec_Int_t * vCofVars; // cofactoring variables Vec_Vec_t * vClockDoms; // clock domains Vec_Flt_t * vTiming; // arrival/required/slack @@ -462,6 +494,78 @@ static inline int Gia_ManIsConst0Lit( int iLit ) { return (iLit == static inline int Gia_ManIsConst1Lit( int iLit ) { return (iLit == 1); } static inline int Gia_ManIsConstLit( int iLit ) { return (iLit <= 1); } +// Multi-origin accessors +static inline Gia_OriginsEntry_t * Gia_ObjOriginsEntry( Gia_Man_t * p, int iObj ) +{ + return (Gia_OriginsEntry_t *)(Vec_IntArray(p->vOrigins) + iObj * GIA_ORIGINS_STRIDE); +} +static inline int Gia_ObjOriginsIsOverflow( Gia_OriginsEntry_t * e ) +{ + return e->inl.origins[0] == GIA_ORIGINS_SENTINEL; +} +static inline int Gia_ObjOriginsNum( Gia_Man_t * p, int iObj ) +{ + Gia_OriginsEntry_t * e; + int k; + if ( !p->vOrigins || iObj * GIA_ORIGINS_STRIDE >= Vec_IntSize(p->vOrigins) ) + return 0; + e = Gia_ObjOriginsEntry( p, iObj ); + if ( Gia_ObjOriginsIsOverflow(e) ) + return e->ovf.count; + for ( k = 0; k < GIA_ORIGINS_INLINE; k++ ) + if ( e->inl.origins[k] == -1 ) break; + return k; +} +static inline int Gia_ObjOriginsGet( Gia_Man_t * p, int iObj, int idx ) +{ + Gia_OriginsEntry_t * e; + if ( !p->vOrigins || iObj * GIA_ORIGINS_STRIDE >= Vec_IntSize(p->vOrigins) ) + return -1; + e = Gia_ObjOriginsEntry( p, iObj ); + if ( Gia_ObjOriginsIsOverflow(e) ) + return (idx < e->ovf.count) ? e->ovf.overflow[idx] : -1; + return (idx < GIA_ORIGINS_INLINE) ? e->inl.origins[idx] : -1; +} +// Backward compatible: get first/primary origin +static inline int Gia_ObjOrigin( Gia_Man_t * p, int iObj ) +{ + Gia_OriginsEntry_t * e; + if ( !p->vOrigins || iObj * GIA_ORIGINS_STRIDE >= Vec_IntSize(p->vOrigins) ) + return -1; + e = Gia_ObjOriginsEntry( p, iObj ); + if ( Gia_ObjOriginsIsOverflow(e) ) + return e->ovf.count > 0 ? e->ovf.overflow[0] : -1; + return e->inl.origins[0]; +} +// Set single origin (clears any existing, for initialization) +static inline void Gia_ObjSetOrigin( Gia_Man_t * p, int iObj, int iOrig ) +{ + Gia_OriginsEntry_t * e; + int k; + if ( !p->vOrigins || iObj * GIA_ORIGINS_STRIDE >= Vec_IntSize(p->vOrigins) ) + return; + e = Gia_ObjOriginsEntry( p, iObj ); + if ( Gia_ObjOriginsIsOverflow(e) && e->ovf.overflow ) + ABC_FREE( e->ovf.overflow ); + e->inl.origins[0] = iOrig; + for ( k = 1; k < GIA_ORIGINS_INLINE; k++ ) + e->inl.origins[k] = -1; +} +// Grow vOrigins to accommodate object iObj +static inline void Gia_ManOriginsGrow( Gia_Man_t * p, int iObj ) +{ + Vec_IntFillExtra( p->vOrigins, (iObj + 1) * GIA_ORIGINS_STRIDE, -1 ); +} +// Allocate vOrigins for nObjs objects (all entries initialized to -1) +static inline Vec_Int_t * Gia_ManOriginsAlloc( int nObjs ) +{ + return Vec_IntStartFull( nObjs * GIA_ORIGINS_STRIDE ); +} +// Iteration macro (caller must declare int _nOrig before use, or use nOrig variant) +#define Gia_ObjForEachOrigin( p, iObj, orig, idx ) \ + for ( idx = 0, _nOrig = Gia_ObjOriginsNum(p, iObj); \ + (idx < _nOrig) && ((orig = Gia_ObjOriginsGet(p, iObj, idx)), 1); idx++ ) + static inline Gia_Obj_t * Gia_Regular( Gia_Obj_t * p ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Gia_Obj_t * Gia_Not( Gia_Obj_t * p ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Gia_Obj_t * Gia_NotCond( Gia_Obj_t * p, int c ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } @@ -1312,10 +1416,14 @@ extern void Cbs_ManStop( Cbs_Man_t * p ); extern int Cbs_ManSolve( Cbs_Man_t * p, Gia_Obj_t * pObj ); extern int Cbs_ManSolve2( Cbs_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ); extern Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose ); +extern Vec_Int_t * Cbs_ManSolveMiterNcOutVals( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose, Vec_Int_t * vOutLits, Vec_Int_t ** pvOutVals ); +extern void Cbs_ManSyncCore( Cbs_Man_t * p ); +extern Vec_Int_t * Cbs_ManSolveRoots( Cbs_Man_t * p, Vec_Int_t * vRootLits, Vec_Str_t ** pvStatus, int fVerbose ); extern void Cbs_ManSetConflictNum( Cbs_Man_t * p, int Num ); extern Vec_Int_t * Cbs_ReadModel( Cbs_Man_t * p ); /*=== giaCTas.c ============================================================*/ extern Vec_Int_t * Tas_ManSolveMiterNc( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); +extern Vec_Int_t * Tas_ManSolveMiterNcOutVals( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose, Vec_Int_t * vOutLits, Vec_Int_t ** pvOutVals ); /*=== giaCof.c =============================================================*/ extern void Gia_ManPrintFanio( Gia_Man_t * pGia, int nNodes ); extern Gia_Man_t * Gia_ManDupCof( Gia_Man_t * p, int iVar ); @@ -1348,6 +1456,15 @@ extern Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p, int fRevFan extern Gia_Man_t * Gia_ManDupOutputGroup( Gia_Man_t * p, int iOutStart, int iOutStop ); extern Gia_Man_t * Gia_ManDupOutputVec( Gia_Man_t * p, Vec_Int_t * vOutPres ); extern Gia_Man_t * Gia_ManDupSelectedOutputs( Gia_Man_t * p, Vec_Int_t * vOutsLeft ); +extern void Gia_ObjAddOrigin( Gia_Man_t * p, int iObj, int iOrig ); +extern void Gia_ObjUnionOrigins( Gia_Man_t * p, int iDst, Gia_Man_t * pSrc, int iSrc ); +extern void Gia_ManOriginsFreeOverflows( Gia_Man_t * p ); +extern void Gia_ManOriginsReset( Gia_Man_t * p ); +extern void Gia_ManOriginsDup( Gia_Man_t * pNew, Gia_Man_t * pOld ); +extern void Gia_ManOriginsDupFill( Gia_Man_t * pNew, Gia_Man_t * pOld ); +extern void Gia_ManOriginsDupVec( Gia_Man_t * pNew, Gia_Man_t * pOld, Vec_Int_t * vCopies ); +extern void Gia_ManOriginsAfterRoundTrip( Gia_Man_t * pNew, Gia_Man_t * pOld ); +extern void Gia_ManOriginsDupIf( Gia_Man_t * pNew, Gia_Man_t * p, void * pIfMan ); extern Gia_Man_t * Gia_ManDupOrderAiger( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupLastPis( Gia_Man_t * p, int nLastPis ); extern Gia_Man_t * Gia_ManDupFlip( Gia_Man_t * p, int * pInitState ); diff --git a/src/aig/gia/giaAig.c b/src/aig/gia/giaAig.c index 07bab5fec2..70d19e351a 100644 --- a/src/aig/gia/giaAig.c +++ b/src/aig/gia/giaAig.c @@ -600,6 +600,7 @@ Gia_Man_t * Gia_ManCompress2( Gia_Man_t * p, int fUpdateLevel, int fVerbose ) Aig_ManStop( pTemp ); pGia = Gia_ManFromAig( pNew ); Aig_ManStop( pNew ); + Gia_ManOriginsAfterRoundTrip( pGia, p ); Gia_ManTransferTiming( pGia, p ); return pGia; } @@ -658,6 +659,8 @@ Gia_Man_t * Gia_ManPerformDch( Gia_Man_t * p, void * pPars ) Gia_ManStop( pGia ); pGia = Gia_ManDup( p ); } + else + Gia_ManOriginsAfterRoundTrip( pGia, p ); Gia_ManTransferTiming( pGia, p ); return pGia; } diff --git a/src/aig/gia/giaAiger.c b/src/aig/gia/giaAiger.c index c37c3ea9e4..0b106a26da 100644 --- a/src/aig/gia/giaAiger.c +++ b/src/aig/gia/giaAiger.c @@ -428,9 +428,6 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi } else if ( *pType == 'l' ) { - char Buffer[1000]; - assert( strlen(pName) < 995 ); - sprintf( Buffer, "%s_in", pName ); if ( vNamesRegIn == NULL ) vNamesRegIn = Vec_PtrStart( nLatches ); if ( vNamesRegOut == NULL ) @@ -440,7 +437,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi fError = 1; break; } - Vec_PtrWriteEntry( vNamesRegIn, iTerm, Abc_UtilStrsav(Buffer) ); + Vec_PtrWriteEntry( vNamesRegIn, iTerm, Abc_UtilStrsavTwo(pName, (char *)"_in") ); Vec_PtrWriteEntry( vNamesRegOut, iTerm, Abc_UtilStrsav(pName) ); } else if ( *pType == 'n' ) @@ -688,16 +685,16 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi if ( fVerbose ) printf( "Finished reading extension \"o\".\n" ); } // read equivalence classes - else if ( *pCur == 'e' ) - { - extern Gia_Rpr_t * Gia_AigerReadEquivClasses( unsigned char ** ppPos, int nSize ); - pCur++; - pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; - pNew->pReprs = Gia_AigerReadEquivClasses( &pCur, Gia_ManObjNum(pNew) ); - pNew->pNexts = Gia_ManDeriveNexts( pNew ); - assert( pCur == pCurTemp ); - if ( fVerbose ) printf( "Finished reading extension \"e\".\n" ); - } + //else if ( *pCur == 'e' ) + //{ + // extern Gia_Rpr_t * Gia_AigerReadEquivClasses( unsigned char ** ppPos, int nSize ); + // pCur++; + // pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; + // pNew->pReprs = Gia_AigerReadEquivClasses( &pCur, Gia_ManObjNum(pNew) ); + // pNew->pNexts = Gia_ManDeriveNexts( pNew ); + // assert( pCur == pCurTemp ); + // if ( fVerbose ) printf( "Finished reading extension \"e\".\n" ); + //} // read flop classes else if ( *pCur == 'f' ) { @@ -947,10 +944,60 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi else if ( fVerbose ) printf( "Finished reading extension \"y\".\n" ); } else { - if ( fVerbose ) printf( "Cannot read extension \"y\" because AIG is rehashed. Use \"&r -s \".\n" ); + if ( fVerbose ) printf( "Skipped extension \"y\" for vEquLitIds (AIG is rehashed).\n" ); + } + // populate vOrigins using vNodes to map AIG→GIA object indices + // sentinel -2 at pData[0] distinguishes new format from old + if ( vNodes && nInts >= 1 && ((int *)pCur)[0] == -2 ) { + // new multi-origin format: sentinel, then [count, lit0, lit1, ...] per AIG object + int k, nAigObjs = Vec_IntSize(vNodes); + int * pData = (int *)pCur; + int pos = 1; // skip sentinel + pNew->vOrigins = Gia_ManOriginsAlloc( Gia_ManObjNum(pNew) ); + for ( k = 0; k < nAigObjs && pos < nInts; k++ ) + { + int giaLit = Vec_IntEntry( vNodes, k ); + int giaObj = Abc_Lit2Var( giaLit ); + int nOrig = pData[pos++]; + int j; + for ( j = 0; j < nOrig && pos < nInts; j++, pos++ ) + { + int rawLit = pData[pos]; + if ( rawLit >= 0 && giaObj < Gia_ManObjNum(pNew) ) + Gia_ObjAddOrigin( pNew, giaObj, Abc_Lit2Var(rawLit) ); + } + } + if ( fVerbose ) printf( "Finished reading extension \"y\" (multi-origin).\n" ); + } + else if ( vNodes && nInts == Vec_IntSize(vNodes) ) { + // old single-origin format: one literal per AIG object + int k; + int * pData = (int *)pCur; + pNew->vOrigins = Gia_ManOriginsAlloc( Gia_ManObjNum(pNew) ); + for ( k = 0; k < nInts; k++ ) + { + int giaLit = Vec_IntEntry( vNodes, k ); + int giaObj = Abc_Lit2Var( giaLit ); + int rawLit = pData[k]; + if ( rawLit >= 0 && giaObj < Gia_ManObjNum(pNew) ) + Gia_ObjSetOrigin( pNew, giaObj, Abc_Lit2Var(rawLit) ); + } } pCur += 4*nInts; } + // skip the "M" cell-mapping doc (consumed by external readers such + // as Yosys's read_xaiger2). Without this, an unrecognized "M" + // section would fall through to "else break" below and abandon all + // subsequent extensions -- notably the "y" origin mapping, which is + // written after "M". + else if ( *pCur == 'M' ) + { + int nSize; + pCur++; + nSize = Gia_AigerReadInt(pCur); pCur += 4; + pCur += nSize; + if ( fVerbose ) printf( "Skipped extension \"M\".\n" ); + } else break; } } @@ -1585,15 +1632,15 @@ void Gia_AigerWriteS( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, in } } // write equivalences - if ( p->pReprs && p->pNexts ) - { - extern Vec_Str_t * Gia_WriteEquivClasses( Gia_Man_t * p ); - fprintf( pFile, "e" ); - vStrExt = Gia_WriteEquivClasses( p ); - Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); - fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); - Vec_StrFree( vStrExt ); - } + //if ( p->pReprs && p->pNexts ) + //{ + // extern Vec_Str_t * Gia_WriteEquivClasses( Gia_Man_t * p ); + // fprintf( pFile, "e" ); + // vStrExt = Gia_WriteEquivClasses( p ); + // Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); + // fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); + // Vec_StrFree( vStrExt ); + //} // write flop classes if ( p->vFlopClasses ) { @@ -1836,8 +1883,30 @@ void Gia_AigerWriteS( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, in assert( Vec_IntSize(p->vObjClasses) == Gia_ManObjNum(p) ); fwrite( Vec_IntArray(p->vObjClasses), 1, 4*Gia_ManObjNum(p), pFile ); } - // write object classes - if ( p->vEquLitIds ) + // write object origins (vOrigins takes priority over vEquLitIds) + // New variable-length format: sentinel -2, then for each object [count, lit0, lit1, ...] + if ( p->vOrigins ) + { + int k, nObjs = Gia_ManObjNum(p); + Vec_Int_t * vData = Vec_IntAlloc( 1 + nObjs * 2 ); + assert( Vec_IntSize(p->vOrigins) >= nObjs * GIA_ORIGINS_STRIDE ); + Vec_IntPush( vData, -2 ); // sentinel distinguishes new format from old + for ( k = 0; k < nObjs; k++ ) + { + int nOrig = Gia_ObjOriginsNum( p, k ); + int idx, orig, _nOrig; + Vec_IntPush( vData, nOrig ); + Gia_ObjForEachOrigin( p, k, orig, idx ) + Vec_IntPush( vData, orig >= 0 ? 2 * orig : -1 ); + } + fprintf( pFile, "y" ); + Gia_FileWriteBufferSize( pFile, 4*Vec_IntSize(vData) ); + fwrite( Vec_IntArray(vData), 1, (size_t)4*Vec_IntSize(vData), pFile ); + if ( fVerbose ) printf( "Finished writing extension \"y\" (multi-origin, %d ints for %d objs).\n", + Vec_IntSize(vData), nObjs ); + Vec_IntFree( vData ); + } + else if ( p->vEquLitIds ) { fprintf( pFile, "y" ); Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) ); diff --git a/src/aig/gia/giaBalAig.c b/src/aig/gia/giaBalAig.c index 5603b4108b..04c082cc27 100644 --- a/src/aig/gia/giaBalAig.c +++ b/src/aig/gia/giaBalAig.c @@ -420,6 +420,11 @@ Gia_Man_t * Gia_ManBalanceInt( Gia_Man_t * p, int fStrict ) } assert( !fStrict || Gia_ManObjNum(pNew) <= Gia_ManObjNum(p) ); Gia_ManHashStop( pNew ); + // Balancing rebuilds the AIG: the new balanced nodes have no 1:1 origin + // correspondence, so fill them bottom-up from their fanins (a plain + // Gia_ManOriginsDup would leave them, and the cells later mapped from them, + // without \src). + Gia_ManOriginsDupFill( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); @@ -819,6 +824,9 @@ Gia_Man_t * Dam_ManMultiAig( Dam_Man_t * pMan ) } // assert( Gia_ManObjNum(pNew) <= Gia_ManObjNum(p) ); Gia_ManHashStop( pNew ); + // Area balancing rebuilds the AIG via the divisor manager: fill the new + // nodes' origins bottom-up (see Gia_ManBalanceInt for the rationale). + Gia_ManOriginsDupFill( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); diff --git a/src/aig/gia/giaCSat.c b/src/aig/gia/giaCSat.c index 67b62655e0..91dfe60653 100644 --- a/src/aig/gia/giaCSat.c +++ b/src/aig/gia/giaCSat.c @@ -64,6 +64,7 @@ struct Cbs_Man_t_ { Cbs_Par_t Pars; // parameters Gia_Man_t * pAig; // AIG manager + int nSyncedObjs; // pAig objects already prepped (Value/marks/refs) for resident reuse Cbs_Que_t pProp; // propagation queue Cbs_Que_t pJust; // justification queue Cbs_Que_t pClauses; // clause queue @@ -71,6 +72,9 @@ struct Cbs_Man_t_ Vec_Int_t * vLevReas; // levels and decisions Vec_Int_t * vModel; // satisfying assignment Vec_Ptr_t * vTemp; // temporary storage + Vec_Int_t * vOutLits; // optional endpoint literals to sample before cancel + Vec_Int_t * vOutVals; // optional endpoint values by output + int iOutVal; // current output whose endpoints are sampled // SAT calls statistics int nSatUnsat; // the number of proofs int nSatSat; // the number of failure @@ -256,6 +260,29 @@ static inline void Cbs_ManSaveModelAll( Cbs_Man_t * p, Vec_Int_t * vCex ) Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs_VarValue(pVar)) ); } +static inline int Cbs_ManLitValue( Cbs_Man_t * p, int iLit ) +{ + Gia_Obj_t * pObj; + if ( iLit < 0 ) + return -1; + if ( Abc_Lit2Var(iLit) == 0 ) + return Abc_LitIsCompl(iLit); + pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(iLit) ); + if ( !Cbs_VarIsAssigned(pObj) ) + return -1; + return Cbs_VarValue(pObj) ^ Abc_LitIsCompl(iLit); +} + +static inline void Cbs_ManSaveOutVals( Cbs_Man_t * p, Vec_Int_t * vOutLits, Vec_Int_t * vOutVals, int Out ) +{ + if ( vOutLits == NULL || vOutVals == NULL ) + return; + if ( 2*Out + 1 >= Vec_IntSize(vOutLits) ) + return; + Vec_IntWriteEntry( vOutVals, 2*Out, Cbs_ManLitValue( p, Vec_IntEntry(vOutLits, 2*Out) ) ); + Vec_IntWriteEntry( vOutVals, 2*Out + 1, Cbs_ManLitValue( p, Vec_IntEntry(vOutLits, 2*Out + 1) ) ); +} + /**Function************************************************************* Synopsis [] @@ -954,7 +981,10 @@ int Cbs_ManSolve( Cbs_Man_t * p, Gia_Obj_t * pObj ) p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0; Cbs_ManAssign( p, pObj, 0, NULL, NULL ); if ( !Cbs_ManSolve_rec(p, 0) && !Cbs_ManCheckLimits(p) ) + { Cbs_ManSaveModel( p, p->vModel ); + Cbs_ManSaveOutVals( p, p->vOutLits, p->vOutVals, p->iOutVal ); + } else RetValue = 1; Cbs_ManCancelUntil( p, 0 ); @@ -1034,14 +1064,14 @@ void Cbs_ManSatPrintStats( Cbs_Man_t * p ) SeeAlso [] ***********************************************************************/ -Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose ) +Vec_Int_t * Cbs_ManSolveMiterNcOutVals( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose, Vec_Int_t * vOutLits, Vec_Int_t ** pvOutVals ) { extern void Gia_ManCollectTest( Gia_Man_t * pAig ); extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); - Cbs_Man_t * p; - Vec_Int_t * vCex, * vVisit, * vCexStore; + Cbs_Man_t * p; + Vec_Int_t * vCex, * vVisit, * vCexStore, * vOutVals = NULL; Vec_Str_t * vStatus; - Gia_Obj_t * pRoot; + Gia_Obj_t * pRoot; int i, status; abctime clk, clkTotal = Abc_Clock(); assert( Gia_ManRegNum(pAig) == 0 ); @@ -1058,6 +1088,12 @@ Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvSt // create resulting data-structures vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); vCexStore = Vec_IntAlloc( 10000 ); + if ( pvOutVals ) + { + *pvOutVals = NULL; + if ( vOutLits ) + vOutVals = Vec_IntStartFull( 2 * Gia_ManPoNum(pAig) ); + } vVisit = Vec_IntAlloc( 100 ); vCex = Cbs_ReadModel( p ); // solve for each output @@ -1084,7 +1120,13 @@ Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvSt clk = Abc_Clock(); p->Pars.fUseHighest = 1; p->Pars.fUseLowest = 0; + p->vOutLits = vOutLits; + p->vOutVals = vOutVals; + p->iOutVal = i; status = Cbs_ManSolve( p, Gia_ObjChild0(pRoot) ); + p->vOutLits = NULL; + p->vOutVals = NULL; + p->iOutVal = -1; // printf( "\n" ); /* if ( status == -1 ) @@ -1126,6 +1168,10 @@ Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvSt // printf( "RecCalls = %8d. RecClause = %8d. RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro ); Cbs_ManStop( p ); *pvStatus = vStatus; + if ( pvOutVals ) + *pvOutVals = vOutVals; + else + Vec_IntFreeP( &vOutVals ); // printf( "Total number of cex literals = %d. (Ave = %d)\n", // Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat, @@ -1133,6 +1179,132 @@ Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvSt return vCexStore; } +Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose ) +{ + return Cbs_ManSolveMiterNcOutVals( pAig, nConfs, pvStatus, f0Proved, fVerbose, NULL, NULL ); +} + +/**Function************************************************************* + + Synopsis [Incrementally prepares newly appended objects of a persistent AIG.] + + Description [The pAig of a resident manager is append-only across solve calls. + Cbs needs every unassigned object to carry Value=~0 and clean marks, and reads + Gia_ObjRefNum during branching. After a clean solve Cbs restores Value/marks + of the nodes it touched, and freshly appended nodes are zero-initialized, so we + only have to prep the suffix [nSyncedObjs, ObjNum): set Value=~0, clear marks, + grow pRefs and bump each new AND's fanin refs (= the global fanout counts that + Gia_ManCreateRefs would produce, computed incrementally). This replaces the + per-round O(|pAig|) refs/marks/value rebuild with O(newly appended).] + + SideEffects [Allocates/grows pAig->pRefs (freed by Gia_ManStop).] + + SeeAlso [] + +***********************************************************************/ +void Cbs_ManSyncCore( Cbs_Man_t * p ) +{ + Gia_Man_t * pAig = p->pAig; + Gia_Obj_t * pObj; + int i, nObjs = Gia_ManObjNum( pAig ); + assert( p->nSyncedObjs <= nObjs ); + if ( p->nSyncedObjs == nObjs ) + return; + pAig->pRefs = ABC_REALLOC( int, pAig->pRefs, nObjs ); + memset( pAig->pRefs + p->nSyncedObjs, 0, sizeof(int) * (nObjs - p->nSyncedObjs) ); + for ( i = p->nSyncedObjs; i < nObjs; i++ ) + { + pObj = Gia_ManObj( pAig, i ); + pObj->fMark0 = pObj->fMark1 = 0; + pObj->Value = ~0; + if ( Gia_ObjIsAnd(pObj) ) + { + pAig->pRefs[Gia_ObjFaninId0(pObj, i)]++; + pAig->pRefs[Gia_ObjFaninId1(pObj, i)]++; + } + } + p->nSyncedObjs = nObjs; +} + +/**Function************************************************************* + + Synopsis [Solves a set of root literals directly on a persistent AIG.] + + Description [Same prover as Cbs_ManSolveMiterNc, but each problem is a root + literal of p->pAig (no CO needed) instead of a CO of a freshly built view, and + the manager is resident: it is allocated once on the persistent COless pCore + and reused across rounds, only Cbs_ManSyncCore-ing the objects appended since + the last call - so neither the throwaway view (alloc + copy-all-CIs + cone + copy) nor the per-round whole-AIG prep is paid. Output index i corresponds to + vRootLits[i]; vCexStore / vStatus format matches Cbs_ManSolveMiterNc. CEX is + saved by CioId, which on pCore equals the view's CI numbering.] + + SideEffects [Prepares newly appended objects via Cbs_ManSyncCore.] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs_ManSolveRoots( Cbs_Man_t * p, Vec_Int_t * vRootLits, Vec_Str_t ** pvStatus, int fVerbose ) +{ + extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); + Gia_Man_t * pAig = p->pAig; + Vec_Int_t * vCex, * vCexStore; + Vec_Str_t * vStatus; + int i, iLit, status; + abctime clk, clkTotal = Abc_Clock(); + assert( Gia_ManRegNum(pAig) == 0 ); + Cbs_ManSyncCore( p ); // prep only objects appended since the last solve + vStatus = Vec_StrAlloc( Vec_IntSize(vRootLits) ); + vCexStore = Vec_IntAlloc( 10000 ); + vCex = Cbs_ReadModel( p ); + Vec_IntForEachEntry( vRootLits, iLit, i ) + { + Vec_IntClear( vCex ); + if ( Abc_Lit2Var(iLit) == 0 ) // structural constant root + { + if ( Abc_LitIsCompl(iLit) ) // const 1: trivial counter-example + { + Cec_ManSatAddToStore( vCexStore, vCex, i ); + Vec_StrPush( vStatus, 0 ); + } + else // const 0: proved + Vec_StrPush( vStatus, 1 ); + continue; + } + clk = Abc_Clock(); + p->Pars.fUseHighest = 1; + p->Pars.fUseLowest = 0; + status = Cbs_ManSolve( p, Gia_ObjFromLit(pAig, iLit) ); + Vec_StrPush( vStatus, (char)status ); + if ( status == -1 ) + { + p->nSatUndec++; + p->nConfUndec += p->Pars.nBTThis; + Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout + p->timeSatUndec += Abc_Clock() - clk; + continue; + } + if ( status == 1 ) + { + p->nSatUnsat++; + p->nConfUnsat += p->Pars.nBTThis; + p->timeSatUnsat += Abc_Clock() - clk; + continue; + } + p->nSatSat++; + p->nConfSat += p->Pars.nBTThis; + Cec_ManSatAddToStore( vCexStore, vCex, i ); + p->timeSatSat += Abc_Clock() - clk; + } + p->nSatTotal = Vec_IntSize( vRootLits ); + p->timeTotal = Abc_Clock() - clkTotal; + if ( fVerbose ) + Cbs_ManSatPrintStats( p ); + // manager is resident: caller (Cec_DynSrm) owns its lifetime + *pvStatus = vStatus; + return vCexStore; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// @@ -1140,4 +1312,3 @@ Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvSt ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/gia/giaCut.c b/src/aig/gia/giaCut.c index 5efc358ff6..0dba9782b6 100644 --- a/src/aig/gia/giaCut.c +++ b/src/aig/gia/giaCut.c @@ -690,7 +690,7 @@ Vec_Wec_t * Gia_ManSelectCuts( Vec_Wec_t * vCuts, int nCuts, int nCutSizeMin ) Vec_Wec_t * vCutsSel = Vec_WecStart( nCuts ); int i; srand( time(NULL) ); for ( i = 0; i < nCuts; i++ ) - while ( !Gia_StoSelectOneCut(vCuts, (rand() | (rand() << 15)) % Vec_WecSize(vCuts), Vec_WecEntry(vCutsSel, i), nCutSizeMin) ); + while ( !Gia_StoSelectOneCut(vCuts, (int)(((unsigned)rand() | ((unsigned)rand() << 15)) % Vec_WecSize(vCuts)), Vec_WecEntry(vCutsSel, i), nCutSizeMin) ); return vCutsSel; } Vec_Wec_t * Gia_ManExtractCuts( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int fVerbose0 ) diff --git a/src/aig/gia/giaDeep.c b/src/aig/gia/giaDeep.c index 9d2a2c8754..9c506eab56 100644 --- a/src/aig/gia/giaDeep.c +++ b/src/aig/gia/giaDeep.c @@ -238,6 +238,229 @@ Gia_Man_t * Gia_ManRandSyn( Gia_Man_t * p, unsigned random_seed ) return pRes; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Gia_ManDeepSynParetoUpdate( Vec_Ptr_t * vPareto, Gia_Man_t * pCand, int nLevels, int nAnds ) +{ + Gia_Man_t * pBest = (Gia_Man_t *)Vec_PtrGetEntry( vPareto, nLevels ); + if ( pBest == NULL || Gia_ManAndNum(pBest) > nAnds ) + { + if ( pBest ) + Gia_ManStop( pBest ); + Vec_PtrSetEntry( vPareto, nLevels, Gia_ManDup(pCand) ); + } +} + +static void Gia_ManDeepSynParetoPrint( Vec_Ptr_t * vPareto ) +{ + Gia_Man_t * pTemp; + int i, fFirst = 1; + printf( "Pareto points:" ); + Vec_PtrForEachEntry( Gia_Man_t *, vPareto, pTemp, i ) + { + if ( pTemp == NULL ) + continue; + printf( "%s%d:%d", fFirst ? " " : " ", i, Gia_ManAndNum(pTemp) ); + fFirst = 0; + } + if ( fFirst ) + printf( " none" ); + printf( "\n" ); +} + +static void Gia_ManDeepSynParetoSave( Vec_Ptr_t * vPareto, char * pBase ) +{ + Gia_Man_t * pTemp; + char FileName[1000]; + int i; + if ( pBase == NULL ) + pBase = Extra_UtilStrsav( "gia" ); + Vec_PtrForEachEntry( Gia_Man_t *, vPareto, pTemp, i ) + { + if ( pTemp == NULL ) + continue; + sprintf( FileName, "%s_%d_%d.aig", pBase, i, Gia_ManAndNum(pTemp) ); + Gia_AigerWrite( pTemp, FileName, 0, 0, 0 ); + } + ABC_FREE( pBase ); +} + +Gia_Man_t * Gia_ManDeepSynOne2( int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fVerbose, Vec_Ptr_t * vGias, Vec_Ptr_t * vPareto ) +{ + abctime nTimeToStop = TimeOut ? Abc_Clock() + TimeOut * CLOCKS_PER_SEC : 0; + abctime clkStart = Abc_Clock(); + int s, i, k, IterMax = 100000, nLevelsMin = -1, nAndsMin = -1; + int nNoImprCount = 0; + Gia_Man_t * pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + Gia_Man_t * pNew = Gia_ManDup( pTemp ); + (void)fUseTwo; + Abc_Random(1); + for ( s = 0; s < 10+Seed; s++ ) + Abc_Random(0); + nLevelsMin = Gia_ManLevelNum(pNew); + nAndsMin = Gia_ManAndNum(pNew); + for ( i = 0; i < IterMax; ) + { + unsigned Rand = Abc_Random(0); + int fDch = Rand & 1; + int fResyn = (Rand >> 1) % 3; + int fChange = 0; + char Command[2000]; + char pResyn[200]; + if ( fResyn == 0 ) + sprintf( pResyn, "&resyn3" ); + else if ( fResyn == 1 ) + sprintf( pResyn, "&resyn3rs" ); + else + sprintf( pResyn, "&resyn3; &resyn3rs" ); + sprintf( Command, "&dch%s; &if -y -K 6; %s", fDch ? " -f" : "", pResyn ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return NULL; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return NULL; + } + Abc_FrameSetBatchMode( 0 ); + } + pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + { + int nLevelTemp = Gia_ManLevelNum(pTemp); + int nAndsTemp = Gia_ManAndNum(pTemp); + if ( vPareto ) + Gia_ManDeepSynParetoUpdate( vPareto, pTemp, nLevelTemp, nAndsTemp ); + if ( nLevelsMin > nLevelTemp || (nLevelsMin == nLevelTemp && nAndsMin > nAndsTemp) ) + { + Gia_ManStop( pNew ); + pNew = Gia_ManDup( pTemp ); + nLevelsMin = nLevelTemp; + nAndsMin = nAndsTemp; + fChange = 1; + if ( vGias ) + Vec_PtrPush( vGias, Gia_ManDup(pTemp) ); + nNoImprCount = 0; + } + else + nNoImprCount++; + } + if ( fChange && fVerbose ) + { + printf( "Iter %6d : ", i ); + printf( "Time %8.2f sec : ", (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + printf( "Lev = %3d ", nLevelsMin ); + printf( "And = %6d ", nAndsMin ); + printf( "<== best : " ); + printf( "%s", Command ); + printf( "\n" ); + } + if ( nTimeToStop && Abc_Clock() > nTimeToStop ) + { + if ( !Abc_FrameIsBatchMode() ) + printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i ); + break; + } + i++; + if ( nNoImprCount > nNoImpr ) + { + int nOuter = 1 + (Abc_Random(0) % 3); + int nKmax = nAnds ? nAnds : 6; + int nKmin = 3; + int nLuts[3]; + if ( nKmax < nKmin ) + nKmin = nKmax; + for ( k = 0; k < nOuter; k++ ) + nLuts[k] = nKmin + (Abc_Random(0) % (nKmax - nKmin + 1)); + if ( fVerbose ) + { + printf( "Completed %d iterations without improvement. Trying %d outer iterations with ", nNoImpr, nOuter ); + for ( k = 0; k < nOuter; k++ ) + printf( "%sK=%d", k ? ", " : "", nLuts[k] ); + printf( ". Time = %.2f sec\n", (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + } + nNoImprCount = 0; + for ( k = 0; k < nOuter && i < IterMax; k++ ) + { + int nLut = nLuts[k]; + int fOuterChange = 0; + sprintf( Command, "&dch; &if -K %d -m; &mfs; &st", nLut ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return NULL; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return NULL; + } + Abc_FrameSetBatchMode( 0 ); + } + pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + { + int nLevelTemp = Gia_ManLevelNum(pTemp); + int nAndsTemp = Gia_ManAndNum(pTemp); + if ( vPareto ) + Gia_ManDeepSynParetoUpdate( vPareto, pTemp, nLevelTemp, nAndsTemp ); + if ( nLevelsMin > nLevelTemp || (nLevelsMin == nLevelTemp && nAndsMin > nAndsTemp) ) + { + Gia_ManStop( pNew ); + pNew = Gia_ManDup( pTemp ); + nLevelsMin = nLevelTemp; + nAndsMin = nAndsTemp; + fOuterChange = 1; + if ( vGias ) + Vec_PtrPush( vGias, Gia_ManDup(pTemp) ); + } + } + if ( fOuterChange && fVerbose ) + { + printf( "Iter %6d : ", i ); + printf( "Time %8.2f sec : ", (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + printf( "Lev = %3d ", nLevelsMin ); + printf( "And = %6d ", nAndsMin ); + printf( "<== best : " ); + printf( "%s", Command ); + printf( "\n" ); + } + if ( nTimeToStop && Abc_Clock() > nTimeToStop ) + { + if ( !Abc_FrameIsBatchMode() ) + printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i ); + return pNew; + } + i++; + } + } + } + if ( i == IterMax ) + printf( "Iteration limit (%d iters) is reached after %.2f seconds.\n", IterMax, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + return pNew; +} + /**Function************************************************************* Synopsis [] @@ -251,7 +474,84 @@ Gia_Man_t * Gia_ManRandSyn( Gia_Man_t * p, unsigned random_seed ) ***********************************************************************/ Gia_Man_t * Gia_ManDeepSyn2( Gia_Man_t * pGia, int nIters, int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fChoices, int fVerbose ) { - return Gia_ManDeepSyn( pGia, nIters, nNoImpr, TimeOut, nAnds, Seed, fUseTwo, fChoices, fVerbose ); + Vec_Ptr_t * vGias = fChoices ? Vec_PtrAlloc(100) : NULL; + Vec_Ptr_t * vPareto = fUseTwo ? Vec_PtrStart(100) : NULL; + char * pParetoBase = NULL; + Gia_Man_t * pInit; + Gia_Man_t * pBest; + Gia_Man_t * pThis; + int i, nBestLev, nBestAnd; + if ( !Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "Gia_ManDeepSyn2(): LMS library is not loaded.\n" ); + Abc_Print( -1, "Download \"rec6Lib_final_filtered3_recanon.aig\" and run \"rec_start3 _/rec6Lib_final_filtered3_recanon.aig\".\n" ); + if ( vGias ) + Vec_PtrFree( vGias ); + if ( vPareto ) + Vec_PtrFree( vPareto ); + return Gia_ManDup( pGia ); + } + if ( vPareto ) + { + if ( pGia->pSpec && pGia->pSpec[0] ) + pParetoBase = Extra_FileNameGeneric( pGia->pSpec ); + else if ( pGia->pName && pGia->pName[0] ) + pParetoBase = Extra_FileNameGeneric( pGia->pName ); + else + pParetoBase = Extra_UtilStrsav( "gia" ); + } + pInit = Gia_ManDup(pGia); + pBest = Gia_ManDup(pGia); + nBestLev = Gia_ManLevelNum(pBest); + nBestAnd = Gia_ManAndNum(pBest); + if ( vPareto ) + Gia_ManDeepSynParetoUpdate( vPareto, pGia, nBestLev, nBestAnd ); + if ( vGias ) + Vec_PtrPush( vGias, Gia_ManDup(pGia) ); + for ( i = 0; i < nIters; i++ ) + { + if ( fVerbose ) + printf( "ITER %d (out of %d) running for %d seconds\n", i + 1, nIters, TimeOut ); + int nThisLev, nThisAnd; + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(pInit) ); + pThis = Gia_ManDeepSynOne2( nNoImpr, TimeOut, nAnds, Seed+i, fUseTwo, fVerbose, vGias, vPareto ); + nThisLev = Gia_ManLevelNum(pThis); + nThisAnd = Gia_ManAndNum(pThis); + if ( nBestLev > nThisLev || (nBestLev == nThisLev && nBestAnd > nThisAnd) ) + { + Gia_ManStop( pBest ); + pBest = pThis; + nBestLev = nThisLev; + nBestAnd = nThisAnd; + } + else + Gia_ManStop( pThis ); + if ( vPareto ) + Gia_ManDeepSynParetoPrint( vPareto ); + } + Gia_ManStop( pInit ); + if ( vGias) { + if ( Vec_PtrSize(vGias) > 1 ) { + extern Gia_Man_t * Gia_ManCreateChoicesArray( Vec_Ptr_t * vGias, int fVerbose ); + Gia_ManStopP( &pBest ); + pBest = Gia_ManCreateChoicesArray( vGias, fVerbose ); + } + // cleanup + Gia_Man_t * pTemp; + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pTemp, i ) + Gia_ManStop( pTemp ); + Vec_PtrFree( vGias ); + } + if ( vPareto ) + { + Gia_ManDeepSynParetoSave( vPareto, pParetoBase ); + Gia_Man_t * pTemp; + Vec_PtrForEachEntry( Gia_Man_t *, vPareto, pTemp, i ) + if ( pTemp ) + Gia_ManStop( pTemp ); + Vec_PtrFree( vPareto ); + } + return pBest; } //////////////////////////////////////////////////////////////////////// @@ -260,4 +560,3 @@ Gia_Man_t * Gia_ManDeepSyn2( Gia_Man_t * pGia, int nIters, int nNoImpr, int Time ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/gia/giaDup.c b/src/aig/gia/giaDup.c index d1187cb241..d3c9ccc372 100644 --- a/src/aig/gia/giaDup.c +++ b/src/aig/gia/giaDup.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "gia.h" +#include "map/if/if.h" #include "misc/tim/tim.h" #include "misc/vec/vecWec.h" #include "proof/cec/cec.h" @@ -193,12 +194,336 @@ int Gia_ManDupOrderDfs_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } +/**Function************************************************************* + + Synopsis [Adds an origin to an object with deduplication.] + + Description [May promote inline storage to heap-allocated overflow.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjAddOrigin( Gia_Man_t * p, int iObj, int iOrig ) +{ + Gia_OriginsEntry_t * e; + int k; + if ( iOrig < 0 || !p->vOrigins || iObj * GIA_ORIGINS_STRIDE >= Vec_IntSize(p->vOrigins) ) + return; + e = Gia_ObjOriginsEntry( p, iObj ); + if ( Gia_ObjOriginsIsOverflow(e) ) + { + // cap check: skip if at user-specified limit + if ( p->nOriginsMax > 0 && e->ovf.count >= p->nOriginsMax ) + return; + // overflow mode: check for duplicate + for ( k = 0; k < e->ovf.count; k++ ) + if ( e->ovf.overflow[k] == iOrig ) return; + // geometric growth: double capacity when count is a power of 2 + if ( e->ovf.count >= 8 && (e->ovf.count & (e->ovf.count - 1)) == 0 ) + e->ovf.overflow = ABC_REALLOC( int, e->ovf.overflow, e->ovf.count * 2 ); + e->ovf.overflow[e->ovf.count++] = iOrig; + } + else + { + // inline mode: check for duplicate and find empty slot + for ( k = 0; k < GIA_ORIGINS_INLINE; k++ ) + { + if ( e->inl.origins[k] == iOrig ) return; + if ( e->inl.origins[k] == -1 ) + { + e->inl.origins[k] = iOrig; + return; + } + } + // inline buffer full: promote to overflow with 8-slot initial capacity + { + int * pOverflow = ABC_ALLOC( int, 8 ); + for ( k = 0; k < GIA_ORIGINS_INLINE; k++ ) + pOverflow[k] = e->inl.origins[k]; + pOverflow[GIA_ORIGINS_INLINE] = iOrig; + e->ovf.sentinel = GIA_ORIGINS_SENTINEL; + e->ovf.count = GIA_ORIGINS_INLINE + 1; + e->ovf.overflow = pOverflow; + } + } +} + +/**Function************************************************************* + + Synopsis [Unions all origins from src object into dst object.] + + Description [Iterates over all origins of iSrc in pSrc and adds each + to iDst in p, with deduplication. pSrc and p may be the same manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjUnionOrigins( Gia_Man_t * p, int iDst, Gia_Man_t * pSrc, int iSrc ) +{ + int idx, orig, _nOrig; + Gia_ObjForEachOrigin( pSrc, iSrc, orig, idx ) + Gia_ObjAddOrigin( p, iDst, orig ); +} + +/**Function************************************************************* + + Synopsis [Frees all overflow arrays in vOrigins.] + + Description [Walks every object's origins entry and frees the heap + array for entries in overflow mode. Must be called before freeing + the vOrigins Vec_Int_t itself.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManOriginsFreeOverflows( Gia_Man_t * p ) +{ + int i, nObjs; + Gia_OriginsEntry_t * e; + if ( !p->vOrigins ) + return; + nObjs = Vec_IntSize(p->vOrigins) / GIA_ORIGINS_STRIDE; + for ( i = 0; i < nObjs; i++ ) + { + e = Gia_ObjOriginsEntry( p, i ); + if ( Gia_ObjOriginsIsOverflow(e) && e->ovf.overflow ) + ABC_FREE( e->ovf.overflow ); + } +} + +/**Function************************************************************* + + Synopsis [Frees existing vOrigins (overflows + vec).] + + Description [Used before reallocation to prevent leaks.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManOriginsReset( Gia_Man_t * p ) +{ + if ( !p->vOrigins ) + return; + Gia_ManOriginsFreeOverflows( p ); + Vec_IntFreeP( &p->vOrigins ); +} + +/**Function************************************************************* + + Synopsis [Propagates origin mapping from old to new manager.] + + Description [Uses Value field of old objects to find corresponding + new objects. Copies full multi-origin entries.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManOriginsDup( Gia_Man_t * pNew, Gia_Man_t * pOld ) +{ + Gia_Obj_t * pObj; + int i; + if ( !pOld->vOrigins ) + return; + Gia_ManOriginsReset( pNew ); + pNew->nOriginsMax = pOld->nOriginsMax; + pNew->vOrigins = Gia_ManOriginsAlloc( Gia_ManObjNum(pNew) ); + Gia_ManForEachObj( pOld, pObj, i ) + { + if ( i * GIA_ORIGINS_STRIDE >= Vec_IntSize(pOld->vOrigins) ) + break; + if ( (int)Gia_ObjValue(pObj) != -1 ) + { + int iNew = Abc_Lit2Var( Gia_ObjValue(pObj) ); + if ( iNew < Gia_ManObjNum(pNew) ) + Gia_ObjUnionOrigins( pNew, iNew, pOld, i ); + } + } +} + +/**Function************************************************************* + + Synopsis [Like Gia_ManOriginsDup, then fills AND nodes left without origins.] + + Description [Use after a rebuild (e.g. balancing) that creates fresh AND nodes + with no 1:1 correspondence to pOld: Gia_ManOriginsDup seeds the survivors + (precise per-node origins), then a single bottom-up pass gives each remaining + AND node the union of its fanins' origins. Because GIA is topologically + ordered, one forward pass suffices: a node's fanins (lower ids) already carry + their origins. New nodes thus inherit the union of the surviving boundary + nodes in their cone — the most precise attribution available once the original + internal nodes are gone.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManOriginsDupFill( Gia_Man_t * pNew, Gia_Man_t * pOld ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManOriginsDup( pNew, pOld ); + if ( !pNew->vOrigins ) + return; + Gia_ManForEachAnd( pNew, pObj, i ) + { + int f0, f1, f2; + if ( Gia_ObjOriginsNum( pNew, i ) > 0 ) + continue; + f0 = Gia_ObjFaninId0( pObj, i ); + f1 = Gia_ObjFaninId1( pObj, i ); + f2 = Gia_ObjFaninId2( pNew, i ); // 3rd fanin of MUX nodes, else -1 + if ( f0 > 0 ) + Gia_ObjUnionOrigins( pNew, i, pNew, f0 ); + if ( f1 > 0 ) + Gia_ObjUnionOrigins( pNew, i, pNew, f1 ); + if ( f2 > 0 ) + Gia_ObjUnionOrigins( pNew, i, pNew, f2 ); + } +} + +/**Function************************************************************* + + Synopsis [Propagates origins using a copies vector.] + + Description [Like Gia_ManOriginsDup but uses an explicit vCopies + vector instead of the Value field. Entry i of vCopies is the literal + in pNew corresponding to old object i.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManOriginsDupVec( Gia_Man_t * pNew, Gia_Man_t * pOld, Vec_Int_t * vCopies ) +{ + int i, iLit; + if ( !pOld->vOrigins ) + return; + Gia_ManOriginsReset( pNew ); + pNew->nOriginsMax = pOld->nOriginsMax; + pNew->vOrigins = Gia_ManOriginsAlloc( Gia_ManObjNum(pNew) ); + Vec_IntForEachEntry( vCopies, iLit, i ) + { + if ( iLit != -1 ) + { + int iNew = Abc_Lit2Var( iLit ); + if ( iNew < Gia_ManObjNum(pNew) && i * GIA_ORIGINS_STRIDE < Vec_IntSize(pOld->vOrigins) ) + Gia_ObjUnionOrigins( pNew, iNew, pOld, i ); + } + } +} + +/**Function************************************************************* + + Synopsis [Restores origins after GIA->AIG->GIA round-trip.] + + Description [CIs map 1:1 in order. CO drivers map 1:1 (output + correspondence preserved through optimization). Remaining AND nodes + get origins via top-down propagation from CO drivers through fanin + cones.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManOriginsAfterRoundTrip( Gia_Man_t * pNew, Gia_Man_t * pOld ) +{ + Gia_Obj_t * pObj; + int i; + if ( !pOld->vOrigins ) + return; + assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(pOld) ); + assert( Gia_ManCoNum(pNew) == Gia_ManCoNum(pOld) ); + Gia_ManOriginsReset( pNew ); + pNew->nOriginsMax = pOld->nOriginsMax; + pNew->vOrigins = Gia_ManOriginsAlloc( Gia_ManObjNum(pNew) ); + // const0 + Gia_ObjUnionOrigins( pNew, 0, pOld, 0 ); + // CIs map 1:1 in order + Gia_ManForEachCi( pNew, pObj, i ) + { + int iNewObj = Gia_ObjId( pNew, pObj ); + int iOldCi = Gia_ObjId( pOld, Gia_ManCi(pOld, i) ); + Gia_ObjUnionOrigins( pNew, iNewObj, pOld, iOldCi ); + } + // CO drivers map 1:1 (output correspondence preserved through optimization) + Gia_ManForEachCo( pNew, pObj, i ) + { + int iNewDriver = Gia_ObjFaninId0p( pNew, pObj ); + Gia_Obj_t * pOldCo = Gia_ManCo( pOld, i ); + int iOldDriver = Gia_ObjFaninId0p( pOld, pOldCo ); + if ( iNewDriver > 0 ) + Gia_ObjUnionOrigins( pNew, iNewDriver, pOld, iOldDriver ); + } + // Top-down propagation: spread CO driver origins backward through fanin cones + for ( i = Gia_ManObjNum(pNew) - 1; i > 0; i-- ) + { + int f0, f1; + pObj = Gia_ManObj( pNew, i ); + if ( !Gia_ObjIsAnd(pObj) ) + continue; + if ( Gia_ObjOriginsNum(pNew, i) == 0 ) + continue; + f0 = Gia_ObjFaninId0(pObj, i); + f1 = Gia_ObjFaninId1(pObj, i); + if ( f0 > 0 ) + Gia_ObjUnionOrigins( pNew, f0, pNew, i ); + if ( f1 > 0 ) + Gia_ObjUnionOrigins( pNew, f1, pNew, i ); + } +} + +/**Function************************************************************* + + Synopsis [Propagates origins through IF mapper correspondence.] + + Description [IF objects 0..Gia_ManObjNum(p)-1 correspond 1:1 to + input GIA objects; iCopy gives the literal in the output GIA.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManOriginsDupIf( Gia_Man_t * pNew, Gia_Man_t * p, void * pIfManVoid ) +{ + If_Man_t * pIfMan = (If_Man_t *)pIfManVoid; + If_Obj_t * pIfObj = NULL; + int i; + if ( !p->vOrigins ) + return; + Gia_ManOriginsReset( pNew ); + pNew->nOriginsMax = p->nOriginsMax; + pNew->vOrigins = Gia_ManOriginsAlloc( Gia_ManObjNum(pNew) ); + If_ManForEachObj( pIfMan, pIfObj, i ) + { + if ( i * GIA_ORIGINS_STRIDE < Vec_IntSize(p->vOrigins) && pIfObj->iCopy >= 0 ) + { + int iNewObj = Abc_Lit2Var( pIfObj->iCopy ); + if ( iNewObj < Gia_ManObjNum(pNew) ) + Gia_ObjUnionOrigins( pNew, iNewObj, p, i ); + } + } +} + /**Function************************************************************* Synopsis [Duplicates AIG while putting objects in the DFS order.] Description [] - + SideEffects [] SeeAlso [] @@ -221,6 +546,7 @@ Gia_Man_t * Gia_ManDupOrderDfs( Gia_Man_t * p ) pObj->Value = Gia_ManAppendCi(pNew); assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); Gia_ManDupRemapCis( pNew, p ); + Gia_ManOriginsDup( pNew, p ); Gia_ManDupRemapEquiv( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; @@ -545,6 +871,7 @@ Gia_Man_t * Gia_ManDupOrderAiger( Gia_Man_t * p ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManOriginsDup( pNew, p ); Gia_ManDupRemapEquiv( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); assert( Gia_ManIsNormalized(pNew) ); @@ -778,6 +1105,7 @@ Gia_Man_t * Gia_ManDup( Gia_Man_t * p ) else if ( Gia_ObjIsCo(pObj) ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } + Gia_ManOriginsDup( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); if ( p->pCexSeq ) pNew->pCexSeq = Abc_CexDup( p->pCexSeq, Gia_ManRegNum(p) ); @@ -829,11 +1157,31 @@ Gia_Man_t * Gia_ManDupWithAttributes( Gia_Man_t * p ) pNew->vConfigs2 = Vec_StrDup( p->vConfigs2 ); if ( p->pCellStr ) pNew->pCellStr = Abc_UtilStrsav( p->pCellStr ); + // copy origins if present (deep-copy overflow arrays) + pNew->nOriginsMax = p->nOriginsMax; + if ( p->vOrigins ) + { + int iObj, nObjs; + Gia_OriginsEntry_t * eSrc, * eDst; + Gia_ManOriginsReset( pNew ); + pNew->vOrigins = Vec_IntDup( p->vOrigins ); + nObjs = Vec_IntSize(p->vOrigins) / GIA_ORIGINS_STRIDE; + for ( iObj = 0; iObj < nObjs; iObj++ ) + { + eSrc = Gia_ObjOriginsEntry( p, iObj ); + if ( Gia_ObjOriginsIsOverflow(eSrc) && eSrc->ovf.overflow ) + { + eDst = Gia_ObjOriginsEntry( pNew, iObj ); + eDst->ovf.overflow = ABC_ALLOC( int, eSrc->ovf.count ); + memcpy( eDst->ovf.overflow, eSrc->ovf.overflow, sizeof(int) * eSrc->ovf.count ); + } + } + } // copy names if present if ( p->vNamesIn ) pNew->vNamesIn = Vec_PtrDupStr( p->vNamesIn ); if ( p->vNamesOut ) - pNew->vNamesOut = Vec_PtrDupStr( p->vNamesOut ); + pNew->vNamesOut = Vec_PtrDupStr( p->vNamesOut ); return pNew; } Gia_Man_t * Gia_ManDupRemovePis( Gia_Man_t * p, int nRemPis ) @@ -1575,6 +1923,7 @@ Gia_Man_t * Gia_ManDupMarked( Gia_Man_t * p ) pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(pSibl->Value); } } + Gia_ManOriginsDup( pNew, p ); return pNew; } @@ -1806,6 +2155,7 @@ Gia_Man_t * Gia_ManDupDfs( Gia_Man_t * p ) Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManOriginsDup( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew->nConstrs = p->nConstrs; if ( p->pCexSeq ) @@ -1874,6 +2224,7 @@ Gia_Man_t * Gia_ManDupDfsRehash( Gia_Man_t * p ) Gia_ManDupDfsRehash_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManOriginsDup( pNew, p ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); @@ -3890,6 +4241,8 @@ Gia_Man_t * Gia_ManChoiceMiter( Vec_Ptr_t * vGias ) Gia_ManChoiceMiter_rec( pNew, pGia, Gia_ManCo( pGia, k ) ); } Gia_ManHashStop( pNew ); + // propagate origins from the first (primary) AIG + Gia_ManOriginsDup( pNew, pGia0 ); // check the presence of dangling nodes nNodes = Gia_ManHasDangling( pNew ); //assert( nNodes == 0 ); @@ -3931,6 +4284,7 @@ Gia_Man_t * Gia_ManDupWithConstraints( Gia_Man_t * p, Vec_Int_t * vPoTypes ) Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); // Gia_ManDupRemapEquiv( pNew, p ); + Gia_ManOriginsDup( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew->nConstrs = nConstr; assert( Gia_ManIsNormalized(pNew) ); @@ -6964,6 +7318,591 @@ void Gia_ManDupSplit( Gia_Man_t * p, int nParts, int nCutLevel ) Vec_PtrFreeFree( vCutNames ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManDupPipelineMapPos( int nStages, int iObj, int iStage ) +{ + return iObj * nStages + iStage; +} + +static int Gia_ManDupPipelineDelayLit( Gia_Man_t * pNew, Vec_Int_t * vLitMap, Vec_Int_t * vStages, Vec_Int_t * vRegDrivers, Vec_Int_t * vRegStages, int nStages, int iObj, int iStage ) +{ + int iPos, iStageBase, iLitPrev, iLit; + if ( iObj == 0 ) + return 0; + iPos = Gia_ManDupPipelineMapPos( nStages, iObj, iStage ); + iLit = Vec_IntEntry( vLitMap, iPos ); + if ( iLit >= 0 ) + return iLit; + iStageBase = Vec_IntEntry( vStages, iObj ); + assert( iStage >= iStageBase ); + assert( iStage > 0 ); + iLitPrev = Gia_ManDupPipelineDelayLit( pNew, vLitMap, vStages, vRegDrivers, vRegStages, nStages, iObj, iStage - 1 ); + iLit = Gia_ManAppendCi( pNew ); + Vec_IntWriteEntry( vLitMap, iPos, iLit ); + Vec_IntPush( vRegDrivers, iLitPrev ); + Vec_IntPush( vRegStages, iStage - 1 ); + return iLit; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Gia_ManDupPipelineNameCopy( Vec_Ptr_t * vNames, int iName, char * pPrefix, int i ) +{ + char * pName = (vNames && iName < Vec_PtrSize(vNames)) ? (char *)Vec_PtrEntry(vNames, iName) : NULL; + return pName ? Abc_UtilStrsav( pName ) : Abc_UtilStrsavNum( pPrefix, i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupPipeline( Gia_Man_t * p, int nLevels, int fVerbose ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vStages, * vLitMap, * vRegDrivers, * vRegStages, * vStageCounts; + Vec_Ptr_t * vNamesIn, * vNamesOut; + char * pNameRo; + int nObjs, nLevelMax, nStageMax, nStageCols, i, iStage, iLit0, iLit1, iLit, iFlop; + + if ( nLevels <= 0 ) + return NULL; + if ( Gia_ManRegNum(p) > 0 ) + return NULL; + + Gia_ManLevelNum( p ); + nObjs = Gia_ManObjNum( p ); + nLevelMax = Gia_ManLevelNum( p ); + nStageMax = nLevelMax ? (nLevelMax - 1) / nLevels : 0; + nStageCols = nStageMax + 1; + + vStages = Vec_IntStart( nObjs ); + vLitMap = Vec_IntStartFull( nObjs * nStageCols ); + vRegDrivers = Vec_IntAlloc( 1000 ); + vRegStages = Vec_IntAlloc( 1000 ); + + Gia_ManForEachAnd( p, pObj, i ) + Vec_IntWriteEntry( vStages, Gia_ObjId(p, pObj), (Gia_ObjLevel(p, pObj) - 1) / nLevels ); + + pNew = Gia_ManStart( Gia_ManObjNum(p) + 2 * Gia_ManAndNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + Gia_ManHashAlloc( pNew ); + + Gia_ManForEachPi( p, pObj, i ) + { + iLit = Gia_ManAppendCi( pNew ); + Vec_IntWriteEntry( vLitMap, Gia_ManDupPipelineMapPos(nStageCols, Gia_ObjId(p, pObj), 0), iLit ); + } + + Gia_ManForEachAnd( p, pObj, i ) + { + iStage = Vec_IntEntry( vStages, Gia_ObjId(p, pObj) ); + iLit0 = Gia_ManDupPipelineDelayLit( pNew, vLitMap, vStages, vRegDrivers, vRegStages, nStageCols, Gia_ObjFaninId0p(p, pObj), iStage ); + iLit1 = Gia_ManDupPipelineDelayLit( pNew, vLitMap, vStages, vRegDrivers, vRegStages, nStageCols, Gia_ObjFaninId1p(p, pObj), iStage ); + iLit = Gia_ManHashAnd( pNew, Abc_LitNotCond(iLit0, Gia_ObjFaninC0(pObj)), Abc_LitNotCond(iLit1, Gia_ObjFaninC1(pObj)) ); + Vec_IntWriteEntry( vLitMap, Gia_ManDupPipelineMapPos(nStageCols, Gia_ObjId(p, pObj), iStage), iLit ); + } + + Gia_ManForEachPo( p, pObj, i ) + { + iLit = Gia_ManDupPipelineDelayLit( pNew, vLitMap, vStages, vRegDrivers, vRegStages, nStageCols, Gia_ObjFaninId0p(p, pObj), nStageMax ); + Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); + } + + Vec_IntForEachEntry( vRegDrivers, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Gia_ManSetRegNum( pNew, Vec_IntSize(vRegDrivers) ); + + vNamesIn = Vec_PtrAlloc( Gia_ManCiNum(pNew) ); + vNamesOut = Vec_PtrAlloc( Gia_ManCoNum(pNew) ); + vStageCounts = Vec_IntStart( nStageCols ); + Gia_ManForEachPi( p, pObj, i ) + Vec_PtrPush( vNamesIn, Gia_ManDupPipelineNameCopy(p->vNamesIn, i, (char *)"pi", i) ); + Gia_ManForEachPo( p, pObj, i ) + Vec_PtrPush( vNamesOut, Gia_ManDupPipelineNameCopy(p->vNamesOut, i, (char *)"po", i) ); + Vec_IntForEachEntry( vRegStages, iStage, i ) + { + char Buffer[64], BufferIn[64]; + iFlop = Vec_IntEntry( vStageCounts, iStage ); + Vec_IntWriteEntry( vStageCounts, iStage, iFlop + 1 ); + snprintf( Buffer, sizeof(Buffer), "cut%d[%d]", iStage, iFlop ); + snprintf( BufferIn, sizeof(BufferIn), "cut%d_in[%d]", iStage, iFlop ); + pNameRo = Abc_UtilStrsav( Buffer ); + Vec_PtrPush( vNamesIn, pNameRo ); + Vec_PtrPush( vNamesOut, Abc_UtilStrsav( BufferIn ) ); + } + pNew->vNamesIn = vNamesIn; + pNew->vNamesOut = vNamesOut; + Gia_ManHashStop( pNew ); + + if ( fVerbose ) + Abc_Print( 1, "Inserted %d fixed-cut pipeline registers using D = %d.\n", Gia_ManRegNum(pNew), nLevels ); + + Vec_IntFree( vStages ); + Vec_IntFree( vLitMap ); + Vec_IntFree( vRegDrivers ); + Vec_IntFree( vRegStages ); + Vec_IntFree( vStageCounts ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Vec_Ptr_t * Gia_ManDupUnpipelineNames( Vec_Ptr_t * vNames, int nNames ) +{ + Vec_Ptr_t * vRes; + char * pName; + int i; + if ( vNames == NULL ) + return NULL; + vRes = Vec_PtrAlloc( nNames ); + for ( i = 0; i < nNames; i++ ) + { + pName = i < Vec_PtrSize(vNames) ? (char *)Vec_PtrEntry( vNames, i ) : NULL; + Vec_PtrPush( vRes, pName ? Abc_UtilStrsav(pName) : NULL ); + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [Duplicates selected names if present.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Vec_Ptr_t * Gia_ManDupUnpipelineNamesUsed( Vec_Ptr_t * vNames, Vec_Bit_t * vUsed, int nNames ) +{ + Vec_Ptr_t * vRes; + char * pName; + int i; + if ( vNames == NULL ) + return NULL; + vRes = Vec_PtrAlloc( Vec_BitCount(vUsed) ); + for ( i = 0; i < nNames; i++ ) + { + if ( !Vec_BitEntry(vUsed, i) ) + continue; + pName = i < Vec_PtrSize(vNames) ? (char *)Vec_PtrEntry( vNames, i ) : NULL; + Vec_PtrPush( vRes, pName ? Abc_UtilStrsav(pName) : NULL ); + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Gia_ManDupUnpipeline_rec( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vCopies, int iObj, int * piCycle ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + int iLit, iLit0, iLit1; + + iLit = Vec_IntEntry( vCopies, iObj ); + if ( iLit >= 0 ) + return iLit; + if ( iLit == -2 ) + { + if ( piCycle ) + *piCycle = iObj; + return -1; + } + Vec_IntWriteEntry( vCopies, iObj, -2 ); + + if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) + { + iLit0 = Gia_ManDupUnpipeline_rec( pNew, p, vCopies, Gia_ObjFaninId0p(p, pObj), piCycle ); + if ( iLit0 < 0 ) + return -1; + iLit = Abc_LitNotCond( iLit0, Gia_ObjFaninC0(pObj) ); + } + else if ( Gia_ObjIsAnd(pObj) ) + { + iLit0 = Gia_ManDupUnpipeline_rec( pNew, p, vCopies, Gia_ObjFaninId0p(p, pObj), piCycle ); + if ( iLit0 < 0 ) + return -1; + iLit1 = Gia_ManDupUnpipeline_rec( pNew, p, vCopies, Gia_ObjFaninId1p(p, pObj), piCycle ); + if ( iLit1 < 0 ) + return -1; + iLit = Gia_ManHashAnd( pNew, Abc_LitNotCond(iLit0, Gia_ObjFaninC0(pObj)), Abc_LitNotCond(iLit1, Gia_ObjFaninC1(pObj)) ); + } + else if ( Gia_ObjIsRo(p, pObj) ) + { + Gia_Obj_t * pObjRi = Gia_ObjRoToRi( p, pObj ); + iLit0 = Gia_ManDupUnpipeline_rec( pNew, p, vCopies, Gia_ObjFaninId0p(p, pObjRi), piCycle ); + if ( iLit0 < 0 ) + return -1; + iLit = Abc_LitNotCond( iLit0, Gia_ObjFaninC0(pObjRi) ); + } + else + { + assert( 0 ); + return -1; + } + + Vec_IntWriteEntry( vCopies, iObj, iLit ); + return iLit; +} + +/**Function************************************************************* + + Synopsis [Marks objects reachable after bypassing flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Gia_ManDupUnpipelineMark_rec( Gia_Man_t * p, Vec_Str_t * vMarks, Vec_Bit_t * vPisUsed, int iObj, int * piCycle ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + int Mark = Vec_StrEntry( vMarks, iObj ); + if ( Mark == 2 ) + return 0; + if ( Mark == 1 ) + { + if ( piCycle ) + *piCycle = iObj; + return -1; + } + if ( Gia_ObjIsConst0(pObj) ) + { + Vec_StrWriteEntry( vMarks, iObj, 2 ); + return 0; + } + if ( Gia_ObjIsPi(p, pObj) ) + { + Vec_BitWriteEntry( vPisUsed, Gia_ObjCioId(pObj), 1 ); + Vec_StrWriteEntry( vMarks, iObj, 2 ); + return 0; + } + + Vec_StrWriteEntry( vMarks, iObj, 1 ); + if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) + { + if ( Gia_ManDupUnpipelineMark_rec( p, vMarks, vPisUsed, Gia_ObjFaninId0p(p, pObj), piCycle ) < 0 ) + return -1; + } + else if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ManDupUnpipelineMark_rec( p, vMarks, vPisUsed, Gia_ObjFaninId0p(p, pObj), piCycle ) < 0 ) + return -1; + if ( Gia_ManDupUnpipelineMark_rec( p, vMarks, vPisUsed, Gia_ObjFaninId1p(p, pObj), piCycle ) < 0 ) + return -1; + } + else if ( Gia_ObjIsRo(p, pObj) ) + { + Gia_Obj_t * pObjRi = Gia_ObjRoToRi( p, pObj ); + if ( Gia_ManDupUnpipelineMark_rec( p, vMarks, vPisUsed, Gia_ObjFaninId0p(p, pObjRi), piCycle ) < 0 ) + return -1; + } + else + { + assert( 0 ); + return -1; + } + Vec_StrWriteEntry( vMarks, iObj, 2 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupUnpipeline( Gia_Man_t * p, int fVerbose ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Bit_t * vPisUsed; + Vec_Int_t * vCopies; + Vec_Str_t * vMarks; + int i, iLit, iCycle = -1, nRegs, nPisUsed = 0; + + if ( Gia_ManRegNum(p) == 0 ) + return Gia_ManDup( p ); + + nRegs = Gia_ManRegNum( p ); + vPisUsed = Vec_BitStart( Gia_ManPiNum(p) ); + vMarks = Vec_StrStart( Gia_ManObjNum(p) ); + Gia_ManForEachPo( p, pObj, i ) + if ( Gia_ManDupUnpipelineMark_rec( p, vMarks, vPisUsed, Gia_ObjFaninId0p(p, pObj), &iCycle ) < 0 ) + break; + Vec_StrFree( vMarks ); + if ( iCycle >= 0 ) + { + if ( fVerbose ) + Abc_Print( 1, "Bypassing flops creates a combinational cycle at object %d.\n", iCycle ); + Vec_BitFree( vPisUsed ); + return NULL; + } + + vCopies = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_IntWriteEntry( vCopies, 0, 0 ); + + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + pNew->vNamesIn = Gia_ManDupUnpipelineNamesUsed( p->vNamesIn, vPisUsed, Gia_ManPiNum(p) ); + pNew->vNamesOut = Gia_ManDupUnpipelineNames( p->vNamesOut, Gia_ManPoNum(p) ); + Gia_ManHashAlloc( pNew ); + + Gia_ManForEachPi( p, pObj, i ) + if ( Vec_BitEntry(vPisUsed, i) ) + { + Vec_IntWriteEntry( vCopies, Gia_ObjId(p, pObj), Gia_ManAppendCi(pNew) ); + nPisUsed++; + } + + Gia_ManForEachPo( p, pObj, i ) + { + iLit = Gia_ManDupUnpipeline_rec( pNew, p, vCopies, Gia_ObjFaninId0p(p, pObj), &iCycle ); + if ( iLit < 0 ) + break; + Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); + } + Gia_ManHashStop( pNew ); + Vec_IntFree( vCopies ); + Vec_BitFree( vPisUsed ); + + Gia_ManSetRegNum( pNew, 0 ); + if ( fVerbose ) + Abc_Print( 1, "Removed %d pipeline registers and kept %d primary inputs.\n", nRegs, nPisUsed ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Gia_ManDupRegioNameCopy( Vec_Ptr_t * vNames, int iName ) +{ + char * pName = (vNames && iName < Vec_PtrSize(vNames)) ? (char *)Vec_PtrEntry(vNames, iName) : NULL; + return pName ? Abc_UtilStrsav(pName) : NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Gia_ManDupRegioNameNew( Vec_Ptr_t * vNames, int iName, char * pSuffix, char * pPrefix, int i ) +{ + char * pName = (vNames && iName < Vec_PtrSize(vNames)) ? (char *)Vec_PtrEntry(vNames, iName) : NULL; + return pName ? Abc_UtilStrsavTwo( pName, pSuffix ) : Abc_UtilStrsavNum( pPrefix, i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupRegio( Gia_Man_t * p, int fRegIns, int fRegOuts, int fVerbose ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vInRos = NULL, * vOutRos = NULL; + Vec_Ptr_t * vNamesIn = NULL, * vNamesOut = NULL; + int nPis = Gia_ManPiNum(p), nPos = Gia_ManPoNum(p), nRegs = Gia_ManRegNum(p); + int nRegIns = fRegIns ? nPis : 0; + int nRegOuts = fRegOuts ? nPos : 0; + int nRegsNew = nRegs + nRegIns + nRegOuts; + int i; + + if ( !fRegIns && !fRegOuts ) + return Gia_ManDup( p ); + + pNew = Gia_ManStart( Gia_ManObjNum(p) + 2 * (nRegIns + nRegOuts) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + + if ( p->vRegClasses ) + { + pNew->vRegClasses = Vec_IntAlloc( nRegsNew ); + for ( i = 0; i < nRegs; i++ ) + Vec_IntPush( pNew->vRegClasses, Vec_IntEntry(p->vRegClasses, i) ); + for ( ; i < nRegsNew; i++ ) + Vec_IntPush( pNew->vRegClasses, 0 ); + } + if ( p->vFlopClasses ) + { + pNew->vFlopClasses = Vec_IntAlloc( nRegsNew ); + for ( i = 0; i < nRegs; i++ ) + Vec_IntPush( pNew->vFlopClasses, Vec_IntEntry(p->vFlopClasses, i) ); + for ( ; i < nRegsNew; i++ ) + Vec_IntPush( pNew->vFlopClasses, 0 ); + } + if ( p->vRegInits ) + { + pNew->vRegInits = Vec_IntAlloc( nRegsNew ); + for ( i = 0; i < nRegs; i++ ) + Vec_IntPush( pNew->vRegInits, Vec_IntEntry(p->vRegInits, i) ); + for ( ; i < nRegsNew; i++ ) + Vec_IntPush( pNew->vRegInits, 0 ); + } + + if ( p->vNamesIn ) + { + vNamesIn = Vec_PtrAlloc( nPis + nRegsNew ); + for ( i = 0; i < nPis; i++ ) + Vec_PtrPush( vNamesIn, Gia_ManDupRegioNameCopy(p->vNamesIn, i) ); + for ( i = 0; i < nRegs; i++ ) + Vec_PtrPush( vNamesIn, Gia_ManDupRegioNameCopy(p->vNamesIn, nPis + i) ); + if ( fRegIns ) + for ( i = 0; i < nPis; i++ ) + Vec_PtrPush( vNamesIn, Gia_ManDupRegioNameNew(p->vNamesIn, i, (char *)"_i_ro", (char *)"inro", i) ); + if ( fRegOuts ) + for ( i = 0; i < nPos; i++ ) + Vec_PtrPush( vNamesIn, Gia_ManDupRegioNameNew(p->vNamesOut, i, (char *)"_o_ro", (char *)"outro", i) ); + pNew->vNamesIn = vNamesIn; + } + if ( p->vNamesOut ) + { + vNamesOut = Vec_PtrAlloc( nPos + nRegsNew ); + for ( i = 0; i < nPos; i++ ) + Vec_PtrPush( vNamesOut, Gia_ManDupRegioNameCopy(p->vNamesOut, i) ); + for ( i = 0; i < nRegs; i++ ) + Vec_PtrPush( vNamesOut, Gia_ManDupRegioNameCopy(p->vNamesOut, nPos + i) ); + if ( fRegIns ) + for ( i = 0; i < nPis; i++ ) + Vec_PtrPush( vNamesOut, Gia_ManDupRegioNameNew(p->vNamesIn, i, (char *)"_i_ri", (char *)"inri", i) ); + if ( fRegOuts ) + for ( i = 0; i < nPos; i++ ) + Vec_PtrPush( vNamesOut, Gia_ManDupRegioNameNew(p->vNamesOut, i, (char *)"_o_ri", (char *)"outri", i) ); + pNew->vNamesOut = vNamesOut; + } + + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachRo( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + + if ( fRegIns ) + { + vInRos = Vec_IntAlloc( nPis ); + Gia_ManForEachPi( p, pObj, i ) + Vec_IntPush( vInRos, Gia_ManAppendCi( pNew ) ); + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Vec_IntEntry( vInRos, i ); + } + if ( fRegOuts ) + { + vOutRos = Vec_IntAlloc( nPos ); + for ( i = 0; i < nPos; i++ ) + Vec_IntPush( vOutRos, Gia_ManAppendCi( pNew ) ); + } + + Gia_ManForEachObj1( p, pObj, i ) + { + if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + + Gia_ManForEachPo( p, pObj, i ) + { + if ( fRegOuts ) + Gia_ManAppendCo( pNew, Vec_IntEntry(vOutRos, i) ); + else + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManForEachRi( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + if ( fRegIns ) + for ( i = 0; i < nPis; i++ ) + Gia_ManAppendCo( pNew, Gia_ManCiLit(pNew, i) ); + if ( fRegOuts ) + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + + Gia_ManSetRegNum( pNew, nRegsNew ); + Vec_IntFreeP( &vInRos ); + Vec_IntFreeP( &vOutRos ); + + if ( fVerbose ) + Abc_Print( 1, "Added %d input flops and %d output flops (total regs = %d).\n", nRegIns, nRegOuts, nRegsNew ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/gia/giaEquiv.c b/src/aig/gia/giaEquiv.c index e8ddc99131..96013df928 100644 --- a/src/aig/gia/giaEquiv.c +++ b/src/aig/gia/giaEquiv.c @@ -744,6 +744,7 @@ Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fS Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); + Gia_ManOriginsDup( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } @@ -2071,6 +2072,7 @@ Gia_Man_t * Gia_ManEquivToChoices( Gia_Man_t * p, int nSnapshots ) Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); Gia_ManRemoveBadChoices( pNew ); //Gia_ManEquivPrintClasses( pNew, 0, 0 ); + Gia_ManOriginsDup( pNew, p ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); //Gia_ManEquivPrintClasses( pNew, 0, 0 ); diff --git a/src/aig/gia/giaGen.c b/src/aig/gia/giaGen.c index c22cb21f8c..e9bf012f5c 100644 --- a/src/aig/gia/giaGen.c +++ b/src/aig/gia/giaGen.c @@ -1446,23 +1446,76 @@ void Gia_ManGenPrefix( Gia_Man_t * pNew, int * p, int * g, int p2, int g2 ) *g = Gia_ManHashOr(pNew, *g, Gia_ManHashAnd(pNew, *p, g2)); *p = Gia_ManHashAnd(pNew, *p, p2); } -Gia_Man_t * Gia_ManGenAdder( int nVars, int fSK, int fBK, int fHC, int fCarries, int fVerbose ) +static int Gia_ManGenAdderMaj( Gia_Man_t * p, int a, int b, int c ) +{ + int ab = Gia_ManHashAnd( p, a, b ); + int ac = Gia_ManHashAnd( p, a, c ); + int bc = Gia_ManHashAnd( p, b, c ); + return Gia_ManHashOr( p, ab, Gia_ManHashOr( p, ac, bc ) ); +} +static int Gia_ManGenAdderFloorPow2( int n ) +{ + int r = 1; + assert( n > 0 ); + while ( r <= n / 2 ) + r *= 2; + return r; +} +static void Gia_ManGenAdderMMRange( Gia_Man_t * p, int nVars, int * pLitsI, int * pM0, int * pM1, int i, int k ) +{ + int Index = i * nVars + k; + int nRange, nLeft, j; + assert( 0 <= i && i <= k && k < nVars ); + if ( pM0[Index] >= 0 ) + return; + if ( i == k ) + { + pM0[Index] = pLitsI[2*i]; + pM1[Index] = pLitsI[2*i+1]; + return; + } + nRange = k - i + 1; + nLeft = Gia_ManGenAdderFloorPow2( nRange - 1 ); + j = i + nLeft - 1; + Gia_ManGenAdderMMRange( p, nVars, pLitsI, pM0, pM1, i, j ); + Gia_ManGenAdderMMRange( p, nVars, pLitsI, pM0, pM1, j+1, k ); + pM0[Index] = Gia_ManGenAdderMaj( p, pM0[(j+1)*nVars+k], pM1[(j+1)*nVars+k], pM0[i*nVars+j] ); + pM1[Index] = Gia_ManGenAdderMaj( p, pM0[(j+1)*nVars+k], pM1[(j+1)*nVars+k], pM1[i*nVars+j] ); +} +static int Gia_ManGenAdderMMCarry( Gia_Man_t * p, int nVars, int * pLitsI, int * pM0, int * pM1, int * pCarries, int iCarry ) +{ + int nBase, iBeg; + assert( 0 <= iCarry && iCarry <= nVars ); + if ( pCarries[iCarry] >= 0 ) + return pCarries[iCarry]; + nBase = Gia_ManGenAdderFloorPow2( iCarry ); + iBeg = nBase - 1; + Gia_ManGenAdderMMRange( p, nVars, pLitsI, pM0, pM1, iBeg, iCarry-1 ); + pCarries[iCarry] = Gia_ManGenAdderMaj( p, pM0[iBeg*nVars+iCarry-1], pM1[iBeg*nVars+iCarry-1], Gia_ManGenAdderMMCarry( p, nVars, pLitsI, pM0, pM1, pCarries, iBeg ) ); + return pCarries[iCarry]; +} +Gia_Man_t * Gia_ManGenAdder( int nVars, int fSK, int fBK, int fHC, int fMM, int fCarries, int fVerbose ) { extern void Wlc_BlastFullAdder( Gia_Man_t * pNew, int a, int b, int c, int * pc, int * ps ); int i, k, nBits = Abc_Base2Log(nVars), nVarsAlloc = (1 << nBits) + 2; - int ** pStore = (int **)Extra_ArrayAlloc( nVarsAlloc, nVarsAlloc, 4 ); + int ** pStore = fMM ? NULL : (int **)Extra_ArrayAlloc( nVarsAlloc, nVarsAlloc, 4 ); printf( "Generating %d-bit ", nVars ); - Gia_ManGenPrep( nVars+2, pStore ); - if ( fSK ) - Gia_ManGenSK( nVars, pStore ), printf("Sklansky "); - else if ( fBK ) - Gia_ManGenBK( nVars, pStore ), printf("Brent-Kung "); - else if ( fHC ) - Gia_ManGenHC( nVars, pStore ), printf("Huan-Carlsson "); + if ( fMM ) + printf("M/M "); else - Gia_ManGenRca( nVars, pStore ), printf("ripple-carry "); + { + Gia_ManGenPrep( nVars+2, pStore ); + if ( fSK ) + Gia_ManGenSK( nVars, pStore ), printf("Sklansky "); + else if ( fBK ) + Gia_ManGenBK( nVars, pStore ), printf("Brent-Kung "); + else if ( fHC ) + Gia_ManGenHC( nVars, pStore ), printf("Huan-Carlsson "); + else + Gia_ManGenRca( nVars, pStore ), printf("ripple-carry "); + } printf( "adder with%s carry-in and carry-out\n", fCarries ? "":"out" ); - if ( fVerbose ) Gia_ManGenPrint( nVars, pStore ); + if ( fVerbose && !fMM ) Gia_ManGenPrint( nVars, pStore ); Gia_Man_t * p = Gia_ManStart( 1000 ), * pTemp; p->pName = Abc_UtilStrsav( "adder" ); int * pLitsI = ABC_CALLOC( int, 2*nVars+10 ); @@ -1472,18 +1525,45 @@ Gia_Man_t * Gia_ManGenAdder( int nVars, int fSK, int fBK, int fHC, int fCarries, pLitsI[2*k+1] = Gia_ManAppendCi(p); int Carry = fCarries ? Gia_ManAppendCi(p) : 0; Gia_ManHashStart( p ); + if ( fMM ) + { + int nPairs = nVars * nVars; + int * pM0 = ABC_ALLOC( int, nPairs ); + int * pM1 = ABC_ALLOC( int, nPairs ); + int * pCarries = ABC_ALLOC( int, nVars + 1 ); + int * pProps = ABC_ALLOC( int, nVars ); + for ( k = 0; k < nPairs; k++ ) + pM0[k] = pM1[k] = -1; + for ( k = 0; k <= nVars; k++ ) + pCarries[k] = -1; + pCarries[0] = Carry; + for ( k = 0; k < nVars; k++ ) + pProps[k] = Gia_ManHashXor( p, pLitsI[2*k], pLitsI[2*k+1] ); + if ( fCarries ) + Gia_ManAppendCo( p, Gia_ManGenAdderMMCarry( p, nVars, pLitsI, pM0, pM1, pCarries, nVars ) ); + for ( k = 0; k < nVars; k++ ) + Gia_ManAppendCo( p, Gia_ManHashXor( p, pProps[k], Gia_ManGenAdderMMCarry( p, nVars, pLitsI, pM0, pM1, pCarries, k ) ) ); + ABC_FREE( pM0 ); + ABC_FREE( pM1 ); + ABC_FREE( pCarries ); + ABC_FREE( pProps ); + ABC_FREE( pLitsI ); + p = Gia_ManCleanup( pTemp = p ); + Gia_ManStop( pTemp ); + return p; + } for ( k = 0; k < nVars; k++ ) Wlc_BlastFullAdder( p, pLitsI[2*k], pLitsI[2*k+1], k ? 0 : Carry, &pLitsI[2*k+1], &pLitsI[2*k] ); int * pLits = ABC_CALLOC( int, 2*nVars+10 ); memcpy( pLits, pLitsI, sizeof(int)*2*nVars ); for ( i = 1; i < nVars; i++ ) - for ( k = 1; k < nVars; k++ ) + for ( k = nVars - 1; k >= 1; k-- ) if ( pStore[i][k] >= 0 ) Gia_ManGenPrefix( p, &pLits[2*k], &pLits[2*k+1], pLits[2*pStore[i][k]], pLits[2*pStore[i][k]+1] ); - for ( k = 0; k < nVars; k++ ) - Gia_ManAppendCo( p, k ? Gia_ManHashXor(p, pLitsI[2*k], pLits[2*(k-1)+1]) : pLitsI[2*k] ); if ( fCarries ) Gia_ManAppendCo( p, pLits[2*(k-1)+1] ); + for ( k = 0; k < nVars; k++ ) + Gia_ManAppendCo( p, k ? Gia_ManHashXor(p, pLitsI[2*k], pLits[2*(k-1)+1]) : pLitsI[2*k] ); ABC_FREE( pStore ); ABC_FREE( pLitsI ); ABC_FREE( pLits ); @@ -1498,4 +1578,3 @@ Gia_Man_t * Gia_ManGenAdder( int nVars, int fSK, int fBK, int fHC, int fCarries, ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/gia/giaHash.c b/src/aig/gia/giaHash.c index 063cfd31ab..fc581149a1 100644 --- a/src/aig/gia/giaHash.c +++ b/src/aig/gia/giaHash.c @@ -491,6 +491,12 @@ int Gia_ManHashXorReal( Gia_Man_t * p, int iLit0, int iLit1 ) if ( *pPlace ) { p->nHashHit++; + // on hash hit, union input origins into existing node + if ( p->vOrigins && *pPlace * GIA_ORIGINS_STRIDE < Vec_IntSize(p->vOrigins) ) + { + Gia_ObjUnionOrigins( p, *pPlace, p, Abc_Lit2Var(iLit0) ); + Gia_ObjUnionOrigins( p, *pPlace, p, Abc_Lit2Var(iLit1) ); + } return Abc_Var2Lit( *pPlace, fCompl ); } p->nHashMiss++; @@ -503,6 +509,14 @@ int Gia_ManHashXorReal( Gia_Man_t * p, int iLit0, int iLit1 ) assert( *pPlace == 0 ); *pPlace = Abc_Lit2Var( iNode ); } + // propagate origins from both inputs into new node + if ( p->vOrigins ) + { + int iNew = *pPlace; + Gia_ManOriginsGrow( p, iNew ); + Gia_ObjUnionOrigins( p, iNew, p, Abc_Lit2Var(iLit0) ); + Gia_ObjUnionOrigins( p, iNew, p, Abc_Lit2Var(iLit1) ); + } return Abc_Var2Lit( *pPlace, fCompl ); } } @@ -546,6 +560,13 @@ int Gia_ManHashMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int iLit0 ) if ( *pPlace ) { p->nHashHit++; + // on hash hit, union input origins into existing node + if ( p->vOrigins && *pPlace * GIA_ORIGINS_STRIDE < Vec_IntSize(p->vOrigins) ) + { + Gia_ObjUnionOrigins( p, *pPlace, p, Abc_Lit2Var(iLit0) ); + Gia_ObjUnionOrigins( p, *pPlace, p, Abc_Lit2Var(iLit1) ); + Gia_ObjUnionOrigins( p, *pPlace, p, Abc_Lit2Var(iLitC) ); + } return Abc_Var2Lit( *pPlace, fCompl ); } p->nHashMiss++; @@ -558,6 +579,15 @@ int Gia_ManHashMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int iLit0 ) assert( *pPlace == 0 ); *pPlace = Abc_Lit2Var( iNode ); } + // propagate origins from all three inputs into new node + if ( p->vOrigins ) + { + int iNew = *pPlace; + Gia_ManOriginsGrow( p, iNew ); + Gia_ObjUnionOrigins( p, iNew, p, Abc_Lit2Var(iLit0) ); + Gia_ObjUnionOrigins( p, iNew, p, Abc_Lit2Var(iLit1) ); + Gia_ObjUnionOrigins( p, iNew, p, Abc_Lit2Var(iLitC) ); + } return Abc_Var2Lit( *pPlace, fCompl ); } } @@ -603,6 +633,12 @@ int Gia_ManHashAnd( Gia_Man_t * p, int iLit0, int iLit1 ) if ( *pPlace ) { p->nHashHit++; + // on hash hit, union input origins into existing node + if ( p->vOrigins && *pPlace * GIA_ORIGINS_STRIDE < Vec_IntSize(p->vOrigins) ) + { + Gia_ObjUnionOrigins( p, *pPlace, p, Abc_Lit2Var(iLit0) ); + Gia_ObjUnionOrigins( p, *pPlace, p, Abc_Lit2Var(iLit1) ); + } return Abc_Var2Lit( *pPlace, 0 ); } p->nHashMiss++; @@ -615,6 +651,14 @@ int Gia_ManHashAnd( Gia_Man_t * p, int iLit0, int iLit1 ) assert( *pPlace == 0 ); *pPlace = Abc_Lit2Var( iNode ); } + // propagate origins from both inputs into new node + if ( p->vOrigins ) + { + int iNew = *pPlace; + Gia_ManOriginsGrow( p, iNew ); + Gia_ObjUnionOrigins( p, iNew, p, Abc_Lit2Var(iLit0) ); + Gia_ObjUnionOrigins( p, iNew, p, Abc_Lit2Var(iLit1) ); + } return Abc_Var2Lit( *pPlace, 0 ); } } @@ -761,6 +805,7 @@ Gia_Man_t * Gia_ManRehash( Gia_Man_t * p, int fAddStrash ) } Gia_ManHashStop( pNew ); pNew->fAddStrash = 0; + Gia_ManOriginsDup( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // printf( "Top gate is %s\n", Gia_ObjFaninC0(Gia_ManCo(pNew, 0))? "OR" : "AND" ); pNew = Gia_ManCleanup( pTemp = pNew ); diff --git a/src/aig/gia/giaIf.c b/src/aig/gia/giaIf.c index c2d8886c0a..ff18328300 100644 --- a/src/aig/gia/giaIf.c +++ b/src/aig/gia/giaIf.c @@ -3010,9 +3010,19 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars ) if ( p->pManTime && pPars->pTimesReq == NULL ) { Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; - pPars->pTimesReq = ABC_CALLOC( float, Gia_ManCoNum(p) ); + int fHasFiniteReq = 0; for ( i = 0; i < Gia_ManCoNum(p); i++ ) - pPars->pTimesReq[i] = Tim_ManGetCoRequired( pManTime, i ); + if ( Tim_ManGetCoRequired( pManTime, i ) < TIM_ETERNITY ) + { + fHasFiniteReq = 1; + break; + } + if ( fHasFiniteReq ) + { + pPars->pTimesReq = ABC_CALLOC( float, Gia_ManCoNum(p) ); + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + pPars->pTimesReq[i] = Tim_ManGetCoRequired( pManTime, i ); + } } ABC_FREE( p->pCellStr ); Vec_IntFreeP( &p->vConfigs ); @@ -3065,6 +3075,8 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars ) pNew = Gia_ManFromIfAig( pIfMan ); else pNew = Gia_ManFromIfLogic( pIfMan ); + // propagate origin mapping from input GIA through IF mapper to output GIA + Gia_ManOriginsDupIf( pNew, p, pIfMan ); if ( p->vCiArrs || p->vCoReqs ) { If_Obj_t * pIfObj = NULL; @@ -3160,6 +3172,7 @@ Gia_Man_t * Gia_ManPerformSopBalance( Gia_Man_t * p, int nCutNum, int nRelaxRati pIfMan = Gia_ManToIf( p, pPars ); If_ManPerformMapping( pIfMan ); pNew = Gia_ManFromIfAig( pIfMan ); + Gia_ManOriginsDupIf( pNew, p, pIfMan ); If_ManStop( pIfMan ); Gia_ManTransferTiming( pNew, p ); // transfer name @@ -3193,6 +3206,7 @@ Gia_Man_t * Gia_ManPerformDsdBalance( Gia_Man_t * p, int nLutSize, int nCutNum, If_DsdManAllocIsops( pIfMan->pIfDsdMan, pPars->nLutSize ); If_ManPerformMapping( pIfMan ); pNew = Gia_ManFromIfAig( pIfMan ); + Gia_ManOriginsDupIf( pNew, p, pIfMan ); If_ManStop( pIfMan ); Gia_ManTransferTiming( pNew, p ); // transfer name @@ -3298,6 +3312,7 @@ Gia_Man_t * Gia_ManDupHashMapping( Gia_Man_t * p ) Vec_IntPush( vMapping, Abc_Lit2Var(pObj->Value) ); } pNew->vMapping = vMapping; + Gia_ManOriginsDup( pNew, p ); return pNew; } @@ -3377,6 +3392,7 @@ Gia_Man_t * Gia_ManDupUnhashMapping( Gia_Man_t * p ) } Vec_IntFree( vMap ); pNew->vMapping = vMapping; + Gia_ManOriginsDup( pNew, p ); return pNew; } diff --git a/src/aig/gia/giaJf.c b/src/aig/gia/giaJf.c index 205ab40801..e0711a288a 100644 --- a/src/aig/gia/giaJf.c +++ b/src/aig/gia/giaJf.c @@ -1511,10 +1511,11 @@ Gia_Man_t * Jf_ManDeriveMappingGia( Jf_Man_t * p ) if ( p->pPars->fGenCnf ) Jf_ManGenCnf( ABC_CONST(0xAAAAAAAAAAAAAAAA), iLit, vLeaves, vLits, vClas, vCover ); } + Gia_ManOriginsDupVec( pNew, p->pGia, vCopies ); Vec_IntFree( vCopies ); Vec_IntFree( vCover ); Vec_IntFree( vLeaves ); - // finish mapping + // finish mapping if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); else @@ -1653,6 +1654,7 @@ Gia_Man_t * Jf_ManDeriveGia( Jf_Man_t * p ) } if ( !p->pPars->fCutMin ) Gia_ObjComputeTruthTableStop( p->pGia ); + Gia_ManOriginsDupVec( pNew, p->pGia, vCopies ); Vec_IntFree( vCopies ); Vec_IntFree( vLeaves ); Vec_IntFree( vCover ); diff --git a/src/aig/gia/giaLf.c b/src/aig/gia/giaLf.c index 4f3e49f424..7d15a45d3d 100644 --- a/src/aig/gia/giaLf.c +++ b/src/aig/gia/giaLf.c @@ -1771,6 +1771,7 @@ Gia_Man_t * Lf_ManDeriveMappingCoarse( Lf_Man_t * p ) Vec_IntPush( pNew->vMapping, pCut->fMux7 ? -Abc_Lit2Var(pObj->Value) : Abc_Lit2Var(pObj->Value) ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); + Gia_ManOriginsDup( pNew, pGia ); assert( Vec_IntCap(pNew->vMapping) == 16 || Vec_IntSize(pNew->vMapping) == Vec_IntCap(pNew->vMapping) ); return pNew; } @@ -1909,10 +1910,11 @@ Gia_Man_t * Lf_ManDeriveMappingGia( Lf_Man_t * p ) iLit = Lf_ManDerivePart( p, pNew, vMapping, vMapping2, vCopies, pCut, vLeaves, vCover, pObj ); Vec_IntWriteEntry( vCopies, i, Abc_LitNotCond(iLit, Abc_LitIsCompl(pCut->iFunc)) ); } + Gia_ManOriginsDupVec( pNew, p->pGia, vCopies ); Vec_IntFree( vCopies ); Vec_IntFree( vCover ); Vec_IntFree( vLeaves ); - // finish mapping + // finish mapping if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); else diff --git a/src/aig/gia/giaMan.c b/src/aig/gia/giaMan.c index 889a49c0e2..6ee993fa02 100644 --- a/src/aig/gia/giaMan.c +++ b/src/aig/gia/giaMan.c @@ -107,6 +107,8 @@ void Gia_ManStop( Gia_Man_t * p ) Vec_IntFreeP( &p->vIdsOrig ); Vec_IntFreeP( &p->vIdsEquiv ); Vec_IntFreeP( &p->vEquLitIds ); + Gia_ManOriginsFreeOverflows( p ); + Vec_IntFreeP( &p->vOrigins ); Vec_IntFreeP( &p->vLutConfigs ); Vec_IntFreeP( &p->vEdgeDelay ); Vec_IntFreeP( &p->vEdgeDelayR ); diff --git a/src/aig/gia/giaMfs.c b/src/aig/gia/giaMfs.c index 6ad6b0039c..5330eac918 100644 --- a/src/aig/gia/giaMfs.c +++ b/src/aig/gia/giaMfs.c @@ -531,6 +531,25 @@ Gia_Man_t * Gia_ManInsertMfs( Gia_Man_t * p, Sfm_Ntk_t * pNtk, int fAllBoxes ) if ( p->vRegInits ) pNew->vRegInits = Vec_IntDup( p->vRegInits ); pNew->nAnd2Delay = p->nAnd2Delay; + // propagate origins via MFS ID correspondence + if ( p->vOrigins ) + { + int iOldObj; + pNew->vOrigins = Gia_ManOriginsAlloc( Gia_ManObjNum(pNew) ); + Vec_IntForEachEntry( vMfs2Old, iOldObj, i ) + { + if ( iOldObj >= 0 ) + { + int iNewLit = Vec_IntEntry( vMfs2Gia, i ); + if ( iNewLit >= 0 ) + { + int iNewObj = Abc_Lit2Var( iNewLit ); + if ( iNewObj < Gia_ManObjNum(pNew) && iOldObj * GIA_ORIGINS_STRIDE < Vec_IntSize(p->vOrigins) ) + Gia_ObjUnionOrigins( pNew, iNewObj, p, iOldObj ); + } + } + } + } // cleanup Vec_WecFree( vGroups ); diff --git a/src/aig/gia/giaMuxes.c b/src/aig/gia/giaMuxes.c index ff542c3053..cade908158 100644 --- a/src/aig/gia/giaMuxes.c +++ b/src/aig/gia/giaMuxes.c @@ -140,6 +140,9 @@ Gia_Man_t * Gia_ManDupMuxes( Gia_Man_t * p, int Limit ) pNew->pSibls[Gia_ObjId(pNew, pObjNew)] = Gia_ObjId(pNew, pSiblNew); } Gia_ManHashStop( pNew ); + // MUX <-> AND conversion rebuilds nodes (collapsing/expanding mux patterns), + // so fill new nodes' origins bottom-up; a plain Gia_ManOriginsDup misses them. + Gia_ManOriginsDupFill( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); @@ -253,6 +256,9 @@ Gia_Man_t * Gia_ManDupNoMuxes( Gia_Man_t * p, int fSkipBufs ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } Gia_ManHashStop( pNew ); + // MUX <-> AND conversion rebuilds nodes (collapsing/expanding mux patterns), + // so fill new nodes' origins bottom-up; a plain Gia_ManOriginsDup misses them. + Gia_ManOriginsDupFill( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); diff --git a/src/aig/gia/giaSatLut.c b/src/aig/gia/giaSatLut.c index 679c9e58b6..31e0972f8b 100644 --- a/src/aig/gia/giaSatLut.c +++ b/src/aig/gia/giaSatLut.c @@ -639,7 +639,9 @@ static inline int Sbl_CutIsFeasible( word CutI1, word CutI2, word CutN1, word Cu CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); if ( LutSize <= 4 ) return Count <= 4; - CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); + CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); + if ( LutSize <= 5 ) + return Count <= 5; CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); return Count <= 6; } diff --git a/src/aig/gia/giaScript.c b/src/aig/gia/giaScript.c index b52288a946..59d8791517 100644 --- a/src/aig/gia/giaScript.c +++ b/src/aig/gia/giaScript.c @@ -315,6 +315,7 @@ Gia_Man_t * Gia_ManDupFromBarBufs( Gia_Man_t * p ) Gia_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Gia_ManOriginsDup( pNew, p ); return pNew; } Gia_Man_t * Gia_ManDupToBarBufs( Gia_Man_t * p, int nBarBufs ) @@ -357,6 +358,7 @@ Gia_Man_t * Gia_ManDupToBarBufs( Gia_Man_t * p, int nBarBufs ) assert( Gia_ManBufNum(pNew) == nBarBufs ); assert( Gia_ManCiNum(pNew) == nPiReal ); assert( Gia_ManCoNum(pNew) == nPoReal ); + Gia_ManOriginsDup( pNew, p ); return pNew; } @@ -396,6 +398,8 @@ Gia_Man_t * Gia_ManAigSynch2Choices( Gia_Man_t * pGia1, Gia_Man_t * pGia2, Gia_M // convert to GIA pGia = Gia_ManFromAigChoices( pMan ); Aig_ManStop( pMan ); + // recover origins from base variant (pGia1) via CI/CO correspondence + Gia_ManOriginsAfterRoundTrip( pGia, pGia1 ); return pGia; } Gia_Man_t * Gia_ManAigSynch2( Gia_Man_t * pInit, void * pPars0, int nLutSize, int nRelaxRatio ) diff --git a/src/aig/gia/giaSweep.c b/src/aig/gia/giaSweep.c index d93ff2a605..d3e8a1407d 100644 --- a/src/aig/gia/giaSweep.c +++ b/src/aig/gia/giaSweep.c @@ -204,6 +204,7 @@ Gia_Man_t * Gia_ManDupWithBoxes( Gia_Man_t * p, int fSeq ) assert( Gia_ManCiNum(pNew) == Tim_ManPiNum((Tim_Man_t*)pNew->pManTime) + Gia_ManCoNum(pNew->pAigExtra) ); Vec_IntFree( vBoxesLeft ); pNew->nAnd2Delay = p->nAnd2Delay; + Gia_ManOriginsDup( pNew, p ); return pNew; } @@ -368,6 +369,7 @@ Gia_Man_t * Gia_ManFraigReduceGia( Gia_Man_t * p, int * pReprs ) else assert( 0 ); } Gia_ManHashStop( pNew ); + Gia_ManOriginsDup( pNew, p ); return pNew; } diff --git a/src/aig/gia/giaTim.c b/src/aig/gia/giaTim.c index 5f13dcfa70..0ad60aac6a 100644 --- a/src/aig/gia/giaTim.c +++ b/src/aig/gia/giaTim.c @@ -186,6 +186,7 @@ Gia_Man_t * Gia_ManDupNormalize( Gia_Man_t * p, int fHashMapping ) Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew->nConstrs = p->nConstrs; assert( Gia_ManIsNormalized(pNew) ); + Gia_ManOriginsDup( pNew, p ); Gia_ManDupRemapEquiv( pNew, p ); return pNew; } @@ -240,6 +241,7 @@ Gia_Man_t * Gia_ManDupUnshuffleInputs( Gia_Man_t * p ) Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew->nConstrs = p->nConstrs; assert( Gia_ManIsNormalized(pNew) ); + Gia_ManOriginsDup( pNew, p ); Gia_ManDupRemapEquiv( pNew, p ); return pNew; } @@ -420,6 +422,7 @@ Gia_Man_t * Gia_ManDupUnnormalize( Gia_Man_t * p ) pObj->Value = 0; else assert( 0 ); } + Gia_ManOriginsDup( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); Vec_IntFree( vNodes ); return pNew; @@ -777,6 +780,7 @@ Gia_Man_t * Gia_ManDupMoveLast( Gia_Man_t * p, int iInsert, int nItems ) else assert( 0 ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Gia_ManOriginsDup( pNew, p ); return pNew; } @@ -903,6 +907,7 @@ Gia_Man_t * Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * v assert( curCo == Gia_ManCoNum(p) ); Gia_ManSetRegNum( pNew, (fSeq && p->vRegClasses) ? Vec_IntSize(p->vRegClasses) : Gia_ManRegNum(p) ); Gia_ManHashStop( pNew ); + Gia_ManOriginsDup( pNew, p ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManCleanupRemap( p, pTemp ); Gia_ManStop( pTemp ); diff --git a/src/aig/hop/hop.h b/src/aig/hop/hop.h index 6b8085cc51..5fc022a69d 100644 --- a/src/aig/hop/hop.h +++ b/src/aig/hop/hop.h @@ -233,7 +233,7 @@ static inline Hop_Obj_t * Hop_ManFetchMemory( Hop_Man_t * p ) if ( p->pListFree == NULL ) Hop_ManAddMemory( p ); pTemp = p->pListFree; - p->pListFree = *((Hop_Obj_t **)pTemp); + memcpy(&p->pListFree, pTemp, sizeof(Hop_Obj_t *)); memset( pTemp, 0, sizeof(Hop_Obj_t) ); if ( p->vObjs ) { @@ -245,8 +245,8 @@ static inline Hop_Obj_t * Hop_ManFetchMemory( Hop_Man_t * p ) } static inline void Hop_ManRecycleMemory( Hop_Man_t * p, Hop_Obj_t * pEntry ) { - pEntry->Type = AIG_NONE; // distinquishes dead node from live node - *((Hop_Obj_t **)pEntry) = p->pListFree; + pEntry->Type = AIG_NONE; // distinguishes dead node from live node + memcpy(pEntry, &p->pListFree, sizeof(Hop_Obj_t *)); p->pListFree = pEntry; } diff --git a/src/aig/hop/hopMem.c b/src/aig/hop/hopMem.c index 79de38048e..50932971cd 100644 --- a/src/aig/hop/hopMem.c +++ b/src/aig/hop/hopMem.c @@ -88,13 +88,15 @@ void Hop_ManStopMemory( Hop_Man_t * p ) ***********************************************************************/ void Hop_ManAddMemory( Hop_Man_t * p ) { - char * pMemory; + char * pMemory = 0; + Hop_Obj_t * pEntry, * pNext; int i, nBytes; assert( sizeof(Hop_Obj_t) <= 64 ); assert( p->pListFree == NULL ); // assert( (Hop_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); // allocate new memory page nBytes = sizeof(Hop_Obj_t) * (1<vChunks, pMemory ); // align memory at the 32-byte boundary @@ -102,13 +104,16 @@ void Hop_ManAddMemory( Hop_Man_t * p ) // remember the manager in the first entry Vec_PtrPush( p->vPages, pMemory ); // break the memory down into nodes - p->pListFree = (Hop_Obj_t *)pMemory; + pEntry = (Hop_Obj_t *)pMemory; + p->pListFree = pEntry; for ( i = 1; i <= IVY_PAGE_MASK; i++ ) { - *((char **)pMemory) = pMemory + sizeof(Hop_Obj_t); - pMemory += sizeof(Hop_Obj_t); + pNext = pEntry + 1; + memcpy( pEntry, &pNext, sizeof(Hop_Obj_t *) ); + pEntry++; } - *((char **)pMemory) = NULL; + pNext = NULL; + memcpy( pEntry, &pNext, sizeof(Hop_Obj_t *) ); } //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 0b0376c47f..e490808232 100644 --- a/src/base/abc/abc.h +++ b/src/base/abc/abc.h @@ -142,6 +142,7 @@ struct Abc_Obj_t_ // 48/72 bytes (32-bits/64-bits) unsigned Level : 20; // the level of the node Vec_Int_t vFanins; // the array of fanins Vec_Int_t vFanouts; // the array of fanouts + void * pDataComp; union { void * pData; // the network specific data int iData; }; // (SOP, BDD, gate, equiv class, etc) union { void * pTemp; // temporary store for user's data @@ -620,6 +621,7 @@ extern ABC_DLL float Abc_NtkDelayTraceLut( Abc_Ntk_t * pNtk, int fU /*=== abcDfs.c ==========================================================*/ extern ABC_DLL Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfs2( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkDfsSup_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Vec_Ptr_t * vSup, int iVerbose); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); @@ -885,6 +887,8 @@ extern ABC_DLL int Abc_NodeRef_rec( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nMinSaved, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); /*=== abcRewrite.c ==========================================================*/ extern ABC_DLL int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ); +/*=== abcRmInverters.c ======================================================*/ +extern ABC_DLL void Abc_NtkRmInverter(Abc_Ntk_t * pNtk, int iVerbose); /*=== abcSat.c ==========================================================*/ extern ABC_DLL int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fVerbose, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects ); extern ABC_DLL void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes ); diff --git a/src/base/abc/abcDfs.c b/src/base/abc/abcDfs.c index 68c005a5e3..d95c8ad024 100644 --- a/src/base/abc/abcDfs.c +++ b/src/base/abc/abcDfs.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "abc.h" +#include "misc/vec/vecPtr.h" #include "proof/cec/cec.h" ABC_NAMESPACE_IMPL_START @@ -137,6 +138,101 @@ Vec_Ptr_t * Abc_NtkDfs2( Abc_Ntk_t * pNtk ) return vNodes; } +/**Function************************************************************* + + Synopsis [Collect support nodes bounded internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsSup_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Vec_Ptr_t * vSup, int iVerbose) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pNode) ); + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + Abc_NodeSetTravIdCurrent( pNode ); + if ( Abc_ObjIsCi(pNode) || Abc_ObjIsCo(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) ) + return; + if( Vec_PtrFind(vSup, pNode) >= 0 ) + { + if(iVerbose) + { + printf("Encountered vSup Node: %s\n", Abc_ObjName(pNode)); + printf("Whose fanins are:\n"); + printf(" Fanin0: %s", Abc_ObjName(Abc_ObjFanin0(pNode))); + printf(" %d on comp\n", pNode->fCompl0); + printf(" Fanin1: %s", Abc_ObjName(Abc_ObjFanin1(pNode))); + printf(" %d on comp\n", pNode->fCompl1); + } + return; + } + assert( Abc_ObjIsNode( pNode ) ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if(iVerbose) + { + printf(" Node %s Fanin %d: ", Abc_ObjName(pNode), i); + printf("%s", Abc_ObjName(pFanin)); + printf(" %d on comp\n", i == 0 ? pNode->fCompl0 : pNode->fCompl1); + } + Abc_NtkDfsSup_rec( Abc_ObjFanin0Ntk(pFanin), vNodes, vSup, iVerbose); + } + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsInvSup_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSup, int * countFlip) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pNode) ); + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + Abc_NodeSetTravIdCurrent( pNode ); + if ( Abc_ObjIsCi(pNode) || Abc_ObjIsCo(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) ) + return; + if( Vec_PtrFind(vSup, pNode) >= 0 ) + { + return; + } + assert( Abc_ObjIsNode( pNode ) || Abc_ObjIsBox( pNode ) ); + + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if(Vec_PtrFind(vSup, pFanin) >= 0) + { + if(i == 0) + { + printf("Flipping edge on Node %s %d (Phase = %d)\n", Abc_ObjName(pNode), i, pFanin->fPhase ); + pNode->fCompl0 ^= 1; + } + else if(i == 1) + { + printf("Flipping edge on Node %s %d (Phase = %d)\n", Abc_ObjName(pNode),i , pFanin->fPhase); + pNode->fCompl1 ^= 1; + } + *countFlip = *countFlip + 1; + } + Abc_NtkDfsInvSup_rec( Abc_ObjFanin0Ntk(pFanin), vSup, countFlip ); + } +} + /**Function************************************************************* Synopsis [Returns the DFS ordered array of logic nodes.] diff --git a/src/base/abc/abcHieGia.c b/src/base/abc/abcHieGia.c index ea3c2d09a3..bb35e7f0e8 100644 --- a/src/base/abc/abcHieGia.c +++ b/src/base/abc/abcHieGia.c @@ -686,6 +686,32 @@ static Vec_Int_t * GiaHie_CountSymbsAll( Vec_Ptr_t * vNames ) } return vArray; } +static Vec_Int_t * GiaHie_CountSymbsSome( Vec_Ptr_t * vNames, int nNames ) +{ + char * pNameLast, * pName; + int i, nSymbsLast; + Vec_Int_t * vArray; + assert( vNames != NULL ); + assert( nNames >= 0 && nNames <= Vec_PtrSize(vNames) ); + if ( nNames == 0 ) + return Vec_IntAlloc( 0 ); + pNameLast = (char *)Vec_PtrEntry( vNames, 0 ); + nSymbsLast = GiaHie_CountSymbs( pNameLast ); + vArray = Vec_IntAlloc( nNames * 2 ); + Vec_IntPush( vArray, 0 ); + Vec_IntPush( vArray, nSymbsLast ); + for ( i = 1; i < nNames; i++ ) + { + pName = (char *)Vec_PtrEntry( vNames, i ); + if ( GiaHie_CountSymbs(pName) == nSymbsLast && !strncmp(pName, pNameLast, nSymbsLast) ) + continue; + nSymbsLast = GiaHie_CountSymbs( pName ); + Vec_IntPush( vArray, i ); + Vec_IntPush( vArray, nSymbsLast ); + pNameLast = pName; + } + return vArray; +} static void GiaHie_DumpIoList( Gia_Man_t * p, FILE * pFile, int fOuts, int fReverse ) { Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; @@ -1013,6 +1039,88 @@ static int GiaHie_IsBitLevelNames( Vec_Ptr_t * vNames ) Vec_IntFree( vArray ); return 1; } +static int GiaHie_IsBitLevelNamesSome( Vec_Ptr_t * vNames, int nNames ) +{ + int nGroups, idx; + Vec_Int_t * vArray; + if ( vNames == NULL ) + return 1; + if ( nNames == 0 ) + return 1; + vArray = GiaHie_CountSymbsSome( vNames, nNames ); + nGroups = Vec_IntSize(vArray) / 2; + for ( idx = 0; idx < nGroups; idx++ ) + { + int iName = Vec_IntEntry( vArray, 2*idx ); + int iNameNext = (idx + 1 < nGroups) ? Vec_IntEntry(vArray, 2*(idx + 1)) : nNames; + if ( iNameNext - iName > 1 ) + { + Vec_IntFree( vArray ); + return 0; + } + } + Vec_IntFree( vArray ); + return 1; +} +static void GiaHie_DumpPortDeclsOneSome( Vec_Ptr_t * vNames, int nBits, FILE * pFile, int fOuts, int * pfFirst ) +{ + int fUsePiPo = (nBits > 2) && GiaHie_IsBitLevelNamesSome( vNames, nBits ); + if ( nBits == 0 ) + return; + if ( fUsePiPo ) + { + int nDigits = Abc_Base10Log( nBits ); + if ( nDigits < 2 ) + nDigits = 2; + if ( !(*pfFirst) ) + fprintf( pFile, ",\n" ); + fprintf( pFile, " %s ", fOuts ? "output" : "input" ); + GiaHie_WritePiPoNames( pFile, fOuts ? "po" : "pi", nBits, nDigits, 8, 4, 0 ); + *pfFirst = 0; + return; + } + if ( vNames == NULL ) + { + if ( !(*pfFirst) ) + fprintf( pFile, ",\n" ); + fprintf( pFile, " %s [%d:0] _%c_", fOuts ? "output" : "input", nBits-1, fOuts ? 'o' : 'i' ); + *pfFirst = 0; + return; + } + { + Vec_Int_t * vArray = GiaHie_CountSymbsSome( vNames, nBits ); + int iName, Size, i; + Vec_IntForEachEntryDouble( vArray, iName, Size, i ) + { + int iNameNext = Vec_IntSize(vArray) > i+2 ? Vec_IntEntry(vArray, i+2) : nBits; + char * pName = (char *)Vec_PtrEntry(vNames, iName); + char * pNameLast = (char *)Vec_PtrEntry(vNames, iNameNext-1); + int NumBeg, NumEnd; + assert( !strncmp(pName, pNameLast, Size) ); + NumBeg = GiaHie_ReadRangeNum( pName, Size ); + NumEnd = GiaHie_ReadRangeNum( pNameLast, Size ); + if ( !(*pfFirst) ) + fprintf( pFile, ",\n" ); + fprintf( pFile, " %s ", fOuts ? "output" : "input" ); + if ( NumBeg != -1 && iName < iNameNext-1 ) + fprintf( pFile, "[%d:%d] ", NumEnd, NumBeg ); + GiaHie_PrintOneName( pFile, pName, Size ); + *pfFirst = 0; + } + Vec_IntFree( vArray ); + } +} +static void GiaHie_DumpPortDeclsSeq( Gia_Man_t * p, FILE * pFile, int fUseCtrlPis ) +{ + int fFirst = fUseCtrlPis ? 1 : 0; + if ( !fUseCtrlPis ) + { + fprintf( pFile, " input clk,\n" ); + fprintf( pFile, " input rst" ); + } + GiaHie_DumpPortDeclsOneSome( p->vNamesIn, Gia_ManPiNum(p), pFile, 0, &fFirst ); + GiaHie_DumpPortDeclsOneSome( p->vNamesOut, Gia_ManPoNum(p), pFile, 1, &fFirst ); +} static void GiaHie_DumpPortDeclsOne( Gia_Man_t * p, FILE * pFile, int fOuts, int * pfFirst ) { Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; @@ -1205,6 +1313,224 @@ static void GiaHie_DumpOutputAssigns( Gia_Man_t * p, FILE * pFile, int nDigits ) Vec_IntFree( vArray ); } } +static void GiaHie_DumpInputAssignsSome( Gia_Man_t * p, FILE * pFile, int nDigits, int nCis ) +{ + Vec_Ptr_t * vNames = p->vNamesIn; + int fUsePiPo = (nCis > 2) && GiaHie_IsBitLevelNamesSome( vNames, nCis ); + if ( nCis == 0 ) + return; + if ( fUsePiPo ) + { + int nDigitsPi = Abc_Base10Log( nCis ); + if ( nDigitsPi < 2 ) + nDigitsPi = 2; + fprintf( pFile, " assign { " ); + GiaHie_WriteObjRange( pFile, p, 0, nCis, nDigits, 11, 4, 1, 1 ); + fprintf( pFile, " } =\n { " ); + GiaHie_WritePiPoNames( pFile, "pi", nCis, nDigitsPi, 18, 4, 1 ); + fprintf( pFile, " };\n" ); + return; + } + if ( vNames == NULL ) + { + if ( nCis == 1 ) + { + fprintf( pFile, " assign " ); + GiaHie_PrintObjName( pFile, Gia_ManCiIdToId(p, 0), nDigits ); + fprintf( pFile, " = _i_;\n" ); + } + else + { + fprintf( pFile, " assign { " ); + GiaHie_WriteObjRange( pFile, p, 0, nCis, nDigits, 11, 4, 1, 1 ); + fprintf( pFile, " } = { _i_ };\n" ); + } + return; + } + { + Vec_Int_t * vArray = GiaHie_CountSymbsSome( vNames, nCis ); + int iName, Size, i; + Vec_IntForEachEntryDouble( vArray, iName, Size, i ) + { + int iNameNext = Vec_IntSize(vArray) > i+2 ? Vec_IntEntry(vArray, i+2) : nCis; + int nBits = iNameNext - iName; + char * pName = (char *)Vec_PtrEntry(vNames, iName); + if ( nBits > 1 ) + { + fprintf( pFile, " assign { " ); + GiaHie_WriteObjRange( pFile, p, iName, iNameNext, nDigits, 11, 4, 1, 1 ); + fprintf( pFile, " } =\n { " ); + GiaHie_PrintOneName( pFile, pName, Size ); + fprintf( pFile, " };\n" ); + } + else + { + fprintf( pFile, " assign " ); + GiaHie_PrintObjName( pFile, Gia_ManCiIdToId(p, iName), nDigits ); + fprintf( pFile, " = " ); + GiaHie_PrintOneName( pFile, pName, Size ); + fprintf( pFile, ";\n" ); + } + } + Vec_IntFree( vArray ); + } +} +static void GiaHie_DumpOutputAssignsSome( Gia_Man_t * p, FILE * pFile, int nDigits, int nCos ) +{ + Vec_Ptr_t * vNames = p->vNamesOut; + int fUsePiPo = (nCos > 2) && GiaHie_IsBitLevelNamesSome( vNames, nCos ); + if ( nCos == 0 ) + return; + if ( fUsePiPo ) + { + int nDigitsPo = Abc_Base10Log( nCos ); + if ( nDigitsPo < 2 ) + nDigitsPo = 2; + fprintf( pFile, " assign { " ); + GiaHie_WritePiPoNames( pFile, "po", nCos, nDigitsPo, 11, 4, 1 ); + fprintf( pFile, " } =\n { " ); + GiaHie_WriteObjRange( pFile, p, 0, nCos, nDigits, 18, 4, 1, 0 ); + fprintf( pFile, " };\n" ); + return; + } + if ( vNames == NULL ) + { + if ( nCos == 1 ) + { + fprintf( pFile, " assign _o_ = " ); + GiaHie_PrintObjName( pFile, Gia_ManCoIdToId(p, 0), nDigits ); + fprintf( pFile, ";\n" ); + } + else + { + fprintf( pFile, " assign { _o_ } = { " ); + GiaHie_WriteObjRange( pFile, p, 0, nCos, nDigits, 18, 4, 1, 0 ); + fprintf( pFile, " };\n" ); + } + return; + } + { + Vec_Int_t * vArray = GiaHie_CountSymbsSome( vNames, nCos ); + int iName, Size, i; + Vec_IntForEachEntryDouble( vArray, iName, Size, i ) + { + int iNameNext = Vec_IntSize(vArray) > i+2 ? Vec_IntEntry(vArray, i+2) : nCos; + int nBits = iNameNext - iName; + char * pName = (char *)Vec_PtrEntry(vNames, iName); + if ( nBits > 1 ) + { + fprintf( pFile, " assign { " ); + GiaHie_PrintOneName( pFile, pName, Size ); + fprintf( pFile, " } =\n { " ); + GiaHie_WriteObjRange( pFile, p, iName, iNameNext, nDigits, 18, 4, 1, 0 ); + fprintf( pFile, " };\n" ); + } + else + { + fprintf( pFile, " assign " ); + GiaHie_PrintOneName( pFile, pName, Size ); + fprintf( pFile, " = " ); + GiaHie_PrintObjName( pFile, Gia_ManCoIdToId(p, iName), nDigits ); + fprintf( pFile, ";\n" ); + } + } + Vec_IntFree( vArray ); + } +} +static void GiaHie_DumpInterfaceAssignsSeq( Gia_Man_t * p, char * pFileName, int fUseCtrlPis ) +{ + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nPerLine = 4, nOnLine = 0; + int i; + FILE * pFile; + if ( fUseCtrlPis && Gia_ManPiNum(p) < 2 ) + { + printf( "Sequential Verilog with \"-c\" expects at least 2 primary inputs.\n" ); + return; + } + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + + fprintf( pFile, "module " ); + GiaHie_DumpModuleName( pFile, p->pName ); + fprintf( pFile, " (\n" ); + GiaHie_DumpPortDeclsSeq( p, pFile, fUseCtrlPis ); + fprintf( pFile, "\n);\n\n" ); + + if ( Gia_ManPiNum(p) ) + { + fprintf( pFile, " wire " ); + GiaHie_WriteObjRange( pFile, p, 0, Gia_ManPiNum(p), nDigits, 7, 4, 0, 1 ); + fprintf( pFile, ";\n\n" ); + GiaHie_DumpInputAssignsSome( p, pFile, nDigits, Gia_ManPiNum(p) ); + fprintf( pFile, "\n" ); + } + if ( Gia_ManCoNum(p) ) + { + fprintf( pFile, " wire " ); + GiaHie_WriteObjRange( pFile, p, 0, Gia_ManCoNum(p), nDigits, 7, 4, 0, 0 ); + fprintf( pFile, ";\n\n" ); + } + if ( Gia_ManRegNum(p) ) + { + fprintf( pFile, " reg " ); + GiaHie_WriteObjRange( pFile, p, Gia_ManPiNum(p), Gia_ManCiNum(p), nDigits, 7, 4, 0, 1 ); + fprintf( pFile, ";\n\n" ); + } + + if ( GiaHie_ConstUsed(p) ) + fprintf( pFile, " wire n%0*d = 1'b0;\n\n", nDigits, 0 ); + + Gia_ManForEachAnd( p, pObj, i ) + { + if ( nOnLine == 0 ) + fprintf( pFile, " " ); + fprintf( pFile, "wire n%0*d = ", nDigits, i ); + GiaHie_PrintObjLit( pFile, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj), nDigits ); + fprintf( pFile, " & " ); + GiaHie_PrintObjLit( pFile, Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC1(pObj), nDigits ); + fprintf( pFile, "; " ); + nOnLine++; + if ( nOnLine == nPerLine ) + { + fprintf( pFile, "\n" ); + nOnLine = 0; + } + else + fprintf( pFile, " " ); + } + if ( nOnLine != 0 ) + fprintf( pFile, "\n" ); + if ( Gia_ManAndNum(p) ) + fprintf( pFile, "\n" ); + + Gia_ManForEachCo( p, pObj, i ) + { + fprintf( pFile, " assign n%0*d = ", nDigits, Gia_ManCoIdToId(p, i) ); + GiaHie_PrintObjLit( pFile, Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj), nDigits ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, "\n" ); + GiaHie_DumpOutputAssignsSome( p, pFile, nDigits, Gia_ManPoNum(p) ); + fprintf( pFile, "\n" ); + + fprintf( pFile, " always @(posedge " ); + if ( fUseCtrlPis ) + GiaHie_PrintObjName( pFile, Gia_ManCiIdToId(p, 0), nDigits ); + else + fprintf( pFile, "clk" ); + fprintf( pFile, ") begin\n" ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) + fprintf( pFile, " n%0*d <= n%0*d;\n", nDigits, Gia_ObjId(p, pObjRo), nDigits, Gia_ObjId(p, pObjRi) ); + fprintf( pFile, " end\n\n" ); + fprintf( pFile, "endmodule\n\n" ); + fclose( pFile ); +} /**Function************************************************************* @@ -1217,13 +1543,18 @@ static void GiaHie_DumpOutputAssigns( Gia_Man_t * p, FILE * pFile, int nDigits ) SeeAlso [] ***********************************************************************/ -static void GiaHie_DumpInterfaceAssigns( Gia_Man_t * p, char * pFileName ) +static void GiaHie_DumpInterfaceAssigns( Gia_Man_t * p, char * pFileName, int fUseCtrlPis ) { Gia_Obj_t * pObj; int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); int nPerLine = 4; int nOnLine = 0; int i; + if ( Gia_ManRegNum(p) > 0 ) + { + GiaHie_DumpInterfaceAssignsSeq( p, pFileName, fUseCtrlPis ); + return; + } FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { @@ -1494,7 +1825,7 @@ static void GiaHie_DumpMappedLuts( Gia_Man_t * p, char * pFileName ) SeeAlso [] ***********************************************************************/ -void Gia_WriteVerilog( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fVerbose ) +void Gia_WriteVerilogInt( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fVerbose, int fUseCtrlPis ) { (void)fVerbose; if ( pFileName == NULL || pGia == NULL ) @@ -1502,7 +1833,12 @@ void Gia_WriteVerilog( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fV if ( fUseGates ) GiaHie_DumpInterfaceGates( pGia, pFileName ); else - GiaHie_DumpInterfaceAssigns( pGia, pFileName ); + GiaHie_DumpInterfaceAssigns( pGia, pFileName, fUseCtrlPis ); +} + +void Gia_WriteVerilog( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fVerbose ) +{ + Gia_WriteVerilogInt( pFileName, pGia, fUseGates, fVerbose, 0 ); } /**Function************************************************************* diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c index 9d6c4f0ea4..047cbf521a 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -39,6 +39,86 @@ ABC_NAMESPACE_IMPL_START /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +static int Abc_NtkDupDfsSameFanins( Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 ) +{ + Abc_Obj_t * pFanin0, * pFanin1; + int i; + if ( pObj0 == NULL || pObj1 == NULL || Abc_ObjFaninNum(pObj0) != Abc_ObjFaninNum(pObj1) ) + return 0; + Abc_ObjForEachFanin( pObj0, pFanin0, i ) + { + pFanin1 = Abc_ObjFanin( pObj1, i ); + if ( pFanin0 != pFanin1 ) + return 0; + } + return 1; +} +static Abc_Obj_t * Abc_NtkDupDfsFindTwin( Vec_Ptr_t * vNodes, Vec_Int_t * vSeen, Abc_Obj_t * pObj ) +{ + Mio_Gate_t * pGate = (Mio_Gate_t *)pObj->pData; + Abc_Obj_t * pObj2; + int i; + if ( pGate == NULL || Mio_GateReadTwin(pGate) == NULL ) + return NULL; + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj2, i ) + { + if ( pObj2 == pObj || Vec_IntEntry(vSeen, Abc_ObjId(pObj2)) ) + continue; + if ( (Mio_Gate_t *)pObj2->pData != Mio_GateReadTwin(pGate) ) + continue; + if ( Abc_NtkDupDfsSameFanins(pObj, pObj2) ) + return pObj2; + } + return NULL; +} +static Vec_Ptr_t * Abc_NtkDupDfsOrderTwinNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ) +{ + Vec_Int_t * vSeen; + Vec_Ptr_t * vRes; + Abc_Obj_t * pObj, * pTwin; + Mio_Gate_t * pGate, * pGateBase; + int i; + if ( !Abc_NtkHasMapping(pNtk) || pNtk->pManFunc == NULL ) + return vNodes; + vSeen = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + vRes = Vec_PtrAlloc( Vec_PtrSize(vNodes) ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + if ( Vec_IntEntry(vSeen, Abc_ObjId(pObj)) ) + continue; + pGate = (Mio_Gate_t *)pObj->pData; + if ( pGate == NULL || Mio_GateReadTwin(pGate) == NULL ) + { + Vec_PtrPush( vRes, pObj ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pObj), 1 ); + continue; + } + pTwin = Abc_NtkDupDfsFindTwin( vNodes, vSeen, pObj ); + if ( pTwin == NULL ) + { + Vec_PtrPush( vRes, pObj ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pObj), 1 ); + continue; + } + pGateBase = Mio_LibraryReadGateByName( (Mio_Library_t *)pNtk->pManFunc, Mio_GateReadName(pGate), NULL ); + if ( pGateBase == (Mio_Gate_t *)pTwin->pData ) + { + Vec_PtrPush( vRes, pTwin ); + Vec_PtrPush( vRes, pObj ); + } + else + { + Vec_PtrPush( vRes, pObj ); + Vec_PtrPush( vRes, pTwin ); + } + Vec_IntWriteEntry( vSeen, Abc_ObjId(pObj), 1 ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pTwin), 1 ); + } + Vec_IntFree( vSeen ); + Vec_PtrFree( vNodes ); + return vRes; +} + /**Function************************************************************* Synopsis [Creates a new Ntk.] @@ -548,6 +628,7 @@ Abc_Ntk_t * Abc_NtkDupDfs( Abc_Ntk_t * pNtk ) pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); // copy the internal nodes vNodes = Abc_NtkDfs( pNtk, 0 ); + vNodes = Abc_NtkDupDfsOrderTwinNodes( pNtk, vNodes ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 0 ); Vec_PtrFree( vNodes ); @@ -2621,4 +2702,3 @@ Abc_Ntk_t * Abc_NtkCreateFromGias( char * pName, Vec_Ptr_t * vGias, Gia_Man_t * ABC_NAMESPACE_IMPL_END - diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 6cc8df18fc..a996515240 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -18,6 +18,7 @@ ***********************************************************************/ +#include #include "base/abc/abc.h" #include "base/main/main.h" #include "base/main/mainInt.h" @@ -149,6 +150,7 @@ static int Abc_CommandRunEco ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandRunGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunScript ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRmInverter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -426,6 +428,8 @@ static int Abc_CommandAbc9WriteVer ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Write ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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_CommandAbc9Origins ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9OriginsId ( 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 ); @@ -579,6 +583,7 @@ static int Abc_CommandAbc9GroupProve ( Abc_Frame_t * pAbc, int argc, cha 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_CommandAbc9SProve2 ( 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 ); @@ -660,10 +665,14 @@ static int Abc_CommandAbc9BsFind ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9AndCare ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cuts ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Divide ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Pipeline ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Unpipeline ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Regio ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9eSLIM ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9elSLIM ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9CatBtor ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -684,7 +693,9 @@ extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wr typedef struct Wlc_Ntk_t_ Wlc_Ntk_t; typedef struct Wlc_BstPar_t_ Wlc_BstPar_t; extern Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pPars ); -extern int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fUseUif, Wlc_Ntk_t * pWlc, int fVerbose, int fVeryVerbose, int fSilent ); +extern int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fUseUif, Wlc_Ntk_t * pWlc, int fVerbose, int fVeryVerbose, int fSilent, char * pReplayFile, char * pUfarArgs ); +extern int Cec_GiaReplayReadParams( char * pFileName, int * pnProcs, int * pnTimeOut, int * pnTimeOut2, int * pnTimeOut3, int * pfUseUif ); +extern int Cec_GiaReplayTest( Gia_Man_t * p, Wlc_Ntk_t * pWlc, char * pFileName, int fVerbose, int fVeryVerbose, int fSilent ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -1001,6 +1012,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "resub_unate", Abc_CommandResubUnate, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "resub_core", Abc_CommandResubCore, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "resub_check", Abc_CommandResubCheck, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "rd_inv", Abc_CommandRmInverter, 1 ); // Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "lutcasdec", Abc_CommandLutCasDec, 1 ); @@ -1269,6 +1281,8 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&write", Abc_CommandAbc9Write, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&wlut", Abc_CommandAbc9WriteLut, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&ps", Abc_CommandAbc9Ps, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&origins", Abc_CommandAbc9Origins, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&origins_id", Abc_CommandAbc9OriginsId, 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 ); @@ -1421,7 +1435,8 @@ 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", "&sprove", Abc_CommandAbc9SProve, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sprove2", Abc_CommandAbc9SProve2, 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 ); @@ -1509,10 +1524,14 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&andcare", Abc_CommandAbc9AndCare, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cuts", Abc_CommandAbc9Cuts, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "÷", Abc_CommandAbc9Divide, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&pipe", Abc_CommandAbc9Pipeline, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&unpipe", Abc_CommandAbc9Unpipeline, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "®io", Abc_CommandAbc9Regio, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&eslim", Abc_CommandAbc9eSLIM, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "elslim", Abc_CommandAbc9elSLIM, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&catbtor", Abc_CommandAbc9CatBtor, 0 ); { @@ -7983,7 +8002,58 @@ int Abc_CommandRunTest( Abc_Frame_t * pAbc, int argc, char ** argv ) Synopsis [] - Description [Orchestration synthesis] + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRmInverter( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Extra_UtilGetoptReset(); + int iVerbose = 0; + int c; + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + iVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkHasAig(pNtk) || !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command only works on AIG network.\n" ); + return 1; + } + Abc_NtkRmInverter(pNtk, iVerbose); + return 0; + +usage: + Abc_Print( -2, "usage: rd_inv\n" ); + Abc_Print( -2, "\t redistribute inverters on self-dual and self-anti-dual functions in network\n" ); + Abc_Print( -2, "\t-v : verbose output\n"); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] SideEffects [] @@ -10590,19 +10660,391 @@ int Abc_CommandMajExact( Abc_Frame_t * pAbc, int argc, char ** argv ) SeeAlso [] ***********************************************************************/ +static int Abc_TwoExactPermAddFanin( int * pFans, int iNode, int iFanin ) +{ + int * pNode = pFans + 2 * iNode; + if ( pNode[0] == iFanin || pNode[1] == iFanin ) + return 0; + if ( pNode[0] == -1 && pNode[1] == -1 ) + pNode[Abc_Random(0) & 1] = iFanin; + else if ( pNode[0] == -1 ) + pNode[0] = iFanin; + else if ( pNode[1] == -1 ) + pNode[1] = iFanin; + else + return 0; + return 1; +} +static int Abc_TwoExactPermAddRequired( int * pFans, int nVars, int nNodes, int iFanin ) +{ + int iNodeStart = (iFanin + 1 > nVars) ? iFanin + 1 - nVars : 0; + int i, nChoices = 0, iChoice = -1; + for ( i = iNodeStart; i < nNodes; i++ ) + { + int * pNode = pFans + 2 * i; + if ( pNode[0] == iFanin || pNode[1] == iFanin ) + continue; + if ( pNode[0] != -1 && pNode[1] != -1 ) + continue; + if ( Abc_Random(0) % ++nChoices == 0 ) + iChoice = i; + } + return iChoice >= 0 && Abc_TwoExactPermAddFanin( pFans, iChoice, iFanin ); +} +static int Abc_TwoExactPermCountDistinct( int * pFans, int nVars, int iNode ) +{ + int iPrevObj = nVars + iNode - 1; + int pVals[4], nVals = 0, i, k; + assert( iNode > 0 ); + for ( i = iNode - 1; i <= iNode; i++ ) + for ( k = 0; k < 2; k++ ) + { + int v = pFans[2 * i + k]; + int j, fSeen = 0; + if ( v == iPrevObj ) + continue; + for ( j = 0; j < nVals; j++ ) + fSeen |= pVals[j] == v; + if ( !fSeen ) + pVals[nVals++] = v; + } + return nVals; +} +static int Abc_TwoExactPermCheck( int * pFans, int nVars, int nNodes, int fStrict ) +{ + int nObjs = nVars + nNodes; + int * pUsed = ABC_CALLOC( int, nObjs ); + int i, RetValue = 1; + for ( i = 0; i < nNodes; i++ ) + { + if ( pFans[2*i] < 0 || pFans[2*i+1] < 0 || pFans[2*i] >= nVars + i || pFans[2*i+1] >= nVars + i || pFans[2*i] == pFans[2*i+1] ) + RetValue = 0; + if ( fStrict && i > 0 && Abc_TwoExactPermCountDistinct(pFans, nVars, i) < 3 ) + RetValue = 0; + if ( !RetValue ) + break; + pUsed[pFans[2*i]]++; + pUsed[pFans[2*i+1]]++; + } + if ( RetValue ) + for ( i = 0; i < nObjs - 1; i++ ) + if ( pUsed[i] == 0 ) + { + RetValue = 0; + break; + } + ABC_FREE( pUsed ); + return RetValue; +} +static char * Abc_TwoExactPermEncode( int * pFans, int nVars, int nNodes ) +{ + char * pPerm = ABC_ALLOC( char, 3 * nNodes ); + int i, k, Pos = 0; + for ( i = 0; i < nNodes; i++ ) + { + if ( i ) + pPerm[Pos++] = '_'; + for ( k = 0; k < 2; k++ ) + pPerm[Pos++] = pFans[2*i+k] >= 0 && pFans[2*i+k] < nVars ? 'a' + pFans[2*i+k] : '*'; + } + pPerm[Pos] = 0; + return pPerm; +} +static char * Abc_TwoExactObjName( int iObj, int nVars, char * pBuffer ) +{ + if ( iObj < 0 ) + sprintf( pBuffer, "*" ); + else if ( iObj < nVars ) + sprintf( pBuffer, "%c", 'a' + iObj ); + else if ( iObj - nVars < 26 ) + sprintf( pBuffer, "%c", 'A' + iObj - nVars ); + else + sprintf( pBuffer, "N%d", iObj - nVars ); + return pBuffer; +} +static char * Abc_TwoExactPermEncodeFull( int * pFans, int nVars, int nNodes ) +{ + int nSize = 8 * (nNodes + 1); + char * pPerm = ABC_ALLOC( char, nSize ); + int i, k, Pos = 0; + char Name[16]; + for ( i = 0; i < nNodes; i++ ) + { + if ( i ) + pPerm[Pos++] = '_'; + for ( k = 0; k < 2; k++ ) + Pos += sprintf( pPerm + Pos, "%s", Abc_TwoExactObjName(pFans[2*i+k], nVars, Name) ); + } + pPerm[Pos] = 0; + return pPerm; +} +static int Abc_TwoExactPermParseObj( char ** ppToken, int nVars, int nNodes, int * pObj ) +{ + char * pToken = *ppToken; + if ( *pToken == '*' ) + { + *pObj = -1; + *ppToken = pToken + 1; + return 1; + } + if ( *pToken >= 'a' && *pToken < 'a' + nVars ) + { + *pObj = *pToken - 'a'; + *ppToken = pToken + 1; + return 1; + } + if ( *pToken >= 'A' && *pToken <= 'Z' ) + { + *pObj = nVars + *pToken - 'A'; + *ppToken = pToken + 1; + return *pObj < nVars + nNodes; + } + if ( *pToken == 'N' ) + { + char * pNext = pToken + 1; + int Num = 0; + if ( *pNext < '0' || *pNext > '9' ) + return 0; + while ( *pNext >= '0' && *pNext <= '9' ) + Num = 10 * Num + *pNext++ - '0'; + *pObj = nVars + Num; + *ppToken = pNext; + return *pObj < nVars + nNodes; + } + return 0; +} +static int Abc_TwoExactPermAddDcs( int * pFans, int nVars, int nNodes, int nDcs, int nSkip, int fAll ) +{ + int i, k, nLetters = 0; + if ( nDcs == 0 ) + return 1; + for ( i = nSkip; i < 2 * nNodes; i++ ) + nLetters += pFans[i] >= 0 && (fAll || pFans[i] < nVars); + if ( nDcs > nLetters ) + return 0; + for ( k = 0; k < nDcs; k++ ) + { + int iChoice = -1, nChoices = 0; + for ( i = nSkip; i < 2 * nNodes; i++ ) + if ( pFans[i] >= 0 && (fAll || pFans[i] < nVars) && Abc_Random(0) % ++nChoices == 0 ) + iChoice = i; + assert( iChoice >= 0 ); + pFans[iChoice] = -1; + } + return 1; +} +static int * Abc_TwoExactPermRandom( int nVars, int nNodes, int nDcs ) +{ + int nObjs = nVars + nNodes; + int Attempt, i, k; + for ( Attempt = 0; Attempt < 200; Attempt++ ) + { + int * pFans = ABC_ALLOC( int, 2 * nNodes ); + int fOk = 1; + for ( i = 0; i < 2 * nNodes; i++ ) + pFans[i] = -1; + for ( i = nObjs - 2; i >= nVars && fOk; i-- ) + fOk = Abc_TwoExactPermAddRequired( pFans, nVars, nNodes, i ); + for ( i = 0; i < nVars && fOk; i++ ) + fOk = Abc_TwoExactPermAddRequired( pFans, nVars, nNodes, i ); + for ( i = 0; i < nNodes && fOk; i++ ) + { + int Limit = nVars + i; + for ( k = 0; k < 2; k++ ) + { + int Try; + if ( pFans[2*i+k] != -1 ) + continue; + for ( Try = 0; Try < 100; Try++ ) + if ( Abc_TwoExactPermAddFanin( pFans, i, Abc_Random(0) % Limit ) ) + break; + if ( Try == 100 ) + fOk = 0; + } + if ( pFans[2*i] > pFans[2*i+1] ) + ABC_SWAP( int, pFans[2*i], pFans[2*i+1] ); + } + if ( fOk && Abc_TwoExactPermCheck(pFans, nVars, nNodes, 1) && Abc_TwoExactPermAddDcs(pFans, nVars, nNodes, nDcs, 0, 0) ) + return pFans; + ABC_FREE( pFans ); + } + return NULL; +} +static int * Abc_TwoExactPermRandomSeeded( int nVars, int nNodes, int nDcs, Vec_Int_t * vSeedPairs, int nSeeds ) +{ + int nObjs = nVars + nNodes; + int Attempt, i, k; + nSeeds = Abc_MinInt( nSeeds, Vec_IntSize(vSeedPairs) ); + for ( Attempt = 0; Attempt < 200; Attempt++ ) + { + int * pFans = ABC_ALLOC( int, 2 * nNodes ); + int * pUsed = ABC_CALLOC( int, Vec_IntSize(vSeedPairs) ); + int fOk = 1; + for ( i = 0; i < 2 * nNodes; i++ ) + pFans[i] = -1; + for ( i = 0; i < nSeeds; i++ ) + { + int s, iSeed = -1, nChoices = 0; + for ( s = 0; s < Vec_IntSize(vSeedPairs); s++ ) + if ( !pUsed[s] && Abc_Random(0) % ++nChoices == 0 ) + iSeed = s; + assert( iSeed >= 0 ); + pUsed[iSeed] = 1; + int Pair = Vec_IntEntry( vSeedPairs, iSeed ); + pFans[2*i] = Pair / nVars; + pFans[2*i+1] = Pair % nVars; + } + for ( i = nObjs - 2; i >= nVars && fOk; i-- ) + fOk = Abc_TwoExactPermAddRequired( pFans, nVars, nNodes, i ); + for ( i = 0; i < nVars && fOk; i++ ) + fOk = Abc_TwoExactPermAddRequired( pFans, nVars, nNodes, i ); + for ( i = 0; i < nNodes && fOk; i++ ) + { + int Limit = nVars + i; + for ( k = 0; k < 2; k++ ) + { + int Try; + if ( pFans[2*i+k] != -1 ) + continue; + for ( Try = 0; Try < 100; Try++ ) + if ( Abc_TwoExactPermAddFanin( pFans, i, Abc_Random(0) % Limit ) ) + break; + if ( Try == 100 ) + fOk = 0; + } + if ( pFans[2*i] > pFans[2*i+1] ) + ABC_SWAP( int, pFans[2*i], pFans[2*i+1] ); + } + if ( fOk && Abc_TwoExactPermCheck(pFans, nVars, nNodes, 0) && Abc_TwoExactPermAddDcs(pFans, nVars, nNodes, nDcs, 2*nSeeds, 1) ) + { + ABC_FREE( pUsed ); + return pFans; + } + ABC_FREE( pUsed ); + ABC_FREE( pFans ); + } + return NULL; +} +static char * Abc_TwoExactCofactorHex( char * pHex, int nVars, int iVar, int Value ) +{ + word pTruth[64], pCof[64]; + int nCofVars = nVars - 1; + int nMints = 1 << nCofVars; + char * pRes = ABC_ALLOC( char, (nCofVars >= 2 ? (1 << (nCofVars-2)) : 1) + 10 ); + int m; + memset( pTruth, 0, sizeof(word) * 64 ); + memset( pCof, 0, sizeof(word) * 64 ); + Abc_TtReadHex( pTruth, pHex ); + for ( m = 0; m < nMints; m++ ) + { + int Low = m & ((1 << iVar) - 1); + int High = m >> iVar; + int Mint = Low | (Value << iVar) | (High << (iVar + 1)); + if ( Abc_TtGetBit(pTruth, Mint) ) + Abc_TtSetBit( pCof, m ); + } + Extra_PrintHexadecimalString( pRes, (unsigned *)pCof, nCofVars ); + return pRes; +} +static int Abc_TwoExactRun( Bmc_EsPar_t * pPars ) +{ + extern int Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ); + extern int Exa_ManExactSynthesis2( Bmc_EsPar_t * pPars ); + return pPars->fGlucose ? Exa_ManExactSynthesis( pPars ) : Exa_ManExactSynthesis2( pPars ); +} +static int Abc_TwoExactRunMin( Bmc_EsPar_t * pPars, int nNodeMax ) +{ + int n, nNodeBeg = pPars->nVars + 1; + int fFound = 0; + for ( n = nNodeBeg; n <= nNodeMax; n++ ) + { + if ( !pPars->fSilent ) + printf( "\nTrying N = %d:\n", n ); + pPars->nNodes = n; + ABC_FREE( pPars->pSolFans ); + fFound = Abc_TwoExactRun( pPars ); + if ( fFound ) + return n; + } + return 0; +} +static Vec_Int_t * Abc_TwoExactCofactorSeeds( Bmc_EsPar_t * pPars, int nNodeMax ) +{ + int Counts[16][16]; + int v, c, i, k, nPairs = 0; + Vec_Int_t * vPairs = Vec_IntAlloc( 16 ); + memset( Counts, 0, sizeof(Counts) ); + if ( pPars->nVars > 16 ) + return vPairs; + for ( v = 0; v < pPars->nVars; v++ ) + for ( c = 0; c < 2; c++ ) + { + Bmc_EsPar_t CofPars, * pCof = &CofPars; + char * pCofHex = Abc_TwoExactCofactorHex( pPars->pTtStr, pPars->nVars, v, c ); + int nFound; + Bmc_EsParSetDefault( pCof ); + pCof->nVars = pPars->nVars - 1; + pCof->nNodes = nNodeMax; + pCof->pTtStr = pCofHex; + pCof->fOnlyAnd = pPars->fOnlyAnd; + pCof->fGlucose = pPars->fGlucose; + pCof->RuntimeLim = pPars->RuntimeLim ? pPars->RuntimeLim : 1; + pCof->fSilent = 1; + nFound = Abc_TwoExactRunMin( pCof, nNodeMax ); + if ( nFound ) + { + printf( "Cofactor %c=%d: minimum N = %d, truth = %s\n", 'a' + v, c, nFound, pCofHex ); + for ( i = 0; i < nFound; i++ ) + { + int Fan0 = pCof->pSolFans[2*i]; + int Fan1 = pCof->pSolFans[2*i+1]; + if ( Fan0 >= pCof->nVars || Fan1 >= pCof->nVars ) + continue; + Fan0 += Fan0 >= v; + Fan1 += Fan1 >= v; + if ( Fan0 > Fan1 ) + ABC_SWAP( int, Fan0, Fan1 ); + Counts[Fan0][Fan1]++; + } + } + else + printf( "Cofactor %c=%d: no solution up to N = %d, truth = %s\n", 'a' + v, c, nNodeMax, pCofHex ); + ABC_FREE( pCof->pSolFans ); + ABC_FREE( pCofHex ); + } + for ( k = pPars->nVars * pPars->nVars; k > 0; k-- ) + { + int BestI = -1, BestJ = -1, Best = 0; + for ( i = 0; i < pPars->nVars; i++ ) + for ( v = i + 1; v < pPars->nVars; v++ ) + if ( Counts[i][v] > Best ) + { + Best = Counts[i][v]; + BestI = i; + BestJ = v; + } + if ( Best == 0 ) + break; + printf( "Frequent seed %d: %c%c appears %d time%s.\n", ++nPairs, 'a' + BestI, 'a' + BestJ, Best, Best == 1 ? "" : "s" ); + for ( v = 0; v < Best; v++ ) + Vec_IntPush( vPairs, BestI * pPars->nVars + BestJ ); + Counts[BestI][BestJ] = 0; + } + return vPairs; +} int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ); - extern void Exa_ManExactSynthesis2( Bmc_EsPar_t * pPars ); + extern int Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ); + extern int Exa_ManExactSynthesis2( Bmc_EsPar_t * pPars ); extern void Exa_ManExactSynthesis4( Bmc_EsPar_t * pPars ); extern void Exa_ManExactSynthesis5( Bmc_EsPar_t * pPars ); extern void Exa_ManExactSynthesis6( Bmc_EsPar_t * pPars, char * pFileName ); extern void Exa_ManExactSynthesis7( Bmc_EsPar_t * pPars, int GateSize ); - int c, fKissat = 0, fKissat2 = 0, fUseNands = 0, GateSize = 0; + int c, fKissat = 0, fKissat2 = 0, fUseNands = 0, GateSize = 0, nCandPerms = 0, nPermDcs = 0, fTryMin = 0, fSmartGen = 0, nSeedNodes = 0; Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INTGSabdconugklmvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INTGSPCDEabdconugklmtxvh" ) ) != EOF ) { switch ( c ) { @@ -10659,6 +11101,48 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pGuide = argv[globalUtilOptind]; globalUtilOptind++; break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by a variable permutation.\n" ); + goto usage; + } + pPars->pPermStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCandPerms = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCandPerms < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + nPermDcs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPermDcs < 0 ) + goto usage; + break; + case 'E': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-E\" should be followed by an integer.\n" ); + goto usage; + } + nSeedNodes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSeedNodes < 0 ) + goto usage; + break; case 'a': pPars->fOnlyAnd ^= 1; break; @@ -10692,6 +11176,12 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': pPars->fCard ^= 1; break; + case 't': + fTryMin ^= 1; + break; + case 'x': + fSmartGen ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -10705,6 +11195,11 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) { if ( strstr(argv[globalUtilOptind], ".") ) { + if ( pPars->pPermStr || nCandPerms ) + { + Abc_Print( -1, "Permutation options -P and -C are not supported when reading the function from a file.\n" ); + return 1; + } Exa_ManExactSynthesis6( pPars, argv[globalUtilOptind] ); return 0; } @@ -10730,6 +11225,147 @@ 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 ( nPermDcs && nCandPerms == 0 ) + { + Abc_Print( -1, "Command line switch \"-D\" can only be used together with \"-C\".\n" ); + return 1; + } + if ( fSmartGen && nCandPerms == 0 ) + { + Abc_Print( -1, "Command line switch \"-x\" can only be used together with \"-C\".\n" ); + return 1; + } + if ( nSeedNodes && !fSmartGen ) + { + Abc_Print( -1, "Command line switch \"-E\" can only be used together with \"-x\".\n" ); + return 1; + } + if ( nCandPerms && pPars->pPermStr ) + { + Abc_Print( -1, "Command line switch \"-C\" cannot be used together with \"-P\".\n" ); + return 1; + } + if ( fTryMin && nCandPerms ) + { + Abc_Print( -1, "Command line switch \"-t\" cannot be used together with \"-C\".\n" ); + return 1; + } + if ( nPermDcs > 2 * pPars->nNodes ) + { + Abc_Print( -1, "The number of don't-care positions should not exceed %d.\n", 2 * pPars->nNodes ); + return 1; + } + if ( pPars->pPermStr ) + { + char * pToken = pPars->pPermStr; + int nEntries = 0; + while ( *pToken ) + { + int iObj = -1; + if ( *pToken == '_' ) + { + pToken++; + continue; + } + if ( !Abc_TwoExactPermParseObj(&pToken, pPars->nVars, pPars->nNodes, &iObj) ) + { + Abc_Print( -1, "Permutation should use '*', '_', input variables 'a' through '%c', or internal nodes 'A' through '%c'.\n", 'a' + pPars->nVars - 1, 'A' + Abc_MinInt(pPars->nNodes, 26) - 1 ); + return 1; + } + nEntries++; + } + if ( nEntries != 2 * pPars->nNodes ) + { + Abc_Print( -1, "Permutation should contain %d non-separator symbols (instead of %d).\n", 2 * pPars->nNodes, nEntries ); + return 1; + } + if ( fUseNands || fKissat || fKissat2 || pPars->fCard ) + { + Abc_Print( -1, "Permutation option -P is currently supported by the default and Glucose (-g) twoexact engines.\n" ); + return 1; + } + } + if ( nCandPerms ) + { + int i, fFound = 0, nGenerated = 0, nFailed = 0, fSilentSave = pPars->fSilent; + Vec_Int_t * vSeedPairs = NULL; + abctime clk = Abc_Clock(); + if ( fUseNands || fKissat || fKissat2 || pPars->fCard ) + { + Abc_Print( -1, "Candidate generation with -C is currently supported by the default and Glucose (-g) twoexact engines.\n" ); + return 1; + } + Abc_Random( 1 ); + if ( fSmartGen ) + { + printf( "Deriving frequent seed nodes from cofactors.\n" ); + vSeedPairs = Abc_TwoExactCofactorSeeds( pPars, pPars->nNodes ); + nSeedNodes = Abc_MinInt( nSeedNodes, Vec_IntSize(vSeedPairs) ); + printf( "Trying %d smart candidate input assignments with %d frozen seed node%s and %d randomized don't-care position%s.\n", nCandPerms, nSeedNodes, nSeedNodes == 1 ? "" : "s", nPermDcs, nPermDcs == 1 ? "" : "s" ); + } + else + printf( "Trying %d random candidate input assignments with %d randomized don't-care position%s.\n", nCandPerms, nPermDcs, nPermDcs == 1 ? "" : "s" ); + pPars->fSilent = 1; + for ( i = 0; i < nCandPerms; i++ ) + { + int * pFans = fSmartGen ? Abc_TwoExactPermRandomSeeded( pPars->nVars, pPars->nNodes, nPermDcs, vSeedPairs, nSeedNodes ) : Abc_TwoExactPermRandom( pPars->nVars, pPars->nNodes, nPermDcs ); + char * pPerm, * pStruct; + if ( pFans == NULL ) + { + nFailed++; + continue; + } + pPerm = Abc_TwoExactPermEncode( pFans, pPars->nVars, pPars->nNodes ); + pStruct = Abc_TwoExactPermEncodeFull( pFans, pPars->nVars, pPars->nNodes ); + nGenerated++; + pPars->pPermFans = pFans; + pPars->pPermStr = pPerm; + if ( nGenerated == 1 || nGenerated % 10000 == 0 ) + printf( "Trying candidate %d/%d: %s\n", nGenerated, nCandPerms, pStruct ); + fFound = pPars->fGlucose ? Exa_ManExactSynthesis( pPars ) : Exa_ManExactSynthesis2( pPars ); + if ( fFound ) + { + pPars->fSilent = fSilentSave; + Abc_TwoExactRun( pPars ); + printf( "Found solution using candidate %d: %s\n", nGenerated, pStruct ); + ABC_FREE( pStruct ); + ABC_FREE( pPerm ); + ABC_FREE( pFans ); + break; + } + ABC_FREE( pStruct ); + ABC_FREE( pPerm ); + ABC_FREE( pFans ); + pPars->pPermStr = NULL; + pPars->pPermFans = NULL; + } + pPars->pPermStr = NULL; + pPars->pPermFans = NULL; + pPars->fSilent = fSilentSave; + Vec_IntFreeP( &vSeedPairs ); + ABC_FREE( pPars->pSolFans ); + if ( !fFound ) + printf( "No solution found after trying %d generated candidate%s (%d generation failure%s).\n", nGenerated, nGenerated == 1 ? "" : "s", nFailed, nFailed == 1 ? "" : "s" ); + Abc_PrintTime( 1, "Total candidate-search runtime", Abc_Clock() - clk ); + return 0; + } + if ( fTryMin ) + { + if ( fUseNands || fKissat || fKissat2 || pPars->fCard ) + { + Abc_Print( -1, "Minimum-node enumeration with -t is currently supported by the default and Glucose (-g) twoexact engines.\n" ); + return 1; + } + if ( pPars->nNodes < pPars->nVars + 1 ) + { + Abc_Print( -1, "Command line switch \"-t\" expects \"-N \" to be at least %d.\n", pPars->nVars + 1 ); + return 1; + } + if ( !Abc_TwoExactRunMin(pPars, pPars->nNodes) ) + printf( "No solution found from N = %d through N = %d.\n", pPars->nVars + 1, pPars->nNodes ); + ABC_FREE( pPars->pSolFans ); + return 0; + } if ( fUseNands ) Exa_ManExactSynthesis7( pPars, GateSize ); else if ( fKissat || pPars->fCard ) @@ -10740,16 +11376,21 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Exa_ManExactSynthesis( pPars ); else Exa_ManExactSynthesis2( pPars ); + ABC_FREE( pPars->pSolFans ); return 0; usage: - Abc_Print( -2, "usage: twoexact [-INTG ] [-S str] [-abdconugklmvh] \n" ); + Abc_Print( -2, "usage: twoexact [-INTGCDE ] [-S str] [-P str] [-abdconugklmtxvh] \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-S : structural guidance from the user [default = %s]\n", pPars->pGuide ? pPars->pGuide : "unknown" ); + Abc_Print( -2, "\t-P : fixed input permutation; '_' separates gates, '*' leaves fanin free [default = %s]\n", pPars->pPermStr ? pPars->pPermStr : "none" ); + Abc_Print( -2, "\t-C : number of random candidate permutations to try [default = %d]\n", nCandPerms ); + Abc_Print( -2, "\t-D : number of fixed variable positions randomized to '*' in each candidate [default = %d]\n", nPermDcs ); + Abc_Print( -2, "\t-E : number of frequent cofactor seed nodes used with -x [default = %d]\n", nSeedNodes ); 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" ); @@ -10761,6 +11402,8 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-k : toggle using Kissat by Armin Biere [default = %s]\n", fKissat ? "yes" : "no" ); Abc_Print( -2, "\t-l : toggle using Kissat by Armin Biere [default = %s]\n", fKissat2 ? "yes" : "no" ); Abc_Print( -2, "\t-m : toggle using CaDiCaL by Armin Biere [default = %s]\n", pPars->fCard ? "yes" : "no" ); + Abc_Print( -2, "\t-t : toggle trying increasing node counts up to \"-N \" [default = %s]\n", fTryMin ? "yes" : "no" ); + Abc_Print( -2, "\t-x : toggle smart candidate generation using cofactor seed nodes [default = %s]\n", fSmartGen ? "yes" : "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose ? "yes" : "no" ); Abc_Print( -2, "\t-h : print the command usage\n" ); Abc_Print( -2, "\t : truth table in hex notation\n" ); @@ -30685,7 +31328,7 @@ int Abc_CommandBmc3( Abc_Frame_t * pAbc, int argc, char ** argv ) int c; Saig_ParBmcSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "SFTHGCDJIPQRLWaxdursgvzh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "SFTHGCDJIPQRLWaxdursgvzhc" ) ) != EOF ) { switch ( c ) { @@ -30860,6 +31503,9 @@ int Abc_CommandBmc3( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'g': pPars->fUseGlucose ^= 1; break; + case 'c': + pPars->fUseCadical ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -30954,6 +31600,7 @@ int Abc_CommandBmc3( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-r : toggle disabling periodic restarts [default = %s]\n", pPars->fNoRestarts? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using Satoko by Bruno Schmitt [default = %s]\n", pPars->fUseSatoko? "yes": "no" ); Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n",pPars->fUseGlucose? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle using CaDiCaL by Armin Biere, University of Freiburg [default = %s]\n",pPars->fUseCadical? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-z : toggle suppressing report about solved outputs [default = %s]\n", pPars->fNotVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -34592,16 +35239,19 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) extern void Abc_NtkRedirectCiCo( Abc_Ntk_t * pNtk ); extern Abc_Ntk_t * Abc_NtkFromCellMappedGia( Gia_Man_t * p, int fUseBuffs ); extern Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs ); + extern Abc_Ntk_t * Abc_NtkFromMappedGiaAnd5( Gia_Man_t * p, int fFindEnables, int fUseBuffs ); + extern Abc_Ntk_t * Abc_NtkFromMappedGia2( Gia_Man_t * p, int fFindEnables, int fUseBuffs, int fCheckAnd5, int fVerbose ); Aig_Man_t * pMan; Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int fStatusClear = 1; int fFindEnables = 0; int fUseBuffs = 0; + int fCheckAnd5 = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "seovh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "seiovh" ) ) != EOF ) { switch ( c ) { @@ -34611,6 +35261,9 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'e': fFindEnables ^= 1; break; + case 'i': + fCheckAnd5 ^= 1; + break; case 'o': fUseBuffs ^= 1; break; @@ -34633,7 +35286,7 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) else if ( Gia_ManHasCellMapping(pAbc->pGia) ) pNtk = Abc_NtkFromCellMappedGia( pAbc->pGia, fUseBuffs ); else if ( Gia_ManHasMapping(pAbc->pGia) || pAbc->pGia->pMuxes ) - pNtk = Abc_NtkFromMappedGia( pAbc->pGia, 0, fUseBuffs ); + pNtk = Abc_NtkFromMappedGia2( pAbc->pGia, 0, fUseBuffs, fCheckAnd5, fVerbose ); else if ( Gia_ManHasDangling(pAbc->pGia) == 0 ) { pMan = Gia_ManToAig( pAbc->pGia, 0 ); @@ -34656,6 +35309,8 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_NtkDelete( pNtkNoCh ); Aig_ManStop( pMan ); } + if ( pNtk == NULL ) + return 1; // transfer the spec name to the pNtk if( pAbc->pGia->pSpec ) { @@ -34722,10 +35377,11 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &put [-seovh]\n" ); + Abc_Print( -2, "usage: &put [-seiovh]\n" ); Abc_Print( -2, "\t transfer the current network into the old ABC\n" ); Abc_Print( -2, "\t-s : toggle clearning verification status [default = %s]\n", fStatusClear? "yes": "no" ); Abc_Print( -2, "\t-e : toggle extracting MUXes for flop enables [default = %s]\n", fFindEnables? "yes": "no" ); + Abc_Print( -2, "\t-i : toggle AND-decomposable polarity for 5-input LUTs [default = %s]\n", fCheckAnd5? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", fUseBuffs? "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"); @@ -34964,13 +35620,16 @@ int Abc_CommandAbc9SaveAig( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( fClear ) + { + Gia_ManStopP( &pAbc->pGiaSaved ); + return 0; + } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } - if ( fClear && pAbc->pGiaSaved != NULL ) - Gia_ManStopP( &pAbc->pGiaSaved ); if ( fArea && pAbc->pGiaSaved != NULL && Gia_ManAndNum(pAbc->pGiaSaved) <= Gia_ManAndNum(pAbc->pGia) ) return 0; if ( !fArea && pAbc->pGiaSaved != NULL && !(Gia_ManLevelNum(pAbc->pGiaSaved) > Gia_ManLevelNum(pAbc->pGia) || (Gia_ManLevelNum(pAbc->pGiaSaved) == Gia_ManLevelNum(pAbc->pGia) && Gia_ManAndNum(pAbc->pGiaSaved) > Gia_ManAndNum(pAbc->pGia))) ) @@ -35134,18 +35793,19 @@ int Abc_CommandAbc9LoadAig( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Gia_WriteVerilog( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fVerbose ); + extern void Gia_WriteVerilogInt( char * pFileName, Gia_Man_t * pGia, int fUseGates, int fVerbose, int fUseCtrlPis ); extern void Gia_WriteMappedVerilog( char * pFileName, Gia_Man_t * pGia, int fVerbose ); char * pFileSpec = NULL; Abc_Ntk_t * pNtkSpec = NULL; char * pFileName; char ** pArgvNew; int c, nArgcNew; + int fUseCtrlPis = 0; int fUseGates = 0; int fUseLuts = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Sglvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Scglvh" ) ) != EOF ) { switch ( c ) { @@ -35158,6 +35818,9 @@ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv ) pFileSpec = argv[globalUtilOptind]; globalUtilOptind++; break; + case 'c': + fUseCtrlPis ^= 1; + break; case 'g': fUseGates ^= 1; break; @@ -35201,7 +35864,7 @@ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv ) } else { - Gia_WriteVerilog( pFileName, pAbc->pGia, fUseGates, fVerbose ); + Gia_WriteVerilogInt( pFileName, pAbc->pGia, fUseGates, fVerbose, fUseCtrlPis ); } } else @@ -35224,9 +35887,10 @@ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &write_ver [-S ] [-glvh] \n" ); + Abc_Print( -2, "usage: &write_ver [-S ] [-cglvh] \n" ); Abc_Print( -2, "\t writes hierarchical Verilog\n" ); Abc_Print( -2, "\t-S file : file name for the original design (required when hierarchy is present)\n" ); + Abc_Print( -2, "\t-c : add clk/rst ports for seq AIGs [default = %s]\n", fUseCtrlPis? "no": "yes" ); Abc_Print( -2, "\t-g : toggle output gates vs assign-statements [default = %s]\n", fUseGates? "gates": "assigns" ); Abc_Print( -2, "\t-l : write LUT6-based Verilog for mapped AIGs [default = %s]\n", fUseLuts? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); @@ -35540,6 +36204,186 @@ int Abc_CommandAbc9Ps( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [Prints multi-origin statistics.] + + Description [Shows how many objects have origins, total origin count, + average/max per node, overflow count, and a histogram. Origins are + populated either by reading an XAIGER file with a "y" extension + (normal abc9 flow) or by the &origins_id command (testing).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Origins( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Gia_Man_t * pGia = pAbc->pGia; + int c, fSetCap = 0, nOriginsMax = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Mh" ) ) != EOF ) + { + switch ( c ) + { + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nOriginsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nOriginsMax < 0 ) + { + Abc_Print( -1, "The max origins value should be non-negative.\n" ); + goto usage; + } + fSetCap = 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Origins(): There is no AIG.\n" ); + return 0; + } + if ( fSetCap ) + { + pGia->nOriginsMax = nOriginsMax; + Abc_Print( 1, "Origins cap set to %d%s.\n", nOriginsMax, nOriginsMax ? "" : " (unlimited)" ); + return 0; + } + if ( pGia->vOrigins == NULL ) + { + Abc_Print( 1, "No origin tracking data.\n" ); + return 0; + } + { + int i, nObjs = Gia_ManObjNum(pGia); + int nEntries = 0, nOrigins = 0, nMaxOrigins = 0; + int nOverflow = 0; + int histogram[16]; + memset( histogram, 0, sizeof(histogram) ); + for ( i = 0; i < nObjs; i++ ) + { + int nOrig = Gia_ObjOriginsNum( pGia, i ); + if ( nOrig > 0 ) + { + nEntries++; + nOrigins += nOrig; + if ( nOrig > nMaxOrigins ) + nMaxOrigins = nOrig; + if ( nOrig < 16 ) + histogram[nOrig]++; + else + histogram[15]++; + if ( nOrig > GIA_ORIGINS_INLINE ) + nOverflow++; + } + } + Abc_Print( 1, "Origins: %d entries, %d total origins (%.2fx avg), max %d, overflow %d\n", + nEntries, nOrigins, + nEntries > 0 ? (double)nOrigins / nEntries : 0.0, + nMaxOrigins, nOverflow ); + Abc_Print( 1, " Histogram: " ); + for ( i = 1; i < 16; i++ ) + if ( histogram[i] > 0 ) + Abc_Print( 1, "%s%d=%d", i > 1 ? " " : "", i, histogram[i] ); + Abc_Print( 1, "\n" ); + } + return 0; + +usage: + Abc_Print( -2, "usage: &origins [-M num] [-h]\n" ); + Abc_Print( -2, "\t prints multi-origin tracking statistics\n" ); + Abc_Print( -2, "\t-M num : set max origins per object (0 = unlimited) [default = %d]\n", pGia ? pGia->nOriginsMax : 0 ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [Initialize identity origins for testing/debugging.] + + Description [Sets each AND node's origin to itself. This is a testing + convenience for exercising origin propagation in standalone ABC sessions. + In the normal abc9 flow, origins are supplied by Yosys via the XAIGER + "y" extension and this command is not needed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9OriginsId( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Gia_Man_t * pGia = pAbc->pGia; + int c, nOriginsMax = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Mh" ) ) != EOF ) + { + switch ( c ) + { + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nOriginsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nOriginsMax < 0 ) + { + Abc_Print( -1, "The max origins value should be non-negative.\n" ); + goto usage; + } + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9OriginsId(): There is no AIG.\n" ); + return 0; + } + if ( pGia->vOrigins != NULL ) + { + Abc_Print( 1, "Origins already present (%d entries). Use without existing origins.\n", + Vec_IntSize(pGia->vOrigins) / GIA_ORIGINS_STRIDE ); + return 0; + } + { + int i, nObjs = Gia_ManObjNum(pGia); + Gia_Obj_t * pObj; + pGia->nOriginsMax = nOriginsMax; + pGia->vOrigins = Gia_ManOriginsAlloc( nObjs ); + Gia_ManForEachAnd( pGia, pObj, i ) + Gia_ObjSetOrigin( pGia, i, i ); + Abc_Print( 1, "Initialized identity origins for %d AND nodes", Gia_ManAndNum(pGia) ); + if ( nOriginsMax > 0 ) + Abc_Print( 1, " (max %d per node)", nOriginsMax ); + Abc_Print( 1, ".\n" ); + } + return 0; + +usage: + Abc_Print( -2, "usage: &origins_id [-M num] [-h]\n" ); + Abc_Print( -2, "\t sets identity origins for testing (each AND node -> itself)\n" ); + Abc_Print( -2, "\t in normal abc9 flow, origins come from XAIGER \"y\" extension\n" ); + Abc_Print( -2, "\t-M num : max origins per object, 0 = unlimited [default = %d]\n", nOriginsMax ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -41150,7 +41994,7 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) Cec_ManCorSetDefaultParams( pPars ); pPars->nProcs = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FCGXPSZpkrecqowvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "FCGXPSZpkrecqiowvh" ) ) != EOF ) { switch ( c ) { @@ -41249,6 +42093,9 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'q': pPars->fStopWhenGone ^= 1; break; + case 'i': + pPars->fIncremental ^= 1; + break; case 'o': fUseOld ^= 1; break; @@ -41262,6 +42109,13 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( pPars->fIncremental ) + { + //preserve for incremental mode, maybe should be a separate command + pPars->fDynSrm = 1; //dynamic SRM + pPars->fIncrSim = 1; //incremental simulation + pPars->fSkipFailResim = 1; //skip resimulation of failed flops + } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Scorr(): There is no AIG.\n" ); @@ -41322,7 +42176,7 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &scorr [-FCGXPSZ num] [-pkrecqowvh]\n" ); + Abc_Print( -2, "usage: &scorr [-FCGXPSZ num] [-pkrecqiowvh]\n" ); Abc_Print( -2, "\t performs signal correpondence computation\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-F num : the number of timeframes in inductive case [default = %d]\n", pPars->nFrames ); @@ -41337,6 +42191,7 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-e : toggle using equivalences as choices [default = %s]\n", pPars->fMakeChoices? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using circuit-based SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" ); Abc_Print( -2, "\t-q : toggle quitting when PO is not a constant candidate [default = %s]\n", pPars->fStopWhenGone? "yes": "no" ); + Abc_Print( -2, "\t-i : toggle integrated incremental SRM/re-proof/resimulation [default = %s]\n", pPars->fIncremental? "yes": "no" ); Abc_Print( -2, "\t-o : toggle calling old engine [default = %s]\n", fUseOld? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing verbose info about equivalent flops [default = %s]\n", pPars->fVerboseFlops? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); @@ -42589,6 +43444,185 @@ int Abc_CommandAbc9EquivFilter( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Vec_Ptr_t * Abc_GiaDupNameVec( Vec_Ptr_t * vNames ) +{ + Vec_Ptr_t * vNew; + char * pName; + int i; + if ( vNames == NULL ) + return NULL; + vNew = Vec_PtrAlloc( Vec_PtrSize(vNames) ); + Vec_PtrForEachEntry( char *, vNames, pName, i ) + Vec_PtrPush( vNew, pName ? Abc_UtilStrsav(pName) : NULL ); + return vNew; +} + +static Gia_Man_t * Abc_GiaReorderInputsByName( Gia_Man_t * pFirst, Gia_Man_t * pSecond ) +{ + Vec_Int_t * vPiPerm; + Gia_Man_t * pNew; + char * pName1, * pName2; + int * pUsed; + int i, k, nPis, fDiff = 0; + if ( pFirst == NULL || pSecond == NULL || pFirst->vNamesIn == NULL || pSecond->vNamesIn == NULL ) + return NULL; + nPis = Gia_ManPiNum( pFirst ); + if ( nPis != Gia_ManPiNum(pSecond) ) + return NULL; + if ( Vec_PtrSize(pFirst->vNamesIn) < nPis || Vec_PtrSize(pSecond->vNamesIn) < nPis ) + return NULL; + vPiPerm = Vec_IntAlloc( nPis ); + pUsed = ABC_CALLOC( int, nPis ); + for ( i = 0; i < nPis; i++ ) + { + pName1 = (char *)Vec_PtrEntry( pFirst->vNamesIn, i ); + if ( pName1 == NULL ) + break; + for ( k = 0; k < nPis; k++ ) + { + pName2 = (char *)Vec_PtrEntry( pSecond->vNamesIn, k ); + if ( pName2 && !pUsed[k] && !strcmp(pName1, pName2) ) + break; + } + if ( k == nPis ) + break; + pUsed[k] = 1; + Vec_IntPush( vPiPerm, k ); + fDiff |= (k != i); + } + ABC_FREE( pUsed ); + if ( i < nPis || !fDiff ) + { + Vec_IntFree( vPiPerm ); + return NULL; + } + pNew = Gia_ManDupPerm( pSecond, vPiPerm ); + Vec_IntFree( vPiPerm ); + pNew->vNamesIn = Vec_PtrAlloc( Vec_PtrSize(pSecond->vNamesIn) ); + for ( i = 0; i < nPis; i++ ) + { + pName1 = (char *)Vec_PtrEntry( pFirst->vNamesIn, i ); + Vec_PtrPush( pNew->vNamesIn, pName1 ? Abc_UtilStrsav(pName1) : NULL ); + } + for ( i = nPis; i < Vec_PtrSize(pSecond->vNamesIn); i++ ) + { + pName2 = (char *)Vec_PtrEntry( pSecond->vNamesIn, i ); + Vec_PtrPush( pNew->vNamesIn, pName2 ? Abc_UtilStrsav(pName2) : NULL ); + } + pNew->vNamesOut = Abc_GiaDupNameVec( pSecond->vNamesOut ); + return pNew; +} + +static Gia_Man_t * Abc_GiaDupPermOutputs( Gia_Man_t * p, Vec_Int_t * vPoPerm ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + assert( Vec_IntSize(vPoPerm) == Gia_ManPoNum(p) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, Vec_IntEntry(vPoPerm, i))) ); + Gia_ManForEachRi( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +static Gia_Man_t * Abc_GiaReorderOutputsByName( Gia_Man_t * pFirst, Gia_Man_t * pSecond ) +{ + Vec_Int_t * vPoPerm; + Gia_Man_t * pNew; + char * pName1, * pName2; + int * pUsed; + int i, k, nPos, fDiff = 0; + if ( pFirst == NULL || pSecond == NULL || pFirst->vNamesOut == NULL || pSecond->vNamesOut == NULL ) + return NULL; + nPos = Gia_ManPoNum( pFirst ); + if ( nPos != Gia_ManPoNum(pSecond) ) + return NULL; + if ( Vec_PtrSize(pFirst->vNamesOut) < nPos || Vec_PtrSize(pSecond->vNamesOut) < nPos ) + return NULL; + vPoPerm = Vec_IntAlloc( nPos ); + pUsed = ABC_CALLOC( int, nPos ); + for ( i = 0; i < nPos; i++ ) + { + pName1 = (char *)Vec_PtrEntry( pFirst->vNamesOut, i ); + if ( pName1 == NULL ) + break; + for ( k = 0; k < nPos; k++ ) + { + pName2 = (char *)Vec_PtrEntry( pSecond->vNamesOut, k ); + if ( pName2 && !pUsed[k] && !strcmp(pName1, pName2) ) + break; + } + if ( k == nPos ) + break; + pUsed[k] = 1; + Vec_IntPush( vPoPerm, k ); + fDiff |= (k != i); + } + ABC_FREE( pUsed ); + if ( i < nPos || !fDiff ) + { + Vec_IntFree( vPoPerm ); + return NULL; + } + pNew = Abc_GiaDupPermOutputs( pSecond, vPoPerm ); + Vec_IntFree( vPoPerm ); + pNew->vNamesIn = Abc_GiaDupNameVec( pSecond->vNamesIn ); + pNew->vNamesOut = Vec_PtrAlloc( Vec_PtrSize(pSecond->vNamesOut) ); + for ( i = 0; i < nPos; i++ ) + { + pName1 = (char *)Vec_PtrEntry( pFirst->vNamesOut, i ); + Vec_PtrPush( pNew->vNamesOut, pName1 ? Abc_UtilStrsav(pName1) : NULL ); + } + for ( i = nPos; i < Vec_PtrSize(pSecond->vNamesOut); i++ ) + { + pName2 = (char *)Vec_PtrEntry( pSecond->vNamesOut, i ); + Vec_PtrPush( pNew->vNamesOut, pName2 ? Abc_UtilStrsav(pName2) : NULL ); + } + return pNew; +} + +static void Abc_GiaTransferNamesIfMatch( Gia_Man_t * pGia, Gia_Man_t * pGiaNames ) +{ + if ( pGia == NULL || pGiaNames == NULL ) + return; + if ( pGia->vNamesIn == NULL && pGiaNames->vNamesIn != NULL && Gia_ManCiNum(pGia) == Vec_PtrSize(pGiaNames->vNamesIn) ) + { + pGia->vNamesIn = pGiaNames->vNamesIn; + pGiaNames->vNamesIn = NULL; + } + if ( pGia->vNamesOut == NULL && pGiaNames->vNamesOut != NULL && Gia_ManCoNum(pGia) == Vec_PtrSize(pGiaNames->vNamesOut) ) + { + pGia->vNamesOut = pGiaNames->vNamesOut; + pGiaNames->vNamesOut = NULL; + } +} + /**Function************************************************************* Synopsis [] @@ -42606,6 +43640,7 @@ static Gia_Man_t * Abc_ReadAigerOrVerilogFile( char * pFileName, char * pFileNam Gia_Man_t * pGia; char * pTemp; char * pOrigFileName = NULL; + char * pFileTemp = NULL; int fVerilog, fSystemVerilog; *pAbc_ReadAigerOrVerilogFileStatus = 0; @@ -42634,17 +43669,24 @@ static Gia_Man_t * Abc_ReadAigerOrVerilogFile( char * pFileName, char * pFileNam extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Aig_Man_t * pAig = NULL; char pCommand[2000]; + char * pFileBase; int RetValue; int fSystemVerilog2 = pFileName2 && Extra_FileIsType( pFileName2, ".sv", NULL, NULL ); // Save the original filename before changing it pOrigFileName = pFileName; + pFileBase = pTopModule ? Abc_UtilStrsav(pTopModule) : + Extra_FileNameGeneric( Extra_FileNameWithoutPath(pFileName) ); + pFileTemp = ABC_ALLOC( char, strlen(pFileBase) + 5 ); + sprintf( pFileTemp, "%s.aig", pFileBase ); + ABC_FREE( pFileBase ); snprintf( pCommand, sizeof(pCommand), - "yosys -qp \"read_verilog %s%s %s%s%s%s; hierarchy %s%s; flatten; proc; opt; async2sync; opt; setundef -undriven -zero; techmap; memory -nomap; memory_map; dffunmap; opt_clean; opt_expr; %saigmap; write_aiger -symbols _temp_.aig\"", + "yosys -qp \"read_verilog %s%s %s%s%s%s; hierarchy %s%s; flatten; proc; opt; async2sync; opt; setundef -undriven -zero; techmap; memory -nomap; memory_map; dffunmap; opt_clean; opt_expr; %saigmap; write_aiger -symbols %s\"", pDefines ? "-D" : "", pDefines ? pDefines : "", (fSystemVerilog || fSystemVerilog2) ? "-sv " : "", pFileName, pFileName2 ? " " : "", pFileName2 ? pFileName2 : "", pTopModule ? "-top " : "-auto-top", pTopModule ? pTopModule : "", - pFileName2 ? "delete t:\\$scopeinfo; " : "" ); + pFileName2 ? "delete t:\\$scopeinfo; " : "", + pFileTemp ); #if defined(__wasm) RetValue = 1; #else @@ -42653,14 +43695,17 @@ static Gia_Man_t * Abc_ReadAigerOrVerilogFile( char * pFileName, char * pFileNam if ( RetValue != 0 ) { Abc_Print( -1, "Yosys command failed: \"%s\".\n", pCommand ); + ABC_FREE( pFileTemp ); return NULL; } if ( pFileName2 ) { - Abc_Ntk_t * pNtk = Io_Read( "_temp_.aig", IO_FILE_AIGER, 1, 0 ); + Gia_Man_t * pGiaNames = NULL; + Abc_Ntk_t * pNtk = Io_Read( pFileTemp, IO_FILE_AIGER, 1, 0 ); if ( pNtk == NULL ) { - Abc_Print( -1, "Reading AIGER from file \"%s\" has failed.\n", "_temp_.aig" ); + Abc_Print( -1, "Reading AIGER from file \"%s\" has failed.\n", pFileTemp ); + ABC_FREE( pFileTemp ); return NULL; } pAig = Abc_NtkToDar( pNtk, 0, 1 ); @@ -42668,14 +43713,19 @@ static Gia_Man_t * Abc_ReadAigerOrVerilogFile( char * pFileName, char * pFileNam if ( pAig == NULL ) { Abc_Print( -1, "Converting the AIGER network into an internal AIG has failed.\n" ); + ABC_FREE( pFileTemp ); return NULL; } pGia = Gia_ManFromAig( pAig ); Aig_ManStop( pAig ); + pGiaNames = Gia_AigerRead( pFileTemp, 0, 1, 0 ); + Abc_GiaTransferNamesIfMatch( pGia, pGiaNames ); + if ( pGiaNames ) + Gia_ManStop( pGiaNames ); } else { - pFileName = "_temp_.aig"; + pFileName = pFileTemp; pGia = Gia_AigerRead( pFileName, 0, 0, 0 ); } } @@ -42684,6 +43734,7 @@ static Gia_Man_t * Abc_ReadAigerOrVerilogFile( char * pFileName, char * pFileNam if ( pGia == NULL ) { Abc_Print( -1, "Reading AIGER from file \"%s\" has failed.\n", pFileName ); + ABC_FREE( pFileTemp ); return NULL; } @@ -42694,6 +43745,7 @@ static Gia_Man_t * Abc_ReadAigerOrVerilogFile( char * pFileName, char * pFileNam pGia->pSpec = Abc_UtilStrsav( pOrigFileName ); } + ABC_FREE( pFileTemp ); return pGia; } @@ -42942,6 +43994,27 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pGias[1] == NULL ) return Abc_ReadAigerOrVerilogFileStatus; } + if ( pGias[0] && pGias[1] ) + { + Gia_Man_t * pTemp = Abc_GiaReorderInputsByName( pGias[0], pGias[1] ); + if ( pTemp ) + { + if ( pPars->fVerbose ) + Abc_Print( 1, "Reordered primary inputs of the second network using input names.\n" ); + if ( pGias[1] != pAbc->pGia && pGias[1] != pAbc->pGiaSaved ) + Gia_ManStop( pGias[1] ); + pGias[1] = pTemp; + } + pTemp = Abc_GiaReorderOutputsByName( pGias[0], pGias[1] ); + if ( pTemp ) + { + if ( pPars->fVerbose ) + Abc_Print( 1, "Reordered primary outputs of the second network using output names.\n" ); + if ( pGias[1] != pAbc->pGia && pGias[1] != pAbc->pGiaSaved ) + Gia_ManStop( pGias[1] ); + pGias[1] = pTemp; + } + } pPars->pNameSpec = pGias[0] ? (pGias[0]->pSpec ? pGias[0]->pSpec : pGias[0]->pName) : NULL; pPars->pNameImpl = pGias[1] ? (pGias[1]->pSpec ? pGias[1]->pSpec : pGias[1]->pName) : NULL; pPars->vNamesIn = pGias[0] ? pGias[0]->vNamesIn : NULL; @@ -51461,9 +52534,10 @@ int Abc_CommandAbc9SProve( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pGiaUse = pAbc->pGia, * pGiaTemp = NULL; Wlc_Ntk_t * pWlc = (Wlc_Ntk_t *)pAbc->pAbcWlc; + char * pReplayFile = NULL, * pUfarArgs = NULL, * pUfarArgsAlloc = NULL; int c, nProcs = 6, nProcsNew = 0, nTimeOut = 3, nTimeOut2 = 10, nTimeOut3 = 100, fUseUif = 0, fVerbose = 0, fVeryVerbose = 0, fSilent = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PTUWusvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PTUCWRusvwh" ) ) != EOF ) { switch ( c ) { @@ -51500,7 +52574,30 @@ int Abc_CommandAbc9SProve( Abc_Frame_t * pAbc, int argc, char ** argv ) globalUtilOptind++; if ( nTimeOut2 <= 0 ) goto usage; - break; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by a string.\n" ); + goto usage; + } + { + int iArg, nChars = 0; + ABC_FREE( pUfarArgsAlloc ); + for ( iArg = globalUtilOptind; iArg < argc; iArg++ ) + nChars += (int)strlen(argv[iArg]) + 1; + pUfarArgsAlloc = ABC_ALLOC( char, nChars + 1 ); + pUfarArgsAlloc[0] = 0; + for ( iArg = globalUtilOptind; iArg < argc; iArg++ ) + { + if ( iArg > globalUtilOptind ) + strcat( pUfarArgsAlloc, " " ); + strcat( pUfarArgsAlloc, argv[iArg] ); + } + pUfarArgs = pUfarArgsAlloc; + globalUtilOptind = argc; + } + break; case 'W': if ( globalUtilOptind >= argc ) { @@ -51512,6 +52609,15 @@ int Abc_CommandAbc9SProve( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nTimeOut3 <= 0 ) goto usage; break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by a file name.\n" ); + goto usage; + } + pReplayFile = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'u': fUseUif ^= 1; break; @@ -51536,27 +52642,37 @@ int Abc_CommandAbc9SProve( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pWlc == NULL ) { Abc_Print( -1, "Abc_CommandAbc9SProve(): There is no word-level design for option \"-u\".\n" ); + ABC_FREE( pUfarArgsAlloc ); return 1; } pGiaTemp = Wlc_NtkBitBlast( pWlc, NULL ); if ( pGiaTemp == NULL ) { Abc_Print( -1, "Abc_CommandAbc9SProve(): Word-level bit-blasting has failed.\n" ); + ABC_FREE( pUfarArgsAlloc ); return 1; } if ( (Gia_ManPoNum(pGiaTemp) & 1) == 1 ) { Abc_Print( -1, "Abc_CommandAbc9SProve(): Internal \"&miter -x\" requires even number of bit-level outputs.\n" ); Gia_ManStop( pGiaTemp ); + ABC_FREE( pUfarArgsAlloc ); return 1; } pGiaUse = Gia_ManTransformMiter2( pGiaTemp ); Gia_ManStop( pGiaTemp ); pGiaTemp = NULL; } + else if ( pUfarArgs != NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9SProve(): Option \"-C\" requires \"-u\".\n" ); + ABC_FREE( pUfarArgsAlloc ); + return 1; + } if ( pGiaUse == NULL ) { Abc_Print( -1, "Abc_CommandAbc9SProve(): There is no AIG.\n" ); + ABC_FREE( pUfarArgsAlloc ); return 1; } if ( Gia_ManRegNum(pGiaUse) == 0 ) @@ -51564,26 +52680,134 @@ int Abc_CommandAbc9SProve( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9SProve(): The problem is combinational.\n" ); if ( fUseUif ) Gia_ManStop( pGiaUse ); + ABC_FREE( pUfarArgsAlloc ); return 1; } - pAbc->Status = Cec_GiaProveTest( pGiaUse, nProcs, nTimeOut, nTimeOut2, nTimeOut3, fUseUif, pWlc, fVerbose, fVeryVerbose, fSilent ); + pAbc->Status = Cec_GiaProveTest( pGiaUse, nProcs, nTimeOut, nTimeOut2, nTimeOut3, fUseUif, pWlc, fVerbose, fVeryVerbose, fSilent, pReplayFile, pUfarArgs ); Abc_FrameReplaceCex( pAbc, &pGiaUse->pCexSeq ); if ( fUseUif ) Gia_ManStop( pGiaUse ); + ABC_FREE( pUfarArgsAlloc ); return 0; usage: - Abc_Print( -2, "usage: &sprove [-PTUW num] [-usvwh]\n" ); - Abc_Print( -2, "\t proves CEC problem by case-splitting\n" ); + Abc_Print( -2, "usage: &sprove [-PTUW num] [-C str] [-R file] [-usvwh]\n" ); + Abc_Print( -2, "\t concurrent sequential model checker\n" ); Abc_Print( -2, "\t-P num : the number of concurrent processes (1 <= num <= 6) [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-T num : first-stage timeout for proving original and scnew reduction [default = %d]\n", nTimeOut ); + Abc_Print( -2, "\t-U num : second-stage proving timeout on optimized miter [default = %d]\n", nTimeOut2 ); + Abc_Print( -2, "\t-W num : late-stage timeout for optimization and final proving [default = %d]\n", nTimeOut3 ); + Abc_Print( -2, "\t-C str : with -u, pass this option string to internal %%ufar\n" ); + Abc_Print( -2, "\t-R str : dump replay/trace file for later execution by &sprove2\n" ); Abc_Print( -2, "\t-u : enable concurrent UFAR on word-level design (uses internal %%blast + &miter -x)\n" ); 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"); + ABC_FREE( pUfarArgsAlloc ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9SProve2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Gia_Man_t * pGiaUse = pAbc->pGia, * pGiaTemp = NULL; + Wlc_Ntk_t * pWlc = (Wlc_Ntk_t *)pAbc->pAbcWlc; + char * pTraceFile = NULL; + int c, nProcs = 0, nTimeOut = 0, nTimeOut2 = 0, nTimeOut3 = 0, fUseUif = 0, fVerbose = 0, fVeryVerbose = 0, fSilent = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "svwh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fSilent ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command &sprove2 expects a replay file name.\n" ); + goto usage; + } + pTraceFile = argv[globalUtilOptind]; + globalUtilOptind++; + if ( globalUtilOptind != argc ) + goto usage; + if ( !Cec_GiaReplayReadParams( pTraceFile, &nProcs, &nTimeOut, &nTimeOut2, &nTimeOut3, &fUseUif ) ) + { + Abc_Print( -1, "Abc_CommandAbc9SProve2(): Cannot read replay file \"%s\".\n", pTraceFile ); + return 1; + } + if ( fUseUif ) + { + pGiaUse = NULL; + if ( pWlc == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9SProve2(): Replay requires word-level design for UIF mode.\n" ); + return 1; + } + pGiaTemp = Wlc_NtkBitBlast( pWlc, NULL ); + if ( pGiaTemp == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9SProve2(): Word-level bit-blasting has failed.\n" ); + return 1; + } + if ( (Gia_ManPoNum(pGiaTemp) & 1) == 1 ) + { + Abc_Print( -1, "Abc_CommandAbc9SProve2(): Internal \"&miter -x\" requires even number of bit-level outputs.\n" ); + Gia_ManStop( pGiaTemp ); + return 1; + } + pGiaUse = Gia_ManTransformMiter2( pGiaTemp ); + Gia_ManStop( pGiaTemp ); + pGiaTemp = NULL; + } + if ( pGiaUse == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9SProve2(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pGiaUse) == 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9SProve2(): The problem is combinational.\n" ); + if ( fUseUif ) + Gia_ManStop( pGiaUse ); + return 1; + } + pAbc->Status = Cec_GiaReplayTest( pGiaUse, pWlc, pTraceFile, fVerbose, fVeryVerbose, fSilent ); + Abc_FrameReplaceCex( pAbc, &pGiaUse->pCexSeq ); + if ( fUseUif ) + Gia_ManStop( pGiaUse ); + return 0; + +usage: + Abc_Print( -2, "usage: &sprove2 [-svwh]\n" ); + Abc_Print( -2, "\t replays &sprove strategy stored in the given trace file\n" ); + 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; } @@ -58466,11 +59690,11 @@ int Abc_CommandAbc9GenNeuron( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandAbc9GenAdder( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Gia_ManGenAdder( int nVars, int fSK, int fBK, int fHC, int fCarries, int fVerbose ); + extern Gia_Man_t * Gia_ManGenAdder( int nVars, int fSK, int fBK, int fHC, int fMM, int fCarries, int fVerbose ); Gia_Man_t * pTemp = NULL; - int c, nBits = 0, fSK = 0, fBK = 0, fHC = 0, fCarries = 0, fVerbose = 0; + int c, nBits = 0, fSK = 0, fBK = 0, fHC = 0, fMM = 0, fCarries = 0, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Nsbhcv" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Nsbhmcv" ) ) != EOF ) { switch ( c ) { @@ -58494,6 +59718,9 @@ int Abc_CommandAbc9GenAdder( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'h': fHC ^= 1; break; + case 'm': + fMM ^= 1; + break; case 'c': fCarries ^= 1; break; @@ -58509,17 +59736,18 @@ int Abc_CommandAbc9GenAdder( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9GenAdder(): The number of inputs should be defined on the command line \"-N num\".\n" ); return 0; } - pTemp = Gia_ManGenAdder( nBits, fSK, fBK, fHC, fCarries, fVerbose ); + pTemp = Gia_ManGenAdder( nBits, fSK, fBK, fHC, fMM, fCarries, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &genadder [-N ] [-sbhcv]\n" ); + Abc_Print( -2, "usage: &genadder [-N ] [-sbhmcv]\n" ); Abc_Print( -2, "\t generates a prefix adder (by default, the ripple carry adder)\n" ); Abc_Print( -2, "\t-N num : the bit-width of the adder [default = undefined]\n" ); Abc_Print( -2, "\t-s : toggles using Sklansky adder [default = %s]\n", fSK ? "yes": "no" ); Abc_Print( -2, "\t-b : toggles using Brent-Kung adder [default = %s]\n", fBK ? "yes": "no" ); Abc_Print( -2, "\t-h : toggles using Huan-Carlsson adder [default = %s]\n", fHC ? "yes": "no" ); + Abc_Print( -2, "\t-m : toggles using majority-based M/M adder [default = %s]\n", fMM ? "yes": "no" ); Abc_Print( -2, "\t-c : toggles using carry-in and carry-out [default = %s]\n", fCarries ? "yes": "no" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose ? "yes": "no" ); return 1; @@ -59642,6 +60870,213 @@ int Abc_CommandAbc9Divide( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Pipeline( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupPipeline( Gia_Man_t * p, int nLevels, int fVerbose ); + Gia_Man_t * pGiaNew; + int nLevels = 20; + int nDelayMax, c, fVerbose = 0; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Dvh" ) ) != EOF ) + { + switch ( c ) + { + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels <= 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Pipeline(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9Pipeline(): This command expects a combinational AIG.\n" ); + return 1; + } + + pGiaNew = Gia_ManDupPipeline( pAbc->pGia, nLevels, fVerbose ); + if ( pGiaNew == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Pipeline(): Pipelining has failed.\n" ); + return 1; + } + nDelayMax = Gia_ManLevelNum( pGiaNew ); + if ( nDelayMax > nLevels ) + { + Abc_Print( -1, "Abc_CommandAbc9Pipeline(): Seed pipeline delay (%d) exceeds target D = %d.\n", nDelayMax, nLevels ); + Gia_ManStop( pGiaNew ); + return 1; + } + Abc_FrameUpdateGia( pAbc, pGiaNew ); + return 0; + +usage: + Abc_Print( -2, "usage: &pipe [-D num] [-vh]\n" ); + Abc_Print( -2, "\t inserts pipeline stages\n" ); + Abc_Print( -2, "\t-D num : max AIG levels between the flops [default = %d]\n", nLevels ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Unpipeline( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupUnpipeline( Gia_Man_t * p, int fVerbose ); + Gia_Man_t * pGiaNew; + int c, fVerbose = 0; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Unpipeline(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) == 0 ) + { + if ( fVerbose ) + Abc_Print( 1, "Abc_CommandAbc9Unpipeline(): The current AIG is already combinational.\n" ); + return 0; + } + + pGiaNew = Gia_ManDupUnpipeline( pAbc->pGia, fVerbose ); + if ( pGiaNew == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Unpipeline(): Removing pipeline flops has failed.\n" ); + return 1; + } + Abc_FrameUpdateGia( pAbc, pGiaNew ); + return 0; + +usage: + Abc_Print( -2, "usage: &unpipe [-vh]\n" ); + Abc_Print( -2, "\t removes the flops to derive a combinational AIG\n" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Regio( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupRegio( Gia_Man_t * p, int fRegIns, int fRegOuts, int fVerbose ); + Gia_Man_t * pGiaNew; + int c, fRegIns = 1, fRegOuts = 1, fVerbose = 0; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "iovh" ) ) != EOF ) + { + switch ( c ) + { + case 'i': + fRegIns ^= 1; + break; + case 'o': + fRegOuts ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Regio(): There is no AIG.\n" ); + return 1; + } + if ( !fRegIns && !fRegOuts ) + { + if ( fVerbose ) + Abc_Print( 1, "Abc_CommandAbc9Regio(): No boundary flops are requested.\n" ); + return 0; + } + + pGiaNew = Gia_ManDupRegio( pAbc->pGia, fRegIns, fRegOuts, fVerbose ); + if ( pGiaNew == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Regio(): Adding boundary flops has failed.\n" ); + return 1; + } + Abc_FrameUpdateGia( pAbc, pGiaNew ); + return 0; + +usage: + Abc_Print( -2, "usage: ®io [-iovh]\n" ); + Abc_Print( -2, "\t adds PI/PO flops while preserving the current AIG\n" ); + Abc_Print( -2, "\t-i : toggle adding PI flops [default = %s]\n", fRegIns ? "yes" : "no" ); + Abc_Print( -2, "\t-o : toggle adding PO flops [default = %s]\n", fRegOuts ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -59766,18 +61201,43 @@ int Abc_CommandAbc9eSLIM( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; Gia_Man_t * pTemp; seteSLIMParams(¶ms); + params.aig = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "DIMPRSTVZdfhns" ) ) != EOF ) { + while ( ( c = Extra_UtilGetopt( argc, argv, "CDIPRSTVWXZcfhistx" ) ) != EOF ) { switch ( c ) { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + params.approximate_relation = 1; + params.relation_tfo_bound = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( params.relation_tfo_bound < 0 ) + goto usage; + if (globalUtilOptind < argc) { + char *next; + int tfi_bound = strtol (argv[globalUtilOptind], &next, 10); + if (argv[globalUtilOptind] != next && *next == '\0') { + params.generate_relation_with_tfi_limit = 1; + params.relation_tfi_bound = tfi_bound; + globalUtilOptind++; + if (params.relation_tfi_bound < 0) { + goto usage; + } + } + } + break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } - params.timeout_inprocessing = atoi(argv[globalUtilOptind]); + params.synthesis_approach = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( params.timeout_inprocessing < 1 ) + if ( params.synthesis_approach < 0 || params.synthesis_approach > 3) goto usage; break; case 'I': @@ -59791,15 +61251,231 @@ int Abc_CommandAbc9eSLIM( Abc_Frame_t * pAbc, int argc, char ** argv ) { if ( params.iterations < 0 ) goto usage; break; - case 'M': + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by a float.\n" ); + goto usage; + } + params.expansion_probability = atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( params.expansion_probability <= 0 || params.expansion_probability > 1) + goto usage; + break; + case 'R': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } - params.mode = atoi(argv[globalUtilOptind]); + params.nruns = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( params.mode < 0 || params.mode > 2) + if ( params.nruns < 1 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + params.subcircuit_max_size = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( params.subcircuit_max_size < 2 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + params.timeout = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( params.timeout < 1 ) + goto usage; + break; + case 'V': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" ); + goto usage; + } + params.verbosity_level = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( params.verbosity_level < 0 || params.verbosity_level > 3 ) + goto usage; + break; + case 'W': + if ( globalUtilOptind >= argc + 1) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by two integers.\n" ); + goto usage; + } + params.nWindows = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if (params.nWindows < 0) + goto usage; + params.window_size = atoi(argv[globalUtilOptind]); + if (params.window_size <= 0) + goto usage; + globalUtilOptind++; + break; + case 'X': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-X\" should be followed by an integer.\n" ); + goto usage; + } + params.additional_gates = atoi(argv[globalUtilOptind]); + if ( params.additional_gates < 0 ) + goto usage; + globalUtilOptind++; + break; + case 'Z': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Z\" should be followed by an integer.\n" ); + goto usage; + } + params.fix_seed = 1; + params.seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'c' : + params.criticial_path_selection_bias ^= 1; + break; + case 'f' : + params.forward_search ^= 1; + break; + case 'h': + goto usage; + case 'i' : + params.apply_inprocessing ^= 1; + break; + case 's' : + params.fill_subcircuits ^= 1; + break; + case 't' : + params.use_taboo_list ^= 1; + break; + case 'x' : + params.aig = 0; + break; + default: + goto usage; + } + } + if (params.nWindows > 0 && params.synthesis_approach != 0) { + Abc_Print( -1, "Windows can only be used with area minimization\n" ); + return 1; + } + if ( pAbc->pGia == NULL ) { + Abc_Print( -1, "Abc_CommandAbc9Test(): There is no AIG.\n" ); + return 1; + } + + pTemp = applyeSLIM(pAbc->pGia, ¶ms); + + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + + + usage: + Abc_Print( -2, "usage: &eslim [-CDIPRSTVWXZ ] [-cfhistx]\n" ); + Abc_Print( -2, "\t circuit optimization using exact synthesis and the SAT-based local improvement method (SLIM)\n" ); + Abc_Print( -2, "\t-C : approximate Boolean relations by only considering the frist C levels in the cone \n"); + Abc_Print( -2, "\t-D : the delay mode to use [default = %d]\n", params.synthesis_approach ); + Abc_Print( -2, "\t-I : the maximal number of iterations (0 = no limit) for the individual eSLIM runs [default = %d]\n", params.iterations ); + Abc_Print( -2, "\t-P : the probability of expanding a node [default = %.2f]\n", params.expansion_probability ); + Abc_Print( -2, "\t-R : the number of runs of eSLIM + Inprocessing [default = %d]\n", params.nruns ); + Abc_Print( -2, "\t-S : the maximal size of considered subcircuits [default = %d]\n", params.subcircuit_max_size ); + Abc_Print( -2, "\t-T : the timeout in seconds for the individual eSLIM runs [default = %d]\n", params.timeout ); + Abc_Print( -2, "\t-V : the verbosity level [default = %d]\n", params.verbosity_level); + Abc_Print( -2, "\t-W : Use m windows of size n [default = %d, %d]\n", params.nWindows, params.window_size); + Abc_Print( -2, "\t-X : the maximal number of additional gates that may be used for depth optimization [default = %d]\n", params.additional_gates); + Abc_Print( -2, "\t-Z : use a fixed seed\n", params.seed); + Abc_Print( -2, "\t-c : toggle bias for selection of nodes on the crictical path\n"); + Abc_Print( -2, "\t-f : toggle forward expansion of root nodes\n"); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t-i : toggle inprocessing\n"); + Abc_Print( -2, "\t-s : toggle fill subcircuits\n"); + Abc_Print( -2, "\t-t : toggle use taboo list\n"); + Abc_Print( -2, "\t-x : allow xor-gates\n"); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Franz-Xaver Reichl from University of Freiburg.\n" ); + + return 1; + +} + +int Abc_CommandAbc9elSLIM( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void seteSLIMParams(eSLIM_ParamStruct* params); + extern Abc_Ntk_t* applyelSLIM(Abc_Ntk_t * pGia, const eSLIM_ParamStruct* params); + + eSLIM_ParamStruct params; + Abc_Ntk_t* pNtk, *pNtknew; + int c; + seteSLIMParams(¶ms); + Extra_UtilGetoptReset(); + params.subcircuit_max_size = 4; + while ( ( c = Extra_UtilGetopt( argc, argv, "CDGIPRSTVWXZcfhist" ) ) != EOF ) { + switch ( c ) { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + params.approximate_relation = 1; + params.relation_tfo_bound = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( params.relation_tfo_bound < 0 ) + goto usage; + if (globalUtilOptind < argc) { + char *next; + int tfi_bound = strtol (argv[globalUtilOptind], &next, 10); + if (argv[globalUtilOptind] != next && *next == '\0') { + params.generate_relation_with_tfi_limit = 1; + params.relation_tfi_bound = tfi_bound; + globalUtilOptind++; + if (params.relation_tfi_bound < 0) { + goto usage; + } + } + } + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + params.synthesis_approach = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( params.synthesis_approach < 0 || params.synthesis_approach > 3) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + params.iterations = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( params.iterations < 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; + } + params.gate_size = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( params.gate_size < 1 || params.gate_size > 6 ) goto usage; break; case 'P': @@ -59830,9 +61506,9 @@ int Abc_CommandAbc9eSLIM( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } - params.subcircuit_size_bound = atoi(argv[globalUtilOptind]); + params.subcircuit_max_size = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( params.subcircuit_size_bound < 2 ) + if ( params.subcircuit_max_size < 2 ) goto usage; break; case 'T': @@ -59857,6 +61533,32 @@ int Abc_CommandAbc9eSLIM( Abc_Frame_t * pAbc, int argc, char ** argv ) { if ( params.verbosity_level < 0 || params.verbosity_level > 3 ) goto usage; break; + case 'W': + if ( globalUtilOptind >= argc + 1) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by two integers.\n" ); + goto usage; + } + params.nWindows = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if (params.nWindows < 0) + goto usage; + params.window_size = atoi(argv[globalUtilOptind]); + if (params.window_size <= 0) + goto usage; + globalUtilOptind++; + break; + case 'X': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-X\" should be followed by an integer.\n" ); + goto usage; + } + params.additional_gates = atoi(argv[globalUtilOptind]); + if ( params.additional_gates < 0 ) + goto usage; + globalUtilOptind++; + break; case 'Z': if ( globalUtilOptind >= argc ) { @@ -59867,58 +61569,80 @@ int Abc_CommandAbc9eSLIM( Abc_Frame_t * pAbc, int argc, char ** argv ) { params.seed = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; - case 'd' : - params.apply_inprocessing ^= 1; + case 'c' : + params.criticial_path_selection_bias ^= 1; break; case 'f' : - params.forbidden_pairs ^= 1; + params.forward_search ^= 1; break; case 'h': goto usage; - case 'n' : - params.extended_normality_processing ^= 1; + case 'i' : + params.apply_inprocessing ^= 1; break; case 's' : params.fill_subcircuits ^= 1; break; + case 't' : + params.use_taboo_list ^= 1; + break; default: goto usage; } } - if ( pAbc->pGia == NULL ) { - Abc_Print( -1, "Abc_CommandAbc9Test(): There is no AIG.\n" ); - return 1; + + pNtk = Abc_FrameReadNtk(pAbc); + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a logic network.\n" ); + return 1; + } + if (!Abc_NtkHasSop(pNtk)) { + Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); } - pTemp = applyeSLIM(pAbc->pGia, ¶ms); + + params.aig = 0; + pNtknew = applyelSLIM(pNtk, ¶ms); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtknew ); - Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &eslim [-DIMPRSTVZ ] [-dfhns]\n" ); - Abc_Print( -2, "\t circuit minimization using exact synthesis and the SAT-based local improvement method (SLIM)\n" ); - Abc_Print( -2, "\t-D : the timeout in seconds for the individual deepsyn runs [default = %d]\n", params.timeout_inprocessing ); + Abc_Print( -2, "usage: elslim [-CDGIPRSTVWXZ ] [-cfhist]\n" ); + Abc_Print( -2, "\t Lut optimization using exact synthesis and the SAT-based local improvement method (SLIM)\n" ); + Abc_Print( -2, "\t-C : approximate Boolean relations by only considering the frist C levels in the cone \n"); + Abc_Print( -2, "\t-D : the delay mode to use [default = %d]\n", params.synthesis_approach ); + Abc_Print( -2, "\t-G : the maximal number of fanins gates may use (at most 6) [default = %d]\n", params.gate_size ); Abc_Print( -2, "\t-I : the maximal number of iterations (0 = no limit) for the individual eSLIM runs [default = %d]\n", params.iterations ); - Abc_Print( -2, "\t-M : the synthesis mode to use [default = %d]\n", params.mode ); Abc_Print( -2, "\t-P : the probability of expanding a node [default = %.2f]\n", params.expansion_probability ); Abc_Print( -2, "\t-R : the number of runs of eSLIM + Inprocessing [default = %d]\n", params.nruns ); - Abc_Print( -2, "\t-S : the maximal size of considered subcircuits [default = %d]\n", params.subcircuit_size_bound ); + Abc_Print( -2, "\t-S : the maximal size of considered subcircuits [default = %d]\n", params.subcircuit_max_size ); Abc_Print( -2, "\t-T : the timeout in seconds for the individual eSLIM runs [default = %d]\n", params.timeout ); Abc_Print( -2, "\t-V : the verbosity level [default = %d]\n", params.verbosity_level); + Abc_Print( -2, "\t-W : Use m windows of size n [default = %d, %d]\n", params.nWindows, params.window_size); + Abc_Print( -2, "\t-X : the maximal number of additional gates that may be used for depth optimization [default = %d]\n", params.additional_gates); Abc_Print( -2, "\t-Z : use a fixed seed\n", params.seed); - Abc_Print( -2, "\t-d : toggle inprocessing with deepsyn\n"); - Abc_Print( -2, "\t-f : toggle using subcircuits with forbidden pairs\n"); + Abc_Print( -2, "\t-c : toggle bias for selection of nodes on the crictical path\n"); + Abc_Print( -2, "\t-f : toggle forward expansion of root nodes\n"); Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\t-n : toggle extended normality processing\n"); + Abc_Print( -2, "\t-i : toggle inprocessing\n"); Abc_Print( -2, "\t-s : toggle fill subcircuits\n"); + Abc_Print( -2, "\t-t : toggle use taboo list\n"); Abc_Print( -2, "\t\n" ); Abc_Print( -2, "\t This command was contributed by Franz-Xaver Reichl from University of Freiburg.\n" ); + return 1; + } int Abc_CommandAbc9CatBtor( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Abc_BtorCat( char * pFileName, int fVerbose ); + extern int32_t Abc_BtorCat( char * pFileName, int fVerbose ); int c, fVerbose = 0; char * pFileName; @@ -59941,9 +61665,7 @@ int Abc_CommandAbc9CatBtor( Abc_Frame_t * pAbc, int argc, char ** argv ) { return 0; } - Abc_BtorCat( pFileName, fVerbose ); - - return 0; + return Abc_BtorCat( pFileName, fVerbose ); usage: Abc_Print( -2, "usage: &catbtor [-v] \n" ); diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c index 6b03223619..e423f9e3d6 100644 --- a/src/base/abci/abcDar.c +++ b/src/base/abci/abcDar.c @@ -38,6 +38,7 @@ #include "opt/csw/csw.h" #include "proof/pdr/pdr.h" #include "sat/bmc/bmc.h" +#include "misc/util/utilTruth.h" #include "map/mio/mio.h" #include "misc/vec/vecMem.h" @@ -757,7 +758,7 @@ Hop_Obj_t * Abc_ObjHopFromGia_rec( Hop_Man_t * pHopMan, Gia_Man_t * p, int Id, V Vec_PtrWriteEntry( vCopies, Id, gFunc ); return gFunc; } -Hop_Obj_t * Abc_ObjHopFromGia( Hop_Man_t * pHopMan, Gia_Man_t * p, int GiaId, Vec_Ptr_t * vCopies ) +static Hop_Obj_t * Abc_ObjHopFromGia2( Hop_Man_t * pHopMan, Gia_Man_t * p, int GiaId, Vec_Ptr_t * vCopies, Vec_Bit_t * vCompls ) { int k, iFan; assert( Gia_ObjIsLut(p, GiaId) ); @@ -766,10 +767,107 @@ Hop_Obj_t * Abc_ObjHopFromGia( Hop_Man_t * pHopMan, Gia_Man_t * p, int GiaId, Ve Gia_LutForEachFanin( p, GiaId, iFan, k ) { Gia_ObjSetTravIdCurrentId(p, iFan); - Vec_PtrWriteEntry( vCopies, iFan, Hop_IthVar(pHopMan, k) ); + Vec_PtrWriteEntry( vCopies, iFan, Hop_NotCond(Hop_IthVar(pHopMan, k), vCompls && Vec_BitEntry(vCompls, iFan)) ); } return Abc_ObjHopFromGia_rec( pHopMan, p, GiaId, vCopies ); } +Hop_Obj_t * Abc_ObjHopFromGia( Hop_Man_t * pHopMan, Gia_Man_t * p, int GiaId, Vec_Ptr_t * vCopies ) +{ + return Abc_ObjHopFromGia2( pHopMan, p, GiaId, vCopies, NULL ); +} + +static int Abc_Tt5HasAndDec( word Truth ) +{ + int v; + for ( v = 0; v < 5; v++ ) + if ( Abc_Tt6Cofactor0(Truth, v) == 0 || Abc_Tt6Cofactor1(Truth, v) == 0 ) + return 1; + return 0; +} +static int Abc_Tt5AndDecPolarity( word Truth ) +{ + if ( Abc_Tt5HasAndDec(Truth) ) + return 0; + if ( Abc_Tt5HasAndDec(~Truth) ) + return 1; + return -1; +} +static word Abc_Tt5CofactorTo4( word Truth, int iVar, int fCompl ) +{ + word Result = 0; + int a, k; + for ( a = 0; a < 16; a++ ) + { + int iMint = fCompl ? 0 : (1 << iVar); + for ( k = 0; k < 4; k++ ) + if ( (a >> k) & 1 ) + iMint |= 1 << (k < iVar ? k : k + 1); + if ( (Truth >> iMint) & 1 ) + Result |= ((word)1) << a; + } + return Result; +} +static int Abc_Tt5FindAndDec( word Truth, int * piVar, int * pfCompl, word * pTruth4 ) +{ + int v; + for ( v = 0; v < 5; v++ ) + { + if ( Abc_Tt6Cofactor0(Truth, v) == 0 ) + { + *piVar = v; + *pfCompl = 0; + *pTruth4 = Abc_Tt5CofactorTo4( Truth, v, 0 ); + return 1; + } + if ( Abc_Tt6Cofactor1(Truth, v) == 0 ) + { + *piVar = v; + *pfCompl = 1; + *pTruth4 = Abc_Tt5CofactorTo4( Truth, v, 1 ); + return 1; + } + } + return 0; +} +static void Abc_NtkFromMappedGiaPrint5Decs( Abc_Ntk_t * pNtk ) +{ + Hop_Man_t * pHopMan; + Abc_Obj_t * pObj; + Vec_Int_t * vTruth; + int i, nNodes5 = 0, nNodesOver5 = 0; + assert( Abc_NtkIsLogic(pNtk) && Abc_NtkHasAig(pNtk) ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + nNodes5 += Abc_ObjFaninNum(pObj) == 5; + nNodesOver5 += Abc_ObjFaninNum(pObj) > 5; + } + if ( nNodes5 == 0 || nNodesOver5 > 0 ) + return; + pHopMan = (Hop_Man_t *)pNtk->pManFunc; + vTruth = Vec_IntAlloc( 64 ); + Abc_Print( 1, "Top-level AND decompositions of 5-input nodes:\n" ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + word Truth, Truth4; + int iVar, fCompl; + if ( Abc_ObjFaninNum(pObj) != 5 ) + continue; + Truth = (word)*Hop_ManConvertAigToTruth( pHopMan, (Hop_Obj_t *)pObj->pData, 5, vTruth, 0 ); + if ( !Abc_Tt5FindAndDec( Truth, &iVar, &fCompl, &Truth4 ) ) + { + Abc_Print( 1, "%05d : ", Abc_ObjId(pObj) ); + Abc_TtPrintHexRev( stdout, &Truth, 5 ); + Abc_Print( 1, " = \n" ); + continue; + } + Abc_Print( 1, "%05d : ", Abc_ObjId(pObj) ); + Abc_TtPrintHexRev( stdout, &Truth, 5 ); + Abc_Print( 1, " = %cx%d & ", fCompl ? '~' : ' ', iVar ); + Abc_TtPrintHexRev( stdout, &Truth4, 4 ); + Abc_Print( 1, "\n" ); + } + Vec_IntFree( vTruth ); +} /**Function************************************************************* @@ -804,14 +902,14 @@ Abc_Obj_t * Abc_NtkFromMappedGia_rec( Abc_Ntk_t * pNtkNew, Gia_Man_t * p, int iO pObjNew = Abc_NtkCreateNodeInv(pNtkNew, pObjNew); return pObjNew; } -Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs ) +Abc_Ntk_t * Abc_NtkFromMappedGiaInt( Gia_Man_t * p, int fFindEnables, int fUseBuffs, int fCheckAnd5, int fVerbose ) { - int fVerbose = 0; int fDuplicate = 0; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObjNew, * pObjNewLi, * pObjNewLo, * pConst0 = NULL; Gia_Obj_t * pObj, * pObjLi, * pObjLo; Vec_Ptr_t * vReflect; + Vec_Bit_t * vCompls = NULL; int i, k, iFan, nDupGates, nCountMux = 0; assert( Gia_ManHasMapping(p) || p->pMuxes || fFindEnables ); assert( !fFindEnables || !p->pMuxes ); @@ -820,6 +918,8 @@ Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs pNtkNew->pName = Extra_UtilStrsav(p->pName); pNtkNew->pSpec = Extra_UtilStrsav(p->pSpec); Gia_ManFillValue( p ); + if ( fCheckAnd5 ) + vCompls = Vec_BitStart( Gia_ManObjNum(p) ); // create constant pConst0 = Abc_NtkCreateNodeConst0( pNtkNew ); Gia_ManConst0(p)->Value = Abc_ObjId(pConst0); @@ -917,6 +1017,7 @@ Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs vReflect = Vec_PtrStart( Gia_ManObjNum(p) ); Gia_ManForEachLut( p, i ) { + Hop_Obj_t * pFunc; pObj = Gia_ManObj(p, i); assert( pObj->Value == ~0 ); if ( Gia_ObjLutSize(p, i) == 0 ) @@ -924,10 +1025,36 @@ Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs pObj->Value = Abc_ObjId(pConst0); continue; } + pFunc = Abc_ObjHopFromGia2( (Hop_Man_t *)pNtkNew->pManFunc, p, i, vReflect, vCompls ); + if ( fCheckAnd5 && Gia_ObjLutSize(p, i) == 5 ) + { + word Truth = Hop_ManComputeTruth6( (Hop_Man_t *)pNtkNew->pManFunc, pFunc, 5 ); + int fCompl = Abc_Tt5AndDecPolarity( Truth ); + if ( fCompl < 0 ) + { + Abc_Print( -1, "Abc_NtkFromMappedGia(): 5-input node %d does not have AND-decomposition in either polarity.\n", i ); + Vec_PtrFree( vReflect ); + Vec_BitFreeP( &vCompls ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + pFunc = Hop_NotCond( pFunc, fCompl ); + Truth = fCompl ? ~Truth : Truth; + assert( Abc_Tt5HasAndDec(Truth) ); + if ( !Abc_Tt5HasAndDec(Truth) ) + { + Abc_Print( -1, "Abc_NtkFromMappedGia(): Internal error: 5-input node %d failed AND-decomposition check.\n", i ); + Vec_PtrFree( vReflect ); + Vec_BitFreeP( &vCompls ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + Vec_BitWriteEntry( vCompls, i, fCompl ); + } pObjNew = Abc_NtkCreateNode( pNtkNew ); Gia_LutForEachFanin( p, i, iFan, k ) Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtkNew, Gia_ObjValue(Gia_ManObj(p, iFan))) ); - pObjNew->pData = Abc_ObjHopFromGia( (Hop_Man_t *)pNtkNew->pManFunc, p, i, vReflect ); + pObjNew->pData = pFunc; pObjNew->fPersist = Gia_ObjLutIsMux(p, i) && Gia_ObjLutSize(p, i) == 3; pObj->Value = Abc_ObjId( pObjNew ); } @@ -939,8 +1066,12 @@ Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs if ( !fFindEnables ) Gia_ManForEachCo( p, pObj, i ) { + int iFanin = Gia_ObjFaninId0p(p, pObj); + int fCompl = Gia_ObjFaninC0(pObj) ^ (vCompls && Vec_BitEntry(vCompls, iFanin)); pObjNew = Abc_NtkObj( pNtkNew, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); - Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), Abc_ObjNotCond( pObjNew, Gia_ObjFaninC0(pObj) ) ); + if ( fCheckAnd5 && fCompl && Gia_ObjIsLut(p, iFanin) && Gia_ObjLutSize(p, iFanin) == 5 ) + pObjNew = Abc_NtkCreateNodeInv( pNtkNew, pObjNew ), fCompl = 0; + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), Abc_ObjNotCond( pObjNew, fCompl ) ); } // create names Abc_NtkAddDummyPiNames( pNtkNew ); @@ -967,8 +1098,23 @@ Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs // check the resulting AIG if ( !Abc_NtkCheck( pNtkNew ) ) Abc_Print( 1, "Abc_NtkFromMappedGia(): Network check has failed.\n" ); + if ( fVerbose && Gia_ManHasMapping(p) ) + Abc_NtkFromMappedGiaPrint5Decs( pNtkNew ); + Vec_BitFreeP( &vCompls ); return pNtkNew; } +Abc_Ntk_t * Abc_NtkFromMappedGia2( Gia_Man_t * p, int fFindEnables, int fUseBuffs, int fCheckAnd5, int fVerbose ) +{ + return Abc_NtkFromMappedGiaInt( p, fFindEnables, fUseBuffs, fCheckAnd5, fVerbose ); +} +Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs ) +{ + return Abc_NtkFromMappedGiaInt( p, fFindEnables, fUseBuffs, 0, 0 ); +} +Abc_Ntk_t * Abc_NtkFromMappedGiaAnd5( Gia_Man_t * p, int fFindEnables, int fUseBuffs ) +{ + return Abc_NtkFromMappedGiaInt( p, fFindEnables, fUseBuffs, 1, 0 ); +} /**Function************************************************************* diff --git a/src/base/abci/abcNpn.c b/src/base/abci/abcNpn.c index 92b47c177a..ab8a7a6859 100644 --- a/src/base/abci/abcNpn.c +++ b/src/base/abci/abcNpn.c @@ -319,10 +319,6 @@ void Abc_TruthNpnPerform( Abc_TtStore_t * p, int NpnType, int fVerbose ) } else if ( NpnType == 8 ) { -// typedef unsigned(*TtCanonicizeFunc)(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag); - unsigned Abc_TtCanonicizeWrap(TtCanonicizeFunc func, Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag); - unsigned Abc_TtCanonicizeAda(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int iThres); - int fHigh = 1, iEnumThres = 25; Abc_TtHieMan_t * pMan = Abc_TtHieManStart(p->nVars, 5); for ( i = 0; i < p->nFuncs; i++ ) @@ -337,11 +333,6 @@ void Abc_TruthNpnPerform( Abc_TtStore_t * p, int NpnType, int fVerbose ) } else if ( NpnType == 9 || NpnType == 10 || NpnType == 11 ) { -// typedef unsigned(*TtCanonicizeFunc)(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag); - unsigned Abc_TtCanonicizeWrap(TtCanonicizeFunc func, Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag); - unsigned Abc_TtCanonicizeAda(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int iThres); - unsigned Abc_TtCanonicizeCA(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int iThres); - Abc_TtHieMan_t * pMan = Abc_TtHieManStart(p->nVars, 5); for ( i = 0; i < p->nFuncs; i++ ) { diff --git a/src/base/abci/abcRmInverters.c b/src/base/abci/abcRmInverters.c new file mode 100644 index 0000000000..2d25d94231 --- /dev/null +++ b/src/base/abci/abcRmInverters.c @@ -0,0 +1,853 @@ +/**CFile**************************************************************** + + FileName [abcRmInverters.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Remove/Redistribute inverted edges on AIG nodes.] + + Author [Jingren Wang] + + Affiliation [HKUST(GZ)] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRmInverters.c,v 1.00 2005/06/20 00:00:00 jingren Exp $] + +***********************************************************************/ + +#include "aig/aig/aig.h" +#include "base/abc/abc.h" +#include "misc/util/abc_global.h" +#include "misc/vec/vecInt.h" +#include "misc/vec/vecPtr.h" +#include "opt/cut/cut.h" + +ABC_NAMESPACE_IMPL_START + +#define RDINV_SIM_SIZE 100 + +static unsigned int uMask[] = { 0x1, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF }; + +extern void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk ); + +/**Function************************************************************* + + Synopsis [Collect cut leaves into a Vec_Ptr.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Ptr_t * Abc_RdInvCollectCutLeaves( Abc_Ntk_t * pNtk, Cut_Cut_t * pCut ) +{ + Vec_Ptr_t * vLeaves = Vec_PtrAlloc( pCut->nLeaves ); + for ( int li = 0; li < pCut->nLeaves; li++ ) + Vec_PtrPush( vLeaves, Abc_NtkObj(pNtk, Cut_CutReadLeaves(pCut)[li]) ); + return vLeaves; +} + +/**Function************************************************************* + + Synopsis [Detect if function is self-dual.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int AbcRmInvHasSelfDual( unsigned int uTruth, int fPhaseOri, unsigned int uTruthFlipped, int fPhaseFlipped, unsigned int uMsk ) +{ + return (uTruth == uTruthFlipped && (fPhaseOri ^ fPhaseFlipped) == 1) || + (uTruth == (~uTruthFlipped & uMsk) && fPhaseOri == fPhaseFlipped); +} + +/**Function************************************************************* + + Synopsis [Detect if function is self-anti-dual.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int AbcRmInvHasSelfAntiDual( unsigned int uTruth, int fPhaseOri, unsigned int uTruthFlipped, int fPhaseFlipped, unsigned int uMsk ) +{ + return (uTruth == uTruthFlipped && fPhaseOri == fPhaseFlipped) || + (uTruth == (~uTruthFlipped & uMsk) && (fPhaseOri ^ fPhaseFlipped) == 1); +} + +/**Function************************************************************* + + Synopsis [Collect MFFC with support variables and internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [abcMffc.c] + +***********************************************************************/ +void Abc_NodeMffcConeSuppCollect( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int iVerbose ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NodeDeref_rec( pNode ); + Abc_NodeMffcConeSupp( pNode, vCone, vSupp ); + Abc_NodeRef_rec( pNode ); + if ( iVerbose ) + { + printf( "Node = %6s : Supp = %3d Cone = %3d (", + Abc_ObjName(pNode), Vec_PtrSize(vSupp), Vec_PtrSize(vCone) ); + Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i ) + printf( " %s", Abc_ObjName(pObj) ); + printf( " )\n" ); + printf("vSupp = ("); + Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i ) + printf( " %s", Abc_ObjName(pObj) ); + printf( " )\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Get inverter count on support variables for self-anti-dual case.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRmInverterCountInvRatioSelfAntiDual( Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int * nLocalInv, int * nLocalInvOnCritical, int * nLocalNonInvOnCritical, int * nLocalSup ) +{ + Abc_Obj_t * pObj, * pFanin; + int i_cone, i_fanin; + Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i_cone ) + { + Abc_ObjForEachFanin( pObj, pFanin, i_fanin ) + { + if ( Vec_PtrFind(vSupp, pFanin) < 0 ) + continue; + if ( (i_fanin == 0 && pObj->fCompl0) || (i_fanin == 1 && pObj->fCompl1) ) + (*nLocalInv)++; + if ( (i_fanin == 0 && pObj->fCompl0 && pFanin->fMarkA) || (i_fanin == 1 && pObj->fCompl1 && pFanin->fMarkA) ) + (*nLocalInvOnCritical)++; + if ( (i_fanin == 0 && !pObj->fCompl0 && pFanin->fMarkA) || (i_fanin == 1 && !pObj->fCompl1 && pFanin->fMarkA) ) + (*nLocalNonInvOnCritical)++; + (*nLocalSup)++; + } + } +} + +/**Function************************************************************* + + Synopsis [Get inverter count on support variables for self-dual case.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRmInverterCountInvRatioSelfDual( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int * nLocalInv, int * nLocalInvOnCritical, int * nLocalNonInvOnCritical, int * nLocalSup ) +{ + Abc_Obj_t * pFanout; + int i; + Abc_NtkRmInverterCountInvRatioSelfAntiDual( vCone, vSupp, nLocalInv, nLocalInvOnCritical, nLocalNonInvOnCritical, nLocalSup ); + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + int fCompl = (Abc_ObjFanin0(pFanout) == pNode) ? pFanout->fCompl0 : pFanout->fCompl1; + *nLocalInv += fCompl; + int fIsCritical = (Abc_ObjFanin0(pFanout) == pNode) + ? (Abc_ObjFanin0(pFanout)->fMarkA == 1) + : (Abc_ObjFanin1(pFanout)->fMarkA == 1); + if ( fCompl && fIsCritical ) + (*nLocalInvOnCritical)++; + else if ( !fCompl && fIsCritical ) + (*nLocalNonInvOnCritical)++; + (*nLocalSup)++; + } +} + +/**Function************************************************************* + + Synopsis [Flip inverters on self-anti-dual function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRmInverterFlipInvSelfAntiDual( Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ) +{ + Abc_Obj_t * pObj, * pFanin; + int i_cone, i_fanin; + Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i_cone ) + { + Abc_ObjForEachFanin( pObj, pFanin, i_fanin ) + { + if ( Vec_PtrFind(vSupp, pFanin) < 0 ) + continue; + if ( i_fanin == 0 ) + pObj->fCompl0 ^= 1; + else if ( i_fanin == 1 ) + pObj->fCompl1 ^= 1; + } + } +} + +/**Function************************************************************* + + Synopsis [Flip inverters on self-dual function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRmInverterFlipInvSelfDual( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ) +{ + Abc_Obj_t * pFanout; + int i; + Abc_NtkRmInverterFlipInvSelfAntiDual( vCone, vSupp ); + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + Abc_ObjFanin0(pFanout) == pNode ? (pFanout->fCompl0 ^= 1) : (pFanout->fCompl1 ^= 1); + } +} + +/**Function************************************************************* + + Synopsis [Simulate AIG nodes and compute truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubSimulateComp( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords ) +{ + Abc_Obj_t * pObj; + unsigned * puData0, * puData1, * puData; + int i, k; + assert( Vec_PtrSize(vDivs) - nLeaves <= Vec_PtrSize(vSims) - nLeavesMax ); + Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pObj, i ) + { + if ( i < nLeaves ) + { + pObj->pDataComp = Vec_PtrEntry( vSims, i ); + continue; + } + pObj->pDataComp = Vec_PtrEntry( vSims, i - nLeaves + nLeavesMax ); + puData = (unsigned *)pObj->pDataComp; + puData0 = (unsigned *)Abc_ObjFanin0(pObj)->pDataComp; + puData1 = (unsigned *)Abc_ObjFanin1(pObj)->pDataComp; + if ( Abc_ObjFaninC0(pObj) && Abc_ObjFaninC1(pObj) ) + for ( k = 0; k < nWords; k++ ) + puData[k] = ~puData0[k] & ~puData1[k]; + else if ( Abc_ObjFaninC0(pObj) ) + for ( k = 0; k < nWords; k++ ) + puData[k] = ~puData0[k] & puData1[k]; + else if ( Abc_ObjFaninC1(pObj) ) + for ( k = 0; k < nWords; k++ ) + puData[k] = puData0[k] & ~puData1[k]; + else + for ( k = 0; k < nWords; k++ ) + puData[k] = puData0[k] & puData1[k]; + } + Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pObj, i ) + { + puData = (unsigned *)pObj->pDataComp; + pObj->fPhase = (puData[0] & 1); + if ( pObj->fPhase ) + for ( k = 0; k < nWords; k++ ) + puData[k] = ~puData[k]; + } +} + +/**Function************************************************************* + + Synopsis [Clean pDataComp on cone nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanDataComp( Vec_Ptr_t * vCone ) +{ + Abc_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i ) + pObj->pDataComp = NULL; +} + +/**Function************************************************************* + + Synopsis [Simulate a cut to extract truth + phase for one polarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void AbcRmInvSimCuts( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Cut_Cut_t * pCut, int nMaxLeaves, unsigned int * uNodeVal, int * fPhaseFlipped, unsigned int * pInfo, Vec_Ptr_t * vSims ) +{ + Abc_Obj_t * pObj; + int nVar = pCut->nLeaves; + int nBits = (1 << nVar); + int nWords = (nBits <= 32) ? 1 : (nBits / 32); + + Vec_Ptr_t * vCone = Vec_PtrAlloc( pCut->nLeaves + 16 ); + Vec_Ptr_t * vSup = Vec_PtrAlloc( pCut->nLeaves ); + for ( int li = 0; li < pCut->nLeaves; li++ ) + { + pObj = Abc_NtkObj( pNtk, Cut_CutReadLeaves(pCut)[li] ); + Vec_PtrPush( vSup, pObj ); + Vec_PtrPush( vCone, pObj ); + } + assert( Vec_PtrSize(vSup) == pCut->nLeaves ); + + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkDfsSup_rec( pNode, vCone, vSup, 0 ); + assert( Vec_PtrSize(vCone) > pCut->nLeaves ); + + Vec_Int_t * vPh = Vec_IntAlloc( Vec_PtrSize(vCone) ); + Abc_Obj_t * pEntry; + int iPh; + Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pEntry, iPh ) + Vec_IntPush( vPh, pEntry->fPhase ); + + Abc_ManResubSimulateComp( vCone, nVar, vSims, nMaxLeaves, nWords ); + unsigned int uNode = (*((unsigned int *)(pNode->pDataComp))); + *uNodeVal = uNode & uMask[nVar]; + *fPhaseFlipped = pNode->fPhase; + + Abc_NtkCleanDataComp( vCone ); + + Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pEntry, iPh ) + pEntry->fPhase = Vec_IntEntry( vPh, iPh ); + + Vec_IntFree( vPh ); + Vec_PtrFree( vCone ); + Vec_PtrFree( vSup ); +} + +/**Function************************************************************* + + Synopsis [Compute original and flipped truth/phase pair for a cut.] + + Description [Allocates and frees simulation arrays internally. + Returns 1 on success, 0 if cut is too large.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Abc_RdInvComputeTruthPair( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Cut_Cut_t * pCut, + unsigned * uTruthOri, int * fPhaseOri, + unsigned * uTruthFlipped, int * fPhaseFlipped ) +{ + int nVar = pCut->nLeaves; + int nBits = (1 << nVar); + int nWords = (nBits <= 32) ? 1 : (nBits / 32); + int in, k; + + Vec_Ptr_t * vSims = Vec_PtrAlloc( RDINV_SIM_SIZE ); + unsigned int *pInfo = ABC_ALLOC( unsigned, nWords * (RDINV_SIM_SIZE + 1) ); + for ( in = 0; in < RDINV_SIM_SIZE; in++ ) + Vec_PtrPush( vSims, pInfo + in * nWords ); + + for ( k = 0; k < nVar; k++ ) + { + unsigned * pData = (unsigned *)vSims->pArray[k]; + Abc_InfoClear( pData, nWords ); + for ( in = 0; in < nBits; in++ ) + if ( in & (1 << k) ) + pData[in >> 5] |= (1 << (in & 31)); + } + AbcRmInvSimCuts( pNtk, pNode, pCut, 5, uTruthOri, fPhaseOri, pInfo, vSims ); + Vec_PtrFree( vSims ); + ABC_FREE( pInfo ); + + vSims = Vec_PtrAlloc( RDINV_SIM_SIZE ); + pInfo = ABC_ALLOC( unsigned, nWords * (RDINV_SIM_SIZE + 1) ); + for ( in = 0; in < RDINV_SIM_SIZE; in++ ) + Vec_PtrPush( vSims, pInfo + in * nWords ); + + for ( k = 0; k < nVar; k++ ) + { + unsigned * pData = (unsigned *)vSims->pArray[k]; + Abc_InfoClear( pData, nWords ); + for ( in = 0; in < nBits; in++ ) + if ( !(in & (1 << k)) ) + pData[in >> 5] |= (1 << (in & 31)); + } + AbcRmInvSimCuts( pNtk, pNode, pCut, 5, uTruthFlipped, fPhaseFlipped, pInfo, vSims ); + Vec_PtrFree( vSims ); + ABC_FREE( pInfo ); + + assert( (*uTruthOri & uMask[nVar]) == *uTruthOri ); + assert( (*uTruthFlipped & uMask[nVar]) == *uTruthFlipped ); +} + +/**Function************************************************************* + + Synopsis [Check if cut is self-dual.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRmInvCutIsSelfDual( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Cut_Cut_t * pCut ) +{ + unsigned uTruthOri, uTruthFlipped; + int fPhaseOri, fPhaseFlipped; + Abc_RdInvComputeTruthPair( pNtk, pNode, pCut, &uTruthOri, &fPhaseOri, &uTruthFlipped, &fPhaseFlipped ); + return AbcRmInvHasSelfDual( uTruthOri, fPhaseOri, uTruthFlipped, fPhaseFlipped, uMask[pCut->nLeaves] ); +} + +/**Function************************************************************* + + Synopsis [Check if cut is self-anti-dual.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRmInvCutIsSelfAntiDual( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Cut_Cut_t * pCut ) +{ + unsigned uTruthOri, uTruthFlipped; + int fPhaseOri, fPhaseFlipped; + Abc_RdInvComputeTruthPair( pNtk, pNode, pCut, &uTruthOri, &fPhaseOri, &uTruthFlipped, &fPhaseFlipped ); + return AbcRmInvHasSelfAntiDual( uTruthOri, fPhaseOri, uTruthFlipped, fPhaseFlipped, uMask[pCut->nLeaves] ); +} + +/**Function************************************************************* + + Synopsis [Get valid cuts of self-dual and self-anti-dual.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void AbcRmInvAvaCuts( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Cut_Man_t * pCutMan, Vec_Ptr_t * vASDCuts, Vec_Ptr_t * vASADCuts, int iVerbose ) +{ + int nCuts = 0; + Vec_Ptr_t * vCutsPreSD = Vec_PtrAlloc( 16 ); + Vec_Ptr_t * vCutsPreSAD = Vec_PtrAlloc( 16 ); + Cut_Cut_t * pCut; + pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pCutMan, pNode, 0, 1 ); + if ( pCut == NULL ) + { + printf("Warning: Abc_NodeGetCutsRecursive returned NULL for node %d\n", Abc_ObjId(pNode)); + Vec_PtrFree( vCutsPreSD ); + Vec_PtrFree( vCutsPreSAD ); + return; + } + for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) + { + if ( Abc_NtkRmInvCutIsSelfDual(pNtk, pNode, pCut) ) + Vec_PtrPush( vCutsPreSD, pCut ); + if ( Abc_NtkRmInvCutIsSelfAntiDual(pNtk, pNode, pCut) ) + Vec_PtrPush( vCutsPreSAD, pCut ); + nCuts++; + } + Vec_PtrCopy( vASADCuts, vCutsPreSAD ); + Vec_PtrCopy( vASDCuts, vCutsPreSD ); + if ( iVerbose ) + { + printf(" %d cuts have been found and processed.\n", nCuts); + printf(" Retrieved %d(%d) of cuts in self-anti-dual and %d(%d) of cuts in self-dual.\n", + Vec_PtrSize(vASADCuts), Vec_PtrSize(vCutsPreSAD), + Vec_PtrSize(vASDCuts), Vec_PtrSize(vCutsPreSD)); + } + Vec_PtrFree( vCutsPreSD ); + Vec_PtrFree( vCutsPreSAD ); +} + +/**Function************************************************************* + + Synopsis [Show cut structure for verbose output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RmInvShowCutStructure( Abc_Ntk_t * pNtk, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) +{ + Vec_Ptr_t * vCone = Vec_PtrAlloc( pCut->nLeaves + 16 ); + Vec_Ptr_t * vSup = Abc_RdInvCollectCutLeaves( pNtk, pCut ); + int li; + for ( li = 0; li < pCut->nLeaves; li++ ) + Vec_PtrPush( vCone, Abc_NtkObj(pNtk, Cut_CutReadLeaves(pCut)[li]) ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkDfsSup_rec( pRoot, vCone, vSup, 1 ); + Vec_PtrFree( vSup ); + Vec_PtrFree( vCone ); +} + +/**Function************************************************************* + + Synopsis [Retrieve max level slack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void AbcRmInvFetchMaxLSlack( Abc_Ntk_t * pNtk, int * iLSM ) +{ + int i = 0; + Abc_Obj_t * pNode; + Vec_Int_t * vLS = Vec_IntAlloc( Abc_NtkNodeNum(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + int item = Abc_ObjRequiredLevel(pNode) - pNode->Level; + Vec_IntPush( vLS, item ); + } + Vec_IntSort( vLS, 1 ); + assert( Vec_IntEntry(vLS, 0) >= Vec_IntEntry(vLS, Vec_IntSize(vLS) - 1) ); + *iLSM = Vec_IntEntry( vLS, 0 ); + Vec_IntFree( vLS ); +} + +/**Function********************************************************* + + Synopsis [Retrieve critical and near-critical edges count.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void AbcRmInvCollectNCE( Abc_Ntk_t * pNtk, int iThreshold, int * iCount ) +{ + Abc_Obj_t * pNode, * pFanin, * pPo; + int i, j, k; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_ObjRequiredLevel(pNode) - pNode->Level <= iThreshold ) + { + Abc_ObjForEachFanin( pNode, pFanin, j ) + { + *iCount += (j == 0) ? pNode->fCompl0 : pNode->fCompl1; + } + } + } + Abc_NtkForEachPo( pNtk, pPo, k ) + { + Abc_Obj_t * pNodeToPo = Abc_ObjFanin0(pPo); + if ( pPo->fCompl0 && Abc_ObjIsNode(pNodeToPo) && (Abc_ObjRequiredLevel(pNodeToPo) - pNodeToPo->Level <= iThreshold) ) + (*iCount)++; + } +} + +/**Function************************************************************* + + Synopsis [Use markB to record level slack, markA for critical flag.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMarkCriticalNodesScale( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_ObjRequiredLevel(pNode) - pNode->Level <= 1 ) + { + pNode->fMarkA = 1; + pNode->fMarkB = Abc_ObjRequiredLevel(pNode) - pNode->Level; + Counter++; + } + } + printf( "The number of nodes on the critical paths = %6d (%5.2f %%)\n", Counter, 100.0 * Counter / Abc_NtkNodeNum(pNtk) ); +} + +/**Function************************************************************* + + Synopsis [Record sum of slack with inverted edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCollectInvRelatedSlack( Abc_Ntk_t * pNtk, int * invSlack ) +{ + Abc_Obj_t * pNode, * pFanin; + int i, j; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Abc_ObjForEachFanin( pNode, pFanin, j ) + { + if ( j == 0 && pNode->fCompl0 == 1 ) + (*invSlack) += pFanin->fMarkB; + if ( j == 1 && pNode->fCompl1 == 1 ) + (*invSlack) += pFanin->fMarkB; + } + } +} + +/**Function************************************************************* + + Synopsis [Process cuts: evaluate gain condition and flip if beneficial.] + + Description [Shared logic for self-anti-dual and self-dual cut processing. + fIsSelfDual=0 treats SAD; fIsSelfDual=1 treats SD.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Abc_RdInvProcessCuts( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, + Vec_Ptr_t * vCone, Vec_Ptr_t * vCuts, int fIsSelfDual, + int * nCountCritical, int * nCountNonCritical, int * nCount, int iVerbose ) +{ + Cut_Cut_t * pCut; + int i; + Vec_PtrForEachEntry( Cut_Cut_t *, vCuts, pCut, i ) + { + int nLocalInv = 0; + int nLocalSup = 0; + int nLocalInvOnCritical = 0; + int nLocalNonInvOnCritical = 0; + + Vec_Ptr_t * vSupCuts = Abc_RdInvCollectCutLeaves( pNtk, pCut ); + + if ( fIsSelfDual ) + Abc_NtkRmInverterCountInvRatioSelfDual( pNode, vCone, vSupCuts, &nLocalInv, &nLocalInvOnCritical, &nLocalNonInvOnCritical, &nLocalSup ); + else + Abc_NtkRmInverterCountInvRatioSelfAntiDual( vCone, vSupCuts, &nLocalInv, &nLocalInvOnCritical, &nLocalNonInvOnCritical, &nLocalSup ); + + int fCheckCritical = (nLocalInvOnCritical > nLocalNonInvOnCritical); + int fCheckNonCritical = (nLocalInvOnCritical == 0 && nLocalNonInvOnCritical == 0 && nLocalSup > 0 && (float)nLocalInv / nLocalSup >= 0.5); + + if ( fCheckCritical || fCheckNonCritical ) + { + if ( fCheckCritical ) + (*nCountCritical)++; + if ( fCheckNonCritical ) + (*nCountNonCritical)++; + + if ( iVerbose ) + Abc_RmInvShowCutStructure( pNtk, pNode, pCut ); + + if ( fIsSelfDual ) + Abc_NtkRmInverterFlipInvSelfDual( pNode, vCone, vSupCuts ); + else + Abc_NtkRmInverterFlipInvSelfAntiDual( vCone, vSupCuts ); + + (*nCount)++; + } + Vec_PtrFree( vSupCuts ); + } +} + +/**Function************************************************************* + + Synopsis [Gain-based inverter removal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRmInverter( Abc_Ntk_t * pNtk, int iVerbose ) +{ + int i; + Abc_Obj_t * pNode, * pObj; + + if ( !Abc_NtkIsStrash(pNtk) ) + { + printf("Error: Abc_NtkRmInverter requires a strashed AIG network.\n"); + printf("Current network type: %d\n", pNtk->ntkType); + return; + } + if ( iVerbose ) + { + printf("Processing strashed AIG network with %d nodes, %d PIs, %d POs\n", + Abc_NtkNodeNum(pNtk), Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk)); + printf("Network level: %d\n", Abc_NtkLevel(pNtk)); + } + + Abc_NtkStartReverseLevels( pNtk, 0 ); + Abc_NtkMarkCriticalNodesScale( pNtk ); + + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_AigNodeIsChoice(pNode) ) + { + Abc_Obj_t * pCurTempNode = (Abc_Obj_t *)pNode->pData; + while ( pCurTempNode != NULL ) + { + pCurTempNode->fMarkA = 1; + pCurTempNode->fMarkB = pNode->fMarkB; + pCurTempNode = (Abc_Obj_t *)pCurTempNode->pData; + } + } + } + + int iNCEBefore = 0; + int iNCEAfter = 0; + int invSlackBefore = 0; + int invSlackAfter = 0; + int iLSM = 0; + AbcRmInvFetchMaxLSlack( pNtk, &iLSM ); + int iThreshold = iLSM; + AbcRmInvCollectNCE( pNtk, iThreshold, &iNCEBefore ); + Abc_NtkCollectInvRelatedSlack( pNtk, &invSlackBefore ); + + int nCountCriticalSAD = 0; + int nCountNonCriticalSAD = 0; + int nCountSAD = 0; + int nCountCriticalSD = 0; + int nCountNonCriticalSD = 0; + int nCountSD = 0; + int nTotalNodes = Abc_NtkNodeNum(pNtk); + int nProcessed = 0; + + { + Cut_Man_t * pCutMan; + Cut_Params_t Params, * pParams = &Params; + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = 5; + pParams->nKeepMax = 250; + pParams->fTruth = 1; + pParams->fFilter = 1; + pParams->fSeq = 0; + pParams->fLocal = 0; + pParams->fGlobal = 0; + pParams->fTree = 1; + pParams->fDrop = 0; + pParams->fVerbose = 1; + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + pCutMan = Cut_ManStart( pParams ); + + int j_ci; + Abc_NtkForEachCi( pNtk, pObj, j_ci ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( pCutMan, pObj->Id ); + + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_ObjFanoutNum(pNode) == 1 && pNode->pData != NULL ) + continue; + + Vec_Ptr_t * vCone = Vec_PtrAlloc( 16 ); + Vec_Ptr_t * vSupp = Vec_PtrAlloc( 16 ); + + if ( iVerbose ) + printf("\n\n\n"); + + Abc_NodeMffcConeSuppCollect( pNode, vCone, vSupp, iVerbose ); + + int i_sup; + Vec_PtrForEachEntryReverse( Abc_Obj_t *, vSupp, pObj, i_sup ) + Vec_PtrInsert( vCone, 0, pObj ); + + if ( iVerbose ) + printf("Support var size %d, internal node size %d\n", Vec_PtrSize(vSupp), Vec_PtrSize(vCone)); + + Vec_Ptr_t * vASDCuts = Vec_PtrAlloc( 16 ); + Vec_Ptr_t * vASADCuts = Vec_PtrAlloc( 16 ); + + AbcRmInvAvaCuts( pNtk, pNode, pCutMan, vASDCuts, vASADCuts, iVerbose ); + + int nSADBefore = nCountSAD; + Abc_RdInvProcessCuts( pNtk, pNode, vCone, vASADCuts, 0, + &nCountCriticalSAD, &nCountNonCriticalSAD, &nCountSAD, iVerbose ); + + int nSDBefore = nCountSD; + Abc_RdInvProcessCuts( pNtk, pNode, vCone, vASDCuts, 1, + &nCountCriticalSD, &nCountNonCriticalSD, &nCountSD, iVerbose ); + + if ( nCountSAD > nSADBefore || nCountSD > nSDBefore ) + nProcessed++; + + Vec_PtrFree( vASADCuts ); + Vec_PtrFree( vASDCuts ); + Vec_PtrFree( vCone ); + Vec_PtrFree( vSupp ); + } + Cut_ManStop( pCutMan ); + } + + AbcRmInvCollectNCE( pNtk, iThreshold, &iNCEAfter ); + Abc_NtkCollectInvRelatedSlack( pNtk, &invSlackAfter ); + + if ( iVerbose ) + { + printf("=====Statistics about invNum with Threshold %d=====\n", iThreshold); + printf("Before %d After %d Gain %d \n", iNCEBefore, iNCEAfter, iNCEBefore - iNCEAfter); + if ( iNCEAfter > 0 || iNCEBefore > 0 ) + printf("=====Statistics about edges that ease on slack=====\n" + "Ease Gain %f \n", (float)invSlackAfter / (iNCEAfter ? iNCEAfter : 1) - (float)invSlackBefore / (iNCEBefore ? iNCEBefore : 1)); + } + + Abc_NtkStopReverseLevels( pNtk ); + Abc_NtkCleanMarkAB( pNtk ); + + assert( nCountCriticalSAD + nCountNonCriticalSAD == nCountSAD ); + assert( nCountCriticalSD + nCountNonCriticalSD == nCountSD ); + + printf("Total %d self-anti-dual functions", nCountSAD); + if ( nCountSAD > 0 ) + printf(", Critical(%f), Non-critical(%f)", (float)nCountCriticalSAD / nCountSAD, (float)nCountNonCriticalSAD / nCountSAD); + printf(" / %d self-dual are modified", nCountSD); + if ( nCountSD > 0 ) + printf(", Critical(%f), Non-critical(%f)", (float)nCountCriticalSD / nCountSD, (float)nCountNonCriticalSD / nCountSD); + printf(". Total process rate %f\n", nTotalNodes > 0 ? (float)nProcessed / nTotalNodes : 0.0f); +} + +ABC_NAMESPACE_IMPL_END diff --git a/src/base/abci/module.make b/src/base/abci/module.make index fe063a42ae..5891071dd8 100644 --- a/src/base/abci/module.make +++ b/src/base/abci/module.make @@ -49,6 +49,7 @@ SRC += src/base/abci/abc.c \ src/base/abci/abcProve.c \ src/base/abci/abcQbf.c \ src/base/abci/abcQuant.c \ + src/base/abci/abcRmInverters.c \ src/base/abci/abcRec3.c \ src/base/abci/abcReconv.c \ src/base/abci/abcReach.c \ diff --git a/src/base/cmd/cmdHist.c b/src/base/cmd/cmdHist.c index 0edd8a6863..759e7ff365 100644 --- a/src/base/cmd/cmdHist.c +++ b/src/base/cmd/cmdHist.c @@ -26,12 +26,6 @@ ABC_NAMESPACE_IMPL_START -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define ABC_USE_HISTORY 1 - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -102,7 +96,7 @@ void Cmd_HistoryAddCommand( Abc_Frame_t * p, const char * command ) ***********************************************************************/ void Cmd_HistoryRead( Abc_Frame_t * p ) { -#if defined(ABC_USE_HISTORY) +#if !defined(ABC_NO_HISTORY) char Buffer[ABC_MAX_STR]; FILE * pFile; assert( Vec_PtrSize(p->aHistory) == 0 ); @@ -134,7 +128,7 @@ void Cmd_HistoryRead( Abc_Frame_t * p ) ***********************************************************************/ void Cmd_HistoryWrite( Abc_Frame_t * p, int Limit ) { -#if defined(ABC_USE_HISTORY) +#if !defined(ABC_NO_HISTORY) FILE * pFile; char * pStr; int i; @@ -186,7 +180,7 @@ void Cmd_HistoryWrite( Abc_Frame_t * p, int Limit ) ***********************************************************************/ void Cmd_HistoryPrint( Abc_Frame_t * p, int Limit ) { -#if defined(ABC_USE_HISTORY) +#if !defined(ABC_NO_HISTORY) char * pStr; int i; Limit = Abc_MaxInt( 0, Vec_PtrSize(p->aHistory)-Limit ); diff --git a/src/base/io/ioJsonc.c b/src/base/io/ioJsonc.c index 5efffe995b..ce069a18ab 100644 --- a/src/base/io/ioJsonc.c +++ b/src/base/io/ioJsonc.c @@ -108,6 +108,8 @@ void json_print_string(json_t *json, json_value_t val, FILE *fp); void json_debug_value(json_t *json, json_value_t val, int indent); extern Abc_Ntk_t * Abc_NtkFromMiniMapping( int * pArray ); +static json_value_t * Jsonc_ObjectLookup( json_t * pJson, json_value_t object, const char * pKey ); +static char * Jsonc_StringDup( json_t * pJson, json_value_t value ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -671,6 +673,68 @@ static const char * Jsonc_GetNodeOutName( Abc_Obj_t * pObj ) snprintf( Buffer, sizeof(Buffer), "n%d", Abc_ObjId(pObj) ); return Buffer; } +static char * Jsonc_GetInstanceOutName( json_t * pJson, json_value_t Node ) +{ + json_value_t * pOutName = Jsonc_ObjectLookup( pJson, Node, "pin" ); + if ( pOutName == NULL ) + pOutName = Jsonc_ObjectLookup( pJson, Node, "output" ); + return pOutName && pOutName->type == JSON_STRING ? Jsonc_StringDup( pJson, *pOutName ) : NULL; +} +static int Jsonc_IsPrevTwinNode( Abc_Obj_t * pObj, Abc_Obj_t ** ppPrev ) +{ + Abc_Obj_t * pPrev; + Mio_Gate_t * pGate = (Mio_Gate_t *)pObj->pData; + if ( ppPrev ) + *ppPrev = NULL; + if ( pGate == NULL || Mio_GateReadTwin(pGate) == NULL || Abc_ObjId(pObj) == 0 ) + return 0; + pPrev = Abc_NtkObj( pObj->pNtk, Abc_ObjId(pObj) - 1 ); + if ( pPrev == NULL || !Abc_ObjIsNode(pPrev) || Abc_ObjFaninNum(pPrev) != Abc_ObjFaninNum(pObj) ) + return 0; + if ( Mio_GateReadTwin(pGate) != (Mio_Gate_t *)pPrev->pData ) + return 0; + if ( ppPrev ) + *ppPrev = pPrev; + return 1; +} +static Vec_Ptr_t * Jsonc_OrderTwinNodes( Abc_Ntk_t * p, Vec_Ptr_t * vNodes ) +{ + Vec_Int_t * vInDfs = Vec_IntStart( Abc_NtkObjNumMax(p) ); + Vec_Int_t * vSeen = Vec_IntStart( Abc_NtkObjNumMax(p) ); + Vec_Ptr_t * vRes = Vec_PtrAlloc( Vec_PtrSize(vNodes) ); + Abc_Obj_t * pObj, * pTwin; + int i; + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + Vec_IntWriteEntry( vInDfs, Abc_ObjId(pObj), 1 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + if ( Vec_IntEntry(vSeen, Abc_ObjId(pObj)) ) + continue; + if ( Jsonc_IsPrevTwinNode( pObj, &pTwin ) && Vec_IntEntry(vInDfs, Abc_ObjId(pTwin)) ) + { + if ( !Vec_IntEntry(vSeen, Abc_ObjId(pTwin)) ) + { + Vec_PtrPush( vRes, pTwin ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pTwin), 1 ); + } + Vec_PtrPush( vRes, pObj ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pObj), 1 ); + continue; + } + Vec_PtrPush( vRes, pObj ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pObj), 1 ); + pTwin = Abc_NtkFetchTwinNode( pObj ); + if ( pTwin && Vec_IntEntry(vInDfs, Abc_ObjId(pTwin)) && !Vec_IntEntry(vSeen, Abc_ObjId(pTwin)) ) + { + Vec_PtrPush( vRes, pTwin ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pTwin), 1 ); + } + } + assert( Vec_PtrSize(vRes) == Vec_PtrSize(vNodes) ); + Vec_IntFree( vInDfs ); + Vec_IntFree( vSeen ); + return vRes; +} /**Function************************************************************* @@ -692,8 +756,18 @@ void Jsonc_WriteTest( Abc_Ntk_t * p, char * pFileName ) int i, Counter, Total; assert( Abc_NtkHasMapping(p) ); vNodes = Abc_NtkDfs2( p ); + { + Vec_Ptr_t * vTemp = Jsonc_OrderTwinNodes( p, vNodes ); + Vec_PtrFree( vNodes ); + vNodes = vTemp; + } vObj2Num = Vec_IntStartFull( Abc_NtkObjNumMax(p) ); Total = Abc_NtkPiNum(p) + Vec_PtrSize(vNodes) + Abc_NtkPoNum(p); + Counter = 0; + Abc_NtkForEachPi( p, pObj, i ) + Vec_IntWriteEntry( vObj2Num, Abc_ObjId(pObj), Counter++ ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + Vec_IntWriteEntry( vObj2Num, Abc_ObjId(pObj), Counter++ ); pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { @@ -727,6 +801,8 @@ void Jsonc_WriteTest( Abc_Ntk_t * p, char * pFileName ) fprintf( pFile, " {\n" ); fprintf( pFile, " \"type\": \"%s\",\n", "instance" ); fprintf( pFile, " \"name\": \"%s\",\n", Mio_GateReadName(pGate) ); + if ( Mio_GateReadTwin(pGate) != NULL ) + fprintf( pFile, " \"pin\": \"%s\",\n", Mio_GateReadOutName(pGate) ); fprintf( pFile, " \"fanins\":\n" ); fprintf( pFile, " {\n" ); for ( pPin = Mio_GateReadPins(pGate), k = 0; pPin; pPin = Mio_PinReadNext(pPin), k++ ) @@ -897,9 +973,10 @@ static void Jsonc_AppendPortNames( Vec_Str_t * vNames, Vec_Ptr_t * vBases, Vec_I Vec_IntFree( vCounts ); Vec_IntFree( vBaseIds ); } -static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * pLib, char ** ppDesignName ) +static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * pLib, char ** ppDesignName, Vec_Ptr_t ** pvNodeOutNames ) { Vec_Ptr_t * vPiBases = NULL, * vPoBases = NULL; + Vec_Ptr_t * vNodeOutNames = NULL; Vec_Int_t * vPiBits = NULL, * vPoBits = NULL; Vec_Int_t * vNodeMap = NULL, * vGateIdx = NULL, * vPoIdx = NULL; Vec_Int_t * vMapping = NULL, * vPoDrivers = NULL; @@ -911,6 +988,8 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p int fSuccess = 0; if ( ppDesignName ) *ppDesignName = NULL; + if ( pvNodeOutNames ) + *pvNodeOutNames = NULL; if ( pLib == NULL ) { printf( "Genlib library is not available.\n" ); @@ -943,6 +1022,7 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p vPiBits = Vec_IntAlloc( pNodes->count ); vPoBases = Vec_PtrAlloc( pNodes->count ); vPoBits = Vec_IntAlloc( pNodes->count ); + vNodeOutNames = Vec_PtrAlloc( pNodes->count ); // first pass: collect object types and names for ( i = 0; i < (int)pNodes->count; i++ ) { @@ -1020,7 +1100,7 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p json_container_t * pFanObj; Mio_Gate_t * pGate; Mio_Pin_t * pPin; - char * pGateStr; + char * pGateStr, * pOutStr; if ( pGateName == NULL || pGateName->type != JSON_STRING ) { printf( "Gate node %d is missing a name.\n", i ); @@ -1032,16 +1112,19 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p printf( "Gate node %d has an invalid name.\n", i ); goto cleanup; } - pGate = Mio_LibraryReadGateByName( pLib, pGateStr, NULL ); + pOutStr = Jsonc_GetInstanceOutName( pJson, Node ); + pGate = Mio_LibraryReadGateByName( pLib, pGateStr, pOutStr ); if ( pGate == NULL ) { - printf( "Gate \"%s\" is not found in the current library.\n", pGateStr ); + printf( "Gate \"%s\"%s%s%s is not found in the current library.\n", pGateStr, pOutStr ? " with output pin \"" : "", pOutStr ? pOutStr : "", pOutStr ? "\"" : "" ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } if ( pFanins == NULL || pFanins->type != JSON_OBJECT ) { printf( "Gate \"%s\" is missing \"fanins\" description.\n", pGateStr ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } @@ -1049,6 +1132,7 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p if ( pFanObj == NULL ) { printf( "Gate \"%s\" has incomplete fanin information.\n", pGateStr ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } @@ -1061,6 +1145,7 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p if ( pPinInfo == NULL || pPinInfo->type != JSON_OBJECT ) { printf( "Gate \"%s\" is missing connection for pin \"%s\".\n", pGateStr, Mio_PinReadName(pPin) ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } @@ -1068,12 +1153,14 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p if ( pNodeLit == NULL || !Jsonc_ParseInt( pJson, *pNodeLit, &NodeId ) ) { printf( "Gate \"%s\" has invalid node reference on pin \"%s\".\n", pGateStr, Mio_PinReadName(pPin) ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } if ( NodeId < 0 || NodeId >= Vec_IntSize(vNodeMap) ) { printf( "Gate \"%s\" references out-of-range node %d.\n", pGateStr, NodeId ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } @@ -1081,6 +1168,7 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p if ( MapId < 0 ) { printf( "Gate \"%s\" refers to unsupported node %d.\n", pGateStr, NodeId ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } @@ -1088,6 +1176,7 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p } Vec_StrPrintStr( vNames, pGateStr ); Vec_StrPush( vNames, '\0' ); + Vec_PtrPush( vNodeOutNames, pOutStr ); ABC_FREE( pGateStr ); } else if ( Jsonc_StringEqual( pJson, *pType, "PO" ) || Jsonc_StringEqual( pJson, *pType, "po" ) ) @@ -1148,6 +1237,18 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p Vec_IntFreeP( &vPoBits ); if ( vNames ) Vec_StrFree( vNames ); + if ( vNodeOutNames ) + { + if ( fSuccess && pvNodeOutNames ) + *pvNodeOutNames = vNodeOutNames; + else + { + char * pOutName; + Vec_PtrForEachEntry( char *, vNodeOutNames, pOutName, i ) + ABC_FREE( pOutName ); + Vec_PtrFree( vNodeOutNames ); + } + } if ( vPiBases ) { Vec_PtrForEachEntry( char *, vPiBases, pBase, i ) @@ -1171,8 +1272,12 @@ Abc_Ntk_t * Jsonc_ReadNetwork( char * pFileName ) { Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); Vec_Int_t * vMapping; + Vec_Ptr_t * vNodeOutNames = NULL; Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj; char * pDesignName = NULL; + char * pOutName; + int i; json_t * pJson = json_create(); if ( pJson == NULL ) { @@ -1185,7 +1290,7 @@ Abc_Ntk_t * Jsonc_ReadNetwork( char * pFileName ) json_destroy( pJson ); return NULL; } - vMapping = Jsonc_ConvertToMiniMapping( pJson, pLib, &pDesignName ); + vMapping = Jsonc_ConvertToMiniMapping( pJson, pLib, &pDesignName, &vNodeOutNames ); json_destroy( pJson ); if ( vMapping == NULL ) return NULL; @@ -1193,9 +1298,35 @@ Abc_Ntk_t * Jsonc_ReadNetwork( char * pFileName ) Vec_IntFree( vMapping ); if ( pNtk == NULL ) { + if ( vNodeOutNames ) + { + Vec_PtrForEachEntry( char *, vNodeOutNames, pOutName, i ) + ABC_FREE( pOutName ); + Vec_PtrFree( vNodeOutNames ); + } ABC_FREE( pDesignName ); return NULL; } + if ( vNodeOutNames ) + { + Vec_PtrForEachEntry( char *, vNodeOutNames, pOutName, i ) + { + Mio_Gate_t * pGate; + pObj = Abc_NtkObj( pNtk, Abc_NtkCiNum(pNtk) + i + 1 ); + if ( pObj == NULL ) + continue; + pGate = (Mio_Gate_t *)pObj->pData; + if ( pOutName && pGate ) + { + Mio_Gate_t * pGateOut = Mio_LibraryReadGateByName( pLib, Mio_GateReadName(pGate), pOutName ); + if ( pGateOut ) + pObj->pData = pGateOut; + } + } + Vec_PtrForEachEntry( char *, vNodeOutNames, pOutName, i ) + ABC_FREE( pOutName ); + Vec_PtrFree( vNodeOutNames ); + } ABC_FREE( pNtk->pName ); pNtk->pName = pDesignName ? pDesignName : Extra_FileNameGeneric( pFileName ); ABC_FREE( pNtk->pSpec ); diff --git a/src/base/io/ioReadBlif.c b/src/base/io/ioReadBlif.c index e8979c9bae..38e8638136 100644 --- a/src/base/io/ioReadBlif.c +++ b/src/base/io/ioReadBlif.c @@ -622,46 +622,65 @@ int Io_ReadBlifReorderFormalNames( Vec_Ptr_t * vTokens, Mio_Gate_t * pGate, Mio_ } else { - if ( i != Mio_GateReadPinNum(pGate) ) // expect the correct order of input pins in the network with twin gates + int nInputs = Mio_GateReadPinNum(pGate); + int nOutputs = nSize - 2 - nInputs; + int nMatched = 0; + if ( nOutputs != 1 && nOutputs != 2 ) return 0; - // check the last two entries - if ( nSize - 3 == Mio_GateReadPinNum(pGate) ) // only one output is available + // reorder the input pins to be in the same order as in the gate + for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) { - pNamePin = Mio_GateReadOutName(pGate); + pNamePin = Mio_PinReadName(pGatePin); Length = strlen(pNamePin); - pName = (char *)Vec_PtrEntry(vTokens, nSize - 1); - if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) // the last entry is pGate + for ( k = 2; k < nSize; k++ ) { - Vec_PtrPush( vTokens, NULL ); - return 1; + pName = (char *)Vec_PtrEntry(vTokens, k); + if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) + { + Vec_PtrPush( vTokens, pName ); + nMatched++; + break; + } } - pNamePin = Mio_GateReadOutName(pTwin); - Length = strlen(pNamePin); - pName = (char *)Vec_PtrEntry(vTokens, nSize - 1); - if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) // the last entry is pTwin + if ( k == nSize ) + return 0; + } + // add the outputs in the base/twin order, with NULL for a missing output + pNamePin = Mio_GateReadOutName(pGate); + Length = strlen(pNamePin); + for ( k = 2; k < nSize; k++ ) + { + pName = (char *)Vec_PtrEntry(vTokens, k); + if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) { - pName = (char *)Vec_PtrPop( vTokens ); - Vec_PtrPush( vTokens, NULL ); Vec_PtrPush( vTokens, pName ); - return 1; + nMatched++; + break; } - return 0; } - if ( nSize - 4 == Mio_GateReadPinNum(pGate) ) // two outputs are available + if ( k == nSize ) + Vec_PtrPush( vTokens, NULL ); + pNamePin = Mio_GateReadOutName(pTwin); + Length = strlen(pNamePin); + for ( k = 2; k < nSize; k++ ) { - pNamePin = Mio_GateReadOutName(pGate); - Length = strlen(pNamePin); - pName = (char *)Vec_PtrEntry(vTokens, nSize - 2); - if ( !(!strncmp( pNamePin, pName, Length ) && pName[Length] == '=') ) - return 0; - pNamePin = Mio_GateReadOutName(pTwin); - Length = strlen(pNamePin); - pName = (char *)Vec_PtrEntry(vTokens, nSize - 1); - if ( !(!strncmp( pNamePin, pName, Length ) && pName[Length] == '=') ) - return 0; - return 1; + pName = (char *)Vec_PtrEntry(vTokens, k); + if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) + { + Vec_PtrPush( vTokens, pName ); + nMatched++; + break; + } } - assert( 0 ); + if ( k == nSize ) + Vec_PtrPush( vTokens, NULL ); + if ( Vec_PtrEntry(vTokens, nSize + nInputs) == NULL && Vec_PtrEntry(vTokens, nSize + nInputs + 1) == NULL ) + return 0; + if ( nMatched != nSize - 2 ) + return 0; + Vec_PtrForEachEntryStart( char *, vTokens, pName, k, nSize ) + Vec_PtrWriteEntry( vTokens, k - nSize + 2, pName ); + Vec_PtrShrink( vTokens, 2 + nInputs + 2 ); } return 1; } @@ -1713,4 +1732,3 @@ int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ) ABC_NAMESPACE_IMPL_END - diff --git a/src/base/io/ioWriteBlif.c b/src/base/io/ioWriteBlif.c index 818f66b377..71a40f96c2 100644 --- a/src/base/io/ioWriteBlif.c +++ b/src/base/io/ioWriteBlif.c @@ -573,6 +573,17 @@ void Io_NtkWriteSubcktFanins( FILE * pFile, Abc_Obj_t * pNode ) SeeAlso [] ***********************************************************************/ +static int Io_NtkNodesHaveSameFanins( Abc_Obj_t * pNode, Abc_Obj_t * pNode2 ) +{ + Abc_Obj_t * pFanin; + int i; + if ( Abc_ObjFaninNum(pNode) != Abc_ObjFaninNum(pNode2) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pFanin != Abc_ObjFanin(pNode2, i) ) + return 0; + return 1; +} int Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ) { static int fReport = 0; @@ -594,6 +605,8 @@ int Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ) fReport = 1, printf( "Warning: Missing second output of gate(s) \"%s\".\n", Mio_GateReadName(pGate) ); return 0; } + if ( !Io_NtkNodesHaveSameFanins( pNode, pNode2 ) ) + return 0; fprintf( pFile, " %s=%s", Mio_GateReadOutName((Mio_Gate_t *)pNode2->pData), Abc_ObjName( Abc_ObjFanout0(pNode2) ) ); return 1; } @@ -1407,4 +1420,3 @@ void Io_WriteBlifSpecial( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct, ABC_NAMESPACE_IMPL_END - diff --git a/src/base/io/ioWritePla.c b/src/base/io/ioWritePla.c index aa6a933d8d..45dc74530c 100644 --- a/src/base/io/ioWritePla.c +++ b/src/base/io/ioWritePla.c @@ -174,7 +174,7 @@ int Io_WritePla( Abc_Ntk_t * pNtk, char * pFileName ) FILE * pFile; assert( Abc_NtkIsSopNetlist(pNtk) ); - assert( Abc_NtkLevel(pNtk) == 1 ); + assert( Abc_NtkLevel(pNtk) <= 1 ); pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c index acddb75511..4d3b06fcdc 100644 --- a/src/base/io/ioWriteVerilog.c +++ b/src/base/io/ioWriteVerilog.c @@ -39,6 +39,8 @@ static void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ); static int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ); static char * Io_WriteVerilogGetName( char * pName ); +static int Io_WriteVerilogNodesHaveSameFanins( Abc_Obj_t * pNode, Abc_Obj_t * pNode2 ); +static int Io_WriteVerilogIsPrevTwinNode( Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -512,6 +514,54 @@ void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ) fprintf( pFile, " end\n" ); } +/**Function************************************************************* + + Synopsis [Checks whether two mapped nodes have the same fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_WriteVerilogNodesHaveSameFanins( Abc_Obj_t * pNode, Abc_Obj_t * pNode2 ) +{ + Abc_Obj_t * pFanin; + int i; + if ( Abc_ObjFaninNum(pNode) != Abc_ObjFaninNum(pNode2) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pFanin != Abc_ObjFanin(pNode2, i) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks whether this mapped node is the second output of a twin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_WriteVerilogIsPrevTwinNode( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pPrev; + Mio_Gate_t * pGate = (Mio_Gate_t *)pNode->pData; + if ( pGate == NULL || Mio_GateReadTwin(pGate) == NULL || Abc_ObjId(pNode) == 0 ) + return 0; + pPrev = Abc_NtkObj( pNode->pNtk, Abc_ObjId(pNode) - 1 ); + if ( pPrev == NULL || !Abc_ObjIsNode(pPrev) ) + return 0; + if ( Mio_GateReadTwin(pGate) != (Mio_Gate_t *)pPrev->pData ) + return 0; + return Io_WriteVerilogNodesHaveSameFanins( pPrev, pNode ); +} + /**Function************************************************************* Synopsis [Writes the nodes and boxes.] @@ -563,12 +613,18 @@ void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ) Abc_NtkForEachNode( pNtk, pObj, k ) { Mio_Gate_t * pGate = (Mio_Gate_t *)pObj->pData; + Abc_Obj_t * pNode2 = NULL; Mio_Pin_t * pGatePin; + if ( Io_WriteVerilogIsPrevTwinNode( pObj ) ) + continue; if ( Abc_ObjFaninNum(pObj) == 0 && (!strcmp(Mio_GateReadName(pGate), "_const0_") || !strcmp(Mio_GateReadName(pGate), "_const1_")) ) { fprintf( pFile, " %-*s %s = 1\'b%d;\n", Length, "assign", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )), !strcmp(Mio_GateReadName(pGate), "_const1_") ); continue; } + pNode2 = Abc_NtkFetchTwinNode( pObj ); + if ( pNode2 && !Io_WriteVerilogNodesHaveSameFanins( pObj, pNode2 ) ) + pNode2 = NULL; // write the node if ( fUseSimpleGateNames ) { @@ -591,6 +647,12 @@ void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ) assert ( i == Abc_ObjFaninNum(pObj) ); fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_GateReadOutName(pGate)) ); fprintf( pFile, "(%s)", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )) ); + if ( pNode2 ) + { + fprintf( pFile, ", " ); + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_GateReadOutName((Mio_Gate_t *)pNode2->pData)) ); + fprintf( pFile, "(%s)", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pNode2) )) ); + } fprintf( pFile, ");\n" ); } } @@ -972,4 +1034,3 @@ void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize, int f ABC_NAMESPACE_IMPL_END - diff --git a/src/base/main/mainInit.c b/src/base/main/mainInit.c index 03c6f94c00..652766248b 100644 --- a/src/base/main/mainInit.c +++ b/src/base/main/mainInit.c @@ -47,6 +47,8 @@ extern void Load_Init( Abc_Frame_t * pAbc ); extern void Load_End( Abc_Frame_t * pAbc ); extern void Scl_Init( Abc_Frame_t * pAbc ); extern void Scl_End( Abc_Frame_t * pAbc ); +extern void Emap_Init( Abc_Frame_t * pAbc ); +extern void Emap_End( Abc_Frame_t * pAbc ); extern void Wlc_Init( Abc_Frame_t * pAbc ); extern void Wlc_End( Abc_Frame_t * pAbc ); extern void Wln_Init( Abc_Frame_t * pAbc ); @@ -118,6 +120,7 @@ void Abc_FrameInit( Abc_Frame_t * pAbc ) Libs_Init( pAbc ); Load_Init( pAbc ); Scl_Init( pAbc ); + Emap_Init( pAbc ); Wlc_Init( pAbc ); Wln_Init( pAbc ); Bac_Init( pAbc ); @@ -159,6 +162,7 @@ void Abc_FrameEnd( Abc_Frame_t * pAbc ) Super_End( pAbc ); Libs_End( pAbc ); Load_End( pAbc ); + Emap_End( pAbc ); Scl_End( pAbc ); Wlc_End( pAbc ); Wln_End( pAbc ); diff --git a/src/base/main/mainUtils.c b/src/base/main/mainUtils.c index 654d246f0e..018914f9c6 100644 --- a/src/base/main/mainUtils.c +++ b/src/base/main/mainUtils.c @@ -18,6 +18,13 @@ ***********************************************************************/ +#ifdef WIN32 +#include +#include +#else +#include +#endif + #include "base/abc/abc.h" #include "mainInt.h" @@ -91,7 +98,13 @@ char * Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc ) { char * pRetValue; fprintf( pAbc->Out, "%s", Prompt ); + fflush( pAbc->Out ); pRetValue = fgets( Prompt, 5000, stdin ); + if ( pRetValue == NULL ) { exit(0); } + if ( !isatty( fileno(stdin) ) ) { + fputs( Prompt, pAbc->Out ); + fflush( pAbc->Out ); + } return Prompt; } #endif diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c index 7e90863d8e..e098684728 100644 --- a/src/base/wlc/wlcBlast.c +++ b/src/base/wlc/wlcBlast.c @@ -1856,29 +1856,26 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn ) Wlc_Obj_t * pFanin = Wlc_ObjFanin0(p, pObj); int End = Wlc_ObjRangeEnd(pObj); int Beg = Wlc_ObjRangeBeg(pObj); - if ( End >= Beg ) + int Low = Abc_MinInt( End, Beg ); + int High = Abc_MaxInt( End, Beg ); + assert( nRange == High - Low + 1 ); + if ( pFanin->End >= pFanin->Beg ) { - if ( pFanin->End >= pFanin->Beg ) - { - assert( nRange == End - Beg + 1 ); - assert( pFanin->Beg <= Beg && End <= pFanin->End ); - for ( k = Beg; k <= End; k++ ) - Vec_IntPush( vRes, pFans0[k - pFanin->Beg] ); - } - else + assert( pFanin->Beg <= Low && High <= pFanin->End ); + for ( k = 0; k < nRange; k++ ) { - assert( nRange == End - Beg + 1 ); - assert( pFanin->End <= Beg && End <= pFanin->Beg ); - for ( k = Beg; k <= End; k++ ) - Vec_IntPush( vRes, pFans0[k - pFanin->End] ); + int Label = End >= Beg ? Beg + k : Beg - k; + Vec_IntPush( vRes, pFans0[Label - pFanin->Beg] ); } } else { - assert( nRange == Beg - End + 1 ); - assert( pFanin->End <= End && Beg <= pFanin->Beg ); - for ( k = End; k <= Beg; k++ ) - Vec_IntPush( vRes, pFans0[k - pFanin->End] ); + assert( pFanin->End <= Low && High <= pFanin->Beg ); + for ( k = 0; k < nRange; k++ ) + { + int Label = End >= Beg ? Beg + k : Beg - k; + Vec_IntPush( vRes, pFans0[pFanin->Beg - Label] ); + } } } else if ( pObj->Type == WLC_OBJ_BIT_CONCAT ) diff --git a/src/base/wln/wlnCom.c b/src/base/wln/wlnCom.c index 2436932cd3..e471bc877d 100644 --- a/src/base/wln/wlnCom.c +++ b/src/base/wln/wlnCom.c @@ -92,13 +92,16 @@ void Wln_End( Abc_Frame_t * pAbc ) ******************************************************************************/ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Abc_Ntk_t * Wln_ReadMappedSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, char * pLibrary, int fVerbose ); - extern Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pFileName2, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fSetUndef, int fVerbose ); - extern Rtl_Lib_t * Wln_ReadSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fCollapse, int fVerbose ); + extern Abc_Ntk_t * Wln_ReadMappedSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, char * pDefines, char * pLibrary, int fVerbose ); + extern Gia_Man_t * Wln_BlastSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fSetUndef, int fVerbose ); + extern Rtl_Lib_t * Wln_ReadSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, char * pDefines, int fCollapse, int fVerbose ); FILE * pFile; char * pFileName = NULL; char * pFileName2= NULL; + char ** ppFileNames = NULL; + int nFileNames = 0; + int fFileNamesAlloc = 0; char * pTopModule= NULL; char * pDefines = NULL; char * pLibrary = NULL; @@ -194,48 +197,64 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( argc != globalUtilOptind + 1 ) + nFileNames = argc - globalUtilOptind; + if ( nFileNames < 1 ) { - printf( "Abc_CommandReadWlc(): Input file name should be given on the command line.\n" ); + printf( "Abc_CommandReadWlc(): Input file name(s) should be given on the command line.\n" ); return 0; } - // get the file name - pFileName = argv[globalUtilOptind]; - if ( (pFile = fopen( pFileName, "r" )) == NULL ) + ppFileNames = pFileName2 ? ABC_ALLOC( char *, nFileNames + 1 ) : argv + globalUtilOptind; + fFileNamesAlloc = pFileName2 != NULL; + if ( pFileName2 ) { - Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName ); - if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".sv", NULL, NULL, NULL )) ) - Abc_Print( 1, "Did you mean \"%s\"?", pFileName ); - Abc_Print( 1, "\n" ); - return 0; + int i; + for ( i = 0; i < nFileNames; i++ ) + ppFileNames[i] = argv[globalUtilOptind + i]; + ppFileNames[nFileNames++] = pFileName2; } - fclose( pFile ); - if ( pFileName2 ) + pFileName = ppFileNames[0]; + for ( c = 0; c < nFileNames; c++ ) { - if ( (pFile = fopen( pFileName2, "r" )) == NULL ) + if ( (pFile = fopen( ppFileNames[c], "r" )) == NULL ) { - Abc_Print( 1, "Cannot open input file \"%s\".\n", pFileName2 ); + Abc_Print( 1, "Cannot open input file \"%s\". ", ppFileNames[c] ); + if ( (pFileName = Extra_FileGetSimilarName( ppFileNames[c], ".v", ".sv", NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", pFileName ); + Abc_Print( 1, "\n" ); + if ( fFileNamesAlloc ) + ABC_FREE( ppFileNames ); return 0; } fclose( pFile ); } - - // perform reading - if ( pLibrary ) + pFileName = ppFileNames[0]; + if ( nFileNames > 1 ) { - if ( pFileName2 ) + int i, fAllVerilog = 1; + for ( i = 0; i < nFileNames; i++ ) + fAllVerilog &= Extra_FileIsType( ppFileNames[i], ".v", ".sv", NULL ); + if ( !fAllVerilog ) { - Abc_Print( 1, "Command line switch \"-F\" only applies in the default bit-blasting path.\n" ); + Abc_Print( 1, "Multiple input files are supported only for Verilog/SystemVerilog files.\n" ); + if ( fFileNamesAlloc ) + ABC_FREE( ppFileNames ); return 0; } + } + + // perform reading + if ( pLibrary ) + { Abc_Ntk_t * pNtk = NULL; if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) - pNtk = Wln_ReadMappedSystemVerilog( pFileName, pTopModule, pDefines, pLibrary, fVerbose ); + pNtk = Wln_ReadMappedSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, pLibrary, fVerbose ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "sv" ) ) - pNtk = Wln_ReadMappedSystemVerilog( pFileName, pTopModule, pDefines, pLibrary, fVerbose ); + pNtk = Wln_ReadMappedSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, pLibrary, fVerbose ); else { printf( "Abc_CommandYosys(): Unknown file extension.\n" ); + if ( fFileNamesAlloc ) + ABC_FREE( ppFileNames ); return 0; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); @@ -244,55 +263,67 @@ 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, pFileName2, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fSetUndef, fVerbose ); + pNew = Wln_BlastSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fSetUndef, fVerbose ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "sv" ) ) - pNew = Wln_BlastSystemVerilog( pFileName, pFileName2, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fSetUndef, fVerbose ); + pNew = Wln_BlastSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fSetUndef, fVerbose ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "rtlil" ) ) { - if ( pFileName2 ) + if ( nFileNames > 1 ) { - Abc_Print( 1, "Command line switch \"-F\" is only supported when the main input is Verilog/SystemVerilog.\n" ); + Abc_Print( 1, "Multiple input files are supported only for Verilog/SystemVerilog files.\n" ); + if ( fFileNamesAlloc ) + ABC_FREE( ppFileNames ); return 0; } - pNew = Wln_BlastSystemVerilog( pFileName, NULL, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fSetUndef, fVerbose ); + pNew = Wln_BlastSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, fSkipStrash, fInvert, fTechMap, fLibInDir, fSetUndef, fVerbose ); } else { printf( "Abc_CommandYosys(): Unknown file extension.\n" ); + if ( fFileNamesAlloc ) + ABC_FREE( ppFileNames ); return 0; } Abc_FrameUpdateGia( pAbc, pNew ); } else { - if ( pFileName2 ) - { - Abc_Print( 1, "Command line switch \"-F\" only applies in the default bit-blasting path.\n" ); - return 0; - } Rtl_Lib_t * pLib = NULL; if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) - pLib = Wln_ReadSystemVerilog( pFileName, pTopModule, pDefines, fCollapse, fVerbose ); + pLib = Wln_ReadSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, fCollapse, fVerbose ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "sv" ) ) - pLib = Wln_ReadSystemVerilog( pFileName, pTopModule, pDefines, fCollapse, fVerbose ); + pLib = Wln_ReadSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, fCollapse, fVerbose ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "rtlil" ) ) - pLib = Wln_ReadSystemVerilog( pFileName, pTopModule, pDefines, fCollapse, fVerbose ); + { + if ( nFileNames > 1 ) + { + Abc_Print( 1, "Multiple input files are supported only for Verilog/SystemVerilog files.\n" ); + if ( fFileNamesAlloc ) + ABC_FREE( ppFileNames ); + return 0; + } + pLib = Wln_ReadSystemVerilog( ppFileNames, nFileNames, pTopModule, pDefines, fCollapse, fVerbose ); + } else { printf( "Abc_CommandYosys(): Unknown file extension.\n" ); + if ( fFileNamesAlloc ) + ABC_FREE( ppFileNames ); return 0; } Wln_AbcUpdateRtl( pAbc, pLib ); } + if ( fFileNamesAlloc ) + ABC_FREE( ppFileNames ); return 0; usage: - Abc_Print( -2, "usage: %%yosys [-TM ] [-D ] [-L ] [-F ] [-bdisumlcvh] \n" ); + Abc_Print( -2, "usage: %%yosys [-TM ] [-D ] [-L ] [-F ] [-bdisumlcvh] [file_name...]\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-M : specify the top module name (default uses \"-auto-top\") (equivalent to \"-T\")\n" ); Abc_Print( -2, "\t-D : specify defines to be used by Yosys (default \"not used\")\n" ); Abc_Print( -2, "\t-L : specify the Liberty library to read a mapped design (default \"not used\")\n" ); - Abc_Print( -2, "\t-F : specify a second Verilog/SystemVerilog file for the default bit-blasting flow (default \"not used\")\n" ); + Abc_Print( -2, "\t-F : specify an additional Verilog/SystemVerilog file (default \"not used\")\n" ); Abc_Print( -2, "\t-b : toggle bit-blasting the design into an AIG using Yosys (this switch has no effect)\n" ); Abc_Print( -2, "\t-d : toggle bit-blasting the design into an AIG using Yosys [default = %s]\n", !fDontBlast? "yes": "no" ); Abc_Print( -2, "\t-i : toggle inverting the outputs (useful for miters) [default = %s]\n", fInvert? "yes": "no" ); diff --git a/src/base/wln/wlnRtl.c b/src/base/wln/wlnRtl.c index ffe8e457d7..ffdd19830b 100644 --- a/src/base/wln/wlnRtl.c +++ b/src/base/wln/wlnRtl.c @@ -122,6 +122,30 @@ char * Wln_GetYosysName() #endif return pYosysName; } +static char * Wln_FileNamesJoin( char ** ppFileNames, int nFileNames ) +{ + char * pFileNames; + int i, nChars = 1; + for ( i = 0; i < nFileNames; i++ ) + nChars += strlen( ppFileNames[i] ) + 1; + pFileNames = ABC_ALLOC( char, nChars ); + pFileNames[0] = 0; + for ( i = 0; i < nFileNames; i++ ) + { + if ( i ) + strcat( pFileNames, " " ); + strcat( pFileNames, ppFileNames[i] ); + } + return pFileNames; +} +static int Wln_FileNamesHasSv( char ** ppFileNames, int nFileNames ) +{ + int i; + for ( i = 0; i < nFileNames; i++ ) + if ( strstr( ppFileNames[i], ".sv" ) != NULL ) + return 1; + return 0; +} int Wln_ConvertToRtl( char * pCommand, char * pFileTemp ) { #if defined(__wasm) @@ -142,29 +166,39 @@ int Wln_ConvertToRtl( char * pCommand, char * pFileTemp ) return 1; #endif } -Rtl_Lib_t * Wln_ReadSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fCollapse, int fVerbose ) +Rtl_Lib_t * Wln_ReadSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, char * pDefines, int fCollapse, int fVerbose ) { Rtl_Lib_t * pNtk = NULL; - char Command[1000]; + char * pFileNames, * pCommand; char * pFileTemp = "_temp_.rtlil"; - int fSVlog = strstr(pFileName, ".sv") != NULL; - if ( strstr(pFileName, ".rtl") ) - return Rtl_LibReadFile( pFileName, pFileName ); - sprintf( Command, "%s -qp \"read_verilog %s%s %s%s; hierarchy %s%s; %sproc; memory -nomap; memory_map; write_rtlil %s\"", + int fSVlog = Wln_FileNamesHasSv(ppFileNames, nFileNames); + int nCommand; + if ( nFileNames == 1 && strstr(ppFileNames[0], ".rtl") ) + return Rtl_LibReadFile( ppFileNames[0], ppFileNames[0] ); + pFileNames = Wln_FileNamesJoin( ppFileNames, nFileNames ); + nCommand = strlen(Wln_GetYosysName()) + strlen(pFileNames) + (pDefines ? strlen(pDefines) : 0) + (pTopModule ? strlen(pTopModule) : 0) + strlen(pFileTemp) + 200; + pCommand = ABC_ALLOC( char, nCommand ); + sprintf( pCommand, "%s -qp \"read_verilog %s%s %s%s; hierarchy %s%s; %sproc; memory -nomap; memory_map; write_rtlil %s\"", Wln_GetYosysName(), pDefines ? "-D" : "", pDefines ? pDefines : "", fSVlog ? "-sv " : "", - pFileName, + pFileNames, pTopModule ? "-top " : "", pTopModule ? pTopModule : "", fCollapse ? "flatten; ": "", pFileTemp ); if ( fVerbose ) - printf( "%s\n", Command ); - if ( !Wln_ConvertToRtl(Command, pFileTemp) ) + printf( "%s\n", pCommand ); + if ( !Wln_ConvertToRtl(pCommand, pFileTemp) ) + { + ABC_FREE( pCommand ); + ABC_FREE( pFileNames ); return NULL; - pNtk = Rtl_LibReadFile( pFileTemp, pFileName ); + } + ABC_FREE( pCommand ); + ABC_FREE( pFileNames ); + pNtk = Rtl_LibReadFile( pFileTemp, ppFileNames[0] ); if ( pNtk == NULL ) { printf( "Dumped the design into file \"%s\".\n", pFileTemp ); @@ -174,63 +208,58 @@ Rtl_Lib_t * Wln_ReadSystemVerilog( char * pFileName, char * pTopModule, char * p unlink( pFileTemp ); return pNtk; } -Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pFileName2, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fSetUndef, int fVerbose ) +Gia_Man_t * Wln_BlastSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fSetUndef, int fVerbose ) { Gia_Man_t * pGia = NULL; - char Command[1000]; - char * pFileTemp = "_temp_.aig"; - int fRtlil = strstr(pFileName, ".rtl") != NULL; - int fSVlog = strstr(pFileName, ".sv") != NULL || (pFileName2 && strstr(pFileName2, ".sv") != NULL); - sprintf( Command, "%s -qp \"%s %s%s %s%s%s%s; hierarchy %s%s; flatten; proc; opt; async2sync; opt; setundef -undriven -zero; %s%smemory -nomap; memory_map; dffunmap; opt_clean; opt_expr; %saigmap; write_aiger -symbols %s\"", + char * pFileNames, * pCommand; + char * pFileTemp, * pFileBase; + int fRtlil = nFileNames == 1 && strstr(ppFileNames[0], ".rtl") != NULL; + int fSVlog = Wln_FileNamesHasSv(ppFileNames, nFileNames); + int nCommand; + pFileBase = pTopModule ? Abc_UtilStrsav(pTopModule) : + Extra_FileNameGeneric( Extra_FileNameWithoutPath(ppFileNames[0]) ); + pFileTemp = ABC_ALLOC( char, strlen(pFileBase) + 5 ); + sprintf( pFileTemp, "%s.aig", pFileBase ); + ABC_FREE( pFileBase ); + pFileNames = Wln_FileNamesJoin( ppFileNames, nFileNames ); + nCommand = strlen(Wln_GetYosysName()) + strlen(pFileNames) + (pDefines ? strlen(pDefines) : 0) + (pTopModule ? strlen(pTopModule) : 0) + strlen(pFileTemp) + 500; + pCommand = ABC_ALLOC( char, nCommand ); + sprintf( pCommand, "%s -qp \"%s %s%s %s%s; hierarchy %s%s; flatten; proc; opt; async2sync; opt; setundef -undriven -zero; %s%smemory -nomap; memory_map; dffunmap; opt_clean; opt_expr; %saigmap; write_aiger -symbols %s\"", Wln_GetYosysName(), fRtlil ? "read_rtlil" : "read_verilog", pDefines ? "-D" : "", pDefines ? pDefines : "", fSVlog ? "-sv " : "", - pFileName, - pFileName2 ? " " : "", - pFileName2 ? pFileName2 : "", + pFileNames, pTopModule ? "-top " : "-auto-top", pTopModule ? pTopModule : "", fTechMap ? (fLibInDir ? "techmap -map techmap.v; " : "techmap; ") : "", fSetUndef ? "setundef -init -zero; " : "", - pFileName2 ? "delete t:\\$scopeinfo; " : "", + nFileNames > 1 ? "delete t:\\$scopeinfo; " : "", pFileTemp ); if ( fVerbose ) - printf( "%s\n", Command ); - if ( !Wln_ConvertToRtl(Command, pFileTemp) ) - return NULL; - if ( pFileName2 ) + printf( "%s\n", pCommand ); + if ( !Wln_ConvertToRtl(pCommand, pFileTemp) ) { - extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); - Aig_Man_t * pAig = NULL; - Abc_Ntk_t * pNtk = Io_Read( pFileTemp, IO_FILE_AIGER, 1, 0 ); - if ( pNtk == NULL ) - { - printf( "Reading AIGER from file \"%s\" has failed.\n", pFileTemp ); - return NULL; - } - pAig = Abc_NtkToDar( pNtk, 0, 1 ); - Abc_NtkDelete( pNtk ); - if ( pAig == NULL ) - { - printf( "Converting the AIGER network into an internal AIG has failed.\n" ); - return NULL; - } - pGia = fSkipStrash ? Gia_ManFromAigSimple(pAig) : Gia_ManFromAig(pAig); - Aig_ManStop( pAig ); + ABC_FREE( pCommand ); + ABC_FREE( pFileNames ); + ABC_FREE( pFileTemp ); + return NULL; } - else - pGia = Gia_AigerRead( pFileTemp, 0, fSkipStrash, 0 ); + ABC_FREE( pCommand ); + ABC_FREE( pFileNames ); + pGia = Gia_AigerRead( pFileTemp, 0, fSkipStrash, 0 ); if ( pGia == NULL ) { printf( "Converting to AIG has failed.\n" ); + ABC_FREE( pFileTemp ); return NULL; } ABC_FREE( pGia->pName ); pGia->pName = pTopModule ? Abc_UtilStrsav(pTopModule) : - Extra_FileNameGeneric( Extra_FileNameWithoutPath(pFileName) ); + Extra_FileNameGeneric( Extra_FileNameWithoutPath(ppFileNames[0]) ); unlink( pFileTemp ); + ABC_FREE( pFileTemp ); // complement the outputs if ( fInvert ) { @@ -240,35 +269,48 @@ Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pFileName2, char * } return pGia; } -Abc_Ntk_t * Wln_ReadMappedSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, char * pLibrary, int fVerbose ) +Abc_Ntk_t * Wln_ReadMappedSystemVerilog( char ** ppFileNames, int nFileNames, char * pTopModule, char * pDefines, char * pLibrary, int fVerbose ) { Abc_Ntk_t * pNtk = NULL; - char Command[1000]; + char * pFileNames, * pCommand; char * pFileTemp = "_temp_.blif"; - int fSVlog = strstr(pFileName, ".sv") != NULL; - sprintf( Command, "%s -qp \"read_liberty -lib %s; read %s %s%s %s; hierarchy %s%s; flatten; proc; memory -nomap; memory_map; write_blif %s%s -impltf -gates %s\"", + int fSVlog = Wln_FileNamesHasSv(ppFileNames, nFileNames); + int nCommand; + pFileNames = Wln_FileNamesJoin( ppFileNames, nFileNames ); + nCommand = strlen(Wln_GetYosysName()) + strlen(pLibrary) + strlen(pFileNames) + (pDefines ? strlen(pDefines) : 0) + 2 * (pTopModule ? strlen(pTopModule) : 0) + strlen(pFileTemp) + 300; + pCommand = ABC_ALLOC( char, nCommand ); + sprintf( pCommand, "%s -qp \"read_liberty -lib %s; read %s %s%s %s; hierarchy %s%s; flatten; proc; memory -nomap; memory_map; write_blif %s%s -impltf -gates %s\"", Wln_GetYosysName(), pLibrary, fSVlog ? "-sv " : "-vlog95", pDefines ? "-D" : "", pDefines ? pDefines : "", - pFileName, + pFileNames, pTopModule ? "-top " : "-auto-top", pTopModule ? pTopModule : "", pTopModule ? "-top " : "", pTopModule ? pTopModule : "", pFileTemp ); if ( fVerbose ) - printf( "%s\n", Command ); - if ( !Wln_ConvertToRtl(Command, pFileTemp) ) + printf( "%s\n", pCommand ); + if ( !Wln_ConvertToRtl(pCommand, pFileTemp) ) + { + ABC_FREE( pCommand ); + ABC_FREE( pFileNames ); return NULL; - sprintf( Command, "read_lib %s", pLibrary ); - if ( Cmd_CommandExecute( Abc_FrameReadGlobalFrame(), Command ) ) + } + ABC_FREE( pCommand ); + ABC_FREE( pFileNames ); + pCommand = ABC_ALLOC( char, strlen(pLibrary) + 20 ); + sprintf( pCommand, "read_lib %s", pLibrary ); + if ( Cmd_CommandExecute( Abc_FrameReadGlobalFrame(), pCommand ) ) { - fprintf( stdout, "Cannot execute ABC command \"%s\".\n", Command ); + fprintf( stdout, "Cannot execute ABC command \"%s\".\n", pCommand ); + ABC_FREE( pCommand ); unlink( pFileTemp ); return NULL; } + ABC_FREE( pCommand ); pNtk = Io_Read( pFileTemp, IO_FILE_BLIF, 1, 0 ); if ( pNtk == NULL ) { diff --git a/src/map/emap/emap.c b/src/map/emap/emap.c new file mode 100644 index 0000000000..3b24b1e378 --- /dev/null +++ b/src/map/emap/emap.c @@ -0,0 +1,158 @@ +/**CFile**************************************************************** + + FileName [emap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Multi-output gate mapper.] + + Synopsis [ABC command entry points.] + +***********************************************************************/ + +#include "emap.h" + +#include "base/abc/abc.h" +#include "base/cmd/cmd.h" +#include "base/main/mainInt.h" +#include "map/mio/mio.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Emap_CommandCountMogPairs( Mio_Library_t * pLib ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the package.] + +***********************************************************************/ +void Emap_Init( Abc_Frame_t * pAbc ) +{ + Cmd_CommandAdd( pAbc, "SC mapping", "emap", Emap_Command, 1 ); +} + +/**Function************************************************************* + + Synopsis [Stops the package.] + +***********************************************************************/ +void Emap_End( Abc_Frame_t * pAbc ) +{ + (void)pAbc; +} + +/**Function************************************************************* + + Synopsis [Counts physical two-output gates represented as twin gates.] + +***********************************************************************/ +static int Emap_CommandCountMogPairs( Mio_Library_t * pLib ) +{ + Mio_Gate_t * pGate; + int nTwinOutputs = 0; + if ( pLib == NULL ) + return 0; + Mio_LibraryForEachGate( pLib, pGate ) + nTwinOutputs += (Mio_GateReadTwin(pGate) != NULL); + return nTwinOutputs / 2; +} + +/**Function************************************************************* + + Synopsis [Runs the ABC-native exact mapper.] + +***********************************************************************/ +int Emap_Command( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); + Abc_Ntk_t * pNtkRes; + int c, fUseMogs = 1, fAreaMode = 0, fVerbose = 0; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "amvh" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fAreaMode ^= 1; + break; + case 'm': + fUseMogs ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind ) + goto usage; + + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "There is no current network.\n" ); + return 1; + } + if ( pLib == NULL ) + { + fprintf( pAbc->Err, "There is no current GENLIB library. Use read_genlib/read_lib first.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pAbc->Err, "The current network is not an AIG. Run strash first.\n" ); + return 1; + } + + if ( fVerbose ) + { + int nMogPairs = fUseMogs ? Emap_CommandCountMogPairs( pLib ) : 0; + fprintf( pAbc->Out, "ABC-native emap setup: PI = %d PO = %d AND = %d\n", + Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkNodeNum(pNtk) ); + fprintf( pAbc->Out, "GENLIB \"%s\": gates = %d MOG pairs = %d MOG use = %s mode = %s\n", + Mio_LibraryReadName(pLib), Mio_LibraryReadGateNum(pLib), nMogPairs, fUseMogs ? "yes" : "no", fAreaMode ? "area" : "delay" ); + } + + pNtkRes = Emap_ManMapAigStructural( pNtk, pLib, fUseMogs, fAreaMode, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pAbc->Err, "ABC-native emap structural mapping has failed.\n" ); + return 1; + } + + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: emap [-amvh]\n" ); + fprintf( pAbc->Err, "\t maps the current AIG using the current GENLIB library\n" ); + fprintf( pAbc->Err, "\t-a : toggle area-oriented mode without required-time pruning [default = %s]\n", fAreaMode ? "yes" : "no" ); + fprintf( pAbc->Err, "\t-m : toggle using multi-output gates when present [default = %s]\n", fUseMogs ? "yes" : "no" ); + fprintf( pAbc->Err, "\t-v : toggle verbose output [default = %s]\n", fVerbose ? "yes" : "no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n\n" ); + fprintf( pAbc->Err, "\tThe mapper is inspired by \"emap\" in Mockturtle developed by Alessandro Tempia Calvino\n" ); + fprintf( pAbc->Err, "\tavailable at https://mockturtle.readthedocs.io/en/latest/algorithms/mapper.html\n" ); + fprintf( pAbc->Err, "\tand described in A. T. Calvino and G. De Micheli, \"Technology mapping using multi-output\n" ); + fprintf( pAbc->Err, "\tlibrary cells\", Proc. ICCAD\'23, https://aletempiac.github.io/publication/2023_006\n" ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END diff --git a/src/map/emap/emap.h b/src/map/emap/emap.h new file mode 100644 index 0000000000..a326d3ed2c --- /dev/null +++ b/src/map/emap/emap.h @@ -0,0 +1,31 @@ +/**CFile**************************************************************** + + FileName [emap.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Multi-output gate mapper.] + + Synopsis [External declarations.] + +***********************************************************************/ + +#ifndef ABC__map__emap__emap_h +#define ABC__map__emap__emap_h + +#include "base/main/main.h" + +ABC_NAMESPACE_HEADER_START + +typedef struct Abc_Ntk_t_ Abc_Ntk_t; +typedef struct Mio_LibraryStruct_t_ Mio_Library_t; + +extern void Emap_Init ( Abc_Frame_t * pAbc ); +extern void Emap_End ( Abc_Frame_t * pAbc ); +extern int Emap_Command( Abc_Frame_t * pAbc, int argc, char ** argv ); + +extern Abc_Ntk_t * Emap_ManMapAigStructural( Abc_Ntk_t * pNtk, Mio_Library_t * pLib, int fUseMogs, int fAreaMode, int fVerbose ); + +ABC_NAMESPACE_HEADER_END + +#endif diff --git a/src/map/emap/emapCore.c b/src/map/emap/emapCore.c new file mode 100644 index 0000000000..1109519400 --- /dev/null +++ b/src/map/emap/emapCore.c @@ -0,0 +1,2662 @@ +/**CFile**************************************************************** + + FileName [emapCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Multi-output gate mapper.] + + Synopsis [Initial mapping core.] + +***********************************************************************/ + +#include "emap.h" + +#include "base/abc/abc.h" +#include "map/mio/mio.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define EMAP_LEAF_MAX 6 +#define EMAP_CUT_MAX 128 +#define EMAP_FLOAT_LARGE ((float)1.0e20) +#define EMAP_DOUBLE_LARGE ((double)1.0e20) +#define EMAP_DELAY_EPS 0.1 + +typedef struct Emap_Cut_t_ Emap_Cut_t; +typedef struct Emap_Best_t_ Emap_Best_t; +typedef struct Emap_Obj_t_ Emap_Obj_t; +typedef struct Emap_Cell_t_ Emap_Cell_t; +typedef struct Emap_Mog_t_ Emap_Mog_t; +typedef struct Emap_PackEntry_t_ Emap_PackEntry_t; +typedef struct Emap_Tuple_t_ Emap_Tuple_t; +typedef struct Emap_Tuples_t_ Emap_Tuples_t; +typedef struct Emap_Lib_t_ Emap_Lib_t; + +struct Emap_Cut_t_ +{ + int nLeaves; + int Leaves[EMAP_LEAF_MAX]; + word Truth; +}; + +struct Emap_Best_t_ +{ + Mio_Gate_t * pGate; + int Cut; + int nPins; + int PinToLeaf[EMAP_LEAF_MAX]; + int PinPhase[EMAP_LEAF_MAX]; + int TwinObj; + int TwinPhase; + int fInv; + double Arr; + float Flow; +}; + +struct Emap_Obj_t_ +{ + int nCuts; + Emap_Cut_t Cuts[EMAP_CUT_MAX]; + Emap_Best_t Best[2]; +}; + +struct Emap_Cell_t_ +{ + Mio_Gate_t * pGate; + int nPins; + int PinToLeaf[EMAP_LEAF_MAX]; + int PinPhase[EMAP_LEAF_MAX]; + word Truth; + float Area; + float Delay[EMAP_LEAF_MAX]; +}; + +struct Emap_Mog_t_ +{ + Mio_Gate_t * pGate0; + Mio_Gate_t * pGate1; + int nPins; + int PinToLeaf[EMAP_LEAF_MAX]; + int PinPhase[EMAP_LEAF_MAX]; + word Truth0; + word Truth1; + float Area; + float Delay0[EMAP_LEAF_MAX]; + float Delay1[EMAP_LEAF_MAX]; +}; + +struct Emap_PackEntry_t_ +{ + int ObjId; + int Phase; + int Cut; + int nLeaves; + int Leaves[EMAP_LEAF_MAX]; + word Truth; +}; + +struct Emap_Tuple_t_ +{ + int Obj0; + int Phase0; + int Cut0; + int Obj1; + int Phase1; + int Cut1; + int Mog; + int fSwap; + int NextHigh; + int NextLow; +}; + +struct Emap_Tuples_t_ +{ + Emap_Tuple_t * pArray; + int nSize; + int nCap; + int * pFirstHigh; + int * pFirstLow; + int nAreaCalls; + int nAreaCandidates; + int nAreaRejectTwin; + int nAreaRejectRequired; + int nAreaRejectFlow; + int nAreaAccepts; + int nAreaSamples; + int nExactLocalCalls; + int nExactLocalCandidates; + int nExactLocalRejectUnused; + int nExactLocalRejectTwin; + int nExactLocalRejectShared; + int nExactLocalRejectRequired; + int nExactLocalRejectArea; + int nExactLocalAccepts; + int nExactLocalCand2; + int nExactLocalCand3; + int nExactLocalAccept2; + int nExactLocalAccept3; +}; + +struct Emap_Lib_t_ +{ + Emap_Cell_t * pCells; + int nCells; + int nCap; + Emap_Mog_t * pMogs; + int nMogs; + int nMogCap; + Mio_Gate_t * pGateInv; + float InvArea; + float InvDelay; +}; + +static Abc_Obj_t * Emap_ManCreateInv ( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanin, Mio_Gate_t * pGateInv ); +static Abc_Obj_t * Emap_ManBuildPhase_rec ( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Emap_Obj_t * pMaps, Vec_Int_t * vCopy, int ObjId, int Phase, Emap_Lib_t * pLib ); +static int Emap_ObjPairHasDirectDanglingRelation( Abc_Ntk_t * pNtk, int ObjId0, int ObjId1 ); +static int Emap_ObjPairHasTfiRelation( Abc_Ntk_t * pNtk, int ObjId0, int ObjId1 ); +static int Emap_ObjPairHasMffcDanglingRelation( Abc_Ntk_t * pNtk, int ObjId0, int ObjId1, Emap_Cut_t * pCut, char * pLeafMarks, int * pDecs, Vec_Int_t * vTouched ); +static double Emap_MogArrival ( Emap_Obj_t * pMaps, Emap_Cut_t * pCut, Emap_Mog_t * pMog, int fSwap ); +static void Emap_MogApply ( Emap_Obj_t * pMaps, Emap_PackEntry_t * pEntry0, Emap_PackEntry_t * pEntry1, Emap_Mog_t * pMog, int fSwap ); +static void Emap_MogSetOppositePhase( Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int ObjId, int Phase, float Flow ); +static int Emap_NodeMatchMogExactLocal( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, Emap_Tuples_t * pTuples, int * pRefs, double * pRequired, Vec_Int_t * vTouched, int ObjId ); +static float Emap_ManComputeActualMappedStats( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, Mio_Library_t * pMio, double * pDelay ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline word Emap_TruthMask( int nVars ) +{ + return nVars == 6 ? ~(word)0 : (((word)1) << (1 << nVars)) - 1; +} + +static inline word Emap_TruthVar( int Var, int nVars ) +{ + word t = 0; + int m; + assert( Var < nVars ); + for ( m = 0; m < (1 << nVars); m++ ) + if ( (m >> Var) & 1 ) + t |= ((word)1) << m; + return t; +} + +static word Emap_TruthStretch( word Truth, int * pLeaves, int nLeaves, int * pLeavesNew, int nLeavesNew ) +{ + word Res = 0; + int m, i, k, mOld; + assert( nLeaves <= nLeavesNew ); + for ( m = 0; m < (1 << nLeavesNew); m++ ) + { + mOld = 0; + for ( i = 0; i < nLeaves; i++ ) + { + for ( k = 0; k < nLeavesNew; k++ ) + if ( pLeaves[i] == pLeavesNew[k] ) + break; + assert( k < nLeavesNew ); + if ( (m >> k) & 1 ) + mOld |= 1 << i; + } + if ( (Truth >> mOld) & 1 ) + Res |= ((word)1) << m; + } + return Res; +} + +static word Emap_TruthPermutePhase( word Truth, int nVars, int * pPinToLeaf, int * pPinPhase ) +{ + word Res = 0; + int m, i, mOld, Bit; + for ( m = 0; m < (1 << nVars); m++ ) + { + mOld = 0; + for ( i = 0; i < nVars; i++ ) + { + Bit = (m >> pPinToLeaf[i]) & 1; + if ( pPinPhase[i] ) + Bit ^= 1; + if ( Bit ) + mOld |= 1 << i; + } + if ( (Truth >> mOld) & 1 ) + Res |= ((word)1) << m; + } + return Res; +} + +static word Emap_TruthShrink6( word Truth, int nVars ) +{ + word Res = 0; + int m; + assert( nVars <= 6 ); + for ( m = 0; m < (1 << nVars); m++ ) + if ( (Truth >> m) & 1 ) + Res |= ((word)1) << m; + return Res; +} + +/**Function************************************************************* + + Synopsis [Creates a mapped inverter node.] + +***********************************************************************/ +static Abc_Obj_t * Emap_ManCreateInv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanin, Mio_Gate_t * pGateInv ) +{ + Abc_Obj_t * pObj; + assert( pGateInv != NULL ); + pObj = Abc_NtkCreateNode( pNtkNew ); + pObj->pData = pGateInv; + Abc_ObjAddFanin( pObj, pFanin ); + return pObj; +} + +static void Emap_BestClean( Emap_Best_t * pBest ) +{ + memset( pBest, 0, sizeof(Emap_Best_t) ); + pBest->Cut = -1; + pBest->TwinObj = -1; + pBest->TwinPhase = -1; + pBest->Arr = EMAP_DOUBLE_LARGE; + pBest->Flow = EMAP_FLOAT_LARGE; +} + +static int Emap_BestIsBetterDelay( double ArrNew, float FlowNew, Emap_Best_t * pBest ) +{ + if ( ArrNew < pBest->Arr - 0.0001 ) + return 1; + if ( ArrNew > pBest->Arr + 0.0001 ) + return 0; + return FlowNew < pBest->Flow - 0.0001; +} + +static int Emap_BestIsBetterArea( double ArrNew, float FlowNew, Emap_Best_t * pBest ) +{ + if ( FlowNew < pBest->Flow - 0.0001 ) + return 1; + if ( FlowNew > pBest->Flow + 0.0001 ) + return 0; + return ArrNew < pBest->Arr - 0.0001; +} + +static int Emap_CutEqual( Emap_Cut_t * pCut, int * pLeaves, int nLeaves, word Truth ) +{ + int i; + if ( pCut->nLeaves != nLeaves || pCut->Truth != Truth ) + return 0; + for ( i = 0; i < nLeaves; i++ ) + if ( pCut->Leaves[i] != pLeaves[i] ) + return 0; + return 1; +} + +static int Emap_CutInsert( Emap_Obj_t * pMap, int * pLeaves, int nLeaves, word Truth ) +{ + Emap_Cut_t * pCut; + int i, iWorst = -1, nWorst = -1; + Truth &= Emap_TruthMask( nLeaves ); + for ( i = 0; i < pMap->nCuts; i++ ) + if ( Emap_CutEqual( &pMap->Cuts[i], pLeaves, nLeaves, Truth ) ) + return 0; + if ( pMap->nCuts == EMAP_CUT_MAX ) + { + for ( i = 0; i < pMap->nCuts; i++ ) + if ( pMap->Cuts[i].nLeaves > nWorst ) + nWorst = pMap->Cuts[i].nLeaves, iWorst = i; + if ( nLeaves >= nWorst ) + return 0; + pCut = &pMap->Cuts[iWorst]; + } + else + pCut = &pMap->Cuts[pMap->nCuts++]; + pCut->nLeaves = nLeaves; + pCut->Truth = Truth; + for ( i = 0; i < nLeaves; i++ ) + pCut->Leaves[i] = pLeaves[i]; + return 1; +} + +static int Emap_CutMergeLeaves( Emap_Cut_t * pCut0, Emap_Cut_t * pCut1, int * pLeaves ) +{ + int i = 0, k = 0, nLeaves = 0; + while ( i < pCut0->nLeaves || k < pCut1->nLeaves ) + { + int Leaf; + if ( k == pCut1->nLeaves || (i < pCut0->nLeaves && pCut0->Leaves[i] < pCut1->Leaves[k]) ) + Leaf = pCut0->Leaves[i++]; + else if ( i == pCut0->nLeaves || pCut1->Leaves[k] < pCut0->Leaves[i] ) + Leaf = pCut1->Leaves[k++]; + else + { + Leaf = pCut0->Leaves[i]; + i++; + k++; + } + if ( nLeaves == EMAP_LEAF_MAX ) + return -1; + pLeaves[nLeaves++] = Leaf; + } + return nLeaves; +} + +static void Emap_NodeAddUnitCut( Emap_Obj_t * pMap, int ObjId ) +{ + int Leaves[1]; + Leaves[0] = ObjId; + Emap_CutInsert( pMap, Leaves, 1, Emap_TruthVar( 0, 1 ) ); +} + +static void Emap_NodeAddConstCut( Emap_Obj_t * pMap ) +{ + Emap_CutInsert( pMap, NULL, 0, 1 ); +} + +static void Emap_LibAddCell( Emap_Lib_t * p, Mio_Gate_t * pGate, int * pPinToLeaf, int * pPinPhase, word Truth ) +{ + Emap_Cell_t * pCell; + Mio_Pin_t * pPin; + int i; + if ( p->nCells == p->nCap ) + { + p->nCap = p->nCap ? 2 * p->nCap : 1024; + p->pCells = ABC_REALLOC( Emap_Cell_t, p->pCells, p->nCap ); + } + pCell = &p->pCells[p->nCells++]; + memset( pCell, 0, sizeof(Emap_Cell_t) ); + pCell->pGate = pGate; + pCell->nPins = Mio_GateReadPinNum( pGate ); + pCell->Truth = Truth; + pCell->Area = (float)Mio_GateReadArea( pGate ); + for ( i = 0; i < pCell->nPins; i++ ) + { + pCell->PinToLeaf[i] = pPinToLeaf[i]; + pCell->PinPhase[i] = pPinPhase[i]; + } + i = 0; + Mio_GateForEachPin( pGate, pPin ) + pCell->Delay[i++] = (float)Mio_PinReadDelayBlockMax( pPin ); +} + +static void Emap_LibAddMog( Emap_Lib_t * p, Mio_Gate_t * pGate0, Mio_Gate_t * pGate1, int * pPinToLeaf, int * pPinPhase, word Truth0, word Truth1 ) +{ + Emap_Mog_t * pMog; + Mio_Pin_t * pPin; + int i; + if ( p->nMogs == p->nMogCap ) + { + p->nMogCap = p->nMogCap ? 2 * p->nMogCap : 128; + p->pMogs = ABC_REALLOC( Emap_Mog_t, p->pMogs, p->nMogCap ); + } + pMog = &p->pMogs[p->nMogs++]; + memset( pMog, 0, sizeof(Emap_Mog_t) ); + pMog->pGate0 = pGate0; + pMog->pGate1 = pGate1; + pMog->nPins = Mio_GateReadPinNum( pGate0 ); + pMog->Truth0 = Truth0; + pMog->Truth1 = Truth1; + pMog->Area = (float)Mio_GateReadArea( pGate0 ); + for ( i = 0; i < pMog->nPins; i++ ) + { + pMog->PinToLeaf[i] = pPinToLeaf[i]; + pMog->PinPhase[i] = pPinPhase[i]; + } + i = 0; + Mio_GateForEachPin( pGate0, pPin ) + pMog->Delay0[i++] = (float)Mio_PinReadDelayBlockMax( pPin ); + i = 0; + Mio_GateForEachPin( pGate1, pPin ) + pMog->Delay1[i++] = (float)Mio_PinReadDelayBlockMax( pPin ); +} + +static void Emap_LibPermute_rec( Emap_Lib_t * p, Mio_Gate_t * pGate, int nPins, int iPin, int * pPinToLeaf, int * pUsed ) +{ + int i; + if ( iPin == nPins ) + { + word Truth = Emap_TruthShrink6( Mio_GateReadTruth(pGate), nPins ); + int PinPhase[EMAP_LEAF_MAX]; + int Phase; + for ( Phase = 0; Phase < (1 << nPins); Phase++ ) + { + for ( i = 0; i < nPins; i++ ) + PinPhase[i] = (Phase >> i) & 1; + Emap_LibAddCell( p, pGate, pPinToLeaf, PinPhase, Emap_TruthPermutePhase( Truth, nPins, pPinToLeaf, PinPhase ) ); + } + return; + } + for ( i = 0; i < nPins; i++ ) + { + if ( pUsed[i] ) + continue; + pUsed[i] = 1; + pPinToLeaf[iPin] = i; + Emap_LibPermute_rec( p, pGate, nPins, iPin + 1, pPinToLeaf, pUsed ); + pUsed[i] = 0; + } +} + +static void Emap_LibMogPermute_rec( Emap_Lib_t * p, Mio_Gate_t * pGate0, Mio_Gate_t * pGate1, int nPins, int iPin, int * pPinToLeaf, int * pUsed ) +{ + int i; + if ( iPin == nPins ) + { + word Truth0 = Emap_TruthShrink6( Mio_GateReadTruth(pGate0), nPins ); + word Truth1 = Emap_TruthShrink6( Mio_GateReadTruth(pGate1), nPins ); + int PinPhase[EMAP_LEAF_MAX]; + int Phase; + for ( Phase = 0; Phase < (1 << nPins); Phase++ ) + { + for ( i = 0; i < nPins; i++ ) + PinPhase[i] = (Phase >> i) & 1; + Emap_LibAddMog( p, pGate0, pGate1, pPinToLeaf, PinPhase, Emap_TruthPermutePhase( Truth0, nPins, pPinToLeaf, PinPhase ), Emap_TruthPermutePhase( Truth1, nPins, pPinToLeaf, PinPhase ) ); + } + return; + } + for ( i = 0; i < nPins; i++ ) + { + if ( pUsed[i] ) + continue; + pUsed[i] = 1; + pPinToLeaf[iPin] = i; + Emap_LibMogPermute_rec( p, pGate0, pGate1, nPins, iPin + 1, pPinToLeaf, pUsed ); + pUsed[i] = 0; + } +} + +static void Emap_LibFree( Emap_Lib_t * p ) +{ + ABC_FREE( p->pCells ); + ABC_FREE( p->pMogs ); +} + +static int Emap_CellCompare( void const * p0, void const * p1 ) +{ + Emap_Cell_t const * pCell0 = (Emap_Cell_t const *)p0; + Emap_Cell_t const * pCell1 = (Emap_Cell_t const *)p1; + if ( pCell0->nPins != pCell1->nPins ) + return pCell0->nPins - pCell1->nPins; + if ( pCell0->Truth < pCell1->Truth ) + return -1; + if ( pCell0->Truth > pCell1->Truth ) + return 1; + return 0; +} + +static int Emap_LibFindFirst( Emap_Lib_t * p, int nPins, word Truth ) +{ + int Beg = 0, End = p->nCells; + while ( Beg < End ) + { + int Mid = (Beg + End) >> 1; + Emap_Cell_t * pCell = &p->pCells[Mid]; + if ( pCell->nPins < nPins || (pCell->nPins == nPins && pCell->Truth < Truth) ) + Beg = Mid + 1; + else + End = Mid; + } + if ( Beg == p->nCells || p->pCells[Beg].nPins != nPins || p->pCells[Beg].Truth != Truth ) + return -1; + return Beg; +} + +static int Emap_LibPrepare( Emap_Lib_t * p, Mio_Library_t * pMio ) +{ + Mio_Gate_t * pGate; + int PinToLeaf[EMAP_LEAF_MAX], Used[EMAP_LEAF_MAX]; + memset( p, 0, sizeof(Emap_Lib_t) ); + p->pGateInv = Mio_LibraryReadInv( pMio ); + if ( p->pGateInv == NULL ) + { + printf( "Cannot find inverter gate in the current GENLIB library.\n" ); + return 0; + } + p->InvArea = (float)Mio_GateReadArea( p->pGateInv ); + p->InvDelay = Mio_GateReadPinNum(p->pGateInv) ? Mio_GateReadPinDelay( p->pGateInv, 0 ) : 0; + Mio_LibraryForEachGate( pMio, pGate ) + { + int nPins = Mio_GateReadPinNum( pGate ); + Mio_Gate_t * pTwin = Mio_GateReadTwin(pGate); + if ( nPins < 2 || nPins > EMAP_LEAF_MAX ) + continue; + if ( pTwin != NULL ) + { + if ( pGate > pTwin || Mio_GateReadPinNum(pTwin) != nPins ) + continue; + memset( Used, 0, sizeof(Used) ); + Emap_LibMogPermute_rec( p, pGate, pTwin, nPins, 0, PinToLeaf, Used ); + continue; + } + memset( Used, 0, sizeof(Used) ); + Emap_LibPermute_rec( p, pGate, nPins, 0, PinToLeaf, Used ); + } + qsort( p->pCells, p->nCells, sizeof(Emap_Cell_t), Emap_CellCompare ); + return 1; +} + +static int Emap_NodeMergeCuts( Emap_Obj_t * pMaps, Abc_Obj_t * pObj ) +{ + Emap_Obj_t * pMap = &pMaps[Abc_ObjId(pObj)]; + Emap_Obj_t * pMap0 = &pMaps[Abc_ObjFaninId0(pObj)]; + Emap_Obj_t * pMap1 = &pMaps[Abc_ObjFaninId1(pObj)]; + Emap_Cut_t * pCut0, * pCut1; + int Leaves[EMAP_LEAF_MAX]; + int i, k, nLeaves; + word Truth0, Truth1, Mask; + Emap_NodeAddUnitCut( pMap, Abc_ObjId(pObj) ); + for ( i = 0; i < pMap0->nCuts; i++ ) + for ( k = 0; k < pMap1->nCuts; k++ ) + { + pCut0 = &pMap0->Cuts[i]; + pCut1 = &pMap1->Cuts[k]; + nLeaves = Emap_CutMergeLeaves( pCut0, pCut1, Leaves ); + if ( nLeaves < 0 ) + continue; + Mask = Emap_TruthMask( nLeaves ); + Truth0 = Emap_TruthStretch( pCut0->Truth, pCut0->Leaves, pCut0->nLeaves, Leaves, nLeaves ); + Truth1 = Emap_TruthStretch( pCut1->Truth, pCut1->Leaves, pCut1->nLeaves, Leaves, nLeaves ); + if ( Abc_ObjFaninC0(pObj) ) Truth0 ^= Mask; + if ( Abc_ObjFaninC1(pObj) ) Truth1 ^= Mask; + Emap_CutInsert( pMap, Leaves, nLeaves, Truth0 & Truth1 ); + } + return pMap->nCuts > 1; +} + +static int Emap_BestIsBetterMode( double ArrNew, float FlowNew, Emap_Best_t * pBest, int fAreaMode ) +{ + return fAreaMode ? Emap_BestIsBetterArea( ArrNew, FlowNew, pBest ) : Emap_BestIsBetterDelay( ArrNew, FlowNew, pBest ); +} + +static void Emap_NodeMatch( Emap_Obj_t * pMaps, Emap_Obj_t * pMap, Emap_Lib_t * pLib, Abc_Obj_t * pObj, double * pRequired, int * pRefs ) +{ + Emap_Cut_t * pCut; + Emap_Cell_t * pCell; + word Mask; + int i, k, c, fCompl, fAreaMode = (pRequired != NULL); + Emap_BestClean( &pMap->Best[0] ); + Emap_BestClean( &pMap->Best[1] ); + for ( i = 0; i < pMap->nCuts; i++ ) + { + pCut = &pMap->Cuts[i]; + if ( pCut->nLeaves < 2 ) + continue; + Mask = Emap_TruthMask( pCut->nLeaves ); + for ( fCompl = 0; fCompl < 2; fCompl++ ) + { + c = Emap_LibFindFirst( pLib, pCut->nLeaves, fCompl ? (pCut->Truth ^ Mask) : pCut->Truth ); + if ( c < 0 ) + continue; + for ( ; c < pLib->nCells; c++ ) + { + double Arr = 0; + double Required = fAreaMode ? pRequired[2 * Abc_ObjId(pObj) + fCompl] : EMAP_DOUBLE_LARGE; + float Flow; + pCell = &pLib->pCells[c]; + if ( pCell->nPins != pCut->nLeaves || pCell->Truth != (fCompl ? (pCut->Truth ^ Mask) : pCut->Truth) ) + break; + Flow = pCell->Area; + for ( k = 0; k < pCut->nLeaves; k++ ) + { + Abc_Obj_t * pLeaf = Abc_NtkObj( pObj->pNtk, pCut->Leaves[pCell->PinToLeaf[k]] ); + Emap_Best_t * pLeafBest = &pMaps[Abc_ObjId(pLeaf)].Best[pCell->PinPhase[k]]; + int LeafPhase = pCell->PinPhase[k]; + float Div = (float)Abc_MaxInt( 1, pRefs ? pRefs[2 * Abc_ObjId(pLeaf) + LeafPhase] : Abc_ObjFanoutNum(pLeaf) ); + Arr = Abc_MaxDouble( Arr, pLeafBest->Arr + pCell->Delay[k] ); + Flow += pLeafBest->Flow / Div; + } + if ( Arr > Required + 0.001 ) + continue; + if ( Emap_BestIsBetterMode( Arr, Flow, &pMap->Best[fCompl], fAreaMode ) ) + { + pMap->Best[fCompl].pGate = pCell->pGate; + pMap->Best[fCompl].Cut = i; + pMap->Best[fCompl].nPins = pCell->nPins; + pMap->Best[fCompl].Arr = Arr; + pMap->Best[fCompl].Flow = Flow; + pMap->Best[fCompl].fInv = 0; + for ( k = 0; k < pCell->nPins; k++ ) + { + pMap->Best[fCompl].PinToLeaf[k] = pCell->PinToLeaf[k]; + pMap->Best[fCompl].PinPhase[k] = pCell->PinPhase[k]; + } + } + } + } + } + for ( fCompl = 0; fCompl < 2; fCompl++ ) + if ( pMap->Best[!fCompl].pGate && (!fAreaMode || pMap->Best[!fCompl].Arr + pLib->InvDelay <= pRequired[2 * Abc_ObjId(pObj) + fCompl] + 0.001) && Emap_BestIsBetterMode( pMap->Best[!fCompl].Arr + pLib->InvDelay, pMap->Best[!fCompl].Flow + pLib->InvArea, &pMap->Best[fCompl], fAreaMode ) ) + { + pMap->Best[fCompl] = pMap->Best[!fCompl]; + pMap->Best[fCompl].fInv = 1; + pMap->Best[fCompl].Arr += pLib->InvDelay; + pMap->Best[fCompl].Flow += pLib->InvArea; + } +} + +static void Emap_NodeDropPhaseArea( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, double * pRequired, int * pRefs, int ObjId ) +{ + Emap_Obj_t * pMap = &pMaps[ObjId]; + Emap_Best_t Best0 = pMap->Best[0]; + Emap_Best_t Best1 = pMap->Best[1]; + float Est0 = (float)Abc_MaxInt( 1, pRefs ? pRefs[2 * ObjId + 0] : Abc_ObjFanoutNum(Abc_NtkObj(pNtk, ObjId)) ); + float Est1 = (float)Abc_MaxInt( 1, pRefs ? pRefs[2 * ObjId + 1] : Abc_ObjFanoutNum(Abc_NtkObj(pNtk, ObjId)) ); + int fUse0, fUse1; + if ( Best0.pGate == NULL || Best1.pGate == NULL || Best0.fInv || Best1.fInv || Best0.TwinObj >= 0 || Best1.TwinObj >= 0 ) + return; + fUse0 = Best0.Arr + pLib->InvDelay <= pRequired[2 * ObjId + 1] + 0.001; + fUse1 = Best1.Arr + pLib->InvDelay <= pRequired[2 * ObjId + 0] + 0.001; + if ( !fUse0 && !fUse1 ) + return; + if ( fUse0 && fUse1 ) + { + float Cost0 = Best0.Flow / Est0 + pLib->InvArea; + float Cost1 = Best1.Flow / Est1 + pLib->InvArea; + if ( Cost0 < Cost1 - 0.001 ) + fUse1 = 0; + else if ( Cost1 < Cost0 - 0.001 ) + fUse0 = 0; + else if ( Best0.Arr + pLib->InvDelay <= Best1.Arr + pLib->InvDelay ) + fUse1 = 0; + else + fUse0 = 0; + } + if ( fUse0 ) + { + pMap->Best[1] = Best0; + pMap->Best[1].fInv = 1; + pMap->Best[1].TwinObj = -1; + pMap->Best[1].TwinPhase = -1; + pMap->Best[1].Arr = Best0.Arr + pLib->InvDelay; + pMap->Best[1].Flow = Best0.Flow + pLib->InvArea; + } + else + { + pMap->Best[0] = Best1; + pMap->Best[0].fInv = 1; + pMap->Best[0].TwinObj = -1; + pMap->Best[0].TwinPhase = -1; + pMap->Best[0].Arr = Best1.Arr + pLib->InvDelay; + pMap->Best[0].Flow = Best1.Flow + pLib->InvArea; + } +} + +static void Emap_RequiredUpdate( double * pRequired, int ObjId, int Phase, double Required ) +{ + if ( Required < pRequired[2 * ObjId + Phase] ) + pRequired[2 * ObjId + Phase] = Required; +} + +static void Emap_RequiredPropagatePhase( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, double * pRequired, int ObjId, int Phase ) +{ + Emap_Obj_t * pMap = &pMaps[ObjId]; + Emap_Best_t * pBest = &pMap->Best[Phase]; + Emap_Cut_t * pCut; + double Required = pRequired[2 * ObjId + Phase]; + int i; + if ( Required >= EMAP_DOUBLE_LARGE / 2 ) + return; + if ( ObjId == Abc_ObjId(Abc_AigConst1(pNtk)) || Abc_ObjIsPi(Abc_NtkObj(pNtk, ObjId)) ) + return; + if ( pBest->fInv ) + { + Emap_RequiredUpdate( pRequired, ObjId, !Phase, Required - pLib->InvDelay ); + return; + } + if ( pBest->pGate == NULL ) + return; + pCut = &pMap->Cuts[pBest->Cut]; + for ( i = 0; i < pBest->nPins; i++ ) + Emap_RequiredUpdate( pRequired, pCut->Leaves[pBest->PinToLeaf[i]], pBest->PinPhase[i], Required - Mio_GateReadPinDelay(pBest->pGate, i) ); +} + +static void Emap_RequiredPropagateUsedObj( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, double * pRequired, int * pRefs, int ObjId ) +{ + Emap_Obj_t * pMap = &pMaps[ObjId]; + Emap_Best_t * pBest; + Emap_Cut_t * pCut; + int Phase, i; + if ( ObjId == Abc_ObjId(Abc_AigConst1(pNtk)) || Abc_ObjIsPi(Abc_NtkObj(pNtk, ObjId)) ) + return; + for ( Phase = 0; Phase < 2; Phase++ ) + { + pBest = &pMap->Best[Phase]; + if ( pRefs[2 * ObjId + Phase] == 0 || !pBest->fInv || pRequired[2 * ObjId + Phase] >= EMAP_DOUBLE_LARGE / 2 ) + continue; + Emap_RequiredUpdate( pRequired, ObjId, !Phase, pRequired[2 * ObjId + Phase] - pLib->InvDelay ); + } + for ( Phase = 0; Phase < 2; Phase++ ) + { + pBest = &pMap->Best[Phase]; + if ( pBest->pGate == NULL || pBest->fInv || pRequired[2 * ObjId + Phase] >= EMAP_DOUBLE_LARGE / 2 ) + continue; + pCut = &pMap->Cuts[pBest->Cut]; + for ( i = 0; i < pBest->nPins; i++ ) + Emap_RequiredUpdate( pRequired, pCut->Leaves[pBest->PinToLeaf[i]], pBest->PinPhase[i], pRequired[2 * ObjId + Phase] - Mio_GateReadPinDelay(pBest->pGate, i) ); + } +} + +static double Emap_ManComputeRequired( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, double * pRequired ) +{ + Abc_Obj_t * pObj; + double DelayTarget = 0; + int i, Phase; + for ( i = 0; i < 2 * Abc_NtkObjNumMax(pNtk); i++ ) + pRequired[i] = EMAP_DOUBLE_LARGE; + Abc_NtkForEachPo( pNtk, pObj, i ) + { + Phase = Abc_ObjFaninC0(pObj); + DelayTarget = Abc_MaxDouble( DelayTarget, pMaps[Abc_ObjFaninId0(pObj)].Best[Phase].Arr ); + } + Abc_NtkForEachPo( pNtk, pObj, i ) + Emap_RequiredUpdate( pRequired, Abc_ObjFaninId0(pObj), Abc_ObjFaninC0(pObj), DelayTarget ); + Abc_NtkForEachNodeReverse( pNtk, pObj, i ) + { + if ( !Abc_AigNodeIsAnd(pObj) ) + continue; + Emap_RequiredPropagatePhase( pNtk, pMaps, pLib, pRequired, Abc_ObjId(pObj), 0 ); + Emap_RequiredPropagatePhase( pNtk, pMaps, pLib, pRequired, Abc_ObjId(pObj), 1 ); + } + return DelayTarget; +} + +static void Emap_ManComputeRequiredTarget( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, double * pRequired, int * pRefs, double DelayTarget ) +{ + Abc_Obj_t * pObj; + int i; + for ( i = 0; i < 2 * Abc_NtkObjNumMax(pNtk); i++ ) + pRequired[i] = EMAP_DOUBLE_LARGE; + Abc_NtkForEachPo( pNtk, pObj, i ) + Emap_RequiredUpdate( pRequired, Abc_ObjFaninId0(pObj), Abc_ObjFaninC0(pObj), DelayTarget ); + Abc_NtkForEachNodeReverse( pNtk, pObj, i ) + { + if ( !Abc_AigNodeIsAnd(pObj) ) + continue; + Emap_RequiredPropagateUsedObj( pNtk, pMaps, pLib, pRequired, pRefs, Abc_ObjId(pObj) ); + } +} + +static void Emap_RefPhase_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, int ObjId, int Phase ) +{ + Emap_Obj_t * pMap = &pMaps[ObjId]; + Emap_Best_t * pBest = &pMap->Best[Phase]; + Emap_Cut_t * pCut; + int i; + if ( ObjId == Abc_ObjId(Abc_AigConst1(pNtk)) || Abc_ObjIsPi(Abc_NtkObj(pNtk, ObjId)) ) + return; + if ( pRefs[2 * ObjId + Phase]++ > 0 ) + return; + if ( pBest->fInv ) + { + Emap_RefPhase_rec( pNtk, pMaps, pLib, pRefs, ObjId, !Phase ); + return; + } + if ( pBest->pGate == NULL ) + return; + pCut = &pMap->Cuts[pBest->Cut]; + for ( i = 0; i < pBest->nPins; i++ ) + Emap_RefPhase_rec( pNtk, pMaps, pLib, pRefs, pCut->Leaves[pBest->PinToLeaf[i]], pBest->PinPhase[i] ); +} + +static void Emap_ManComputeRefs( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs ) +{ + Abc_Obj_t * pObj; + int i; + memset( pRefs, 0, sizeof(int) * 2 * Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Emap_RefPhase_rec( pNtk, pMaps, pLib, pRefs, Abc_ObjFaninId0(pObj), Abc_ObjFaninC0(pObj) ); +} + +static float Emap_ManComputeArea( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs ) +{ + Abc_Obj_t * pObj; + float Area = 0; + int i, f; + Emap_ManComputeRefs( pNtk, pMaps, pLib, pRefs ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + for ( f = 0; f < 2; f++ ) + { + Emap_Best_t * pBest = &pMaps[Abc_ObjId(pObj)].Best[f]; + if ( pRefs[2 * Abc_ObjId(pObj) + f] == 0 ) + continue; + if ( pBest->TwinObj >= 0 && 2 * Abc_ObjId(pObj) + f > 2 * pBest->TwinObj + pBest->TwinPhase ) + continue; + Area += pBest->fInv ? pLib->InvArea : (float)Mio_GateReadArea(pBest->pGate); + } + } + return Area; +} + +static void Emap_ManSaveBests( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Best_t * pSave ) +{ + int i; + for ( i = 0; i < Abc_NtkObjNumMax(pNtk); i++ ) + { + pSave[2 * i + 0] = pMaps[i].Best[0]; + pSave[2 * i + 1] = pMaps[i].Best[1]; + } +} + +static void Emap_ManRestoreBests( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Best_t * pSave ) +{ + int i; + for ( i = 0; i < Abc_NtkObjNumMax(pNtk); i++ ) + { + pMaps[i].Best[0] = pSave[2 * i + 0]; + pMaps[i].Best[1] = pSave[2 * i + 1]; + } +} + +static float Emap_PhaseRefVisit_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, Vec_Int_t * vTouched, int ObjId, int Phase ); +static float Emap_PhaseRef_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, int ObjId, int Phase ); +static float Emap_PhaseDeref_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, int ObjId, int Phase ); + +static float Emap_CutRefLeaves_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, int ObjId, int Phase ) +{ + Emap_Best_t * pBest = &pMaps[ObjId].Best[Phase]; + Emap_Cut_t * pCut; + float Area; + int i; + if ( pBest->pGate == NULL && !pBest->fInv ) + return 0; + if ( pBest->fInv ) + return pLib->InvArea + Emap_PhaseRef_rec( pNtk, pMaps, pLib, pRefs, ObjId, !Phase ); + Area = (float)Mio_GateReadArea( pBest->pGate ); + pCut = &pMaps[ObjId].Cuts[pBest->Cut]; + for ( i = 0; i < pBest->nPins; i++ ) + Area += Emap_PhaseRef_rec( pNtk, pMaps, pLib, pRefs, pCut->Leaves[pBest->PinToLeaf[i]], pBest->PinPhase[i] ); + return Area; +} + +static float Emap_CutDerefLeaves_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, int ObjId, int Phase ) +{ + Emap_Best_t * pBest = &pMaps[ObjId].Best[Phase]; + Emap_Cut_t * pCut; + float Area; + int i; + if ( pBest->pGate == NULL && !pBest->fInv ) + return 0; + if ( pBest->fInv ) + return pLib->InvArea + Emap_PhaseDeref_rec( pNtk, pMaps, pLib, pRefs, ObjId, !Phase ); + Area = (float)Mio_GateReadArea( pBest->pGate ); + pCut = &pMaps[ObjId].Cuts[pBest->Cut]; + for ( i = 0; i < pBest->nPins; i++ ) + Area += Emap_PhaseDeref_rec( pNtk, pMaps, pLib, pRefs, pCut->Leaves[pBest->PinToLeaf[i]], pBest->PinPhase[i] ); + return Area; +} + +static float Emap_CutRefOnlyLeaves_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, int ObjId, int Phase ) +{ + Emap_Best_t * pBest = &pMaps[ObjId].Best[Phase]; + Emap_Cut_t * pCut; + float Area = 0; + int i; + if ( pBest->pGate == NULL && !pBest->fInv ) + return 0; + if ( pBest->fInv ) + return pLib->InvArea + Emap_PhaseRef_rec( pNtk, pMaps, pLib, pRefs, ObjId, !Phase ); + pCut = &pMaps[ObjId].Cuts[pBest->Cut]; + for ( i = 0; i < pBest->nPins; i++ ) + Area += Emap_PhaseRef_rec( pNtk, pMaps, pLib, pRefs, pCut->Leaves[pBest->PinToLeaf[i]], pBest->PinPhase[i] ); + return Area; +} + +static float Emap_PhaseRef_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, int ObjId, int Phase ) +{ + if ( ObjId == Abc_ObjId(Abc_AigConst1(pNtk)) || Abc_ObjIsPi(Abc_NtkObj(pNtk, ObjId)) ) + return 0; + if ( pRefs[2 * ObjId + Phase]++ > 0 ) + return 0; + return Emap_CutRefLeaves_rec( pNtk, pMaps, pLib, pRefs, ObjId, Phase ); +} + +static float Emap_PhaseDeref_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, int ObjId, int Phase ) +{ + if ( ObjId == Abc_ObjId(Abc_AigConst1(pNtk)) || Abc_ObjIsPi(Abc_NtkObj(pNtk, ObjId)) ) + return 0; + assert( pRefs[2 * ObjId + Phase] > 0 ); + if ( --pRefs[2 * ObjId + Phase] > 0 ) + return 0; + return Emap_CutDerefLeaves_rec( pNtk, pMaps, pLib, pRefs, ObjId, Phase ); +} + +static float Emap_CutRefVisitLeaves_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, Vec_Int_t * vTouched, int ObjId, int Phase ) +{ + Emap_Best_t * pBest = &pMaps[ObjId].Best[Phase]; + Emap_Cut_t * pCut; + float Area; + int i; + if ( pBest->pGate == NULL && !pBest->fInv ) + return 0; + if ( pBest->fInv ) + return pLib->InvArea + Emap_PhaseRefVisit_rec( pNtk, pMaps, pLib, pRefs, vTouched, ObjId, !Phase ); + Area = (float)Mio_GateReadArea( pBest->pGate ); + pCut = &pMaps[ObjId].Cuts[pBest->Cut]; + for ( i = 0; i < pBest->nPins; i++ ) + Area += Emap_PhaseRefVisit_rec( pNtk, pMaps, pLib, pRefs, vTouched, pCut->Leaves[pBest->PinToLeaf[i]], pBest->PinPhase[i] ); + return Area; +} + +static float Emap_CutRefOnlyLeavesVisit_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, Vec_Int_t * vTouched, int ObjId, int Phase ) +{ + Emap_Best_t * pBest = &pMaps[ObjId].Best[Phase]; + Emap_Cut_t * pCut; + float Area = 0; + int i; + if ( pBest->pGate == NULL && !pBest->fInv ) + return 0; + if ( pBest->fInv ) + return pLib->InvArea + Emap_PhaseRefVisit_rec( pNtk, pMaps, pLib, pRefs, vTouched, ObjId, !Phase ); + pCut = &pMaps[ObjId].Cuts[pBest->Cut]; + for ( i = 0; i < pBest->nPins; i++ ) + Area += Emap_PhaseRefVisit_rec( pNtk, pMaps, pLib, pRefs, vTouched, pCut->Leaves[pBest->PinToLeaf[i]], pBest->PinPhase[i] ); + return Area; +} + +static float Emap_PhaseRefVisit_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, Vec_Int_t * vTouched, int ObjId, int Phase ) +{ + if ( ObjId == Abc_ObjId(Abc_AigConst1(pNtk)) || Abc_ObjIsPi(Abc_NtkObj(pNtk, ObjId)) ) + return 0; + Vec_IntPush( vTouched, 2 * ObjId + Phase ); + if ( pRefs[2 * ObjId + Phase]++ > 0 ) + return 0; + return Emap_CutRefVisitLeaves_rec( pNtk, pMaps, pLib, pRefs, vTouched, ObjId, Phase ); +} + +static float Emap_CutMeasureCandidate( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, Vec_Int_t * vTouched, int ObjId, Emap_Cut_t * pCut, Emap_Cell_t * pCell ) +{ + float Area = pCell->Area; + int i, Entry; + Vec_IntClear( vTouched ); + for ( i = 0; i < pCell->nPins; i++ ) + Area += Emap_PhaseRefVisit_rec( pNtk, pMaps, pLib, pRefs, vTouched, pCut->Leaves[pCell->PinToLeaf[i]], pCell->PinPhase[i] ); + Vec_IntForEachEntryReverse( vTouched, Entry, i ) + pRefs[Entry]--; + return Area; +} + +static void Emap_NodeRefreshInverterPhase( Emap_Obj_t * pMap, Emap_Lib_t * pLib, int Phase ) +{ + if ( !pMap->Best[Phase].fInv ) + return; + pMap->Best[Phase] = pMap->Best[!Phase]; + pMap->Best[Phase].fInv = 1; + pMap->Best[Phase].Arr += pLib->InvDelay; + pMap->Best[Phase].Flow += pLib->InvArea; +} + +static int Emap_NodeImproveExactPhase( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, double * pRequired, Vec_Int_t * vTouched, int ObjId, int Phase, int fRelaxArrival ) +{ + Emap_Obj_t * pMap = &pMaps[ObjId]; + Emap_Best_t OldBest = pMap->Best[Phase]; + Emap_Best_t BestBest = OldBest; + Emap_Cut_t * pCut; + Emap_Cell_t * pCell; + word Mask; + float AreaOld, AreaBest, AreaCand; + double Required, ArrBest, ArrCand; + int i, k, c, fCompl, fChanged = 0; + if ( pRefs[2 * ObjId + Phase] == 0 ) + return 0; + if ( OldBest.pGate == NULL || OldBest.fInv || OldBest.TwinObj >= 0 ) + return 0; + Required = pRequired[2 * ObjId + Phase]; + if ( Required >= EMAP_DOUBLE_LARGE / 2 ) + return 0; + AreaOld = Emap_CutDerefLeaves_rec( pNtk, pMaps, pLib, pRefs, ObjId, Phase ); + AreaBest = AreaOld; + ArrBest = OldBest.Arr; + for ( i = 0; i < pMap->nCuts; i++ ) + { + pCut = &pMap->Cuts[i]; + if ( pCut->nLeaves < 2 ) + continue; + Mask = Emap_TruthMask( pCut->nLeaves ); + for ( fCompl = 0; fCompl < 2; fCompl++ ) + { + if ( fCompl != Phase ) + continue; + c = Emap_LibFindFirst( pLib, pCut->nLeaves, fCompl ? (pCut->Truth ^ Mask) : pCut->Truth ); + if ( c < 0 ) + continue; + for ( ; c < pLib->nCells; c++ ) + { + pCell = &pLib->pCells[c]; + if ( pCell->nPins != pCut->nLeaves || pCell->Truth != (fCompl ? (pCut->Truth ^ Mask) : pCut->Truth) ) + break; + ArrCand = 0; + for ( k = 0; k < pCell->nPins; k++ ) + ArrCand = Abc_MaxDouble( ArrCand, pMaps[pCut->Leaves[pCell->PinToLeaf[k]]].Best[pCell->PinPhase[k]].Arr + pCell->Delay[k] ); + if ( ArrCand > Required + 0.001 ) + continue; + if ( !fRelaxArrival && ArrCand > OldBest.Arr + 0.001 ) + continue; + AreaCand = Emap_CutMeasureCandidate( pNtk, pMaps, pLib, pRefs, vTouched, ObjId, pCut, pCell ); + if ( AreaCand < AreaBest - 0.001 || (AreaCand < AreaBest + 0.001 && ArrCand < ArrBest - 0.001) ) + { + Emap_BestClean( &BestBest ); + BestBest.pGate = pCell->pGate; + BestBest.Cut = i; + BestBest.nPins = pCell->nPins; + BestBest.Arr = ArrCand; + BestBest.Flow = AreaCand; + BestBest.fInv = 0; + for ( k = 0; k < pCell->nPins; k++ ) + { + BestBest.PinToLeaf[k] = pCell->PinToLeaf[k]; + BestBest.PinPhase[k] = pCell->PinPhase[k]; + } + AreaBest = AreaCand; + ArrBest = ArrCand; + } + } + } + } + fChanged = (BestBest.pGate != OldBest.pGate || BestBest.Cut != OldBest.Cut || memcmp( BestBest.PinToLeaf, OldBest.PinToLeaf, sizeof(int) * EMAP_LEAF_MAX ) || memcmp( BestBest.PinPhase, OldBest.PinPhase, sizeof(int) * EMAP_LEAF_MAX )); + pMap->Best[Phase] = BestBest; + Emap_CutRefLeaves_rec( pNtk, pMaps, pLib, pRefs, ObjId, Phase ); + return fChanged; +} + +static int Emap_NodeDropPhaseExact( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, double * pRequired, int ObjId, int Phase ) +{ + Emap_Obj_t * pMap = &pMaps[ObjId]; + Emap_Best_t OldBest = pMap->Best[Phase]; + Emap_Best_t SrcBest = pMap->Best[!Phase]; + float AreaOld, AreaNew; + if ( pRefs[2 * ObjId + Phase] == 0 ) + return 0; + if ( SrcBest.pGate == NULL || SrcBest.fInv || SrcBest.TwinObj >= 0 ) + return 0; + if ( SrcBest.Arr + pLib->InvDelay > pRequired[2 * ObjId + Phase] + 0.001 ) + return 0; + AreaOld = Emap_CutDerefLeaves_rec( pNtk, pMaps, pLib, pRefs, ObjId, Phase ); + pMap->Best[Phase] = SrcBest; + pMap->Best[Phase].fInv = 1; + pMap->Best[Phase].TwinObj = -1; + pMap->Best[Phase].TwinPhase = -1; + pMap->Best[Phase].Arr = SrcBest.Arr + pLib->InvDelay; + pMap->Best[Phase].Flow = SrcBest.Flow + pLib->InvArea; + AreaNew = Emap_CutRefLeaves_rec( pNtk, pMaps, pLib, pRefs, ObjId, Phase ); + if ( AreaNew < AreaOld - 0.001 ) + return 1; + Emap_CutDerefLeaves_rec( pNtk, pMaps, pLib, pRefs, ObjId, Phase ); + pMap->Best[Phase] = OldBest; + Emap_CutRefLeaves_rec( pNtk, pMaps, pLib, pRefs, ObjId, Phase ); + return 0; +} + +static int Emap_ObjSharedPhase( Emap_Obj_t * pMaps, int * pRefs, int ObjId ) +{ + Emap_Best_t * pBest0 = &pMaps[ObjId].Best[0]; + Emap_Best_t * pBest1 = &pMaps[ObjId].Best[1]; + if ( pBest0->fInv && !pBest1->fInv && pBest1->pGate != NULL && pBest1->TwinObj < 0 ) + return 1; + if ( pBest1->fInv && !pBest0->fInv && pBest0->pGate != NULL && pBest0->TwinObj < 0 ) + return 0; + if ( pRefs[2 * ObjId] && !pRefs[2 * ObjId + 1] && !pBest0->fInv && pBest0->pGate != NULL && pBest0->TwinObj < 0 ) + return 0; + if ( pRefs[2 * ObjId + 1] && !pRefs[2 * ObjId] && !pBest1->fInv && pBest1->pGate != NULL && pBest1->TwinObj < 0 ) + return 1; + return -1; +} + +static float Emap_CutDerefLeavesLocal_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, Vec_Int_t * vTouched, int ObjId, int Phase ); + +static float Emap_PhaseDerefLocal_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, Vec_Int_t * vTouched, int ObjId, int Phase ) +{ + int Entry = 2 * ObjId + Phase; + if ( ObjId == Abc_ObjId(Abc_AigConst1(pNtk)) || Abc_ObjIsPi(Abc_NtkObj(pNtk, ObjId)) ) + return 0; + if ( pRefs[Entry] == 0 ) + return 0; + Vec_IntPush( vTouched, Entry ); + if ( --pRefs[Entry] > 0 ) + return 0; + return Emap_CutDerefLeavesLocal_rec( pNtk, pMaps, pLib, pRefs, vTouched, ObjId, Phase ); +} + +static float Emap_CutDerefLeavesLocal_rec( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, Vec_Int_t * vTouched, int ObjId, int Phase ) +{ + Emap_Best_t * pBest = &pMaps[ObjId].Best[Phase]; + Emap_Cut_t * pCut; + float Area; + int i; + if ( pBest->pGate == NULL && !pBest->fInv ) + return 0; + if ( pBest->fInv ) + return pLib->InvArea + Emap_PhaseDerefLocal_rec( pNtk, pMaps, pLib, pRefs, vTouched, ObjId, !Phase ); + Area = (float)Mio_GateReadArea( pBest->pGate ); + pCut = &pMaps[ObjId].Cuts[pBest->Cut]; + for ( i = 0; i < pBest->nPins; i++ ) + Area += Emap_PhaseDerefLocal_rec( pNtk, pMaps, pLib, pRefs, vTouched, pCut->Leaves[pBest->PinToLeaf[i]], pBest->PinPhase[i] ); + return Area; +} + +static float Emap_MogRefLeavesForUsedPhases( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int * pRefs, Vec_Int_t * vTouched, int ObjId, int Phase, int fVisit ) +{ + float Area = 0; + if ( pRefs[2 * ObjId + Phase] || pRefs[2 * ObjId + !Phase] ) + { + if ( fVisit ) + Area += Emap_CutRefOnlyLeavesVisit_rec( pNtk, pMaps, pLib, pRefs, vTouched, ObjId, Phase ); + else + Area += Emap_CutRefOnlyLeaves_rec( pNtk, pMaps, pLib, pRefs, ObjId, Phase ); + } + if ( pRefs[2 * ObjId + !Phase] ) + Area += pLib->InvArea; + return Area; +} + +static int Emap_NodeMatchMogExactLocal( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, Emap_Tuples_t * pTuples, int * pRefs, double * pRequired, Vec_Int_t * vTouched, int ObjId ) +{ + int iTuple, nChanged = 0; + if ( pTuples == NULL || pTuples->pFirstLow == NULL ) + return 0; + pTuples->nExactLocalCalls++; + for ( iTuple = pTuples->pFirstLow[ObjId]; iTuple >= 0; iTuple = pTuples->pArray[iTuple].NextLow ) + { + Emap_Tuple_t * pTuple = &pTuples->pArray[iTuple]; + Emap_Mog_t * pMog = &pLib->pMogs[pTuple->Mog]; + Emap_PackEntry_t Entry0, Entry1; + Emap_Best_t OldBest00, OldBest01, OldBest10, OldBest11; + int Shared0, Shared1, Entry, t, fObj0Low, nDerefTouched; + float AreaOld, AreaNew; + double Arr0, Arr1; + int Obj0 = pTuple->Obj0, Obj1 = pTuple->Obj1; + int Used0 = pRefs[2 * Obj0] || pRefs[2 * Obj0 + 1]; + int Used1 = pRefs[2 * Obj1] || pRefs[2 * Obj1 + 1]; + pTuples->nExactLocalCandidates++; + if ( pMog->nPins == 2 ) + pTuples->nExactLocalCand2++; + else if ( pMog->nPins == 3 ) + pTuples->nExactLocalCand3++; + if ( !Used0 || !Used1 ) + { + pTuples->nExactLocalRejectUnused++; + continue; + } + if ( pMaps[Obj0].Best[0].TwinObj >= 0 || pMaps[Obj0].Best[1].TwinObj >= 0 || pMaps[Obj1].Best[0].TwinObj >= 0 || pMaps[Obj1].Best[1].TwinObj >= 0 ) + { + pTuples->nExactLocalRejectTwin++; + continue; + } + Shared0 = Emap_ObjSharedPhase( pMaps, pRefs, Obj0 ); + Shared1 = Emap_ObjSharedPhase( pMaps, pRefs, Obj1 ); + if ( Shared0 < 0 || Shared1 < 0 ) + { + pTuples->nExactLocalRejectShared++; + continue; + } + Arr0 = Emap_MogArrival( pMaps, &pMaps[Obj0].Cuts[pTuple->Cut0], pMog, pTuple->fSwap ); + Arr1 = Emap_MogArrival( pMaps, &pMaps[Obj1].Cuts[pTuple->Cut1], pMog, !pTuple->fSwap ); + if ( Arr0 > pRequired[2 * Obj0 + pTuple->Phase0] + 0.001 || Arr1 > pRequired[2 * Obj1 + pTuple->Phase1] + 0.001 ) + { + pTuples->nExactLocalRejectRequired++; + continue; + } + if ( pRefs[2 * Obj0 + !pTuple->Phase0] && Arr0 + pLib->InvDelay > pRequired[2 * Obj0 + !pTuple->Phase0] + 0.001 ) + { + pTuples->nExactLocalRejectRequired++; + continue; + } + if ( pRefs[2 * Obj1 + !pTuple->Phase1] && Arr1 + pLib->InvDelay > pRequired[2 * Obj1 + !pTuple->Phase1] + 0.001 ) + { + pTuples->nExactLocalRejectRequired++; + continue; + } + + OldBest00 = pMaps[Obj0].Best[0]; + OldBest01 = pMaps[Obj0].Best[1]; + OldBest10 = pMaps[Obj1].Best[0]; + OldBest11 = pMaps[Obj1].Best[1]; + fObj0Low = Obj0 < Obj1; + Vec_IntClear( vTouched ); + AreaOld = 0; + if ( fObj0Low ) + { + AreaOld += Emap_CutDerefLeavesLocal_rec( pNtk, pMaps, pLib, pRefs, vTouched, Obj1, Shared1 ); + AreaOld += pRefs[2 * Obj1 + !Shared1] ? pLib->InvArea : 0; + AreaOld += Emap_CutDerefLeavesLocal_rec( pNtk, pMaps, pLib, pRefs, vTouched, Obj0, Shared0 ); + AreaOld += pRefs[2 * Obj0 + !Shared0] ? pLib->InvArea : 0; + } + else + { + AreaOld += Emap_CutDerefLeavesLocal_rec( pNtk, pMaps, pLib, pRefs, vTouched, Obj0, Shared0 ); + AreaOld += pRefs[2 * Obj0 + !Shared0] ? pLib->InvArea : 0; + AreaOld += Emap_CutDerefLeavesLocal_rec( pNtk, pMaps, pLib, pRefs, vTouched, Obj1, Shared1 ); + AreaOld += pRefs[2 * Obj1 + !Shared1] ? pLib->InvArea : 0; + } + nDerefTouched = Vec_IntSize( vTouched ); + + memset( &Entry0, 0, sizeof(Entry0) ); + memset( &Entry1, 0, sizeof(Entry1) ); + Entry0.ObjId = Obj0; Entry0.Phase = pTuple->Phase0; Entry0.Cut = pTuple->Cut0; + Entry1.ObjId = Obj1; Entry1.Phase = pTuple->Phase1; Entry1.Cut = pTuple->Cut1; + Emap_MogApply( pMaps, &Entry0, &Entry1, pMog, pTuple->fSwap ); + Emap_MogSetOppositePhase( pMaps, pLib, Obj0, pTuple->Phase0, pMog->Area ); + Emap_MogSetOppositePhase( pMaps, pLib, Obj1, pTuple->Phase1, pMog->Area ); + + AreaNew = pMog->Area; + AreaNew += Emap_MogRefLeavesForUsedPhases( pNtk, pMaps, pLib, pRefs, vTouched, Obj0, pTuple->Phase0, 1 ); + AreaNew += Emap_MogRefLeavesForUsedPhases( pNtk, pMaps, pLib, pRefs, vTouched, Obj1, pTuple->Phase1, 1 ); + Vec_IntForEachEntryReverse( vTouched, Entry, t ) + { + if ( t < nDerefTouched ) + break; + pRefs[Entry]--; + } + + if ( AreaNew < AreaOld - 0.001 ) + { + Emap_ManComputeRefs( pNtk, pMaps, pLib, pRefs ); + pTuples->nExactLocalAccepts++; + if ( pMog->nPins == 2 ) + pTuples->nExactLocalAccept2++; + else if ( pMog->nPins == 3 ) + pTuples->nExactLocalAccept3++; + nChanged++; + break; + } + pTuples->nExactLocalRejectArea++; + + pMaps[Obj0].Best[0] = OldBest00; + pMaps[Obj0].Best[1] = OldBest01; + pMaps[Obj1].Best[0] = OldBest10; + pMaps[Obj1].Best[1] = OldBest11; + for ( t = 0; t < nDerefTouched; t++ ) + pRefs[Vec_IntEntry(vTouched, t)]++; + } + return nChanged; +} + +static int Emap_ManRecoverExactArea( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, Emap_Tuples_t * pTuples, double * pRequired, int * pRefs, int nRounds, double DelayTarget, int fRelaxArrival, int fDropPhase ) +{ + Vec_Int_t * vTouched = Vec_IntAlloc( 1000 ); + Abc_Obj_t * pObj; + int i, r, f, nChanges = 0; + for ( r = 0; r < nRounds; r++ ) + { + int nChangesThis = 0; + Emap_ManComputeRefs( pNtk, pMaps, pLib, pRefs ); + Emap_ManComputeRequiredTarget( pNtk, pMaps, pLib, pRequired, pRefs, DelayTarget ); + Abc_NtkForEachNodeReverse( pNtk, pObj, i ) + { + if ( !Abc_AigNodeIsAnd(pObj) ) + continue; + for ( f = 0; f < 2; f++ ) + nChangesThis += Emap_NodeImproveExactPhase( pNtk, pMaps, pLib, pRefs, pRequired, vTouched, Abc_ObjId(pObj), f, fRelaxArrival ); + Emap_NodeRefreshInverterPhase( &pMaps[Abc_ObjId(pObj)], pLib, 0 ); + Emap_NodeRefreshInverterPhase( &pMaps[Abc_ObjId(pObj)], pLib, 1 ); + if ( fDropPhase ) + { + nChangesThis += Emap_NodeDropPhaseExact( pNtk, pMaps, pLib, pRefs, pRequired, Abc_ObjId(pObj), 0 ); + nChangesThis += Emap_NodeDropPhaseExact( pNtk, pMaps, pLib, pRefs, pRequired, Abc_ObjId(pObj), 1 ); + } + if ( pTuples && getenv("ABC_EMAP_LOCAL_MOG_EXACT") ) + nChangesThis += Emap_NodeMatchMogExactLocal( pNtk, pMaps, pLib, pTuples, pRefs, pRequired, vTouched, Abc_ObjId(pObj) ); + Emap_RequiredPropagateUsedObj( pNtk, pMaps, pLib, pRequired, pRefs, Abc_ObjId(pObj) ); + } + nChanges += nChangesThis; + if ( nChangesThis == 0 ) + break; + } + Vec_IntFree( vTouched ); + return nChanges; +} + +static int Emap_PackEntryCompare( void const * p0, void const * p1 ) +{ + Emap_PackEntry_t const * pEntry0 = (Emap_PackEntry_t const *)p0; + Emap_PackEntry_t const * pEntry1 = (Emap_PackEntry_t const *)p1; + int i; + if ( pEntry0->nLeaves != pEntry1->nLeaves ) + return pEntry0->nLeaves - pEntry1->nLeaves; + if ( pEntry0->Truth < pEntry1->Truth ) + return -1; + if ( pEntry0->Truth > pEntry1->Truth ) + return 1; + for ( i = 0; i < pEntry0->nLeaves; i++ ) + if ( pEntry0->Leaves[i] != pEntry1->Leaves[i] ) + return pEntry0->Leaves[i] - pEntry1->Leaves[i]; + return 0; +} + +static int Emap_PackEntryFindFirst( Emap_PackEntry_t * pEntries, int nEntries, Emap_Cut_t * pCut, word Truth ) +{ + Emap_PackEntry_t Key; + int Beg = 0, End = nEntries, i; + memset( &Key, 0, sizeof(Key) ); + Key.nLeaves = pCut->nLeaves; + Key.Truth = Truth; + for ( i = 0; i < pCut->nLeaves; i++ ) + Key.Leaves[i] = pCut->Leaves[i]; + while ( Beg < End ) + { + int Mid = (Beg + End) >> 1; + if ( Emap_PackEntryCompare( &pEntries[Mid], &Key ) < 0 ) + Beg = Mid + 1; + else + End = Mid; + } + if ( Beg == nEntries || Emap_PackEntryCompare( &pEntries[Beg], &Key ) != 0 ) + return -1; + return Beg; +} + +static void Emap_TuplesFree( Emap_Tuples_t * p ) +{ + ABC_FREE( p->pArray ); + ABC_FREE( p->pFirstHigh ); + ABC_FREE( p->pFirstLow ); +} + +static void Emap_TuplesAdd( Emap_Tuples_t * p, int Obj0, int Phase0, int Cut0, int Obj1, int Phase1, int Cut1, int Mog, int fSwap ) +{ + Emap_Tuple_t * pTuple; + int High = Abc_MaxInt( Obj0, Obj1 ); + int Low = Abc_MinInt( Obj0, Obj1 ); + if ( p->nSize == p->nCap ) + { + p->nCap = p->nCap ? 2 * p->nCap : 1024; + p->pArray = ABC_REALLOC( Emap_Tuple_t, p->pArray, p->nCap ); + } + pTuple = &p->pArray[p->nSize]; + pTuple->Obj0 = Obj0; + pTuple->Phase0 = Phase0; + pTuple->Cut0 = Cut0; + pTuple->Obj1 = Obj1; + pTuple->Phase1 = Phase1; + pTuple->Cut1 = Cut1; + pTuple->Mog = Mog; + pTuple->fSwap = fSwap; + pTuple->NextHigh = p->pFirstHigh[High]; + pTuple->NextLow = p->pFirstLow[Low]; + p->pFirstHigh[High] = p->nSize; + p->pFirstLow[Low] = p->nSize++; +} + +static void Emap_ManComputeMogTuples( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, Emap_Tuples_t * pTuples ) +{ + Emap_PackEntry_t * pEntries; + int * pAssign; + Vec_Int_t * vMffcTouched = NULL; + int * pDecs = NULL; + char * pLeafMarks = NULL; + Abc_Obj_t * pObj; + int i, k, f, nEntries = 0, nGroups = 0, fUseMffc = getenv("ABC_EMAP_MFFC_TUPLES") != NULL; + memset( pTuples, 0, sizeof(Emap_Tuples_t) ); + if ( pLib->nMogs == 0 ) + return; + pTuples->pFirstHigh = ABC_ALLOC( int, Abc_NtkObjNumMax(pNtk) ); + pTuples->pFirstLow = ABC_ALLOC( int, Abc_NtkObjNumMax(pNtk) ); + for ( i = 0; i < Abc_NtkObjNumMax(pNtk); i++ ) + { + pTuples->pFirstHigh[i] = -1; + pTuples->pFirstLow[i] = -1; + } + pEntries = ABC_ALLOC( Emap_PackEntry_t, 2 * EMAP_CUT_MAX * Abc_NtkObjNumMax(pNtk) ); + pAssign = ABC_ALLOC( int, Abc_NtkObjNumMax(pNtk) ); + for ( i = 0; i < Abc_NtkObjNumMax(pNtk); i++ ) + pAssign[i] = -1; + if ( fUseMffc ) + { + vMffcTouched = Vec_IntAlloc( 100 ); + pDecs = ABC_CALLOC( int, Abc_NtkObjNumMax(pNtk) ); + pLeafMarks = ABC_CALLOC( char, Abc_NtkObjNumMax(pNtk) ); + } + Abc_AigForEachAnd( pNtk, pObj, i ) + { + for ( f = 0; f < 2; f++ ) + { + Emap_Obj_t * pMap = &pMaps[Abc_ObjId(pObj)]; + int c; + for ( c = 0; c < pMap->nCuts; c++ ) + { + Emap_Cut_t * pCut = &pMap->Cuts[c]; + word Truth = f ? (pCut->Truth ^ Emap_TruthMask(pCut->nLeaves)) : pCut->Truth; + if ( pCut->nLeaves < 2 || pCut->nLeaves > 3 ) + continue; + pEntries[nEntries].ObjId = Abc_ObjId(pObj); + pEntries[nEntries].Phase = f; + pEntries[nEntries].Cut = c; + pEntries[nEntries].nLeaves = pCut->nLeaves; + pEntries[nEntries].Truth = Truth; + for ( k = 0; k < pCut->nLeaves; k++ ) + pEntries[nEntries].Leaves[k] = pCut->Leaves[k]; + nEntries++; + } + } + } + qsort( pEntries, nEntries, sizeof(Emap_PackEntry_t), Emap_PackEntryCompare ); + for ( i = nEntries - 1; i >= 0; i-- ) + { + Emap_PackEntry_t * pEntry0 = &pEntries[i]; + Emap_Cut_t * pCut0 = &pMaps[pEntry0->ObjId].Cuts[pEntry0->Cut]; + for ( k = 0; k < pLib->nMogs; k++ ) + { + Emap_Mog_t * pMog = &pLib->pMogs[k]; + int s; + if ( pMog->nPins != pCut0->nLeaves ) + continue; + for ( s = 0; s < 2; s++ ) + { + word Truth0 = s ? pMog->Truth1 : pMog->Truth0; + word Truth1 = s ? pMog->Truth0 : pMog->Truth1; + int Beg; + if ( Truth0 != pEntry0->Truth ) + continue; + Beg = Emap_PackEntryFindFirst( pEntries, nEntries, pCut0, Truth1 ); + if ( Beg < 0 ) + continue; + for ( ; Beg < nEntries && pEntries[Beg].nLeaves == pCut0->nLeaves && pEntries[Beg].Truth == Truth1; Beg++ ) + { + Emap_PackEntry_t * pEntry1 = &pEntries[Beg]; + int m, fSameLeaves = 1; + for ( m = 0; m < pCut0->nLeaves; m++ ) + if ( pEntry1->Leaves[m] != pCut0->Leaves[m] ) + fSameLeaves = 0; + if ( !fSameLeaves ) + break; + if ( pEntry1->ObjId == pEntry0->ObjId ) + continue; + if ( Emap_ObjPairHasDirectDanglingRelation( pNtk, pEntry0->ObjId, pEntry1->ObjId ) ) + continue; + if ( fUseMffc ? Emap_ObjPairHasMffcDanglingRelation( pNtk, pEntry0->ObjId, pEntry1->ObjId, pCut0, pLeafMarks, pDecs, vMffcTouched ) : Emap_ObjPairHasTfiRelation( pNtk, pEntry0->ObjId, pEntry1->ObjId ) ) + continue; + if ( pAssign[pEntry0->ObjId] == -1 && pAssign[pEntry1->ObjId] == -1 ) + pAssign[pEntry0->ObjId] = pAssign[pEntry1->ObjId] = nGroups++; + else if ( pAssign[pEntry0->ObjId] != pAssign[pEntry1->ObjId] || pAssign[pEntry0->ObjId] == -1 ) + continue; + Emap_TuplesAdd( pTuples, pEntry0->ObjId, pEntry0->Phase, pEntry0->Cut, pEntry1->ObjId, pEntry1->Phase, pEntry1->Cut, k, s ); + } + } + } + } + if ( getenv("ABC_EMAP_DEBUG_MOG") ) + printf( "ABC emap MOG tuple setup: tuples=%d groups=%d mode=%s\n", pTuples->nSize, nGroups, fUseMffc ? "mffc" : "strict" ); + ABC_FREE( pLeafMarks ); + ABC_FREE( pDecs ); + if ( vMffcTouched ) + Vec_IntFree( vMffcTouched ); + ABC_FREE( pAssign ); + ABC_FREE( pEntries ); +} + +static int Emap_ObjPairHasDirectDanglingRelation( Abc_Ntk_t * pNtk, int ObjId0, int ObjId1 ) +{ + Abc_Obj_t * pObj0 = Abc_NtkObj( pNtk, ObjId0 ); + Abc_Obj_t * pObj1 = Abc_NtkObj( pNtk, ObjId1 ); + if ( !Abc_ObjIsPi(pObj0) && !Abc_AigNodeIsConst(pObj0) && (Abc_ObjFaninId0(pObj0) == ObjId1 || Abc_ObjFaninId1(pObj0) == ObjId1) && Abc_ObjFanoutNum(pObj1) == 1 ) + return 1; + if ( !Abc_ObjIsPi(pObj1) && !Abc_AigNodeIsConst(pObj1) && (Abc_ObjFaninId0(pObj1) == ObjId0 || Abc_ObjFaninId1(pObj1) == ObjId0) && Abc_ObjFanoutNum(pObj0) == 1 ) + return 1; + return 0; +} + +static void Emap_MffcDeref_rec( Abc_Obj_t * pObj, char * pLeafMarks, int * pDecs, Vec_Int_t * vTouched ) +{ + Abc_Obj_t * pFanin; + int i, ObjId; + if ( Abc_ObjIsPi(pObj) || Abc_AigNodeIsConst(pObj) || pLeafMarks[Abc_ObjId(pObj)] ) + return; + Abc_ObjForEachFanin( pObj, pFanin, i ) + { + ObjId = Abc_ObjId(pFanin); + if ( pLeafMarks[ObjId] ) + continue; + if ( pDecs[ObjId]++ == 0 ) + Vec_IntPush( vTouched, ObjId ); + if ( pDecs[ObjId] == Abc_ObjFanoutNum(pFanin) ) + Emap_MffcDeref_rec( pFanin, pLeafMarks, pDecs, vTouched ); + } +} + +static int Emap_ObjPairHasMffcDanglingRelation( Abc_Ntk_t * pNtk, int ObjId0, int ObjId1, Emap_Cut_t * pCut, char * pLeafMarks, int * pDecs, Vec_Int_t * vTouched ) +{ + int Low = Abc_MinInt( ObjId0, ObjId1 ); + int High = Abc_MaxInt( ObjId0, ObjId1 ); + Abc_Obj_t * pLow = Abc_NtkObj( pNtk, Low ); + Abc_Obj_t * pHigh = Abc_NtkObj( pNtk, High ); + int i, Entry, fDangling; + assert( Vec_IntSize(vTouched) == 0 ); + if ( !Abc_ObjIsPi(pHigh) && !Abc_AigNodeIsConst(pHigh) && (Abc_ObjFaninId0(pHigh) == Low || Abc_ObjFaninId1(pHigh) == Low) && Abc_ObjFanoutNum(pLow) == 1 ) + return 1; + for ( i = 0; i < pCut->nLeaves; i++ ) + pLeafMarks[pCut->Leaves[i]] = 1; + Emap_MffcDeref_rec( pHigh, pLeafMarks, pDecs, vTouched ); + fDangling = Abc_ObjFanoutNum(pLow) - pDecs[Low] <= 0; + for ( i = 0; i < pCut->nLeaves; i++ ) + pLeafMarks[pCut->Leaves[i]] = 0; + Vec_IntForEachEntry( vTouched, Entry, i ) + pDecs[Entry] = 0; + Vec_IntClear( vTouched ); + return fDangling; +} + +static int Emap_ObjIsInTfi_rec( Abc_Obj_t * pRoot, int TargetId ) +{ + if ( Abc_ObjId(pRoot) == TargetId ) + return 1; + if ( Abc_ObjIsPi(pRoot) || Abc_AigNodeIsConst(pRoot) ) + return 0; + if ( Abc_NodeIsTravIdCurrent(pRoot) ) + return 0; + Abc_NodeSetTravIdCurrent(pRoot); + return Emap_ObjIsInTfi_rec( Abc_ObjFanin0(pRoot), TargetId ) || Emap_ObjIsInTfi_rec( Abc_ObjFanin1(pRoot), TargetId ); +} + +static int Emap_ObjPairHasTfiRelation( Abc_Ntk_t * pNtk, int ObjId0, int ObjId1 ) +{ + Abc_NtkIncrementTravId( pNtk ); + if ( Emap_ObjIsInTfi_rec( Abc_NtkObj(pNtk, ObjId0), ObjId1 ) ) + return 1; + Abc_NtkIncrementTravId( pNtk ); + return Emap_ObjIsInTfi_rec( Abc_NtkObj(pNtk, ObjId1), ObjId0 ); +} + +static double Emap_MogArrival( Emap_Obj_t * pMaps, Emap_Cut_t * pCut, Emap_Mog_t * pMog, int fSwap ); + +static void Emap_MogApply( Emap_Obj_t * pMaps, Emap_PackEntry_t * pEntry0, Emap_PackEntry_t * pEntry1, Emap_Mog_t * pMog, int fSwap ) +{ + Emap_Best_t * pBest0 = &pMaps[pEntry0->ObjId].Best[pEntry0->Phase]; + Emap_Best_t * pBest1 = &pMaps[pEntry1->ObjId].Best[pEntry1->Phase]; + Emap_Cut_t * pCut0 = &pMaps[pEntry0->ObjId].Cuts[pEntry0->Cut]; + Emap_Cut_t * pCut1 = &pMaps[pEntry1->ObjId].Cuts[pEntry1->Cut]; + int i; + pBest0->pGate = fSwap ? pMog->pGate1 : pMog->pGate0; + pBest1->pGate = fSwap ? pMog->pGate0 : pMog->pGate1; + pBest0->Cut = pEntry0->Cut; + pBest1->Cut = pEntry1->Cut; + pBest0->nPins = pBest1->nPins = pMog->nPins; + pBest0->TwinObj = pEntry1->ObjId; + pBest0->TwinPhase = pEntry1->Phase; + pBest1->TwinObj = pEntry0->ObjId; + pBest1->TwinPhase = pEntry0->Phase; + pBest0->fInv = pBest1->fInv = 0; + pBest0->Arr = Emap_MogArrival( pMaps, pCut0, pMog, fSwap ); + pBest1->Arr = Emap_MogArrival( pMaps, pCut1, pMog, !fSwap ); + pBest0->Flow = pBest1->Flow = pMog->Area; + for ( i = 0; i < pMog->nPins; i++ ) + { + pBest0->PinToLeaf[i] = pBest1->PinToLeaf[i] = pMog->PinToLeaf[i]; + pBest0->PinPhase[i] = pBest1->PinPhase[i] = pMog->PinPhase[i]; + } +} + +static double Emap_MogArrival( Emap_Obj_t * pMaps, Emap_Cut_t * pCut, Emap_Mog_t * pMog, int fSwap ) +{ + double Arr = 0; + int i; + for ( i = 0; i < pMog->nPins; i++ ) + { + Emap_Best_t * pLeafBest = &pMaps[pCut->Leaves[pMog->PinToLeaf[i]]].Best[pMog->PinPhase[i]]; + Arr = Abc_MaxDouble( Arr, pLeafBest->Arr + (fSwap ? pMog->Delay1[i] : pMog->Delay0[i]) ); + } + return Arr; +} + +static void Emap_MogSetOppositePhase( Emap_Obj_t * pMaps, Emap_Lib_t * pLib, int ObjId, int Phase, float Flow ) +{ + pMaps[ObjId].Best[!Phase] = pMaps[ObjId].Best[Phase]; + pMaps[ObjId].Best[!Phase].fInv = 1; + pMaps[ObjId].Best[!Phase].TwinObj = -1; + pMaps[ObjId].Best[!Phase].TwinPhase = -1; + pMaps[ObjId].Best[!Phase].Arr = pMaps[ObjId].Best[Phase].Arr + pLib->InvDelay; + pMaps[ObjId].Best[!Phase].Flow = Flow + pLib->InvArea; +} + +static int Emap_NodeMatchMogArea( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, Emap_Tuples_t * pTuples, int * pRefs, double * pRequired, int ObjId, int fCheckRequired ) +{ + int iTuple, iBestTuple = -1; + float BestFlow = (float)EMAP_DOUBLE_LARGE, BestScore = (float)EMAP_DOUBLE_LARGE; + if ( pTuples == NULL || pTuples->pFirstHigh == NULL ) + return 0; + pTuples->nAreaCalls++; + for ( iTuple = pTuples->pFirstHigh[ObjId]; iTuple >= 0; iTuple = pTuples->pArray[iTuple].NextHigh ) + { + Emap_Tuple_t * pTuple = &pTuples->pArray[iTuple]; + Emap_Mog_t * pMog = &pLib->pMogs[pTuple->Mog]; + Emap_Cut_t * pCut0 = &pMaps[pTuple->Obj0].Cuts[pTuple->Cut0]; + Emap_Cut_t * pCut1 = &pMaps[pTuple->Obj1].Cuts[pTuple->Cut1]; + Emap_Best_t * pBest0 = &pMaps[pTuple->Obj0].Best[pTuple->Phase0]; + Emap_Best_t * pBest1 = &pMaps[pTuple->Obj1].Best[pTuple->Phase1]; + double Arr0, Arr1; + float OldFlow = 0, NewFlow, NewScore, LeafFlow = 0, CombinedRefs = 0; + int fRespectsRequired = 1; + int i; + pTuples->nAreaCandidates++; + if ( pBest0->TwinObj >= 0 || pBest1->TwinObj >= 0 ) + { + pTuples->nAreaRejectTwin++; + continue; + } + Arr0 = Emap_MogArrival( pMaps, pCut0, pMog, pTuple->fSwap ); + Arr1 = Emap_MogArrival( pMaps, pCut1, pMog, !pTuple->fSwap ); + if ( fCheckRequired ) + { + if ( Arr0 > pRequired[2 * pTuple->Obj0 + pTuple->Phase0] + 0.001 || Arr1 > pRequired[2 * pTuple->Obj1 + pTuple->Phase1] + 0.001 ) + { + if ( getenv("ABC_EMAP_DEBUG_MOG") && pTuples->nAreaSamples < 8 ) + { + printf( "ABC emap MOG req sample %d: roots=(%d,%d) phases=(%d,%d) arr=(%.2f,%.2f) req=(%.2f,%.2f) invreq=(%.2f,%.2f)\n", + pTuples->nAreaSamples, pTuple->Obj0, pTuple->Obj1, pTuple->Phase0, pTuple->Phase1, Arr0, Arr1, + pRequired[2 * pTuple->Obj0 + pTuple->Phase0], pRequired[2 * pTuple->Obj1 + pTuple->Phase1], + pRequired[2 * pTuple->Obj0 + !pTuple->Phase0], pRequired[2 * pTuple->Obj1 + !pTuple->Phase1] ); + pTuples->nAreaSamples++; + } + pTuples->nAreaRejectRequired++; + continue; + } + if ( (pRefs == NULL || pRefs[2 * pTuple->Obj0 + !pTuple->Phase0] > 0) && Arr0 + pLib->InvDelay > pRequired[2 * pTuple->Obj0 + !pTuple->Phase0] + 0.001 ) + { + if ( getenv("ABC_EMAP_DEBUG_MOG") && pTuples->nAreaSamples < 8 ) + { + printf( "ABC emap MOG invreq sample %d: roots=(%d,%d) phases=(%d,%d) arr=(%.2f,%.2f) req=(%.2f,%.2f) invreq=(%.2f,%.2f)\n", + pTuples->nAreaSamples, pTuple->Obj0, pTuple->Obj1, pTuple->Phase0, pTuple->Phase1, Arr0, Arr1, + pRequired[2 * pTuple->Obj0 + pTuple->Phase0], pRequired[2 * pTuple->Obj1 + pTuple->Phase1], + pRequired[2 * pTuple->Obj0 + !pTuple->Phase0], pRequired[2 * pTuple->Obj1 + !pTuple->Phase1] ); + pTuples->nAreaSamples++; + } + pTuples->nAreaRejectRequired++; + continue; + } + if ( (pRefs == NULL || pRefs[2 * pTuple->Obj1 + !pTuple->Phase1] > 0) && Arr1 + pLib->InvDelay > pRequired[2 * pTuple->Obj1 + !pTuple->Phase1] + 0.001 ) + { + pTuples->nAreaRejectRequired++; + continue; + } + } + if ( pRequired != NULL ) + { + if ( pBest0->Arr > pRequired[2 * pTuple->Obj0 + pTuple->Phase0] + 0.001 || pBest1->Arr > pRequired[2 * pTuple->Obj1 + pTuple->Phase1] + 0.001 ) + fRespectsRequired = 0; + if ( (pRefs == NULL || pRefs[2 * pTuple->Obj0 + !pTuple->Phase0] > 0) && pBest0->Arr + pLib->InvDelay > pRequired[2 * pTuple->Obj0 + !pTuple->Phase0] + 0.001 ) + fRespectsRequired = 0; + if ( (pRefs == NULL || pRefs[2 * pTuple->Obj1 + !pTuple->Phase1] > 0) && pBest1->Arr + pLib->InvDelay > pRequired[2 * pTuple->Obj1 + !pTuple->Phase1] + 0.001 ) + fRespectsRequired = 0; + } + { + float Est0 = (float)Abc_MaxInt( 1, pRefs ? pRefs[2 * pTuple->Obj0 + pTuple->Phase0] : Abc_ObjFanoutNum(Abc_NtkObj(pNtk, pTuple->Obj0)) ); + float Est1 = (float)Abc_MaxInt( 1, pRefs ? pRefs[2 * pTuple->Obj1 + pTuple->Phase1] : Abc_ObjFanoutNum(Abc_NtkObj(pNtk, pTuple->Obj1)) ); + OldFlow = pBest0->Flow / Est0 + pBest1->Flow / Est1; + CombinedRefs = Est0 + Est1; + } + for ( i = 0; i < pMog->nPins; i++ ) + { + int Leaf = pCut0->Leaves[pMog->PinToLeaf[i]]; + int LeafPhase = pMog->PinPhase[i]; + float Div = (float)Abc_MaxInt( 1, pRefs ? pRefs[2 * Leaf + LeafPhase] : Abc_ObjFanoutNum(Abc_NtkObj(pNtk, Leaf)) ); + LeafFlow += pMaps[Leaf].Best[LeafPhase].Flow / Div; + } + NewFlow = (pMog->Area + 2 * LeafFlow) / Abc_MaxFloat( 1.0f, CombinedRefs ); + NewScore = NewFlow; + if ( pRefs != NULL ) + { + if ( pRefs[2 * pTuple->Obj0 + !pTuple->Phase0] > 0 ) + NewScore += pLib->InvArea / Abc_MaxFloat( 1.0f, CombinedRefs ); + if ( pRefs[2 * pTuple->Obj1 + !pTuple->Phase1] > 0 ) + NewScore += pLib->InvArea / Abc_MaxFloat( 1.0f, CombinedRefs ); + } + if ( fRespectsRequired && NewFlow > OldFlow - 0.001 ) + { + pTuples->nAreaRejectFlow++; + continue; + } + if ( NewScore < BestScore - 0.001 || (NewScore < BestScore + 0.001 && NewFlow < BestFlow - 0.001) ) + { + iBestTuple = iTuple; + BestFlow = NewFlow; + BestScore = NewScore; + } + } + if ( iBestTuple < 0 ) + return 0; + { + Emap_Tuple_t * pTuple = &pTuples->pArray[iBestTuple]; + Emap_Mog_t * pMog = &pLib->pMogs[pTuple->Mog]; + Emap_PackEntry_t Entry0, Entry1; + memset( &Entry0, 0, sizeof(Entry0) ); + memset( &Entry1, 0, sizeof(Entry1) ); + Entry0.ObjId = pTuple->Obj0; + Entry0.Phase = pTuple->Phase0; + Entry0.Cut = pTuple->Cut0; + Entry1.ObjId = pTuple->Obj1; + Entry1.Phase = pTuple->Phase1; + Entry1.Cut = pTuple->Cut1; + Emap_MogApply( pMaps, &Entry0, &Entry1, pMog, pTuple->fSwap ); + pMaps[pTuple->Obj0].Best[pTuple->Phase0].Flow = BestFlow; + pMaps[pTuple->Obj1].Best[pTuple->Phase1].Flow = BestFlow; + Emap_MogSetOppositePhase( pMaps, pLib, pTuple->Obj0, pTuple->Phase0, BestFlow ); + Emap_MogSetOppositePhase( pMaps, pLib, pTuple->Obj1, pTuple->Phase1, BestFlow ); + pTuples->nAreaAccepts++; + return 1; + } +} + +static int Emap_ManPackMogs( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, double * pRequired, int * pRefs ) +{ + Emap_PackEntry_t * pEntries; + Abc_Obj_t * pObj; + int i, k, f, nEntries = 0, nPacked = 0; + if ( pLib->nMogs == 0 ) + return 0; + Emap_ManComputeRefs( pNtk, pMaps, pLib, pRefs ); + pEntries = ABC_ALLOC( Emap_PackEntry_t, 2 * EMAP_CUT_MAX * Abc_NtkObjNumMax(pNtk) ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + for ( f = 0; f < 2; f++ ) + { + Emap_Best_t * pBest = &pMaps[Abc_ObjId(pObj)].Best[f]; + Emap_Obj_t * pMap = &pMaps[Abc_ObjId(pObj)]; + int c; + if ( pRefs[2 * Abc_ObjId(pObj) + f] == 0 || pBest->TwinObj >= 0 ) + continue; + for ( c = 0; c < pMap->nCuts; c++ ) + { + Emap_Cut_t * pCut = &pMap->Cuts[c]; + word Truth = f ? (pCut->Truth ^ Emap_TruthMask(pCut->nLeaves)) : pCut->Truth; + if ( pCut->nLeaves < 2 ) + continue; + pEntries[nEntries].ObjId = Abc_ObjId(pObj); + pEntries[nEntries].Phase = f; + pEntries[nEntries].Cut = c; + pEntries[nEntries].nLeaves = pCut->nLeaves; + pEntries[nEntries].Truth = Truth; + for ( k = 0; k < pCut->nLeaves; k++ ) + pEntries[nEntries].Leaves[k] = pCut->Leaves[k]; + nEntries++; + } + } + } + qsort( pEntries, nEntries, sizeof(Emap_PackEntry_t), Emap_PackEntryCompare ); + for ( i = 0; i < nEntries; i++ ) + { + Emap_PackEntry_t * pEntry0 = &pEntries[i]; + Emap_Best_t * pBest0 = &pMaps[pEntry0->ObjId].Best[pEntry0->Phase]; + Emap_Cut_t * pCut0; + if ( pBest0->TwinObj >= 0 ) + continue; + pCut0 = &pMaps[pEntry0->ObjId].Cuts[pEntry0->Cut]; + for ( k = 0; k < pLib->nMogs; k++ ) + { + Emap_Mog_t * pMog = &pLib->pMogs[k]; + int s; + if ( pMog->nPins != pCut0->nLeaves ) + continue; + for ( s = 0; s < 2; s++ ) + { + word Truth0 = s ? pMog->Truth1 : pMog->Truth0; + word Truth1 = s ? pMog->Truth0 : pMog->Truth1; + int Beg; + if ( Truth0 != pEntry0->Truth ) + continue; + if ( Emap_MogArrival( pMaps, pCut0, pMog, s ) > pRequired[2 * pEntry0->ObjId + pEntry0->Phase] + 0.001 ) + continue; + Beg = Emap_PackEntryFindFirst( pEntries, nEntries, pCut0, Truth1 ); + if ( Beg < 0 ) + continue; + for ( ; Beg < nEntries && pEntries[Beg].nLeaves == pCut0->nLeaves && pEntries[Beg].Truth == Truth1; Beg++ ) + { + Emap_PackEntry_t * pEntry1 = &pEntries[Beg]; + Emap_Best_t * pBest1 = &pMaps[pEntry1->ObjId].Best[pEntry1->Phase]; + Emap_Cut_t * pCut1 = &pMaps[pEntry1->ObjId].Cuts[pEntry1->Cut]; + int m, fSameLeaves = 1; + for ( m = 0; m < pCut0->nLeaves; m++ ) + if ( pEntry1->Leaves[m] != pCut0->Leaves[m] ) + fSameLeaves = 0; + if ( !fSameLeaves ) + break; + if ( pEntry1->ObjId == pEntry0->ObjId || pBest1->TwinObj >= 0 ) + continue; + if ( Emap_ObjPairHasDirectDanglingRelation( pNtk, pEntry0->ObjId, pEntry1->ObjId ) ) + continue; + if ( Emap_MogArrival( pMaps, pCut1, pMog, !s ) > pRequired[2 * pEntry1->ObjId + pEntry1->Phase] + 0.001 ) + continue; + Emap_MogApply( pMaps, pEntry0, pEntry1, pMog, s ); + nPacked++; + break; + } + if ( pBest0->TwinObj >= 0 ) + break; + } + if ( pBest0->TwinObj >= 0 ) + break; + } + } + ABC_FREE( pEntries ); + return nPacked; +} + +static int Emap_ManRecoverMogsExact( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, double * pRequired, int * pRefs ) +{ + Emap_PackEntry_t * pEntries; + Vec_Int_t * vTouched; + Abc_Obj_t * pObj; + int i, k, f, nEntries = 0, nApplied = 0; + if ( pLib->nMogs == 0 ) + return 0; + Emap_ManComputeRefs( pNtk, pMaps, pLib, pRefs ); + pEntries = ABC_ALLOC( Emap_PackEntry_t, 2 * EMAP_CUT_MAX * Abc_NtkObjNumMax(pNtk) ); + vTouched = Vec_IntAlloc( 1000 ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + for ( f = 0; f < 2; f++ ) + { + Emap_Obj_t * pMap = &pMaps[Abc_ObjId(pObj)]; + int c; + if ( pRefs[2 * Abc_ObjId(pObj) + f] == 0 || pMap->Best[f].TwinObj >= 0 ) + continue; + for ( c = 0; c < pMap->nCuts; c++ ) + { + Emap_Cut_t * pCut = &pMap->Cuts[c]; + word Truth = f ? (pCut->Truth ^ Emap_TruthMask(pCut->nLeaves)) : pCut->Truth; + if ( pCut->nLeaves < 2 ) + continue; + pEntries[nEntries].ObjId = Abc_ObjId(pObj); + pEntries[nEntries].Phase = f; + pEntries[nEntries].Cut = c; + pEntries[nEntries].nLeaves = pCut->nLeaves; + pEntries[nEntries].Truth = Truth; + for ( k = 0; k < pCut->nLeaves; k++ ) + pEntries[nEntries].Leaves[k] = pCut->Leaves[k]; + nEntries++; + } + } + } + qsort( pEntries, nEntries, sizeof(Emap_PackEntry_t), Emap_PackEntryCompare ); + for ( i = 0; i < nEntries; i++ ) + { + Emap_PackEntry_t * pEntry0 = &pEntries[i]; + Emap_Best_t * pBest0 = &pMaps[pEntry0->ObjId].Best[pEntry0->Phase]; + Emap_Cut_t * pCut0; + if ( pRefs[2 * pEntry0->ObjId + pEntry0->Phase] == 0 || pBest0->TwinObj >= 0 ) + continue; + pCut0 = &pMaps[pEntry0->ObjId].Cuts[pEntry0->Cut]; + for ( k = 0; k < pLib->nMogs; k++ ) + { + Emap_Mog_t * pMog = &pLib->pMogs[k]; + int s; + if ( pMog->nPins != pCut0->nLeaves ) + continue; + for ( s = 0; s < 2; s++ ) + { + word Truth0 = s ? pMog->Truth1 : pMog->Truth0; + word Truth1 = s ? pMog->Truth0 : pMog->Truth1; + int Beg; + if ( Truth0 != pEntry0->Truth ) + continue; + if ( Emap_MogArrival( pMaps, pCut0, pMog, s ) > pRequired[2 * pEntry0->ObjId + pEntry0->Phase] + 0.001 ) + continue; + Beg = Emap_PackEntryFindFirst( pEntries, nEntries, pCut0, Truth1 ); + if ( Beg < 0 ) + continue; + for ( ; Beg < nEntries && pEntries[Beg].nLeaves == pCut0->nLeaves && pEntries[Beg].Truth == Truth1; Beg++ ) + { + Emap_PackEntry_t * pEntry1 = &pEntries[Beg]; + Emap_Best_t * pBest1 = &pMaps[pEntry1->ObjId].Best[pEntry1->Phase]; + Emap_Best_t OldBest0, OldBest1; + float AreaOld, AreaNew; + int m, Entry, t, fSameLeaves = 1; + for ( m = 0; m < pCut0->nLeaves; m++ ) + if ( pEntry1->Leaves[m] != pCut0->Leaves[m] ) + fSameLeaves = 0; + if ( !fSameLeaves ) + break; + if ( pEntry1->ObjId == pEntry0->ObjId || pRefs[2 * pEntry1->ObjId + pEntry1->Phase] == 0 || pBest1->TwinObj >= 0 ) + continue; + if ( Emap_ObjPairHasDirectDanglingRelation( pNtk, pEntry0->ObjId, pEntry1->ObjId ) ) + continue; + if ( Emap_ObjPairHasTfiRelation( pNtk, pEntry0->ObjId, pEntry1->ObjId ) ) + continue; + if ( Emap_MogArrival( pMaps, &pMaps[pEntry1->ObjId].Cuts[pEntry1->Cut], pMog, !s ) > pRequired[2 * pEntry1->ObjId + pEntry1->Phase] + 0.001 ) + continue; + + OldBest0 = *pBest0; + OldBest1 = *pBest1; + AreaOld = Emap_CutDerefLeaves_rec( pNtk, pMaps, pLib, pRefs, pEntry0->ObjId, pEntry0->Phase ); + AreaOld += Emap_CutDerefLeaves_rec( pNtk, pMaps, pLib, pRefs, pEntry1->ObjId, pEntry1->Phase ); + Emap_MogApply( pMaps, pEntry0, pEntry1, pMog, s ); + AreaNew = pMog->Area; + Vec_IntClear( vTouched ); + AreaNew += Emap_CutRefOnlyLeavesVisit_rec( pNtk, pMaps, pLib, pRefs, vTouched, pEntry0->ObjId, pEntry0->Phase ); + AreaNew += Emap_CutRefOnlyLeavesVisit_rec( pNtk, pMaps, pLib, pRefs, vTouched, pEntry1->ObjId, pEntry1->Phase ); + Vec_IntForEachEntryReverse( vTouched, Entry, t ) + pRefs[Entry]--; + if ( AreaNew < AreaOld - 0.001 ) + { + Emap_CutRefOnlyLeaves_rec( pNtk, pMaps, pLib, pRefs, pEntry0->ObjId, pEntry0->Phase ); + Emap_CutRefOnlyLeaves_rec( pNtk, pMaps, pLib, pRefs, pEntry1->ObjId, pEntry1->Phase ); + nApplied++; + break; + } + *pBest0 = OldBest0; + *pBest1 = OldBest1; + Emap_CutRefLeaves_rec( pNtk, pMaps, pLib, pRefs, pEntry0->ObjId, pEntry0->Phase ); + Emap_CutRefLeaves_rec( pNtk, pMaps, pLib, pRefs, pEntry1->ObjId, pEntry1->Phase ); + } + if ( pBest0->TwinObj >= 0 ) + break; + } + if ( pBest0->TwinObj >= 0 ) + break; + } + } + Vec_IntFree( vTouched ); + ABC_FREE( pEntries ); + return nApplied; +} + +static int Emap_ManRecoverMogsExactMffc( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, Mio_Library_t * pMio, double * pRequired, int * pRefs, double DelayLimit, float * pAreaBest, double * pDelayBest ) +{ + Emap_PackEntry_t * pEntries; + Vec_Int_t * vMffcTouched; + int * pDecs; + char * pLeafMarks; + Abc_Obj_t * pObj; + float AreaBest = *pAreaBest; + double DelayBest = *pDelayBest; + int i, k, f, nEntries = 0, nApplied = 0, nTried = 0; + if ( pLib->nMogs == 0 ) + return 0; + Emap_ManComputeRefs( pNtk, pMaps, pLib, pRefs ); + pEntries = ABC_ALLOC( Emap_PackEntry_t, 2 * EMAP_CUT_MAX * Abc_NtkObjNumMax(pNtk) ); + vMffcTouched = Vec_IntAlloc( 100 ); + pDecs = ABC_CALLOC( int, Abc_NtkObjNumMax(pNtk) ); + pLeafMarks = ABC_CALLOC( char, Abc_NtkObjNumMax(pNtk) ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + for ( f = 0; f < 2; f++ ) + { + Emap_Obj_t * pMap = &pMaps[Abc_ObjId(pObj)]; + int c; + if ( pRefs[2 * Abc_ObjId(pObj)] + pRefs[2 * Abc_ObjId(pObj) + 1] == 0 || pMap->Best[0].TwinObj >= 0 || pMap->Best[1].TwinObj >= 0 ) + continue; + for ( c = 0; c < pMap->nCuts; c++ ) + { + Emap_Cut_t * pCut = &pMap->Cuts[c]; + word Truth = f ? (pCut->Truth ^ Emap_TruthMask(pCut->nLeaves)) : pCut->Truth; + if ( pCut->nLeaves < 2 || pCut->nLeaves > 3 ) + continue; + pEntries[nEntries].ObjId = Abc_ObjId(pObj); + pEntries[nEntries].Phase = f; + pEntries[nEntries].Cut = c; + pEntries[nEntries].nLeaves = pCut->nLeaves; + pEntries[nEntries].Truth = Truth; + for ( k = 0; k < pCut->nLeaves; k++ ) + pEntries[nEntries].Leaves[k] = pCut->Leaves[k]; + nEntries++; + } + } + } + qsort( pEntries, nEntries, sizeof(Emap_PackEntry_t), Emap_PackEntryCompare ); + for ( i = 0; i < nEntries; i++ ) + { + Emap_PackEntry_t * pEntry0 = &pEntries[i]; + Emap_Obj_t * pMap0 = &pMaps[pEntry0->ObjId]; + Emap_Cut_t * pCut0; + if ( pRefs[2 * pEntry0->ObjId] + pRefs[2 * pEntry0->ObjId + 1] == 0 || pMap0->Best[0].TwinObj >= 0 || pMap0->Best[1].TwinObj >= 0 ) + continue; + pCut0 = &pMaps[pEntry0->ObjId].Cuts[pEntry0->Cut]; + for ( k = 0; k < pLib->nMogs; k++ ) + { + Emap_Mog_t * pMog = &pLib->pMogs[k]; + int s; + if ( pMog->nPins != pCut0->nLeaves ) + continue; + for ( s = 0; s < 2; s++ ) + { + word Truth0 = s ? pMog->Truth1 : pMog->Truth0; + word Truth1 = s ? pMog->Truth0 : pMog->Truth1; + int Beg; + if ( Truth0 != pEntry0->Truth ) + continue; + if ( Emap_MogArrival( pMaps, pCut0, pMog, s ) > pRequired[2 * pEntry0->ObjId + pEntry0->Phase] + 0.001 ) + continue; + Beg = Emap_PackEntryFindFirst( pEntries, nEntries, pCut0, Truth1 ); + if ( Beg < 0 ) + continue; + for ( ; Beg < nEntries && pEntries[Beg].nLeaves == pCut0->nLeaves && pEntries[Beg].Truth == Truth1; Beg++ ) + { + Emap_PackEntry_t * pEntry1 = &pEntries[Beg]; + Emap_Obj_t * pMap1 = &pMaps[pEntry1->ObjId]; + Emap_Best_t OldBest00, OldBest01, OldBest10, OldBest11; + float AreaCur; + double DelayCur; + int m, fSameLeaves = 1; + for ( m = 0; m < pCut0->nLeaves; m++ ) + if ( pEntry1->Leaves[m] != pCut0->Leaves[m] ) + fSameLeaves = 0; + if ( !fSameLeaves ) + break; + if ( pEntry1->ObjId == pEntry0->ObjId || pRefs[2 * pEntry1->ObjId] + pRefs[2 * pEntry1->ObjId + 1] == 0 || pMap1->Best[0].TwinObj >= 0 || pMap1->Best[1].TwinObj >= 0 ) + continue; + if ( Emap_ObjPairHasMffcDanglingRelation( pNtk, pEntry0->ObjId, pEntry1->ObjId, pCut0, pLeafMarks, pDecs, vMffcTouched ) ) + continue; + if ( Emap_MogArrival( pMaps, &pMaps[pEntry1->ObjId].Cuts[pEntry1->Cut], pMog, !s ) > pRequired[2 * pEntry1->ObjId + pEntry1->Phase] + 0.001 ) + continue; + OldBest00 = pMap0->Best[0]; + OldBest01 = pMap0->Best[1]; + OldBest10 = pMap1->Best[0]; + OldBest11 = pMap1->Best[1]; + Emap_MogApply( pMaps, pEntry0, pEntry1, pMog, s ); + Emap_MogSetOppositePhase( pMaps, pLib, pEntry0->ObjId, pEntry0->Phase, pMog->Area ); + Emap_MogSetOppositePhase( pMaps, pLib, pEntry1->ObjId, pEntry1->Phase, pMog->Area ); + AreaCur = Emap_ManComputeActualMappedStats( pNtk, pMaps, pLib, pMio, &DelayCur ); + nTried++; + if ( DelayCur <= DelayLimit + EMAP_DELAY_EPS && AreaCur < AreaBest - 0.001 ) + { + AreaBest = AreaCur; + DelayBest = DelayCur; + nApplied++; + Emap_ManComputeRefs( pNtk, pMaps, pLib, pRefs ); + break; + } + pMap0->Best[0] = OldBest00; + pMap0->Best[1] = OldBest01; + pMap1->Best[0] = OldBest10; + pMap1->Best[1] = OldBest11; + } + if ( pMap0->Best[0].TwinObj >= 0 || pMap0->Best[1].TwinObj >= 0 ) + break; + } + if ( pMap0->Best[0].TwinObj >= 0 || pMap0->Best[1].TwinObj >= 0 ) + break; + } + } + if ( getenv("ABC_EMAP_DEBUG_MOG") ) + printf( "ABC emap MOG MFFC-exact trial: entries=%d tried=%d applied=%d area=%.2f delay=%.2f\n", nEntries, nTried, nApplied, AreaBest, DelayBest ); + *pAreaBest = AreaBest; + *pDelayBest = DelayBest; + ABC_FREE( pLeafMarks ); + ABC_FREE( pDecs ); + Vec_IntFree( vMffcTouched ); + ABC_FREE( pEntries ); + return nApplied; +} + +static int Emap_ManRecoverMogsTimed( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, Mio_Library_t * pMio, int * pRefs, double DelayTarget, float * pAreaBest ) +{ + Emap_PackEntry_t * pEntries; + Abc_Obj_t * pObj; + float AreaBest = *pAreaBest; + double DelayCur; + int i, k, f, nEntries = 0, nApplied = 0; + if ( pLib->nMogs == 0 ) + return 0; + Emap_ManComputeRefs( pNtk, pMaps, pLib, pRefs ); + pEntries = ABC_ALLOC( Emap_PackEntry_t, 2 * EMAP_CUT_MAX * Abc_NtkObjNumMax(pNtk) ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + for ( f = 0; f < 2; f++ ) + { + Emap_Obj_t * pMap = &pMaps[Abc_ObjId(pObj)]; + int c; + if ( pRefs[2 * Abc_ObjId(pObj) + f] == 0 ) + continue; + for ( c = 0; c < pMap->nCuts; c++ ) + { + Emap_Cut_t * pCut = &pMap->Cuts[c]; + word Truth = f ? (pCut->Truth ^ Emap_TruthMask(pCut->nLeaves)) : pCut->Truth; + if ( pCut->nLeaves < 2 ) + continue; + pEntries[nEntries].ObjId = Abc_ObjId(pObj); + pEntries[nEntries].Phase = f; + pEntries[nEntries].Cut = c; + pEntries[nEntries].nLeaves = pCut->nLeaves; + pEntries[nEntries].Truth = Truth; + for ( k = 0; k < pCut->nLeaves; k++ ) + pEntries[nEntries].Leaves[k] = pCut->Leaves[k]; + nEntries++; + } + } + } + qsort( pEntries, nEntries, sizeof(Emap_PackEntry_t), Emap_PackEntryCompare ); + for ( i = 0; i < nEntries; i++ ) + { + Emap_PackEntry_t * pEntry0 = &pEntries[i]; + Emap_Best_t * pBest0 = &pMaps[pEntry0->ObjId].Best[pEntry0->Phase]; + Emap_Cut_t * pCut0; + if ( pRefs[2 * pEntry0->ObjId + pEntry0->Phase] == 0 || pBest0->TwinObj >= 0 ) + continue; + pCut0 = &pMaps[pEntry0->ObjId].Cuts[pEntry0->Cut]; + for ( k = 0; k < pLib->nMogs; k++ ) + { + Emap_Mog_t * pMog = &pLib->pMogs[k]; + int s; + if ( pMog->nPins != pCut0->nLeaves ) + continue; + for ( s = 0; s < 2; s++ ) + { + word Truth0 = s ? pMog->Truth1 : pMog->Truth0; + word Truth1 = s ? pMog->Truth0 : pMog->Truth1; + int Beg; + if ( Truth0 != pEntry0->Truth ) + continue; + Beg = Emap_PackEntryFindFirst( pEntries, nEntries, pCut0, Truth1 ); + if ( Beg < 0 ) + continue; + for ( ; Beg < nEntries && pEntries[Beg].nLeaves == pCut0->nLeaves && pEntries[Beg].Truth == Truth1; Beg++ ) + { + Emap_PackEntry_t * pEntry1 = &pEntries[Beg]; + Emap_Best_t * pBest1 = &pMaps[pEntry1->ObjId].Best[pEntry1->Phase]; + Emap_Best_t OldBest0, OldBest1; + float AreaCur; + int m, fSameLeaves = 1; + for ( m = 0; m < pCut0->nLeaves; m++ ) + if ( pEntry1->Leaves[m] != pCut0->Leaves[m] ) + fSameLeaves = 0; + if ( !fSameLeaves ) + break; + if ( pEntry1->ObjId == pEntry0->ObjId || pRefs[2 * pEntry1->ObjId + pEntry1->Phase] == 0 || pBest1->TwinObj >= 0 ) + continue; + if ( Emap_ObjPairHasDirectDanglingRelation( pNtk, pEntry0->ObjId, pEntry1->ObjId ) ) + continue; + if ( Emap_ObjPairHasTfiRelation( pNtk, pEntry0->ObjId, pEntry1->ObjId ) ) + continue; + OldBest0 = *pBest0; + OldBest1 = *pBest1; + Emap_MogApply( pMaps, pEntry0, pEntry1, pMog, s ); + AreaCur = Emap_ManComputeActualMappedStats( pNtk, pMaps, pLib, pMio, &DelayCur ); + if ( DelayCur <= DelayTarget + EMAP_DELAY_EPS && AreaCur < AreaBest - 0.001 ) + { + AreaBest = AreaCur; + nApplied++; + Emap_ManComputeRefs( pNtk, pMaps, pLib, pRefs ); + break; + } + *pBest0 = OldBest0; + *pBest1 = OldBest1; + } + if ( pBest0->TwinObj >= 0 ) + break; + } + if ( pBest0->TwinObj >= 0 ) + break; + } + } + *pAreaBest = AreaBest; + ABC_FREE( pEntries ); + return nApplied; +} + +static Abc_Ntk_t * Emap_ManBuildMappedNtk( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, Mio_Library_t * pMio ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pObjNew, * pFanin; + Vec_Int_t * vCopy; + int i; + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_MAP, 1 ); + pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ? pNtk->pName : "emap" ); + pNtkNew->pManFunc = pMio; + vCopy = Vec_IntStartFull( 2 * Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + pObjNew = Abc_NtkCreatePi( pNtkNew ); + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); + Vec_IntWriteEntry( vCopy, 2 * Abc_ObjId(pObj) + 0, Abc_ObjId(pObjNew) ); + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pObjNew = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); + pFanin = Emap_ManBuildPhase_rec( pNtk, pNtkNew, pMaps, vCopy, Abc_ObjFaninId0(pObj), Abc_ObjFaninC0(pObj), pLib ); + if ( pFanin == NULL ) + { + Vec_IntFree( vCopy ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + Abc_ObjAddFanin( pObjNew, pFanin ); + } + Vec_IntFree( vCopy ); + if ( !Abc_NtkCheck( pNtkNew ) ) + { + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +static float Emap_ManComputeActualMappedStats( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, Mio_Library_t * pMio, double * pDelay ) +{ + Abc_Ntk_t * pNtkNew = Emap_ManBuildMappedNtk( pNtk, pMaps, pLib, pMio ); + float Area; + if ( pNtkNew == NULL ) + { + *pDelay = EMAP_DOUBLE_LARGE; + return EMAP_FLOAT_LARGE; + } + *pDelay = Abc_NtkDelayTrace( pNtkNew, NULL, NULL, 0 ); + Area = (float)Abc_NtkGetMappedArea( pNtkNew ); + Abc_NtkDelete( pNtkNew ); + return Area; +} + +static int Emap_ManTryExactRecoveries( Abc_Ntk_t * pNtk, Emap_Obj_t * pMaps, Emap_Lib_t * pLib, Mio_Library_t * pMio, Emap_Tuples_t * pTuples, double * pRequired, int * pRefs, Emap_Best_t * pBase, Emap_Best_t * pSave, float * pAreaBest, double * pDelayBest, double DelayTarget ) +{ + float AreaCur, AreaBase, AreaBest = EMAP_FLOAT_LARGE; + double DelayCur, DelayBase, DelayBest = EMAP_DOUBLE_LARGE; + int Mode, fHaveBest = 0, nChanges, nChangesBest = 0; + for ( Mode = 0; Mode < 4; Mode++ ) + { + int fRelax = Mode & 1; + int fDropPhase = (Mode >> 1) & 1; + Emap_ManRestoreBests( pNtk, pMaps, pBase ); + nChanges = Emap_ManRecoverExactArea( pNtk, pMaps, pLib, pTuples, pRequired, pRefs, 2, DelayTarget, fRelax, fDropPhase ); + AreaCur = Emap_ManComputeActualMappedStats( pNtk, pMaps, pLib, pMio, &DelayCur ); + if ( DelayCur <= DelayTarget + EMAP_DELAY_EPS && AreaCur < AreaBest - 0.001 ) + { + AreaBest = AreaCur; + DelayBest = DelayCur; + nChangesBest = nChanges; + Emap_ManSaveBests( pNtk, pMaps, pSave ); + fHaveBest = 1; + } + } + if ( fHaveBest ) + { + Emap_ManRestoreBests( pNtk, pMaps, pSave ); + *pAreaBest = AreaBest; + *pDelayBest = DelayBest; + return nChangesBest; + } + Emap_ManRestoreBests( pNtk, pMaps, pBase ); + AreaBase = Emap_ManComputeActualMappedStats( pNtk, pMaps, pLib, pMio, &DelayBase ); + Emap_ManSaveBests( pNtk, pMaps, pSave ); + *pAreaBest = AreaBase; + *pDelayBest = DelayBase; + return 0; +} + +/**Function************************************************************* + + Synopsis [Creates a mapped network by cut matching AIG nodes.] + +***********************************************************************/ +Abc_Ntk_t * Emap_ManMapAigStructural( Abc_Ntk_t * pNtk, Mio_Library_t * pMio, int fUseMogs, int fAreaMode, int fVerbose ) +{ + Emap_Lib_t Lib; + Emap_Tuples_t Tuples; + Emap_Obj_t * pMaps; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj; + double * pRequired = NULL, DelayTarget = 0, DelayLimit = 0; + Emap_Best_t * pBestSave = NULL; + Emap_Best_t * pBestRound = NULL; + Emap_Best_t * pBestTrial = NULL; + float AreaBest, AreaCur; + double DelayBest, DelayCur; + int * pRefs = NULL; + int i, r, nNodesMapped = 0, nNodesFailed = 0, nMogsPacked = 0, nMogsBest = 0, nExactChanges = 0, nExactChangesBest = 0; + + assert( Abc_NtkIsStrash(pNtk) ); + memset( &Tuples, 0, sizeof(Tuples) ); + if ( !Emap_LibPrepare( &Lib, pMio ) ) + return NULL; + + pMaps = ABC_CALLOC( Emap_Obj_t, Abc_NtkObjNumMax(pNtk) ); + Emap_NodeAddConstCut( &pMaps[Abc_ObjId(Abc_AigConst1(pNtk))] ); + pMaps[Abc_ObjId(Abc_AigConst1(pNtk))].Best[0].Arr = 0; + pMaps[Abc_ObjId(Abc_AigConst1(pNtk))].Best[0].Flow = 0; + pMaps[Abc_ObjId(Abc_AigConst1(pNtk))].Best[1].Arr = Lib.InvDelay; + pMaps[Abc_ObjId(Abc_AigConst1(pNtk))].Best[1].Flow = Lib.InvArea; + pMaps[Abc_ObjId(Abc_AigConst1(pNtk))].Best[1].fInv = 1; + + Abc_NtkForEachPi( pNtk, pObj, i ) + { + Emap_NodeAddUnitCut( &pMaps[Abc_ObjId(pObj)], Abc_ObjId(pObj) ); + pMaps[Abc_ObjId(pObj)].Best[0].Arr = 0; + pMaps[Abc_ObjId(pObj)].Best[0].Flow = 0; + pMaps[Abc_ObjId(pObj)].Best[1].Arr = Lib.InvDelay; + pMaps[Abc_ObjId(pObj)].Best[1].Flow = Lib.InvArea; + pMaps[Abc_ObjId(pObj)].Best[1].fInv = 1; + } + + Abc_AigForEachAnd( pNtk, pObj, i ) + { + Emap_NodeMergeCuts( pMaps, pObj ); + Emap_NodeMatch( pMaps, &pMaps[Abc_ObjId(pObj)], &Lib, pObj, NULL, NULL ); + if ( pMaps[Abc_ObjId(pObj)].Best[0].pGate ) + nNodesMapped++; + else + nNodesFailed++; + } + if ( nNodesFailed ) + printf( "Warning: %d AIG nodes did not receive a direct cut match.\n", nNodesFailed ); + if ( fUseMogs ) + Emap_ManComputeMogTuples( pNtk, pMaps, &Lib, &Tuples ); + + pRequired = ABC_ALLOC( double, 2 * Abc_NtkObjNumMax(pNtk) ); + pRefs = ABC_ALLOC( int, 2 * Abc_NtkObjNumMax(pNtk) ); + pBestSave = ABC_ALLOC( Emap_Best_t, 2 * Abc_NtkObjNumMax(pNtk) ); + pBestRound = ABC_ALLOC( Emap_Best_t, 2 * Abc_NtkObjNumMax(pNtk) ); + pBestTrial = ABC_ALLOC( Emap_Best_t, 2 * Abc_NtkObjNumMax(pNtk) ); + DelayTarget = Emap_ManComputeRequired( pNtk, pMaps, &Lib, pRequired ); + DelayLimit = fAreaMode ? EMAP_DOUBLE_LARGE / 4 : DelayTarget; + if ( fAreaMode ) + for ( i = 0; i < 2 * Abc_NtkObjNumMax(pNtk); i++ ) + pRequired[i] = EMAP_DOUBLE_LARGE; + Emap_ManSaveBests( pNtk, pMaps, pBestTrial ); + nExactChangesBest = Emap_ManTryExactRecoveries( pNtk, pMaps, &Lib, pMio, fUseMogs ? &Tuples : NULL, pRequired, pRefs, pBestTrial, pBestRound, &AreaBest, &DelayBest, DelayLimit ); + Emap_ManSaveBests( pNtk, pMaps, pBestSave ); + Emap_ManSaveBests( pNtk, pMaps, pBestRound ); + if ( fUseMogs ) + { + int fAcceptedThisRound = 0; + if ( getenv("ABC_EMAP_TIMED_MOG") ) + { + float AreaTimed = AreaBest; + Emap_ManRestoreBests( pNtk, pMaps, pBestRound ); + nMogsPacked = Emap_ManRecoverMogsTimed( pNtk, pMaps, &Lib, pMio, pRefs, DelayLimit, &AreaTimed ); + if ( getenv("ABC_EMAP_DEBUG_MOG") ) + printf( "ABC emap MOG timed trial initial: applied=%d area=%.2f best=%.2f\n", nMogsPacked, AreaTimed, AreaBest ); + if ( nMogsPacked && AreaTimed < AreaBest - 0.001 ) + { + AreaBest = AreaTimed; + nMogsBest = nMogsPacked; + Emap_ManSaveBests( pNtk, pMaps, pBestSave ); + fAcceptedThisRound = 1; + } + Emap_ManRestoreBests( pNtk, pMaps, pBestRound ); + } + nMogsPacked = Emap_ManRecoverMogsExact( pNtk, pMaps, &Lib, pRequired, pRefs ); + AreaCur = Emap_ManComputeActualMappedStats( pNtk, pMaps, &Lib, pMio, &DelayCur ); + if ( getenv("ABC_EMAP_DEBUG_MOG") ) + printf( "ABC emap MOG exact trial initial: applied=%d area=%.2f delay=%.2f best=%.2f\n", nMogsPacked, AreaCur, DelayCur, AreaBest ); + if ( nMogsPacked && (fAreaMode || DelayCur <= DelayTarget + EMAP_DELAY_EPS) && AreaCur < AreaBest - 0.001 ) + { + AreaBest = AreaCur; + DelayBest = DelayCur; + nMogsBest = nMogsPacked; + Emap_ManSaveBests( pNtk, pMaps, pBestSave ); + fAcceptedThisRound = 1; + } + Emap_ManRestoreBests( pNtk, pMaps, pBestRound ); + if ( getenv("ABC_EMAP_MFFC_EXACT") ) + { + float AreaMffc = AreaBest; + double DelayMffc = DelayBest; + nMogsPacked = Emap_ManRecoverMogsExactMffc( pNtk, pMaps, &Lib, pMio, pRequired, pRefs, DelayLimit, &AreaMffc, &DelayMffc ); + if ( getenv("ABC_EMAP_DEBUG_MOG") ) + printf( "ABC emap MOG MFFC exact trial initial: applied=%d area=%.2f delay=%.2f best=%.2f\n", nMogsPacked, AreaMffc, DelayMffc, AreaBest ); + if ( nMogsPacked && AreaMffc < AreaBest - 0.001 ) + { + AreaBest = AreaMffc; + DelayBest = DelayMffc; + nMogsBest = nMogsPacked; + Emap_ManSaveBests( pNtk, pMaps, pBestSave ); + fAcceptedThisRound = 1; + } + Emap_ManRestoreBests( pNtk, pMaps, pBestRound ); + } + nMogsPacked = Emap_ManPackMogs( pNtk, pMaps, &Lib, pRequired, pRefs ); + AreaCur = Emap_ManComputeActualMappedStats( pNtk, pMaps, &Lib, pMio, &DelayCur ); + if ( getenv("ABC_EMAP_DEBUG_MOG") ) + printf( "ABC emap MOG pack trial initial: applied=%d area=%.2f delay=%.2f best=%.2f\n", nMogsPacked, AreaCur, DelayCur, AreaBest ); + if ( nMogsPacked && (fAreaMode || DelayCur <= DelayTarget + EMAP_DELAY_EPS) && AreaCur < AreaBest - 0.001 ) + { + AreaBest = AreaCur; + DelayBest = DelayCur; + nMogsBest = nMogsPacked; + Emap_ManSaveBests( pNtk, pMaps, pBestSave ); + fAcceptedThisRound = 1; + } + Emap_ManRestoreBests( pNtk, pMaps, fAcceptedThisRound ? pBestSave : pBestRound ); + } + for ( r = 0; r < 6; r++ ) + { + int nMogsCur; + Emap_ManComputeRefs( pNtk, pMaps, &Lib, pRefs ); + if ( fAreaMode ) + for ( i = 0; i < 2 * Abc_NtkObjNumMax(pNtk); i++ ) + pRequired[i] = EMAP_DOUBLE_LARGE; + else + Emap_ManComputeRequiredTarget( pNtk, pMaps, &Lib, pRequired, pRefs, DelayTarget ); + nNodesMapped = nNodesFailed = 0; + Abc_AigForEachAnd( pNtk, pObj, i ) + { + Emap_NodeMatch( pMaps, &pMaps[Abc_ObjId(pObj)], &Lib, pObj, pRequired, pRefs ); + if ( fUseMogs && !getenv("ABC_EMAP_SKIP_MOG_AREA") ) + Emap_NodeMatchMogArea( pNtk, pMaps, &Lib, &Tuples, pRefs, pRequired, Abc_ObjId(pObj), 1 ); + if ( pMaps[Abc_ObjId(pObj)].Best[0].pGate ) + nNodesMapped++; + else + nNodesFailed++; + } + Emap_ManSaveBests( pNtk, pMaps, pBestTrial ); + AreaCur = Emap_ManComputeActualMappedStats( pNtk, pMaps, &Lib, pMio, &DelayCur ); + if ( fUseMogs && (fAreaMode || DelayCur <= DelayTarget + EMAP_DELAY_EPS) && AreaCur < AreaBest - 0.001 ) + { + AreaBest = AreaCur; + DelayBest = DelayCur; + nMogsBest = Tuples.nAreaAccepts; + nExactChangesBest = nExactChanges; + Emap_ManSaveBests( pNtk, pMaps, pBestSave ); + Emap_ManSaveBests( pNtk, pMaps, pBestRound ); + } + nExactChanges = Emap_ManTryExactRecoveries( pNtk, pMaps, &Lib, pMio, fUseMogs ? &Tuples : NULL, pRequired, pRefs, pBestTrial, pBestRound, &AreaCur, &DelayCur, DelayLimit ); + AreaCur = Emap_ManComputeActualMappedStats( pNtk, pMaps, &Lib, pMio, &DelayCur ); + if ( (fAreaMode || DelayCur <= DelayTarget + EMAP_DELAY_EPS) && AreaCur < AreaBest - 0.001 ) + { + AreaBest = AreaCur; + DelayBest = DelayCur; + nMogsBest = 0; + nExactChangesBest = nExactChanges; + Emap_ManSaveBests( pNtk, pMaps, pBestSave ); + Emap_ManSaveBests( pNtk, pMaps, pBestRound ); + } + if ( fUseMogs ) + { + int fAcceptedThisRound = 0; + if ( getenv("ABC_EMAP_TIMED_MOG") ) + { + float AreaTimed = AreaBest; + Emap_ManRestoreBests( pNtk, pMaps, pBestRound ); + nMogsCur = Emap_ManRecoverMogsTimed( pNtk, pMaps, &Lib, pMio, pRefs, DelayLimit, &AreaTimed ); + if ( getenv("ABC_EMAP_DEBUG_MOG") ) + printf( "ABC emap MOG timed trial round %d: applied=%d area=%.2f best=%.2f\n", r, nMogsCur, AreaTimed, AreaBest ); + if ( nMogsCur && AreaTimed < AreaBest - 0.001 ) + { + AreaBest = AreaTimed; + nMogsBest = nMogsCur; + nExactChangesBest = nExactChanges; + Emap_ManSaveBests( pNtk, pMaps, pBestSave ); + fAcceptedThisRound = 1; + } + Emap_ManRestoreBests( pNtk, pMaps, pBestRound ); + } + nMogsCur = Emap_ManRecoverMogsExact( pNtk, pMaps, &Lib, pRequired, pRefs ); + AreaCur = Emap_ManComputeActualMappedStats( pNtk, pMaps, &Lib, pMio, &DelayCur ); + if ( getenv("ABC_EMAP_DEBUG_MOG") ) + printf( "ABC emap MOG exact trial round %d: applied=%d area=%.2f delay=%.2f best=%.2f\n", r, nMogsCur, AreaCur, DelayCur, AreaBest ); + if ( nMogsCur && (fAreaMode || DelayCur <= DelayTarget + EMAP_DELAY_EPS) && AreaCur < AreaBest - 0.001 ) + { + AreaBest = AreaCur; + DelayBest = DelayCur; + nMogsBest = nMogsCur; + nExactChangesBest = nExactChanges; + Emap_ManSaveBests( pNtk, pMaps, pBestSave ); + fAcceptedThisRound = 1; + } + Emap_ManRestoreBests( pNtk, pMaps, pBestRound ); + if ( getenv("ABC_EMAP_MFFC_EXACT") ) + { + float AreaMffc = AreaBest; + double DelayMffc = DelayBest; + nMogsCur = Emap_ManRecoverMogsExactMffc( pNtk, pMaps, &Lib, pMio, pRequired, pRefs, DelayLimit, &AreaMffc, &DelayMffc ); + if ( getenv("ABC_EMAP_DEBUG_MOG") ) + printf( "ABC emap MOG MFFC exact trial round %d: applied=%d area=%.2f delay=%.2f best=%.2f\n", r, nMogsCur, AreaMffc, DelayMffc, AreaBest ); + if ( nMogsCur && AreaMffc < AreaBest - 0.001 ) + { + AreaBest = AreaMffc; + DelayBest = DelayMffc; + nMogsBest = nMogsCur; + nExactChangesBest = nExactChanges; + Emap_ManSaveBests( pNtk, pMaps, pBestSave ); + fAcceptedThisRound = 1; + } + Emap_ManRestoreBests( pNtk, pMaps, pBestRound ); + } + nMogsCur = Emap_ManPackMogs( pNtk, pMaps, &Lib, pRequired, pRefs ); + AreaCur = Emap_ManComputeActualMappedStats( pNtk, pMaps, &Lib, pMio, &DelayCur ); + if ( getenv("ABC_EMAP_DEBUG_MOG") ) + printf( "ABC emap MOG pack trial round %d: applied=%d area=%.2f delay=%.2f best=%.2f\n", r, nMogsCur, AreaCur, DelayCur, AreaBest ); + if ( nMogsCur && (fAreaMode || DelayCur <= DelayTarget + EMAP_DELAY_EPS) && AreaCur < AreaBest - 0.001 ) + { + AreaBest = AreaCur; + DelayBest = DelayCur; + nMogsBest = nMogsCur; + nExactChangesBest = nExactChanges; + Emap_ManSaveBests( pNtk, pMaps, pBestSave ); + fAcceptedThisRound = 1; + } + Emap_ManRestoreBests( pNtk, pMaps, fAcceptedThisRound ? pBestSave : pBestRound ); + } + } + Emap_ManRestoreBests( pNtk, pMaps, pBestSave ); + nMogsPacked = nMogsBest; + if ( nNodesFailed ) + printf( "Warning: %d AIG nodes did not receive an area-recovery match.\n", nNodesFailed ); + + pNtkNew = Emap_ManBuildMappedNtk( pNtk, pMaps, &Lib, pMio ); + if ( pNtkNew == NULL ) + { + Emap_LibFree( &Lib ); + Emap_TuplesFree( &Tuples ); + ABC_FREE( pMaps ); + ABC_FREE( pRequired ); + ABC_FREE( pRefs ); + ABC_FREE( pBestSave ); + ABC_FREE( pBestRound ); + ABC_FREE( pBestTrial ); + return NULL; + } + + if ( getenv("ABC_EMAP_DEBUG_MOG") ) + { + printf( "ABC emap MOG area: tuples=%d calls=%d candidates=%d accepts=%d reject_twin=%d reject_required=%d reject_flow=%d\n", + Tuples.nSize, Tuples.nAreaCalls, Tuples.nAreaCandidates, Tuples.nAreaAccepts, + Tuples.nAreaRejectTwin, Tuples.nAreaRejectRequired, Tuples.nAreaRejectFlow ); + printf( "ABC emap MOG local exact: calls=%d candidates=%d accepts=%d reject_unused=%d reject_twin=%d reject_shared=%d reject_required=%d reject_area=%d\n", + Tuples.nExactLocalCalls, Tuples.nExactLocalCandidates, Tuples.nExactLocalAccepts, + Tuples.nExactLocalRejectUnused, Tuples.nExactLocalRejectTwin, Tuples.nExactLocalRejectShared, + Tuples.nExactLocalRejectRequired, Tuples.nExactLocalRejectArea ); + printf( "ABC emap MOG local exact by arity: cand2=%d cand3=%d accept2=%d accept3=%d\n", + Tuples.nExactLocalCand2, Tuples.nExactLocalCand3, Tuples.nExactLocalAccept2, Tuples.nExactLocalAccept3 ); + } + + if ( fVerbose ) + printf( "ABC-native emap mapped %d AIG nodes using %d GENLIB truth variants, %d MOG variants, %d exact-cover changes, and packed %d MOG pairs in %s mode with delay target %.2f.\n", nNodesMapped, Lib.nCells, Lib.nMogs, nExactChangesBest, nMogsPacked, fAreaMode ? "area" : "delay", DelayTarget ); + + Emap_LibFree( &Lib ); + Emap_TuplesFree( &Tuples ); + ABC_FREE( pMaps ); + ABC_FREE( pRequired ); + ABC_FREE( pRefs ); + ABC_FREE( pBestSave ); + ABC_FREE( pBestRound ); + ABC_FREE( pBestTrial ); + return pNtkNew; +} + +static Abc_Obj_t * Emap_ManBuildConst( Abc_Ntk_t * pNtkNew, Vec_Int_t * vCopy, int ObjId, int Phase ) +{ + Abc_Obj_t * pObj; + int Entry = Vec_IntEntry( vCopy, 2 * ObjId + Phase ); + if ( Entry >= 0 ) + return Abc_NtkObj( pNtkNew, Entry ); + pObj = Phase ? Abc_NtkCreateNodeConst0( pNtkNew ) : Abc_NtkCreateNodeConst1( pNtkNew ); + Vec_IntWriteEntry( vCopy, 2 * ObjId + Phase, Abc_ObjId(pObj) ); + return pObj; +} + +static Abc_Obj_t * Emap_ManBuildPhase_rec( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Emap_Obj_t * pMaps, Vec_Int_t * vCopy, int ObjId, int Phase, Emap_Lib_t * pLib ) +{ + Emap_Obj_t * pMap = &pMaps[ObjId]; + Emap_Best_t * pBest = &pMap->Best[Phase]; + Emap_Cut_t * pCut; + Abc_Obj_t * pObj, * pFanin; + int i, Entry = Vec_IntEntry( vCopy, 2 * ObjId + Phase ); + if ( Entry >= 0 ) + return Abc_NtkObj( pNtkNew, Entry ); + if ( ObjId == Abc_ObjId(Abc_AigConst1(pNtk)) ) + return Emap_ManBuildConst( pNtkNew, vCopy, ObjId, Phase ); + if ( Abc_ObjIsPi(Abc_NtkObj(pNtk, ObjId)) ) + { + Entry = Vec_IntEntry( vCopy, 2 * ObjId + 0 ); + assert( Entry >= 0 ); + if ( Phase == 0 ) + return Abc_NtkObj( pNtkNew, Entry ); + pObj = Emap_ManCreateInv( pNtkNew, Abc_NtkObj(pNtkNew, Entry), pLib->pGateInv ); + Vec_IntWriteEntry( vCopy, 2 * ObjId + 1, Abc_ObjId(pObj) ); + return pObj; + } + if ( pBest->fInv ) + { + pFanin = Emap_ManBuildPhase_rec( pNtk, pNtkNew, pMaps, vCopy, ObjId, !Phase, pLib ); + if ( pFanin == NULL ) + return NULL; + pObj = Emap_ManCreateInv( pNtkNew, pFanin, pLib->pGateInv ); + Vec_IntWriteEntry( vCopy, 2 * ObjId + Phase, Abc_ObjId(pObj) ); + return pObj; + } + if ( pBest->TwinObj >= 0 ) + { + Emap_Best_t * pTwinBest = &pMaps[pBest->TwinObj].Best[pBest->TwinPhase]; + Abc_Obj_t * pFanins[EMAP_LEAF_MAX]; + Abc_Obj_t * pObjTwin; + int fCurrentFirst = pBest->pGate <= pTwinBest->pGate; + pCut = &pMap->Cuts[pBest->Cut]; + for ( i = 0; i < pBest->nPins; i++ ) + { + pFanins[i] = Emap_ManBuildPhase_rec( pNtk, pNtkNew, pMaps, vCopy, pCut->Leaves[pBest->PinToLeaf[i]], pBest->PinPhase[i], pLib ); + if ( pFanins[i] == NULL ) + return NULL; + } + pObj = Abc_NtkCreateNode( pNtkNew ); + pObjTwin = Abc_NtkCreateNode( pNtkNew ); + pObj->pData = fCurrentFirst ? pBest->pGate : pTwinBest->pGate; + pObjTwin->pData = fCurrentFirst ? pTwinBest->pGate : pBest->pGate; + for ( i = 0; i < pBest->nPins; i++ ) + { + Abc_ObjAddFanin( pObj, pFanins[i] ); + Abc_ObjAddFanin( pObjTwin, pFanins[i] ); + } + if ( fCurrentFirst ) + { + Vec_IntWriteEntry( vCopy, 2 * ObjId + Phase, Abc_ObjId(pObj) ); + Vec_IntWriteEntry( vCopy, 2 * pBest->TwinObj + pBest->TwinPhase, Abc_ObjId(pObjTwin) ); + return pObj; + } + Vec_IntWriteEntry( vCopy, 2 * pBest->TwinObj + pBest->TwinPhase, Abc_ObjId(pObj) ); + Vec_IntWriteEntry( vCopy, 2 * ObjId + Phase, Abc_ObjId(pObjTwin) ); + return pObjTwin; + } + if ( pBest->pGate == NULL ) + return NULL; + pCut = &pMap->Cuts[pBest->Cut]; + pObj = Abc_NtkCreateNode( pNtkNew ); + pObj->pData = pBest->pGate; + for ( i = 0; i < pBest->nPins; i++ ) + { + pFanin = Emap_ManBuildPhase_rec( pNtk, pNtkNew, pMaps, vCopy, pCut->Leaves[pBest->PinToLeaf[i]], pBest->PinPhase[i], pLib ); + if ( pFanin == NULL ) + return NULL; + Abc_ObjAddFanin( pObj, pFanin ); + } + Vec_IntWriteEntry( vCopy, 2 * ObjId + Phase, Abc_ObjId(pObj) ); + return pObj; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END diff --git a/src/map/emap/module.make b/src/map/emap/module.make new file mode 100644 index 0000000000..261e0879e1 --- /dev/null +++ b/src/map/emap/module.make @@ -0,0 +1,2 @@ +SRC += src/map/emap/emap.c \ + src/map/emap/emapCore.c diff --git a/src/map/if/ifDec07.c b/src/map/if/ifDec07.c index 6311df6d1e..1458175980 100644 --- a/src/map/if/ifDec07.c +++ b/src/map/if/ifDec07.c @@ -1127,9 +1127,10 @@ int If_MatchCheck1( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, cha } int If_MatchCheck2( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ) { - if ( nLeaves < nVars ) + if ( nLeaves < p->pPars->nLutSize ) return 1; - assert( nLeaves == nVars ); + assert( nLeaves == p->pPars->nLutSize ); + assert( nLeaves <= nVars ); if ( Abc_Tt6Check2( ((word *)pTruth)[0], nLeaves ) ) return 1; return 0; @@ -1141,4 +1142,3 @@ int If_MatchCheck2( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, cha ABC_NAMESPACE_IMPL_END - diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c index f93b73edb0..6a0148d4f6 100644 --- a/src/map/if/ifMap.c +++ b/src/map/if/ifMap.c @@ -194,7 +194,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->Delay = If_CutSopBalanceEval( p, pCut, NULL ); else if ( p->pPars->fDsdBalance ) pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL ); - else if ( p->pPars->fEnableCheck07 && p->pPars->fDelayOptCell ) + else if ( p->pPars->fEnableCheck07 && p->pPars->pCellLib ) { int iLeaf, Intrinsic[IF_MAX_LUTSIZE]; float Delay = -IF_FLOAT_LARGE; @@ -364,7 +364,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep for ( iLeaf = 0; iLeaf < p->nCutLeavesCur; iLeaf++ ) { If_Obj_t * pLeaf = If_CutLeaf( p, pCut, iLeaf ); - if ( p->pPars->fEnableCheck07 && p->pPars->fDelayOptCell && pCut->nLeaves > 1 ) + if ( p->pPars->fEnableCheck07 && p->pPars->pCellLib && pCut->nLeaves > 1 ) { If_Cut_t * pBestCut = If_ObjCutBest( pLeaf ); assert( pBestCut != NULL ); @@ -472,8 +472,10 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->Delay = If_CutSopBalanceEval( p, pCut, NULL ); else if ( p->pPars->fDsdBalance ) pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL ); - else if ( p->pPars->fEnableCheck07 && p->pPars->fDelayOptCell ) + else if ( p->pPars->fEnableCheck07 && p->pPars->pCellLib ) { + int iLeaf, Intrinsic[IF_MAX_LUTSIZE]; + float Delay = -IF_FLOAT_LARGE; if ( pCut->nLeaves == 0 ) { pCut->Delay = 0.0; @@ -487,9 +489,16 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep pCut->fUseless = 0; goto IfMapCutEvalDone; } - assert( pCut->fUseless || p->fCutDelayCurValid ); assert( pCut->fUseless || pCut->Config != 0 ); - pCut->Delay = pCut->fUseless ? IF_FLOAT_LARGE : p->CutDelayCur; + if ( pCut->fUseless ) + pCut->Delay = IF_FLOAT_LARGE; + else + { + If_CutComputeIntrinsicJ( p, pCut->Config, pCut->nLeaves, Intrinsic ); + If_CutForEachLeaf( p, pCut, pLeaf, iLeaf ) + Delay = IF_MAX( Delay, If_ObjArrTime(pLeaf) + (float)Intrinsic[iLeaf] ); + pCut->Delay = Delay; + } IfMapCutEvalDone: ; } diff --git a/src/map/if/ifTime.c b/src/map/if/ifTime.c index 81f88fd72e..3126b75a71 100644 --- a/src/map/if/ifTime.c +++ b/src/map/if/ifTime.c @@ -131,7 +131,7 @@ float If_CutDelay( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut ) } else { - if ( p->pPars->fEnableCheck07 && p->pPars->fDelayOptCell && p->pPars->pCellLib ) + if ( p->pPars->fEnableCheck07 && p->pPars->pCellLib ) { int Intrinsic[IF_MAX_LUTSIZE]; if ( pCut->nLeaves == 0 ) @@ -233,7 +233,7 @@ void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, fl } else { - if ( p->pPars->fEnableCheck07 && p->pPars->fDelayOptCell && p->pPars->pCellLib ) + if ( p->pPars->fEnableCheck07 && p->pPars->pCellLib ) { int Intrinsic[IF_MAX_LUTSIZE]; if ( pCut->nLeaves == 0 ) @@ -338,7 +338,7 @@ float If_ManDelayMax( If_Man_t * p, int fSeq ) void If_ManComputeRequired( If_Man_t * p ) { If_Obj_t * pObj; - int i, Counter; + int i, iBox, Counter; float reqTime; // compute area, clean required times, collect nodes used in the mapping @@ -480,7 +480,7 @@ void If_ManComputeRequired( If_Man_t * p ) if ( p->pPars->pTimesReq ) { Counter = 0; - If_ManForEachCo( p, pObj, i ) + If_ManForEachPo( p, pObj, i ) { reqTime = p->pPars->pTimesReq[i]; if ( If_ObjArrTime(If_ObjFanin0(pObj)) > reqTime + p->fEpsilon ) @@ -551,6 +551,9 @@ void If_ManComputeRequired( If_Man_t * p ) { reqTime = pObj->Required; Tim_ManSetCiRequired( p->pManTim, pObj->IdPio, reqTime ); + iBox = Tim_ManBoxForCi( p->pManTim, pObj->IdPio ); + if ( iBox >= 0 ) + Tim_ManSetPreviousTravIdBoxInputs( p->pManTim, iBox ); } else if ( If_ObjIsCo(pObj) ) { diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index b012435f5a..f023680e2d 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -42,6 +42,7 @@ static int Scl_CommandLeak2Area ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandDumpGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandPrintGS ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandStime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Scl_CommandPower ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandTopo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandUnBuffer ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandBuffer ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -110,6 +111,7 @@ void Scl_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "SCL mapping", "dump_genlib", Scl_CommandDumpGen, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "print_gs", Scl_CommandPrintGS, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "stime", Scl_CommandStime, 0 ); + Cmd_CommandAdd( pAbc, "SCL mapping", "power", Scl_CommandPower, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "topo", Scl_CommandTopo, 1 ); Cmd_CommandAdd( pAbc, "SCL mapping", "unbuffer", Scl_CommandUnBuffer, 1 ); Cmd_CommandAdd( pAbc, "SCL mapping", "buffer", Scl_CommandBuffer, 1 ); @@ -836,6 +838,108 @@ int Scl_CommandPrintGS( Abc_Frame_t * pAbc, int argc, char **argv ) SeeAlso [] +***********************************************************************/ +int Scl_CommandPower( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int c; + int fUseWireLoads = 0; + int nTreeCRatio = 0; + int nFrames = 48; + int nPref = 16; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "XFPch" ) ) != EOF ) + { + switch ( c ) + { + case 'X': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-X\" should be followed by a positive integer.\n" ); + goto usage; + } + nTreeCRatio = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nTreeCRatio < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a positive integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames <= 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by a non-negative integer.\n" ); + goto usage; + } + nPref = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPref < 0 ) + goto usage; + break; + case 'c': + fUseWireLoads ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( Abc_FrameReadNtk(pAbc) == NULL ) + { + fprintf( pAbc->Err, "There is no current network.\n" ); + return 1; + } + if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) ) + { + fprintf( pAbc->Err, "The current network is not mapped.\n" ); + return 1; + } + if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) ) + { + fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" ); + return 1; + } + if ( pAbc->pLibScl == NULL ) + { + fprintf( pAbc->Err, "There is no Liberty library available.\n" ); + return 1; + } + + Abc_SclPowerPerform( (SC_Lib *)pAbc->pLibScl, Abc_FrameReadNtk(pAbc), nTreeCRatio, fUseWireLoads, nFrames, nPref ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: power [-X num] [-F num] [-P num] [-ch]\n" ); + fprintf( pAbc->Err, "\t computes power using Liberty library\n" ); + fprintf( pAbc->Err, "\t-X : min Cout/Cave ratio for tree estimations [default = %d]\n", nTreeCRatio ); + fprintf( pAbc->Err, "\t-F : number of frames to simulate for switching [default = %d]\n", nFrames ); + fprintf( pAbc->Err, "\t-P : number of prefix frames for switching [default = %d]\n", nPref ); + fprintf( pAbc->Err, "\t-c : toggle using wire-loads if specified [default = %s]\n", fUseWireLoads? "yes": "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + ***********************************************************************/ int Scl_CommandStime( Abc_Frame_t * pAbc, int argc, char **argv ) { @@ -2127,4 +2231,3 @@ int Scl_CommandResetConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclDnsize.c b/src/map/scl/sclDnsize.c index 35f2c8247d..20ffebb6f8 100644 --- a/src/map/scl/sclDnsize.c +++ b/src/map/scl/sclDnsize.c @@ -149,7 +149,7 @@ p->timeSize += Abc_Clock() - clk; { pCellNew = SC_LibCell( p->pLib, gateBest ); Abc_SclObjSetCell( pObj, pCellNew ); - p->SumArea += pCellNew->area - pCellOld->area; + p->SumArea += Abc_SclObjAreaDelta( pObj, pCellOld, pCellNew ); // printf( "%f %f -> %f\n", pCellNew->area - pCellOld->area, p->SumArea - (pCellNew->area - pCellOld->area), p->SumArea ); // printf( "%6d %20s -> %20s %f -> %f\n", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName, pCellOld->area, pCellNew->area ); // mark used nodes with the current trav ID @@ -376,4 +376,3 @@ void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclLib.h b/src/map/scl/sclLib.h index b50e6ffb7e..fd2f5bb497 100644 --- a/src/map/scl/sclLib.h +++ b/src/map/scl/sclLib.h @@ -40,7 +40,7 @@ ABC_NAMESPACE_HEADER_START /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// -#define ABC_SCL_CUR_VERSION 8 +#define ABC_SCL_CUR_VERSION 10 typedef enum { @@ -172,6 +172,8 @@ struct SC_Timing_ SC_Surface pCellFall; SC_Surface pRiseTrans; // -- Used to compute output slew SC_Surface pFallTrans; + SC_Surface pRisePower; // -- Used to compute internal power + SC_Surface pFallPower; }; struct SC_Timings_ @@ -230,6 +232,7 @@ struct SC_Lib_ int unit_time; // -- Valid 9..12. Unit is '10^(-val)' seconds (e.g. 9=1ns, 10=100ps, 11=10ps, 12=1ps) float unit_cap_fst; // -- First part is a multiplier, second either 12 or 15 for 'pf' or 'ff'. int unit_cap_snd; + float nom_voltage; // -- nominal voltage, used for external switching power Vec_Ptr_t vWireLoads; // NamedSet Vec_Ptr_t vWireLoadSels; // NamedSet Vec_Ptr_t vTempls; // NamedSet @@ -351,6 +354,7 @@ static inline SC_Lib * Abc_SclLibAlloc() p->unit_time = 9; p->unit_cap_fst = 1; p->unit_cap_snd = 12; + p->nom_voltage = 1; return p; } @@ -407,6 +411,8 @@ static inline void Abc_SclTimingFree( SC_Timing * p ) Abc_SclSurfaceFree( &p->pCellFall ); Abc_SclSurfaceFree( &p->pRiseTrans ); Abc_SclSurfaceFree( &p->pFallTrans ); + Abc_SclSurfaceFree( &p->pRisePower ); + Abc_SclSurfaceFree( &p->pFallPower ); ABC_FREE( p->related_pin ); ABC_FREE( p->when_text ); ABC_FREE( p ); @@ -492,11 +498,63 @@ static inline float Scl_LibLookup( SC_Surface * p, float slew, float load ) // handle constant table if ( Vec_FltSize(&p->vIndex0) == 1 && Vec_FltSize(&p->vIndex1) == 1 ) { - Vec_Flt_t * vTemp = (Vec_Flt_t *)Vec_PtrEntry(&p->vData, 0); - assert( Vec_PtrSize(&p->vData) == 1 ); + Vec_Flt_t * vTemp; + if ( Vec_PtrSize(&p->vData) != 1 ) + return 0; + vTemp = (Vec_Flt_t *)Vec_PtrEntry(&p->vData, 0); assert( Vec_FltSize(vTemp) == 1 ); + if ( Vec_FltSize(vTemp) != 1 ) + return 0; return Vec_FltEntry(vTemp, 0); } + if ( Vec_FltSize(&p->vIndex0) > 1 && Vec_FltSize(&p->vIndex1) == 1 ) + { + pIndex0 = Vec_FltArray(&p->vIndex0); + for ( s = 1; s < Vec_FltSize(&p->vIndex0)-1; s++ ) + if ( pIndex0[s] > slew ) + break; + s--; + if ( pIndex0[s+1] == pIndex0[s] ) + return 0; + sfrac = (slew - pIndex0[s]) / (pIndex0[s+1] - pIndex0[s]); + if ( Vec_PtrSize(&p->vData) == Vec_FltSize(&p->vIndex0) ) + { + Vec_Flt_t * vDataS = (Vec_Flt_t *)Vec_PtrEntry(&p->vData, s); + Vec_Flt_t * vDataS1 = (Vec_Flt_t *)Vec_PtrEntry(&p->vData, s+1); + if ( Vec_FltSize(vDataS) < 1 || Vec_FltSize(vDataS1) < 1 ) + return 0; + pDataS = Vec_FltArray( vDataS ); + pDataS1 = Vec_FltArray( vDataS1 ); + return pDataS[0] + sfrac * (pDataS1[0] - pDataS[0]); + } + if ( Vec_PtrSize(&p->vData) != 1 ) + return 0; + if ( Vec_FltSize((Vec_Flt_t *)Vec_PtrEntry(&p->vData, 0)) != Vec_FltSize(&p->vIndex0) ) + return 0; + pDataS = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(&p->vData, 0) ); + return pDataS[s] + sfrac * (pDataS[s+1] - pDataS[s]); + } + if ( Vec_FltSize(&p->vIndex0) == 1 && Vec_FltSize(&p->vIndex1) > 1 ) + { + pIndex1 = Vec_FltArray(&p->vIndex1); + for ( l = 1; l < Vec_FltSize(&p->vIndex1)-1; l++ ) + if ( pIndex1[l] > load ) + break; + l--; + if ( pIndex1[l+1] == pIndex1[l] ) + return 0; + lfrac = (load - pIndex1[l]) / (pIndex1[l+1] - pIndex1[l]); + if ( Vec_PtrSize(&p->vData) != 1 ) + return 0; + if ( Vec_FltSize((Vec_Flt_t *)Vec_PtrEntry(&p->vData, 0)) != Vec_FltSize(&p->vIndex1) ) + return 0; + pDataS = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(&p->vData, 0) ); + return pDataS[l] + lfrac * (pDataS[l+1] - pDataS[l]); + } + if ( Vec_PtrSize(&p->vData) != Vec_FltSize(&p->vIndex0) ) + return 0; + if ( Vec_FltSize(&p->vIndex0) < 2 || Vec_FltSize(&p->vIndex1) < 2 ) + return 0; // Find closest sample points in surface: pIndex0 = Vec_FltArray(&p->vIndex0); @@ -512,9 +570,14 @@ static inline float Scl_LibLookup( SC_Surface * p, float slew, float load ) l--; // Interpolate (or extrapolate) function value from sample points: + if ( pIndex0[s+1] == pIndex0[s] || pIndex1[l+1] == pIndex1[l] ) + return 0; sfrac = (slew - pIndex0[s]) / (pIndex0[s+1] - pIndex0[s]); lfrac = (load - pIndex1[l]) / (pIndex1[l+1] - pIndex1[l]); + if ( Vec_FltSize((Vec_Flt_t *)Vec_PtrEntry(&p->vData, s)) <= l+1 || + Vec_FltSize((Vec_Flt_t *)Vec_PtrEntry(&p->vData, s+1)) <= l+1 ) + return 0; pDataS = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(&p->vData, s) ); pDataS1 = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(&p->vData, s+1) ); @@ -656,19 +719,27 @@ static inline void Scl_LibPinRequiredI( SC_Timing * pTime, SC_PairI * pReqIn, SC SeeAlso [] ***********************************************************************/ -static inline SC_Timing * Scl_CellPinTime( SC_Cell * pCell, int iPin ) +static inline SC_Timing * Scl_CellPinOutTime( SC_Cell * pCell, int iOut, int iPin ) { SC_Pin * pPin; SC_Timings * pRTime; + assert( iOut >= 0 && iOut < pCell->n_outputs ); assert( iPin >= 0 && iPin < pCell->n_inputs ); - pPin = SC_CellPin( pCell, pCell->n_inputs ); - assert( Vec_PtrSize(&pPin->vRTimings) == pCell->n_inputs ); + if ( pCell->n_inputs + iOut >= Vec_PtrSize(&pCell->vPins) ) + return NULL; + pPin = SC_CellPin( pCell, pCell->n_inputs + iOut ); + if ( iPin >= Vec_PtrSize(&pPin->vRTimings) ) + return NULL; pRTime = (SC_Timings *)Vec_PtrEntry( &pPin->vRTimings, iPin ); if ( Vec_PtrSize(&pRTime->vTimings) == 0 ) return NULL; assert( Vec_PtrSize(&pRTime->vTimings) == 1 ); return (SC_Timing *)Vec_PtrEntry( &pRTime->vTimings, 0 ); } +static inline SC_Timing * Scl_CellPinTime( SC_Cell * pCell, int iPin ) +{ + return Scl_CellPinOutTime( pCell, 0, iPin ); +} static inline float Scl_LibPinArrivalEstimate( SC_Cell * pCell, int iPin, float Slew, float Load ) { SC_Pair LoadIn = { Load, Load }; diff --git a/src/map/scl/sclLibScl.c b/src/map/scl/sclLibScl.c index 18a4b8a57a..42dd6b78e6 100644 --- a/src/map/scl/sclLibScl.c +++ b/src/map/scl/sclLibScl.c @@ -89,6 +89,7 @@ static int Abc_SclReadLibraryGenlib( SC_Lib * p, Mio_Library_t * pLib ) p->unit_time = 12; p->unit_cap_fst = 1.0; p->unit_cap_snd = 15; + p->nom_voltage = 1.0; Mio_LibraryForEachGate( pLib, pGate ) { @@ -251,6 +252,7 @@ static int Abc_SclReadLibrary( Vec_Str_t * vOut, int * pPos, SC_Lib * p ) p->unit_time = Vec_StrGetI(vOut, pPos); p->unit_cap_fst = Vec_StrGetF(vOut, pPos); p->unit_cap_snd = Vec_StrGetI(vOut, pPos); + p->nom_voltage = Vec_StrGetF(vOut, pPos); // Read 'wire_load' vector: for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) @@ -392,6 +394,8 @@ static int Abc_SclReadLibrary( Vec_Str_t * vOut, int * pPos, SC_Lib * p ) Abc_SclReadSurface( vOut, pPos, &pTime->pCellFall ); Abc_SclReadSurface( vOut, pPos, &pTime->pRiseTrans ); Abc_SclReadSurface( vOut, pPos, &pTime->pFallTrans ); + Abc_SclReadSurface( vOut, pPos, &pTime->pRisePower ); + Abc_SclReadSurface( vOut, pPos, &pTime->pFallPower ); } else assert( Vec_PtrSize(&pRTime->vTimings) == 0 ); @@ -554,6 +558,8 @@ static void Abc_SclWriteLibraryCellsOnly( Vec_Str_t * vOut, SC_Lib * p, int fAdd Abc_SclWriteSurface( vOut, &pTime->pCellFall ); Abc_SclWriteSurface( vOut, &pTime->pRiseTrans ); Abc_SclWriteSurface( vOut, &pTime->pFallTrans ); + Abc_SclWriteSurface( vOut, &pTime->pRisePower ); + Abc_SclWriteSurface( vOut, &pTime->pFallPower ); } else assert( Vec_PtrSize(&pRTime->vTimings) == 0 ); @@ -590,6 +596,7 @@ static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p, int nExtra, int f Vec_StrPutI( vOut, p->unit_time ); Vec_StrPutF( vOut, p->unit_cap_fst ); Vec_StrPutI( vOut, p->unit_cap_snd ); + Vec_StrPutF( vOut, p->nom_voltage ); // Write 'wire_load' vector: Vec_StrPutI( vOut, Vec_PtrSize(&p->vWireLoads) ); @@ -731,6 +738,7 @@ static void Abc_SclWriteLibraryText( FILE * s, SC_Lib * p ) else if ( p->unit_time == 12 ) fprintf( s, " time_unit : \"1ps\";\n" ); else assert( 0 ); + fprintf( s, " nom_voltage : %f;\n", p->nom_voltage ); fprintf( s, " capacitive_load_unit(%.1f,%s);\n", p->unit_cap_fst, p->unit_cap_snd == 12 ? "pf" : "ff" ); fprintf( s, "\n" ); @@ -831,6 +839,19 @@ static void Abc_SclWriteLibraryText( FILE * s, SC_Lib * p ) fprintf( s, " fall_transition() {\n" ); Abc_SclWriteSurfaceText( s, &pTime->pFallTrans ); fprintf( s, " }\n" ); + + if ( Vec_FltSize(&pTime->pRisePower.vIndex0) ) + { + fprintf( s, " rise_power() {\n" ); + Abc_SclWriteSurfaceText( s, &pTime->pRisePower ); + fprintf( s, " }\n" ); + } + if ( Vec_FltSize(&pTime->pFallPower.vIndex0) ) + { + fprintf( s, " fall_power() {\n" ); + Abc_SclWriteSurfaceText( s, &pTime->pFallPower ); + fprintf( s, " }\n" ); + } fprintf( s, " }\n" ); } else @@ -887,4 +908,3 @@ SC_Lib * Abc_SclMergeLibraries( SC_Lib * pLib1, SC_Lib * pLib2, int fUsePrefix ) ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclLibUtil.c b/src/map/scl/sclLibUtil.c index 4115143c38..e132b73417 100644 --- a/src/map/scl/sclLibUtil.c +++ b/src/map/scl/sclLibUtil.c @@ -747,6 +747,14 @@ void Abc_SclLibNormalizeSurface( SC_Surface * p, float Time, float Load ) Vec_FltForEachEntry( vArray, Entry, i ) // delay/slew Vec_FltWriteEntry( vArray, i, Time * Entry ); } +void Abc_SclLibNormalizeSurfaceIndex( SC_Surface * p, float Time, float Load ) +{ + int i; float Entry; + Vec_FltForEachEntry( &p->vIndex0, Entry, i ) // slew + Vec_FltWriteEntry( &p->vIndex0, i, Time * Entry ); + Vec_FltForEachEntry( &p->vIndex1, Entry, i ) // load + Vec_FltWriteEntry( &p->vIndex1, i, Load * Entry ); +} void Abc_SclLibNormalize( SC_Lib * p ) { SC_WireLoad * pWL; @@ -780,6 +788,8 @@ void Abc_SclLibNormalize( SC_Lib * p ) Abc_SclLibNormalizeSurface( &pTiming->pCellFall, Time, Load ); Abc_SclLibNormalizeSurface( &pTiming->pRiseTrans, Time, Load ); Abc_SclLibNormalizeSurface( &pTiming->pFallTrans, Time, Load ); + Abc_SclLibNormalizeSurfaceIndex( &pTiming->pRisePower, Time, Load ); + Abc_SclLibNormalizeSurfaceIndex( &pTiming->pFallPower, Time, Load ); } } } @@ -1134,4 +1144,3 @@ void Abc_SclInstallGenlib( void * pScl, float SlewInit, float Gain, int fUseAll, ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclLiberty.c b/src/map/scl/sclLiberty.c index 06d40c84bf..98d5e2ab35 100644 --- a/src/map/scl/sclLiberty.c +++ b/src/map/scl/sclLiberty.c @@ -935,6 +935,19 @@ int Scl_LibertyReadTimeUnit( Scl_Tree_t * p ) printf( "Liberty parser cannot read \"time_unit\". Assuming time_unit : \"1ns\".\n" ); return 9; } +float Scl_LibertyReadNomVoltage( Scl_Tree_t * p ) +{ + Scl_Item_t * pItem; + Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "nom_voltage" ) + return atof(Scl_LibertyReadString(p, pItem->Head)); + Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "operating_conditions" ) + { + Scl_Item_t * pChild; + Scl_ItemForEachChildName( p, pItem, pChild, "voltage" ) + return atof(Scl_LibertyReadString(p, pChild->Head)); + } + return 1.0; +} void Scl_LibertyReadLoadUnit( Scl_Tree_t * p, Vec_Str_t * vOut ) { Scl_Item_t * pItem; @@ -1116,6 +1129,24 @@ void Scl_LibertyDumpTables( Vec_Str_t * vOut, Vec_Flt_t * vInd1, Vec_Flt_t * vIn } // dump approximations Vec_StrPut_( vOut ); + for ( i = 0; i < 3; i++ ) + Vec_StrPutF_( vOut, 0 ); + for ( i = 0; i < 4; i++ ) + Vec_StrPutF_( vOut, 0 ); + for ( i = 0; i < 6; i++ ) + Vec_StrPutF_( vOut, 0 ); + Vec_StrPut_( vOut ); + Vec_StrPut_( vOut ); +} +void Scl_LibertyDumpEmptyTable( Vec_Str_t * vOut ) +{ + int i; + Vec_StrPutI_( vOut, 0 ); + Vec_StrPut_( vOut ); + Vec_StrPutI_( vOut, 0 ); + Vec_StrPut_( vOut ); + Vec_StrPut_( vOut ); + Vec_StrPut_( vOut ); for ( i = 0; i < 3; i++ ) Vec_StrPutF_( vOut, 0 ); for ( i = 0; i < 4; i++ ) @@ -1206,6 +1237,19 @@ int Scl_LibertyScanTable( Scl_Tree_t * p, Vec_Ptr_t * vOut, Scl_Item_t * pTiming // check the template style vInd1 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 2 ); // slew vInd2 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 3 ); // load + if ( vInd2 == NULL ) + { + assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd1) ); + vInd1 = vIndex1 ? vIndex1 : vInd1; + vInd2 = Vec_FltAlloc( 1 ); + Vec_FltPush( vInd2, 0 ); + assert( Vec_FltSize(vInd1) == Vec_FltSize(vValues) ); + // write entries + Vec_PtrPush( vOut, Vec_FltDup(vInd1) ); + Vec_PtrPush( vOut, vInd2 ); + Vec_PtrPush( vOut, Vec_FltDup(vValues) ); + } + else if ( Vec_PtrEntry(vTemples, iPlace + 1) == NULL ) // normal order (vIndex1 is slew; vIndex2 is load) { assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd1) ); @@ -1287,6 +1331,43 @@ int Scl_LibertyComputeWorstCase( Vec_Ptr_t * vTables, Vec_Flt_t ** pvInd0, Vec_F *pvValues = vValues; return 1; } +Vec_Ptr_t * Scl_LibertyReadPinPowerAll( Scl_Tree_t * p, Scl_Item_t * pPinOut, char * pNameIn ) +{ + Vec_Ptr_t * vPowers = Vec_PtrAlloc( 4 ); + Scl_Item_t * pPower, * pPinIn; + Scl_ItemForEachChildName( p, pPinOut, pPower, "internal_power" ) + Scl_ItemForEachChildName( p, pPower, pPinIn, "related_pin" ) + if ( !strcmp(Scl_LibertyReadString(p, pPinIn->Head), pNameIn) ) + Vec_PtrPush( vPowers, pPower ); + return vPowers; +} +void Scl_LibertyWritePowerTable( Scl_Tree_t * p, Vec_Str_t * vOut, Vec_Ptr_t * vPowers, char * pName1, char * pName2, Vec_Ptr_t * vTemples ) +{ + Scl_Item_t * pPower; + Vec_Ptr_t * vTables = Vec_PtrAlloc( 16 ); + Vec_Flt_t * vInd0, * vInd1, * vValues; + int i; + Vec_PtrForEachEntry( Scl_Item_t *, vPowers, pPower, i ) + if ( !Scl_LibertyScanTable( p, vTables, pPower, pName1, vTemples ) && pName2 ) + Scl_LibertyScanTable( p, vTables, pPower, pName2, vTemples ); + if ( Vec_PtrSize(vTables) == 0 ) + { + Vec_PtrFree( vTables ); + Scl_LibertyDumpEmptyTable( vOut ); + return; + } + if ( !Scl_LibertyComputeWorstCase( vTables, &vInd0, &vInd1, &vValues ) ) + { + Vec_VecFree( (Vec_Vec_t *)vTables ); + Scl_LibertyDumpEmptyTable( vOut ); + return; + } + Vec_VecFree( (Vec_Vec_t *)vTables ); + Scl_LibertyDumpTables( vOut, vInd0, vInd1, vValues ); + Vec_FltFree( vInd0 ); + Vec_FltFree( vInd1 ); + Vec_FltFree( vValues ); +} int Scl_LibertyReadTable( Scl_Tree_t * p, Vec_Str_t * vOut, Scl_Item_t * pTiming, char * pName, Vec_Ptr_t * vTemples ) { @@ -1460,10 +1541,12 @@ Vec_Ptr_t * Scl_LibertyReadTemplates( Scl_Tree_t * p ) Vec_Flt_t * vIndex1, * vIndex2; Scl_Item_t * pTempl, * pItem; char * pVar1, * pVar2; - int fFlag0, fFlag1; + int fFlag0, fFlag1, fVar1Slew, fVar2Slew; vRes = Vec_PtrAlloc( 100 ); - Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pTempl, "lu_table_template" ) + Scl_ItemForEachChild( p, Scl_LibertyRoot(p), pTempl ) { + if ( Scl_LibertyCompare(p, pTempl->Key, "lu_table_template") && Scl_LibertyCompare(p, pTempl->Key, "power_lut_template") ) + continue; pVar1 = pVar2 = NULL; vIndex1 = vIndex2 = NULL; Scl_ItemForEachChild( p, pTempl, pItem ) @@ -1477,7 +1560,7 @@ Vec_Ptr_t * Scl_LibertyReadTemplates( Scl_Tree_t * p ) else if ( !Scl_LibertyCompare(p, pItem->Key, "variable_2") ) assert(pVar2 == NULL), pVar2 = Abc_UtilStrsav( Scl_LibertyReadString(p, pItem->Head) ); } - if ( pVar1 == NULL || pVar2 == NULL ) + if ( pVar1 == NULL ) { ABC_FREE( pVar1 ); ABC_FREE( pVar2 ); @@ -1485,9 +1568,11 @@ Vec_Ptr_t * Scl_LibertyReadTemplates( Scl_Tree_t * p ) Vec_FltFreeP( &vIndex2 ); continue; } - assert( pVar1 != NULL && pVar2 != NULL ); - fFlag0 = (!strcmp(pVar1, "input_net_transition") && !strcmp(pVar2, "total_output_net_capacitance")); - fFlag1 = (!strcmp(pVar2, "input_net_transition") && !strcmp(pVar1, "total_output_net_capacitance")); + assert( pVar1 != NULL ); + fVar1Slew = !strcmp(pVar1, "input_net_transition") || !strcmp(pVar1, "input_transition_time") || !strcmp(pVar1, "related_pin_transition"); + fVar2Slew = pVar2 && (!strcmp(pVar2, "input_net_transition") || !strcmp(pVar2, "input_transition_time") || !strcmp(pVar2, "related_pin_transition")); + fFlag0 = fVar1Slew && (pVar2 == NULL || !strcmp(pVar2, "total_output_net_capacitance")); + fFlag1 = fVar2Slew && !strcmp(pVar1, "total_output_net_capacitance"); ABC_FREE( pVar1 ); ABC_FREE( pVar2 ); if ( !fFlag0 && !fFlag1 ) @@ -1534,6 +1619,7 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos Vec_StrPutF_( vOut, Scl_LibertyReadDefaultMaxTrans(p) ); Vec_StrPutI_( vOut, Scl_LibertyReadTimeUnit(p) ); Scl_LibertyReadLoadUnit( p, vOut ); + Vec_StrPutF_( vOut, Scl_LibertyReadNomVoltage(p) ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); @@ -1668,6 +1754,7 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos { Vec_PtrForEachEntry( char *, vNameIns, pName, i ) { + Vec_Ptr_t * vPowers; pTiming = Scl_LibertyReadPinTiming( p, pPin, pName ); Vec_StrPutS_( vOut, pName ); Vec_StrPutI_( vOut, (int)(pTiming != NULL) ); @@ -1689,6 +1776,10 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos if ( !Scl_LibertyReadTable( p, vOut, pTiming, "fall_transition", vTemples ) ) if ( !Scl_LibertyReadTable( p, vOut, pTiming, "rise_transition", vTemples ) ) { printf( "Table cannot be found\n" ); return NULL; } + vPowers = Scl_LibertyReadPinPowerAll( p, pPin, pName ); + Scl_LibertyWritePowerTable( p, vOut, vPowers, "rise_power", "power", vTemples ); + Scl_LibertyWritePowerTable( p, vOut, vPowers, "fall_power", "power", vTemples ); + Vec_PtrFree( vPowers ); } continue; } @@ -1697,7 +1788,7 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos Vec_PtrForEachEntry( char *, vNameIns, pName, i ) { Vec_Ptr_t * vTables[4]; - Vec_Ptr_t * vTimings; + Vec_Ptr_t * vTimings, * vPowers; vTimings = Scl_LibertyReadPinTimingAll( p, pPin, pName ); Vec_StrPutS_( vOut, pName ); Vec_StrPutI_( vOut, (int)(Vec_PtrSize(vTimings) != 0) ); @@ -1741,6 +1832,10 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos Vec_FltFree( vInd1 ); Vec_FltFree( vValues ); } + vPowers = Scl_LibertyReadPinPowerAll( p, pPin, pName ); + Scl_LibertyWritePowerTable( p, vOut, vPowers, "rise_power", "power", vTemples ); + Scl_LibertyWritePowerTable( p, vOut, vPowers, "fall_power", "power", vTemples ); + Vec_PtrFree( vPowers ); } } Vec_StrPut_( vOut ); @@ -1834,4 +1929,3 @@ void Scl_LibertyTest() ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclSize.c b/src/map/scl/sclSize.c index bf2a40090c..a2ba65ee9f 100644 --- a/src/map/scl/sclSize.c +++ b/src/map/scl/sclSize.c @@ -103,6 +103,35 @@ Abc_Obj_t * Abc_SclFindMostCriticalFanin( SC_Man * p, int * pfRise, Abc_Obj_t * return pPivot; } +/**Function************************************************************* + + Synopsis [Find the output pin represented by this mapped node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_SclObjOutputIndex( Abc_Obj_t * pObj, SC_Cell * pCell ) +{ + Mio_Gate_t * pGate; + char * pOutName; + int i; + if ( pCell->n_outputs == 1 ) + return 0; + pGate = (Mio_Gate_t *)pObj->pData; + assert( pGate != NULL ); + pOutName = Mio_GateReadOutName( pGate ); + assert( pOutName != NULL ); + for ( i = 0; i < pCell->n_outputs; i++ ) + if ( !strcmp( pOutName, SC_CellPinName(pCell, pCell->n_inputs + i) ) ) + return i; + assert( 0 ); + return 0; +} + /**Function************************************************************* Synopsis [Printing timing information for the node/network.] @@ -299,10 +328,20 @@ static inline void Abc_SclDeptObj( SC_Man * p, Abc_Obj_t * pObj ) SC_PairClean( Abc_SclObjDept(p, pObj) ); Abc_ObjForEachFanout( pObj, pFanout, i ) { + SC_Cell * pFanoutCell; + int iFanin, iOut; 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_NodeFindFanin(pFanout, pObj) ); + pFanoutCell = Abc_SclObjCell( pFanout ); + iFanin = Abc_NodeFindFanin( pFanout, pObj ); + iOut = Abc_SclObjOutputIndex( pFanout, pFanoutCell ); + pTime = Scl_CellPinOutTime( pFanoutCell, iOut, iFanin ); + if ( pTime == NULL ) + { + assert( pFanoutCell->n_outputs > 1 ); + continue; + } + Abc_SclDeptFanin( p, pTime, pFanout, pObj, iFanin ); } } static inline float Abc_SclObjLoadValue( SC_Man * p, Abc_Obj_t * pObj ) @@ -370,7 +409,13 @@ void Abc_SclTimeNode( SC_Man * p, Abc_Obj_t * pObj, int fDept ) // compute for each fanin Abc_ObjForEachFanin( pObj, pFanin, k ) { - pTime = Scl_CellPinTime( pCell, k ); + int iOut = Abc_SclObjOutputIndex( pObj, pCell ); + pTime = Scl_CellPinOutTime( pCell, iOut, k ); + if ( pTime == NULL ) + { + assert( pCell->n_outputs > 1 ); + continue; + } if ( fDept ) Abc_SclDeptFanin( p, pTime, pObj, pFanin, k ); else @@ -714,6 +759,92 @@ void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int f Abc_NtkDelete( pNtkNew ); } +/**Function************************************************************* + + Synopsis [Printing out power information for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Abc_SclPowerTableLookup( SC_Surface * p, float Slew, float Load ) +{ + Vec_Flt_t * vRow; + int i, nSize0 = Vec_FltSize(&p->vIndex0); + int nSize1 = Vec_FltSize(&p->vIndex1); + if ( nSize0 == 0 || nSize1 == 0 || Vec_PtrSize(&p->vData) != nSize0 ) + return 0; + Vec_PtrForEachEntry( Vec_Flt_t *, &p->vData, vRow, i ) + if ( Vec_FltSize(vRow) != nSize1 ) + return 0; + return Scl_LibLookup( p, Slew, Load ); +} +void Abc_SclPowerPerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int nFrames, int nPref ) +{ + SC_Man * p; + Vec_Flt_t * vSwitching; + Abc_Obj_t * pObj, * pFanin; + double StaticPower = 0, InternalPower = 0, ExternalPower = 0, DynamicPower = 0; + double TotalPower, TotalPowerAbs; + int i, k, nPowerArcs = 0; + p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 0, 0, nTreeCRatio ); + vSwitching = Abc_SclComputeSwitching( pNtk, nFrames, nPref ); + Abc_NtkForEachNodeNotBarBuf1( pNtk, pObj, i ) + { + SC_Cell * pCell = Abc_SclObjCell( pObj ); + int iOut = Abc_SclObjOutputIndex( pObj, pCell ); + if ( !Abc_SclObjIsSecondTwin(pObj) ) + StaticPower += pCell->leakage; + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + SC_Timing * pTime = Scl_CellPinOutTime( pCell, iOut, k ); + SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); + SC_Pair * pSlew = Abc_SclObjSlew( p, pFanin ); + float Switch = Vec_FltEntry( vSwitching, Abc_ObjId(pFanin) ); + float RisePower, FallPower; + if ( pTime == NULL ) + { + assert( pCell->n_outputs > 1 ); + continue; + } + RisePower = Abc_SclPowerTableLookup( &pTime->pRisePower, pSlew->rise, pLoad->rise ); + FallPower = Abc_SclPowerTableLookup( &pTime->pFallPower, pSlew->fall, pLoad->fall ); + RisePower = Abc_MaxFloat( 0, RisePower ); + FallPower = Abc_MaxFloat( 0, FallPower ); + if ( RisePower == 0 && FallPower == 0 ) + continue; + InternalPower += Switch * 0.5 * (RisePower + FallPower); + nPowerArcs++; + } + ExternalPower += Vec_FltEntry( vSwitching, Abc_ObjId(pObj) ) * 0.5 * Abc_SclObjLoadAve(p, pObj) * pLib->nom_voltage * pLib->nom_voltage; + } + DynamicPower = InternalPower + ExternalPower; + TotalPower = StaticPower + DynamicPower; + TotalPowerAbs = fabs(StaticPower) + fabs(DynamicPower); + Abc_Print( 1, "WireLoad = \"%s\" ", p->pWLoadUsed ? p->pWLoadUsed->pName : "none" ); + Abc_Print( 1, "Frames = %d Prefix = %d ", nFrames, nPref ); + Abc_Print( 1, "Power = %.6g ", TotalPower ); + Abc_Print( 1, "Static = %.6g (%5.1f %%) ", StaticPower, 100.0 * StaticPower / Abc_MaxDouble(1.0, TotalPowerAbs) ); + Abc_Print( 1, "Dynamic = %.6g (%5.1f %%) ", DynamicPower, 100.0 * DynamicPower / Abc_MaxDouble(1.0, TotalPowerAbs) ); + Abc_Print( 1, "Internal = %.6g ", InternalPower ); + Abc_Print( 1, "External = %.6g ", ExternalPower ); + Abc_Print( 1, "Arcs = %d\n", nPowerArcs ); + Vec_FltFree( vSwitching ); + Abc_SclManFree( p ); +} +void Abc_SclPowerPerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int nFrames, int nPref ) +{ + Abc_Ntk_t * pNtkNew = pNtk; + if ( pNtk->nBarBufs2 > 0 ) + pNtkNew = Abc_NtkDupDfsNoBarBufs( pNtk ); + Abc_SclPowerPerformInt( pLib, pNtkNew, nTreeCRatio, fUseWireLoads, nFrames, nPref ); + if ( pNtk->nBarBufs2 > 0 ) + Abc_NtkDelete( pNtkNew ); +} + /**Function************************************************************* @@ -927,5 +1058,3 @@ void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose ) ABC_NAMESPACE_IMPL_END - - diff --git a/src/map/scl/sclSize.h b/src/map/scl/sclSize.h index 133ae6647b..8466469c42 100644 --- a/src/map/scl/sclSize.h +++ b/src/map/scl/sclSize.h @@ -27,6 +27,7 @@ //////////////////////////////////////////////////////////////////////// #include "base/abc/abc.h" +#include "map/mio/mio.h" #include "misc/vec/vecQue.h" #include "misc/vec/vecWec.h" #include "sclLib.h" @@ -130,6 +131,64 @@ static inline float Abc_SclObjInDrive( SC_Man * p, Abc_Obj_t * pObj ) 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; } +static inline int Abc_SclObjsHaveSameFanins( Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 ) +{ + Abc_Obj_t * pFanin0, * pFanin1; + int i; + if ( pObj0 == NULL || pObj1 == NULL || Abc_ObjFaninNum(pObj0) != Abc_ObjFaninNum(pObj1) ) + return 0; + Abc_ObjForEachFanin( pObj0, pFanin0, i ) + { + pFanin1 = Abc_ObjFanin( pObj1, i ); + if ( pFanin0 != pFanin1 ) + return 0; + } + return 1; +} +static inline int Abc_SclObjIsMogOutput( Abc_Obj_t * pObj ) +{ + Mio_Gate_t * pGate; + if ( pObj == NULL || !Abc_ObjIsNode(pObj) ) + return 0; + pGate = (Mio_Gate_t *)pObj->pData; + return pGate != NULL && Mio_GateReadTwin(pGate) != NULL; +} +static inline int Abc_SclObjIsSecondTwin( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pPrev; + Mio_Gate_t * pGate; + if ( !Abc_SclObjIsMogOutput(pObj) || Abc_ObjId(pObj) == 0 ) + return 0; + pPrev = Abc_NtkObj( pObj->pNtk, Abc_ObjId(pObj) - 1 ); + if ( pPrev == NULL || !Abc_ObjIsNode(pPrev) ) + return 0; + pGate = (Mio_Gate_t *)pObj->pData; + if ( Mio_GateReadTwin(pGate) != (Mio_Gate_t *)pPrev->pData ) + return 0; + return Abc_SclObjsHaveSameFanins( pObj, pPrev ); +} +static inline Abc_Obj_t * Abc_SclObjTwin( Abc_Obj_t * pObj ) +{ + if ( Abc_SclObjIsSecondTwin(pObj) ) + return Abc_NtkObj( pObj->pNtk, Abc_ObjId(pObj) - 1 ); + return Abc_NtkFetchTwinNode( pObj ); +} +static inline int Abc_SclObjTwinFaninsMatch( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pTwin = Abc_SclObjTwin( pObj ); + return pTwin != NULL && Abc_SclObjsHaveSameFanins( pObj, pTwin ); +} +static inline int Abc_SclObjIsCanonicalMog( Abc_Obj_t * pObj ) +{ + return Abc_SclObjIsMogOutput(pObj) && !Abc_SclObjIsSecondTwin(pObj); +} +static inline float Abc_SclObjAreaDelta( Abc_Obj_t * pObj, SC_Cell * pCellOld, SC_Cell * pCellNew ) +{ + if ( Abc_SclObjIsSecondTwin(pObj) ) + return 0.0; + return pCellNew->area - pCellOld->area; +} + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -450,7 +509,11 @@ static inline float Abc_SclGetTotalArea( Abc_Ntk_t * pNtk ) Abc_Obj_t * pObj; int i; Abc_NtkForEachNodeNotBarBuf1( pNtk, pObj, i ) + { + if ( Abc_SclObjIsSecondTwin(pObj) ) + continue; Area += Abc_SclObjCell(pObj)->area; + } return Area; } static inline float Abc_SclGetMaxDelay( SC_Man * p ) @@ -571,6 +634,7 @@ extern int Abc_SclTimeIncUpdate( SC_Man * p ); extern void Abc_SclTimeIncInsert( SC_Man * p, Abc_Obj_t * pObj ); extern void Abc_SclTimeIncUpdateLevel( Abc_Obj_t * pObj ); extern void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int fShowAll, int fPrintPath, int fDumpStats ); +extern void Abc_SclPowerPerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int nFrames, int nPref ); extern void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose ); /*=== sclUpsize.c ===============================================================*/ extern int Abc_SclCountNearCriticalNodes( SC_Man * p ); @@ -582,6 +646,7 @@ extern void Abc_SclTransferGates( Abc_Ntk_t * pOld, Abc_Ntk_t * pNew ); extern void Abc_SclPrintGateSizes( SC_Lib * pLib, Abc_Ntk_t * p ); extern void Abc_SclMinsizePerform( SC_Lib * pLib, Abc_Ntk_t * p, int fUseMax, int fVerbose ); extern int Abc_SclCountMinSize( SC_Lib * pLib, Abc_Ntk_t * p, int fUseMax ); +extern Vec_Flt_t * Abc_SclComputeSwitching( Abc_Ntk_t * pNtk, int nFrames, int nPref ); extern Vec_Int_t * Abc_SclExtractBarBufs( Abc_Ntk_t * pNtk ); extern void Abc_SclInsertBarBufs( Abc_Ntk_t * pNtk, Vec_Int_t * vBufs ); diff --git a/src/map/scl/sclUpsize.c b/src/map/scl/sclUpsize.c index 822278a338..fbc3290af0 100644 --- a/src/map/scl/sclUpsize.c +++ b/src/map/scl/sclUpsize.c @@ -489,7 +489,7 @@ int Abc_SclFindBypasses( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notc // update cell pCellOld = Abc_SclObjCell( pFanin ); pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(p->vNode2Gate, iNode) ); - p->SumArea += pCellNew->area - pCellOld->area; + p->SumArea += Abc_SclObjAreaDelta( pFanin, pCellOld, pCellNew ); Abc_SclObjSetCell( pFanin, pCellNew ); Abc_SclUpdateLoad( p, pFanin, pCellOld, pCellNew ); // record the update @@ -646,7 +646,7 @@ int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notch //printf( "gain is %f\n", Vec_FltEntry(p->vNode2Gain, Abc_ObjId(pObj)) ); // update gate Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); - p->SumArea += pCellNew->area - pCellOld->area; + p->SumArea += Abc_SclObjAreaDelta( pObj, pCellOld, pCellNew ); Abc_SclObjSetCell( pObj, pCellNew ); // record the update Vec_IntPush( p->vUpdates, Abc_ObjId(pObj) ); @@ -686,7 +686,7 @@ return Limit; // if ( pCellOld->Order > 0 ) // printf( "%.2f %d -> %d(%d) ", Vec_FltEntry(p->vNode2Gain, iNode), pCellOld->Order, pCellNew->Order, pCellNew->nGates ); // update gate - p->SumArea += pCellNew->area - pCellOld->area; + p->SumArea += Abc_SclObjAreaDelta( pObj, pCellOld, pCellNew ); Abc_SclObjSetCell( pObj, pCellNew ); Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); // record the update @@ -1043,4 +1043,3 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclUtil.c b/src/map/scl/sclUtil.c index 0deb0f0fdf..8d56148f23 100644 --- a/src/map/scl/sclUtil.c +++ b/src/map/scl/sclUtil.c @@ -21,6 +21,7 @@ #include "sclSize.h" #include "map/mio/mio.h" #include "base/main/main.h" +#include "aig/aig/aig.h" ABC_NAMESPACE_IMPL_START @@ -75,9 +76,11 @@ void Abc_SclSclGates2MioGates( SC_Lib * pLib, Abc_Ntk_t * p ) assert( p->vGates != NULL ); Abc_NtkForEachNodeNotBarBuf1( p, pObj, i ) { + Mio_Gate_t * pGateOld = (Mio_Gate_t *)pObj->pData; + char * pOutName = Abc_SclObjIsMogOutput(pObj) ? Mio_GateReadOutName(pGateOld) : NULL; pCell = Abc_SclObjCell(pObj); assert( pCell->n_inputs == Abc_ObjFaninNum(pObj) ); - pObj->pData = Mio_LibraryReadGateByName( (Mio_Library_t *)p->pManFunc, pCell->pName, NULL ); + pObj->pData = Mio_LibraryReadGateByName( (Mio_Library_t *)p->pManFunc, pCell->pName, pOutName ); Counter += (pObj->pData == NULL); assert( pObj->fMarkA == 0 && pObj->fMarkB == 0 ); CounterAll++; @@ -273,6 +276,81 @@ void Abc_SclReadTimingConstr( Abc_Frame_t * pAbc, char * pFileName, int fVerbose fclose( pFile ); } +/**Function************************************************************* + + Synopsis [Computes switching activity for each object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Flt_t * Abc_SclComputeSwitching( Abc_Ntk_t * pNtk, int nFrames, int nPref ) +{ + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); + Vec_Int_t * vSwitching = NULL; + Vec_Flt_t * vResult; + float * pSwitching, * pResult; + Abc_Ntk_t * pNtkDup = NULL, * pNtkStr = NULL; + Aig_Man_t * pAig = NULL; + Aig_Obj_t * pObjAig; + Abc_Obj_t * pObj, * pObjDup, * pObjStr; + int i; + vResult = Vec_FltStart( Abc_NtkObjNumMax(pNtk) ); + pResult = Vec_FltArray(vResult); + pNtkDup = Abc_NtkDup( pNtk ); + if ( pNtkDup == NULL ) + goto cleanup; + // strash the duplicated network + pNtkStr = Abc_NtkStrash( pNtkDup, 0, 1, 0 ); + if ( pNtkStr == NULL ) + goto cleanup; + Abc_NtkForEachObj( pNtkDup, pObj, i ) + if ( (pObj->pTemp && Abc_ObjRegular((Abc_Obj_t *)pObj->pTemp)->Type == ABC_FUNC_NONE) || (!Abc_ObjIsCi(pObj) && !Abc_ObjIsNode(pObj)) ) + pObj->pTemp = NULL; + // map network into an AIG + pAig = Abc_NtkToDar( pNtkStr, 0, (int)(Abc_NtkLatchNum(pNtkDup) > 0) ); + if ( pAig == NULL ) + goto cleanup; + vSwitching = Saig_ManComputeSwitchProbs( pAig, nFrames, nPref, 0 ); + if ( vSwitching == NULL ) + goto cleanup; + pSwitching = (float *)Vec_IntArray(vSwitching); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + pObjDup = (Abc_Obj_t *)pObj->pCopy; + if ( pObjDup == NULL ) + continue; + if ( pObjDup->pTemp == NULL ) + continue; + pObjStr = Abc_ObjRegular((Abc_Obj_t *)pObjDup->pTemp); + if ( pObjStr == NULL ) + continue; + if ( pObjStr->pTemp == NULL ) + continue; + pObjAig = Aig_Regular((Aig_Obj_t *)pObjStr->pTemp); + if ( pObjAig == NULL ) + continue; + pResult[pObj->Id] = pSwitching[pObjAig->Id]; + } +cleanup: + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pCopy = NULL; + pNtk->pCopy = NULL; + if ( vSwitching ) + Vec_IntFree( vSwitching ); + if ( pAig ) + Aig_ManStop( pAig ); + if ( pNtkStr ) + Abc_NtkDelete( pNtkStr ); + if ( pNtkDup ) + Abc_NtkDelete( pNtkDup ); + return vResult; +} + /**Function************************************************************* Synopsis [] @@ -317,4 +395,3 @@ void Abc_SclInsertBarBufs( Abc_Ntk_t * pNtk, Vec_Int_t * vBufs ) ABC_NAMESPACE_IMPL_END - diff --git a/src/misc/bzlib/blocksort.c b/src/misc/bzlib/blocksort.c index 0dc4ff461d..0921a3c377 100644 --- a/src/misc/bzlib/blocksort.c +++ b/src/misc/bzlib/blocksort.c @@ -8,8 +8,8 @@ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. - bzip2/libbzip2 version 1.0.5 of 10 December 2007 - Copyright (C) 1996-2007 Julian Seward + bzip2/libbzip2 version 1.0.8 of 13 July 2019 + Copyright (C) 1996-2019 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. @@ -204,9 +204,9 @@ void fallbackQSort3 ( UInt32* fmap, bhtab [ 0 .. 2+(nblock/32) ] destroyed */ -#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31)) -#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31)) -#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31))) +#define SET_BH(zz) bhtab[(zz) >> 5] |= ((UInt32)1 << ((zz) & 31)) +#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~((UInt32)1 << ((zz) & 31)) +#define ISSET_BH(zz) (bhtab[(zz) >> 5] & ((UInt32)1 << ((zz) & 31))) #define WORD_BH(zz) bhtab[(zz) >> 5] #define UNALIGNED_BH(zz) ((zz) & 0x01f) @@ -276,7 +276,7 @@ void fallbackSort ( UInt32* fmap, r = -1; while (1) { - /*-- find the next non-singleton bucket --*/ + /*-- find the next non-singleton bucket --*/ k = r + 1; while (ISSET_BH(k) && UNALIGNED_BH(k)) k++; if (ISSET_BH(k)) { diff --git a/src/misc/bzlib/bzlib.c b/src/misc/bzlib/bzlib.c index 96c10de64c..5618c76cbb 100644 --- a/src/misc/bzlib/bzlib.c +++ b/src/misc/bzlib/bzlib.c @@ -8,8 +8,8 @@ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. - bzip2/libbzip2 version 1.0.5 of 10 December 2007 - Copyright (C) 1996-2007 Julian Seward + bzip2/libbzip2 version 1.0.8 of 13 July 2019 + Copyright (C) 1996-2019 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. @@ -54,12 +54,12 @@ void BZ2_bz__AssertH__fail ( int errcode ) fprintf(stderr, "\n\nbzip2/libbzip2: internal error number %d.\n" "This is a bug in bzip2/libbzip2, %s.\n" - "Please report it to me at: jseward@bzip.org. If this happened\n" + "Please report it to: bzip2-devel@sourceware.org. If this happened\n" "when you were using some program which uses libbzip2 as a\n" "component, you should also report this bug to the author(s)\n" "of that program. Please make an effort to report this bug;\n" "timely and accurate bug reports eventually lead to higher\n" - "quality software. Thanks. Julian Seward, 10 December 2007.\n\n", + "quality software. Thanks.\n\n", errcode, BZ2_bzlibVersion() ); @@ -436,7 +436,7 @@ int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; } else - if (action == BZ_FLUSH) { + if (action == BZ_FLUSH) { s->avail_in_expect = strm->avail_in; s->mode = BZ_M_FLUSHING; goto preswitch; diff --git a/src/misc/bzlib/bzlib.h b/src/misc/bzlib/bzlib.h index a1bca0bcad..063d9220b1 100644 --- a/src/misc/bzlib/bzlib.h +++ b/src/misc/bzlib/bzlib.h @@ -8,8 +8,8 @@ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. - bzip2/libbzip2 version 1.0.5 of 10 December 2007 - Copyright (C) 1996-2007 Julian Seward + bzip2/libbzip2 version 1.0.8 of 13 July 2019 + Copyright (C) 1996-2019 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. diff --git a/src/misc/bzlib/bzlib_private.h b/src/misc/bzlib/bzlib_private.h index 229ed3863e..c766070f42 100644 --- a/src/misc/bzlib/bzlib_private.h +++ b/src/misc/bzlib/bzlib_private.h @@ -8,8 +8,8 @@ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. - bzip2/libbzip2 version 1.0.5 of 10 December 2007 - Copyright (C) 1996-2007 Julian Seward + bzip2/libbzip2 version 1.0.8 of 13 July 2019 + Copyright (C) 1996-2019 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. @@ -38,7 +38,7 @@ ABC_NAMESPACE_HEADER_START /*-- General stuff. --*/ -#define BZ_VERSION "1.0.5, 10-Dec-2007" +#define BZ_VERSION "1.0.8, 13-Jul-2019" typedef char Char; typedef unsigned char Bool; @@ -483,7 +483,7 @@ typedef /*-- externs for decompression. --*/ -Int32 +extern Int32 BZ2_indexIntoF ( Int32, Int32* ); extern Int32 diff --git a/src/misc/bzlib/compress.c b/src/misc/bzlib/compress.c index d4d5ac9246..70a080f1ab 100644 --- a/src/misc/bzlib/compress.c +++ b/src/misc/bzlib/compress.c @@ -8,8 +8,8 @@ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. - bzip2/libbzip2 version 1.0.5 of 10 December 2007 - Copyright (C) 1996-2007 Julian Seward + bzip2/libbzip2 version 1.0.8 of 13 July 2019 + Copyright (C) 1996-2019 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. @@ -332,14 +332,14 @@ void sendMTFValues ( EState* s ) /*--- Set up an auxiliary length table which is used to fast-track - the common case (nGroups == 6). + the common case (nGroups == 6). ---*/ if (nGroups == 6) { for (v = 0; v < alphaSize; v++) { s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v]; s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v]; s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v]; - } + } } nSelectors = 0; @@ -388,7 +388,7 @@ void sendMTFValues ( EState* s ) cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16; } else { - /*--- slow version which correctly handles all situations ---*/ + /*--- slow version which correctly handles all situations ---*/ for (i = gs; i <= ge; i++) { UInt16 icv = mtfv[i]; for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv]; @@ -429,7 +429,7 @@ void sendMTFValues ( EState* s ) # undef BZ_ITUR } else { - /*--- slow version which correctly handles all situations ---*/ + /*--- slow version which correctly handles all situations ---*/ for (i = gs; i <= ge; i++) s->rfreq[bt][ mtfv[i] ]++; } @@ -457,7 +457,7 @@ void sendMTFValues ( EState* s ) AssertH( nGroups < 8, 3002 ); AssertH( nSelectors < 32768 && - nSelectors <= (2 + (900000 / BZ_G_SIZE)), + nSelectors <= BZ_MAX_SELECTORS, 3003 ); @@ -582,7 +582,7 @@ void sendMTFValues ( EState* s ) # undef BZ_ITAH } else { - /*--- slow version which correctly handles all situations ---*/ + /*--- slow version which correctly handles all situations ---*/ for (i = gs; i <= ge; i++) { bsW ( s, s->len [s->selector[selCtr]] [mtfv[i]], diff --git a/src/misc/bzlib/crctable.c b/src/misc/bzlib/crctable.c index 6e033d0d25..e1476dfdec 100644 --- a/src/misc/bzlib/crctable.c +++ b/src/misc/bzlib/crctable.c @@ -8,8 +8,8 @@ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. - bzip2/libbzip2 version 1.0.5 of 10 December 2007 - Copyright (C) 1996-2007 Julian Seward + bzip2/libbzip2 version 1.0.8 of 13 July 2019 + Copyright (C) 1996-2019 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. diff --git a/src/misc/bzlib/decompress.c b/src/misc/bzlib/decompress.c index 4b7370f1e2..421d7e9c18 100644 --- a/src/misc/bzlib/decompress.c +++ b/src/misc/bzlib/decompress.c @@ -8,8 +8,8 @@ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. - bzip2/libbzip2 version 1.0.5 of 10 December 2007 - Copyright (C) 1996-2007 Julian Seward + bzip2/libbzip2 version 1.0.8 of 13 July 2019 + Copyright (C) 1996-2019 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. @@ -292,7 +292,7 @@ Int32 BZ2_decompress ( DState* s ) /*--- Now the selectors ---*/ GET_BITS(BZ_X_SELECTOR_1, nGroups, 3); - if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR); + if (nGroups < 2 || nGroups > BZ_N_GROUPS) RETURN(BZ_DATA_ERROR); GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15); if (nSelectors < 1) RETURN(BZ_DATA_ERROR); for (i = 0; i < nSelectors; i++) { @@ -303,8 +303,14 @@ Int32 BZ2_decompress ( DState* s ) j++; if (j >= nGroups) RETURN(BZ_DATA_ERROR); } - s->selectorMtf[i] = j; + /* Having more than BZ_MAX_SELECTORS doesn't make much sense + since they will never be used, but some implementations might + "round up" the number of selectors, so just ignore those. */ + if (i < BZ_MAX_SELECTORS) + s->selectorMtf[i] = j; } + if (nSelectors > BZ_MAX_SELECTORS) + nSelectors = BZ_MAX_SELECTORS; /*--- Undo the MTF values for the selectors. ---*/ { @@ -388,6 +394,13 @@ Int32 BZ2_decompress ( DState* s ) es = -1; N = 1; do { + /* Check that N doesn't get too big, so that es doesn't + go negative. The maximum value that can be + RUNA/RUNB encoded is equal to the block size (post + the initial RLE), viz, 900k, so bounding N at 2 + million should guard against overflow without + rejecting any legitimate inputs. */ + if (N >= 2*1024*1024) RETURN(BZ_DATA_ERROR); if (nextSym == BZ_RUNA) es = es + (0+1) * N; else if (nextSym == BZ_RUNB) es = es + (1+1) * N; N = N * 2; @@ -492,15 +505,28 @@ Int32 BZ2_decompress ( DState* s ) RETURN(BZ_DATA_ERROR); /*-- Set up cftab to facilitate generation of T^(-1) --*/ + /* Check: unzftab entries in range. */ + for (i = 0; i <= 255; i++) { + if (s->unzftab[i] < 0 || s->unzftab[i] > nblock) + RETURN(BZ_DATA_ERROR); + } + /* Actually generate cftab. */ s->cftab[0] = 0; for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1]; for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1]; + /* Check: cftab entries in range. */ for (i = 0; i <= 256; i++) { if (s->cftab[i] < 0 || s->cftab[i] > nblock) { /* s->cftab[i] can legitimately be == nblock */ RETURN(BZ_DATA_ERROR); } } + /* Check: cftab entries non-descending. */ + for (i = 1; i <= 256; i++) { + if (s->cftab[i-1] > s->cftab[i]) { + RETURN(BZ_DATA_ERROR); + } + } s->state_out_len = 0; s->state_out_ch = 0; diff --git a/src/misc/bzlib/huffman.c b/src/misc/bzlib/huffman.c index 0f367d6242..df877c73c3 100644 --- a/src/misc/bzlib/huffman.c +++ b/src/misc/bzlib/huffman.c @@ -8,8 +8,8 @@ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. - bzip2/libbzip2 version 1.0.5 of 10 December 2007 - Copyright (C) 1996-2007 Julian Seward + bzip2/libbzip2 version 1.0.8 of 13 July 2019 + Copyright (C) 1996-2019 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. diff --git a/src/misc/bzlib/randtable.c b/src/misc/bzlib/randtable.c index 9cabcb6969..ea8ad3f48a 100644 --- a/src/misc/bzlib/randtable.c +++ b/src/misc/bzlib/randtable.c @@ -8,8 +8,8 @@ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. - bzip2/libbzip2 version 1.0.5 of 10 December 2007 - Copyright (C) 1996-2007 Julian Seward + bzip2/libbzip2 version 1.0.8 of 13 July 2019 + Copyright (C) 1996-2019 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. diff --git a/src/misc/extra/extraUtilFile.c b/src/misc/extra/extraUtilFile.c index 6585b7a729..480280f3ce 100644 --- a/src/misc/extra/extraUtilFile.c +++ b/src/misc/extra/extraUtilFile.c @@ -23,6 +23,9 @@ #define PATH_MAX MAX_PATH #else #include +# ifndef PATH_MAX +# define PATH_MAX 4096 +# endif #endif #include "extra.h" diff --git a/src/misc/util/utilAigSim.c b/src/misc/util/utilAigSim.c index 4d89b615f7..a86753aa24 100644 --- a/src/misc/util/utilAigSim.c +++ b/src/misc/util/utilAigSim.c @@ -34,6 +34,11 @@ #include #endif +// defined by gcc and clang when __int128 is available +#if defined(__SIZEOF_INT128__) +# define HAVE_INT_128 +#endif + #ifdef _WIN32 // Windows doesn't have __builtin_ctzll, implement it using portable algorithm static inline int __builtin_ctzll(uint64_t x) { @@ -187,8 +192,9 @@ static inline uint64_t u64_mask_n(int nBits) { return (nBits >= 64) ? ~0ull : ((nBits <= 0) ? 0ull : ((1ull << nBits) - 1ull)); } -#ifdef _WIN32 -// Windows doesn't support __int128, so we limit to 32 variables on Windows +#ifndef HAVE_INT_128 +// Most 32 bit platforms and Windows doesn't support __int128, so we +// limit to 32 variables on those. static void u128_to_dec(uint64_t x, char *buf, size_t cap) { char tmp[64]; int n = 0; if (!x) { snprintf(buf, cap, "0"); return; } @@ -397,10 +403,10 @@ static int SimulateCompareAigAig(const AigMan *p1, const AigMan *p2, const uint64_t inMask = u64_mask_n(p1->nCis); const uint64_t outMask = u64_mask_n(p1->nCos); -#ifdef _WIN32 - // Windows doesn't support __int128, limit to 32 variables +#ifndef HAVE_INT_128 + // No support for __int128, limit to 32 variables if (nVars > 32) { - fprintf(stderr, "Error: Windows build supports nVars<=32 (got nVars=%d)\n", nVars); + fprintf(stderr, "Error: This architecture build supports nVars<=32 (got nVars=%d)\n", nVars); return 0; } const uint64_t combs = ((uint64_t)1) << (unsigned)nVars; @@ -420,7 +426,7 @@ static int SimulateCompareAigAig(const AigMan *p1, const AigMan *p2, uint64_t inVec[BATCH], valid[NW]; unsigned long long rounds = 0; -#ifdef _WIN32 +#ifndef HAVE_INT_128 uint64_t patsDone = 0; #else unsigned __int128 patsDone = 0; @@ -428,7 +434,7 @@ static int SimulateCompareAigAig(const AigMan *p1, const AigMan *p2, clock_t t0 = clock(); -#ifdef _WIN32 +#ifndef HAVE_INT_128 for (uint64_t base = 0; base < combs; base += BATCH) { uint64_t remain = combs - base; #else @@ -535,10 +541,10 @@ static int SimulateCompareAigBin(const AigMan *p1, const char *bin, const uint64_t inMask = u64_mask_n(p1->nCis); const uint64_t outMask = u64_mask_n(p1->nCos); -#ifdef _WIN32 - // Windows doesn't support __int128, limit to 32 variables +#ifndef HAVE_INT_128 + // No support for __int128, limit to 32 variables if (nVars > 32) { - fprintf(stderr, "Error: Windows build supports nVars<=32 (got nVars=%d)\n", nVars); + fprintf(stderr, "Error: This architecture build supports nVars<=32 (got nVars=%d)\n", nVars); return 0; } const uint64_t combs = ((uint64_t)1) << (unsigned)nVars; @@ -565,7 +571,7 @@ static int SimulateCompareAigBin(const AigMan *p1, const char *bin, uint64_t inVec[BATCH], valid[NW]; unsigned long long rounds = 0; -#ifdef _WIN32 +#ifndef HAVE_INT_128 uint64_t patsDone = 0; #else unsigned __int128 patsDone = 0; @@ -573,7 +579,7 @@ static int SimulateCompareAigBin(const AigMan *p1, const char *bin, clock_t t0 = clock(); -#ifdef _WIN32 +#ifndef HAVE_INT_128 for (uint64_t base = 0; base < combs; base += BATCH) { uint64_t remain = combs - base; #else diff --git a/src/misc/vec/vecInt.h b/src/misc/vec/vecInt.h index e32a2dd18a..9a73cde837 100644 --- a/src/misc/vec/vecInt.h +++ b/src/misc/vec/vecInt.h @@ -1069,28 +1069,28 @@ static inline int Vec_IntFind( Vec_Int_t * p, int Entry ) ***********************************************************************/ static inline int Vec_IntRemove( Vec_Int_t * p, int Entry ) { - int i; - for ( i = 0; i < p->nSize; i++ ) + int i, Size = p->nSize; + for ( i = 0; i < Size; i++ ) if ( p->pArray[i] == Entry ) break; - if ( i == p->nSize ) + if ( i == Size ) return 0; - assert( i < p->nSize ); - for ( i++; i < p->nSize; i++ ) + assert( i < Size ); + for ( i++; i < Size; i++ ) p->pArray[i-1] = p->pArray[i]; p->nSize--; return 1; } static inline int Vec_IntRemove1( Vec_Int_t * p, int Entry ) { - int i; - for ( i = 1; i < p->nSize; i++ ) + int i, Size = p->nSize; + for ( i = 1; i < Size; i++ ) if ( p->pArray[i] == Entry ) break; - if ( i >= p->nSize ) + if ( i >= Size ) return 0; - assert( i < p->nSize ); - for ( i++; i < p->nSize; i++ ) + assert( i < Size ); + for ( i++; i < Size; i++ ) p->pArray[i-1] = p->pArray[i]; p->nSize--; return 1; diff --git a/src/misc/zlib/README b/src/misc/zlib/README index d4219bf889..2b1e6f36fe 100644 --- a/src/misc/zlib/README +++ b/src/misc/zlib/README @@ -1,52 +1,51 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.5 is a general purpose data compression library. All the code is -thread safe. The data format used by the zlib library is described by RFCs -(Request for Comments) 1950 to 1952 in the files -http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) -and rfc1952.txt (gzip format). +zlib 1.3.2 is a general purpose data compression library. All the code is +thread safe (though see the FAQ for caveats). The data format used by the zlib +library is described by RFCs (Request for Comments) 1950 to 1952 at +https://datatracker.ietf.org/doc/html/rfc1950 (zlib format), rfc1951 (deflate +format) and rfc1952 (gzip format). All functions of the compression library are documented in the file zlib.h (volunteer to write man pages welcome, contact zlib@gzip.org). A usage example -of the library is given in the file example.c which also tests that the library -is working correctly. Another example is given in the file minigzip.c. The -compression library itself is composed of all source files except example.c and -minigzip.c. +of the library is given in the file test/example.c which also tests that +the library is working correctly. Another example is given in the file +test/minigzip.c. The compression library itself is composed of all source +files in the root directory. To compile all files and run the test program, follow the instructions given at the top of Makefile.in. In short "./configure; make test", and if that goes -well, "make install" should work for most flavors of Unix. For Windows, use one -of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use +well, "make install" should work for most flavors of Unix. For Windows, use +one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use make_vms.com. Questions about zlib should be sent to , or to Gilles Vollant for the Windows DLL version. The zlib home page is -http://zlib.net/ . Before reporting a problem, please check this site to +https://zlib.net/ . Before reporting a problem, please check this site to verify that you have the latest version of zlib; otherwise get the latest version and check whether the problem still exists or not. -PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. +PLEASE read the zlib FAQ https://zlib.net/zlib_faq.html before asking for help. Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at -http://marknelson.us/1997/01/01/zlib-engine/ . +https://zlib.net/nelson/ . -The changes made in version 1.2.5 are documented in the file ChangeLog. +The changes made in version 1.3.2 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . -zlib is available in Java using the java.util.zip package, documented at -http://java.sun.com/developer/technicalArticles/Programming/compression/ . +zlib is available in Java using the java.util.zip package. Follow the API +Documentation link at: https://docs.oracle.com/search/?q=java.util.zip . -A Perl interface to zlib written by Paul Marquess is available -at CPAN (Comprehensive Perl Archive Network) sites, including -http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . +A Perl interface to zlib and bzip2 written by Paul Marquess +can be found at https://github.com/pmqs/IO-Compress . A Python interface to zlib written by A.M. Kuchling is available in Python 1.5 and later versions, see -http://www.python.org/doc/lib/module-zlib.html . +https://docs.python.org/3/library/zlib.html . -zlib is built into tcl: http://wiki.tcl.tk/4610 . +zlib is built into tcl: https://wiki.tcl-lang.org/page/zlib . An experimental package to read and write files in .zip format, written on top of zlib by Gilles Vollant , is available in the @@ -64,15 +63,13 @@ Notes for some targets: - zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works when compiled with cc. -- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is +- On Digital Unix 4.0D (formerly OSF/1) on AlphaServer, the cc option -std1 is necessary to get gzprintf working correctly. This is done by configure. - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with other compilers. Use "make test" to check your compiler. -- gzdopen is not supported on RISCOS or BEOS. - -- For PalmOs, see http://palmzlib.sourceforge.net/ +- For PalmOs, see https://palmzlib.sourceforge.net/ Acknowledgments: @@ -84,7 +81,7 @@ Acknowledgments: Copyright notice: - (C) 1995-2010 Jean-loup Gailly and Mark Adler + (C) 1995-2026 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -108,7 +105,10 @@ Copyright notice: If you use the zlib library in a product, we would appreciate *not* receiving lengthy legal documents to sign. The sources are provided for free but without warranty of any kind. The library has been entirely written by Jean-loup -Gailly and Mark Adler; it does not include third-party code. +Gailly and Mark Adler; it does not include third-party code. We make all +contributions to and distributions of this project solely in our personal +capacity, and are not conveying any rights to any intellectual property of +any third parties. If you redistribute modified sources, we would appreciate that you include in the file ChangeLog history information documenting your changes. Please read diff --git a/src/misc/zlib/adler32.c b/src/misc/zlib/adler32.c index 2015a3277d..e153a2c48f 100644 --- a/src/misc/zlib/adler32.c +++ b/src/misc/zlib/adler32.c @@ -1,5 +1,5 @@ /* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2007 Mark Adler + * Copyright (C) 1995-2011, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -14,11 +14,8 @@ ABC_NAMESPACE_IMPL_START -#define local static -local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); - -#define BASE 65521UL /* largest prime smaller than 65536 */ +#define BASE 65521U /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ @@ -28,44 +25,48 @@ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); -/* use NO_DIVIDE if your processor does not do division in hardware */ +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ #ifdef NO_DIVIDE -# define MOD(a) \ +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ + do { \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ do { \ - if (a >= (BASE << 16)) a -= (BASE << 16); \ - if (a >= (BASE << 15)) a -= (BASE << 15); \ - if (a >= (BASE << 14)) a -= (BASE << 14); \ - if (a >= (BASE << 13)) a -= (BASE << 13); \ - if (a >= (BASE << 12)) a -= (BASE << 12); \ - if (a >= (BASE << 11)) a -= (BASE << 11); \ - if (a >= (BASE << 10)) a -= (BASE << 10); \ - if (a >= (BASE << 9)) a -= (BASE << 9); \ - if (a >= (BASE << 8)) a -= (BASE << 8); \ - if (a >= (BASE << 7)) a -= (BASE << 7); \ - if (a >= (BASE << 6)) a -= (BASE << 6); \ - if (a >= (BASE << 5)) a -= (BASE << 5); \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ + CHOP(a); \ if (a >= BASE) a -= BASE; \ } while (0) -# define MOD4(a) \ +# define MOD(a) \ do { \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ if (a >= BASE) a -= BASE; \ } while (0) #else # define MOD(a) a %= BASE -# define MOD4(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE #endif /* ========================================================================= */ -uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) -{ +uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) { unsigned long sum2; unsigned n; @@ -96,7 +97,7 @@ uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) } if (adler >= BASE) adler -= BASE; - MOD4(sum2); /* only added so many BASE's */ + MOD28(sum2); /* only added so many BASE's */ return adler | (sum2 << 16); } @@ -132,14 +133,23 @@ uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) } /* ========================================================================= */ -local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) -{ +uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) { + return adler32_z(adler, buf, len); +} + +/* ========================================================================= */ +local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) { unsigned long sum1; unsigned long sum2; unsigned rem; + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + /* the derivation of this formula is left as an exercise for the reader */ - rem = (unsigned)(len2 % BASE); + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; sum1 = adler1 & 0xffff; sum2 = rem * sum1; MOD(sum2); @@ -147,22 +157,19 @@ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; if (sum1 >= BASE) sum1 -= BASE; if (sum1 >= BASE) sum1 -= BASE; - if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); if (sum2 >= BASE) sum2 -= BASE; return sum1 | (sum2 << 16); } /* ========================================================================= */ -uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) -{ +uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) { return adler32_combine_(adler1, adler2, len2); } -uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) -{ +uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) { return adler32_combine_(adler1, adler2, len2); } - ABC_NAMESPACE_IMPL_END diff --git a/src/misc/zlib/compress_.c b/src/misc/zlib/compress_.c index 7fbfdb3b7a..2788aed994 100644 --- a/src/misc/zlib/compress_.c +++ b/src/misc/zlib/compress_.c @@ -1,15 +1,21 @@ /* compress.c -- compress a memory buffer - * Copyright (C) 1995-2005 Jean-loup Gailly. + * Copyright (C) 1995-2026 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #define ZLIB_INTERNAL +#include +#include +#include +#include "misc/util/abc_global.h" + #include "zlib.h" ABC_NAMESPACE_IMPL_START + /* =========================================================================== Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte @@ -20,21 +26,22 @@ ABC_NAMESPACE_IMPL_START compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. + + The _z versions of the functions take size_t length arguments. */ -int ZEXPORT compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level) -{ +int ZEXPORT compress2_z(Bytef *dest, z_size_t *destLen, const Bytef *source, + z_size_t sourceLen, int level) { z_stream stream; int err; + const uInt max = (uInt)-1; + z_size_t left; - stream.next_in = (Bytef*)source; - stream.avail_in = (uInt)sourceLen; -#ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; -#endif - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + if ((sourceLen > 0 && source == NULL) || + destLen == NULL || (*destLen > 0 && dest == NULL)) + return Z_STREAM_ERROR; + + left = *destLen; + *destLen = 0; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; @@ -43,21 +50,45 @@ int ZEXPORT compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, uLong err = deflateInit(&stream, level); if (err != Z_OK) return err; - err = deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - deflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; + stream.next_out = dest; + stream.avail_out = 0; + stream.next_in = (z_const Bytef *)source; + stream.avail_in = 0; + + do { + if (stream.avail_out == 0) { + stream.avail_out = left > (z_size_t)max ? max : (uInt)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = sourceLen > (z_size_t)max ? max : + (uInt)sourceLen; + sourceLen -= stream.avail_in; + } + err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); + } while (err == Z_OK); - err = deflateEnd(&stream); - return err; + *destLen = (z_size_t)(stream.next_out - dest); + deflateEnd(&stream); + return err == Z_STREAM_END ? Z_OK : err; +} +int ZEXPORT compress2(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen, int level) { + int ret; + z_size_t got = *destLen; + ret = compress2_z(dest, &got, source, sourceLen, level); + *destLen = (uLong)got; + return ret; } - /* =========================================================================== */ -int ZEXPORT compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) -{ +int ZEXPORT compress_z(Bytef *dest, z_size_t *destLen, const Bytef *source, + z_size_t sourceLen) { + return compress2_z(dest, destLen, source, sourceLen, + Z_DEFAULT_COMPRESSION); +} +int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen) { return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); } @@ -65,12 +96,15 @@ int ZEXPORT compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong s If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ -uLong ZEXPORT compressBound (uLong sourceLen) -{ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + - (sourceLen >> 25) + 13; +z_size_t ZEXPORT compressBound_z(z_size_t sourceLen) { + z_size_t bound = sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13; + return bound < sourceLen ? (z_size_t)-1 : bound; +} +uLong ZEXPORT compressBound(uLong sourceLen) { + z_size_t bound = compressBound_z(sourceLen); + return (uLong)bound != bound ? (uLong)-1 : (uLong)bound; } - ABC_NAMESPACE_IMPL_END diff --git a/src/misc/zlib/crc32.c b/src/misc/zlib/crc32.c index c6ff6b7867..923a07b6c5 100644 --- a/src/misc/zlib/crc32.c +++ b/src/misc/zlib/crc32.c @@ -1,12 +1,10 @@ /* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010 Mark Adler + * Copyright (C) 1995-2026 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * - * Thanks to Rodney Brown for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + * This interleaved implementation of a CRC makes use of pipelined multiple + * arithmetic-logic units, commonly found in modern CPU cores. It is due to + * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution. */ /* @(#) $Id$ */ @@ -14,420 +12,983 @@ /* Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore protection on the static variables used to control the first-use generation - of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should first call get_crc_table() to initialize the tables before allowing more than one thread to use crc32(). + + MAKECRCH can be #defined to write out crc32.h. A main() routine is also + produced, so that this one source file can be compiled to an executable. */ #ifdef MAKECRCH # include # ifndef DYNAMIC_CRC_TABLE # define DYNAMIC_CRC_TABLE -# endif /* !DYNAMIC_CRC_TABLE */ -#endif /* MAKECRCH */ +# endif +#endif +#ifdef DYNAMIC_CRC_TABLE +# define Z_ONCE +#endif #include #include #include #include "misc/util/abc_global.h" -#include "zutil.h" /* for STDC and FAR definitions */ +#include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */ ABC_NAMESPACE_IMPL_START -#define local static -/* Find a four-byte integer type for crc32_little() and crc32_big(). */ -#ifndef NOBYFOUR -# ifdef STDC /* need ANSI C limits.h to determine sizes */ -ABC_NAMESPACE_IMPL_END -# include -ABC_NAMESPACE_IMPL_START -# define BYFOUR -# if (UINT_MAX == 0xffffffffUL) - typedef unsigned int u4; +#ifdef HAVE_S390X_VX +# include "contrib/crc32vx/crc32_vx_hooks.h" +#endif + + /* + A CRC of a message is computed on N braids of words in the message, where + each word consists of W bytes (4 or 8). If N is 3, for example, then three + running sparse CRCs are calculated respectively on each braid, at these + indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ... + This is done starting at a word boundary, and continues until as many blocks + of N * W bytes as are available have been processed. The results are combined + into a single CRC at the end. For this code, N must be in the range 1..6 and + W must be 4 or 8. The upper limit on N can be increased if desired by adding + more #if blocks, extending the patterns apparent in the code. In addition, + crc32.h would need to be regenerated, if the maximum N value is increased. + + N and W are chosen empirically by benchmarking the execution time on a given + processor. The choices for N and W below were based on testing on Intel Kaby + Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64 + Octeon II processors. The Intel, AMD, and ARM processors were all fastest + with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4. + They were all tested with either gcc or clang, all using the -O3 optimization + level. Your mileage may vary. + */ + +/* Define N */ +#ifdef Z_TESTN +# define N Z_TESTN +#else +# define N 5 +#endif +#if N < 1 || N > 6 +# error N must be in 1..6 +#endif + +/* + z_crc_t must be at least 32 bits. z_word_t must be at least as long as + z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and + that bytes are eight bits. + */ + +/* + Define W and the associated z_word_t type. If W is not defined, then a + braided calculation is not used, and the associated tables and code are not + compiled. + */ +#ifdef Z_TESTW +# if Z_TESTW-1 != -1 +# define W Z_TESTW +# endif +#else +# ifdef MAKECRCH +# define W 8 /* required for MAKECRCH */ +# else +# if defined(__x86_64__) || defined(__aarch64__) +# define W 8 # else -# if (ULONG_MAX == 0xffffffffUL) - typedef unsigned long u4; -# else -# if (USHRT_MAX == 0xffffffffUL) - typedef unsigned short u4; -# else -# undef BYFOUR /* can't find a four-byte integer type! */ -# endif -# endif +# define W 4 # endif -# endif /* STDC */ -#endif /* !NOBYFOUR */ - -/* Definitions for doing the crc four data bytes at a time. */ -#ifdef BYFOUR -# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ - (((w)&0xff00)<<8)+(((w)&0xff)<<24)) - local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, unsigned)); - local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, unsigned)); -# define TBLS 8 +# endif +#endif +#ifdef W +# if W == 8 && defined(Z_U8) + typedef Z_U8 z_word_t; +# elif defined(Z_U4) +# undef W +# define W 4 + typedef Z_U4 z_word_t; +# else +# undef W +# endif +#endif + +/* If available, use the ARM processor CRC32 instruction. */ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && \ + defined(W) && W == 8 +# define ARMCRC32 +#endif + +#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) +/* + Swap the bytes in a z_word_t to convert between little and big endian. Any + self-respecting compiler will optimize this to a single machine byte-swap + instruction, if one is available. This assumes that word_t is either 32 bits + or 64 bits. + */ +local z_word_t byte_swap(z_word_t word) { +# if W == 8 + return + (word & 0xff00000000000000) >> 56 | + (word & 0xff000000000000) >> 40 | + (word & 0xff0000000000) >> 24 | + (word & 0xff00000000) >> 8 | + (word & 0xff000000) << 8 | + (word & 0xff0000) << 24 | + (word & 0xff00) << 40 | + (word & 0xff) << 56; +# else /* W == 4 */ + return + (word & 0xff000000) >> 24 | + (word & 0xff0000) >> 8 | + (word & 0xff00) << 8 | + (word & 0xff) << 24; +# endif +} +#endif + +#ifdef DYNAMIC_CRC_TABLE +/* ========================================================================= + * Table of powers of x for combining CRC-32s, filled in by make_crc_table() + * below. + */ + local z_crc_t FAR x2n_table[32]; #else -# define TBLS 1 -#endif /* BYFOUR */ +/* ========================================================================= + * Tables for byte-wise and braided CRC-32 calculations, and a table of powers + * of x for combining CRC-32s, all made by make_crc_table(). + */ +# include "crc32.h" +#endif + +/* CRC polynomial. */ +#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ -/* Local functions for crc concatenation */ -local unsigned long gf2_matrix_times OF((unsigned long *mat, - unsigned long vec)); -local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); -local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); +/* + Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, + reflected. For speed, this requires that a not be zero. + */ +local uLong multmodp(uLong a, uLong b) { + uLong m, p; + + m = (uLong)1 << 31; + p = 0; + for (;;) { + if (a & m) { + p ^= b; + if ((a & (m - 1)) == 0) + break; + } + m >>= 1; + b = b & 1 ? (b >> 1) ^ POLY : b >> 1; + } + return p; +} +/* + Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been + initialized. n must not be negative. + */ +local uLong x2nmodp(z_off64_t n, unsigned k) { + uLong p; + + p = (uLong)1 << 31; /* x^0 == 1 */ + while (n) { + if (n & 1) + p = multmodp(x2n_table[k & 31], p); + n >>= 1; + k++; + } + return p; +} #ifdef DYNAMIC_CRC_TABLE - -local volatile int crc_table_empty = 1; -local unsigned long FAR crc_table[TBLS][256]; -local void make_crc_table OF((void)); +/* ========================================================================= + * Build the tables for byte-wise and braided CRC-32 calculations, and a table + * of powers of x for combining CRC-32s. + */ +local z_crc_t FAR crc_table[256]; +#ifdef W + local z_word_t FAR crc_big_table[256]; + local z_crc_t FAR crc_braid_table[W][256]; + local z_word_t FAR crc_braid_big_table[W][256]; + local void braid(z_crc_t [][256], z_word_t [][256], int, int); +#endif #ifdef MAKECRCH - local void write_table OF((FILE *, const unsigned long FAR *)); + local void write_table(FILE *, const z_crc_t FAR *, int); + local void write_table32hi(FILE *, const z_word_t FAR *, int); + local void write_table64(FILE *, const z_word_t FAR *, int); #endif /* MAKECRCH */ + +/* State for once(). */ +local z_once_t made = Z_ONCE_INIT; + /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials + with the lowest powers in the most significant bit. Then adding polynomials is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the + one. If we call the above polynomial p, and represent a byte as the polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p, where a mod b means the remainder after dividing a by b. This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each + taking the remainder. The register is initialized to zero, and for each incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The first table is simply the CRC of all possible eight bit values. This is - all the information needed to generate CRCs on data a byte at a time for all - combinations of CRC register values and incoming bytes. The remaining tables - allow for word-at-a-time CRC calculation for both big-endian and little- - endian machines, where a word is four bytes. -*/ -local void make_crc_table() -{ - unsigned long c; - int n, k; - unsigned long poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static volatile int first = 1; /* flag to limit concurrent making */ - static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; - - /* See if another task is already doing this (not thread-safe, but better - than nothing -- significantly reduces duration of vulnerability in - case the advice about DYNAMIC_CRC_TABLE is ignored) */ - if (first) { - first = 0; - - /* make exclusive-or pattern from polynomial (0xedb88320UL) */ - poly = 0UL; - for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) - poly |= 1UL << (31 - p[n]); - - /* generate a crc for every 8-bit value */ - for (n = 0; n < 256; n++) { - c = (unsigned long)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[0][n] = c; - } - -#ifdef BYFOUR - /* generate crc for each value followed by one, two, and three zeros, - and then the byte reversal of those as well as the first table */ - for (n = 0; n < 256; n++) { - c = crc_table[0][n]; - crc_table[4][n] = REV(c); - for (k = 1; k < 4; k++) { - c = crc_table[0][c & 0xff] ^ (c >> 8); - crc_table[k][n] = c; - crc_table[k + 4][n] = REV(c); - } - } -#endif /* BYFOUR */ + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x + (which is shifting right by one and adding x^32 mod p if the bit shifted out + is a one). We start with the highest power (least significant bit) of q and + repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all the + information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. + */ - crc_table_empty = 0; - } - else { /* not first */ - /* wait for the other guy to finish (not efficient, but rare) */ - while (crc_table_empty) - ; +local void make_crc_table(void) { + unsigned i, j, n; + z_crc_t p; + + /* initialize the CRC of bytes tables */ + for (i = 0; i < 256; i++) { + p = i; + for (j = 0; j < 8; j++) + p = p & 1 ? (p >> 1) ^ POLY : p >> 1; + crc_table[i] = p; +#ifdef W + crc_big_table[i] = byte_swap(p); +#endif } + /* initialize the x^2^n mod p(x) table */ + p = (z_crc_t)1 << 30; /* x^1 */ + x2n_table[0] = p; + for (n = 1; n < 32; n++) + x2n_table[n] = p = (z_crc_t)multmodp(p, p); + +#ifdef W + /* initialize the braiding tables -- needs x2n_table[] */ + braid(crc_braid_table, crc_braid_big_table, N, W); +#endif + #ifdef MAKECRCH - /* write out CRC tables to crc32.h */ { + /* + The crc32.h header file contains tables for both 32-bit and 64-bit + z_word_t's, and so requires a 64-bit type be available. In that case, + z_word_t must be defined to be 64-bits. This code then also generates + and writes out the tables for the case that z_word_t is 32 bits. + */ +#if !defined(W) || W != 8 +# error Need a 64-bit integer type in order to generate crc32.h. +#endif FILE *out; + int k, n; + z_crc_t ltl[8][256]; + z_word_t big[8][256]; out = fopen("crc32.h", "w"); if (out == NULL) return; - fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); - fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); - fprintf(out, "local const unsigned long FAR "); - fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); - write_table(out, crc_table[0]); -# ifdef BYFOUR - fprintf(out, "#ifdef BYFOUR\n"); - for (k = 1; k < 8; k++) { - fprintf(out, " },\n {\n"); - write_table(out, crc_table[k]); + + /* write out little-endian CRC table to crc32.h */ + fprintf(out, + "/* crc32.h -- tables for rapid CRC calculation\n" + " * Generated automatically by crc32.c\n */\n" + "\n" + "local const z_crc_t FAR crc_table[] = {\n" + " "); + write_table(out, crc_table, 256); + fprintf(out, + "};\n"); + + /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#ifdef W\n" + "\n" + "#if W == 8\n" + "\n" + "local const z_word_t FAR crc_big_table[] = {\n" + " "); + write_table64(out, crc_big_table, 256); + fprintf(out, + "};\n"); + + /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#else /* W == 4 */\n" + "\n" + "local const z_word_t FAR crc_big_table[] = {\n" + " "); + write_table32hi(out, crc_big_table, 256); + fprintf(out, + "};\n" + "\n" + "#endif\n"); + + /* write out braid tables for each value of N */ + for (n = 1; n <= 6; n++) { + fprintf(out, + "\n" + "#if N == %d\n", n); + + /* compute braid tables for this N and 64-bit word_t */ + braid(ltl, big, n, 8); + + /* write out braid tables for 64-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#if W == 8\n" + "\n" + "local const z_crc_t FAR crc_braid_table[][256] = {\n"); + for (k = 0; k < 8; k++) { + fprintf(out, " {"); + write_table(out, ltl[k], 256); + fprintf(out, "}%s", k < 7 ? ",\n" : ""); + } + fprintf(out, + "};\n" + "\n" + "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); + for (k = 0; k < 8; k++) { + fprintf(out, " {"); + write_table64(out, big[k], 256); + fprintf(out, "}%s", k < 7 ? ",\n" : ""); + } + fprintf(out, + "};\n"); + + /* compute braid tables for this N and 32-bit word_t */ + braid(ltl, big, n, 4); + + /* write out braid tables for 32-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#else /* W == 4 */\n" + "\n" + "local const z_crc_t FAR crc_braid_table[][256] = {\n"); + for (k = 0; k < 4; k++) { + fprintf(out, " {"); + write_table(out, ltl[k], 256); + fprintf(out, "}%s", k < 3 ? ",\n" : ""); + } + fprintf(out, + "};\n" + "\n" + "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); + for (k = 0; k < 4; k++) { + fprintf(out, " {"); + write_table32hi(out, big[k], 256); + fprintf(out, "}%s", k < 3 ? ",\n" : ""); + } + fprintf(out, + "};\n" + "\n" + "#endif\n" + "\n" + "#endif\n"); } - fprintf(out, "#endif\n"); -# endif /* BYFOUR */ - fprintf(out, " }\n};\n"); + fprintf(out, + "\n" + "#endif\n"); + + /* write out zeros operator table to crc32.h */ + fprintf(out, + "\n" + "local const z_crc_t FAR x2n_table[] = {\n" + " "); + write_table(out, x2n_table, 32); + fprintf(out, + "};\n"); fclose(out); } #endif /* MAKECRCH */ } #ifdef MAKECRCH -local void write_table(FILE *out, const unsigned long FAR *table) -{ + +/* + Write the 32-bit values in table[0..k-1] to out, five per line in + hexadecimal separated by commas. + */ +local void write_table(FILE *out, const z_crc_t FAR *table, int k) { + int n; + + for (n = 0; n < k; n++) + fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", + (unsigned long)(table[n]), + n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); +} + +/* + Write the high 32-bits of each value in table[0..k-1] to out, five per line + in hexadecimal separated by commas. + */ +local void write_table32hi(FILE *out, const z_word_t FAR *table, int k) { + int n; + + for (n = 0; n < k; n++) + fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", + (unsigned long)(table[n] >> 32), + n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); +} + +/* + Write the 64-bit values in table[0..k-1] to out, three per line in + hexadecimal separated by commas. This assumes that if there is a 64-bit + type, then there is also a long long integer type, and it is at least 64 + bits. If not, then the type cast and format string can be adjusted + accordingly. + */ +local void write_table64(FILE *out, const z_word_t FAR *table, int k) { int n; - for (n = 0; n < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], - n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); + for (n = 0; n < k; n++) + fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ", + (unsigned long long)(table[n]), + n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", ")); } + +/* Actually do the deed. */ +int main(void) { + make_crc_table(); + return 0; +} + #endif /* MAKECRCH */ -#else /* !DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Tables of CRC-32s of all single-byte values, made by make_crc_table(). +#ifdef W +/* + Generate the little and big-endian braid tables for the given n and z_word_t + size w. Each array must have room for w blocks of 256 elements. */ -ABC_NAMESPACE_IMPL_END -#include "crc32.h" -ABC_NAMESPACE_IMPL_START +local void braid(z_crc_t ltl[][256], z_word_t big[][256], int n, int w) { + int k; + z_crc_t i, p, q; + for (k = 0; k < w; k++) { + p = (z_crc_t)x2nmodp((n * w + 3 - k) << 3, 0); + ltl[k][0] = 0; + big[w - 1 - k][0] = 0; + for (i = 1; i < 256; i++) { + ltl[k][i] = q = (z_crc_t)multmodp(i << 24, p); + big[w - 1 - k][i] = byte_swap(q); + } + } +} +#endif + #endif /* DYNAMIC_CRC_TABLE */ /* ========================================================================= - * This function can be used by asm versions of crc32() + * This function can be used by asm versions of crc32(), and to force the + * generation of the CRC tables in a threaded application. */ -const unsigned long FAR * ZEXPORT get_crc_table() -{ +const z_crc_t FAR * ZEXPORT get_crc_table(void) { #ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); + z_once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ - return (const unsigned long FAR *)crc_table; + return (const z_crc_t FAR *)crc_table; } -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 +/* ========================================================================= + * Use ARM machine instructions if available. This will compute the CRC about + * ten times faster than the braided calculation. This code does not check for + * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will + * only be defined if the compilation specifies an ARM processor architecture + * that has the instructions. For example, compiling with -march=armv8.1-a or + * -march=armv8-a+crc, or -march=native if the compile machine has the crc32 + * instructions. + */ +#ifdef ARMCRC32 -/* ========================================================================= */ -unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len) -{ - if (buf == Z_NULL) return 0UL; +/* + Constants empirically determined to maximize speed. These values are from + measurements on a Cortex-A57. Your mileage may vary. + */ +#define Z_BATCH 3990 /* number of words in a batch */ +#define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */ +#define Z_BATCH_MIN 800 /* fewest words in a final batch */ + +uLong ZEXPORT crc32_z(uLong crc, const unsigned char FAR *buf, z_size_t len) { + uLong val; + z_word_t crc1, crc2; + const z_word_t *word; + z_word_t val0, val1, val2; + z_size_t last, last2, i; + z_size_t num; + + /* Return initial CRC, if requested. */ + if (buf == Z_NULL) return 0; #ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); + z_once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ -#ifdef BYFOUR - if (sizeof(void *) == sizeof(ptrdiff_t)) { - u4 endian; + /* Pre-condition the CRC */ + crc = (~crc) & 0xffffffff; - endian = 1; - if (*((unsigned char *)(&endian))) - return crc32_little(crc, buf, len); - else - return crc32_big(crc, buf, len); + /* Compute the CRC up to a word boundary. */ + while (len && ((z_size_t)buf & 7) != 0) { + len--; + val = *buf++; + __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); } -#endif /* BYFOUR */ - crc = crc ^ 0xffffffffUL; - while (len >= 8) { - DO8; - len -= 8; + + /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */ + word = (z_word_t const *)buf; + num = len >> 3; + len &= 7; + + /* Do three interleaved CRCs to realize the throughput of one crc32x + instruction per cycle. Each CRC is calculated on Z_BATCH words. The + three CRCs are combined into a single CRC after each set of batches. */ + while (num >= 3 * Z_BATCH) { + crc1 = 0; + crc2 = 0; + for (i = 0; i < Z_BATCH; i++) { + val0 = word[i]; + val1 = word[i + Z_BATCH]; + val2 = word[i + 2 * Z_BATCH]; + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); + } + word += 3 * Z_BATCH; + num -= 3 * Z_BATCH; + crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1; + crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2; } - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffffUL; -} -#ifdef BYFOUR + /* Do one last smaller batch with the remaining words, if there are enough + to pay for the combination of CRCs. */ + last = num / 3; + if (last >= Z_BATCH_MIN) { + last2 = last << 1; + crc1 = 0; + crc2 = 0; + for (i = 0; i < last; i++) { + val0 = word[i]; + val1 = word[i + last]; + val2 = word[i + last2]; + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); + } + word += 3 * last; + num -= 3 * last; + val = x2nmodp((int)last, 6); + crc = multmodp(val, crc) ^ crc1; + crc = multmodp(val, crc) ^ crc2; + } -/* ========================================================================= */ -#define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] -#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + /* Compute the CRC on any remaining words. */ + for (i = 0; i < num; i++) { + val0 = word[i]; + __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); + } + word += num; -/* ========================================================================= */ -local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf, unsigned len) -{ - u4 c; - const u4 FAR *buf4; - - c = (u4)crc; - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + /* Complete the CRC on any remaining bytes. */ + buf = (const unsigned char FAR *)word; + while (len) { len--; + val = *buf++; + __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); } - buf4 = (const u4 FAR *)(const void FAR *)buf; - while (len >= 32) { - DOLIT32; - len -= 32; - } - while (len >= 4) { - DOLIT4; - len -= 4; - } - buf = (const unsigned char FAR *)buf4; + /* Return the CRC, post-conditioned. */ + return crc ^ 0xffffffff; +} + +#else - if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - } while (--len); - c = ~c; - return (unsigned long)c; +#ifdef W + +/* + Return the CRC of the W bytes in the word_t data, taking the + least-significant byte of the word as the first byte of data, without any pre + or post conditioning. This is used to combine the CRCs of each braid. + */ +local z_crc_t crc_word(z_word_t data) { + int k; + for (k = 0; k < W; k++) + data = (data >> 8) ^ crc_table[data & 0xff]; + return (z_crc_t)data; } -/* ========================================================================= */ -#define DOBIG4 c ^= *++buf4; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] -#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 +local z_word_t crc_word_big(z_word_t data) { + int k; + for (k = 0; k < W; k++) + data = (data << 8) ^ + crc_big_table[(data >> ((W - 1) << 3)) & 0xff]; + return data; +} + +#endif /* ========================================================================= */ -local unsigned long crc32_big(unsigned long crc, const unsigned char FAR *buf, unsigned len) -{ - u4 c; - const u4 FAR *buf4; - - c = REV((u4)crc); - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - len--; +uLong ZEXPORT crc32_z(uLong crc, const unsigned char FAR *buf, z_size_t len) { + /* Return initial CRC, if requested. */ + if (buf == Z_NULL) return 0; + +#ifdef DYNAMIC_CRC_TABLE + z_once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + + /* Pre-condition the CRC */ + crc = (~crc) & 0xffffffff; + +#ifdef W + + /* If provided enough bytes, do a braided CRC calculation. */ + if (len >= N * W + W - 1) { + z_size_t blks; + z_word_t const *words; + unsigned endian; + int k; + + /* Compute the CRC up to a z_word_t boundary. */ + while (len && ((z_size_t)buf & (W - 1)) != 0) { + len--; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + } + + /* Compute the CRC on as many N z_word_t blocks as are available. */ + blks = len / (N * W); + len -= blks * N * W; + words = (z_word_t const *)buf; + + /* Do endian check at execution time instead of compile time, since ARM + processors can change the endianness at execution time. If the + compiler knows what the endianness will be, it can optimize out the + check and the unused branch. */ + endian = 1; + if (*(unsigned char *)&endian) { + /* Little endian. */ + + z_crc_t crc0; + z_word_t word0; +#if N > 1 + z_crc_t crc1; + z_word_t word1; +#if N > 2 + z_crc_t crc2; + z_word_t word2; +#if N > 3 + z_crc_t crc3; + z_word_t word3; +#if N > 4 + z_crc_t crc4; + z_word_t word4; +#if N > 5 + z_crc_t crc5; + z_word_t word5; +#endif +#endif +#endif +#endif +#endif + + /* Initialize the CRC for each braid. */ + crc0 = crc; +#if N > 1 + crc1 = 0; +#if N > 2 + crc2 = 0; +#if N > 3 + crc3 = 0; +#if N > 4 + crc4 = 0; +#if N > 5 + crc5 = 0; +#endif +#endif +#endif +#endif +#endif + + /* + Process the first blks-1 blocks, computing the CRCs on each braid + independently. + */ + while (--blks) { + /* Load the word for each braid into registers. */ + word0 = crc0 ^ words[0]; +#if N > 1 + word1 = crc1 ^ words[1]; +#if N > 2 + word2 = crc2 ^ words[2]; +#if N > 3 + word3 = crc3 ^ words[3]; +#if N > 4 + word4 = crc4 ^ words[4]; +#if N > 5 + word5 = crc5 ^ words[5]; +#endif +#endif +#endif +#endif +#endif + words += N; + + /* Compute and update the CRC for each word. The loop should + get unrolled. */ + crc0 = crc_braid_table[0][word0 & 0xff]; +#if N > 1 + crc1 = crc_braid_table[0][word1 & 0xff]; +#if N > 2 + crc2 = crc_braid_table[0][word2 & 0xff]; +#if N > 3 + crc3 = crc_braid_table[0][word3 & 0xff]; +#if N > 4 + crc4 = crc_braid_table[0][word4 & 0xff]; +#if N > 5 + crc5 = crc_braid_table[0][word5 & 0xff]; +#endif +#endif +#endif +#endif +#endif + for (k = 1; k < W; k++) { + crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff]; +#if N > 1 + crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff]; +#if N > 2 + crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff]; +#if N > 3 + crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff]; +#if N > 4 + crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff]; +#if N > 5 + crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff]; +#endif +#endif +#endif +#endif +#endif + } + } + + /* + Process the last block, combining the CRCs of the N braids at the + same time. + */ + crc = crc_word(crc0 ^ words[0]); +#if N > 1 + crc = crc_word(crc1 ^ words[1] ^ crc); +#if N > 2 + crc = crc_word(crc2 ^ words[2] ^ crc); +#if N > 3 + crc = crc_word(crc3 ^ words[3] ^ crc); +#if N > 4 + crc = crc_word(crc4 ^ words[4] ^ crc); +#if N > 5 + crc = crc_word(crc5 ^ words[5] ^ crc); +#endif +#endif +#endif +#endif +#endif + words += N; + } + else { + /* Big endian. */ + + z_word_t crc0, word0, comb; +#if N > 1 + z_word_t crc1, word1; +#if N > 2 + z_word_t crc2, word2; +#if N > 3 + z_word_t crc3, word3; +#if N > 4 + z_word_t crc4, word4; +#if N > 5 + z_word_t crc5, word5; +#endif +#endif +#endif +#endif +#endif + + /* Initialize the CRC for each braid. */ + crc0 = byte_swap(crc); +#if N > 1 + crc1 = 0; +#if N > 2 + crc2 = 0; +#if N > 3 + crc3 = 0; +#if N > 4 + crc4 = 0; +#if N > 5 + crc5 = 0; +#endif +#endif +#endif +#endif +#endif + + /* + Process the first blks-1 blocks, computing the CRCs on each braid + independently. + */ + while (--blks) { + /* Load the word for each braid into registers. */ + word0 = crc0 ^ words[0]; +#if N > 1 + word1 = crc1 ^ words[1]; +#if N > 2 + word2 = crc2 ^ words[2]; +#if N > 3 + word3 = crc3 ^ words[3]; +#if N > 4 + word4 = crc4 ^ words[4]; +#if N > 5 + word5 = crc5 ^ words[5]; +#endif +#endif +#endif +#endif +#endif + words += N; + + /* Compute and update the CRC for each word. The loop should + get unrolled. */ + crc0 = crc_braid_big_table[0][word0 & 0xff]; +#if N > 1 + crc1 = crc_braid_big_table[0][word1 & 0xff]; +#if N > 2 + crc2 = crc_braid_big_table[0][word2 & 0xff]; +#if N > 3 + crc3 = crc_braid_big_table[0][word3 & 0xff]; +#if N > 4 + crc4 = crc_braid_big_table[0][word4 & 0xff]; +#if N > 5 + crc5 = crc_braid_big_table[0][word5 & 0xff]; +#endif +#endif +#endif +#endif +#endif + for (k = 1; k < W; k++) { + crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff]; +#if N > 1 + crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff]; +#if N > 2 + crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff]; +#if N > 3 + crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff]; +#if N > 4 + crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff]; +#if N > 5 + crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff]; +#endif +#endif +#endif +#endif +#endif + } + } + + /* + Process the last block, combining the CRCs of the N braids at the + same time. + */ + comb = crc_word_big(crc0 ^ words[0]); +#if N > 1 + comb = crc_word_big(crc1 ^ words[1] ^ comb); +#if N > 2 + comb = crc_word_big(crc2 ^ words[2] ^ comb); +#if N > 3 + comb = crc_word_big(crc3 ^ words[3] ^ comb); +#if N > 4 + comb = crc_word_big(crc4 ^ words[4] ^ comb); +#if N > 5 + comb = crc_word_big(crc5 ^ words[5] ^ comb); +#endif +#endif +#endif +#endif +#endif + words += N; + crc = byte_swap(comb); + } + + /* + Update the pointer to the remaining bytes to process. + */ + buf = (unsigned char const *)words; } - buf4 = (const u4 FAR *)(const void FAR *)buf; - buf4--; - while (len >= 32) { - DOBIG32; - len -= 32; +#endif /* W */ + + /* Complete the computation of the CRC on any remaining bytes. */ + while (len >= 8) { + len -= 8; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; } - while (len >= 4) { - DOBIG4; - len -= 4; + while (len) { + len--; + crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; } - buf4++; - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - } while (--len); - c = ~c; - return (unsigned long)(REV(c)); -} -#endif /* BYFOUR */ + /* Return the CRC, post-conditioned. */ + return crc ^ 0xffffffff; +} -#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ +#endif /* ========================================================================= */ -local unsigned long gf2_matrix_times(unsigned long *mat, unsigned long vec) -{ - unsigned long sum; - - sum = 0; - while (vec) { - if (vec & 1) - sum ^= *mat; - vec >>= 1; - mat++; - } - return sum; +uLong ZEXPORT crc32(uLong crc, const unsigned char FAR *buf, uInt len) { + #ifdef HAVE_S390X_VX + return crc32_z_hook(crc, buf, len); + #endif + return crc32_z(crc, buf, len); } /* ========================================================================= */ -local void gf2_matrix_square(unsigned long *square, unsigned long *mat) -{ - int n; - - for (n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); +uLong ZEXPORT crc32_combine_gen64(z_off64_t len2) { + if (len2 < 0) + return 0; +#ifdef DYNAMIC_CRC_TABLE + z_once(&made, make_crc_table); +#endif /* DYNAMIC_CRC_TABLE */ + return x2nmodp(len2, 3); } /* ========================================================================= */ -local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2) -{ - int n; - unsigned long row; - unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ - unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ - - /* degenerate case (also disallow negative lengths) */ - if (len2 <= 0) - return crc1; - - /* put operator for one zero bit in odd */ - odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ - row = 1; - for (n = 1; n < GF2_DIM; n++) { - odd[n] = row; - row <<= 1; - } - - /* put operator for two zero bits in even */ - gf2_matrix_square(even, odd); - - /* put operator for four zero bits in odd */ - gf2_matrix_square(odd, even); - - /* apply len2 zeros to crc1 (first square will put the operator for one - zero byte, eight zero bits, in even) */ - do { - /* apply zeros operator for this bit of len2 */ - gf2_matrix_square(even, odd); - if (len2 & 1) - crc1 = gf2_matrix_times(even, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - if (len2 == 0) - break; - - /* another iteration of the loop with odd and even swapped */ - gf2_matrix_square(odd, even); - if (len2 & 1) - crc1 = gf2_matrix_times(odd, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - } while (len2 != 0); - - /* return combined crc */ - crc1 ^= crc2; - return crc1; +uLong ZEXPORT crc32_combine_gen(z_off_t len2) { + return crc32_combine_gen64((z_off64_t)len2); } /* ========================================================================= */ -uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) -{ - return crc32_combine_(crc1, crc2, len2); +uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op) { + if (op == 0) + return 0; + return multmodp(op, crc1 & 0xffffffff) ^ (crc2 & 0xffffffff); } -uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) -{ - return crc32_combine_(crc1, crc2, len2); +/* ========================================================================= */ +uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) { + return crc32_combine_op(crc1, crc2, crc32_combine_gen64(len2)); } +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) { + return crc32_combine64(crc1, crc2, (z_off64_t)len2); +} ABC_NAMESPACE_IMPL_END diff --git a/src/misc/zlib/crc32.h b/src/misc/zlib/crc32.h index d023439aa5..137df68d61 100644 --- a/src/misc/zlib/crc32.h +++ b/src/misc/zlib/crc32.h @@ -2,444 +2,9445 @@ * Generated automatically by crc32.c */ -ABC_NAMESPACE_HEADER_START - -local const unsigned long FAR crc_table[TBLS][256] = -{ - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL +local const z_crc_t FAR crc_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}; + +#ifdef W + +#if W == 8 + +local const z_word_t FAR crc_big_table[] = { + 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, + 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, + 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, + 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, + 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, + 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, + 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, + 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, + 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, + 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, + 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, + 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, + 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, + 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, + 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, + 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, + 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, + 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, + 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, + 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, + 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, + 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, + 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, + 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, + 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, + 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, + 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, + 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, + 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, + 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, + 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, + 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, + 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, + 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, + 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, + 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, + 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, + 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, + 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, + 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, + 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, + 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, + 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, + 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, + 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, + 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, + 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, + 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, + 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, + 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, + 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, + 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, + 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, + 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, + 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, + 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, + 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, + 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, + 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, + 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, + 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, + 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, + 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, + 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, + 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, + 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, + 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, + 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, + 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, + 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, + 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, + 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, + 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, + 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, + 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, + 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, + 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, + 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, + 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, + 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, + 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, + 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, + 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, + 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, + 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, + 0x8def022d00000000}; + +#else /* W == 4 */ + +local const z_word_t FAR crc_big_table[] = { + 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, + 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, + 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, + 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, + 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, + 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, + 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, + 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, + 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, + 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, + 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, + 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, + 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, + 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, + 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, + 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, + 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, + 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, + 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, + 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, + 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, + 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, + 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, + 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, + 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, + 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, + 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, + 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, + 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, + 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, + 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, + 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, + 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, + 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, + 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, + 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, + 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, + 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, + 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, + 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, + 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, + 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, + 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, + 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, + 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, + 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, + 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, + 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, + 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, + 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, + 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, + 0x8def022d}; + +#endif + +#if N == 1 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, + 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, + 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, + 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, + 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, + 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, + 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, + 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, + 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, + 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, + 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, + 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, + 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, + 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, + 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, + 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, + 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, + 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, + 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, + 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, + 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, + 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, + 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, + 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, + 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, + 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, + 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, + 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, + 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, + 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, + 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, + 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, + 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, + 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, + 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, + 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, + 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, + 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, + 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, + 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, + 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, + 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, + 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, + 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, + 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, + 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, + 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, + 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, + 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, + 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, + 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, + 0x264b06e6}, + {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, + 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, + 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, + 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, + 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, + 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, + 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, + 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, + 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, + 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, + 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, + 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, + 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, + 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, + 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, + 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, + 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, + 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, + 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, + 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, + 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, + 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, + 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, + 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, + 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, + 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, + 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, + 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, + 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, + 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, + 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, + 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, + 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, + 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, + 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, + 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, + 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, + 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, + 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, + 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, + 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, + 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, + 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, + 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, + 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, + 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, + 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, + 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, + 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, + 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, + 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, + 0x92364a30}, + {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, + 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, + 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, + 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, + 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, + 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, + 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, + 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, + 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, + 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, + 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, + 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, + 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, + 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, + 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, + 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, + 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, + 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, + 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, + 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, + 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, + 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, + 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, + 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, + 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, + 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, + 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, + 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, + 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, + 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, + 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, + 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, + 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, + 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, + 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, + 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, + 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, + 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, + 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, + 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, + 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, + 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, + 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, + 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, + 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, + 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, + 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, + 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, + 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, + 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, + 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, + 0xe4c4abcc}, + {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, + 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, + 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, + 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, + 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, + 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, + 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, + 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, + 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, + 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, + 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, + 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, + 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, + 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, + 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, + 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, + 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, + 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, + 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, + 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, + 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, + 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, + 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, + 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, + 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, + 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, + 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, + 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, + 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, + 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, + 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, + 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, + 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, + 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, + 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, + 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, + 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, + 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, + 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, + 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, + 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, + 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, + 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, + 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, + 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, + 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, + 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, + 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, + 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, + 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, + 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, + 0xca64c78c}, + {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, + 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, + 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, + 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, + 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, + 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, + 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, + 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, + 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, + 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, + 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, + 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, + 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, + 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, + 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, + 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, + 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, + 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, + 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, + 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, + 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, + 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, + 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, + 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, + 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, + 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, + 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, + 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, + 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, + 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, + 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, + 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, + 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, + 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, + 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, + 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, + 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, + 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, + 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, + 0xde0506f1}, + {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, + 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, + 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, + 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, + 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, + 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, + 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, + 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, + 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, + 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, + 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, + 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, + 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, + 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, + 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, + 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, + 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, + 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, + 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, + 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, + 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, + 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, + 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, + 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, + 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, + 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, + 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, + 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, + 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, + 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, + 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, + 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, + 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, + 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, + 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, + 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, + 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, + 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, + 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, + 0xbe9834ed}, + {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, + 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, + 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, + 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, + 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, + 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, + 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, + 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, + 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, + 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, + 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, + 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, + 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, + 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, + 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, + 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, + 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, + 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, + 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, + 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, + 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, + 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, + 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, + 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, + 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, + 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, + 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, + 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, + 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, + 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, + 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, + 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, + 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, + 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, + 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, + 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, + 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, + 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, + 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, + 0x9324fd72}, + {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, + 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, + 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, + 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, + 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, + 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, + 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, + 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, + 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, + 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, + 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, + 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, + 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, + 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, + 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, + 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, + 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, + 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, + 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, + 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, + 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, + 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, + 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, + 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, + 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, + 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, + 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, + 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, + 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, + 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, + 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, + 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, + 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, + 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, + 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, + 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, + 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, + 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, + 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, + 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, + 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, + 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, + 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, + 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, + 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, + 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, + 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, + 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, + 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, + 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, + 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, + 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, + 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, + 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, + 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, + 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, + 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, + 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, + 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, + 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, + 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, + 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, + 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, + 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, + 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, + 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, + 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, + 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, + 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, + 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, + 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, + 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, + 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, + 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, + 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, + 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, + 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, + 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, + 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, + 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, + 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, + 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, + 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, + 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, + 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, + 0x8def022d00000000}, + {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000, + 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000, + 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000, + 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000, + 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000, + 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000, + 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000, + 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000, + 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000, + 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000, + 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000, + 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000, + 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000, + 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000, + 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000, + 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000, + 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000, + 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000, + 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000, + 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000, + 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000, + 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000, + 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000, + 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000, + 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000, + 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000, + 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000, + 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000, + 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000, + 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000, + 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000, + 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000, + 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000, + 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000, + 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000, + 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000, + 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000, + 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000, + 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000, + 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000, + 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000, + 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000, + 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000, + 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000, + 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000, + 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000, + 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000, + 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000, + 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000, + 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000, + 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000, + 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000, + 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000, + 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000, + 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000, + 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000, + 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000, + 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000, + 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000, + 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000, + 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000, + 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000, + 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000, + 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000, + 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000, + 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000, + 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000, + 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000, + 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000, + 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000, + 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000, + 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000, + 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000, + 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000, + 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000, + 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000, + 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000, + 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000, + 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000, + 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000, + 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000, + 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000, + 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000, + 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000, + 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000, + 0x72fd249300000000}, + {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000, + 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000, + 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000, + 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000, + 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000, + 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000, + 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000, + 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000, + 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000, + 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000, + 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000, + 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000, + 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000, + 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000, + 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000, + 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000, + 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000, + 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000, + 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000, + 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000, + 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000, + 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000, + 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000, + 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000, + 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000, + 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000, + 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000, + 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000, + 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000, + 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000, + 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000, + 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000, + 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000, + 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000, + 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000, + 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000, + 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000, + 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000, + 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000, + 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000, + 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000, + 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000, + 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000, + 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000, + 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000, + 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000, + 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000, + 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000, + 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000, + 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000, + 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000, + 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000, + 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000, + 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000, + 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000, + 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000, + 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000, + 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000, + 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000, + 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000, + 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000, + 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000, + 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000, + 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000, + 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000, + 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000, + 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000, + 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000, + 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000, + 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000, + 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000, + 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000, + 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000, + 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000, + 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000, + 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000, + 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000, + 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000, + 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000, + 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000, + 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000, + 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000, + 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000, + 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000, + 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000, + 0xed3498be00000000}, + {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000, + 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000, + 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000, + 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000, + 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000, + 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000, + 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000, + 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000, + 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000, + 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000, + 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000, + 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000, + 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000, + 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000, + 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000, + 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000, + 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000, + 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000, + 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000, + 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000, + 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000, + 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000, + 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000, + 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000, + 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000, + 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000, + 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000, + 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000, + 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000, + 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000, + 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000, + 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000, + 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000, + 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000, + 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000, + 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000, + 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000, + 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000, + 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000, + 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000, + 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000, + 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000, + 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000, + 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000, + 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000, + 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000, + 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000, + 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000, + 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000, + 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000, + 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000, + 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000, + 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000, + 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000, + 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000, + 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000, + 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000, + 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000, + 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000, + 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000, + 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000, + 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000, + 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000, + 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000, + 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000, + 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000, + 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000, + 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000, + 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000, + 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000, + 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000, + 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000, + 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000, + 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000, + 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000, + 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000, + 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000, + 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000, + 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000, + 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000, + 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000, + 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000, + 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000, + 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000, + 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000, + 0xf10605de00000000}, + {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000, + 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000, + 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000, + 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000, + 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000, + 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000, + 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000, + 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000, + 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000, + 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000, + 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000, + 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000, + 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000, + 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000, + 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000, + 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000, + 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000, + 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000, + 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000, + 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000, + 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000, + 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000, + 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000, + 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000, + 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000, + 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000, + 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000, + 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000, + 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000, + 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000, + 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000, + 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000, + 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000, + 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000, + 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000, + 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000, + 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000, + 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000, + 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000, + 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000, + 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000, + 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000, + 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000, + 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000, + 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000, + 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000, + 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000, + 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000, + 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000, + 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000, + 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000, + 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000, + 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000, + 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000, + 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000, + 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000, + 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000, + 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000, + 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000, + 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000, + 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000, + 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000, + 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000, + 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000, + 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000, + 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000, + 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000, + 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000, + 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000, + 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000, + 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000, + 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000, + 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000, + 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000, + 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000, + 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000, + 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000, + 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000, + 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000, + 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000, + 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000, + 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000, + 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000, + 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000, + 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000, + 0x8cc764ca00000000}, + {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000, + 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000, + 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000, + 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000, + 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000, + 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000, + 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000, + 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000, + 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000, + 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000, + 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000, + 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000, + 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000, + 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000, + 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000, + 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000, + 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000, + 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000, + 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000, + 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000, + 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000, + 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000, + 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000, + 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000, + 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000, + 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000, + 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000, + 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000, + 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000, + 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000, + 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000, + 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000, + 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000, + 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000, + 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000, + 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000, + 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000, + 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000, + 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000, + 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000, + 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000, + 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000, + 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000, + 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000, + 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000, + 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000, + 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000, + 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000, + 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000, + 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000, + 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000, + 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000, + 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000, + 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000, + 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000, + 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000, + 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000, + 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000, + 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000, + 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000, + 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000, + 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000, + 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000, + 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000, + 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000, + 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000, + 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000, + 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000, + 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000, + 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000, + 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000, + 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000, + 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000, + 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000, + 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000, + 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000, + 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000, + 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000, + 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000, + 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000, + 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000, + 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000, + 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000, + 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000, + 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000, + 0xccabc4e400000000}, + {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000, + 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000, + 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000, + 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000, + 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000, + 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000, + 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000, + 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000, + 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000, + 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000, + 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000, + 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000, + 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000, + 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000, + 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000, + 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000, + 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000, + 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000, + 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000, + 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000, + 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000, + 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000, + 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000, + 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000, + 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000, + 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000, + 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000, + 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000, + 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000, + 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000, + 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000, + 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000, + 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000, + 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000, + 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000, + 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000, + 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000, + 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000, + 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000, + 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000, + 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000, + 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000, + 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000, + 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000, + 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000, + 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000, + 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000, + 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000, + 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000, + 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000, + 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000, + 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000, + 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000, + 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000, + 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000, + 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000, + 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000, + 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000, + 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000, + 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000, + 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000, + 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000, + 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000, + 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000, + 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000, + 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000, + 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000, + 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000, + 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000, + 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000, + 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000, + 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000, + 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000, + 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000, + 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000, + 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000, + 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000, + 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000, + 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000, + 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000, + 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000, + 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000, + 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000, + 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000, + 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000, + 0x304a369200000000}, + {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000, + 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000, + 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000, + 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000, + 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000, + 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000, + 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000, + 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000, + 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000, + 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000, + 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000, + 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000, + 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000, + 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000, + 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000, + 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000, + 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000, + 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000, + 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000, + 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000, + 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000, + 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000, + 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000, + 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000, + 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000, + 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000, + 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000, + 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000, + 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000, + 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000, + 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000, + 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000, + 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000, + 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000, + 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000, + 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000, + 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000, + 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000, + 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000, + 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000, + 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000, + 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000, + 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000, + 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000, + 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000, + 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000, + 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000, + 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000, + 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000, + 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000, + 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000, + 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000, + 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000, + 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000, + 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000, + 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000, + 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000, + 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000, + 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000, + 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000, + 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000, + 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000, + 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000, + 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000, + 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000, + 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000, + 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000, + 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000, + 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000, + 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000, + 0x6171384400000000, 0xff71928800000000, 0xe678578200000000, + 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000, + 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000, + 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000, + 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000, + 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000, + 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000, + 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000, + 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000, + 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000, + 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000, + 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000, + 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000, + 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000, + 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000, + 0xe6064b2600000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, + 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, + 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, + 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, + 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, + 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, + 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, + 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, + 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, + 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, + 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, + 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, + 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, + 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, + 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, + 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, + 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, + 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, + 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, + 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, + 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, + 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, + 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, + 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, + 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, + 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, + 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, + 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, + 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, + 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, + 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, + 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, + 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, + 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, + 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, + 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, + 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, + 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, + 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, + 0xde0506f1}, + {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, + 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, + 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, + 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, + 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, + 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, + 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, + 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, + 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, + 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, + 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, + 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, + 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, + 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, + 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, + 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, + 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, + 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, + 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, + 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, + 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, + 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, + 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, + 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, + 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, + 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, + 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, + 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, + 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, + 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, + 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, + 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, + 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, + 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, + 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, + 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, + 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, + 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, + 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, + 0xbe9834ed}, + {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, + 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, + 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, + 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, + 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, + 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, + 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, + 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, + 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, + 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, + 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, + 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, + 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, + 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, + 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, + 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, + 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, + 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, + 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, + 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, + 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, + 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, + 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, + 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, + 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, + 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, + 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, + 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, + 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, + 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, + 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, + 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, + 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, + 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, + 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, + 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, + 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, + 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, + 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, + 0x9324fd72}, + {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, + 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, + 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, + 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, + 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, + 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, + 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, + 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, + 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, + 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, + 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, + 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, + 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, + 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, + 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, + 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, + 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, + 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, + 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, + 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, + 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, + 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, + 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, + 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, + 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, + 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, + 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, + 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, + 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, + 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, + 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, + 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, + 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, + 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, + 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, + 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, + 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, + 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, + 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, + 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, + 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, + 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, + 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, + 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, + 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, + 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, + 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, + 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, + 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, + 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, + 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, + 0x8def022d}, + {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64, + 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1, + 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e, + 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61, + 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82, + 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff, + 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7, + 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da, + 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139, + 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6, + 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89, + 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c, + 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0, + 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d, + 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a, + 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177, + 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de, + 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b, + 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824, + 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e, + 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad, + 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0, + 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d, + 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60, + 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83, + 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822, + 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d, + 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8, + 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171, + 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c, + 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b, + 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6, + 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca, + 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f, + 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430, + 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf, + 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c, + 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51, + 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9, + 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84, + 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67, + 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398, + 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7, + 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62, + 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e, + 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923, + 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4, + 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9, + 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070, + 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5, + 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a, + 0x72fd2493}, + {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907, + 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f, + 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a, + 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e, + 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512, + 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14, + 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b, + 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d, + 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731, + 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925, + 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620, + 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28, + 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70, + 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176, + 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d, + 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b, + 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b, + 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63, + 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266, + 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a, + 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446, + 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40, + 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557, + 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51, + 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d, + 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0, + 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5, + 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed, + 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd, + 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb, + 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0, + 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6, + 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de, + 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6, + 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3, + 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7, + 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb, + 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd, + 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92, + 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094, + 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598, + 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c, + 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489, + 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81, + 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9, + 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af, + 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4, + 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2, + 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2, + 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba, + 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf, + 0xed3498be}, + {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f, + 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d, + 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0, + 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42, + 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95, + 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2, + 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a, + 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d, + 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea, + 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748, + 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5, + 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27, + 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b, + 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac, + 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4, + 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3, + 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44, + 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6, + 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b, + 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329, + 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe, + 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9, + 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1, + 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6, + 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921, + 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555, + 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8, + 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a, + 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd, + 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a, + 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2, + 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5, + 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2, + 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330, + 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad, + 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f, + 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8, + 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef, + 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc, + 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb, + 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c, + 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e, + 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03, + 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1, + 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6, + 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1, + 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9, + 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e, + 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409, + 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb, + 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966, + 0xf10605de}}; + +#endif + +#endif + +#if N == 2 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, + 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, + 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, + 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, + 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, + 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, + 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, + 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, + 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, + 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, + 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, + 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, + 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, + 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, + 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, + 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, + 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, + 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, + 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, + 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, + 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, + 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, + 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, + 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, + 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, + 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, + 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, + 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, + 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, + 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, + 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, + 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, + 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, + 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, + 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, + 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, + 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, + 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, + 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, + 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, + 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, + 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, + 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, + 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, + 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, + 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, + 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, + 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, + 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, + 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, + 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, + 0x0d7139d7}, + {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, + 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, + 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, + 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, + 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, + 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, + 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, + 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, + 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, + 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, + 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, + 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, + 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, + 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, + 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, + 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, + 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, + 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, + 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, + 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, + 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, + 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, + 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, + 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, + 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, + 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, + 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, + 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, + 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, + 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, + 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, + 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, + 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, + 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, + 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, + 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, + 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, + 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, + 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, + 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, + 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, + 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, + 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, + 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, + 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, + 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, + 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, + 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, + 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, + 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, + 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, + 0x1c53e98a}, + {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, + 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, + 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, + 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, + 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, + 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, + 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, + 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, + 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, + 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, + 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, + 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, + 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, + 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, + 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, + 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, + 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, + 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, + 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, + 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, + 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, + 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, + 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, + 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, + 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, + 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, + 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, + 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, + 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, + 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, + 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, + 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, + 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, + 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, + 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, + 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, + 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, + 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, + 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, + 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, + 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, + 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, + 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, + 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, + 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, + 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, + 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, + 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, + 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, + 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, + 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, + 0x3f88e851}, + {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, + 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, + 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, + 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, + 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, + 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, + 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, + 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, + 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, + 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, + 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, + 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, + 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, + 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, + 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, + 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, + 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, + 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, + 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, + 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, + 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, + 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, + 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, + 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, + 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, + 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, + 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, + 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, + 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, + 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, + 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, + 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, + 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, + 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, + 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, + 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, + 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, + 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, + 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, + 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, + 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, + 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, + 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, + 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, + 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, + 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, + 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, + 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, + 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, + 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, + 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, + 0x3dee8ca6}, + {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, + 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, + 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, + 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, + 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, + 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, + 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, + 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, + 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, + 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, + 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, + 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, + 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, + 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, + 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, + 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, + 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, + 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, + 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, + 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, + 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, + 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, + 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, + 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, + 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, + 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, + 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, + 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, + 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, + 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, + 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, + 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, + 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, + 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, + 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, + 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, + 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, + 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, + 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, + 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, + 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, + 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, + 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, + 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, + 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, + 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, + 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, + 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, + 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, + 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, + 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, + 0x36197165}, + {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, + 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, + 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, + 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, + 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, + 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, + 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, + 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, + 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, + 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, + 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, + 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, + 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, + 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, + 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, + 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, + 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, + 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, + 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, + 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, + 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, + 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, + 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, + 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, + 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, + 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, + 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, + 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, + 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, + 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, + 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, + 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, + 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, + 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, + 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, + 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, + 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, + 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, + 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, + 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, + 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, + 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, + 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, + 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, + 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, + 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, + 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, + 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, + 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, + 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, + 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, + 0x1a3b93aa}, + {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, + 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, + 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, + 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, + 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, + 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, + 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, + 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, + 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, + 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, + 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, + 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, + 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, + 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, + 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, + 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, + 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, + 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, + 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, + 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, + 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, + 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, + 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, + 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, + 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, + 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, + 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, + 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, + 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, + 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, + 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, + 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, + 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, + 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, + 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, + 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, + 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, + 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, + 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, + 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, + 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, + 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, + 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, + 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, + 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, + 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, + 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, + 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, + 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, + 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, + 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, + 0xe147d714}, + {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, + 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, + 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, + 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, + 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, + 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, + 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, + 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, + 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, + 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, + 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, + 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, + 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, + 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, + 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, + 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, + 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, + 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, + 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, + 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, + 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, + 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, + 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, + 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, + 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, + 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, + 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, + 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, + 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, + 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, + 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, + 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, + 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, + 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, + 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, + 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, + 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, + 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, + 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, + 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, + 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, + 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, + 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, + 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, + 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, + 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, + 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, + 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, + 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, + 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, + 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, + 0x494f0c4b}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000, + 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000, + 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000, + 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000, + 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000, + 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000, + 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000, + 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000, + 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000, + 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000, + 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000, + 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000, + 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000, + 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000, + 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000, + 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000, + 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000, + 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000, + 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000, + 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000, + 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000, + 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000, + 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000, + 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000, + 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000, + 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000, + 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000, + 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000, + 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000, + 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000, + 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000, + 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000, + 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000, + 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000, + 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000, + 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000, + 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000, + 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000, + 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000, + 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000, + 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000, + 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000, + 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000, + 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000, + 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000, + 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000, + 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000, + 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000, + 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000, + 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000, + 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000, + 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000, + 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000, + 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000, + 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000, + 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000, + 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000, + 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000, + 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000, + 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000, + 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000, + 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000, + 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000, + 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000, + 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000, + 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000, + 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000, + 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000, + 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000, + 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000, + 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000, + 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000, + 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000, + 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000, + 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000, + 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000, + 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000, + 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000, + 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000, + 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000, + 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000, + 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000, + 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000, + 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000, + 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000, + 0x4b0c4f4900000000}, + {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000, + 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000, + 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000, + 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000, + 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000, + 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000, + 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000, + 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000, + 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000, + 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000, + 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000, + 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000, + 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000, + 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000, + 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000, + 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000, + 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000, + 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000, + 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000, + 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000, + 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000, + 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000, + 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000, + 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000, + 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000, + 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000, + 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000, + 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000, + 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000, + 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000, + 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000, + 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000, + 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000, + 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000, + 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000, + 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000, + 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000, + 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000, + 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000, + 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000, + 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000, + 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000, + 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000, + 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000, + 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000, + 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000, + 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000, + 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000, + 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000, + 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000, + 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000, + 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000, + 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000, + 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000, + 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000, + 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000, + 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000, + 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000, + 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000, + 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000, + 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000, + 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000, + 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000, + 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000, + 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000, + 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000, + 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000, + 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000, + 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000, + 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000, + 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000, + 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000, + 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000, + 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000, + 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000, + 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000, + 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000, + 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000, + 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000, + 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000, + 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000, + 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000, + 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000, + 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000, + 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000, + 0x14d747e100000000}, + {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000, + 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000, + 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000, + 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000, + 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000, + 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000, + 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000, + 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000, + 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000, + 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000, + 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000, + 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000, + 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000, + 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000, + 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000, + 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000, + 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000, + 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000, + 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000, + 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000, + 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000, + 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000, + 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000, + 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000, + 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000, + 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000, + 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000, + 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000, + 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000, + 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000, + 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000, + 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000, + 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000, + 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000, + 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000, + 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000, + 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000, + 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000, + 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000, + 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000, + 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000, + 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000, + 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000, + 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000, + 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000, + 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000, + 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000, + 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000, + 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000, + 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000, + 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000, + 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000, + 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000, + 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000, + 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000, + 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000, + 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000, + 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000, + 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000, + 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000, + 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000, + 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000, + 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000, + 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000, + 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000, + 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000, + 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000, + 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000, + 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000, + 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000, + 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000, + 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000, + 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000, + 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000, + 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000, + 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000, + 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000, + 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000, + 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000, + 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000, + 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000, + 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000, + 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000, + 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000, + 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000, + 0xaa933b1a00000000}, + {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000, + 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000, + 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000, + 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000, + 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000, + 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000, + 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000, + 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000, + 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000, + 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000, + 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000, + 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000, + 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000, + 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000, + 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000, + 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000, + 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000, + 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000, + 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000, + 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000, + 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000, + 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000, + 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000, + 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000, + 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000, + 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000, + 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000, + 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000, + 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000, + 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000, + 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000, + 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000, + 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000, + 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000, + 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000, + 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000, + 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000, + 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000, + 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000, + 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000, + 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000, + 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000, + 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000, + 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000, + 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000, + 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000, + 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000, + 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000, + 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000, + 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000, + 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000, + 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000, + 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000, + 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000, + 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000, + 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000, + 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000, + 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000, + 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000, + 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000, + 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000, + 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000, + 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000, + 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000, + 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000, + 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000, + 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000, + 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000, + 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000, + 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000, + 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000, + 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000, + 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000, + 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000, + 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000, + 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000, + 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000, + 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000, + 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000, + 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000, + 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000, + 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000, + 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000, + 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000, + 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000, + 0x6571193600000000}, + {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000, + 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000, + 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000, + 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000, + 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000, + 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000, + 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000, + 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000, + 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000, + 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000, + 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000, + 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000, + 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000, + 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000, + 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000, + 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000, + 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000, + 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000, + 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000, + 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000, + 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000, + 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000, + 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000, + 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000, + 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000, + 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000, + 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000, + 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000, + 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000, + 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000, + 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000, + 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000, + 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000, + 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000, + 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000, + 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000, + 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000, + 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000, + 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000, + 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000, + 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000, + 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000, + 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000, + 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000, + 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000, + 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000, + 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000, + 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000, + 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000, + 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000, + 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000, + 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000, + 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000, + 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000, + 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000, + 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000, + 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000, + 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000, + 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000, + 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000, + 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000, + 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000, + 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000, + 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000, + 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000, + 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000, + 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000, + 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000, + 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000, + 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000, + 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000, + 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000, + 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000, + 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000, + 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000, + 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000, + 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000, + 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000, + 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000, + 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000, + 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000, + 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000, + 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000, + 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000, + 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000, + 0xa68cee3d00000000}, + {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000, + 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000, + 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000, + 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000, + 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000, + 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000, + 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000, + 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000, + 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000, + 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000, + 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000, + 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000, + 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000, + 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000, + 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000, + 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000, + 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000, + 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000, + 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000, + 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000, + 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000, + 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000, + 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000, + 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000, + 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000, + 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000, + 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000, + 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000, + 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000, + 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000, + 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000, + 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000, + 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000, + 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000, + 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000, + 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000, + 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000, + 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000, + 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000, + 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000, + 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000, + 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000, + 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000, + 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000, + 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000, + 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000, + 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000, + 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000, + 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000, + 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000, + 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000, + 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000, + 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000, + 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000, + 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000, + 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000, + 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000, + 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000, + 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000, + 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000, + 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000, + 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000, + 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000, + 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000, + 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000, + 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000, + 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000, + 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000, + 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000, + 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000, + 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000, + 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000, + 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000, + 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000, + 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000, + 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000, + 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000, + 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000, + 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000, + 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000, + 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000, + 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000, + 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000, + 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000, + 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000, + 0x51e8883f00000000}, + {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000, + 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000, + 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000, + 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000, + 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000, + 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000, + 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000, + 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000, + 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000, + 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000, + 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000, + 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000, + 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000, + 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000, + 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000, + 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000, + 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000, + 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000, + 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000, + 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000, + 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000, + 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000, + 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000, + 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000, + 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000, + 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000, + 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000, + 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000, + 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000, + 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000, + 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000, + 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000, + 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000, + 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000, + 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000, + 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000, + 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000, + 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000, + 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000, + 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000, + 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000, + 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000, + 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000, + 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000, + 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000, + 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000, + 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000, + 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000, + 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000, + 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000, + 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000, + 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000, + 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000, + 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000, + 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000, + 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000, + 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000, + 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000, + 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000, + 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000, + 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000, + 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000, + 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000, + 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000, + 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000, + 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000, + 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000, + 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000, + 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000, + 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000, + 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000, + 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000, + 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000, + 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000, + 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000, + 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000, + 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000, + 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000, + 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000, + 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000, + 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000, + 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000, + 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000, + 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000, + 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000, + 0x8ae9531c00000000}, + {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000, + 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000, + 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000, + 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000, + 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000, + 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000, + 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000, + 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000, + 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000, + 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000, + 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000, + 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000, + 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000, + 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000, + 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000, + 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000, + 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000, + 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000, + 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000, + 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000, + 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000, + 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000, + 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000, + 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000, + 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000, + 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000, + 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000, + 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000, + 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000, + 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000, + 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000, + 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000, + 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000, + 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000, + 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000, + 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000, + 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000, + 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000, + 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000, + 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000, + 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000, + 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000, + 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000, + 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000, + 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000, + 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000, + 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000, + 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000, + 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000, + 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000, + 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000, + 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000, + 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000, + 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000, + 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000, + 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000, + 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000, + 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000, + 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000, + 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000, + 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000, + 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000, + 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000, + 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000, + 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000, + 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000, + 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000, + 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000, + 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000, + 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000, + 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000, + 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000, + 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000, + 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000, + 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000, + 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000, + 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000, + 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000, + 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000, + 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000, + 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000, + 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000, + 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000, + 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000, + 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000, + 0xd739710d00000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, + 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, + 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, + 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, + 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, + 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, + 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, + 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, + 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, + 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, + 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, + 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, + 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, + 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, + 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, + 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, + 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, + 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, + 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, + 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, + 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, + 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, + 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, + 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, + 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, + 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, + 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, + 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, + 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, + 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, + 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, + 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, + 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, + 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, + 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, + 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, + 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, + 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, + 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, + 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, + 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, + 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, + 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, + 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, + 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, + 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, + 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, + 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, + 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, + 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, + 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, + 0x264b06e6}, + {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, + 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, + 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, + 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, + 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, + 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, + 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, + 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, + 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, + 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, + 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, + 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, + 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, + 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, + 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, + 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, + 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, + 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, + 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, + 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, + 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, + 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, + 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, + 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, + 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, + 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, + 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, + 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, + 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, + 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, + 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, + 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, + 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, + 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, + 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, + 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, + 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, + 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, + 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, + 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, + 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, + 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, + 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, + 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, + 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, + 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, + 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, + 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, + 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, + 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, + 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, + 0x92364a30}, + {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, + 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, + 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, + 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, + 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, + 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, + 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, + 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, + 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, + 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, + 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, + 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, + 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, + 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, + 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, + 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, + 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, + 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, + 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, + 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, + 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, + 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, + 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, + 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, + 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, + 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, + 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, + 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, + 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, + 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, + 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, + 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, + 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, + 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, + 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, + 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, + 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, + 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, + 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, + 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, + 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, + 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, + 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, + 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, + 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, + 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, + 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, + 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, + 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, + 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, + 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, + 0xe4c4abcc}, + {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, + 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, + 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, + 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, + 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, + 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, + 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, + 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, + 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, + 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, + 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, + 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, + 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, + 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, + 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, + 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, + 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, + 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, + 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, + 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, + 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, + 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, + 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, + 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, + 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, + 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, + 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, + 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, + 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, + 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, + 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, + 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, + 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, + 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, + 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, + 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, + 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, + 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, + 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, + 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, + 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, + 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, + 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, + 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, + 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, + 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, + 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, + 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, + 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, + 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, + 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, + 0xca64c78c}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5, + 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d, + 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf, + 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027, + 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050, + 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098, + 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb, + 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173, + 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104, + 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c, + 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e, + 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6, + 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358, + 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390, + 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312, + 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da, + 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd, + 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335, + 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387, + 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de, + 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9, + 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261, + 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283, + 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b, + 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c, + 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c, + 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e, + 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6, + 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1, + 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619, + 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b, + 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653, + 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785, + 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d, + 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf, + 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757, + 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720, + 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8, + 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593, + 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b, + 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c, + 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4, + 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506, + 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe, + 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428, + 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0, + 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462, + 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa, + 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd, + 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445, + 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7, + 0x8cc764ca}, + {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b, + 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27, + 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a, + 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285, + 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef, + 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf, + 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a, + 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a, + 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70, + 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf, + 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2, + 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e, + 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f, + 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f, + 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae, + 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe, + 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97, + 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b, + 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436, + 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e, + 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4, + 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4, + 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46, + 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716, + 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c, + 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5, + 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8, + 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774, + 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d, + 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d, + 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc, + 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec, + 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82, + 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e, + 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623, + 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c, + 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6, + 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6, + 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c, + 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c, + 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66, + 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9, + 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4, + 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978, + 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416, + 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946, + 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7, + 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7, + 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e, + 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32, + 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f, + 0xccabc4e4}, + {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4, + 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895, + 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50, + 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656, + 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154, + 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906, + 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258, + 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a, + 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08, + 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e, + 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb, + 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa, + 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44, + 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316, + 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0, + 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2, + 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7, + 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6, + 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73, + 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba, + 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8, + 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea, + 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b, + 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29, + 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b, + 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e, + 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb, + 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a, + 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef, + 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd, + 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b, + 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019, + 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3, + 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2, + 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417, + 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11, + 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13, + 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241, + 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b, + 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09, + 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b, + 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d, + 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8, + 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9, + 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003, + 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851, + 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7, + 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5, + 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190, + 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1, + 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134, + 0x304a3692}, + {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84, + 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f, + 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15, + 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2, + 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf, + 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7, + 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb, + 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3, + 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae, + 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749, + 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243, + 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8, + 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29, + 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61, + 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8, + 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0, + 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1, + 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a, + 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40, + 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e, + 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03, + 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b, + 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee, + 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6, + 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb, + 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f, + 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495, + 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e, + 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f, + 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067, + 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be, + 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6, + 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e, + 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5, + 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf, + 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958, + 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305, + 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d, + 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338, + 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370, + 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d, + 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca, + 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0, + 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b, + 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083, + 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb, + 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012, + 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a, + 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b, + 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0, + 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea, + 0xe6064b26}}; + +#endif + +#endif + +#if N == 3 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, + 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, + 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, + 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, + 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, + 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, + 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, + 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, + 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, + 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, + 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, + 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, + 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, + 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, + 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, + 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, + 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, + 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, + 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, + 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, + 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, + 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, + 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, + 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, + 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, + 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, + 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, + 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, + 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, + 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, + 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, + 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, + 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, + 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, + 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, + 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, + 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, + 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, + 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, + 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, + 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, + 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, + 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, + 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, + 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, + 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, + 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, + 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, + 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, + 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, + 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, + 0x09cd8551}, + {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, + 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, + 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, + 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, + 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, + 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, + 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, + 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, + 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, + 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, + 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, + 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, + 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, + 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, + 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, + 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, + 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, + 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, + 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, + 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, + 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, + 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, + 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, + 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, + 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, + 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, + 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, + 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, + 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, + 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, + 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, + 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, + 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, + 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, + 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, + 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, + 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, + 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, + 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, + 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, + 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, + 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, + 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, + 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, + 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, + 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, + 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, + 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, + 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, + 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, + 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, + 0x7bc97a0c}, + {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, + 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, + 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, + 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, + 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, + 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, + 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, + 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, + 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, + 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, + 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, + 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, + 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, + 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, + 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, + 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, + 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, + 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, + 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, + 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, + 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, + 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, + 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, + 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, + 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, + 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, + 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, + 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, + 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, + 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, + 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, + 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, + 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, + 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, + 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, + 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, + 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, + 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, + 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, + 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, + 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, + 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, + 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, + 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, + 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, + 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, + 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, + 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, + 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, + 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, + 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, + 0x7851a2ca}, + {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, + 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, + 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, + 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, + 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, + 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, + 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, + 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, + 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, + 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, + 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, + 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, + 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, + 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, + 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, + 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, + 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, + 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, + 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, + 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, + 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, + 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, + 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, + 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, + 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, + 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, + 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, + 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, + 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, + 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, + 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, + 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, + 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, + 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, + 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, + 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, + 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, + 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, + 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, + 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, + 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, + 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, + 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, + 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, + 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, + 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, + 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, + 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, + 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, + 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, + 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, + 0x566b6848}, + {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, + 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, + 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, + 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, + 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, + 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, + 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, + 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, + 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, + 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, + 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, + 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, + 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, + 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, + 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, + 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, + 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, + 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, + 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, + 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, + 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, + 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, + 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, + 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, + 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, + 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, + 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, + 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, + 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, + 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, + 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, + 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, + 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, + 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, + 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, + 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, + 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, + 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, + 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, + 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, + 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, + 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, + 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, + 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, + 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, + 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, + 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, + 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, + 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, + 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, + 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, + 0xd8ac6b35}, + {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, + 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, + 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, + 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, + 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, + 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, + 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, + 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, + 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, + 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, + 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, + 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, + 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, + 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, + 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, + 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, + 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, + 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, + 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, + 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, + 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, + 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, + 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, + 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, + 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, + 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, + 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, + 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, + 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, + 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, + 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, + 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, + 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, + 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, + 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, + 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, + 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, + 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, + 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, + 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, + 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, + 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, + 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, + 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, + 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, + 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, + 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, + 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, + 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, + 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, + 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, + 0xa140efa8}, + {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, + 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, + 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, + 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, + 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, + 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, + 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, + 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, + 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, + 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, + 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, + 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, + 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, + 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, + 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, + 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, + 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, + 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, + 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, + 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, + 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, + 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, + 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, + 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, + 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, + 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, + 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, + 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, + 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, + 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, + 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, + 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, + 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, + 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, + 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, + 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, + 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, + 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, + 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, + 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, + 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, + 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, + 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, + 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, + 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, + 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, + 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, + 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, + 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, + 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, + 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, + 0x917cd6a1}, + {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, + 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, + 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, + 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, + 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, + 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, + 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, + 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, + 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, + 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, + 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, + 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, + 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, + 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, + 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, + 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, + 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, + 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, + 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, + 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, + 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, + 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, + 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, + 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, + 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, + 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, + 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, + 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, + 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, + 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, + 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, + 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, + 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, + 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, + 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, + 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, + 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, + 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, + 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, + 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, + 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, + 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, + 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, + 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, + 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, + 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, + 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, + 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, + 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, + 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, + 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, + 0x18ba364e}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000, + 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000, + 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000, + 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000, + 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000, + 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000, + 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000, + 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000, + 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000, + 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000, + 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000, + 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000, + 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000, + 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000, + 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000, + 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000, + 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000, + 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000, + 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000, + 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000, + 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000, + 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000, + 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000, + 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000, + 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000, + 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000, + 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000, + 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000, + 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000, + 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000, + 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000, + 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000, + 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000, + 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000, + 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000, + 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000, + 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000, + 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000, + 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000, + 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000, + 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000, + 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000, + 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000, + 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000, + 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000, + 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000, + 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000, + 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000, + 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000, + 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000, + 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000, + 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000, + 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000, + 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000, + 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000, + 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000, + 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000, + 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000, + 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000, + 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000, + 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000, + 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000, + 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000, + 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000, + 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000, + 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000, + 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000, + 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000, + 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000, + 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000, + 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000, + 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000, + 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000, + 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000, + 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000, + 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000, + 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000, + 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000, + 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000, + 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000, + 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000, + 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000, + 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000, + 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000, + 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000, + 0x4e36ba1800000000}, + {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000, + 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000, + 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000, + 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000, + 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000, + 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000, + 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000, + 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000, + 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000, + 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000, + 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000, + 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000, + 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000, + 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000, + 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000, + 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000, + 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000, + 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000, + 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000, + 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000, + 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000, + 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000, + 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000, + 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000, + 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000, + 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000, + 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000, + 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000, + 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000, + 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000, + 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000, + 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000, + 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000, + 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000, + 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000, + 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000, + 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000, + 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000, + 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000, + 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000, + 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000, + 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000, + 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000, + 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000, + 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000, + 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000, + 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000, + 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000, + 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000, + 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000, + 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000, + 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000, + 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000, + 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000, + 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000, + 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000, + 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000, + 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000, + 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000, + 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000, + 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000, + 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000, + 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000, + 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000, + 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000, + 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000, + 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000, + 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000, + 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000, + 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000, + 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000, + 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000, + 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000, + 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000, + 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000, + 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000, + 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000, + 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000, + 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000, + 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000, + 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000, + 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000, + 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000, + 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000, + 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000, + 0xa1d67c9100000000}, + {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000, + 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000, + 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000, + 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000, + 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000, + 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000, + 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000, + 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000, + 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000, + 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000, + 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000, + 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000, + 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000, + 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000, + 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000, + 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000, + 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000, + 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000, + 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000, + 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000, + 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000, + 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000, + 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000, + 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000, + 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000, + 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000, + 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000, + 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000, + 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000, + 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000, + 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000, + 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000, + 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000, + 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000, + 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000, + 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000, + 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000, + 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000, + 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000, + 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000, + 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000, + 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000, + 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000, + 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000, + 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000, + 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000, + 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000, + 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000, + 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000, + 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000, + 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000, + 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000, + 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000, + 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000, + 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000, + 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000, + 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000, + 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000, + 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000, + 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000, + 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000, + 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000, + 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000, + 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000, + 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000, + 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000, + 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000, + 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000, + 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000, + 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000, + 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000, + 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000, + 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000, + 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000, + 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000, + 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000, + 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000, + 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000, + 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000, + 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000, + 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000, + 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000, + 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000, + 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000, + 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000, + 0xa8ef40a100000000}, + {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000, + 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000, + 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000, + 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000, + 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000, + 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000, + 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000, + 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000, + 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000, + 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000, + 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000, + 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000, + 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000, + 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000, + 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000, + 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000, + 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000, + 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000, + 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000, + 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000, + 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000, + 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000, + 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000, + 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000, + 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000, + 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000, + 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000, + 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000, + 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000, + 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000, + 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000, + 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000, + 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000, + 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000, + 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000, + 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000, + 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000, + 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000, + 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000, + 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000, + 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000, + 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000, + 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000, + 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000, + 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000, + 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000, + 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000, + 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000, + 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000, + 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000, + 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000, + 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000, + 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000, + 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000, + 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000, + 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000, + 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000, + 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000, + 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000, + 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000, + 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000, + 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000, + 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000, + 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000, + 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000, + 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000, + 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000, + 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000, + 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000, + 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000, + 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000, + 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000, + 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000, + 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000, + 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000, + 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000, + 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000, + 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000, + 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000, + 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000, + 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000, + 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000, + 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000, + 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000, + 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000, + 0x356bacd800000000}, + {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000, + 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000, + 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000, + 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000, + 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000, + 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000, + 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000, + 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000, + 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000, + 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000, + 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000, + 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000, + 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000, + 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000, + 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000, + 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000, + 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000, + 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000, + 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000, + 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000, + 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000, + 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000, + 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000, + 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000, + 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000, + 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000, + 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000, + 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000, + 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000, + 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000, + 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000, + 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000, + 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000, + 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000, + 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000, + 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000, + 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000, + 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000, + 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000, + 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000, + 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000, + 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000, + 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000, + 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000, + 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000, + 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000, + 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000, + 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000, + 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000, + 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000, + 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000, + 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000, + 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000, + 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000, + 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000, + 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000, + 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000, + 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000, + 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000, + 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000, + 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000, + 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000, + 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000, + 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000, + 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000, + 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000, + 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000, + 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000, + 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000, + 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000, + 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000, + 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000, + 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000, + 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000, + 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000, + 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000, + 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000, + 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000, + 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000, + 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000, + 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000, + 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000, + 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000, + 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000, + 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000, + 0x48686b5600000000}, + {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000, + 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000, + 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000, + 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000, + 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000, + 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000, + 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000, + 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000, + 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000, + 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000, + 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000, + 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000, + 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000, + 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000, + 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000, + 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000, + 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000, + 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000, + 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000, + 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000, + 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000, + 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000, + 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000, + 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000, + 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000, + 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000, + 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000, + 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000, + 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000, + 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000, + 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000, + 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000, + 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000, + 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000, + 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000, + 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000, + 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000, + 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000, + 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000, + 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000, + 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000, + 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000, + 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000, + 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000, + 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000, + 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000, + 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000, + 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000, + 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000, + 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000, + 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000, + 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000, + 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000, + 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000, + 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000, + 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000, + 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000, + 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000, + 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000, + 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000, + 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000, + 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000, + 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000, + 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000, + 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000, + 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000, + 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000, + 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000, + 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000, + 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000, + 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000, + 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000, + 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000, + 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000, + 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000, + 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000, + 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000, + 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000, + 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000, + 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000, + 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000, + 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000, + 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000, + 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000, + 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000, + 0xcaa2517800000000}, + {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000, + 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000, + 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000, + 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000, + 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000, + 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000, + 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000, + 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000, + 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000, + 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000, + 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000, + 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000, + 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000, + 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000, + 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000, + 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000, + 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000, + 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000, + 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000, + 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000, + 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000, + 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000, + 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000, + 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000, + 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000, + 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000, + 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000, + 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000, + 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000, + 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000, + 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000, + 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000, + 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000, + 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000, + 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000, + 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000, + 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000, + 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000, + 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000, + 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000, + 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000, + 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000, + 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000, + 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000, + 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000, + 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000, + 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000, + 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000, + 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000, + 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000, + 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000, + 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000, + 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000, + 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000, + 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000, + 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000, + 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000, + 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000, + 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000, + 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000, + 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000, + 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000, + 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000, + 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000, + 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000, + 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000, + 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000, + 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000, + 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000, + 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000, + 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000, + 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000, + 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000, + 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000, + 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000, + 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000, + 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000, + 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000, + 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000, + 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000, + 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000, + 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000, + 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000, + 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000, + 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000, + 0x0c7ac97b00000000}, + {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000, + 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000, + 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000, + 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000, + 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000, + 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000, + 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000, + 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000, + 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000, + 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000, + 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000, + 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000, + 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000, + 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000, + 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000, + 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000, + 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000, + 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000, + 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000, + 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000, + 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000, + 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000, + 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000, + 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000, + 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000, + 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000, + 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000, + 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000, + 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000, + 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000, + 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000, + 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000, + 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000, + 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000, + 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000, + 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000, + 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000, + 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000, + 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000, + 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000, + 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000, + 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000, + 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000, + 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000, + 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000, + 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000, + 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000, + 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000, + 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000, + 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000, + 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000, + 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000, + 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000, + 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000, + 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000, + 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000, + 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000, + 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000, + 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000, + 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000, + 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000, + 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000, + 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000, + 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000, + 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000, + 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000, + 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000, + 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000, + 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000, + 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000, + 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000, + 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000, + 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000, + 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000, + 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000, + 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000, + 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000, + 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000, + 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000, + 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000, + 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000, + 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000, + 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000, + 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000, + 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000, + 0x5185cd0900000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, + 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, + 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, + 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, + 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, + 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, + 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, + 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, + 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, + 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, + 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, + 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, + 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, + 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, + 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, + 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, + 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, + 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, + 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, + 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, + 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, + 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, + 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, + 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, + 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, + 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, + 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, + 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, + 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, + 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, + 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, + 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, + 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, + 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, + 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, + 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, + 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, + 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, + 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, + 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, + 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, + 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, + 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, + 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, + 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, + 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, + 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, + 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, + 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, + 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, + 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, + 0x36197165}, + {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, + 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, + 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, + 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, + 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, + 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, + 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, + 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, + 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, + 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, + 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, + 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, + 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, + 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, + 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, + 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, + 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, + 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, + 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, + 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, + 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, + 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, + 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, + 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, + 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, + 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, + 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, + 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, + 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, + 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, + 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, + 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, + 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, + 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, + 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, + 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, + 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, + 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, + 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, + 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, + 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, + 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, + 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, + 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, + 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, + 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, + 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, + 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, + 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, + 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, + 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, + 0x1a3b93aa}, + {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, + 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, + 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, + 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, + 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, + 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, + 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, + 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, + 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, + 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, + 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, + 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, + 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, + 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, + 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, + 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, + 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, + 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, + 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, + 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, + 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, + 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, + 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, + 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, + 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, + 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, + 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, + 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, + 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, + 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, + 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, + 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, + 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, + 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, + 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, + 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, + 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, + 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, + 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, + 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, + 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, + 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, + 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, + 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, + 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, + 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, + 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, + 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, + 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, + 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, + 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, + 0xe147d714}, + {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, + 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, + 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, + 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, + 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, + 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, + 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, + 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, + 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, + 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, + 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, + 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, + 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, + 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, + 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, + 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, + 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, + 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, + 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, + 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, + 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, + 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, + 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, + 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, + 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, + 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, + 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, + 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, + 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, + 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, + 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, + 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, + 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, + 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, + 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, + 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, + 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, + 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, + 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, + 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, + 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, + 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, + 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, + 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, + 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, + 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, + 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, + 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, + 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, + 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, + 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, + 0x494f0c4b}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d, + 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac, + 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8, + 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95, + 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817, + 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d, + 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac, + 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6, + 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564, + 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39, + 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d, + 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac, + 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de, + 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594, + 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b, + 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01, + 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f, + 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de, + 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba, + 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65, + 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7, + 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad, + 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de, + 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294, + 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716, + 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71, + 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15, + 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4, + 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca, + 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280, + 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f, + 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15, + 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9, + 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748, + 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c, + 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971, + 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3, + 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9, + 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196, + 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc, + 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e, + 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03, + 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67, + 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296, + 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a, + 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170, + 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af, + 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5, + 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb, + 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a, + 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e, + 0x4b0c4f49}, + {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09, + 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc, + 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e, + 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc, + 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934, + 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2, + 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b, + 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad, + 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155, + 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187, + 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65, + 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390, + 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e, + 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378, + 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889, + 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f, + 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0, + 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145, + 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7, + 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a, + 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2, + 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924, + 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2, + 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514, + 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec, + 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709, + 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb, + 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e, + 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1, + 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227, + 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6, + 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030, + 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0, + 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55, + 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7, + 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165, + 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d, + 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b, + 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c, + 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a, + 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362, + 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0, + 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52, + 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7, + 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237, + 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1, + 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020, + 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6, + 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719, + 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec, + 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e, + 0x14d747e1}, + {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0, + 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b, + 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652, + 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437, + 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514, + 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265, + 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de, + 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af, + 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c, + 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9, + 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0, + 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b, + 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6, + 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7, + 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734, + 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045, + 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8, + 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303, + 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a, + 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9, + 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea, + 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b, + 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6, + 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7, + 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4, + 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6, + 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f, + 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054, + 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9, + 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8, + 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b, + 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a, + 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441, + 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a, + 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3, + 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6, + 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5, + 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94, + 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9, + 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288, + 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab, + 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce, + 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7, + 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c, + 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527, + 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256, + 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5, + 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4, + 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39, + 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2, + 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db, + 0xaa933b1a}, + {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603, + 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d, + 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9, + 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b, + 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a, + 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792, + 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4, + 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c, + 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d, + 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f, + 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb, + 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65, + 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330, + 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8, + 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da, + 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742, + 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f, + 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1, + 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5, + 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f, + 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e, + 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6, + 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8, + 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250, + 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021, + 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb, + 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f, + 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511, + 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c, + 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4, + 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886, + 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e, + 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b, + 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5, + 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791, + 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003, + 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272, + 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea, + 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc, + 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24, + 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55, + 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7, + 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3, + 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d, + 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548, + 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0, + 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2, + 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a, + 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47, + 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9, + 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad, + 0x65711936}}; + +#endif + +#endif + +#if N == 4 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a, + 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe, + 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b, + 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656, + 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd, + 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d, + 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7, + 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47, + 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac, + 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691, + 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404, + 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0, + 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4, + 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424, + 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5, + 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65, + 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67, + 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3, + 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626, + 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9, + 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222, + 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2, + 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a, + 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a, + 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1, + 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2, + 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077, + 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3, + 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1, + 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621, + 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0, + 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60, + 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0, + 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64, + 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1, + 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc, + 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027, + 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7, + 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9, + 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79, + 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292, + 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af, + 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a, + 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee, + 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e, + 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe, + 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f, + 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff, + 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd, + 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29, + 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc, + 0xe3c45916}, + {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344, + 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59, + 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e, + 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463, + 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98, + 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d, + 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3, + 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656, + 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad, + 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0, + 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397, + 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a, + 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2, + 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357, + 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8, + 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d, + 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696, + 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b, + 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc, + 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0, + 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b, + 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be, + 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811, + 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384, + 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f, + 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955, + 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362, + 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f, + 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94, + 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701, + 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe, + 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b, + 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1, + 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc, + 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b, + 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986, + 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d, + 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8, + 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4, + 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371, + 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a, + 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87, + 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0, + 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad, + 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527, + 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2, + 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d, + 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998, + 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73, + 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e, + 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59, + 0xa7520488}, + {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20, + 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09, + 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431, + 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a, + 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203, + 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b, + 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14, + 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c, + 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25, + 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e, + 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36, + 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f, + 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649, + 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961, + 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58, + 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170, + 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b, + 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742, + 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a, + 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55, + 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c, + 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64, + 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f, + 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77, + 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e, + 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a, + 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2, + 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b, + 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090, + 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8, + 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881, + 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9, + 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6, + 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f, + 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7, + 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c, + 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695, + 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd, + 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb, + 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3, + 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa, + 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1, + 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9, + 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0, + 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df, + 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7, + 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace, + 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6, + 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd, + 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4, + 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec, + 0x3522e9e4}, + {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1, + 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86, + 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b, + 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669, + 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7, + 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352, + 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03, + 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6, + 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38, + 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a, + 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7, + 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80, + 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7, + 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522, + 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d, + 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8, + 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103, + 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54, + 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9, + 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0, + 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e, + 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb, + 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1, + 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624, + 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea, + 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a, + 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37, + 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360, + 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab, + 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e, + 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741, + 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4, + 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334, + 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63, + 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de, + 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c, + 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942, + 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7, + 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131, + 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4, + 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a, + 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758, + 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5, + 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2, + 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32, + 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7, + 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8, + 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d, + 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6, + 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1, + 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c, + 0x97411e28}, + {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474, + 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5, + 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6, + 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7, + 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938, + 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051, + 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a, + 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3, + 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c, + 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d, + 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e, + 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf, + 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740, + 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29, + 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592, + 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb, + 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4, + 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365, + 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036, + 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7, + 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08, + 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561, + 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a, + 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663, + 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac, + 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d, + 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce, + 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f, + 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50, + 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639, + 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82, + 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb, + 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954, + 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5, + 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86, + 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7, + 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418, + 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71, + 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa, + 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93, + 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c, + 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d, + 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e, + 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df, + 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60, + 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309, + 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2, + 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db, + 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4, + 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45, + 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16, + 0x93c7a00b}, + {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45, + 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb, + 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d, + 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696, + 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf, + 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb, + 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028, + 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c, + 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65, + 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be, + 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038, + 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6, + 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15, + 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11, + 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d, + 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19, + 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05, + 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b, + 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d, + 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c, + 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35, + 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31, + 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068, + 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c, + 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25, + 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a, + 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac, + 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22, + 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e, + 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a, + 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36, + 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32, + 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84, + 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a, + 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c, + 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057, + 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e, + 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a, + 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc, + 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8, + 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1, + 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a, + 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec, + 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62, + 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4, + 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0, + 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc, + 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8, + 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4, + 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a, + 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc, + 0xce5f968d}, + {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de, + 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b, + 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d, + 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680, + 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4, + 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d, + 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde, + 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97, + 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3, + 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e, + 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678, + 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d, + 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723, + 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a, + 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0, + 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9, + 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85, + 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770, + 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56, + 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a, + 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e, + 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67, + 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785, + 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc, + 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788, + 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90, + 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6, + 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843, + 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f, + 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336, + 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac, + 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5, + 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68, + 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d, + 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb, + 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36, + 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72, + 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b, + 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b, + 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402, + 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446, + 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb, + 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed, + 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418, + 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95, + 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc, + 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946, + 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f, + 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233, + 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6, + 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0, + 0x3e721277}, + {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb, + 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9, + 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11, + 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d, + 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9, + 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c, + 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881, + 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274, + 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790, + 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc, + 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514, + 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56, + 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9, + 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c, + 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13, + 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6, + 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c, + 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e, + 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386, + 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376, + 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692, + 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67, + 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416, + 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3, + 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07, + 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd, + 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15, + 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457, + 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd, + 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28, + 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337, + 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2, + 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594, + 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6, + 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e, + 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52, + 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6, + 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143, + 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17, + 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2, + 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306, + 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a, + 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182, + 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0, + 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496, + 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63, + 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c, + 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89, + 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903, + 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041, + 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9, + 0x1c65ace7}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000, + 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000, + 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000, + 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000, + 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000, + 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000, + 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000, + 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000, + 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000, + 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000, + 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000, + 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000, + 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000, + 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000, + 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000, + 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000, + 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000, + 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000, + 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000, + 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000, + 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000, + 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000, + 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000, + 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000, + 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000, + 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000, + 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000, + 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000, + 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000, + 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000, + 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000, + 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000, + 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000, + 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000, + 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000, + 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000, + 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000, + 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000, + 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000, + 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000, + 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000, + 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000, + 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000, + 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000, + 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000, + 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000, + 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000, + 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000, + 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000, + 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000, + 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000, + 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000, + 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000, + 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000, + 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000, + 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000, + 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000, + 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000, + 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000, + 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000, + 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000, + 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000, + 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000, + 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000, + 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000, + 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000, + 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000, + 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000, + 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000, + 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000, + 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000, + 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000, + 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000, + 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000, + 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000, + 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000, + 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000, + 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000, + 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000, + 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000, + 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000, + 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000, + 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000, + 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000, + 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000, + 0xe7ac651c00000000}, + {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000, + 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000, + 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000, + 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000, + 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000, + 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000, + 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000, + 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000, + 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000, + 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000, + 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000, + 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000, + 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000, + 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000, + 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000, + 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000, + 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000, + 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000, + 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000, + 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000, + 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000, + 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000, + 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000, + 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000, + 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000, + 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000, + 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000, + 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000, + 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000, + 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000, + 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000, + 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000, + 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000, + 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000, + 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000, + 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000, + 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000, + 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000, + 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000, + 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000, + 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000, + 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000, + 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000, + 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000, + 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000, + 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000, + 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000, + 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000, + 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000, + 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000, + 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000, + 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000, + 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000, + 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000, + 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000, + 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000, + 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000, + 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000, + 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000, + 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000, + 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000, + 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000, + 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000, + 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000, + 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000, + 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000, + 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000, + 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000, + 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000, + 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000, + 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000, + 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000, + 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000, + 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000, + 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000, + 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000, + 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000, + 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000, + 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000, + 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000, + 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000, + 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000, + 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000, + 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000, + 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000, + 0x7712723e00000000}, + {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000, + 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000, + 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000, + 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000, + 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000, + 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000, + 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000, + 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000, + 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000, + 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000, + 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000, + 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000, + 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000, + 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000, + 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000, + 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000, + 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000, + 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000, + 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000, + 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000, + 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000, + 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000, + 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000, + 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000, + 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000, + 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000, + 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000, + 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000, + 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000, + 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000, + 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000, + 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000, + 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000, + 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000, + 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000, + 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000, + 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000, + 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000, + 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000, + 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000, + 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000, + 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000, + 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000, + 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000, + 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000, + 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000, + 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000, + 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000, + 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000, + 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000, + 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000, + 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000, + 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000, + 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000, + 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000, + 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000, + 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000, + 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000, + 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000, + 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000, + 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000, + 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000, + 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000, + 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000, + 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000, + 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000, + 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000, + 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000, + 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000, + 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000, + 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000, + 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000, + 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000, + 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000, + 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000, + 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000, + 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000, + 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000, + 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000, + 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000, + 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000, + 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000, + 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000, + 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000, + 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000, + 0x8d965fce00000000}, + {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000, + 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000, + 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000, + 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000, + 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000, + 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000, + 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000, + 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000, + 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000, + 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000, + 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000, + 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000, + 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000, + 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000, + 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000, + 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000, + 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000, + 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000, + 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000, + 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000, + 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000, + 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000, + 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000, + 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000, + 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000, + 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000, + 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000, + 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000, + 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000, + 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000, + 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000, + 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000, + 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000, + 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000, + 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000, + 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000, + 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000, + 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000, + 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000, + 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000, + 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000, + 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000, + 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000, + 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000, + 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000, + 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000, + 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000, + 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000, + 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000, + 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000, + 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000, + 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000, + 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000, + 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000, + 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000, + 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000, + 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000, + 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000, + 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000, + 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000, + 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000, + 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000, + 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000, + 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000, + 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000, + 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000, + 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000, + 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000, + 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000, + 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000, + 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000, + 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000, + 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000, + 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000, + 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000, + 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000, + 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000, + 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000, + 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000, + 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000, + 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000, + 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000, + 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000, + 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000, + 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000, + 0x0ba0c79300000000}, + {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000, + 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000, + 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000, + 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000, + 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000, + 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000, + 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000, + 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000, + 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000, + 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000, + 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000, + 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000, + 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000, + 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000, + 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000, + 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000, + 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000, + 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000, + 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000, + 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000, + 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000, + 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000, + 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000, + 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000, + 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000, + 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000, + 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000, + 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000, + 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000, + 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000, + 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000, + 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000, + 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000, + 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000, + 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000, + 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000, + 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000, + 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000, + 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000, + 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000, + 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000, + 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000, + 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000, + 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000, + 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000, + 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000, + 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000, + 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000, + 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000, + 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000, + 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000, + 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000, + 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000, + 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000, + 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000, + 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000, + 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000, + 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000, + 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000, + 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000, + 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000, + 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000, + 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000, + 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000, + 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000, + 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000, + 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000, + 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000, + 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000, + 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000, + 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000, + 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000, + 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000, + 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000, + 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000, + 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000, + 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000, + 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000, + 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000, + 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000, + 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000, + 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000, + 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000, + 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000, + 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000, + 0x281e419700000000}, + {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000, + 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000, + 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000, + 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000, + 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000, + 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000, + 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000, + 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000, + 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000, + 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000, + 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000, + 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000, + 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000, + 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000, + 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000, + 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000, + 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000, + 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000, + 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000, + 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000, + 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000, + 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000, + 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000, + 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000, + 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000, + 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000, + 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000, + 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000, + 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000, + 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000, + 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000, + 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000, + 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000, + 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000, + 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000, + 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000, + 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000, + 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000, + 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000, + 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000, + 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000, + 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000, + 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000, + 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000, + 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000, + 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000, + 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000, + 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000, + 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000, + 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000, + 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000, + 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000, + 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000, + 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000, + 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000, + 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000, + 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000, + 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000, + 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000, + 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000, + 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000, + 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000, + 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000, + 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000, + 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000, + 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000, + 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000, + 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000, + 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000, + 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000, + 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000, + 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000, + 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000, + 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000, + 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000, + 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000, + 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000, + 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000, + 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000, + 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000, + 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000, + 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000, + 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000, + 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000, + 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000, + 0xe4e9223500000000}, + {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000, + 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000, + 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000, + 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000, + 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000, + 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000, + 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000, + 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000, + 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000, + 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000, + 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000, + 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000, + 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000, + 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000, + 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000, + 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000, + 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000, + 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000, + 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000, + 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000, + 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000, + 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000, + 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000, + 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000, + 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000, + 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000, + 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000, + 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000, + 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000, + 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000, + 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000, + 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000, + 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000, + 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000, + 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000, + 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000, + 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000, + 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000, + 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000, + 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000, + 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000, + 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000, + 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000, + 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000, + 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000, + 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000, + 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000, + 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000, + 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000, + 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000, + 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000, + 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000, + 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000, + 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000, + 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000, + 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000, + 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000, + 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000, + 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000, + 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000, + 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000, + 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000, + 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000, + 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000, + 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000, + 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000, + 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000, + 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000, + 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000, + 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000, + 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000, + 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000, + 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000, + 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000, + 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000, + 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000, + 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000, + 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000, + 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000, + 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000, + 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000, + 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000, + 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000, + 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000, + 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000, + 0x880452a700000000}, + {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000, + 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000, + 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000, + 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000, + 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000, + 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000, + 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000, + 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000, + 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000, + 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000, + 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000, + 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000, + 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000, + 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000, + 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000, + 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000, + 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000, + 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000, + 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000, + 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000, + 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000, + 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000, + 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000, + 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000, + 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000, + 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000, + 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000, + 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000, + 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000, + 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000, + 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000, + 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000, + 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000, + 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000, + 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000, + 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000, + 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000, + 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000, + 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000, + 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000, + 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000, + 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000, + 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000, + 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000, + 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000, + 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000, + 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000, + 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000, + 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000, + 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000, + 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000, + 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000, + 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000, + 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000, + 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000, + 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000, + 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000, + 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000, + 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000, + 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000, + 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000, + 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000, + 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000, + 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000, + 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000, + 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000, + 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000, + 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000, + 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000, + 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000, + 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000, + 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000, + 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000, + 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000, + 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000, + 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000, + 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000, + 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000, + 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000, + 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000, + 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000, + 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000, + 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000, + 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000, + 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000, + 0x1659c4e300000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, + 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, + 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, + 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, + 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, + 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, + 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, + 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, + 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, + 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, + 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, + 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, + 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, + 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, + 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, + 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, + 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, + 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, + 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, + 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, + 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, + 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, + 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, + 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, + 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, + 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, + 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, + 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, + 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, + 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, + 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, + 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, + 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, + 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, + 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, + 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, + 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, + 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, + 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, + 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, + 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, + 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, + 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, + 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, + 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, + 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, + 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, + 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, + 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, + 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, + 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, + 0x0d7139d7}, + {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, + 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, + 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, + 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, + 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, + 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, + 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, + 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, + 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, + 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, + 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, + 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, + 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, + 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, + 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, + 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, + 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, + 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, + 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, + 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, + 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, + 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, + 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, + 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, + 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, + 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, + 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, + 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, + 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, + 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, + 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, + 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, + 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, + 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, + 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, + 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, + 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, + 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, + 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, + 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, + 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, + 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, + 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, + 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, + 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, + 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, + 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, + 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, + 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, + 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, + 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, + 0x1c53e98a}, + {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, + 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, + 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, + 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, + 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, + 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, + 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, + 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, + 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, + 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, + 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, + 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, + 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, + 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, + 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, + 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, + 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, + 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, + 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, + 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, + 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, + 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, + 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, + 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, + 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, + 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, + 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, + 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, + 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, + 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, + 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, + 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, + 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, + 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, + 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, + 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, + 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, + 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, + 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, + 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, + 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, + 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, + 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, + 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, + 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, + 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, + 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, + 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, + 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, + 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, + 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, + 0x3f88e851}, + {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, + 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, + 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, + 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, + 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, + 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, + 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, + 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, + 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, + 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, + 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, + 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, + 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, + 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, + 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, + 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, + 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, + 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, + 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, + 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, + 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, + 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, + 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, + 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, + 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, + 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, + 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, + 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, + 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, + 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, + 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, + 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, + 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, + 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, + 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, + 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, + 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, + 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, + 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, + 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, + 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, + 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, + 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, + 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, + 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, + 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, + 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, + 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, + 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, + 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, + 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, + 0x3dee8ca6}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0, + 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587, + 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa, + 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09, + 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee, + 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3, + 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3, + 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce, + 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429, + 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda, + 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7, + 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0, + 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd, + 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0, + 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287, + 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a, + 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9, + 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e, + 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3, + 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3, + 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054, + 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49, + 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da, + 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7, + 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20, + 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d, + 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00, + 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347, + 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14, + 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209, + 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e, + 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33, + 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3, + 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194, + 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9, + 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a, + 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd, + 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0, + 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d, + 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460, + 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87, + 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674, + 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509, + 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e, + 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae, + 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3, + 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694, + 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989, + 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da, + 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d, + 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0, + 0xa68cee3d}, + {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19, + 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae, + 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb, + 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a, + 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55, + 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1, + 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c, + 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8, + 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7, + 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936, + 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453, + 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4, + 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941, + 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5, + 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93, + 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17, + 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e, + 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89, + 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec, + 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0, + 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf, + 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b, + 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b, + 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f, + 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0, + 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e, + 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b, + 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc, + 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5, + 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261, + 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637, + 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3, + 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57, + 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0, + 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85, + 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454, + 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b, + 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f, + 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423, + 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7, + 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8, + 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739, + 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c, + 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb, + 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f, + 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b, + 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd, + 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59, + 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070, + 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7, + 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2, + 0x51e8883f}, + {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a, + 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276, + 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed, + 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55, + 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b, + 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8, + 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320, + 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413, + 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd, + 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75, + 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee, + 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312, + 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca, + 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9, + 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad, + 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e, + 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504, + 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8, + 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63, + 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353, + 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d, + 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be, + 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae, + 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d, + 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943, + 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7, + 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c, + 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390, + 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a, + 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239, + 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d, + 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e, + 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c, + 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0, + 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b, + 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93, + 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d, + 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e, + 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c, + 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f, + 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1, + 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579, + 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2, + 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e, + 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c, + 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f, + 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b, + 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158, + 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2, + 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e, + 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5, + 0x8ae9531c}, + {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4, + 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd, + 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220, + 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf, + 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495, + 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def, + 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90, + 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea, + 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0, + 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f, + 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2, + 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab, + 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e, + 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754, + 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda, + 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0, + 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c, + 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215, + 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8, + 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910, + 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a, + 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30, + 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658, + 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22, + 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478, + 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2, + 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f, + 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606, + 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba, + 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0, + 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e, + 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034, + 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f, + 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996, + 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b, + 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84, + 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de, + 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4, + 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5, + 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f, + 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5, + 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a, + 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7, + 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce, + 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65, + 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f, + 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91, + 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb, + 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57, + 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e, + 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3, + 0xd739710d}}; + +#endif + +#endif + +#if N == 5 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df, + 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8, + 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef, + 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376, + 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201, + 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399, + 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372, + 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea, + 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d, + 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004, + 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353, + 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334, + 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a, + 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2, + 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a, + 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2, + 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b, + 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c, + 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b, + 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f, + 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338, + 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0, + 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6, + 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e, + 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319, + 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3, + 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4, + 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783, + 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a, + 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492, + 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a, + 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2, + 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496, + 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1, + 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6, + 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f, + 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548, + 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0, + 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741, + 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9, + 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae, + 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437, + 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760, + 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707, + 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433, + 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab, + 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703, + 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b, + 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412, + 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475, + 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722, + 0xe9947565}, + {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5, + 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22, + 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c, + 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed, + 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d, + 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1, + 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e, + 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32, + 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142, + 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93, + 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d, + 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a, + 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58, + 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14, + 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81, + 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd, + 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab, + 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c, + 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72, + 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f, + 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff, + 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3, + 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30, + 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c, + 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c, + 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558, + 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146, + 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581, + 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7, + 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab, + 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e, + 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272, + 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838, + 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff, + 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1, + 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330, + 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840, + 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c, + 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb, + 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7, + 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7, + 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616, + 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208, + 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf, + 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85, + 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9, + 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c, + 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10, + 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76, + 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1, + 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf, + 0xf7d05006}, + {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b, + 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774, + 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58, + 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a, + 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb, + 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952, + 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e, + 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7, + 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746, + 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14, + 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338, + 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907, + 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777, + 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de, + 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064, + 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd, + 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951, + 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e, + 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42, + 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b, + 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a, + 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3, + 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904, + 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad, + 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c, + 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d, + 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861, + 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e, + 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2, + 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b, + 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1, + 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78, + 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f, + 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40, + 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c, + 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e, + 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf, + 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166, + 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d, + 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4, + 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805, + 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157, + 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b, + 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644, + 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43, + 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea, + 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850, + 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9, + 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165, + 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a, + 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676, + 0xb2075b94}, + {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf, + 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61, + 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be, + 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd, + 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3, + 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063, + 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105, + 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5, + 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb, + 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8, + 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07, + 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9, + 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5, + 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515, + 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4, + 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014, + 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7, + 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269, + 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6, + 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af, + 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1, + 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111, + 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d, + 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad, + 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3, + 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75, + 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa, + 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74, + 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7, + 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477, + 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6, + 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176, + 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af, + 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71, + 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae, + 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd, + 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3, + 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073, + 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0, + 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400, + 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e, + 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d, + 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2, + 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c, + 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5, + 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505, + 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4, + 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004, + 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7, + 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279, + 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6, + 0xba50bcb9}, + {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897, + 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb, + 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2, + 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2, + 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372, + 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70, + 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92, + 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190, + 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40, + 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430, + 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759, + 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75, + 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2, + 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0, + 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7, + 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5, + 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39, + 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215, + 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c, + 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5, + 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625, + 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27, + 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c, + 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e, + 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee, + 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71, + 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18, + 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134, + 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8, + 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba, + 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd, + 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff, + 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a, + 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6, + 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf, + 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf, + 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f, + 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d, + 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d, + 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f, + 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af, + 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df, + 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6, + 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a, + 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef, + 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed, + 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa, + 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8, + 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624, + 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08, + 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861, + 0x808abcf4}, + {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2, + 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd, + 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76, + 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52, + 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e, + 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124, + 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147, + 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d, + 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31, + 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15, + 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae, + 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1, + 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d, + 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307, + 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9, + 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3, + 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084, + 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb, + 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850, + 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2, + 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe, + 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94, + 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261, + 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b, + 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917, + 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53, + 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8, + 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787, + 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0, + 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba, + 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404, + 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e, + 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af, + 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0, + 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b, + 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f, + 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543, + 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129, + 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627, + 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d, + 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51, + 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75, + 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce, + 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1, + 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760, + 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a, + 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4, + 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde, + 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089, + 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6, + 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d, + 0xefdb3f95}, + {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8, + 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7, + 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945, + 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9, + 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652, + 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc, + 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a, + 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4, + 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f, + 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3, + 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51, + 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e, + 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c, + 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362, + 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11, + 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff, + 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7, + 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8, + 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a, + 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690, + 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b, + 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5, + 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05, + 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb, + 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740, + 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f, + 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded, + 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2, + 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa, + 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714, + 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67, + 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89, + 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7, + 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8, + 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a, + 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6, + 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d, + 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3, + 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9, + 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57, + 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc, + 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540, + 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2, + 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd, + 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93, + 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d, + 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e, + 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0, + 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8, + 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7, + 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75, + 0x0e2fbf43}, + {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc, + 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a, + 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3, + 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7, + 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b, + 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154, + 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3, + 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc, + 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330, + 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264, + 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd, + 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b, + 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a, + 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175, + 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275, + 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a, + 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234, + 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2, + 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b, + 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a, + 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6, + 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189, + 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b, + 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204, + 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8, + 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226, + 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff, + 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219, + 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167, + 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258, + 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158, + 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267, + 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c, + 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da, + 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003, + 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157, + 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b, + 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4, + 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179, + 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246, + 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a, + 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de, + 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107, + 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1, + 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba, + 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285, + 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185, + 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba, + 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4, + 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322, + 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb, + 0xf4377108}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000, + 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000, + 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000, + 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000, + 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000, + 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000, + 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000, + 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000, + 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000, + 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000, + 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000, + 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000, + 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000, + 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000, + 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000, + 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000, + 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000, + 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000, + 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000, + 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000, + 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000, + 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000, + 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000, + 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000, + 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000, + 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000, + 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000, + 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000, + 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000, + 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000, + 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000, + 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000, + 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000, + 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000, + 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000, + 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000, + 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000, + 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000, + 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000, + 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000, + 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000, + 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000, + 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000, + 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000, + 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000, + 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000, + 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000, + 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000, + 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000, + 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000, + 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000, + 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000, + 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000, + 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000, + 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000, + 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000, + 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000, + 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000, + 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000, + 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000, + 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000, + 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000, + 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000, + 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000, + 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000, + 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000, + 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000, + 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000, + 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000, + 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000, + 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000, + 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000, + 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000, + 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000, + 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000, + 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000, + 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000, + 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000, + 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000, + 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000, + 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000, + 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000, + 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000, + 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000, + 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000, + 0x087137f400000000}, + {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000, + 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000, + 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000, + 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000, + 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000, + 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000, + 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000, + 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000, + 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000, + 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000, + 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000, + 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000, + 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000, + 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000, + 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000, + 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000, + 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000, + 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000, + 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000, + 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000, + 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000, + 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000, + 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000, + 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000, + 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000, + 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000, + 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000, + 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000, + 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000, + 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000, + 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000, + 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000, + 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000, + 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000, + 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000, + 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000, + 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000, + 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000, + 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000, + 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000, + 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000, + 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000, + 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000, + 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000, + 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000, + 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000, + 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000, + 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000, + 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000, + 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000, + 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000, + 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000, + 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000, + 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000, + 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000, + 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000, + 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000, + 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000, + 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000, + 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000, + 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000, + 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000, + 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000, + 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000, + 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000, + 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000, + 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000, + 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000, + 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000, + 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000, + 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000, + 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000, + 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000, + 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000, + 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000, + 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000, + 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000, + 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000, + 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000, + 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000, + 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000, + 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000, + 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000, + 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000, + 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000, + 0x43bf2f0e00000000}, + {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000, + 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000, + 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000, + 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000, + 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000, + 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000, + 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000, + 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000, + 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000, + 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000, + 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000, + 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000, + 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000, + 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000, + 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000, + 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000, + 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000, + 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000, + 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000, + 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000, + 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000, + 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000, + 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000, + 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000, + 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000, + 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000, + 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000, + 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000, + 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000, + 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000, + 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000, + 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000, + 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000, + 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000, + 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000, + 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000, + 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000, + 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000, + 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000, + 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000, + 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000, + 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000, + 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000, + 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000, + 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000, + 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000, + 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000, + 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000, + 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000, + 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000, + 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000, + 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000, + 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000, + 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000, + 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000, + 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000, + 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000, + 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000, + 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000, + 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000, + 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000, + 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000, + 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000, + 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000, + 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000, + 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000, + 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000, + 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000, + 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000, + 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000, + 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000, + 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000, + 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000, + 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000, + 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000, + 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000, + 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000, + 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000, + 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000, + 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000, + 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000, + 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000, + 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000, + 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000, + 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000, + 0x953fdbef00000000}, + {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000, + 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000, + 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000, + 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000, + 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000, + 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000, + 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000, + 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000, + 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000, + 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000, + 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000, + 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000, + 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000, + 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000, + 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000, + 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000, + 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000, + 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000, + 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000, + 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000, + 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000, + 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000, + 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000, + 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000, + 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000, + 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000, + 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000, + 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000, + 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000, + 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000, + 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000, + 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000, + 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000, + 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000, + 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000, + 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000, + 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000, + 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000, + 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000, + 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000, + 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000, + 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000, + 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000, + 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000, + 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000, + 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000, + 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000, + 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000, + 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000, + 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000, + 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000, + 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000, + 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000, + 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000, + 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000, + 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000, + 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000, + 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000, + 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000, + 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000, + 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000, + 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000, + 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000, + 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000, + 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000, + 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000, + 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000, + 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000, + 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000, + 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000, + 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000, + 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000, + 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000, + 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000, + 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000, + 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000, + 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000, + 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000, + 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000, + 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000, + 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000, + 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000, + 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000, + 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000, + 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000, + 0xf4bc8a8000000000}, + {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000, + 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000, + 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000, + 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000, + 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000, + 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000, + 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000, + 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000, + 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000, + 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000, + 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000, + 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000, + 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000, + 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000, + 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000, + 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000, + 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000, + 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000, + 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000, + 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000, + 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000, + 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000, + 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000, + 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000, + 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000, + 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000, + 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000, + 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000, + 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000, + 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000, + 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000, + 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000, + 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000, + 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000, + 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000, + 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000, + 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000, + 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000, + 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000, + 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000, + 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000, + 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000, + 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000, + 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000, + 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000, + 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000, + 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000, + 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000, + 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000, + 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000, + 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000, + 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000, + 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000, + 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000, + 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000, + 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000, + 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000, + 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000, + 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000, + 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000, + 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000, + 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000, + 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000, + 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000, + 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000, + 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000, + 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000, + 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000, + 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000, + 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000, + 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000, + 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000, + 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000, + 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000, + 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000, + 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000, + 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000, + 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000, + 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000, + 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000, + 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000, + 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000, + 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000, + 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000, + 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000, + 0xb9bc50ba00000000}, + {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000, + 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000, + 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000, + 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000, + 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000, + 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000, + 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000, + 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000, + 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000, + 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000, + 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000, + 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000, + 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000, + 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000, + 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000, + 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000, + 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000, + 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000, + 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000, + 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000, + 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000, + 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000, + 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000, + 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000, + 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000, + 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000, + 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000, + 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000, + 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000, + 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000, + 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000, + 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000, + 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000, + 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000, + 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000, + 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000, + 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000, + 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000, + 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000, + 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000, + 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000, + 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000, + 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000, + 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000, + 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000, + 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000, + 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000, + 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000, + 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000, + 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000, + 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000, + 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000, + 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000, + 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000, + 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000, + 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000, + 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000, + 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000, + 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000, + 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000, + 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000, + 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000, + 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000, + 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000, + 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000, + 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000, + 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000, + 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000, + 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000, + 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000, + 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000, + 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000, + 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000, + 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000, + 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000, + 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000, + 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000, + 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000, + 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000, + 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000, + 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000, + 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000, + 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000, + 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000, + 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000, + 0x945b07b200000000}, + {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000, + 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000, + 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000, + 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000, + 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000, + 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000, + 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000, + 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000, + 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000, + 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000, + 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000, + 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000, + 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000, + 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000, + 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000, + 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000, + 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000, + 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000, + 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000, + 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000, + 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000, + 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000, + 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000, + 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000, + 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000, + 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000, + 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000, + 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000, + 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000, + 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000, + 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000, + 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000, + 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000, + 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000, + 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000, + 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000, + 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000, + 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000, + 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000, + 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000, + 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000, + 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000, + 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000, + 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000, + 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000, + 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000, + 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000, + 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000, + 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000, + 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000, + 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000, + 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000, + 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000, + 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000, + 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000, + 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000, + 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000, + 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000, + 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000, + 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000, + 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000, + 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000, + 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000, + 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000, + 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000, + 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000, + 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000, + 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000, + 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000, + 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000, + 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000, + 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000, + 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000, + 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000, + 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000, + 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000, + 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000, + 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000, + 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000, + 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000, + 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000, + 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000, + 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000, + 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000, + 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000, + 0x0650d0f700000000}, + {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000, + 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000, + 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000, + 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000, + 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000, + 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000, + 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000, + 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000, + 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000, + 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000, + 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000, + 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000, + 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000, + 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000, + 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000, + 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000, + 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000, + 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000, + 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000, + 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000, + 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000, + 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000, + 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000, + 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000, + 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000, + 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000, + 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000, + 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000, + 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000, + 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000, + 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000, + 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000, + 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000, + 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000, + 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000, + 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000, + 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000, + 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000, + 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000, + 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000, + 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000, + 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000, + 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000, + 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000, + 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000, + 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000, + 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000, + 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000, + 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000, + 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000, + 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000, + 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000, + 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000, + 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000, + 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000, + 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000, + 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000, + 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000, + 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000, + 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000, + 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000, + 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000, + 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000, + 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000, + 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000, + 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000, + 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000, + 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000, + 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000, + 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000, + 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000, + 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000, + 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000, + 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000, + 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000, + 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000, + 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000, + 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000, + 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000, + 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000, + 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000, + 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000, + 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000, + 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000, + 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000, + 0x657594e900000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, + 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, + 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, + 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, + 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, + 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, + 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, + 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, + 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, + 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, + 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, + 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, + 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, + 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, + 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, + 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, + 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, + 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, + 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, + 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, + 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, + 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, + 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, + 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, + 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, + 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, + 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, + 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, + 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, + 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, + 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, + 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, + 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, + 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, + 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, + 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, + 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, + 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, + 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, + 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, + 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, + 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, + 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, + 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, + 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, + 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, + 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, + 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, + 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, + 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, + 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, + 0xd8ac6b35}, + {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, + 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, + 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, + 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, + 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, + 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, + 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, + 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, + 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, + 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, + 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, + 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, + 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, + 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, + 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, + 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, + 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, + 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, + 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, + 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, + 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, + 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, + 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, + 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, + 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, + 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, + 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, + 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, + 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, + 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, + 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, + 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, + 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, + 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, + 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, + 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, + 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, + 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, + 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, + 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, + 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, + 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, + 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, + 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, + 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, + 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, + 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, + 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, + 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, + 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, + 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, + 0xa140efa8}, + {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, + 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, + 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, + 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, + 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, + 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, + 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, + 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, + 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, + 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, + 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, + 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, + 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, + 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, + 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, + 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, + 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, + 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, + 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, + 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, + 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, + 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, + 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, + 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, + 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, + 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, + 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, + 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, + 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, + 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, + 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, + 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, + 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, + 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, + 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, + 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, + 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, + 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, + 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, + 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, + 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, + 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, + 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, + 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, + 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, + 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, + 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, + 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, + 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, + 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, + 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, + 0x917cd6a1}, + {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, + 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, + 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, + 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, + 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, + 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, + 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, + 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, + 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, + 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, + 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, + 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, + 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, + 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, + 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, + 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, + 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, + 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, + 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, + 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, + 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, + 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, + 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, + 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, + 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, + 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, + 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, + 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, + 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, + 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, + 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, + 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, + 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, + 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, + 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, + 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, + 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, + 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, + 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, + 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, + 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, + 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, + 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, + 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, + 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, + 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, + 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, + 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, + 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, + 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, + 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, + 0x18ba364e}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873, + 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661, + 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441, + 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44, + 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1, + 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05, + 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa, + 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e, + 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb, + 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be, + 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e, + 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c, + 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d, + 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9, + 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f, + 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b, + 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39, + 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b, + 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b, + 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20, + 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595, + 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61, + 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0, + 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644, + 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1, + 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d, + 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d, + 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f, + 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad, + 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359, + 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f, + 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b, + 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7, + 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5, + 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5, + 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0, + 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65, + 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091, + 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633, + 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7, + 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272, + 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77, + 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57, + 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145, + 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9, + 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d, + 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb, + 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f, + 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad, + 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf, + 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f, + 0x4e36ba18}, + {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b, + 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8, + 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19, + 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4, + 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239, + 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd, + 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258, + 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc, + 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41, + 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c, + 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d, + 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e, + 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba, + 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e, + 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8, + 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c, + 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f, + 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c, + 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d, + 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d, + 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0, + 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014, + 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc, + 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628, + 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5, + 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941, + 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0, + 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53, + 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880, + 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264, + 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92, + 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776, + 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8, + 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b, + 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea, + 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837, + 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca, + 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e, + 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211, + 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5, + 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08, + 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5, + 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934, + 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7, + 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049, + 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad, + 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b, + 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf, + 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c, + 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f, + 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e, + 0xa1d67c91}, + {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9, + 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de, + 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94, + 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0, + 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a, + 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924, + 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052, + 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c, + 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6, + 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2, + 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8, + 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f, + 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d, + 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273, + 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30, + 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e, + 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7, + 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980, + 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca, + 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8, + 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62, + 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c, + 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c, + 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032, + 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798, + 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d, + 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07, + 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630, + 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389, + 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7, + 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4, + 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca, + 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55, + 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662, + 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828, + 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c, + 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6, + 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98, + 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3, + 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d, + 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037, + 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913, + 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759, + 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e, + 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1, + 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf, + 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c, + 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2, + 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b, + 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c, + 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276, + 0xa8ef40a1}, + {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e, + 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8, + 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819, + 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f, + 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d, + 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756, + 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0, + 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb, + 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9, + 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f, + 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e, + 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8, + 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835, + 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e, + 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62, + 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749, + 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b, + 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d, + 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc, + 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80, + 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2, + 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599, + 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05, + 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e, + 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c, + 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e, + 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef, + 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359, + 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b, + 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0, + 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc, + 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7, + 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f, + 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189, + 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568, + 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e, + 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c, + 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27, + 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794, + 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf, + 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d, + 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db, + 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a, + 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c, + 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544, + 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f, + 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013, + 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38, + 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea, + 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c, + 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd, + 0x356bacd8}}; + +#endif + +#endif + +#if N == 6 + +#if W == 8 + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370, + 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d, + 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69, + 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426, + 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3, + 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f, + 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c, + 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490, + 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155, + 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a, + 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e, + 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603, + 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349, + 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5, + 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50, + 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc, + 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b, + 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76, + 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862, + 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9, + 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c, + 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0, + 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937, + 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b, + 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e, + 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e, + 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a, + 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357, + 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0, + 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c, + 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9, + 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165, + 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766, + 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b, + 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f, + 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030, + 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5, + 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59, + 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63, + 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf, + 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a, + 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845, + 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51, + 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c, + 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f, + 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3, + 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46, + 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea, + 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d, + 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60, + 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74, + 0x8568a0a8}, + {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5, + 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf, + 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5, + 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba, + 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf, + 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f, + 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0, + 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450, + 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55, + 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a, + 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620, + 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a, + 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454, + 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4, + 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534, + 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584, + 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694, + 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e, + 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4, + 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1, + 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4, + 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164, + 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1, + 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911, + 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314, + 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c, + 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6, + 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec, + 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc, + 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c, + 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c, + 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c, + 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716, + 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c, + 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676, + 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879, + 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c, + 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc, + 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77, + 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7, + 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2, + 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd, + 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7, + 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad, + 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897, + 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827, + 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7, + 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947, + 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57, + 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d, + 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37, + 0x0d907052}, + {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d, + 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89, + 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31, + 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81, + 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e, + 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0, + 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f, + 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291, + 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e, + 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e, + 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936, + 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2, + 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13, + 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d, + 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f, + 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1, + 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a, + 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae, + 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516, + 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f, + 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20, + 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe, + 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28, + 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6, + 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419, + 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5, + 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d, + 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889, + 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412, + 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c, + 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e, + 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0, + 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02, + 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986, + 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e, + 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e, + 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221, + 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf, + 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913, + 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d, + 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622, + 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592, + 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a, + 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae, + 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c, + 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82, + 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20, + 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe, + 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025, + 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1, + 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719, + 0xfd1a6c8a}, + {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3, + 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb, + 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d, + 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb, + 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9, + 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156, + 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045, + 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa, + 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8, + 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e, + 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8, + 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0, + 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38, + 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87, + 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46, + 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9, + 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585, + 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d, + 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb, + 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531, + 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03, + 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc, + 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33, + 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c, + 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be, + 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d, + 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b, + 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303, + 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f, + 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0, + 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801, + 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe, + 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e, + 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346, + 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620, + 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776, + 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844, + 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb, + 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0, + 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f, + 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d, + 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b, + 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d, + 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75, + 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795, + 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a, + 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb, + 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354, + 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28, + 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30, + 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856, + 0x7895f01a}, + {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188, + 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33, + 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d, + 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445, + 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2, + 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058, + 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43, + 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9, + 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e, + 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06, + 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228, + 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93, + 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e, + 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4, + 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b, + 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371, + 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265, + 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede, + 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0, + 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f, + 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8, + 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32, + 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae, + 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544, + 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3, + 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f, + 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911, + 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa, + 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be, + 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54, + 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b, + 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1, + 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652, + 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9, + 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7, + 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f, + 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68, + 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782, + 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797, + 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d, + 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a, + 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2, + 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc, + 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647, + 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4, + 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e, + 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41, + 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab, + 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf, + 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904, + 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a, + 0x9239b848}, + {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad, + 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0, + 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40, + 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b, + 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d, + 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b, + 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb, + 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d, + 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b, + 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0, + 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840, + 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d, + 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b, + 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d, + 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6, + 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0, + 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580, + 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd, + 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d, + 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b, + 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d, + 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b, + 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6, + 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0, + 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6, + 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c, + 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c, + 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461, + 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841, + 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317, + 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac, + 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa, + 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7, + 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba, + 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a, + 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161, + 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777, + 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21, + 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a, + 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc, + 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da, + 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1, + 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01, + 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c, + 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241, + 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917, + 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac, + 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa, + 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da, + 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397, + 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537, + 0xeb36d3cc}, + {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b, + 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059, + 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251, + 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d, + 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9, + 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c, + 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41, + 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4, + 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10, + 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c, + 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54, + 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476, + 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8, + 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d, + 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92, + 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307, + 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad, + 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f, + 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87, + 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17, + 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3, + 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46, + 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197, + 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02, + 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6, + 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e, + 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96, + 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4, + 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e, + 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b, + 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934, + 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1, + 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7, + 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5, + 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd, + 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1, + 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475, + 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0, + 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155, + 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0, + 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304, + 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348, + 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140, + 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862, + 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14, + 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181, + 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e, + 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab, + 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01, + 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523, + 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b, + 0x38e5f3c5}, + {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06, + 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad, + 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509, + 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba, + 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414, + 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3, + 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733, + 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994, + 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a, + 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889, + 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d, + 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386, + 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621, + 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886, + 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e, + 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389, + 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f, + 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294, + 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30, + 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3, + 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d, + 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba, + 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a, + 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad, + 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03, + 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2, + 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306, + 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad, + 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b, + 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc, + 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914, + 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3, + 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435, + 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e, + 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a, + 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589, + 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27, + 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080, + 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21, + 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586, + 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28, + 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b, + 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f, + 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94, + 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12, + 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5, + 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d, + 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba, + 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c, + 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7, + 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103, + 0x3d3101a2}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000, + 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000, + 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000, + 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000, + 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000, + 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000, + 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000, + 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000, + 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000, + 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000, + 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000, + 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000, + 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000, + 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000, + 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000, + 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000, + 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000, + 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000, + 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000, + 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000, + 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000, + 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000, + 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000, + 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000, + 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000, + 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000, + 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000, + 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000, + 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000, + 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000, + 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000, + 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000, + 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000, + 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000, + 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000, + 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000, + 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000, + 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000, + 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000, + 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000, + 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000, + 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000, + 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000, + 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000, + 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000, + 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000, + 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000, + 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000, + 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000, + 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000, + 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000, + 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000, + 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000, + 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000, + 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000, + 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000, + 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000, + 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000, + 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000, + 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000, + 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000, + 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000, + 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000, + 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000, + 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000, + 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000, + 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000, + 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000, + 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000, + 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000, + 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000, + 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000, + 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000, + 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000, + 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000, + 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000, + 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000, + 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000, + 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000, + 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000, + 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000, + 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000, + 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000, + 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000, + 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000, + 0xa201313d00000000}, + {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000, + 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000, + 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000, + 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000, + 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000, + 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000, + 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000, + 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000, + 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000, + 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000, + 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000, + 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000, + 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000, + 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000, + 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000, + 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000, + 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000, + 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000, + 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000, + 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000, + 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000, + 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000, + 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000, + 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000, + 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000, + 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000, + 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000, + 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000, + 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000, + 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000, + 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000, + 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000, + 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000, + 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000, + 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000, + 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000, + 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000, + 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000, + 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000, + 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000, + 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000, + 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000, + 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000, + 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000, + 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000, + 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000, + 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000, + 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000, + 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000, + 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000, + 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000, + 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000, + 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000, + 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000, + 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000, + 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000, + 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000, + 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000, + 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000, + 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000, + 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000, + 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000, + 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000, + 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000, + 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000, + 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000, + 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000, + 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000, + 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000, + 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000, + 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000, + 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000, + 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000, + 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000, + 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000, + 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000, + 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000, + 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000, + 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000, + 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000, + 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000, + 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000, + 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000, + 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000, + 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000, + 0xc5f3e53800000000}, + {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000, + 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000, + 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000, + 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000, + 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000, + 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000, + 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000, + 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000, + 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000, + 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000, + 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000, + 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000, + 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000, + 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000, + 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000, + 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000, + 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000, + 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000, + 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000, + 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000, + 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000, + 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000, + 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000, + 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000, + 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000, + 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000, + 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000, + 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000, + 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000, + 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000, + 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000, + 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000, + 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000, + 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000, + 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000, + 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000, + 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000, + 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000, + 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000, + 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000, + 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000, + 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000, + 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000, + 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000, + 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000, + 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000, + 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000, + 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000, + 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000, + 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000, + 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000, + 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000, + 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000, + 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000, + 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000, + 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000, + 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000, + 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000, + 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000, + 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000, + 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000, + 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000, + 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000, + 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000, + 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000, + 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000, + 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000, + 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000, + 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000, + 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000, + 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000, + 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000, + 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000, + 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000, + 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000, + 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000, + 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000, + 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000, + 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000, + 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000, + 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000, + 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000, + 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000, + 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000, + 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000, + 0xccd336eb00000000}, + {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000, + 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000, + 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000, + 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000, + 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000, + 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000, + 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000, + 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000, + 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000, + 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000, + 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000, + 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000, + 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000, + 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000, + 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000, + 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000, + 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000, + 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000, + 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000, + 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000, + 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000, + 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000, + 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000, + 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000, + 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000, + 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000, + 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000, + 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000, + 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000, + 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000, + 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000, + 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000, + 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000, + 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000, + 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000, + 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000, + 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000, + 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000, + 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000, + 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000, + 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000, + 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000, + 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000, + 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000, + 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000, + 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000, + 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000, + 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000, + 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000, + 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000, + 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000, + 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000, + 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000, + 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000, + 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000, + 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000, + 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000, + 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000, + 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000, + 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000, + 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000, + 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000, + 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000, + 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000, + 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000, + 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000, + 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000, + 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000, + 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000, + 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000, + 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000, + 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000, + 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000, + 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000, + 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000, + 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000, + 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000, + 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000, + 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000, + 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000, + 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000, + 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000, + 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000, + 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000, + 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000, + 0x48b8399200000000}, + {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000, + 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000, + 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000, + 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000, + 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000, + 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000, + 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000, + 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000, + 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000, + 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000, + 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000, + 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000, + 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000, + 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000, + 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000, + 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000, + 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000, + 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000, + 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000, + 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000, + 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000, + 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000, + 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000, + 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000, + 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000, + 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000, + 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000, + 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000, + 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000, + 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000, + 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000, + 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000, + 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000, + 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000, + 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000, + 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000, + 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000, + 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000, + 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000, + 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000, + 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000, + 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000, + 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000, + 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000, + 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000, + 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000, + 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000, + 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000, + 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000, + 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000, + 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000, + 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000, + 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000, + 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000, + 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000, + 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000, + 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000, + 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000, + 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000, + 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000, + 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000, + 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000, + 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000, + 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000, + 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000, + 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000, + 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000, + 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000, + 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000, + 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000, + 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000, + 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000, + 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000, + 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000, + 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000, + 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000, + 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000, + 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000, + 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000, + 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000, + 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000, + 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000, + 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000, + 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000, + 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000, + 0x1af0957800000000}, + {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000, + 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000, + 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000, + 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000, + 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000, + 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000, + 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000, + 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000, + 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000, + 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000, + 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000, + 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000, + 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000, + 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000, + 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000, + 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000, + 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000, + 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000, + 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000, + 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000, + 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000, + 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000, + 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000, + 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000, + 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000, + 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000, + 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000, + 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000, + 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000, + 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000, + 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000, + 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000, + 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000, + 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000, + 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000, + 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000, + 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000, + 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000, + 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000, + 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000, + 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000, + 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000, + 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000, + 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000, + 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000, + 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000, + 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000, + 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000, + 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000, + 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000, + 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000, + 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000, + 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000, + 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000, + 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000, + 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000, + 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000, + 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000, + 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000, + 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000, + 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000, + 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000, + 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000, + 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000, + 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000, + 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000, + 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000, + 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000, + 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000, + 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000, + 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000, + 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000, + 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000, + 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000, + 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000, + 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000, + 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000, + 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000, + 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000, + 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000, + 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000, + 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000, + 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000, + 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000, + 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000, + 0x8a6c1afd00000000}, + {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000, + 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000, + 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000, + 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000, + 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000, + 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000, + 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000, + 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000, + 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000, + 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000, + 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000, + 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000, + 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000, + 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000, + 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000, + 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000, + 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000, + 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000, + 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000, + 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000, + 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000, + 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000, + 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000, + 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000, + 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000, + 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000, + 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000, + 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000, + 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000, + 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000, + 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000, + 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000, + 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000, + 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000, + 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000, + 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000, + 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000, + 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000, + 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000, + 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000, + 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000, + 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000, + 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000, + 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000, + 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000, + 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000, + 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000, + 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000, + 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000, + 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000, + 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000, + 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000, + 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000, + 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000, + 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000, + 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000, + 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000, + 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000, + 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000, + 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000, + 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000, + 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000, + 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000, + 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000, + 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000, + 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000, + 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000, + 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000, + 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000, + 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000, + 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000, + 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000, + 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000, + 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000, + 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000, + 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000, + 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000, + 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000, + 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000, + 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000, + 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000, + 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000, + 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000, + 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000, + 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000, + 0x5270900d00000000}, + {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000, + 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000, + 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000, + 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000, + 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000, + 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000, + 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000, + 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000, + 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000, + 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000, + 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000, + 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000, + 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000, + 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000, + 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000, + 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000, + 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000, + 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000, + 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000, + 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000, + 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000, + 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000, + 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000, + 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000, + 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000, + 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000, + 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000, + 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000, + 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000, + 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000, + 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000, + 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000, + 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000, + 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000, + 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000, + 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000, + 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000, + 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000, + 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000, + 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000, + 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000, + 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000, + 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000, + 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000, + 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000, + 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000, + 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000, + 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000, + 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000, + 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000, + 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000, + 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000, + 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000, + 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000, + 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000, + 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000, + 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000, + 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000, + 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000, + 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000, + 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000, + 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000, + 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000, + 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000, + 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000, + 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000, + 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000, + 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000, + 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000, + 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000, + 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000, + 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000, + 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000, + 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000, + 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000, + 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000, + 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000, + 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000, + 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000, + 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000, + 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000, + 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000, + 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000, + 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000, + 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000, + 0xa8a0688500000000}}; + +#else /* W == 4 */ + +local const z_crc_t FAR crc_braid_table[][256] = { + {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, + 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, + 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, + 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, + 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, + 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, + 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, + 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, + 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, + 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, + 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, + 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, + 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, + 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, + 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, + 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, + 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, + 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, + 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, + 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, + 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, + 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, + 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, + 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, + 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, + 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, + 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, + 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, + 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, + 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, + 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, + 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, + 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, + 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, + 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, + 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, + 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, + 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, + 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, + 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, + 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, + 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, + 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, + 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, + 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, + 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, + 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, + 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, + 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, + 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, + 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, + 0x09cd8551}, + {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, + 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, + 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, + 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, + 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, + 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, + 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, + 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, + 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, + 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, + 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, + 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, + 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, + 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, + 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, + 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, + 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, + 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, + 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, + 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, + 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, + 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, + 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, + 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, + 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, + 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, + 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, + 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, + 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, + 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, + 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, + 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, + 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, + 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, + 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, + 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, + 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, + 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, + 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, + 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, + 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, + 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, + 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, + 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, + 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, + 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, + 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, + 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, + 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, + 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, + 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, + 0x7bc97a0c}, + {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, + 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, + 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, + 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, + 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, + 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, + 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, + 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, + 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, + 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, + 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, + 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, + 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, + 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, + 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, + 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, + 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, + 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, + 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, + 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, + 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, + 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, + 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, + 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, + 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, + 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, + 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, + 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, + 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, + 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, + 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, + 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, + 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, + 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, + 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, + 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, + 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, + 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, + 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, + 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, + 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, + 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, + 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, + 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, + 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, + 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, + 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, + 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, + 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, + 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, + 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, + 0x7851a2ca}, + {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, + 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, + 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, + 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, + 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, + 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, + 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, + 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, + 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, + 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, + 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, + 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, + 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, + 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, + 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, + 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, + 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, + 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, + 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, + 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, + 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, + 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, + 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, + 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, + 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, + 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, + 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, + 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, + 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, + 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, + 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, + 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, + 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, + 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, + 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, + 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, + 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, + 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, + 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, + 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, + 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, + 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, + 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, + 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, + 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, + 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, + 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, + 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, + 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, + 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, + 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, + 0x566b6848}}; + +local const z_word_t FAR crc_braid_big_table[][256] = { + {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912, + 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba, + 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3, + 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30, + 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e, + 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3, + 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73, + 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe, + 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0, + 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643, + 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a, + 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082, + 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4, + 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279, + 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735, + 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8, + 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad, + 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05, + 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c, + 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718, + 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46, + 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb, + 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc, + 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41, + 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f, + 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad, + 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4, + 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c, + 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779, + 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4, + 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8, + 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235, + 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7, + 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f, + 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476, + 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195, + 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb, + 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46, + 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622, + 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af, + 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1, + 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12, + 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b, + 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3, + 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51, + 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc, + 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90, + 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d, + 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708, + 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0, + 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9, + 0x48686b56}, + {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c, + 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae, + 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb, + 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90, + 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410, + 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b, + 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6, + 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed, + 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d, + 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036, + 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953, + 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1, + 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca, + 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781, + 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d, + 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416, + 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f, + 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd, + 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8, + 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b, + 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb, + 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0, + 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5, + 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e, + 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e, + 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558, + 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d, + 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf, + 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6, + 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad, + 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971, + 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a, + 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b, + 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969, + 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c, + 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57, + 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7, + 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c, + 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab, + 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0, + 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160, + 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b, + 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e, + 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac, + 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d, + 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546, + 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a, + 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1, + 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8, + 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a, + 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f, + 0xcaa25178}, + {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00, + 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b, + 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed, + 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777, + 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01, + 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a, + 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef, + 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74, + 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002, + 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498, + 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee, + 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75, + 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05, + 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e, + 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8, + 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73, + 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404, + 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f, + 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9, + 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71, + 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607, + 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c, + 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb, + 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470, + 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806, + 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790, + 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6, + 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d, + 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a, + 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991, + 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7, + 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c, + 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09, + 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92, + 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4, + 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e, + 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08, + 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593, + 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3, + 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778, + 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e, + 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94, + 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2, + 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079, + 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c, + 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497, + 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1, + 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a, + 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d, + 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396, + 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0, + 0x0c7ac97b}, + {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669, + 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853, + 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062, + 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527, + 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad, + 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545, + 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27, + 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf, + 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45, + 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800, + 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031, + 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b, + 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26, + 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce, + 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d, + 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5, + 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130, + 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a, + 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b, + 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480, + 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a, + 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2, + 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e, + 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996, + 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c, + 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc, + 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd, + 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7, + 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232, + 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da, + 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439, + 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1, + 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da, + 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0, + 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1, + 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94, + 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e, + 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6, + 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2, + 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a, + 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0, + 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95, + 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4, + 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e, + 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395, + 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d, + 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e, + 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676, + 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83, + 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9, + 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888, + 0x5185cd09}}; + +#endif + +#endif + #endif - } -}; -ABC_NAMESPACE_HEADER_END +local const z_crc_t FAR x2n_table[] = { + 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000, + 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467, + 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0, + 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169, + 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37, + 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a, + 0xc40ba6d0, 0xc4e22c3c}; diff --git a/src/misc/zlib/deflate.c b/src/misc/zlib/deflate.c index 5e71508388..0551c5e341 100644 --- a/src/misc/zlib/deflate.c +++ b/src/misc/zlib/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2026 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -37,7 +37,7 @@ * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://www.ietf.org/rfc/rfc1951.txt + * Available at https://datatracker.ietf.org/doc/html/rfc1951 * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. @@ -58,8 +58,9 @@ ABC_NAMESPACE_IMPL_START + const char deflate_copyright[] = - " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; + " deflate 1.3.2 Copyright 1995-2026 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -67,9 +68,6 @@ const char deflate_copyright[] = copyright string in the executable of your product. */ -/* =========================================================================== - * Function prototypes. - */ typedef enum { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ @@ -77,32 +75,16 @@ typedef enum { finish_done /* finish done, accept no more input or output */ } block_state; -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +typedef block_state (*compress_func)(deflate_state *s, int flush); /* Compression function. Returns the block state after the call. */ -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); +local block_state deflate_stored(deflate_state *s, int flush); +local block_state deflate_fast(deflate_state *s, int flush); #ifndef FASTEST -local block_state deflate_slow OF((deflate_state *s, int flush)); -#endif -local block_state deflate_rle OF((deflate_state *s, int flush)); -local block_state deflate_huff OF((deflate_state *s, int flush)); -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); -local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -#ifdef ASMV - void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match)); -#else -local uInt longest_match OF((deflate_state *s, IPos cur_match)); -#endif - -#ifdef DEBUG -local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); +local block_state deflate_slow(deflate_state *s, int flush); #endif +local block_state deflate_rle(deflate_state *s, int flush); +local block_state deflate_huff(deflate_state *s, int flush); /* =========================================================================== * Local data @@ -155,20 +137,16 @@ local const config configuration_table[10] = { * meaning. */ -#define EQUAL 0 -/* result of memcmp for equal strings */ - -#ifndef NO_DUMMY_DECL -struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ -#endif +/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ +#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) /* =========================================================================== * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. + * IN assertion: all calls to UPDATE_HASH are made with consecutive input + * characters, so that a running hash key can be computed from the previous + * key instead of complete recalculation each time. */ -#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) +#define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask) /* =========================================================================== @@ -177,9 +155,9 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). + * IN assertion: all calls to INSERT_STRING are made with consecutive input + * characters and the first MIN_MATCH bytes of str are valid (except for + * the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ @@ -198,30 +176,229 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ * prev[] will be initialized on the fly. */ #define CLEAR_HASH(s) \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + do { \ + s->head[s->hash_size - 1] = NIL; \ + zmemzero(s->head, (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \ + s->slid = 0; \ + } while (0) + +/* =========================================================================== + * Slide the hash table when sliding the window down (could be avoided with 32 + * bit values at the expense of memory usage). We slide even when level == 0 to + * keep the hash table consistent if we switch back to level > 0 later. + */ +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + __attribute__((no_sanitize("memory"))) +# endif +#endif +local void slide_hash(deflate_state *s) { + unsigned n, m; + Posf *p; + uInt wsize = s->w_size; + + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + } while (--n); +#ifndef FASTEST + n = wsize; + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + s->slid = 1; +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size) { + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + zmemcpy(buf, strm->next_in, len); + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, buf, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, buf, len); + } +#endif + strm->next_in += len; + strm->total_in += len; + + return len; +} + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(deflate_state *s) { + unsigned n; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif + if (sizeof(int) <= 2) { +#ifdef _MSC_VER +#pragma warning(pop) +#endif + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize + MAX_DIST(s)) { + + zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + if (s->insert > s->strstart) + s->insert = s->strstart; + slide_hash(s); + more += wsize; + } + if (s->strm->avail_in == 0) break; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead + s->insert >= MIN_MATCH) { + uInt str = s->strstart - s->insert; + s->ins_h = s->window[str]; + UPDATE_HASH(s, s->ins_h, s->window[str + 1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + while (s->insert) { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + s->insert--; + if (s->lookahead + s->insert < MIN_MATCH) + break; + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } + + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "not enough room for search"); +} /* ========================================================================= */ -int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int stream_size) -{ +int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, + int stream_size) { return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ -int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, - const char *version, int stream_size) -{ +int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, + int windowBits, int memLevel, int strategy, + const char *version, int stream_size) { deflate_state *s; int wrap = 1; static const char my_version[] = ZLIB_VERSION; - ushf *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ - if (version == Z_NULL || version[0] != my_version[0] || stream_size != sizeof(z_stream)) { return Z_VERSION_ERROR; @@ -230,10 +407,19 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBi strm->msg = Z_NULL; if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; +#endif } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif #ifdef FASTEST if (level != 0) level = 1; @@ -243,6 +429,8 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBi if (windowBits < 0) { /* suppress zlib wrapper */ wrap = 0; + if (windowBits < -15) + return Z_STREAM_ERROR; windowBits = -windowBits; } #ifdef GZIP @@ -253,25 +441,27 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBi #endif if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { + strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { return Z_STREAM_ERROR; } if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); if (s == Z_NULL) return Z_MEM_ERROR; + zmemzero(s, sizeof(deflate_state)); strm->state = (struct internal_state FAR *)s; s->strm = strm; + s->status = INIT_STATE; /* to pass state test in deflateReset() */ s->wrap = wrap; s->gzhead = Z_NULL; - s->w_bits = windowBits; + s->w_bits = (uInt)windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; - s->hash_bits = memLevel + 7; + s->hash_bits = (uInt)memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH); s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); @@ -281,19 +471,67 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBi s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - s->pending_buf = (uchf *) overlay; - s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + /* We overlay pending_buf and sym_buf. This works since the average size + * for length/distance pairs over any compressed block is assured to be 31 + * bits or less. + * + * Analysis: The longest fixed codes are a length code of 8 bits plus 5 + * extra bits, for lengths 131 to 257. The longest fixed distance codes are + * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest + * possible fixed-codes length/distance pair is then 31 bits total. + * + * sym_buf starts one-fourth of the way into pending_buf. So there are + * three bytes in sym_buf for every four bytes in pending_buf. Each symbol + * in sym_buf is three bytes -- two for the distance and one for the + * literal/length. As each symbol is consumed, the pointer to the next + * sym_buf value to read moves forward three bytes. From that symbol, up to + * 31 bits are written to pending_buf. The closest the written pending_buf + * bits gets to the next sym_buf symbol to read is just before the last + * code is written. At that time, 31*(n - 2) bits have been written, just + * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at + * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1 + * symbols are written.) The closest the writing gets to what is unread is + * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and + * can range from 128 to 32768. + * + * Therefore, at a minimum, there are 142 bits of space between what is + * written and what is read in the overlain buffers, so the symbols cannot + * be overwritten by the compressed data. That space is actually 139 bits, + * due to the three-bit fixed-code block header. + * + * That covers the case where either Z_FIXED is specified, forcing fixed + * codes, or when the use of fixed codes is chosen, because that choice + * results in a smaller compressed block than dynamic codes. That latter + * condition then assures that the above analysis also covers all dynamic + * blocks. A dynamic-code block will only be chosen to be emitted if it has + * fewer bits than a fixed-code block would for the same set of symbols. + * Therefore its average symbol length is assured to be less than 31. So + * the compressed data for a dynamic block also cannot overwrite the + * symbols from which it is being constructed. + */ + + s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, LIT_BUFS); + s->pending_buf_size = (ulg)s->lit_bufsize * 4; if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { s->status = FINISH_STATE; - strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + strm->msg = ERR_MSG(Z_MEM_ERROR); deflateEnd (strm); return Z_MEM_ERROR; } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; +#ifdef LIT_MEM + s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1)); + s->l_buf = s->pending_buf + (s->lit_bufsize << 2); + s->sym_end = s->lit_bufsize - 1; +#else + s->sym_buf = s->pending_buf + s->lit_bufsize; + s->sym_end = (s->lit_bufsize - 1) * 3; +#endif + /* We avoid equality with lit_bufsize*3 because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ s->level = level; s->strategy = strategy; @@ -302,52 +540,119 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBi return deflateReset(strm); } +/* ========================================================================= + * Check for a valid deflate stream state. Return 0 if ok, 1 if not. + */ +local int deflateStateCheck(z_streamp strm) { + deflate_state *s; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + s = strm->state; + if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && +#ifdef GZIP + s->status != GZIP_STATE && +#endif + s->status != EXTRA_STATE && + s->status != NAME_STATE && + s->status != COMMENT_STATE && + s->status != HCRC_STATE && + s->status != BUSY_STATE && + s->status != FINISH_STATE)) + return 1; + return 0; +} + /* ========================================================================= */ -int ZEXPORT deflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength) -{ +int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary, + uInt dictLength) { deflate_state *s; - uInt length = dictLength; - uInt n; - IPos hash_head = 0; + uInt str, n; + int wrap; + unsigned avail; + z_const unsigned char *next; - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || - strm->state->wrap == 2 || - (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + if (deflateStateCheck(strm) || dictionary == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - if (s->wrap) - strm->adler = adler32(strm->adler, dictionary, dictLength); + wrap = s->wrap; + if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) + return Z_STREAM_ERROR; - if (length < MIN_MATCH) return Z_OK; - if (length > s->w_size) { - length = s->w_size; - dictionary += dictLength - length; /* use the tail of the dictionary */ + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap == 1) + strm->adler = adler32(strm->adler, dictionary, dictLength); + s->wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s->w_size) { + if (wrap == 0) { /* already empty otherwise */ + CLEAR_HASH(s); + s->strstart = 0; + s->block_start = 0L; + s->insert = 0; + } + dictionary += dictLength - s->w_size; /* use the tail */ + dictLength = s->w_size; } - zmemcpy(s->window, dictionary, length); - s->strstart = length; - s->block_start = (long)length; - /* Insert all strings in the hash table (except for the last two bytes). - * s->lookahead stays null, so s->ins_h will be recomputed at the next - * call of fill_window. - */ - s->ins_h = s->window[0]; - UPDATE_HASH(s, s->ins_h, s->window[1]); - for (n = 0; n <= length - MIN_MATCH; n++) { - INSERT_STRING(s, n, hash_head); + /* insert dictionary into window and hash */ + avail = strm->avail_in; + next = strm->next_in; + strm->avail_in = dictLength; + strm->next_in = (z_const Bytef *)dictionary; + fill_window(s); + while (s->lookahead >= MIN_MATCH) { + str = s->strstart; + n = s->lookahead - (MIN_MATCH-1); + do { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + } while (--n); + s->strstart = str; + s->lookahead = MIN_MATCH-1; + fill_window(s); } - if (hash_head) hash_head = 0; /* to make compiler happy */ + s->strstart += s->lookahead; + s->block_start = (long)s->strstart; + s->insert = s->lookahead; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + strm->next_in = next; + strm->avail_in = avail; + s->wrap = wrap; return Z_OK; } /* ========================================================================= */ -int ZEXPORT deflateReset (z_streamp strm) -{ +int ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary, + uInt *dictLength) { deflate_state *s; + uInt len; - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + len = s->strstart + s->lookahead; + if (len > s->w_size) + len = s->w_size; + if (dictionary != Z_NULL && len) + zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); + if (dictLength != Z_NULL) + *dictLength = len; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateResetKeep(z_streamp strm) { + deflate_state *s; + + if (deflateStateCheck(strm)) { return Z_STREAM_ERROR; } @@ -362,46 +667,123 @@ int ZEXPORT deflateReset (z_streamp strm) if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ } - s->status = s->wrap ? INIT_STATE : BUSY_STATE; + s->status = +#ifdef GZIP + s->wrap == 2 ? GZIP_STATE : +#endif + INIT_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : #endif adler32(0L, Z_NULL, 0); - s->last_flush = Z_NO_FLUSH; + s->last_flush = -2; _tr_init(s); - lm_init(s); return Z_OK; } +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init(deflate_state *s) { + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->insert = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +} + /* ========================================================================= */ -int ZEXPORT deflateSetHeader (z_streamp strm, gz_headerp head) -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (strm->state->wrap != 2) return Z_STREAM_ERROR; +int ZEXPORT deflateReset(z_streamp strm) { + int ret; + + ret = deflateResetKeep(strm); + if (ret == Z_OK) + lm_init(strm->state); + return ret; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader(z_streamp strm, gz_headerp head) { + if (deflateStateCheck(strm) || strm->state->wrap != 2) + return Z_STREAM_ERROR; strm->state->gzhead = head; return Z_OK; } /* ========================================================================= */ -int ZEXPORT deflatePrime (z_streamp strm, int bits, int value) -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - strm->state->bi_valid = bits; - strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); +int ZEXPORT deflatePending(z_streamp strm, unsigned *pending, int *bits) { + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + if (bits != Z_NULL) + *bits = strm->state->bi_valid; + if (pending != Z_NULL) { + *pending = (unsigned)strm->state->pending; + if (*pending != strm->state->pending) { + *pending = (unsigned)-1; + return Z_BUF_ERROR; + } + } + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateUsed(z_streamp strm, int *bits) { + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + if (bits != Z_NULL) + *bits = strm->state->bi_used; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) { + deflate_state *s; + int put; + + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + s = strm->state; +#ifdef LIT_MEM + if (bits < 0 || bits > 16 || + (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3)) + return Z_BUF_ERROR; +#else + if (bits < 0 || bits > 16 || + s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3)) + return Z_BUF_ERROR; +#endif + do { + put = Buf_size - s->bi_valid; + if (put > bits) + put = bits; + s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); + s->bi_valid += put; + _tr_flush_bits(s); + value >>= put; + bits -= put; + } while (bits); return Z_OK; } /* ========================================================================= */ -int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) -{ +int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) { deflate_state *s; compress_func func; - int err = Z_OK; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; #ifdef FASTEST @@ -415,11 +797,22 @@ int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) func = configuration_table[s->level].func; if ((strategy != s->strategy || func != configuration_table[level].func) && - strm->total_in != 0) { + s->last_flush != -2) { /* Flush the last buffer: */ - err = deflate(strm, Z_BLOCK); + int err = deflate(strm, Z_BLOCK); + if (err == Z_STREAM_ERROR) + return err; + if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead) + return Z_BUF_ERROR; } if (s->level != level) { + if (s->level == 0 && s->matches != 0) { + if (s->matches == 1) + slide_hash(s); + else + CLEAR_HASH(s); + s->matches = 0; + } s->level = level; s->max_lazy_match = configuration_table[level].max_lazy; s->good_match = configuration_table[level].good_length; @@ -427,66 +820,86 @@ int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) s->max_chain_length = configuration_table[level].max_chain; } s->strategy = strategy; - return err; + return Z_OK; } /* ========================================================================= */ -int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain) -{ +int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, + int nice_length, int max_chain) { deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; - s->good_match = good_length; - s->max_lazy_match = max_lazy; + s->good_match = (uInt)good_length; + s->max_lazy_match = (uInt)max_lazy; s->nice_match = nice_length; - s->max_chain_length = max_chain; + s->max_chain_length = (uInt)max_chain; return Z_OK; } /* ========================================================================= - * For the default windowBits of 15 and memLevel of 8, this function returns - * a close to exact, as well as small, upper bound on the compressed size. - * They are coded as constants here for a reason--if the #define's are - * changed, then this function needs to be changed as well. The return - * value for 15 and 8 only works for those exact settings. + * For the default windowBits of 15 and memLevel of 8, this function returns a + * close to exact, as well as small, upper bound on the compressed size. This + * is an expansion of ~0.03%, plus a small constant. + * + * For any setting other than those defaults for windowBits and memLevel, one + * of two worst case bounds is returned. This is at most an expansion of ~4% or + * ~13%, plus a small constant. + * + * Both the 0.03% and 4% derive from the overhead of stored blocks. The first + * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second + * is for stored blocks of 127 bytes (the worst case memLevel == 1). The + * expansion results from five bytes of header for each stored block. * - * For any setting other than those defaults for windowBits and memLevel, - * the value returned is a conservative worst case for the maximum expansion - * resulting from using fixed blocks instead of stored blocks, which deflate - * can emit on compressed data for some combinations of the parameters. + * The larger expansion of 13% results from a window size less than or equal to + * the symbols buffer size (windowBits <= memLevel + 7). In that case some of + * the data being compressed may have slid out of the sliding window, impeding + * a stored block from being emitted. Then the only choice is a fixed or + * dynamic block, where a fixed block limits the maximum expansion to 9 bits + * per 8-bit byte, plus 10 bits for every block. The smallest block size for + * which this can occur is 255 (memLevel == 2). * - * This function could be more sophisticated to provide closer upper bounds for - * every combination of windowBits and memLevel. But even the conservative - * upper bound of about 14% expansion does not seem onerous for output buffer - * allocation. + * Shifts are used to approximate divisions, for speed. */ -uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) -{ +z_size_t ZEXPORT deflateBound_z(z_streamp strm, z_size_t sourceLen) { deflate_state *s; - uLong complen, wraplen; - Bytef *str; - - /* conservative upper bound for compressed data */ - complen = sourceLen + - ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; - - /* if can't get parameters, return conservative bound plus zlib wrapper */ - if (strm == Z_NULL || strm->state == Z_NULL) - return complen + 6; + z_size_t fixedlen, storelen, wraplen, bound; + + /* upper bound for fixed blocks with 9-bit literals and length 255 + (memLevel == 2, which is the lowest that may not use stored blocks) -- + ~13% overhead plus a small constant */ + fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) + + (sourceLen >> 9) + 4; + if (fixedlen < sourceLen) + fixedlen = (z_size_t)-1; + + /* upper bound for stored blocks with length 127 (memLevel == 1) -- + ~4% overhead plus a small constant */ + storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) + + (sourceLen >> 11) + 7; + if (storelen < sourceLen) + storelen = (z_size_t)-1; + + /* if can't get parameters, return larger bound plus a wrapper */ + if (deflateStateCheck(strm)) { + bound = fixedlen > storelen ? fixedlen : storelen; + return bound + 18 < bound ? (z_size_t)-1 : bound + 18; + } /* compute wrapper length */ s = strm->state; - switch (s->wrap) { + switch (s->wrap < 0 ? -s->wrap : s->wrap) { case 0: /* raw deflate */ wraplen = 0; break; case 1: /* zlib wrapper */ wraplen = 6 + (s->strstart ? 4 : 0); break; +#ifdef GZIP case 2: /* gzip wrapper */ wraplen = 18; if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + Bytef *str; if (s->gzhead->extra != Z_NULL) wraplen += 2 + s->gzhead->extra_len; str = s->gzhead->name; @@ -503,17 +916,27 @@ uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) wraplen += 2; } break; +#endif default: /* for compiler happiness */ - wraplen = 6; + wraplen = 18; } - /* if not default parameters, return conservative bound */ - if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return complen + wraplen; + /* if not default parameters, return one of the conservative bounds */ + if (s->w_bits != 15 || s->hash_bits != 8 + 7) { + bound = s->w_bits <= s->hash_bits && s->level ? fixedlen : + storelen; + return bound + wraplen < bound ? (z_size_t)-1 : bound + wraplen; + } - /* default settings: return tight bound for that case */ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + - (sourceLen >> 25) + 13 - 6 + wraplen; + /* default settings: return tight bound for that case -- ~0.03% overhead + plus a small constant */ + bound = sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13 - 6 + wraplen; + return bound < sourceLen ? (z_size_t)-1 : bound; +} +uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) { + z_size_t bound = deflateBound_z(strm, sourceLen); + return (uLong)bound != bound ? (uLong)-1 : (uLong)bound; } /* ========================================================================= @@ -521,266 +944,277 @@ uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ -local void putShortMSB (deflate_state *s, uInt b) -{ +local void putShortMSB(deflate_state *s, uInt b) { put_byte(s, (Byte)(b >> 8)); put_byte(s, (Byte)(b & 0xff)); } /* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). + * Flush as much pending output as possible. All deflate() output, except for + * some deflate_stored() output, goes through this function so some + * applications may wish to modify it to avoid allocating a large + * strm->next_out buffer and copying into it. (See also read_buf()). */ -local void flush_pending(z_streamp strm) -{ - unsigned len = strm->state->pending; +local void flush_pending(z_streamp strm) { + unsigned len; + deflate_state *s = strm->state; - if (len > strm->avail_out) len = strm->avail_out; + _tr_flush_bits(s); + len = s->pending > strm->avail_out ? strm->avail_out : + (unsigned)s->pending; if (len == 0) return; - zmemcpy(strm->next_out, strm->state->pending_out, len); + zmemcpy(strm->next_out, s->pending_out, len); strm->next_out += len; - strm->state->pending_out += len; + s->pending_out += len; strm->total_out += len; - strm->avail_out -= len; - strm->state->pending -= len; - if (strm->state->pending == 0) { - strm->state->pending_out = strm->state->pending_buf; + strm->avail_out -= len; + s->pending -= len; + if (s->pending == 0) { + s->pending_out = s->pending_buf; } } +/* =========================================================================== + * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. + */ +#define HCRC_UPDATE(beg) \ + do { \ + if (s->gzhead->hcrc && s->pending > (beg)) \ + strm->adler = crc32_z(strm->adler, s->pending_buf + (beg), \ + s->pending - (beg)); \ + } while (0) + /* ========================================================================= */ -int ZEXPORT deflate (z_streamp strm, int flush) -{ +int ZEXPORT deflate(z_streamp strm, int flush) { int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_BLOCK || flush < 0) { + if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || + (strm->avail_in != 0 && strm->next_in == Z_NULL) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - s->strm = strm; /* just in case */ old_flush = s->last_flush; s->last_flush = flush; + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + /* Write the header */ + if (s->status == INIT_STATE && s->wrap == 0) + s->status = BUSY_STATE; if (s->status == INIT_STATE) { -#ifdef GZIP - if (s->wrap == 2) { - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == Z_NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (Byte)(s->gzhead->time & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != Z_NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } + /* zlib header */ + uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; else -#endif - { - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + putShortMSB(s, header); + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#ifdef GZIP + if (s->status == GZIP_STATE) { + /* gzip header */ + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); s->status = BUSY_STATE; - putShortMSB(s, header); - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); } - strm->adler = adler32(0L, Z_NULL, 0); + if (s->gzhead->hcrc) + strm->adler = crc32_z(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; } } -#ifdef GZIP if (s->status == EXTRA_STATE) { if (s->gzhead->extra != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - - while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) - break; + ulg beg = s->pending; /* start of bytes to update crc */ + ulg left = (s->gzhead->extra_len & 0xffff) - s->gzindex; + while (s->pending + left > s->pending_buf_size) { + ulg copy = s->pending_buf_size - s->pending; + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, copy); + s->pending = s->pending_buf_size; + HCRC_UPDATE(beg); + s->gzindex += copy; + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; } - put_byte(s, s->gzhead->extra[s->gzindex]); - s->gzindex++; - } - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (s->gzindex == s->gzhead->extra_len) { - s->gzindex = 0; - s->status = NAME_STATE; + beg = 0; + left -= copy; } + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, left); + s->pending += left; + HCRC_UPDATE(beg); + s->gzindex = 0; } - else - s->status = NAME_STATE; + s->status = NAME_STATE; } if (s->status == NAME_STATE) { if (s->gzhead->name != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ + ulg beg = s->pending; /* start of bytes to update crc */ int val; - do { if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); + HCRC_UPDATE(beg); flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; } + beg = 0; } val = s->gzhead->name[s->gzindex++]; put_byte(s, val); } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) { - s->gzindex = 0; - s->status = COMMENT_STATE; - } + HCRC_UPDATE(beg); + s->gzindex = 0; } - else - s->status = COMMENT_STATE; + s->status = COMMENT_STATE; } if (s->status == COMMENT_STATE) { if (s->gzhead->comment != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ + ulg beg = s->pending; /* start of bytes to update crc */ int val; - do { if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); + HCRC_UPDATE(beg); flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; } + beg = 0; } val = s->gzhead->comment[s->gzindex++]; put_byte(s, val); } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) - s->status = HCRC_STATE; + HCRC_UPDATE(beg); } - else - s->status = HCRC_STATE; + s->status = HCRC_STATE; } if (s->status == HCRC_STATE) { if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) + if (s->pending + 2 > s->pending_buf_size) { flush_pending(strm); - if (s->pending + 2 <= s->pending_buf_size) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - s->status = BUSY_STATE; + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } } + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); } - else - s->status = BUSY_STATE; - } -#endif + s->status = BUSY_STATE; - /* Flush as much pending output as possible */ - if (s->pending != 0) { + /* Compression must start with an empty pending buffer */ flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ + if (s->pending != 0) { s->last_flush = -1; return Z_OK; } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm->avail_in == 0 && flush <= old_flush && - flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); } +#endif /* Start a new block or continue the current one. */ @@ -788,9 +1222,10 @@ int ZEXPORT deflate (z_streamp strm, int flush) (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; - bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : - (s->strategy == Z_RLE ? deflate_rle(s, flush) : - (*(configuration_table[s->level].func))(s, flush)); + bstate = s->level == 0 ? deflate_stored(s, flush) : + s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; @@ -821,6 +1256,7 @@ int ZEXPORT deflate (z_streamp strm, int flush) if (s->lookahead == 0) { s->strstart = 0; s->block_start = 0L; + s->insert = 0; } } } @@ -831,7 +1267,6 @@ int ZEXPORT deflate (z_streamp strm, int flush) } } } - Assert(strm->avail_out > 0, "bug2"); if (flush != Z_FINISH) return Z_OK; if (s->wrap <= 0) return Z_STREAM_END; @@ -863,22 +1298,12 @@ int ZEXPORT deflate (z_streamp strm, int flush) } /* ========================================================================= */ -int ZEXPORT deflateEnd (z_streamp strm) -{ +int ZEXPORT deflateEnd(z_streamp strm) { int status; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; status = strm->state->status; - if (status != INIT_STATE && - status != EXTRA_STATE && - status != NAME_STATE && - status != COMMENT_STATE && - status != HCRC_STATE && - status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); @@ -897,17 +1322,17 @@ int ZEXPORT deflateEnd (z_streamp strm) * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ -int ZEXPORT deflateCopy (z_streamp dest, z_streamp source) -{ +int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) { #ifdef MAXSEG_64K + (void)dest; + (void)source; return Z_STREAM_ERROR; #else deflate_state *ds; deflate_state *ss; - ushf *overlay; - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + if (deflateStateCheck(source) || dest == Z_NULL) { return Z_STREAM_ERROR; } @@ -917,6 +1342,7 @@ int ZEXPORT deflateCopy (z_streamp dest, z_streamp source) ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; + zmemzero(ds, sizeof(deflate_state)); dest->state = (struct internal_state FAR *) ds; zmemcpy(ds, ss, sizeof(deflate_state)); ds->strm = dest; @@ -924,23 +1350,31 @@ int ZEXPORT deflateCopy (z_streamp dest, z_streamp source) ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; + ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, LIT_BUFS); if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ds->pending_buf == Z_NULL) { deflateEnd (dest); return Z_MEM_ERROR; } - /* following zmemcpy do not work for 16-bit MSDOS */ - zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + /* following zmemcpy's do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ss->high_water); + zmemcpy(ds->prev, ss->prev, + (ss->slid || ss->strstart - ss->insert > ds->w_size ? ds->w_size : + ss->strstart - ss->insert) * sizeof(Pos)); zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); - ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + zmemcpy(ds->pending_out, ss->pending_out, ss->pending); +#ifdef LIT_MEM + ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1)); + ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2); + zmemcpy(ds->d_buf, ss->d_buf, ss->sym_next * sizeof(ush)); + zmemcpy(ds->l_buf, ss->l_buf, ss->sym_next); +#else + ds->sym_buf = ds->pending_buf + ds->lit_bufsize; + zmemcpy(ds->sym_buf, ss->sym_buf, ss->sym_next); +#endif ds->l_desc.dyn_tree = ds->dyn_ltree; ds->d_desc.dyn_tree = ds->dyn_dtree; @@ -950,66 +1384,6 @@ int ZEXPORT deflateCopy (z_streamp dest, z_streamp source) #endif /* MAXSEG_64K */ } -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -local int read_buf(z_streamp strm, Bytef *buf, unsigned size) -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, strm->next_in, len); - } -#ifdef GZIP - else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, strm->next_in, len); - } -#endif - zmemcpy(buf, strm->next_in, len); - strm->next_in += len; - strm->total_in += len; - - return (int)len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -local void lm_init (deflate_state *s) -{ - s->window_size = (ulg)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -#ifndef FASTEST -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif -#endif -} - #ifndef FASTEST /* =========================================================================== * Set match_start to the longest match starting at the given string and @@ -1020,17 +1394,12 @@ local void lm_init (deflate_state *s) * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ -#ifndef ASMV -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ -local uInt longest_match(deflate_state *s, IPos cur_match) -{ +local uInt longest_match(deflate_state *s, IPos cur_match) { unsigned chain_length = s->max_chain_length;/* max hash chain length */ - Bytef *scan = s->window + s->strstart; /* current string */ - Bytef *match; /* matched string */ - int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ + Bytef *scan = s->window + s->strstart; /* current string */ + Bytef *match; /* matched string */ + int len; /* length of current match */ + int best_len = (int)s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; @@ -1046,10 +1415,10 @@ local uInt longest_match(deflate_state *s, IPos cur_match) */ Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; ush scan_start = *(ushf*)scan; - ush scan_end = *(ushf*)(scan+best_len-1); + ush scan_end = *(ushf*)(scan + best_len - 1); #else Bytef *strend = s->window + s->strstart + MAX_MATCH; - Byte scan_end1 = scan[best_len-1]; + Byte scan_end1 = scan[best_len - 1]; Byte scan_end = scan[best_len]; #endif @@ -1065,9 +1434,10 @@ local uInt longest_match(deflate_state *s, IPos cur_match) /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); @@ -1085,43 +1455,44 @@ local uInt longest_match(deflate_state *s, IPos cur_match) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ - if (*(ushf*)(match+best_len-1) != scan_end || + if (*(ushf*)(match + best_len - 1) != scan_end || *(ushf*)match != scan_start) continue; /* It is not necessary to compare scan[2] and match[2] since they are * always equal when the other bytes match, given that the hash keys * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient + * strstart + 3, + 5, up to strstart + 257. We check for insufficient * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ Assert(scan[2] == match[2], "scan[2]?"); scan++, match++; do { - } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) && + *(ushf*)(scan += 2) == *(ushf*)(match += 2) && + *(ushf*)(scan += 2) == *(ushf*)(match += 2) && + *(ushf*)(scan += 2) == *(ushf*)(match += 2) && scan < strend); /* The funny "do {}" generates better code on most compilers */ - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + /* Here, scan <= window + strstart + 257 */ + Assert(scan <= s->window + (unsigned)(s->window_size - 1), + "wild scan"); if (*scan == *match) scan++; - len = (MAX_MATCH - 1) - (int)(strend-scan); + len = (MAX_MATCH - 1) - (int)(strend - scan); scan = strend - (MAX_MATCH-1); #else /* UNALIGNED_OK */ - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; + if (match[best_len] != scan_end || + match[best_len - 1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; - /* The check at best_len-1 can be removed because it will be made + /* The check at best_len - 1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that @@ -1131,7 +1502,7 @@ local uInt longest_match(deflate_state *s, IPos cur_match) Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. + * the 256th check will be made at strstart + 258. */ do { } while (*++scan == *++match && *++scan == *++match && @@ -1140,7 +1511,8 @@ local uInt longest_match(deflate_state *s, IPos cur_match) *++scan == *++match && *++scan == *++match && scan < strend); - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + Assert(scan <= s->window + (unsigned)(s->window_size - 1), + "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; @@ -1152,9 +1524,9 @@ local uInt longest_match(deflate_state *s, IPos cur_match) best_len = len; if (len >= nice_match) break; #ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); + scan_end = *(ushf*)(scan + best_len - 1); #else - scan_end1 = scan[best_len-1]; + scan_end1 = scan[best_len - 1]; scan_end = scan[best_len]; #endif } @@ -1164,18 +1536,16 @@ local uInt longest_match(deflate_state *s, IPos cur_match) if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } -#endif /* ASMV */ #else /* FASTEST */ /* --------------------------------------------------------------------------- * Optimized version for FASTEST only */ -local uInt longest_match(deflate_state *s, IPos cur_match) -{ - Bytef *scan = s->window + s->strstart; /* current string */ - Bytef *match; /* matched string */ - int len; /* length of current match */ +local uInt longest_match(deflate_state *s, IPos cur_match) { + Bytef *scan = s->window + s->strstart; /* current string */ + Bytef *match; /* matched string */ + int len; /* length of current match */ Bytef *strend = s->window + s->strstart + MAX_MATCH; /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. @@ -1183,7 +1553,8 @@ local uInt longest_match(deflate_state *s, IPos cur_match) */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "need lookahead"); Assert(cur_match < s->strstart, "no future"); @@ -1193,7 +1564,7 @@ local uInt longest_match(deflate_state *s, IPos cur_match) */ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; - /* The check at best_len-1 can be removed because it will be made + /* The check at best_len - 1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that @@ -1203,7 +1574,7 @@ local uInt longest_match(deflate_state *s, IPos cur_match) Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. + * the 256th check will be made at strstart + 258. */ do { } while (*++scan == *++match && *++scan == *++match && @@ -1212,7 +1583,7 @@ local uInt longest_match(deflate_state *s, IPos cur_match) *++scan == *++match && *++scan == *++match && scan < strend); - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); @@ -1224,166 +1595,41 @@ local uInt longest_match(deflate_state *s, IPos cur_match) #endif /* FASTEST */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG + +#define EQUAL 0 +/* result of memcmp for equal strings */ + /* =========================================================================== * Check that the match at match_start is indeed a match. */ -local void check_match(deflate_state *s, IPos start, IPos match, int length) -{ +local void check_match(deflate_state *s, IPos start, IPos match, int length) { /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, (size_t)length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); + Bytef *back = s->window + (int)match, *here = s->window + start; + IPos len = (IPos)length; + if (match == (IPos)-1) { + /* match starts one byte before the current window -- just compare the + subsequent length-1 bytes */ + back++; + here++; + len--; + } + if (zmemcmp(back, here, len) != EQUAL) { + fprintf(stderr, " start %u, match %d, length %d\n", + start, (int)match, length); do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); + fprintf(stderr, "(%02x %02x)", *back++, *here++); + } while (--len != 0); z_error("invalid match"); } if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); + fprintf(stderr,"\\[%d,%d]", start - match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } } #else # define check_match(s, start, match, length) -#endif /* DEBUG */ - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -local void fill_window(deflate_state *s) -{ - unsigned n, m; - Posf *p; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s->strstart >= wsize+MAX_DIST(s)) { - - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif - more += wsize; - } - if (s->strm->avail_in == 0) return; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead >= MIN_MATCH) { - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - if (s->high_water < s->window_size) { - ulg curr = s->strstart + (ulg)(s->lookahead); - ulg init; - - if (s->high_water < curr) { - /* Previous high water mark below current data -- zero WIN_INIT - * bytes or up to end of window, whichever is less. - */ - init = s->window_size - curr; - if (init > WIN_INIT) - init = WIN_INIT; - zmemzero(s->window + curr, (unsigned)init); - s->high_water = curr + init; - } - else if (s->high_water < (ulg)curr + WIN_INIT) { - /* High water mark at or above current data, but below current data - * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - * to end of window, whichever is less. - */ - init = (ulg)curr + WIN_INIT - s->high_water; - if (init > s->window_size - s->high_water) - init = s->window_size - s->high_water; - zmemzero(s->window + s->high_water, (unsigned)init); - s->high_water += init; - } - } -} +#endif /* ZLIB_DEBUG */ /* =========================================================================== * Flush the current block, with given end-of-file flag. @@ -1406,62 +1652,207 @@ local void fill_window(deflate_state *s) if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ } +/* Maximum stored block length in deflate format (not including header). */ +#define MAX_STORED 65535 + +/* Minimum of a and b. */ +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. + * + * In case deflateParams() is used to later switch to a non-zero compression + * level, s->matches (otherwise unused when storing) keeps track of the number + * of hash table slides to perform. If s->matches is 1, then one hash table + * slide will be done when switching. If s->matches is 2, the maximum value + * allowed here, then the hash table will be cleared, since two or more slides + * is the same as a clear. + * + * deflate_stored() is written to minimize the number of times an input byte is + * copied. It is most efficient with large input and output buffers, which + * maximizes the opportunities to have a single copy from next_in to next_out. */ -local block_state deflate_stored(deflate_state *s, int flush) -{ - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: +local block_state deflate_stored(deflate_state *s, int flush) { + /* Smallest worthy block size when not flushing or finishing. By default + * this is 32K. This can be as small as 507 bytes for memLevel == 1. For + * large input and output buffers, the stored block size will be larger. */ - ulg max_block_size = 0xffff; - ulg max_start; + unsigned min_block = (unsigned)(MIN(s->pending_buf_size - 5, s->w_size)); - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); + /* Copy as many min_block or larger stored blocks directly to next_out as + * possible. If flushing, copy the remaining available input to next_out as + * stored blocks, if there is enough space. + */ + int last = 0; + unsigned len, left, have; + unsigned used = s->strm->avail_in; + do { + /* Set len to the maximum size block that we can copy directly with the + * available input data and output space. Set left to how much of that + * would be copied from what's left in the window. + */ + len = MAX_STORED; /* maximum deflate stored block length */ + have = ((unsigned)s->bi_valid + 42) >> 3; /* bytes in header */ + if (s->strm->avail_out < have) /* need room for header */ + break; + /* maximum stored block length that will fit in avail_out: */ + have = s->strm->avail_out - have; + left = (unsigned)(s->strstart - s->block_start); /* window bytes */ + if (len > (ulg)left + s->strm->avail_in) + len = left + s->strm->avail_in; /* limit len to the input */ + if (len > have) + len = have; /* limit len to the output */ + + /* If the stored block would be less than min_block in length, or if + * unable to copy all of the available input when flushing, then try + * copying to the window and the pending buffer instead. Also don't + * write an empty block when flushing -- deflate() does that. + */ + if (len < min_block && ((len == 0 && flush != Z_FINISH) || + flush == Z_NO_FLUSH || + len != left + s->strm->avail_in)) + break; - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + /* Make a dummy stored block in pending to get the header bytes, + * including any pending bits. This also updates the debugging counts. + */ + last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; + _tr_stored_block(s, (char *)0, 0L, last); + + /* Replace the lengths in the dummy stored block with len. */ + s->pending_buf[s->pending - 4] = (Bytef)len; + s->pending_buf[s->pending - 3] = (Bytef)(len >> 8); + s->pending_buf[s->pending - 2] = (Bytef)~len; + s->pending_buf[s->pending - 1] = (Bytef)(~len >> 8); + + /* Write the stored block header bytes. */ + flush_pending(s->strm); + +#ifdef ZLIB_DEBUG + /* Update debugging counts for the data about to be copied. */ + s->compressed_len += len << 3; + s->bits_sent += len << 3; +#endif - if (s->lookahead == 0) break; /* flush the current block */ + /* Copy uncompressed bytes from the window to next_out. */ + if (left) { + if (left > len) + left = len; + zmemcpy(s->strm->next_out, s->window + s->block_start, left); + s->strm->next_out += left; + s->strm->avail_out -= left; + s->strm->total_out += left; + s->block_start += left; + len -= left; } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); + + /* Copy uncompressed bytes directly from next_in to next_out, updating + * the check value. + */ + if (len) { + read_buf(s->strm, s->strm->next_out, len); + s->strm->next_out += len; + s->strm->avail_out -= len; + s->strm->total_out += len; } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: + } while (last == 0); + + /* Update the sliding window with the last s->w_size bytes of the copied + * data, or append all of the copied data to the existing window if less + * than s->w_size bytes were copied. Also update the number of bytes to + * insert in the hash tables, in the event that deflateParams() switches to + * a non-zero compression level. + */ + used -= s->strm->avail_in; /* number of input bytes directly copied */ + if (used) { + /* If any input was used, then no unused input remains in the window, + * therefore s->block_start == s->strstart. */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); + if (used >= s->w_size) { /* supplant the previous history */ + s->matches = 2; /* clear hash */ + zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); + s->strstart = s->w_size; + s->insert = s->strstart; } + else { + if (s->window_size - s->strstart <= used) { + /* Slide the window down. */ + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + if (s->insert > s->strstart) + s->insert = s->strstart; + } + zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); + s->strstart += used; + s->insert += MIN(used, s->w_size - s->insert); + } + s->block_start = s->strstart; + } + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* If the last block was written to next_out, then done. */ + if (last) { + s->bi_used = 8; + return finish_done; + } + + /* If flushing and all input has been consumed, then done. */ + if (flush != Z_NO_FLUSH && flush != Z_FINISH && + s->strm->avail_in == 0 && (long)s->strstart == s->block_start) + return block_done; + + /* Fill the window with any remaining input. */ + have = (unsigned)(s->window_size - s->strstart); + if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { + /* Slide the window down. */ + s->block_start -= s->w_size; + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + have += s->w_size; /* more space now */ + if (s->insert > s->strstart) + s->insert = s->strstart; + } + if (have > s->strm->avail_in) + have = s->strm->avail_in; + if (have) { + read_buf(s->strm, s->window + s->strstart, have); + s->strstart += have; + s->insert += MIN(have, s->w_size - s->insert); + } + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* There was not enough avail_out to write a complete worthy or flushed + * stored block to next_out. Write a stored block to pending instead, if we + * have enough input for a worthy block, or if flushing and there is enough + * room for the remaining input as a stored block in the pending buffer. + */ + have = ((unsigned)s->bi_valid + 42) >> 3; /* bytes in header */ + /* maximum stored block length that will fit in pending: */ + have = (unsigned)MIN(s->pending_buf_size - have, MAX_STORED); + min_block = MIN(have, s->w_size); + left = (unsigned)(s->strstart - s->block_start); + if (left >= min_block || + ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && + s->strm->avail_in == 0 && left <= have)) { + len = MIN(left, have); + last = flush == Z_FINISH && s->strm->avail_in == 0 && + len == left ? 1 : 0; + _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); + s->block_start += len; + flush_pending(s->strm); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + + /* We've done all we can with the available input and output. */ + if (last) + s->bi_used = 8; + return last ? finish_started : need_more; } /* =========================================================================== @@ -1471,8 +1862,7 @@ local block_state deflate_stored(deflate_state *s, int flush) * new strings in the dictionary only for unmatched strings or for short * matches. It is used only for the fast compression options. */ -local block_state deflate_fast(deflate_state *s, int flush) -{ +local block_state deflate_fast(deflate_state *s, int flush) { IPos hash_head; /* head of the hash chain */ int bflush; /* set if current block must be flushed */ @@ -1490,7 +1880,7 @@ local block_state deflate_fast(deflate_state *s, int flush) if (s->lookahead == 0) break; /* flush the current block */ } - /* Insert the string window[strstart .. strstart+2] in the + /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; @@ -1510,7 +1900,7 @@ local block_state deflate_fast(deflate_state *s, int flush) /* longest_match() sets match_start */ } if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); + check_match(s, s->strstart, s->match_start, (int)s->match_length); _tr_tally_dist(s, s->strstart - s->match_start, s->match_length - MIN_MATCH, bflush); @@ -1538,7 +1928,7 @@ local block_state deflate_fast(deflate_state *s, int flush) s->strstart += s->match_length; s->match_length = 0; s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); + UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif @@ -1549,14 +1939,20 @@ local block_state deflate_fast(deflate_state *s, int flush) } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->sym_next) + FLUSH_BLOCK(s, 0); + return block_done; } #ifndef FASTEST @@ -1565,8 +1961,7 @@ local block_state deflate_fast(deflate_state *s, int flush) * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ -local block_state deflate_slow(deflate_state *s, int flush) -{ +local block_state deflate_slow(deflate_state *s, int flush) { IPos hash_head; /* head of hash chain */ int bflush; /* set if current block must be flushed */ @@ -1585,7 +1980,7 @@ local block_state deflate_slow(deflate_state *s, int flush) if (s->lookahead == 0) break; /* flush the current block */ } - /* Insert the string window[strstart .. strstart+2] in the + /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; @@ -1627,17 +2022,17 @@ local block_state deflate_slow(deflate_state *s, int flush) uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ - check_match(s, s->strstart-1, s->prev_match, s->prev_length); + check_match(s, s->strstart - 1, s->prev_match, (int)s->prev_length); - _tr_tally_dist(s, s->strstart -1 - s->prev_match, + _tr_tally_dist(s, s->strstart - 1 - s->prev_match, s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not + * strstart - 1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ - s->lookahead -= s->prev_length-1; + s->lookahead -= s->prev_length - 1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { @@ -1655,8 +2050,8 @@ local block_state deflate_slow(deflate_state *s, int flush) * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); + Tracevv((stderr,"%c", s->window[s->strstart - 1])); + _tr_tally_lit(s, s->window[s->strstart - 1], bflush); if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } @@ -1674,12 +2069,18 @@ local block_state deflate_slow(deflate_state *s, int flush) } Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); + Tracevv((stderr,"%c", s->window[s->strstart - 1])); + _tr_tally_lit(s, s->window[s->strstart - 1], bflush); s->match_available = 0; } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->sym_next) + FLUSH_BLOCK(s, 0); + return block_done; } #endif /* FASTEST */ @@ -1688,8 +2089,7 @@ local block_state deflate_slow(deflate_state *s, int flush) * one. Do not maintain a hash table. (It will be regenerated if this run of * deflate switches away from Z_RLE.) */ -local block_state deflate_rle(deflate_state *s, int flush) -{ +local block_state deflate_rle(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ uInt prev; /* byte at distance one to match */ Bytef *scan, *strend; /* scan goes up to strend for length of run */ @@ -1697,11 +2097,11 @@ local block_state deflate_rle(deflate_state *s, int flush) for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes - * for the longest encodable run. + * for the longest run, plus one for the unrolled loop. */ - if (s->lookahead < MAX_MATCH) { + if (s->lookahead <= MAX_MATCH) { fill_window(s); - if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ @@ -1720,15 +2120,17 @@ local block_state deflate_rle(deflate_state *s, int flush) prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && scan < strend); - s->match_length = MAX_MATCH - (int)(strend - scan); + s->match_length = MAX_MATCH - (uInt)(strend - scan); if (s->match_length > s->lookahead) s->match_length = s->lookahead; } + Assert(scan <= s->window + (uInt)(s->window_size - 1), + "wild scan"); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->strstart - 1, s->match_length); + check_match(s, s->strstart, s->strstart - 1, (int)s->match_length); _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); @@ -1738,22 +2140,27 @@ local block_state deflate_rle(deflate_state *s, int flush) } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->sym_next) + FLUSH_BLOCK(s, 0); + return block_done; } /* =========================================================================== * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. * (It will be regenerated if this run of deflate switches away from Huffman.) */ -local block_state deflate_huff(deflate_state *s, int flush) -{ +local block_state deflate_huff(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ for (;;) { @@ -1770,15 +2177,20 @@ local block_state deflate_huff(deflate_state *s, int flush) /* Output a literal byte */ s->match_length = 0; Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); + _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->sym_next) + FLUSH_BLOCK(s, 0); + return block_done; } - ABC_NAMESPACE_IMPL_END diff --git a/src/misc/zlib/deflate.h b/src/misc/zlib/deflate.h index 8d17d971c3..af0d9fc233 100644 --- a/src/misc/zlib/deflate.h +++ b/src/misc/zlib/deflate.h @@ -1,5 +1,5 @@ /* deflate.h -- internal compression state - * Copyright (C) 1995-2010 Jean-loup Gailly + * Copyright (C) 1995-2026 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -17,6 +17,7 @@ ABC_NAMESPACE_HEADER_START + /* define NO_GZIP when compiling if you want to disable gzip header and trailer creation by deflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip encoding @@ -25,6 +26,10 @@ ABC_NAMESPACE_HEADER_START # define GZIP #endif +/* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at + the cost of a larger memory footprint */ +/* #define LIT_MEM */ + /* =========================================================================== * Internal compression state. */ @@ -50,13 +55,19 @@ ABC_NAMESPACE_HEADER_START #define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ -#define INIT_STATE 42 -#define EXTRA_STATE 69 -#define NAME_STATE 73 -#define COMMENT_STATE 91 -#define HCRC_STATE 103 -#define BUSY_STATE 113 -#define FINISH_STATE 666 +#define Buf_size 16 +/* size of bit buffer in bi_buf */ + +#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ +#ifdef GZIP +# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ +#endif +#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ +#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ +#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ +#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ +#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ +#define FINISH_STATE 666 /* stream complete */ /* Stream status */ @@ -82,7 +93,7 @@ typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ + const static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; @@ -99,11 +110,11 @@ typedef struct internal_state { Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ - uInt pending; /* nb of bytes in the pending buffer */ + ulg pending; /* nb of bytes in the pending buffer */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ - uInt gzindex; /* where in extra, name, or comment */ - Byte method; /* STORED (for zip only) or DEFLATED */ + ulg gzindex; /* where in extra, name, or comment */ + Byte method; /* can only be DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ @@ -190,7 +201,7 @@ typedef struct internal_state { int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ - /* Didn't use ct_data typedef below to supress compiler warning */ + /* Didn't use ct_data typedef below to suppress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ @@ -213,7 +224,14 @@ typedef struct internal_state { /* Depth of each subtree used as tie breaker for trees of equal frequency */ - uchf *l_buf; /* buffer for literals or lengths */ +#ifdef LIT_MEM +# define LIT_BUFS 5 + ushf *d_buf; /* buffer for distances */ + uchf *l_buf; /* buffer for literals/lengths */ +#else +# define LIT_BUFS 4 + uchf *sym_buf; /* buffer for distances and literals/lengths */ +#endif uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for @@ -235,20 +253,15 @@ typedef struct internal_state { * - I can't count above 4 */ - uInt last_lit; /* running index in l_buf */ - - ushf *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ + uInt sym_next; /* running index in symbol buffer */ + uInt sym_end; /* symbol table full when sym_next reaches this */ ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ uInt matches; /* number of string matches in current block */ - int last_eob_len; /* bit length of EOB code for last block */ + uInt insert; /* bytes at end of window left to insert */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ #endif @@ -261,6 +274,9 @@ typedef struct internal_state { /* Number of valid bits in bi_buf. All bits above the last valid bit * are always zero. */ + int bi_used; + /* Last number of used bits when going to a byte boundary. + */ ulg high_water; /* High water mark offset in window for initialized bytes -- bytes above @@ -269,12 +285,15 @@ typedef struct internal_state { * updated to the new high water mark. */ + int slid; + /* True if the hash table has been slid since it was cleared. */ + } FAR deflate_state; /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} +#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) @@ -292,13 +311,14 @@ typedef struct internal_state { memory checker errors from longest match routines */ /* in trees.c */ -void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); -int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); -void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_init(deflate_state *s); +int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc); +void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, + ulg stored_len, int last); +void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s); +void ZLIB_INTERNAL _tr_align(deflate_state *s); +void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, + ulg stored_len, int last); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) @@ -307,7 +327,7 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, * used. */ -#ifndef DEBUG +#ifndef ZLIB_DEBUG /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) @@ -318,29 +338,52 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, extern const uch ZLIB_INTERNAL _dist_code[]; #endif +#ifdef LIT_MEM +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->sym_next] = 0; \ + s->l_buf[s->sym_next++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->sym_next == s->sym_end); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (uch)(length); \ + ush dist = (ush)(distance); \ + s->d_buf[s->sym_next] = dist; \ + s->l_buf[s->sym_next++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->sym_next == s->sym_end); \ + } +#else # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ - s->d_buf[s->last_lit] = 0; \ - s->l_buf[s->last_lit++] = cc; \ + s->sym_buf[s->sym_next++] = 0; \ + s->sym_buf[s->sym_next++] = 0; \ + s->sym_buf[s->sym_next++] = cc; \ s->dyn_ltree[cc].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ + flush = (s->sym_next == s->sym_end); \ } # define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (length); \ - ush dist = (distance); \ - s->d_buf[s->last_lit] = dist; \ - s->l_buf[s->last_lit++] = len; \ + { uch len = (uch)(length); \ + ush dist = (ush)(distance); \ + s->sym_buf[s->sym_next++] = (uch)dist; \ + s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \ + s->sym_buf[s->sym_next++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ + flush = (s->sym_next == s->sym_end); \ } +#endif #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_dist(s, distance, length, flush) \ flush = _tr_tally(s, distance, length) #endif + ABC_NAMESPACE_HEADER_END #endif /* DEFLATE_H */ diff --git a/src/misc/zlib/gzclose.c b/src/misc/zlib/gzclose.c index 4e796f6c18..6f02cd2af9 100644 --- a/src/misc/zlib/gzclose.c +++ b/src/misc/zlib/gzclose.c @@ -12,11 +12,11 @@ ABC_NAMESPACE_IMPL_START + /* gzclose() is in a separate file so that it is linked in only if it is used. That way the other gzclose functions can be used instead to avoid linking in unneeded compression or decompression routines. */ -int ZEXPORT gzclose(gzFile file) -{ +int ZEXPORT gzclose(gzFile file) { #ifndef NO_GZCOMPRESS gz_statep state; @@ -31,3 +31,4 @@ int ZEXPORT gzclose(gzFile file) } ABC_NAMESPACE_IMPL_END + diff --git a/src/misc/zlib/gzguts.h b/src/misc/zlib/gzguts.h index 80961a54c5..258708ba52 100644 --- a/src/misc/zlib/gzguts.h +++ b/src/misc/zlib/gzguts.h @@ -1,5 +1,5 @@ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010 Mark Adler + * Copyright (C) 2004-2026 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -7,17 +7,28 @@ # ifndef _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE 1 # endif -# ifdef _FILE_OFFSET_BITS -# undef _FILE_OFFSET_BITS -# endif +# undef _FILE_OFFSET_BITS +# undef _TIME_BITS #endif -#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +#ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL #endif +#if defined(_WIN32) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +# endif +# ifndef _CRT_NONSTDC_NO_DEPRECATE +# define _CRT_NONSTDC_NO_DEPRECATE +# endif +#endif + #include #include "zlib.h" #ifdef STDC @@ -25,26 +36,93 @@ # include # include #endif + +#ifndef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200112L +#endif #include +#ifdef _WIN32 +# include +#else +# include /* for read, write, close, lseek */ +#endif + +#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) +# include +# include +#endif + +#if defined(_WIN32) && !defined(WIDECHAR) +# define WIDECHAR +#endif + #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif -#ifdef _MSC_VER -# include -# define vsnprintf _vsnprintf +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#ifndef HAVE_VSNPRINTF +# if !defined(NO_vsnprintf) && \ + (defined(MSDOS) || defined(__TURBOC__) || defined(__SASC) || \ + defined(VMS) || defined(__OS400) || defined(__MVS__)) +/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef WIN32 +/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# ifndef vsnprintf +# define vsnprintf _vsnprintf +# endif +# endif +# elif !defined(__STDC_VERSION__) || __STDC_VERSION__-0 < 199901L +/* Otherwise if C89/90, assume no C99 snprintf() or vsnprintf() */ +# ifndef NO_snprintf +# define NO_snprintf +# endif +# ifndef NO_vsnprintf +# define NO_vsnprintf +# endif +# endif +#endif + +/* unlike snprintf (which is required in C99), _snprintf does not guarantee + null termination of the result -- however this is only used in gzlib.c where + the result is assured to fit in the space provided */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +# define snprintf _snprintf #endif #ifndef local # define local static #endif -/* compile with -Dlocal if your debugger can't find static symbols */ +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ /* gz* functions always use library allocation functions */ #ifndef STDC - extern voidp malloc OF((uInt size)); - extern void free OF((voidpf ptr)); + extern voidp malloc(uInt size); + extern void free(voidpf ptr); #endif /* get errno and strerror definition */ @@ -52,7 +130,7 @@ # include # define zstrerror() gz_strwinerror((DWORD)GetLastError()) #else -# ifdef STDC +# ifndef NO_STRERROR # include # define zstrerror() strerror(errno) # else @@ -60,28 +138,27 @@ # endif #endif -#include #include "misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START -#ifdef _WIN32 -#define open _open -#define close _close -#define lseek _lseek -#define read _read -#define write _write -#endif - /* provide prototypes for these when building zlib without LFS */ #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); + ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); +#endif + +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif -/* default i/o buffer size -- double this for output when reading */ +/* default i/o buffer size -- double this for output when reading (this and + twice this must be able to fit in an unsigned type) */ #define GZBUFSIZE 8192 /* gzip modes, also provide a little integrity check on the passed structure */ @@ -97,29 +174,33 @@ ABC_NAMESPACE_HEADER_START /* internal gzip file state data structure */ typedef struct { + /* exposed contents for gzgetc() macro */ + struct gzFile_s x; /* "x" for exposed */ + /* x.have: number of bytes available at x.next */ + /* x.next: next output data to deliver or write */ + /* x.pos: current position in uncompressed data */ /* used for both reading and writing */ int mode; /* see gzip modes above */ int fd; /* file descriptor */ char *path; /* path or fd for error messages */ - z_off64_t pos; /* current position in uncompressed data */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ - unsigned char *in; /* input buffer */ + unsigned char *in; /* input buffer (double-sized when writing) */ unsigned char *out; /* output buffer (double-sized when reading) */ - unsigned char *next; /* next output data to deliver or write */ + int direct; /* 0 if processing gzip, 1 if transparent */ /* just for reading */ - unsigned have; /* amount of output data unused at next */ - int eof; /* true if end of input file reached */ - z_off64_t start; /* where the gzip data started, for rewinding */ - z_off64_t raw; /* where the raw data started, for seeking */ + int junk; /* -1 = start, 1 = junk candidate, 0 = in gzip */ int how; /* 0: get header, 1: copy, 2: decompress */ - int direct; /* true if last read direct, false if gzip */ + int again; /* true if EAGAIN or EWOULDBLOCK on last i/o */ + z_off64_t start; /* where the gzip data started, for rewinding */ + int eof; /* true if end of input file reached */ + int past; /* true if read requested past end */ /* just for writing */ int level; /* compression level */ int strategy; /* compression strategy */ + int reset; /* true if a reset is pending after a Z_FINISH */ /* seek request */ z_off64_t skip; /* amount to skip (already rewound if backwards) */ - int seek; /* true if seek request pending */ /* error information */ int err; /* error code */ char *msg; /* error message */ @@ -129,19 +210,15 @@ typedef struct { typedef gz_state FAR *gz_statep; /* shared functions */ -void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +void ZLIB_INTERNAL gz_error(gz_statep, int, const char *); #if defined UNDER_CE -char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +char ZLIB_INTERNAL *gz_strwinerror(DWORD error); #endif /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t value -- needed when comparing unsigned to z_off64_t, which is signed (possible z_off64_t types off_t, off64_t, and long are all signed) */ -#ifdef INT_MAX -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) -#else -unsigned ZLIB_INTERNAL gz_intmax OF((void)); -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) -#endif +unsigned ZLIB_INTERNAL gz_intmax(void); +#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) ABC_NAMESPACE_HEADER_END diff --git a/src/misc/zlib/gzlib.c b/src/misc/zlib/gzlib.c index 743dccb6b2..fa42788471 100644 --- a/src/misc/zlib/gzlib.c +++ b/src/misc/zlib/gzlib.c @@ -1,5 +1,5 @@ /* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004, 2010 Mark Adler + * Copyright (C) 2004-2026 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -12,16 +12,17 @@ ABC_NAMESPACE_IMPL_START -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + +#if defined(__DJGPP__) +# define LSEEK llseek +#elif defined(_WIN32) && !defined(__BORLANDC__) && !defined(UNDER_CE) +# define LSEEK _lseeki64 +#elif defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 # define LSEEK lseek64 #else # define LSEEK lseek #endif -/* Local functions */ -local void gz_reset OF((gz_statep)); -local gzFile gz_open OF((const char *, int, const char *)); - #if defined UNDER_CE /* Map the Windows error number in ERROR to a locale-dependent error message @@ -33,8 +34,7 @@ local gzFile gz_open OF((const char *, int, const char *)); The gz_strwinerror function does not change the current setting of GetLastError. */ -char ZLIB_INTERNAL *gz_strwinerror (DWORD error) -{ +char ZLIB_INTERNAL *gz_strwinerror(DWORD error) { static char buf[1024]; wchar_t *msgbuf; @@ -60,7 +60,7 @@ char ZLIB_INTERNAL *gz_strwinerror (DWORD error) msgbuf[chars] = 0; } - wcstombs(buf, msgbuf, chars + 1); + wcstombs(buf, msgbuf, chars + 1); /* assumes buf is big enough */ LocalFree(msgbuf); } else { @@ -74,24 +74,35 @@ char ZLIB_INTERNAL *gz_strwinerror (DWORD error) #endif /* UNDER_CE */ /* Reset gzip file state */ -local void gz_reset(gz_statep state) -{ +local void gz_reset(gz_statep state) { + state->x.have = 0; /* no output data available */ if (state->mode == GZ_READ) { /* for reading ... */ - state->have = 0; /* no output data available */ state->eof = 0; /* not at end of file */ + state->past = 0; /* have not read past end yet */ state->how = LOOK; /* look for gzip header */ - state->direct = 1; /* default for empty file */ + state->junk = -1; /* mark first member */ } - state->seek = 0; /* no seek request pending */ + else /* for writing ... */ + state->reset = 0; /* no deflateReset pending */ + state->again = 0; /* no stalled i/o yet */ + state->skip = 0; /* no seek request pending */ gz_error(state, Z_OK, NULL); /* clear error */ - state->pos = 0; /* no uncompressed data yet */ + state->x.pos = 0; /* no uncompressed data yet */ state->strm.avail_in = 0; /* no input data yet */ } /* Open a gzip file either by name or file descriptor. */ -local gzFile gz_open(const char *path, int fd, const char *mode) -{ +local gzFile gz_open(const void *path, int fd, const char *mode) { gz_statep state; + z_size_t len; + int oflag = 0; +#ifdef O_EXCL + int exclusive = 0; +#endif + + /* check input */ + if (path == NULL || mode == NULL) + return NULL; /* allocate gzFile structure to return */ state = (gz_statep)malloc(sizeof(gz_state)); @@ -99,12 +110,14 @@ local gzFile gz_open(const char *path, int fd, const char *mode) return NULL; state->size = 0; /* no buffers allocated yet */ state->want = GZBUFSIZE; /* requested buffer size */ + state->err = Z_OK; /* no error yet */ state->msg = NULL; /* no error message yet */ /* interpret mode */ state->mode = GZ_NONE; state->level = Z_DEFAULT_COMPRESSION; state->strategy = Z_DEFAULT_STRATEGY; + state->direct = 0; while (*mode) { if (*mode >= '0' && *mode <= '9') state->level = *mode - '0'; @@ -126,6 +139,16 @@ local gzFile gz_open(const char *path, int fd, const char *mode) return NULL; case 'b': /* ignore -- will request binary anyway */ break; +#ifdef O_CLOEXEC + case 'e': + oflag |= O_CLOEXEC; + break; +#endif +#ifdef O_EXCL + case 'x': + exclusive = 1; + break; +#endif case 'f': state->strategy = Z_FILTERED; break; @@ -137,6 +160,18 @@ local gzFile gz_open(const char *path, int fd, const char *mode) break; case 'F': state->strategy = Z_FIXED; + break; + case 'G': + state->direct = -1; + break; +#ifdef O_NONBLOCK + case 'N': + oflag |= O_NONBLOCK; + break; +#endif + case 'T': + state->direct = 1; + break; default: /* could consider as an error, but just ignore */ ; } @@ -149,37 +184,100 @@ local gzFile gz_open(const char *path, int fd, const char *mode) return NULL; } + /* direct is 0, 1 if "T", or -1 if "G" (last "G" or "T" wins) */ + if (state->mode == GZ_READ) { + if (state->direct == 1) { + /* can't force a transparent read */ + free(state); + return NULL; + } + if (state->direct == 0) + /* default when reading is auto-detect of gzip vs. transparent -- + start with a transparent assumption in case of an empty file */ + state->direct = 1; + } + else if (state->direct == -1) { + /* "G" has no meaning when writing -- disallow it */ + free(state); + return NULL; + } + /* if reading, direct == 1 for auto-detect, -1 for gzip only; if writing or + appending, direct == 0 for gzip, 1 for transparent (copy in to out) */ + /* save the path name for error messages */ - state->path = (char *)malloc(strlen(path) + 1); +#ifdef WIDECHAR + if (fd == -2) + len = wcstombs(NULL, path, 0); + else +#endif + len = strlen((const char *)path); + state->path = (char *)malloc(len + 1); if (state->path == NULL) { free(state); return NULL; } - strcpy(state->path, path); +#ifdef WIDECHAR + if (fd == -2) { + if (len) + wcstombs(state->path, path, len + 1); + else + *(state->path) = 0; + } + else +#endif + { +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(state->path, len + 1, "%s", (const char *)path); +#else + strcpy(state->path, (const char *)path); +#endif + } - /* open the file with the appropriate mode (or just use fd) */ - state->fd = fd != -1 ? fd : - open(path, + /* compute the flags for open() */ + oflag |= #ifdef O_LARGEFILE - O_LARGEFILE | + O_LARGEFILE | #endif #ifdef O_BINARY - O_BINARY | + O_BINARY | #endif - (state->mode == GZ_READ ? - O_RDONLY : - (O_WRONLY | O_CREAT | ( - state->mode == GZ_WRITE ? - O_TRUNC : - O_APPEND))), - 0666); + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | +#ifdef O_EXCL + (exclusive ? O_EXCL : 0) | +#endif + (state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))); + + /* open the file with the appropriate flags (or just use fd) */ + if (fd == -1) + state->fd = open((const char *)path, oflag, 0666); +#ifdef WIDECHAR + else if (fd == -2) + state->fd = _wopen(path, oflag, _S_IREAD | _S_IWRITE); +#endif + else { +#ifdef O_NONBLOCK + if (oflag & O_NONBLOCK) + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); +#endif +#ifdef O_CLOEXEC + if (oflag & O_CLOEXEC) + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | O_CLOEXEC); +#endif + state->fd = fd; + } if (state->fd == -1) { free(state->path); free(state); return NULL; } - if (state->mode == GZ_APPEND) + if (state->mode == GZ_APPEND) { + LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ state->mode = GZ_WRITE; /* simplify later checks */ + } /* save the current position for rewinding (only if reading) */ if (state->mode == GZ_READ) { @@ -195,34 +293,41 @@ local gzFile gz_open(const char *path, int fd, const char *mode) } /* -- see zlib.h -- */ -gzFile ZEXPORT gzopen(const char *path, const char *mode) -{ +gzFile ZEXPORT gzopen(const char *path, const char *mode) { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ -gzFile ZEXPORT gzopen64(const char *path, const char *mode) -{ +gzFile ZEXPORT gzopen64(const char *path, const char *mode) { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ -gzFile ZEXPORT gzdopen(int fd, const char *mode) -{ +gzFile ZEXPORT gzdopen(int fd, const char *mode) { char *path; /* identifier for error messages */ gzFile gz; if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) return NULL; +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(path, 7 + 3 * sizeof(int), "", fd); +#else sprintf(path, "", fd); /* for debugging */ +#endif gz = gz_open(path, fd, mode); free(path); return gz; } /* -- see zlib.h -- */ -int ZEXPORT gzbuffer(gzFile file, unsigned size) -{ +#ifdef WIDECHAR +gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) { + return gz_open(path, -2, mode); +} +#endif + +/* -- see zlib.h -- */ +int ZEXPORT gzbuffer(gzFile file, unsigned size) { gz_statep state; /* get internal structure and check integrity */ @@ -237,15 +342,16 @@ int ZEXPORT gzbuffer(gzFile file, unsigned size) return -1; /* check and set requested size */ - if (size == 0) - return -1; + if ((size << 1) < size) + return -1; /* need to be able to double it */ + if (size < 8) + size = 8; /* needed to behave well with flushing */ state->want = size; return 0; } /* -- see zlib.h -- */ -int ZEXPORT gzrewind(gzFile file) -{ +int ZEXPORT gzrewind(gzFile file) { gz_statep state; /* get internal structure */ @@ -254,7 +360,8 @@ int ZEXPORT gzrewind(gzFile file) state = (gz_statep)file; /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* back up and start over */ @@ -265,8 +372,7 @@ int ZEXPORT gzrewind(gzFile file) } /* -- see zlib.h -- */ -z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) -{ +z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { unsigned n; z_off64_t ret; gz_statep state; @@ -279,7 +385,7 @@ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) return -1; /* check that there's no error */ - if (state->err != Z_OK) + if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; /* can only seek from start or relative to current position */ @@ -288,31 +394,33 @@ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) /* normalize offset to a SEEK_CUR specification */ if (whence == SEEK_SET) - offset -= state->pos; - else if (state->seek) - offset += state->skip; - state->seek = 0; + offset -= state->x.pos; + else { + offset += state->past ? 0 : state->skip; + state->skip = 0; + } /* if within raw area while reading, just go there */ if (state->mode == GZ_READ && state->how == COPY && - state->pos + offset >= state->raw) { - ret = LSEEK(state->fd, offset - state->have, SEEK_CUR); + state->x.pos + offset >= 0) { + ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR); if (ret == -1) return -1; - state->have = 0; + state->x.have = 0; state->eof = 0; - state->seek = 0; + state->past = 0; + state->skip = 0; gz_error(state, Z_OK, NULL); state->strm.avail_in = 0; - state->pos += offset; - return state->pos; + state->x.pos += offset; + return state->x.pos; } /* calculate skip amount, rewinding if needed for back seek when reading */ if (offset < 0) { if (state->mode != GZ_READ) /* writing -- can't go backwards */ return -1; - offset += state->pos; + offset += state->x.pos; if (offset < 0) /* before start of file! */ return -1; if (gzrewind(file) == -1) /* rewind, then skip to offset */ @@ -321,25 +429,21 @@ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) /* if reading, skip what's in output buffer (one less gzgetc() check) */ if (state->mode == GZ_READ) { - n = GT_OFF(state->have) || (z_off64_t)state->have > offset ? - (unsigned)offset : state->have; - state->have -= n; - state->next += n; - state->pos += n; + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? + (unsigned)offset : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; offset -= n; } /* request skip (if not zero) */ - if (offset) { - state->seek = 1; - state->skip = offset; - } - return state->pos + offset; + state->skip = offset; + return state->x.pos + offset; } /* -- see zlib.h -- */ -z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) -{ +z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) { z_off64_t ret; ret = gzseek64(file, (z_off64_t)offset, whence); @@ -347,8 +451,7 @@ z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) } /* -- see zlib.h -- */ -z_off64_t ZEXPORT gztell64(gzFile file) -{ +z_off64_t ZEXPORT gztell64(gzFile file) { gz_statep state; /* get internal structure and check integrity */ @@ -359,12 +462,11 @@ z_off64_t ZEXPORT gztell64(gzFile file) return -1; /* return position */ - return state->pos + (state->seek ? state->skip : 0); + return state->x.pos + (state->past ? 0 : state->skip); } /* -- see zlib.h -- */ -z_off_t ZEXPORT gztell(gzFile file) -{ +z_off_t ZEXPORT gztell(gzFile file) { z_off64_t ret; ret = gztell64(file); @@ -372,8 +474,7 @@ z_off_t ZEXPORT gztell(gzFile file) } /* -- see zlib.h -- */ -z_off64_t ZEXPORT gzoffset64(gzFile file) -{ +z_off64_t ZEXPORT gzoffset64(gzFile file) { z_off64_t offset; gz_statep state; @@ -394,8 +495,7 @@ z_off64_t ZEXPORT gzoffset64(gzFile file) } /* -- see zlib.h -- */ -z_off_t ZEXPORT gzoffset(gzFile file) -{ +z_off_t ZEXPORT gzoffset(gzFile file) { z_off64_t ret; ret = gzoffset64(file); @@ -403,8 +503,7 @@ z_off_t ZEXPORT gzoffset(gzFile file) } /* -- see zlib.h -- */ -int ZEXPORT gzeof(gzFile file) -{ +int ZEXPORT gzeof(gzFile file) { gz_statep state; /* get internal structure and check integrity */ @@ -415,13 +514,11 @@ int ZEXPORT gzeof(gzFile file) return 0; /* return end-of-file state */ - return state->mode == GZ_READ ? - (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0; + return state->mode == GZ_READ ? state->past : 0; } /* -- see zlib.h -- */ -const char * ZEXPORT gzerror(gzFile file, int *errnum) -{ +const char * ZEXPORT gzerror(gzFile file, int *errnum) { gz_statep state; /* get internal structure and check integrity */ @@ -434,12 +531,12 @@ const char * ZEXPORT gzerror(gzFile file, int *errnum) /* return error information */ if (errnum != NULL) *errnum = state->err; - return state->msg == NULL ? "" : state->msg; + return state->err == Z_MEM_ERROR ? "out of memory" : + (state->msg == NULL ? "" : state->msg); } /* -- see zlib.h -- */ -void ZEXPORT gzclearerr(gzFile file) -{ +void ZEXPORT gzclearerr(gzFile file) { gz_statep state; /* get internal structure and check integrity */ @@ -450,8 +547,10 @@ void ZEXPORT gzclearerr(gzFile file) return; /* clear error and end-of-file */ - if (state->mode == GZ_READ) + if (state->mode == GZ_READ) { state->eof = 0; + state->past = 0; + } gz_error(state, Z_OK, NULL); } @@ -461,8 +560,7 @@ void ZEXPORT gzclearerr(gzFile file) memory). Simply save the error message as a static string. If there is an allocation failure constructing the error message, then convert the error to out of memory. */ -void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) -{ +void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) { /* free previously allocated message and clear */ if (state->msg != NULL) { if (state->err != Z_MEM_ERROR) @@ -470,48 +568,53 @@ void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) state->msg = NULL; } + /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ + if (err != Z_OK && err != Z_BUF_ERROR && !state->again) + state->x.have = 0; + /* set error code, and if no message, then done */ state->err = err; if (msg == NULL) return; - /* for an out of memory error, save as static string */ - if (err == Z_MEM_ERROR) { - state->msg = (char *)msg; + /* for an out of memory error, return literal string when requested */ + if (err == Z_MEM_ERROR) return; - } /* construct error message with path */ - if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { + if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == + NULL) { state->err = Z_MEM_ERROR; - state->msg = (char *)"out of memory"; return; } +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, + "%s%s%s", state->path, ": ", msg); +#else strcpy(state->msg, state->path); strcat(state->msg, ": "); strcat(state->msg, msg); - return; +#endif } -#ifndef INT_MAX /* portably return maximum value for an int (when limits.h presumed not available) -- we need to do this to cover cases where 2's complement not used, since C standard permits 1's complement and sign-bit representations, otherwise we could just use ((unsigned)-1) >> 1 */ -unsigned ZLIB_INTERNAL gz_intmax() -{ - unsigned p, q; +unsigned ZLIB_INTERNAL gz_intmax(void) { +#ifdef INT_MAX + return INT_MAX; +#else + unsigned p = 1, q; - p = 1; do { q = p; p <<= 1; p++; } while (p > q); return q >> 1; -} #endif - +} ABC_NAMESPACE_IMPL_END diff --git a/src/misc/zlib/gzread.c b/src/misc/zlib/gzread.c index 71a6f4624e..e35eb04acf 100644 --- a/src/misc/zlib/gzread.c +++ b/src/misc/zlib/gzread.c @@ -1,5 +1,5 @@ /* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010 Mark Adler + * Copyright (C) 2004-2026 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -12,31 +12,40 @@ ABC_NAMESPACE_IMPL_START -/* Local functions */ -local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); -local int gz_avail OF((gz_statep)); -local int gz_next4 OF((gz_statep, unsigned long *)); -local int gz_head OF((gz_statep)); -local int gz_decomp OF((gz_statep)); -local int gz_make OF((gz_statep)); -local int gz_skip OF((gz_statep, z_off64_t)); /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from state->fd, and update state->eof, state->err, and state->msg as appropriate. This function needs to loop on read(), since read() is not guaranteed to - read the number of bytes requested, depending on the type of descriptor. */ -local int gz_load(gz_statep state, unsigned char *buf, unsigned len, unsigned *have) -{ + read the number of bytes requested, depending on the type of descriptor. It + also needs to loop to manage the fact that read() returns an int. If the + descriptor is non-blocking and read() returns with no data in order to avoid + blocking, then gz_load() will return 0 if some data has been read, or -1 if + no data has been read. Either way, state->again is set true to indicate a + non-blocking event. If errno is non-zero on return, then there was an error + signaled from read(). *have is set to the number of bytes read. */ +local int gz_load(gz_statep state, unsigned char *buf, unsigned len, + unsigned *have) { int ret; + unsigned get, max = ((unsigned)-1 >> 2) + 1; + state->again = 0; + errno = 0; *have = 0; do { - ret = read(state->fd, buf + *have, len - *have); + get = len - *have; + if (get > max) + get = max; + ret = (int)read(state->fd, buf + *have, get); if (ret <= 0) break; - *have += ret; + *have += (unsigned)ret; } while (*have < len); if (ret < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + state->again = 1; + if (*have != 0) + return 0; + } gz_error(state, Z_ERRNO, zstrerror()); return -1; } @@ -49,63 +58,48 @@ local int gz_load(gz_statep state, unsigned char *buf, unsigned len, unsigned *h error, 0 otherwise. Note that the eof flag is set when the end of the input file is reached, even though there may be unused data in the buffer. Once that data has been used, no more attempts will be made to read the file. - gz_avail() assumes that strm->avail_in == 0. */ -local int gz_avail(gz_statep state) -{ + If strm->avail_in != 0, then the current data is moved to the beginning of + the input buffer, and then the remainder of the buffer is loaded with the + available data from the input file. */ +local int gz_avail(gz_statep state) { + unsigned got; z_streamp strm = &(state->strm); - if (state->err != Z_OK) + if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; if (state->eof == 0) { - if (gz_load(state, state->in, state->size, - (unsigned *)&(strm->avail_in)) == -1) + if (strm->avail_in) { /* copy what's there to the start */ + unsigned char *p = state->in; + unsigned const char *q = strm->next_in; + + if (q != p) { + unsigned n = strm->avail_in; + + do { + *p++ = *q++; + } while (--n); + } + } + if (gz_load(state, state->in + strm->avail_in, + state->size - strm->avail_in, &got) == -1) return -1; + strm->avail_in += got; strm->next_in = state->in; } return 0; } -/* Get next byte from input, or -1 if end or error. */ -#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \ - (strm->avail_in == 0 ? -1 : \ - (strm->avail_in--, *(strm->next_in)++))) - -/* Get a four-byte little-endian integer and return 0 on success and the value - in *ret. Otherwise -1 is returned and *ret is not modified. */ -local int gz_next4(gz_statep state, unsigned long *ret) -{ - int ch; - unsigned long val; - z_streamp strm = &(state->strm); - - val = NEXT(); - val += (unsigned)NEXT() << 8; - val += (unsigned long)NEXT() << 16; - ch = NEXT(); - if (ch == -1) - return -1; - val += (unsigned long)ch << 24; - *ret = val; - return 0; -} - -/* Look for gzip header, set up for inflate or copy. state->have must be zero. +/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. If this is the first time in, allocate required memory. state->how will be left unchanged if there is no more input data available, will be set to COPY if there is no gzip header and direct copying will be performed, or it will - be set to GZIP for decompression, and the gzip header will be skipped so - that the next available input data is the raw deflate stream. If direct - copying, then leftover input data from the input buffer will be copied to - the output buffer. In that case, all further file reads will be directly to - either the output buffer or a user buffer. If decompressing, the inflate - state and the check value will be initialized. gz_head() will return 0 on - success or -1 on failure. Failures may include read errors or gzip header - errors. */ -local int gz_head(gz_statep state) -{ + be set to GZIP for decompression. If direct copying, then leftover input + data from the input buffer will be copied to the output buffer. In that + case, all further file reads will be directly to either the output buffer or + a user buffer. If decompressing, the inflate state will be initialized. + gz_look() will return 0 on success or -1 on failure. */ +local int gz_look(gz_statep state) { z_streamp strm = &(state->strm); - int flags; - unsigned len; /* allocate read buffers and inflate memory */ if (state->size == 0) { @@ -113,10 +107,8 @@ local int gz_head(gz_statep state) state->in = (unsigned char *)malloc(state->want); state->out = (unsigned char *)malloc(state->want << 1); if (state->in == NULL || state->out == NULL) { - if (state->out != NULL) - free(state->out); - if (state->in != NULL) - free(state->in); + free(state->out); + free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } @@ -128,7 +120,7 @@ local int gz_head(gz_statep state) state->strm.opaque = Z_NULL; state->strm.avail_in = 0; state->strm.next_in = Z_NULL; - if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */ + if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ free(state->out); free(state->in); state->size = 0; @@ -137,207 +129,177 @@ local int gz_head(gz_statep state) } } - /* get some data in the input buffer */ - if (strm->avail_in == 0) { - if (gz_avail(state) == -1) - return -1; - if (strm->avail_in == 0) - return 0; + /* if transparent reading is disabled, which would only be at the start, or + if we're looking for a gzip member after the first one, which is not at + the start, then proceed directly to look for a gzip member next */ + if (state->direct == -1 || state->junk == 0) { + inflateReset(strm); + state->how = GZIP; + state->junk = state->junk != -1; + state->direct = 0; + return 0; } - /* look for the gzip magic header bytes 31 and 139 */ - if (strm->next_in[0] == 31) { - strm->avail_in--; - strm->next_in++; - if (strm->avail_in == 0 && gz_avail(state) == -1) - return -1; - if (strm->avail_in && strm->next_in[0] == 139) { - /* we have a gzip header, woo hoo! */ - strm->avail_in--; - strm->next_in++; - - /* skip rest of header */ - if (NEXT() != 8) { /* compression method */ - gz_error(state, Z_DATA_ERROR, "unknown compression method"); - return -1; - } - flags = NEXT(); - if (flags & 0xe0) { /* reserved flag bits */ - gz_error(state, Z_DATA_ERROR, "unknown header flags set"); - return -1; - } - NEXT(); /* modification time */ - NEXT(); - NEXT(); - NEXT(); - NEXT(); /* extra flags */ - NEXT(); /* operating system */ - if (flags & 4) { /* extra field */ - len = (unsigned)NEXT(); - len += (unsigned)NEXT() << 8; - while (len--) - if (NEXT() < 0) - break; - } - if (flags & 8) /* file name */ - while (NEXT() > 0) - ; - if (flags & 16) /* comment */ - while (NEXT() > 0) - ; - if (flags & 2) { /* header crc */ - NEXT(); - NEXT(); - } - /* an unexpected end of file is not checked for here -- it will be - noticed on the first request for uncompressed data */ - - /* set up for decompression */ - inflateReset(strm); - strm->adler = crc32(0L, Z_NULL, 0); - state->how = GZIP; - state->direct = 0; - return 0; - } - else { - /* not a gzip file -- save first byte (31) and fall to raw i/o */ - state->out[0] = 31; - state->have = 1; - } - } + /* otherwise we're at the start with auto-detect -- we check to see if the + first four bytes could be gzip header in order to decide whether or not + this will be a transparent read */ - /* doing raw i/o, save start of raw data for seeking, copy any leftover - input to output -- this assumes that the output buffer is larger than - the input buffer, which also assures space for gzungetc() */ - state->raw = state->pos; - state->next = state->out; - if (strm->avail_in) { - memcpy(state->next + state->have, strm->next_in, strm->avail_in); - state->have += strm->avail_in; - strm->avail_in = 0; + /* load any header bytes into the input buffer -- if the input is empty, + then it's not an error as this is a transparent read of zero bytes */ + if (gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0 || (state->again && strm->avail_in < 4)) + /* if non-blocking input stalled before getting four bytes, then + return and wait until a later call has accumulated enough */ + return 0; + + /* see if this is (likely) gzip input -- if the first four bytes are + consistent with a gzip header, then go look for the first gzip member, + otherwise proceed to copy the input transparently */ + if (strm->avail_in > 3 && + strm->next_in[0] == 31 && strm->next_in[1] == 139 && + strm->next_in[2] == 8 && strm->next_in[3] < 32) { + inflateReset(strm); + state->how = GZIP; + state->junk = 1; + state->direct = 0; + return 0; } + + /* doing raw i/o: copy any leftover input to output -- this assumes that + the output buffer is larger than the input buffer, which also assures + space for gzungetc() */ + state->x.next = state->out; + memcpy(state->x.next, strm->next_in, strm->avail_in); + state->x.have = strm->avail_in; + strm->avail_in = 0; state->how = COPY; - state->direct = 1; return 0; } /* Decompress from input to the provided next_out and avail_out in the state. - If the end of the compressed data is reached, then verify the gzip trailer - check value and length (modulo 2^32). state->have and state->next are set - to point to the just decompressed data, and the crc is updated. If the - trailer is verified, state->how is reset to LOOK to look for the next gzip - stream or raw data, once state->have is depleted. Returns 0 on success, -1 - on failure. Failures may include invalid compressed data or a failed gzip - trailer verification. */ -local int gz_decomp(gz_statep state) -{ - int ret; + On return, state->x.have and state->x.next point to the just decompressed + data. If the gzip stream completes, state->how is reset to LOOK to look for + the next gzip stream or raw data, once state->x.have is depleted. Returns 0 + on success, -1 on failure. If EOF is reached when looking for more input to + complete the gzip member, then an unexpected end of file error is raised. + If there is no more input, but state->again is true, then EOF has not been + reached, and no error is raised. */ +local int gz_decomp(gz_statep state) { + int ret = Z_OK; unsigned had; - unsigned long crc, len; z_streamp strm = &(state->strm); /* fill output buffer up to end of deflate stream */ had = strm->avail_out; do { /* get more input for inflate() */ - if (strm->avail_in == 0 && gz_avail(state) == -1) - return -1; + if (strm->avail_in == 0 && gz_avail(state) == -1) { + ret = state->err; + break; + } if (strm->avail_in == 0) { - gz_error(state, Z_DATA_ERROR, "unexpected end of file"); - return -1; + if (!state->again) + gz_error(state, Z_BUF_ERROR, "unexpected end of file"); + break; } /* decompress and handle errors */ ret = inflate(strm, Z_NO_FLUSH); + if (strm->avail_out < had) + /* any decompressed data marks this as a real gzip stream */ + state->junk = 0; if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { gz_error(state, Z_STREAM_ERROR, - "internal error: inflate stream corrupt"); - return -1; + "internal error: inflate stream corrupt"); + break; } if (ret == Z_MEM_ERROR) { gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; + break; } if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ + if (state->junk == 1) { /* trailing garbage is ok */ + strm->avail_in = 0; + state->eof = 1; + state->how = LOOK; + ret = Z_OK; + break; + } gz_error(state, Z_DATA_ERROR, - strm->msg == NULL ? "compressed data error" : strm->msg); - return -1; + strm->msg == NULL ? "compressed data error" : strm->msg); + break; } } while (strm->avail_out && ret != Z_STREAM_END); - /* update available output and crc check value */ - state->have = had - strm->avail_out; - state->next = strm->next_out - state->have; - strm->adler = crc32(strm->adler, state->next, state->have); + /* update available output */ + state->x.have = had - strm->avail_out; + state->x.next = strm->next_out - state->x.have; - /* check gzip trailer if at end of deflate stream */ + /* if the gzip stream completed successfully, look for another */ if (ret == Z_STREAM_END) { - if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { - gz_error(state, Z_DATA_ERROR, "unexpected end of file"); - return -1; - } - if (crc != strm->adler) { - gz_error(state, Z_DATA_ERROR, "incorrect data check"); - return -1; - } - if (len != (strm->total_out & 0xffffffffL)) { - gz_error(state, Z_DATA_ERROR, "incorrect length check"); - return -1; - } - state->how = LOOK; /* ready for next stream, once have is 0 (leave - state->direct unchanged to remember how) */ + state->junk = 0; + state->how = LOOK; + return 0; } - /* good decompression */ - return 0; + /* return decompression status */ + return ret != Z_OK ? -1 : 0; } -/* Make data and put in the output buffer. Assumes that state->have == 0. +/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. Data is either copied from the input file or decompressed from the input file depending on state->how. If state->how is LOOK, then a gzip header is - looked for (and skipped if found) to determine wither to copy or decompress. - Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY - or GZIP unless the end of the input file has been reached and all data has - been processed. */ -local int gz_make(gz_statep state) -{ + looked for to determine whether to copy or decompress. Returns -1 on error, + otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the + end of the input file has been reached and all data has been processed. */ +local int gz_fetch(gz_statep state) { z_streamp strm = &(state->strm); - if (state->how == LOOK) { /* look for gzip header */ - if (gz_head(state) == -1) - return -1; - if (state->have) /* got some data from gz_head() */ + do { + switch(state->how) { + case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ + if (gz_look(state) == -1) + return -1; + if (state->how == LOOK) + return 0; + break; + case COPY: /* -> COPY */ + if (gz_load(state, state->out, state->size << 1, &(state->x.have)) + == -1) + return -1; + state->x.next = state->out; return 0; - } - if (state->how == COPY) { /* straight copy */ - if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1) - return -1; - state->next = state->out; - } - else if (state->how == GZIP) { /* decompress */ - strm->avail_out = state->size << 1; - strm->next_out = state->out; - if (gz_decomp(state) == -1) + case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ + strm->avail_out = state->size << 1; + strm->next_out = state->out; + if (gz_decomp(state) == -1) + return -1; + break; + default: + gz_error(state, Z_STREAM_ERROR, "state corrupt"); return -1; - } + } + } while (state->x.have == 0 && (!state->eof || strm->avail_in)); return 0; } -/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ -local int gz_skip(gz_statep state, z_off64_t len) -{ +/* Skip state->skip (> 0) uncompressed bytes of output. Return -1 on error, 0 + on success. */ +local int gz_skip(gz_statep state) { unsigned n; /* skip over len bytes or reach end-of-file, whichever comes first */ - while (len) + do { /* skip over whatever is in output buffer */ - if (state->have) { - n = GT_OFF(state->have) || (z_off64_t)state->have > len ? - (unsigned)len : state->have; - state->have -= n; - state->next += n; - state->pos += n; - len -= n; + if (state->x.have) { + n = GT_OFF(state->x.have) || + (z_off64_t)state->x.have > state->skip ? + (unsigned)state->skip : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + state->skip -= n; } /* output buffer empty -- return if we're at the end of the input */ @@ -347,247 +309,330 @@ local int gz_skip(gz_statep state, z_off64_t len) /* need more data to skip -- load up output buffer */ else { /* get more output, looking for header if required */ - if (gz_make(state) == -1) + if (gz_fetch(state) == -1) return -1; } + } while (state->skip); return 0; } -/* -- see zlib.h -- */ -int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) -{ - unsigned got, n; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) - return -1; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids the flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); - return -1; - } +/* Read len bytes into buf from file, or less than len up to the end of the + input. Return the number of bytes read. If zero is returned, either the end + of file was reached, or there was an error. state->err must be consulted in + that case to determine which. If there was an error, but some uncompressed + bytes were read before the error, then that count is returned. The error is + still recorded, and so is deferred until the next call. */ +local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) { + z_size_t got; + unsigned n; + int err; /* if len is zero, avoid unnecessary operations */ if (len == 0) return 0; /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return -1; - } + if (state->skip && gz_skip(state) == -1) + return 0; /* get len bytes to buf, or less than len if at the end */ got = 0; + err = 0; do { + /* set n to the maximum amount of len that fits in an unsigned int */ + n = (unsigned)-1; + if (n > len) + n = (unsigned)len; + /* first just try copying data from the output buffer */ - if (state->have) { - n = state->have > len ? len : state->have; - memcpy(buf, state->next, n); - state->next += n; - state->have -= n; + if (state->x.have) { + if (state->x.have < n) + n = state->x.have; + memcpy(buf, state->x.next, n); + state->x.next += n; + state->x.have -= n; + if (state->err != Z_OK) + /* caught deferred error from gz_fetch() */ + err = -1; } /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && strm->avail_in == 0) + else if (state->eof && state->strm.avail_in == 0) break; /* need output data -- for small len or new stream load up our output - buffer */ - else if (state->how == LOOK || len < (state->size << 1)) { + buffer, so that gzgetc() can be fast */ + else if (state->how == LOOK || n < (state->size << 1)) { /* get more output, looking for header if required */ - if (gz_make(state) == -1) - return -1; - continue; /* no progress yet -- go back to memcpy() above */ + if (gz_fetch(state) == -1 && state->x.have == 0) + /* if state->x.have != 0, error will be caught after copy */ + err = -1; + continue; /* no progress yet -- go back to copy above */ /* the copy above assures that we will leave with space in the output buffer, allowing at least one gzungetc() to succeed */ } /* large len -- read directly into user buffer */ - else if (state->how == COPY) { /* read directly */ - if (gz_load(state, (unsigned char *)buf, len, &n) == -1) - return -1; - } + else if (state->how == COPY) /* read directly */ + err = gz_load(state, (unsigned char *)buf, n, &n); /* large len -- decompress directly into user buffer */ else { /* state->how == GZIP */ - strm->avail_out = len; - strm->next_out = (unsigned char *)buf; - if (gz_decomp(state) == -1) - return -1; - n = state->have; - state->have = 0; + state->strm.avail_out = n; + state->strm.next_out = (unsigned char *)buf; + err = gz_decomp(state); + n = state->x.have; + state->x.have = 0; } /* update progress */ len -= n; buf = (char *)buf + n; got += n; - state->pos += n; - } while (len); + state->x.pos += n; + } while (len && !err); + + /* note read past eof */ + if (len && state->eof) + state->past = 1; - /* return number of bytes read into user buffer (will fit in int) */ - return (int)got; + /* return number of bytes read into user buffer */ + return got; } /* -- see zlib.h -- */ -int ZEXPORT gzgetc(gzFile file) -{ - int ret; +int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) { + gz_statep state; + + /* get internal structure and check that it's for reading */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ) + return -1; + + /* check that there was no (serious) error */ + if (state->err != Z_OK && state->err != Z_BUF_ERROR && !state->again) + return -1; + gz_error(state, Z_OK, NULL); + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); + return -1; + } + + /* read len or fewer bytes to buf */ + len = (unsigned)gz_read(state, buf, len); + + /* check for an error */ + if (len == 0) { + if (state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + if (state->again) { + /* non-blocking input stalled after some input was read, but no + uncompressed bytes were produced -- let the application know + this isn't EOF */ + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + } + + /* return the number of bytes read */ + return (int)len; +} + +/* -- see zlib.h -- */ +z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, + gzFile file) { + z_size_t len; + gz_statep state; + + /* get internal structure and check that it's for reading */ + if (file == NULL) + return 0; + state = (gz_statep)file; + if (state->mode != GZ_READ) + return 0; + + /* check that there was no (serious) error */ + if (state->err != Z_OK && state->err != Z_BUF_ERROR && !state->again) + return 0; + gz_error(state, Z_OK, NULL); + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (size && len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* read len or fewer bytes to buf, return the number of full items read */ + return len ? gz_read(state, buf, len) / size : 0; +} + +/* -- see zlib.h -- */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +#else +# undef gzgetc +#endif +int ZEXPORT gzgetc(gzFile file) { unsigned char buf[1]; gz_statep state; - /* get internal structure */ + /* get internal structure and check that it's for reading */ if (file == NULL) return -1; state = (gz_statep)file; + if (state->mode != GZ_READ) + return -1; - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + /* check that there was no (serious) error */ + if (state->err != Z_OK && state->err != Z_BUF_ERROR && !state->again) return -1; + gz_error(state, Z_OK, NULL); /* try output buffer (no need to check for skip request) */ - if (state->have) { - state->have--; - state->pos++; - return *(state->next)++; + if (state->x.have) { + state->x.have--; + state->x.pos++; + return *(state->x.next)++; } - /* nothing there -- try gzread() */ - ret = gzread(file, buf, 1); - return ret < 1 ? -1 : buf[0]; + /* nothing there -- try gz_read() */ + return gz_read(state, buf, 1) < 1 ? -1 : buf[0]; +} + +int ZEXPORT gzgetc_(gzFile file) { + return gzgetc(file); } /* -- see zlib.h -- */ -int ZEXPORT gzungetc(int c, gzFile file) -{ +int ZEXPORT gzungetc(int c, gzFile file) { gz_statep state; - /* get internal structure */ + /* get internal structure and check that it's for reading */ if (file == NULL) return -1; state = (gz_statep)file; + if (state->mode != GZ_READ) + return -1; - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + /* in case this was just opened, set up the input buffer */ + if (state->how == LOOK && state->x.have == 0) + (void)gz_look(state); + + /* check that there was no (serious) error */ + if (state->err != Z_OK && state->err != Z_BUF_ERROR && !state->again) return -1; + gz_error(state, Z_OK, NULL); /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return -1; - } + if (state->skip && gz_skip(state) == -1) + return -1; /* can't push EOF */ if (c < 0) return -1; /* if output buffer empty, put byte at end (allows more pushing) */ - if (state->have == 0) { - state->have = 1; - state->next = state->out + (state->size << 1) - 1; - state->next[0] = c; - state->pos--; + if (state->x.have == 0) { + state->x.have = 1; + state->x.next = state->out + (state->size << 1) - 1; + state->x.next[0] = (unsigned char)c; + state->x.pos--; + state->past = 0; return c; } /* if no room, give up (must have already done a gzungetc()) */ - if (state->have == (state->size << 1)) { - gz_error(state, Z_BUF_ERROR, "out of room to push characters"); + if (state->x.have == (state->size << 1)) { + gz_error(state, Z_DATA_ERROR, "out of room to push characters"); return -1; } /* slide output data if needed and insert byte before existing data */ - if (state->next == state->out) { - unsigned char *src = state->out + state->have; + if (state->x.next == state->out) { + unsigned char *src = state->out + state->x.have; unsigned char *dest = state->out + (state->size << 1); + while (src > state->out) *--dest = *--src; - state->next = dest; + state->x.next = dest; } - state->have++; - state->next--; - state->next[0] = c; - state->pos--; + state->x.have++; + state->x.next--; + state->x.next[0] = (unsigned char)c; + state->x.pos--; + state->past = 0; return c; } /* -- see zlib.h -- */ -char * ZEXPORT gzgets(gzFile file, char *buf, int len) -{ +char * ZEXPORT gzgets(gzFile file, char *buf, int len) { unsigned left, n; char *str; unsigned char *eol; gz_statep state; - /* check parameters and get internal structure */ + /* check parameters, get internal structure, and check that it's for + reading */ if (file == NULL || buf == NULL || len < 1) return NULL; state = (gz_statep)file; + if (state->mode != GZ_READ) + return NULL; - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + /* check that there was no (serious) error */ + if (state->err != Z_OK && state->err != Z_BUF_ERROR && !state->again) return NULL; + gz_error(state, Z_OK, NULL); /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return NULL; - } + if (state->skip && gz_skip(state) == -1) + return NULL; - /* copy output bytes up to new line or len - 1, whichever comes first -- - append a terminating zero to the string (we don't check for a zero in - the contents, let the user worry about that) */ + /* copy output up to a new line, len-1 bytes, or there is no more output, + whichever comes first */ str = buf; left = (unsigned)len - 1; if (left) do { /* assure that something is in the output buffer */ - if (state->have == 0) { - if (gz_make(state) == -1) - return NULL; /* error */ - if (state->have == 0) { /* end of file */ - if (buf == str) /* got bupkus */ - return NULL; - break; /* got something -- return it */ - } + if (state->x.have == 0 && gz_fetch(state) == -1) + break; /* error */ + if (state->x.have == 0) { /* end of file */ + state->past = 1; /* read past end */ + break; /* return what we have */ } /* look for end-of-line in current output buffer */ - n = state->have > left ? left : state->have; - eol = (unsigned char *)memchr(state->next, '\n', n); + n = state->x.have > left ? left : state->x.have; + eol = (unsigned char *)memchr(state->x.next, '\n', n); if (eol != NULL) - n = (unsigned)(eol - state->next) + 1; + n = (unsigned)(eol - state->x.next) + 1; /* copy through end-of-line, or remainder if not found */ - memcpy(buf, state->next, n); - state->have -= n; - state->next += n; - state->pos += n; + memcpy(buf, state->x.next, n); + state->x.have -= n; + state->x.next += n; + state->x.pos += n; left -= n; buf += n; } while (left && eol == NULL); - /* found end-of-line or out of space -- terminate string and return it */ + /* append a terminating zero to the string (we don't check for a zero in + the contents, let the user worry about that) -- return the terminated + string, or if nothing was read, NULL */ + if (buf == str) + return NULL; buf[0] = 0; return str; } /* -- see zlib.h -- */ -int ZEXPORT gzdirect(gzFile file) -{ +int ZEXPORT gzdirect(gzFile file) { gz_statep state; /* get internal structure */ @@ -595,31 +640,24 @@ int ZEXPORT gzdirect(gzFile file) return 0; state = (gz_statep)file; - /* check that we're reading */ - if (state->mode != GZ_READ) - return 0; - /* if the state is not known, but we can find out, then do so (this is mainly for right after a gzopen() or gzdopen()) */ - if (state->how == LOOK && state->have == 0) - (void)gz_head(state); + if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) + (void)gz_look(state); - /* return 1 if reading direct, 0 if decompressing a gzip stream */ - return state->direct; + /* return 1 if transparent, 0 if processing a gzip stream */ + return state->direct == 1; } /* -- see zlib.h -- */ -int ZEXPORT gzclose_r(gzFile file) -{ - int ret; +int ZEXPORT gzclose_r(gzFile file) { + int ret, err; gz_statep state; - /* get internal structure */ + /* get internal structure and check that it's for reading */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; - - /* check that we're reading */ if (state->mode != GZ_READ) return Z_STREAM_ERROR; @@ -629,13 +667,13 @@ int ZEXPORT gzclose_r(gzFile file) free(state->out); free(state->in); } + err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; gz_error(state, Z_OK, NULL); free(state->path); ret = close(state->fd); free(state); - return ret ? Z_ERRNO : Z_OK; + return ret ? Z_ERRNO : err; } - ABC_NAMESPACE_IMPL_END diff --git a/src/misc/zlib/gzwrite.c b/src/misc/zlib/gzwrite.c index 19015b4467..d87e39b2c9 100644 --- a/src/misc/zlib/gzwrite.c +++ b/src/misc/zlib/gzwrite.c @@ -1,5 +1,5 @@ /* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004, 2005, 2010 Mark Adler + * Copyright (C) 2004-2026 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -12,66 +12,102 @@ ABC_NAMESPACE_IMPL_START -/* Local functions */ -local int gz_init OF((gz_statep)); -local int gz_comp OF((gz_statep, int)); -local int gz_zero OF((gz_statep, z_off64_t)); /* Initialize state for writing a gzip file. Mark initialization by setting - state->size to non-zero. Return -1 on failure or 0 on success. */ -local int gz_init(gz_statep state) -{ + state->size to non-zero. Return -1 on a memory allocation failure, or 0 on + success. */ +local int gz_init(gz_statep state) { int ret; z_streamp strm = &(state->strm); - /* allocate input and output buffers */ - state->in = (unsigned char *)malloc(state->want); - state->out = (unsigned char *)malloc(state->want); - if (state->in == NULL || state->out == NULL) { - if (state->out != NULL) - free(state->out); - if (state->in != NULL) - free(state->in); + /* allocate input buffer (double size for gzprintf) */ + state->in = (unsigned char *)malloc(state->want << 1); + if (state->in == NULL) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } - /* allocate deflate memory, set up for gzip compression */ - strm->zalloc = Z_NULL; - strm->zfree = Z_NULL; - strm->opaque = Z_NULL; - ret = deflateInit2(strm, state->level, Z_DEFLATED, - 15 + 16, 8, state->strategy); - if (ret != Z_OK) { - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; + /* only need output buffer and deflate state if compressing */ + if (!state->direct) { + /* allocate output buffer */ + state->out = (unsigned char *)malloc(state->want); + if (state->out == NULL) { + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* allocate deflate memory, set up for gzip compression */ + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = deflateInit2(strm, state->level, Z_DEFLATED, + MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); + if (ret != Z_OK) { + free(state->out); + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + strm->next_in = NULL; } /* mark state as initialized */ state->size = state->want; - /* initialize write buffer */ - strm->avail_out = state->size; - strm->next_out = state->out; - state->next = strm->next_out; + /* initialize write buffer if compressing */ + if (!state->direct) { + strm->avail_out = state->size; + strm->next_out = state->out; + state->x.next = strm->next_out; + } return 0; } /* Compress whatever is at avail_in and next_in and write to the output file. - Return -1 if there is an error writing to the output file, otherwise 0. - flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, - then the deflate() state is reset to start a new gzip stream. */ -local int gz_comp(gz_statep state, int flush) -{ - int ret, got; - unsigned have; + Return -1 if there is an error writing to the output file or if gz_init() + fails to allocate memory, otherwise 0. flush is assumed to be a valid + deflate() flush value. If flush is Z_FINISH, then the deflate() state is + reset to start a new gzip stream. If gz->direct is true, then simply write + to the output file without compressing, and ignore flush. */ +local int gz_comp(gz_statep state, int flush) { + int ret, writ; + unsigned have, put, max = ((unsigned)-1 >> 2) + 1; z_streamp strm = &(state->strm); /* allocate memory if this is the first time through */ if (state->size == 0 && gz_init(state) == -1) return -1; + /* write directly if requested */ + if (state->direct) { + while (strm->avail_in) { + errno = 0; + state->again = 0; + put = strm->avail_in > max ? max : strm->avail_in; + writ = (int)write(state->fd, strm->next_in, put); + if (writ < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + state->again = 1; + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + strm->avail_in -= (unsigned)writ; + strm->next_in += writ; + } + return 0; + } + + /* check for a pending reset */ + if (state->reset) { + /* don't start a new gzip member unless there is data to write and + we're not flushing */ + if (strm->avail_in == 0 && flush == Z_NO_FLUSH) + return 0; + deflateReset(strm); + state->reset = 0; + } + /* run deflate() on provided input until it produces no more output */ ret = Z_OK; do { @@ -79,17 +115,25 @@ local int gz_comp(gz_statep state, int flush) doing Z_FINISH then don't write until we get to Z_STREAM_END */ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { - have = (unsigned)(strm->next_out - state->next); - if (have && ((got = write(state->fd, state->next, have)) < 0 || - (unsigned)got != have)) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; + while (strm->next_out > state->x.next) { + errno = 0; + state->again = 0; + put = strm->next_out - state->x.next > (int)max ? max : + (unsigned)(strm->next_out - state->x.next); + writ = (int)write(state->fd, state->x.next, put); + if (writ < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + state->again = 1; + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + state->x.next += writ; } if (strm->avail_out == 0) { strm->avail_out = state->size; strm->next_out = state->out; + state->x.next = state->out; } - state->next = strm->next_out; } /* compress */ @@ -105,16 +149,18 @@ local int gz_comp(gz_statep state, int flush) /* if that completed a deflate stream, allow another to start */ if (flush == Z_FINISH) - deflateReset(strm); + state->reset = 1; /* all done, no errors */ return 0; } -/* Compress len zeros to output. Return -1 on error, 0 on success. */ -local int gz_zero(gz_statep state, z_off64_t len) -{ - int first; +/* Compress state->skip (> 0) zeros to output. Return -1 on a write error or + memory allocation failure by gz_comp(), or 0 on success. state->skip is + updated with the number of successfully written zeros, in case there is a + stall on a non-blocking write destination. */ +local int gz_zero(gz_statep state) { + int first, ret; unsigned n; z_streamp strm = &(state->strm); @@ -122,49 +168,34 @@ local int gz_zero(gz_statep state, z_off64_t len) if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return -1; - /* compress len zeros (len guaranteed > 0) */ + /* compress state->skip zeros */ first = 1; - while (len) { - n = GT_OFF(state->size) || (z_off64_t)state->size > len ? - (unsigned)len : state->size; + do { + n = GT_OFF(state->size) || (z_off64_t)state->size > state->skip ? + (unsigned)state->skip : state->size; if (first) { - memset(state->in, 0, (size_t)n); + memset(state->in, 0, n); first = 0; } strm->avail_in = n; strm->next_in = state->in; - state->pos += n; - if (gz_comp(state, Z_NO_FLUSH) == -1) + ret = gz_comp(state, Z_NO_FLUSH); + n -= strm->avail_in; + state->x.pos += n; + state->skip -= n; + if (ret == -1) return -1; - len -= n; - } + } while (state->skip); return 0; } -/* -- see zlib.h -- */ -int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) -{ - unsigned put = len; - unsigned n; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids the flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); - return 0; - } +/* Write len bytes from buf to file. Return the number of bytes written. If + the returned value is less than len, then there was an error. If the error + was a non-blocking stall, then the number of bytes consumed is returned. + For any other error, 0 is returned. */ +local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) { + z_size_t put = len; + int ret; /* if len is zero, avoid unnecessary operations */ if (len == 0) @@ -175,50 +206,114 @@ int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) return 0; /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; - } + if (state->skip && gz_zero(state) == -1) + return 0; /* for small len, copy to input buffer, otherwise compress directly */ if (len < state->size) { /* copy to input buffer, compress when full */ - do { - if (strm->avail_in == 0) - strm->next_in = state->in; - n = state->size - strm->avail_in; - if (n > len) - n = len; - memcpy(strm->next_in + strm->avail_in, buf, n); - strm->avail_in += n; - state->pos += n; - buf = (char *)buf + n; - len -= n; - if (len && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - } while (len); + for (;;) { + unsigned have, copy; + + if (state->strm.avail_in == 0) + state->strm.next_in = state->in; + have = (unsigned)((state->strm.next_in + state->strm.avail_in) - + state->in); + copy = state->size - have; + if (copy > len) + copy = (unsigned)len; + memcpy(state->in + have, buf, copy); + state->strm.avail_in += copy; + state->x.pos += copy; + buf = (const char *)buf + copy; + len -= copy; + if (len == 0) + break; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return state->again ? put - len : 0; + } } else { /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* directly compress user buffer to file */ - strm->avail_in = len; - strm->next_in = (unsigned char *)(voidp)buf; - state->pos += len; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return 0; + state->strm.next_in = (z_const Bytef *)buf; + do { + unsigned n = (unsigned)-1; + + if (n > len) + n = (unsigned)len; + state->strm.avail_in = n; + ret = gz_comp(state, Z_NO_FLUSH); + n -= state->strm.avail_in; + state->x.pos += n; + len -= n; + if (ret == -1) + return state->again ? put - len : 0; + } while (len); + } + + /* input was all buffered or compressed */ + return put; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) { + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're writing and that there's no (serious) error */ + if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again)) + return 0; + gz_error(state, Z_OK, NULL); + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); + return 0; } - /* input was all buffered or compressed (put will fit in int) */ - return (int)put; + /* write len bytes from buf (the return value will fit in an int) */ + return (int)gz_write(state, buf, len); } /* -- see zlib.h -- */ -int ZEXPORT gzputc(gzFile file, int c) -{ +z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems, + gzFile file) { + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're writing and that there's no (serious) error */ + if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again)) + return 0; + gz_error(state, Z_OK, NULL); + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (size && len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* write len bytes to buf, return the number of full items written */ + return len ? gz_write(state, buf, len) / size : 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputc(gzFile file, int c) { + unsigned have; unsigned char buf[1]; gz_statep state; z_streamp strm; @@ -229,223 +324,320 @@ int ZEXPORT gzputc(gzFile file, int c) state = (gz_statep)file; strm = &(state->strm); - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) + /* check that we're writing and that there's no (serious) error */ + if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again)) return -1; + gz_error(state, Z_OK, NULL); /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } + if (state->skip && gz_zero(state) == -1) + return -1; /* try writing to input buffer for speed (state->size == 0 if buffer not initialized) */ - if (strm->avail_in < state->size) { + if (state->size) { if (strm->avail_in == 0) strm->next_in = state->in; - strm->next_in[strm->avail_in++] = c; - state->pos++; - return c; + have = (unsigned)((strm->next_in + strm->avail_in) - state->in); + if (have < state->size) { + state->in[have] = (unsigned char)c; + strm->avail_in++; + state->x.pos++; + return c & 0xff; + } } /* no room in buffer or not initialized, use gz_write() */ - buf[0] = c; - if (gzwrite(file, buf, 1) != 1) + buf[0] = (unsigned char)c; + if (gz_write(state, buf, 1) != 1) return -1; - return c; + return c & 0xff; } /* -- see zlib.h -- */ -int ZEXPORT gzputs(gzFile file, const char *str) -{ - int ret; - unsigned len; +int ZEXPORT gzputs(gzFile file, const char *s) { + z_size_t len, put; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're writing and that there's no (serious) error */ + if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again)) + return -1; + gz_error(state, Z_OK, NULL); /* write string */ - len = (unsigned)strlen(str); - ret = gzwrite(file, str, len); - return ret == 0 && len != 0 ? -1 : ret; + len = strlen(s); + if ((int)len < 0 || (unsigned)len != len) { + gz_error(state, Z_STREAM_ERROR, "string length does not fit in int"); + return -1; + } + put = gz_write(state, s, len); + return len && put == 0 ? -1 : (int)put; +} + +#if (((!defined(STDC) && !defined(Z_HAVE_STDARG_H)) || !defined(NO_vsnprintf)) && \ + (defined(STDC) || defined(Z_HAVE_STDARG_H) || !defined(NO_snprintf))) || \ + defined(ZLIB_INSECURE) +/* If the second half of the input buffer is occupied, write out the contents. + If there is any input remaining due to a non-blocking stall on write, move + it to the start of the buffer. Return true if this did not open up the + second half of the buffer. state->err should be checked after this to + handle a gz_comp() error. */ +local int gz_vacate(gz_statep state) { + z_streamp strm; + + strm = &(state->strm); + if (strm->next_in + strm->avail_in <= state->in + state->size) + return 0; + (void)gz_comp(state, Z_NO_FLUSH); + if (strm->avail_in == 0) { + strm->next_in = state->in; + return 0; + } + memmove(state->in, strm->next_in, strm->avail_in); + strm->next_in = state->in; + return strm->avail_in > state->size; } +#endif -#ifdef STDC +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +ABC_NAMESPACE_IMPL_END #include +ABC_NAMESPACE_IMPL_START /* -- see zlib.h -- */ -int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) -{ - int size, len; +int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { +#if defined(NO_vsnprintf) && !defined(ZLIB_INSECURE) +#warning "vsnprintf() not available -- gzprintf() stub returns Z_STREAM_ERROR" +#warning "you can recompile with ZLIB_INSECURE defined to use vsprintf()" + /* prevent use of insecure vsprintf(), unless purposefully requested */ + (void)file, (void)format, (void)va; + return Z_STREAM_ERROR; +#else + int len, ret; + char *next; gz_statep state; z_streamp strm; - va_list va; /* get internal structure */ if (file == NULL) - return -1; + return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; + /* check that we're writing and that there's no (serious) error */ + if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again)) + return Z_STREAM_ERROR; + gz_error(state, Z_OK, NULL); /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) - return 0; + return state->err; /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; + if (state->skip && gz_zero(state) == -1) + return state->err; + + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there should be + state->size bytes available after the current contents */ + ret = gz_vacate(state); + if (state->err) { + if (ret && state->again) { + /* There was a non-blocking stall on write, resulting in the part + of the second half of the output buffer being occupied. Return + a Z_BUF_ERROR to let the application know that this gzprintf() + needs to be retried. */ + gz_error(state, Z_BUF_ERROR, "stalled write on gzprintf"); + } + if (!state->again) + return state->err; } - - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* do the printf() into the input buffer, put length in len */ - size = (int)(state->size); - state->in[size - 1] = 0; - va_start(va, format); + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); + next[state->size - 1] = 0; #ifdef NO_vsnprintf # ifdef HAS_vsprintf_void - (void)vsprintf(state->in, format, va); - va_end(va); - for (len = 0; len < size; len++) - if (state->in[len] == 0) break; + (void)vsprintf(next, format, va); + for (len = 0; len < state->size; len++) + if (next[len] == 0) break; # else - len = vsprintf(state->in, format, va); - va_end(va); + len = vsprintf(next, format, va); # endif #else # ifdef HAS_vsnprintf_void - (void)vsnprintf(state->in, size, format, va); - va_end(va); - len = strlen(state->in); + (void)vsnprintf(next, state->size, format, va); + len = strlen(next); # else - len = vsnprintf((char *)(state->in), size, format, va); - va_end(va); + len = vsnprintf(next, state->size, format, va); # endif #endif /* check that printf() results fit in buffer */ - if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) return 0; - /* update buffer and position, defer compression until needed */ - strm->avail_in = (unsigned)len; - strm->next_in = state->in; - state->pos += len; + /* update buffer and position */ + strm->avail_in += (unsigned)len; + state->x.pos += len; + + /* write out buffer if more than half is occupied */ + ret = gz_vacate(state); + if (state->err && !state->again) + return state->err; return len; +#endif } -#else /* !STDC */ +int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) { + va_list va; + int ret; + + va_start(va, format); + ret = gzvprintf(file, format, va); + va_end(va); + return ret; +} + +#else /* !STDC && !Z_HAVE_STDARG_H */ /* -- see zlib.h -- */ -int ZEXPORTVA gzprintf (gzFile file, const char *format, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, - int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20) -{ - int size, len; +int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3, + int a4, int a5, int a6, int a7, int a8, int a9, int a10, + int a11, int a12, int a13, int a14, int a15, int a16, + int a17, int a18, int a19, int a20) { +#if defined(NO_snprintf) && !defined(ZLIB_INSECURE) +#warning "snprintf() not available -- gzprintf() stub returns Z_STREAM_ERROR" +#warning "you can recompile with ZLIB_INSECURE defined to use sprintf()" + /* prevent use of insecure sprintf(), unless purposefully requested */ + (void)file, (void)format, (void)a1, (void)a2, (void)a3, (void)a4, (void)a5, + (void)a6, (void)a7, (void)a8, (void)a9, (void)a10, (void)a11, (void)a12, + (void)a13, (void)a14, (void)a15, (void)a16, (void)a17, (void)a18, + (void)a19, (void)a20; + return Z_STREAM_ERROR; +#else + int ret; + unsigned len, left; + char *next; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) - return -1; + return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; + /* check that can really pass pointer in ints */ + if (sizeof(int) != sizeof(void *)) + return Z_STREAM_ERROR; + + /* check that we're writing and that there's no (serious) error */ + if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again)) + return Z_STREAM_ERROR; + gz_error(state, Z_OK, NULL); /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) - return 0; + return state->err; /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; + if (state->skip && gz_zero(state) == -1) + return state->err; + + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there is guaranteed to + be state->size bytes available after the current contents */ + ret = gz_vacate(state); + if (state->err) { + if (ret && state->again) { + /* There was a non-blocking stall on write, resulting in the part + of the second half of the output buffer being occupied. Return + a Z_BUF_ERROR to let the application know that this gzprintf() + needs to be retried. */ + gz_error(state, Z_BUF_ERROR, "stalled write on gzprintf"); + } + if (!state->again) + return state->err; } - - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* do the printf() into the input buffer, put length in len */ - size = (int)(state->size); - state->in[size - 1] = 0; + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(strm->next_in + strm->avail_in); + next[state->size - 1] = 0; #ifdef NO_snprintf # ifdef HAS_sprintf_void - sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, + a13, a14, a15, a16, a17, a18, a19, a20); for (len = 0; len < size; len++) - if (state->in[len] == 0) break; + if (next[len] == 0) + break; # else - len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, + a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #else # ifdef HAS_snprintf_void - snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen(state->in); + snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(next); # else - len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #endif /* check that printf() results fit in buffer */ - if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + if (len == 0 || len >= state->size || next[state->size - 1] != 0) return 0; - /* update buffer and position, defer compression until needed */ - strm->avail_in = (unsigned)len; - strm->next_in = state->in; - state->pos += len; - return len; + /* update buffer and position, compress first half if past that */ + strm->avail_in += len; + state->x.pos += len; + + /* write out buffer if more than half is occupied */ + ret = gz_vacate(state); + if (state->err && !state->again) + return state->err; + return (int)len; +#endif } #endif /* -- see zlib.h -- */ -int ZEXPORT gzflush(gzFile file, int flush) -{ +int ZEXPORT gzflush(gzFile file, int flush) { gz_statep state; /* get internal structure */ if (file == NULL) - return -1; + return Z_STREAM_ERROR; state = (gz_statep)file; - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) + /* check that we're writing and that there's no (serious) error */ + if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again)) return Z_STREAM_ERROR; + gz_error(state, Z_OK, NULL); /* check flush parameter */ if (flush < 0 || flush > Z_FINISH) return Z_STREAM_ERROR; /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } + if (state->skip && gz_zero(state) == -1) + return state->err; /* compress remaining data with requested flush */ - gz_comp(state, flush); + (void)gz_comp(state, flush); return state->err; } /* -- see zlib.h -- */ -int ZEXPORT gzsetparams(gzFile file, int level, int strategy) -{ +int ZEXPORT gzsetparams(gzFile file, int level, int strategy) { gz_statep state; z_streamp strm; @@ -455,25 +647,24 @@ int ZEXPORT gzsetparams(gzFile file, int level, int strategy) state = (gz_statep)file; strm = &(state->strm); - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) + /* check that we're compressing and that there's no (serious) error */ + if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again) || + state->direct) return Z_STREAM_ERROR; + gz_error(state, Z_OK, NULL); /* if no change is requested, then do nothing */ if (level == state->level && strategy == state->strategy) return Z_OK; /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } + if (state->skip && gz_zero(state) == -1) + return state->err; /* change compression parameters for subsequent input */ if (state->size) { /* flush previous input with previous parameters before changing */ - if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) + if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) return state->err; deflateParams(strm, level, strategy); } @@ -483,9 +674,8 @@ int ZEXPORT gzsetparams(gzFile file, int level, int strategy) } /* -- see zlib.h -- */ -int ZEXPORT gzclose_w(gzFile file) -{ - int ret = 0; +int ZEXPORT gzclose_w(gzFile file) { + int ret = Z_OK; gz_statep state; /* get internal structure */ @@ -498,23 +688,26 @@ int ZEXPORT gzclose_w(gzFile file) return Z_STREAM_ERROR; /* check for seek request */ - if (state->seek) { - state->seek = 0; - ret += gz_zero(state, state->skip); - } + if (state->skip && gz_zero(state) == -1) + ret = state->err; /* flush, free memory, and close file */ - ret += gz_comp(state, Z_FINISH); - (void)deflateEnd(&(state->strm)); - free(state->out); - free(state->in); + if (gz_comp(state, Z_FINISH) == -1) + ret = state->err; + if (state->size) { + if (!state->direct) { + (void)deflateEnd(&(state->strm)); + free(state->out); + } + free(state->in); + } gz_error(state, Z_OK, NULL); free(state->path); - ret += close(state->fd); + if (close(state->fd) == -1) + ret = Z_ERRNO; free(state); - return ret ? Z_ERRNO : Z_OK; + return ret; } - ABC_NAMESPACE_IMPL_END diff --git a/src/misc/zlib/infback.c b/src/misc/zlib/infback.c index 7559f7fdbc..8943f46076 100644 --- a/src/misc/zlib/infback.c +++ b/src/misc/zlib/infback.c @@ -1,5 +1,5 @@ /* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2009 Mark Adler + * Copyright (C) 1995-2026 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -22,8 +22,6 @@ ABC_NAMESPACE_IMPL_START -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); /* strm provides memory allocation functions in zalloc and zfree, or @@ -32,8 +30,9 @@ local void fixedtables OF((struct inflate_state FAR *state)); windowBits is in the range 8..15, and window is a user-supplied window and output buffer that is 2**windowBits bytes. */ -int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size) -{ +int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, + unsigned char FAR *window, const char *version, + int stream_size) { struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || @@ -44,76 +43,34 @@ int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR * return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; +#endif } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif state = (struct inflate_state FAR *)ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->dmax = 32768U; - state->wbits = windowBits; + state->wbits = (uInt)windowBits; state->wsize = 1U << windowBits; state->window = window; state->wnext = 0; state->whave = 0; + state->sane = 1; return Z_OK; } -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(struct inflate_state FAR *state) -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - /* Macros for inflateBack(): */ /* Load returned state from inflate_fast() */ @@ -239,10 +196,10 @@ local void fixedtables(struct inflate_state FAR *state) inflateBack() can also return Z_STREAM_ERROR if the input parameters are not correct, i.e. strm is Z_NULL or the state was not initialized. */ -int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc) -{ +int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc) { struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ + z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ @@ -293,7 +250,7 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func state->mode = STORED; break; case 1: /* fixed block */ - fixedtables(state); + inflate_fixed(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN; /* decode codes */ @@ -303,8 +260,8 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func state->last ? " (last)" : "")); state->mode = TABLE; break; - case 3: - strm->msg = (char *)"invalid block type"; + default: + strm->msg = (z_const char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); @@ -315,7 +272,7 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; + strm->msg = (z_const char *)"invalid stored block lengths"; state->mode = BAD; break; } @@ -353,7 +310,8 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; + strm->msg = (z_const char *) + "too many length or distance symbols"; state->mode = BAD; break; } @@ -375,7 +333,7 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid code lengths set"; + strm->msg = (z_const char *)"invalid code lengths set"; state->mode = BAD; break; } @@ -390,7 +348,6 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func PULLBYTE(); } if (here.val < 16) { - NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } @@ -399,7 +356,8 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; + strm->msg = (z_const char *) + "invalid bit length repeat"; state->mode = BAD; break; } @@ -422,7 +380,8 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; + strm->msg = (z_const char *) + "invalid bit length repeat"; state->mode = BAD; break; } @@ -436,7 +395,8 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; + strm->msg = (z_const char *) + "invalid code -- missing end-of-block"; state->mode = BAD; break; } @@ -450,7 +410,7 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; + strm->msg = (z_const char *)"invalid literal/lengths set"; state->mode = BAD; break; } @@ -459,12 +419,13 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { - strm->msg = (char *)"invalid distances set"; + strm->msg = (z_const char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN; + /* fallthrough */ case LEN: /* use inflate_fast() if we have enough input and output */ @@ -517,7 +478,7 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func /* invalid code */ if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; + strm->msg = (z_const char *)"invalid literal/length code"; state->mode = BAD; break; } @@ -549,7 +510,7 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func } DROPBITS(here.bits); if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; + strm->msg = (z_const char *)"invalid distance code"; state->mode = BAD; break; } @@ -564,7 +525,7 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func } if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = (z_const char *)"invalid distance too far back"; state->mode = BAD; break; } @@ -592,32 +553,33 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func break; case DONE: - /* inflate stream terminated properly -- write leftover output */ + /* inflate stream terminated properly */ ret = Z_STREAM_END; - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left)) - ret = Z_BUF_ERROR; - } goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; - default: /* can't happen, but makes compilers happy */ + default: + /* can't happen, but makes compilers happy */ ret = Z_STREAM_ERROR; goto inf_leave; } - /* Return unused input */ + /* Write leftover output and return unused input */ inf_leave: + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left) && + ret == Z_STREAM_END) + ret = Z_BUF_ERROR; + } strm->next_in = next; strm->avail_in = have; return ret; } -int ZEXPORT inflateBackEnd(z_streamp strm) -{ +int ZEXPORT inflateBackEnd(z_streamp strm) { if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; ZFREE(strm, strm->state); @@ -626,6 +588,5 @@ int ZEXPORT inflateBackEnd(z_streamp strm) return Z_OK; } - ABC_NAMESPACE_IMPL_END diff --git a/src/misc/zlib/inffast.c b/src/misc/zlib/inffast.c index a44d180ec7..d76bdc681d 100644 --- a/src/misc/zlib/inffast.c +++ b/src/misc/zlib/inffast.c @@ -1,5 +1,5 @@ /* inffast.c -- fast decoding - * Copyright (C) 1995-2008, 2010 Mark Adler + * Copyright (C) 1995-2026 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -15,26 +15,10 @@ ABC_NAMESPACE_IMPL_START -#ifndef ASMINF -/* Allow machine dependent optimization for post-increment or pre-increment. - Based on testing to date, - Pre-increment preferred for: - - PowerPC G3 (Adler) - - MIPS R5000 (Randers-Pehrson) - Post-increment preferred for: - - none - No measurable difference: - - Pentium III (Anderson) - - M68060 (Nikl) - */ -#ifdef POSTINC -# define OFF 0 -# define PUP(a) *(a)++ +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") #else -# define OFF 1 -# define PUP(a) *++(a) -#endif /* Decode literal, length, and distance codes and write out the resulting @@ -71,11 +55,10 @@ ABC_NAMESPACE_IMPL_START requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ -void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s starting value for strm->avail_out */ -{ +void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) { struct inflate_state FAR *state; - unsigned char FAR *in; /* local strm->next_in */ - unsigned char FAR *last; /* while in < last, enough input available */ + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ @@ -92,7 +75,7 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s code const FAR *dcode; /* local strm->distcode */ unsigned lmask; /* mask for first level of length codes */ unsigned dmask; /* mask for first level of distance codes */ - code here; /* retrieved table entry */ + code const *here; /* retrieved table entry */ unsigned op; /* code bits, operation, extra bits, or */ /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ @@ -101,9 +84,9 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; - in = strm->next_in - OFF; + in = strm->next_in; last = in + (strm->avail_in - 5); - out = strm->next_out - OFF; + out = strm->next_out; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT @@ -124,29 +107,29 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s input data or output space */ do { if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } - here = lcode[hold & lmask]; + here = lcode + (hold & lmask); dolen: - op = (unsigned)(here.bits); + op = (unsigned)(here->bits); hold >>= op; bits -= op; - op = (unsigned)(here.op); + op = (unsigned)(here->op); if (op == 0) { /* literal */ - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - PUP(out) = (unsigned char)(here.val); + "inflate: literal 0x%02x\n", here->val)); + *out++ = (unsigned char)(here->val); } else if (op & 16) { /* length base */ - len = (unsigned)(here.val); + len = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); @@ -155,32 +138,33 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } - here = dcode[hold & dmask]; + here = dcode + (hold & dmask); dodist: - op = (unsigned)(here.bits); + op = (unsigned)(here->bits); hold >>= op; bits -= op; - op = (unsigned)(here.op); + op = (unsigned)(here->op); if (op & 16) { /* distance base */ - dist = (unsigned)(here.val); + dist = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } } dist += (unsigned)hold & ((1U << op) - 1); #ifdef INFLATE_STRICT if (dist > dmax) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = (z_const char *) + "invalid distance too far back"; state->mode = BAD; break; } @@ -193,38 +177,38 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s op = dist - op; /* distance back in window */ if (op > whave) { if (state->sane) { - strm->msg = - (char *)"invalid distance too far back"; + strm->msg = (z_const char *) + "invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { - PUP(out) = 0; + *out++ = 0; } while (--len); continue; } len -= op - whave; do { - PUP(out) = 0; + *out++ = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--len); continue; } #endif } - from = window - OFF; + from = window; if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } @@ -235,14 +219,14 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s if (op < len) { /* some from end of window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); - from = window - OFF; + from = window; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } @@ -253,50 +237,50 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s if (op < len) { /* some from window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; len -= 3; } if (len) { - PUP(out) = PUP(from); + *out++ = *from++; if (len > 1) - PUP(out) = PUP(from); + *out++ = *from++; } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; len -= 3; } while (len > 2); if (len) { - PUP(out) = PUP(from); + *out++ = *from++; if (len > 1) - PUP(out) = PUP(from); + *out++ = *from++; } } } else if ((op & 64) == 0) { /* 2nd level distance code */ - here = dcode[here.val + (hold & ((1U << op) - 1))]; + here = dcode + here->val + (hold & ((1U << op) - 1)); goto dodist; } else { - strm->msg = (char *)"invalid distance code"; + strm->msg = (z_const char *)"invalid distance code"; state->mode = BAD; break; } } else if ((op & 64) == 0) { /* 2nd level length code */ - here = lcode[here.val + (hold & ((1U << op) - 1))]; + here = lcode + here->val + (hold & ((1U << op) - 1)); goto dolen; } else if (op & 32) { /* end-of-block */ @@ -305,7 +289,7 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s break; } else { - strm->msg = (char *)"invalid literal/length code"; + strm->msg = (z_const char *)"invalid literal/length code"; state->mode = BAD; break; } @@ -318,8 +302,8 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s hold &= (1U << bits) - 1; /* update state and return */ - strm->next_in = in + OFF; - strm->next_out = out + OFF; + strm->next_in = in; + strm->next_out = out; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); @@ -344,8 +328,5 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s #endif /* !ASMINF */ - - ABC_NAMESPACE_IMPL_END - diff --git a/src/misc/zlib/inffast.h b/src/misc/zlib/inffast.h index 4fb86a11d3..899dbaebe6 100644 --- a/src/misc/zlib/inffast.h +++ b/src/misc/zlib/inffast.h @@ -3,13 +3,14 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ +ABC_NAMESPACE_HEADER_START + + /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ -ABC_NAMESPACE_HEADER_START - -void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); +void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start); ABC_NAMESPACE_HEADER_END diff --git a/src/misc/zlib/inffixed.h b/src/misc/zlib/inffixed.h index 19befa9a25..05ce88e4ff 100644 --- a/src/misc/zlib/inffixed.h +++ b/src/misc/zlib/inffixed.h @@ -1,98 +1,94 @@ - /* inffixed.h -- table for decoding fixed codes - * Generated automatically by makefixed(). - */ +/* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ - /* WARNING: this file should *not* be used by applications. It - is part of the implementation of the compression library and - is subject to change. Applications should only use zlib.h. - */ +/* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. + */ -//ABC_NAMESPACE_HEADER_START +static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} +}; - static const code lenfix[512] = { - {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, - {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, - {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, - {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, - {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, - {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, - {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, - {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, - {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, - {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, - {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, - {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, - {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, - {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, - {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, - {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, - {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, - {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, - {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, - {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, - {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, - {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, - {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, - {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, - {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, - {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, - {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, - {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, - {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, - {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, - {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, - {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, - {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, - {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, - {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, - {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, - {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, - {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, - {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, - {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, - {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, - {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, - {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, - {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, - {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, - {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, - {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, - {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, - {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, - {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, - {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, - {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, - {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, - {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, - {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, - {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, - {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, - {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, - {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, - {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, - {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, - {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, - {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, - {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, - {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, - {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, - {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, - {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, - {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, - {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, - {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, - {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, - {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, - {0,9,255} - }; - - static const code distfix[32] = { - {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, - {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, - {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, - {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, - {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, - {22,5,193},{64,5,0} - }; - -//ABC_NAMESPACE_HEADER_END +static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} +}; diff --git a/src/misc/zlib/inflate.c b/src/misc/zlib/inflate.c index 9fae70457b..d51b9e78a8 100644 --- a/src/misc/zlib/inflate.c +++ b/src/misc/zlib/inflate.c @@ -1,5 +1,5 @@ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2010 Mark Adler + * Copyright (C) 1995-2026 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -92,38 +92,35 @@ ABC_NAMESPACE_IMPL_START -#ifdef MAKEFIXED -# ifndef BUILDFIXED -# define BUILDFIXED -# endif -#endif -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, unsigned out)); -#ifdef BUILDFIXED - void makefixed OF((void)); -#endif -local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, - unsigned len)); +local int inflateStateCheck(z_streamp strm) { + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} -int ZEXPORT inflateReset(z_streamp strm) -{ +int ZEXPORT inflateResetKeep(z_streamp strm) { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; - strm->adler = 1; /* to support ill-conceived Java test suite */ + strm->data_type = 0; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; state->mode = HEAD; state->last = 0; state->havedict = 0; + state->flags = -1; state->dmax = 32768U; state->head = Z_NULL; - state->wsize = 0; - state->whave = 0; - state->wnext = 0; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; @@ -133,22 +130,34 @@ int ZEXPORT inflateReset(z_streamp strm) return Z_OK; } -int ZEXPORT inflateReset2(z_streamp strm, int windowBits) -{ +int ZEXPORT inflateReset(z_streamp strm) { + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + +int ZEXPORT inflateReset2(z_streamp strm, int windowBits) { int wrap; struct inflate_state FAR *state; /* get the state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* extract wrap request from windowBits parameter */ if (windowBits < 0) { + if (windowBits < -15) + return Z_STREAM_ERROR; wrap = 0; windowBits = -windowBits; } else { - wrap = (windowBits >> 4) + 1; + wrap = (windowBits >> 4) + 5; #ifdef GUNZIP if (windowBits < 48) windowBits &= 15; @@ -169,8 +178,8 @@ int ZEXPORT inflateReset2(z_streamp strm, int windowBits) return inflateReset(strm); } -int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size) -{ +int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size) { int ret; struct inflate_state FAR *state; @@ -180,16 +189,28 @@ int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, i if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; +#endif } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif state = (struct inflate_state FAR *) ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; + zmemzero(state, sizeof(struct inflate_state)); Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; + state->strm = strm; state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); @@ -198,142 +219,30 @@ int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, i return ret; } -int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size) -{ +int ZEXPORT inflateInit_(z_streamp strm, const char *version, + int stream_size) { return inflateInit2_(strm, DEF_WBITS, version, stream_size); } -int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) -{ +int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + if (bits == 0) + return Z_OK; state = (struct inflate_state FAR *)strm->state; if (bits < 0) { state->hold = 0; state->bits = 0; return Z_OK; } - if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; - state->hold += value << state->bits; - state->bits += bits; + state->hold += (unsigned long)value << state->bits; + state->bits += (uInt)bits; return Z_OK; } -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(struct inflate_state FAR *state) -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -#ifdef MAKEFIXED -#include - -/* - Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also - defines BUILDFIXED, so the tables are built on the fly. makefixed() writes - those tables to stdout, which would be piped to inffixed.h. A small program - can simply call makefixed to do this: - - void makefixed(void); - - int main(void) - { - makefixed(); - return 0; - } - - Then that can be linked with zlib built with MAKEFIXED defined and run: - - a.out > inffixed.h - */ -void makefixed() -{ - unsigned low, size; - struct inflate_state state; - - fixedtables(&state); - puts(" /* inffixed.h -- table for decoding fixed codes"); - puts(" * Generated automatically by makefixed()."); - puts(" */"); - puts(""); - puts(" /* WARNING: this file should *not* be used by applications."); - puts(" It is part of the implementation of this library and is"); - puts(" subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - size = 1U << 9; - printf(" static const code lenfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 7) == 0) printf("\n "); - printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, - state.lencode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); - size = 1U << 5; - printf("\n static const code distfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 6) == 0) printf("\n "); - printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, - state.distcode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); -} -#endif /* MAKEFIXED */ - /* Update the window with the last wsize (normally 32K) bytes written before returning. If window does not exist yet, create it. This is only called @@ -348,10 +257,9 @@ void makefixed() output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ -local int updatewindow(z_streamp strm, unsigned out) -{ +local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) { struct inflate_state FAR *state; - unsigned copy, dist; + unsigned dist; state = (struct inflate_state FAR *)strm->state; @@ -371,19 +279,18 @@ local int updatewindow(z_streamp strm, unsigned out) } /* copy state->wsize or less output bytes into the circular window */ - copy = out - strm->avail_out; if (copy >= state->wsize) { - zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + zmemcpy(state->window, end - state->wsize, state->wsize); state->wnext = 0; state->whave = state->wsize; } else { dist = state->wsize - state->wnext; if (dist > copy) dist = copy; - zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + zmemcpy(state->window + state->wnext, end - copy, dist); copy -= dist; if (copy) { - zmemcpy(state->window, strm->next_out - copy, copy); + zmemcpy(state->window, end - copy, copy); state->wnext = copy; state->whave = state->wsize; } @@ -400,10 +307,10 @@ local int updatewindow(z_streamp strm, unsigned out) /* check function to use adler32() for zlib or crc32() for gzip */ #ifdef GUNZIP -# define UPDATE(check, buf, len) \ +# define UPDATE_CHECK(check, buf, len) \ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) #else -# define UPDATE(check, buf, len) adler32(check, buf, len) +# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len) #endif /* check macros for header crc */ @@ -490,11 +397,6 @@ local int updatewindow(z_streamp strm, unsigned out) bits -= bits & 7; \ } while (0) -/* Reverse the bytes in a 32-bit value */ -#define REVERSE(q) \ - ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - /* inflate() uses a state machine to process as much input data and generate as much output data as possible before returning. The state machine is @@ -577,10 +479,9 @@ local int updatewindow(z_streamp strm, unsigned out) will return Z_BUF_ERROR if it has not reached the end of the stream. */ -int ZEXPORT inflate(z_streamp strm, int flush) -{ +int ZEXPORT inflate(z_streamp strm, int flush) { struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ + z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ @@ -598,7 +499,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; @@ -618,13 +519,14 @@ int ZEXPORT inflate(z_streamp strm, int flush) NEEDBITS(16); #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; state->check = crc32(0L, Z_NULL, 0); CRC2(state->check, hold); INITBITS(); state->mode = FLAGS; break; } - state->flags = 0; /* expect zlib header */ if (state->head != Z_NULL) state->head->done = -1; if (!(state->wrap & 1) || /* check if zlib header allowed */ @@ -632,12 +534,12 @@ int ZEXPORT inflate(z_streamp strm, int flush) if ( #endif ((BITS(8) << 8) + (hold >> 8)) % 31) { - strm->msg = (char *)"incorrect header check"; + strm->msg = (z_const char *)"incorrect header check"; state->mode = BAD; break; } if (BITS(4) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; + strm->msg = (z_const char *)"unknown compression method"; state->mode = BAD; break; } @@ -645,12 +547,13 @@ int ZEXPORT inflate(z_streamp strm, int flush) len = BITS(4) + 8; if (state->wbits == 0) state->wbits = len; - else if (len > state->wbits) { - strm->msg = (char *)"invalid window size"; + if (len > 15 || len > state->wbits) { + strm->msg = (z_const char *)"invalid window size"; state->mode = BAD; break; } state->dmax = 1U << len; + state->flags = 0; /* indicate zlib header */ Tracev((stderr, "inflate: zlib header ok\n")); strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = hold & 0x200 ? DICTID : TYPE; @@ -661,61 +564,70 @@ int ZEXPORT inflate(z_streamp strm, int flush) NEEDBITS(16); state->flags = (int)(hold); if ((state->flags & 0xff) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; + strm->msg = (z_const char *)"unknown compression method"; state->mode = BAD; break; } if (state->flags & 0xe000) { - strm->msg = (char *)"unknown header flags set"; + strm->msg = (z_const char *)"unknown header flags set"; state->mode = BAD; break; } if (state->head != Z_NULL) state->head->text = (int)((hold >> 8) & 1); - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); state->mode = TIME; + /* fallthrough */ case TIME: NEEDBITS(32); if (state->head != Z_NULL) state->head->time = hold; - if (state->flags & 0x0200) CRC4(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); INITBITS(); state->mode = OS; + /* fallthrough */ case OS: NEEDBITS(16); if (state->head != Z_NULL) { state->head->xflags = (int)(hold & 0xff); state->head->os = (int)(hold >> 8); } - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; + /* fallthrough */ case EXLEN: if (state->flags & 0x0400) { NEEDBITS(16); state->length = (unsigned)(hold); if (state->head != Z_NULL) state->head->extra_len = (unsigned)hold; - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); } else if (state->head != Z_NULL) state->head->extra = Z_NULL; state->mode = EXTRA; + /* fallthrough */ case EXTRA: if (state->flags & 0x0400) { copy = state->length; if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; + state->head->extra != Z_NULL && + (len = state->head->extra_len - state->length) < + state->head->extra_max) { zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -725,6 +637,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) } state->length = 0; state->mode = NAME; + /* fallthrough */ case NAME: if (state->flags & 0x0800) { if (have == 0) goto inf_leave; @@ -734,9 +647,9 @@ int ZEXPORT inflate(z_streamp strm, int flush) if (state->head != Z_NULL && state->head->name != Z_NULL && state->length < state->head->name_max) - state->head->name[state->length++] = len; + state->head->name[state->length++] = (Bytef)len; } while (len && copy < have); - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -746,6 +659,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) state->head->name = Z_NULL; state->length = 0; state->mode = COMMENT; + /* fallthrough */ case COMMENT: if (state->flags & 0x1000) { if (have == 0) goto inf_leave; @@ -755,9 +669,9 @@ int ZEXPORT inflate(z_streamp strm, int flush) if (state->head != Z_NULL && state->head->comment != Z_NULL && state->length < state->head->comm_max) - state->head->comment[state->length++] = len; + state->head->comment[state->length++] = (Bytef)len; } while (len && copy < have); - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -766,11 +680,12 @@ int ZEXPORT inflate(z_streamp strm, int flush) else if (state->head != Z_NULL) state->head->comment = Z_NULL; state->mode = HCRC; + /* fallthrough */ case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); - if (hold != (state->check & 0xffff)) { - strm->msg = (char *)"header crc mismatch"; + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { + strm->msg = (z_const char *)"header crc mismatch"; state->mode = BAD; break; } @@ -786,9 +701,10 @@ int ZEXPORT inflate(z_streamp strm, int flush) #endif case DICTID: NEEDBITS(32); - strm->adler = state->check = REVERSE(hold); + strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; + /* fallthrough */ case DICT: if (state->havedict == 0) { RESTORE(); @@ -796,8 +712,10 @@ int ZEXPORT inflate(z_streamp strm, int flush) } strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = TYPE; + /* fallthrough */ case TYPE: if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + /* fallthrough */ case TYPEDO: if (state->last) { BYTEBITS(); @@ -814,7 +732,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) state->mode = STORED; break; case 1: /* fixed block */ - fixedtables(state); + inflate_fixed(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN_; /* decode codes */ @@ -828,8 +746,8 @@ int ZEXPORT inflate(z_streamp strm, int flush) state->last ? " (last)" : "")); state->mode = TABLE; break; - case 3: - strm->msg = (char *)"invalid block type"; + default: + strm->msg = (z_const char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); @@ -838,7 +756,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; + strm->msg = (z_const char *)"invalid stored block lengths"; state->mode = BAD; break; } @@ -848,8 +766,10 @@ int ZEXPORT inflate(z_streamp strm, int flush) INITBITS(); state->mode = COPY_; if (flush == Z_TREES) goto inf_leave; + /* fallthrough */ case COPY_: state->mode = COPY; + /* fallthrough */ case COPY: copy = state->length; if (copy) { @@ -877,7 +797,8 @@ int ZEXPORT inflate(z_streamp strm, int flush) DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; + strm->msg = (z_const char *) + "too many length or distance symbols"; state->mode = BAD; break; } @@ -885,6 +806,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) Tracev((stderr, "inflate: table sizes ok\n")); state->have = 0; state->mode = LENLENS; + /* fallthrough */ case LENLENS: while (state->have < state->ncode) { NEEDBITS(3); @@ -894,18 +816,19 @@ int ZEXPORT inflate(z_streamp strm, int flush) while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; - state->lencode = (code const FAR *)(state->next); + state->lencode = state->distcode = (const code FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid code lengths set"; + strm->msg = (z_const char *)"invalid code lengths set"; state->mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); state->have = 0; state->mode = CODELENS; + /* fallthrough */ case CODELENS: while (state->have < state->nlen + state->ndist) { for (;;) { @@ -914,7 +837,6 @@ int ZEXPORT inflate(z_streamp strm, int flush) PULLBYTE(); } if (here.val < 16) { - NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } @@ -923,7 +845,8 @@ int ZEXPORT inflate(z_streamp strm, int flush) NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; + strm->msg = (z_const char *) + "invalid bit length repeat"; state->mode = BAD; break; } @@ -946,7 +869,8 @@ int ZEXPORT inflate(z_streamp strm, int flush) DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; + strm->msg = (z_const char *) + "invalid bit length repeat"; state->mode = BAD; break; } @@ -960,7 +884,8 @@ int ZEXPORT inflate(z_streamp strm, int flush) /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; + strm->msg = (z_const char *) + "invalid code -- missing end-of-block"; state->mode = BAD; break; } @@ -969,29 +894,31 @@ int ZEXPORT inflate(z_streamp strm, int flush) values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; - state->lencode = (code const FAR *)(state->next); + state->lencode = (const code FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; + strm->msg = (z_const char *)"invalid literal/lengths set"; state->mode = BAD; break; } - state->distcode = (code const FAR *)(state->next); + state->distcode = (const code FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { - strm->msg = (char *)"invalid distances set"; + strm->msg = (z_const char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN_; if (flush == Z_TREES) goto inf_leave; + /* fallthrough */ case LEN_: state->mode = LEN; + /* fallthrough */ case LEN: if (have >= 6 && left >= 258) { RESTORE(); @@ -1035,12 +962,13 @@ int ZEXPORT inflate(z_streamp strm, int flush) break; } if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; + strm->msg = (z_const char *)"invalid literal/length code"; state->mode = BAD; break; } state->extra = (unsigned)(here.op) & 15; state->mode = LENEXT; + /* fallthrough */ case LENEXT: if (state->extra) { NEEDBITS(state->extra); @@ -1051,6 +979,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) Tracevv((stderr, "inflate: length %u\n", state->length)); state->was = state->length; state->mode = DIST; + /* fallthrough */ case DIST: for (;;) { here = state->distcode[BITS(state->distbits)]; @@ -1071,13 +1000,14 @@ int ZEXPORT inflate(z_streamp strm, int flush) DROPBITS(here.bits); state->back += here.bits; if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; + strm->msg = (z_const char *)"invalid distance code"; state->mode = BAD; break; } state->offset = (unsigned)here.val; state->extra = (unsigned)(here.op) & 15; state->mode = DISTEXT; + /* fallthrough */ case DISTEXT: if (state->extra) { NEEDBITS(state->extra); @@ -1087,13 +1017,14 @@ int ZEXPORT inflate(z_streamp strm, int flush) } #ifdef INFLATE_STRICT if (state->offset > state->dmax) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = (z_const char *)"invalid distance too far back"; state->mode = BAD; break; } #endif Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; + /* fallthrough */ case MATCH: if (left == 0) goto inf_leave; copy = out - left; @@ -1101,7 +1032,8 @@ int ZEXPORT inflate(z_streamp strm, int flush) copy = state->offset - copy; if (copy > state->whave) { if (state->sane) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = (z_const char *) + "invalid distance too far back"; state->mode = BAD; break; } @@ -1151,16 +1083,16 @@ int ZEXPORT inflate(z_streamp strm, int flush) out -= left; strm->total_out += out; state->total += out; - if (out) + if ((state->wrap & 4) && out) strm->adler = state->check = - UPDATE(state->check, put - out, out); + UPDATE_CHECK(state->check, put - out, out); out = left; - if (( + if ((state->wrap & 4) && ( #ifdef GUNZIP state->flags ? hold : #endif - REVERSE(hold)) != state->check) { - strm->msg = (char *)"incorrect data check"; + ZSWAP32(hold)) != state->check) { + strm->msg = (z_const char *)"incorrect data check"; state->mode = BAD; break; } @@ -1169,11 +1101,12 @@ int ZEXPORT inflate(z_streamp strm, int flush) } #ifdef GUNZIP state->mode = LENGTH; + /* fallthrough */ case LENGTH: if (state->wrap && state->flags) { NEEDBITS(32); - if (hold != (state->total & 0xffffffffUL)) { - strm->msg = (char *)"incorrect length check"; + if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { + strm->msg = (z_const char *)"incorrect length check"; state->mode = BAD; break; } @@ -1182,6 +1115,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) } #endif state->mode = DONE; + /* fallthrough */ case DONE: ret = Z_STREAM_END; goto inf_leave; @@ -1191,6 +1125,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) case MEM: return Z_MEM_ERROR; case SYNC: + /* fallthrough */ default: return Z_STREAM_ERROR; } @@ -1203,8 +1138,9 @@ int ZEXPORT inflate(z_streamp strm, int flush) */ inf_leave: RESTORE(); - if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) - if (updatewindow(strm, out)) { + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { state->mode = MEM; return Z_MEM_ERROR; } @@ -1213,10 +1149,10 @@ int ZEXPORT inflate(z_streamp strm, int flush) strm->total_in += in; strm->total_out += out; state->total += out; - if (state->wrap && out) + if ((state->wrap & 4) && out) strm->adler = state->check = - UPDATE(state->check, strm->next_out - out, out); - strm->data_type = state->bits + (state->last ? 64 : 0) + + UPDATE_CHECK(state->check, strm->next_out - out, out); + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) @@ -1224,10 +1160,9 @@ int ZEXPORT inflate(z_streamp strm, int flush) return ret; } -int ZEXPORT inflateEnd(z_streamp strm) -{ +int ZEXPORT inflateEnd(z_streamp strm) { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->window != Z_NULL) ZFREE(strm, state->window); @@ -1237,51 +1172,63 @@ int ZEXPORT inflateEnd(z_streamp strm) return Z_OK; } -int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength) -{ +int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary, + uInt *dictLength) { + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, + uInt dictLength) { struct inflate_state FAR *state; - unsigned long id; + unsigned long dictid; + int ret; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; - /* check for correct dictionary id */ + /* check for correct dictionary identifier */ if (state->mode == DICT) { - id = adler32(0L, Z_NULL, 0); - id = adler32(id, dictionary, dictLength); - if (id != state->check) + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) return Z_DATA_ERROR; } - /* copy dictionary to window */ - if (updatewindow(strm, strm->avail_out)) { + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { state->mode = MEM; return Z_MEM_ERROR; } - if (dictLength > state->wsize) { - zmemcpy(state->window, dictionary + dictLength - state->wsize, - state->wsize); - state->whave = state->wsize; - } - else { - zmemcpy(state->window + state->wsize - dictLength, dictionary, - dictLength); - state->whave = dictLength; - } state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; } -int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) -{ +int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) { struct inflate_state FAR *state; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; @@ -1302,8 +1249,8 @@ int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) called again with more data and the *have state. *have is initialized to zero for the first call. */ -local unsigned syncsearch(unsigned FAR *have, unsigned char FAR *buf, unsigned len) -{ +local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf, + unsigned len) { unsigned got; unsigned next; @@ -1322,22 +1269,22 @@ local unsigned syncsearch(unsigned FAR *have, unsigned char FAR *buf, unsigned l return next; } -int ZEXPORT inflateSync(z_streamp strm) -{ +int ZEXPORT inflateSync(z_streamp strm) { unsigned len; /* number of bytes to look at or looked at */ + int flags; /* temporary to save header status */ unsigned long in, out; /* temporary to save total_in and total_out */ unsigned char buf[4]; /* to restore bit buffer to byte string */ struct inflate_state FAR *state; /* check parameters */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; /* if first time, start search in bit buffer */ if (state->mode != SYNC) { state->mode = SYNC; - state->hold <<= state->bits & 7; + state->hold >>= state->bits & 7; state->bits -= state->bits & 7; len = 0; while (state->bits >= 8) { @@ -1357,9 +1304,15 @@ int ZEXPORT inflateSync(z_streamp strm) /* return no joy or set up to restart inflate() on a new block */ if (state->have != 4) return Z_DATA_ERROR; + if (state->flags == -1) + state->wrap = 0; /* if no header yet, treat as raw */ + else + state->wrap &= ~4; /* no point in computing a check value now */ + flags = state->flags; in = strm->total_in; out = strm->total_out; inflateReset(strm); strm->total_in = in; strm->total_out = out; + state->flags = flags; state->mode = TYPE; return Z_OK; } @@ -1372,25 +1325,21 @@ int ZEXPORT inflateSync(z_streamp strm) block. When decompressing, PPP checks that at the end of input packet, inflate is waiting for these length bytes. */ -int ZEXPORT inflateSyncPoint(z_streamp strm) -{ +int ZEXPORT inflateSyncPoint(z_streamp strm) { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; return state->mode == STORED && state->bits == 0; } -int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) -{ +int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) { struct inflate_state FAR *state; struct inflate_state FAR *copy; unsigned char FAR *window; - unsigned wsize; /* check input */ - if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || - source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + if (inflateStateCheck(source) || dest == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)source->state; @@ -1398,6 +1347,7 @@ int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) copy = (struct inflate_state FAR *) ZALLOC(source, 1, sizeof(struct inflate_state)); if (copy == Z_NULL) return Z_MEM_ERROR; + zmemzero(copy, sizeof(struct inflate_state)); window = Z_NULL; if (state->window != Z_NULL) { window = (unsigned char FAR *) @@ -1411,47 +1361,64 @@ int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) /* copy state */ zmemcpy(dest, source, sizeof(z_stream)); zmemcpy(copy, state, sizeof(struct inflate_state)); + copy->strm = dest; if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); copy->distcode = copy->codes + (state->distcode - state->codes); } copy->next = copy->codes + (state->next - state->codes); - if (window != Z_NULL) { - wsize = 1U << state->wbits; - zmemcpy(window, state->window, wsize); - } + if (window != Z_NULL) + zmemcpy(window, state->window, state->whave); copy->window = window; dest->state = (struct internal_state FAR *)copy; return Z_OK; } -int ZEXPORT inflateUndermine(z_streamp strm, int subvert) -{ +int ZEXPORT inflateUndermine(z_streamp strm, int subvert) { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; - state->sane = !subvert; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; return Z_OK; #else + (void)subvert; state->sane = 1; return Z_DATA_ERROR; #endif } -long ZEXPORT inflateMark(z_streamp strm) -{ +int ZEXPORT inflateValidate(z_streamp strm, int check) { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return -(1L << 16); + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; - return ((long)(state->back) << 16) + + if (check && state->wrap) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + +long ZEXPORT inflateMark(z_streamp strm) { + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) + return -(1L << 16); + state = (struct inflate_state FAR *)strm->state; + return (long)(((unsigned long)((long)state->back)) << 16) + (state->mode == COPY ? state->length : (state->mode == MATCH ? state->was - state->length : 0)); } +unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) { + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +} ABC_NAMESPACE_IMPL_END diff --git a/src/misc/zlib/inflate.h b/src/misc/zlib/inflate.h index e58b57768f..55247c2897 100644 --- a/src/misc/zlib/inflate.h +++ b/src/misc/zlib/inflate.h @@ -1,15 +1,16 @@ /* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2009 Mark Adler + * Copyright (C) 1995-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ +ABC_NAMESPACE_HEADER_START + + /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ -ABC_NAMESPACE_HEADER_START - /* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip decoding @@ -20,7 +21,7 @@ ABC_NAMESPACE_HEADER_START /* Possible inflate modes between inflate() calls */ typedef enum { - HEAD, /* i: waiting for magic header */ + HEAD = 16180, /* i: waiting for magic header */ FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ @@ -79,13 +80,17 @@ typedef enum { CHECK -> LENGTH -> DONE */ -/* state maintained between inflate() calls. Approximately 10K bytes. */ +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ struct inflate_state { + z_streamp strm; /* pointer back to this zlib stream */ inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ int havedict; /* true if dictionary provided */ - int flags; /* gzip header method and flags (0 if zlib) */ + int flags; /* gzip header method and flags, 0 if zlib, or + -1 if raw or no header yet */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ unsigned long check; /* protected copy of check value */ unsigned long total; /* protected copy of output count */ @@ -98,7 +103,7 @@ struct inflate_state { unsigned char FAR *window; /* allocated sliding window, if needed */ /* bit accumulator */ unsigned long hold; /* input bit accumulator */ - unsigned bits; /* number of bits in "in" */ + unsigned bits; /* number of bits in hold */ /* for string and stored block copying */ unsigned length; /* literal or length of data to copy */ unsigned offset; /* distance back to copy string from */ diff --git a/src/misc/zlib/inftrees.c b/src/misc/zlib/inftrees.c index f3835cfcdb..15eba41032 100644 --- a/src/misc/zlib/inftrees.c +++ b/src/misc/zlib/inftrees.c @@ -1,8 +1,17 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2010 Mark Adler + * Copyright (C) 1995-2026 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif +#ifdef BUILDFIXED +# define Z_ONCE +#endif + #include #include #include @@ -10,13 +19,19 @@ #include "zutil.h" #include "inftrees.h" +#include "inflate.h" ABC_NAMESPACE_IMPL_START + +#ifndef NULL +# define NULL 0 +#endif + #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; + " inflate 1.3.2 Copyright 1995-2026 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -36,8 +51,9 @@ const char inflate_copyright[] = table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ -int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work) -{ +int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work) { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ unsigned min, max; /* minimum and maximum code lengths */ @@ -53,9 +69,9 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigne unsigned mask; /* mask for low root bits */ code here; /* table entry for duplication */ code FAR *next; /* next available space in table */ - const unsigned short FAR *base; /* base value table to use */ - const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ + const unsigned short FAR *base = NULL; /* base value table to use */ + const unsigned short FAR *extra = NULL; /* extra bits table to use */ + unsigned match = 0; /* use base and extra for symbol >= match */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ @@ -63,7 +79,7 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigne 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 75}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, @@ -181,20 +197,16 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigne /* set up for code type */ switch (type) { case CODES: - base = extra = work; /* dummy value--not used */ - end = 19; + match = 20; break; case LENS: base = lbase; - base -= 257; extra = lext; - extra -= 257; - end = 256; + match = 257; break; - default: /* DISTS */ + case DISTS: base = dbase; extra = dext; - end = -1; } /* initialize state for loop */ @@ -209,21 +221,21 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigne mask = used - 1; /* mask for comparing low */ /* check available table space */ - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) return 1; /* process all codes and make table entries */ for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { + if (work[sym] + 1U < match) { here.op = (unsigned char)0; here.val = work[sym]; } - else if ((int)(work[sym]) > end) { - here.op = (unsigned char)(extra[work[sym]]); - here.val = base[work[sym]]; + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ @@ -278,8 +290,8 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigne /* check for enough space */ used += 1U << curr; - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) return 1; /* point entry in root table to sub-table */ @@ -290,38 +302,14 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigne } } - /* - Fill in rest of table for incomplete codes. This loop is similar to the - loop above in incrementing huff for table indices. It is assumed that - len is equal to curr + drop, so there is no loop needed to increment - through high index bits. When the current sub-table is filled, the loop - drops back to the root table to fill in any remaining entries there. - */ - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)(len - drop); - here.val = (unsigned short)0; - while (huff != 0) { - /* when done with sub-table, drop back to root table */ - if (drop != 0 && (huff & mask) != low) { - drop = 0; - len = root; - next = *table; - here.bits = (unsigned char)len; - } - - /* put invalid code marker in table */ - next[huff >> drop] = here; - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; } /* set return parameters */ @@ -330,8 +318,117 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigne return 0; } +#ifdef BUILDFIXED +/* + If this is compiled with BUILDFIXED defined, and if inflate will be used in + multiple threads, and if atomics are not available, then inflate() must be + called with a fixed block (e.g. 0x03 0x00) to initialize the tables and must + return before any other threads are allowed to call inflate. + */ +static code *lenfix, *distfix; +static code fixed[544]; + +/* State for z_once(). */ +local z_once_t built = Z_ONCE_INIT; + +local void buildtables(void) { + unsigned sym, bits; + static code *next; + unsigned short lens[288], work[288]; + + /* literal/length table */ + sym = 0; + while (sym < 144) lens[sym++] = 8; + while (sym < 256) lens[sym++] = 9; + while (sym < 280) lens[sym++] = 7; + while (sym < 288) lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, lens, 288, &(next), &(bits), work); + + /* distance table */ + sym = 0; + while (sym < 32) lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, lens, 32, &(next), &(bits), work); +} +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications if atomics are not available, as it will + not be thread-safe. + */ +void inflate_fixed(struct inflate_state FAR *state) { +#ifdef BUILDFIXED + z_once(&built, buildtables); +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} ABC_NAMESPACE_IMPL_END +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that will be #include'd above. Defining MAKEFIXED + also defines BUILDFIXED, so the tables are built on the fly. main() writes + those tables to stdout, which would directed to inffixed.h. Compile this + along with zutil.c: + cc -DMAKEFIXED -o fix inftrees.c zutil.c + ./fix > inffixed.h + */ +int main(void) { + unsigned low, size; + struct inflate_state state; + + inflate_fixed(&state); + puts("/* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts("/* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf("static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n};"); + size = 1U << 5; + printf("\nstatic const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n};"); + return 0; +} +#endif /* MAKEFIXED */ diff --git a/src/misc/zlib/inftrees.h b/src/misc/zlib/inftrees.h index 8aed88570a..1fd22c90e5 100644 --- a/src/misc/zlib/inftrees.h +++ b/src/misc/zlib/inftrees.h @@ -1,15 +1,16 @@ /* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2005, 2010 Mark Adler + * Copyright (C) 1995-2026 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ +ABC_NAMESPACE_HEADER_START + + /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ -ABC_NAMESPACE_HEADER_START - /* Structure for decoding tables. Each entry provides either the information needed to do the operation requested by the code that indexed that table entry, or it provides a pointer to another @@ -40,11 +41,11 @@ typedef struct { /* Maximum size of the dynamic table. The maximum number of code structures is 1444, which is the sum of 852 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribtution. The arguments to that + examples/enough.c found in the zlib distribution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 30 6 15" for distance codes returns 592. - The initial root table size (9 or 6) is found in the fifth argument of the + returns 852, and "enough 30 6 15" for distance codes returns 592. The + initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and updated. */ @@ -59,8 +60,10 @@ typedef enum { DISTS } codetype; -int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); +int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work); +struct inflate_state; +void ZLIB_INTERNAL inflate_fixed(struct inflate_state FAR *state); ABC_NAMESPACE_HEADER_END diff --git a/src/misc/zlib/trees.c b/src/misc/zlib/trees.c index cb2e6c677d..fbf38b58d5 100644 --- a/src/misc/zlib/trees.c +++ b/src/misc/zlib/trees.c @@ -1,5 +1,5 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2010 Jean-loup Gailly + * Copyright (C) 1995-2026 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -41,12 +41,13 @@ #include "deflate.h" -#ifdef DEBUG +ABC_NAMESPACE_IMPL_START + + +#ifdef ZLIB_DEBUG # include #endif -ABC_NAMESPACE_IMPL_START - /* =========================================================================== * Constants */ @@ -81,11 +82,6 @@ local const uch bl_order[BL_CODES] * probability, to avoid transmitting the lengths for unused bit length codes. */ -#define Buf_size (8 * 2*sizeof(char)) -/* Number of bits used within bi_buf. (bi_buf might be implemented on - * more than 16 bits on some systems.) - */ - /* =========================================================================== * Local data. These are initialized only once. */ @@ -123,10 +119,8 @@ local int base_dist[D_CODES]; /* First normalized distance for each code (0 = distance of 1) */ #else -ABC_NAMESPACE_IMPL_END # include "trees.h" -ABC_NAMESPACE_IMPL_START -#endif /* GEN_TREES_H */ +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ struct static_tree_desc_s { const ct_data *static_tree; /* static tree or NULL */ @@ -136,77 +130,141 @@ struct static_tree_desc_s { int max_length; /* max bit length for the codes */ }; -local static_tree_desc static_l_desc = +#ifdef NO_INIT_GLOBAL_POINTERS +# define TCONST +#else +# define TCONST const +#endif + +local TCONST static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; -local static_tree_desc static_d_desc = +local TCONST static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; -local static_tree_desc static_bl_desc = +local TCONST static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== - * Local (static) routines in this file. + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(unsigned code, int len) { + unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(deflate_state *s) { + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(deflate_state *s) { + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_used = ((s->bi_valid - 1) & 7) + 1; + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef ZLIB_DEBUG + s->bits_sent = (s->bits_sent + 7) & ~(ulg)7; +#endif +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. */ +local void gen_codes(ct_data *tree, int max_code, ushf *bl_count) { + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + unsigned code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ -local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local int build_bl_tree OF((deflate_state *s)); -local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); -local void compress_block OF((deflate_state *s, ct_data *ltree, - ct_data *dtree)); -local int detect_data_type OF((deflate_state *s)); -local unsigned bi_reverse OF((unsigned value, int length)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); -local void copy_block OF((deflate_state *s, charf *buf, unsigned len, - int header)); + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + code = (code + bl_count[bits - 1]) << 1; + next_code[bits] = (ush)code; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1, + "inconsistent bit counts"); + Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n].Len; + if (len == 0) continue; + /* Now reverse the bits */ + tree[n].Code = (ush)bi_reverse(next_code[len]++, len); + + Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", + n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1)); + } +} #ifdef GEN_TREES_H -local void gen_trees_header OF((void)); +local void gen_trees_header(void); #endif -#ifndef DEBUG +#ifndef ZLIB_DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ -#else /* DEBUG */ +#else /* !ZLIB_DEBUG */ # define send_code(s, c, tree) \ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, tree[c].Code, tree[c].Len); } #endif -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - /* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ -#ifdef DEBUG -local void send_bits OF((deflate_state *s, int value, int length)); - -local void send_bits(deflate_state *s, int value, int length) -{ +#ifdef ZLIB_DEBUG +local void send_bits(deflate_state *s, int value, int length) { Tracevv((stderr," l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); s->bits_sent += (ulg)length; /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid)) * unused bits in value. */ if (s->bi_valid > (int)Buf_size - length) { @@ -219,12 +277,12 @@ local void send_bits(deflate_state *s, int value, int length) s->bi_valid += length; } } -#else /* !DEBUG */ +#else /* !ZLIB_DEBUG */ #define send_bits(s, value, length) \ { int len = length;\ if (s->bi_valid > (int)Buf_size - len) {\ - int val = value;\ + int val = (int)value;\ s->bi_buf |= (ush)val << s->bi_valid;\ put_short(s, s->bi_buf);\ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ @@ -234,7 +292,7 @@ local void send_bits(deflate_state *s, int value, int length) s->bi_valid += len;\ }\ } -#endif /* DEBUG */ +#endif /* ZLIB_DEBUG */ /* the arguments must not have side effects */ @@ -242,8 +300,7 @@ local void send_bits(deflate_state *s, int value, int length) /* =========================================================================== * Initialize the various 'constant' tables. */ -local void tr_static_init() -{ +local void tr_static_init(void) { #if defined(GEN_TREES_H) || !defined(STDC) static int static_init_done = 0; int n; /* iterates over tree elements */ @@ -269,7 +326,7 @@ local void tr_static_init() length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { _dist_code[256 + dist++] = (uch)code; } } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); + Assert (dist == 256, "tr_static_init: 256 + dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; @@ -325,21 +382,18 @@ local void tr_static_init() } /* =========================================================================== - * Genererate the file trees.h describing the static trees. + * Generate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H -# ifndef DEBUG -ABC_NAMESPACE_IMPL_END +# ifndef ZLIB_DEBUG # include -ABC_NAMESPACE_IMPL_START # endif # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) + ((i) % (width) == (width) - 1 ? ",\n" : ", ")) -void gen_trees_header() -{ +void gen_trees_header(void) { FILE *header = fopen("trees.h", "w"); int i; @@ -388,11 +442,26 @@ void gen_trees_header() } #endif /* GEN_TREES_H */ +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(deflate_state *s) { + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->sym_next = s->matches = 0; +} + /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ -void ZLIB_INTERNAL _tr_init(deflate_state *s) -{ +void ZLIB_INTERNAL _tr_init(deflate_state *s) { tr_static_init(); s->l_desc.dyn_tree = s->dyn_ltree; @@ -406,8 +475,8 @@ void ZLIB_INTERNAL _tr_init(deflate_state *s) s->bi_buf = 0; s->bi_valid = 0; - s->last_eob_len = 8; /* enough lookahead for inflate */ -#ifdef DEBUG + s->bi_used = 0; +#ifdef ZLIB_DEBUG s->compressed_len = 0L; s->bits_sent = 0L; #endif @@ -416,23 +485,6 @@ void ZLIB_INTERNAL _tr_init(deflate_state *s) init_block(s); } -/* =========================================================================== - * Initialize a new block. - */ -local void init_block(deflate_state *s) -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; -} - #define SMALLEST 1 /* Index within the heap array of least frequent node in the Huffman tree */ @@ -462,14 +514,13 @@ local void init_block(deflate_state *s) * when the heap property is re-established (each father smaller than its * two sons). */ -local void pqdownheap(deflate_state *s, ct_data *tree, int k) -{ +local void pqdownheap(deflate_state *s, ct_data *tree, int k) { int v = s->heap[k]; int j = k << 1; /* left son of k */ while (j <= s->heap_len) { /* Set j to the smallest of the two sons: */ if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) { j++; } /* Exit if v is smaller than both sons */ @@ -494,8 +545,7 @@ local void pqdownheap(deflate_state *s, ct_data *tree, int k) * The length opt_len is updated; static_len is also updated if stree is * not null. */ -local void gen_bitlen(deflate_state *s, tree_desc *desc) -{ +local void gen_bitlen(deflate_state *s, tree_desc *desc) { ct_data *tree = desc->dyn_tree; int max_code = desc->max_code; const ct_data *stree = desc->stat_desc->static_tree; @@ -516,7 +566,7 @@ local void gen_bitlen(deflate_state *s, tree_desc *desc) */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + for (h = s->heap_max + 1; h < HEAP_SIZE; h++) { n = s->heap[h]; bits = tree[tree[n].Dad].Len + 1; if (bits > max_length) bits = max_length, overflow++; @@ -527,22 +577,22 @@ local void gen_bitlen(deflate_state *s, tree_desc *desc) s->bl_count[bits]++; xbits = 0; - if (n >= base) xbits = extra[n-base]; + if (n >= base) xbits = extra[n - base]; f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + s->opt_len += (ulg)f * (unsigned)(bits + xbits); + if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); } if (overflow == 0) return; - Trace((stderr,"\nbit length overflow\n")); + Tracev((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ do { - bits = max_length-1; + bits = max_length - 1; while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */ s->bl_count[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] @@ -561,9 +611,8 @@ local void gen_bitlen(deflate_state *s, tree_desc *desc) m = s->heap[--h]; if (m > max_code) continue; if ((unsigned) tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; + Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq; tree[m].Len = (ush)bits; } n--; @@ -571,47 +620,9 @@ local void gen_bitlen(deflate_state *s, tree_desc *desc) } } -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes (ct_data *tree, int max_code, ushf *bl_count) - /* the tree to decorate */ - /* largest code with non zero frequency */ - /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS]-1 == (1< +#endif /* =========================================================================== * Construct one Huffman tree and assigns the code bit strings and lengths. @@ -621,8 +632,7 @@ local void gen_codes (ct_data *tree, int max_code, ushf *bl_count) * and corresponding code. The length opt_len is updated; static_len is * also updated if stree is not null. The field max_code is set. */ -local void build_tree(deflate_state *s, tree_desc *desc) -{ +local void build_tree(deflate_state *s, tree_desc *desc) { ct_data *tree = desc->dyn_tree; const ct_data *stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; @@ -631,7 +641,7 @@ local void build_tree(deflate_state *s, tree_desc *desc) int node; /* new node being created */ /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n + 1]. * heap[0] is not used. */ s->heap_len = 0, s->heap_max = HEAP_SIZE; @@ -659,7 +669,7 @@ local void build_tree(deflate_state *s, tree_desc *desc) } desc->max_code = max_code; - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); @@ -707,8 +717,7 @@ local void build_tree(deflate_state *s, tree_desc *desc) * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ -local void scan_tree (deflate_state *s, ct_data *tree, int max_code) -{ +local void scan_tree(deflate_state *s, ct_data *tree, int max_code) { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ @@ -718,14 +727,14 @@ local void scan_tree (deflate_state *s, ct_data *tree, int max_code) int min_count = 4; /* min repeat count */ if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ + tree[max_code + 1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; + curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; + s->bl_tree[curlen].Freq += (ush)count; } else if (curlen != 0) { if (curlen != prevlen) s->bl_tree[curlen].Freq++; s->bl_tree[REP_3_6].Freq++; @@ -749,8 +758,7 @@ local void scan_tree (deflate_state *s, ct_data *tree, int max_code) * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ -local void send_tree (deflate_state *s, ct_data *tree, int max_code) -{ +local void send_tree(deflate_state *s, ct_data *tree, int max_code) { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ @@ -759,11 +767,11 @@ local void send_tree (deflate_state *s, ct_data *tree, int max_code) int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ - /* tree[max_code+1].Len = -1; */ /* guard already set */ + /* tree[max_code + 1].Len = -1; */ /* guard already set */ if (nextlen == 0) max_count = 138, min_count = 3; for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; + curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { @@ -774,13 +782,13 @@ local void send_tree (deflate_state *s, ct_data *tree, int max_code) send_code(s, curlen, s->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2); } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3); } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { @@ -797,8 +805,7 @@ local void send_tree (deflate_state *s, ct_data *tree, int max_code) * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */ -local int build_bl_tree(deflate_state *s) -{ +local int build_bl_tree(deflate_state *s) { int max_blindex; /* index of last bit length code of non zero freq */ /* Determine the bit length frequencies for literal and distance trees */ @@ -807,8 +814,8 @@ local int build_bl_tree(deflate_state *s) /* Build the bit length tree: */ build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + /* opt_len now includes the length of the tree representations, except the + * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts. */ /* Determine the number of bit length codes to send. The pkzip format @@ -819,8 +826,8 @@ local int build_bl_tree(deflate_state *s) if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; - Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4; + Tracev((stderr, "\ndyn trees: dyn %lu, stat %lu", s->opt_len, s->static_len)); return max_blindex; @@ -831,84 +838,172 @@ local int build_bl_tree(deflate_state *s) * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ -local void send_all_trees(deflate_state *s, int lcodes, int dcodes, int blcodes) -{ +local void send_all_trees(deflate_state *s, int lcodes, int dcodes, + int blcodes) { int rank; /* index in bl_order */ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ for (rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); } - Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + Tracev((stderr, "\nbl tree: sent %lu", s->bits_sent)); - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %lu", s->bits_sent)); - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); + send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %lu", s->bits_sent)); } /* =========================================================================== * Send a stored block */ -void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, ulg stored_len, int last) -{ - send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ -#ifdef DEBUG +void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, + ulg stored_len, int last) { + send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */ + bi_windup(s); /* align on byte boundary */ + put_short(s, (ush)stored_len); + put_short(s, (ush)~stored_len); + if (stored_len) + zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len); + s->pending += stored_len; +#ifdef ZLIB_DEBUG s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; + s->bits_sent += 2*16; + s->bits_sent += stored_len << 3; #endif - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) + */ +void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s) { + bi_flush(s); } /* =========================================================================== * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. - * The current inflate code requires 9 bits of lookahead. If the - * last two codes for the previous block (real code plus EOB) were coded - * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode - * the last real code. In this case we send two empty static blocks instead - * of one. (There are no problems if the previous block is stored or fixed.) - * To simplify the code, we assume the worst case of last real code encoded - * on one bit only. */ -void ZLIB_INTERNAL _tr_align(deflate_state *s) -{ +void ZLIB_INTERNAL _tr_align(deflate_state *s) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); - /* Of the 10 bits for the empty block, we have already sent - * (10 - bi_valid) bits. The lookahead for the last real code (before - * the EOB of the previous block) was thus at least one plus the length - * of the EOB plus what we have just sent of the empty static block. - */ - if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(deflate_state *s, const ct_data *ltree, + const ct_data *dtree) { + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned sx = 0; /* running index in symbol buffers */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->sym_next != 0) do { +#ifdef LIT_MEM + dist = s->d_buf[sx]; + lc = s->l_buf[sx++]; +#else + dist = s->sym_buf[sx++] & 0xff; + dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; + lc = s->sym_buf[sx++]; #endif - bi_flush(s); - } - s->last_eob_len = 7; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code + LITERALS + 1, ltree); /* send length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= (unsigned)base_dist[code]; + send_bits(s, (int)dist, extra); /* send the extra bits */ + } + } /* literal or match pair ? */ + + /* Check for no overlay of pending_buf on needed symbols */ +#ifdef LIT_MEM + Assert(s->pending < 2 * (s->lit_bufsize + sx), "pendingBuf overflow"); +#else + Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); +#endif + + } while (sx < s->sym_next); + + send_code(s, END_BLOCK, ltree); +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "block list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(deflate_state *s) { + /* block_mask is the bit mask of block-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long block_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("block-listed") bytes. */ + for (n = 0; n <= 31; n++, block_mask >>= 1) + if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("allow-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "block-listed" or "allow-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; } /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. + * trees or store, and write out the encoded block. */ -void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int last) -{ +void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, + ulg stored_len, int last) { ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex = 0; /* index of last bit length code of non zero freq */ @@ -921,11 +1016,11 @@ void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, /* Construct the literal and distance trees */ build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + Tracev((stderr, "\nlit data: dyn %lu, stat %lu", s->opt_len, s->static_len)); build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + Tracev((stderr, "\ndist data: dyn %lu, stat %lu", s->opt_len, s->static_len)); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. @@ -937,14 +1032,17 @@ void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, max_blindex = build_bl_tree(s); /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; + opt_lenb = (s->opt_len + 3 + 7) >> 3; + static_lenb = (s->static_len + 3 + 7) >> 3; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); + s->sym_next / 3)); - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; +#ifndef FORCE_STATIC + if (static_lenb <= opt_lenb || s->strategy == Z_FIXED) +#endif + opt_lenb = static_lenb; } else { Assert(buf != (char*)0, "lost buf"); @@ -954,7 +1052,7 @@ void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, #ifdef FORCE_STORED if (buf != (char*)0) { /* force stored block */ #else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { + if (stored_len + 4 <= opt_lenb && buf != (char*)0) { /* 4: two words for the lengths */ #endif /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. @@ -965,22 +1063,20 @@ void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, */ _tr_stored_block(s, buf, stored_len, last); -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+last, 3); - compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); -#ifdef DEBUG + } else if (static_lenb == opt_lenb) { + send_bits(s, (STATIC_TREES<<1) + last, 3); + compress_block(s, (const ct_data *)static_ltree, + (const ct_data *)static_dtree); +#ifdef ZLIB_DEBUG s->compressed_len += 3 + s->static_len; #endif } else { - send_bits(s, (DYN_TREES<<1)+last, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); - compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); -#ifdef DEBUG + send_bits(s, (DYN_TREES<<1) + last, 3); + send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1, + max_blindex + 1); + compress_block(s, (const ct_data *)s->dyn_ltree, + (const ct_data *)s->dyn_dtree); +#ifdef ZLIB_DEBUG s->compressed_len += 3 + s->opt_len; #endif } @@ -992,22 +1088,27 @@ void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, if (last) { bi_windup(s); -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->compressed_len += 7; /* align on byte boundary */ #endif } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*last)); + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3, + s->compressed_len - 7*(ulg)last)); } /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ -int ZLIB_INTERNAL _tr_tally (deflate_state *s, unsigned dist, unsigned lc) -{ - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; +int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) { +#ifdef LIT_MEM + s->d_buf[s->sym_next] = (ush)dist; + s->l_buf[s->sym_next++] = (uch)lc; +#else + s->sym_buf[s->sym_next++] = (uch)dist; + s->sym_buf[s->sym_next++] = (uch)(dist >> 8); + s->sym_buf[s->sym_next++] = (uch)lc; +#endif if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; @@ -1019,198 +1120,11 @@ int ZLIB_INTERNAL _tr_tally (deflate_state *s, unsigned dist, unsigned lc) (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } - -#ifdef TRUNCATE_BLOCK - /* Try to guess if it is profitable to stop the current block here */ - if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } -#endif - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ + return (s->sym_next == s->sym_end); } -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -local void compress_block(deflate_state *s, ct_data *ltree, ct_data *dtree) -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - "pendingBuf overflow"); - - } while (lx < s->last_lit); - - send_code(s, END_BLOCK, ltree); - s->last_eob_len = ltree[END_BLOCK].Len; -} - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -local int detect_data_type(deflate_state *s) -{ - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - unsigned long black_mask = 0xf3ffc07fUL; - int n; - - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>= 1) - if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) - return Z_BINARY; - - /* Check for textual ("white-listed") bytes. */ - if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 - || s->dyn_ltree[13].Freq != 0) - return Z_TEXT; - for (n = 32; n < LITERALS; n++) - if (s->dyn_ltree[n].Freq != 0) - return Z_TEXT; - - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -local unsigned bi_reverse(unsigned code, int len) -{ - unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -local void bi_flush(deflate_state *s) -{ - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -local void bi_windup(deflate_state *s) -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; -#endif -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -local void copy_block(deflate_state *s, charf *buf, unsigned len, int header) -{ - bi_windup(s); /* align on byte boundary */ - s->last_eob_len = 8; /* enough lookahead for inflate */ - - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); -#ifdef DEBUG - s->bits_sent += 2*16; -#endif - } -#ifdef DEBUG - s->bits_sent += (ulg)len<<3; -#endif - while (len--) { - put_byte(s, *buf++); - } -} - - - ABC_NAMESPACE_IMPL_END - diff --git a/src/misc/zlib/trees.h b/src/misc/zlib/trees.h index 8629d66e4c..d35639d82a 100644 --- a/src/misc/zlib/trees.h +++ b/src/misc/zlib/trees.h @@ -1,7 +1,5 @@ /* header created automatically with -DGEN_TREES_H */ -ABC_NAMESPACE_HEADER_START - local const ct_data static_ltree[L_CODES+2] = { {{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, {{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, @@ -128,5 +126,3 @@ local const int base_dist[D_CODES] = { 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 }; -ABC_NAMESPACE_HEADER_END - diff --git a/src/misc/zlib/uncompr.c b/src/misc/zlib/uncompr.c index fedb3ed2b0..831c913a3e 100644 --- a/src/misc/zlib/uncompr.c +++ b/src/misc/zlib/uncompr.c @@ -1,67 +1,112 @@ /* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. + * Copyright (C) 1995-2026 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ +#define ZLIB_INTERNAL #include #include #include #include "misc/util/abc_global.h" -#define ZLIB_INTERNAL #include "zlib.h" ABC_NAMESPACE_IMPL_START + /* =========================================================================== - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. + Decompresses the source buffer into the destination buffer. *sourceLen is + the byte length of the source buffer. Upon entry, *destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, + *destLen is the size of the decompressed data and *sourceLen is the number + of source bytes consumed. Upon return, source + *sourceLen points to the + first unused input byte. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, or + Z_DATA_ERROR if the input data was corrupted, including if the input data is + an incomplete zlib stream. + + The _z versions of the functions take size_t length arguments. */ -int ZEXPORT uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) -{ +int ZEXPORT uncompress2_z(Bytef *dest, z_size_t *destLen, const Bytef *source, + z_size_t *sourceLen) { z_stream stream; int err; + const uInt max = (uInt)-1; + z_size_t len, left; - stream.next_in = (Bytef*)source; - stream.avail_in = (uInt)sourceLen; - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + if (sourceLen == NULL || (*sourceLen > 0 && source == NULL) || + destLen == NULL || (*destLen > 0 && dest == NULL)) + return Z_STREAM_ERROR; - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + len = *sourceLen; + left = *destLen; + if (left == 0 && dest == Z_NULL) + dest = (Bytef *)&stream.reserved; /* next_out cannot be NULL */ + stream.next_in = (z_const Bytef *)source; + stream.avail_in = 0; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; err = inflateInit(&stream); if (err != Z_OK) return err; - err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) - return Z_DATA_ERROR; - return err; - } - *destLen = stream.total_out; - - err = inflateEnd(&stream); - return err; + stream.next_out = dest; + stream.avail_out = 0; + + do { + if (stream.avail_out == 0) { + stream.avail_out = left > (z_size_t)max ? max : (uInt)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = len > (z_size_t)max ? max : (uInt)len; + len -= stream.avail_in; + } + err = inflate(&stream, Z_NO_FLUSH); + } while (err == Z_OK); + + /* Set len and left to the unused input data and unused output space. Set + *sourceLen to the amount of input consumed. Set *destLen to the amount + of data produced. */ + len += stream.avail_in; + left += stream.avail_out; + *sourceLen -= len; + *destLen -= left; + + inflateEnd(&stream); + return err == Z_STREAM_END ? Z_OK : + err == Z_NEED_DICT ? Z_DATA_ERROR : + err == Z_BUF_ERROR && len == 0 ? Z_DATA_ERROR : + err; +} +int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong *sourceLen) { + int ret; + z_size_t got = *destLen, used = *sourceLen; + ret = uncompress2_z(dest, &got, source, &used); + *sourceLen = (uLong)used; + *destLen = (uLong)got; + return ret; +} +int ZEXPORT uncompress_z(Bytef *dest, z_size_t *destLen, const Bytef *source, + z_size_t sourceLen) { + z_size_t used = sourceLen; + return uncompress2_z(dest, destLen, source, &used); +} +int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen) { + uLong used = sourceLen; + return uncompress2(dest, destLen, source, &used); } - - ABC_NAMESPACE_IMPL_END diff --git a/src/misc/zlib/zconf.h b/src/misc/zlib/zconf.h index 30a013b70e..828ca617e9 100644 --- a/src/misc/zlib/zconf.h +++ b/src/misc/zlib/zconf.h @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2010 Jean-loup Gailly. + * Copyright (C) 1995-2026 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -15,11 +15,13 @@ * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET -/* all linked symbols */ +/* all linked symbols and init macros */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits # define _tr_flush_block z__tr_flush_block # define _tr_init z__tr_init # define _tr_stored_block z__tr_stored_block @@ -27,81 +29,122 @@ # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compress_z z_compress_z +# define compress2_z z_compress2_z +# define compressBound z_compressBound +# define compressBound_z z_compressBound_z +# endif # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op +# define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound +# define deflateBound_z z_deflateBound_z # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams +# define deflatePending z_deflatePending # define deflatePrime z_deflatePrime # define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep # define deflateSetDictionary z_deflateSetDictionary # define deflateSetHeader z_deflateSetHeader # define deflateTune z_deflateTune +# define deflateUsed z_deflateUsed # define deflate_copyright z_deflate_copyright # define get_crc_table z_get_crc_table -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit # define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary # define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep # define inflateSetDictionary z_inflateSetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table -# define uncompress z_uncompress +# define inflate_fixed z_inflate_fixed +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# define uncompress_z z_uncompress_z +# define uncompress2_z z_uncompress2_z +# endif # define zError z_zError -# define zcalloc z_zcalloc -# define zcfree z_zcfree +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion @@ -111,7 +154,9 @@ # define alloc_func z_alloc_func # define charf z_charf # define free_func z_free_func -# define gzFile z_gzFile +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif # define gz_header z_gz_header # define gz_headerp z_gz_headerp # define in_func z_in_func @@ -197,9 +242,31 @@ # endif #endif -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL +#ifndef z_const +# ifdef ZLIB_CONST +# define z_const const +# else +# define z_const +# endif +#endif + +#ifdef Z_SOLO +# ifdef _WIN64 + typedef unsigned long long z_size_t; +# else + typedef unsigned long z_size_t; +# endif +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong #endif /* Maximum value for memLevel in deflateInit2 */ @@ -229,7 +296,7 @@ Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ @@ -291,6 +358,9 @@ # ifdef FAR # undef FAR # endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ @@ -356,12 +426,47 @@ typedef uLong FAR uLongf; typedef Byte *voidp; #endif -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#if HAVE_UNISTD_H-0 /* may be set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif +#if HAVE_STDARG_H-0 /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + #ifdef STDC -# include /* for off_t */ +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and @@ -370,46 +475,62 @@ typedef uLong FAR uLongf; * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ -#if -_LARGEFILE64_SOURCE - -1 == 1 +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif -#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ +#ifndef Z_HAVE_UNISTD_H +# if defined(__WATCOMC__) || defined(__GO32__) || \ + (defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)) +# define Z_HAVE_UNISTD_H # endif -# ifndef z_off_t -# define z_off_t off_t +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif # endif #endif -ABC_NAMESPACE_HEADER_START +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif -#ifndef SEEK_SET +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t -# define z_off_t long +# define z_off_t long long #endif -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +#if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t +#elif defined(__MINGW32__) +# define z_off64_t long long +#elif defined(_WIN32) && !defined(__GNUC__) +# define z_off64_t __int64 +#elif defined(__GO32__) +# define z_off64_t offset_t #else # define z_off64_t z_off_t #endif -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf -#endif - /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) #pragma map(deflateInit_,"DEIN") @@ -427,6 +548,4 @@ ABC_NAMESPACE_HEADER_START #pragma map(inflate_copyright,"INCOPY") #endif -ABC_NAMESPACE_HEADER_END - #endif /* ZCONF_H */ diff --git a/src/misc/zlib/zlib.h b/src/misc/zlib/zlib.h index 46c1a1aecb..c2e060a22a 100644 --- a/src/misc/zlib/zlib.h +++ b/src/misc/zlib/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.5, April 19th, 2010 + version 1.3.2, February 17th, 2026 - Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2026 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -24,32 +24,32 @@ The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). + Comments) 1950 to 1952 at https://datatracker.ietf.org/doc/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef ZLIB_H #define ZLIB_H +#ifdef ZLIB_BUILD +# include +#else +# include "zconf.h" +#endif + #include #include #include -#ifndef WIN32 -#include -#endif - #include "misc/util/abc_global.h" -#include "zconf.h" - ABC_NAMESPACE_HEADER_START -#define ZLIB_VERSION "1.2.5" -#define ZLIB_VERNUM 0x1250 +#define ZLIB_VERSION "1.3.2" +#define ZLIB_VERNUM 0x1320 #define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_MINOR 3 +#define ZLIB_VER_REVISION 2 #define ZLIB_VER_SUBREVISION 0 /* @@ -73,7 +73,8 @@ ABC_NAMESPACE_HEADER_START with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - This library can optionally read and write gzip streams in memory as well. + This library can optionally read and write gzip and raw deflate streams in + memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- @@ -82,32 +83,33 @@ ABC_NAMESPACE_HEADER_START The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash - even in case of corrupted input. + even in the case of corrupted input. */ -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); +typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size); +typedef void (*free_func)(voidpf opaque, voidpf address); struct internal_state; typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ + z_const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ + uLong total_in; /* total number of input bytes read so far */ - Bytef *next_out; /* next output byte should be put there */ + Bytef *next_out; /* next output byte will go here */ uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ + uLong total_out; /* total number of bytes output so far */ - char *msg; /* last error message, NULL if no error */ + z_const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; @@ -150,7 +152,9 @@ typedef gz_header FAR *gz_headerp; zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if @@ -163,7 +167,7 @@ typedef gz_header FAR *gz_headerp; The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use in the decompressor (particularly + uncompressed data and may be saved for use by the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ @@ -208,7 +212,7 @@ typedef gz_header FAR *gz_headerp; #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ +/* Possible values of the data_type field for deflate() */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ @@ -221,7 +225,7 @@ typedef gz_header FAR *gz_headerp; /* basic functions */ -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +ZEXTERN const char * ZEXPORT zlibVersion(void); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check @@ -229,12 +233,12 @@ ZEXTERN const char * ZEXPORT zlibVersion OF((void)); */ /* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); +ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default - allocation functions. + allocation functions. total_in, total_out, adler, and msg are initialized. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all @@ -251,7 +255,7 @@ ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); */ -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce @@ -266,11 +270,11 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - - Provide more output starting at next_out and update next_out and avail_out + - Generate more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). Some - output may be provided even if flush is not set. + should be set only when necessary. Some output may be provided even if + flush is zero. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more @@ -279,7 +283,9 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more output + in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to @@ -300,8 +306,8 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed code - block. + in order for the decompressor to finish the block before the empty fixed + codes block. If flush is set to Z_BLOCK, a deflate block is completed and emitted, as for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to @@ -322,42 +328,47 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. + avail_out is greater than six when the flush marker begins, in order to avoid + repeated flush markers upon calling deflate() again when avail_out == 0. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the stream - are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect the - compression algorithm in any manner. + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. */ -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT deflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending @@ -372,31 +383,30 @@ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); /* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateInit(z_streamp strm); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the - exact value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. total_in, total_out, adler, and + msg are initialized. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit() does not process any header information -- that is deferred - until inflate() is called. + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. */ -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce @@ -408,17 +418,20 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing will - resume at this point for the next call of inflate(). + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). - - Provide more output starting at next_out and update next_out and avail_out + - Generate more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. The + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be @@ -435,8 +448,8 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 if + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the input taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or decoding the complete header up to just before the first byte of the deflate @@ -459,60 +472,68 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all the uncompressed data. (The size - of the uncompressed data may have been saved by the compressor for this - purpose.) The next operation on this stream must be inflateEnd to deallocate - the decompression state. The use of Z_FINISH is never required, but can be - used to inform inflate that a faster approach may be used for the single - inflate() call. + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. In this implementation, inflate() always flushes as much output as possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK or Z_TREES is used. + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, + strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 + below. At the end of the stream, inflate() checks that its computed Adler-32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() can decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically, if requested when initializing with inflateInit2(). Any information contained in the gzip - header is not retained, so applications that need that information should - instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial - recovery of the data is desired. + recovery of the data is to be attempted. */ -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. */ @@ -523,16 +544,15 @@ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); */ /* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); +ZEXTERN int ZEXPORT deflateInit2(z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy); This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by the - caller. + fields zalloc, zfree and opaque must be initialized before by the caller. The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. @@ -543,16 +563,29 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. + with no zlib header or trailer, and will not compute a check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is @@ -562,18 +595,21 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as - fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The - strategy parameter only affects the compression ratio but not the - correctness of the compressed output even if it is not set appropriately. - Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler - decoder for special applications. + filter (or predictor), Z_RLE to limit match distances to one (run-length + encoding), or Z_HUFFMAN_ONLY to force Huffman encoding only (no string + matching). Filtered data consists mostly of small values with a somewhat + random distribution, as produced by the PNG filters. In this case, the + compression algorithm is tuned to compress them better. The effect of + Z_FILTERED is to force more Huffman coding and less string matching than the + default; it is intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. + Z_RLE is almost as fast as Z_HUFFMAN_ONLY, but should give better + compression for PNG image data than Huffman only. The degree of string + matching from most to none is: Z_DEFAULT_STRATEGY, Z_FILTERED, Z_RLE, then + Z_HUFFMAN_ONLY. The strategy parameter affects the compression ratio but + never the correctness of the compressed output, even if it is not set + optimally for the given data. Z_FIXED uses the default string matching, but + prevents the use of dynamic Huffman codes, allowing for a simpler decoder + for special applications. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid @@ -583,15 +619,20 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, compression: this will be done by deflate(). */ -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); +ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); /* Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any call - of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly @@ -608,22 +649,44 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. - Upon return of this function, strm->adler is set to the adler32 value + Upon return of this function, strm->adler is set to the Adler-32 value of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value + which dictionary has been used by the compressor. (The Adler-32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. + Adler-32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. */ -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); +ZEXTERN int ZEXPORT deflateCopy(z_streamp dest, + z_streamp source); /* Sets the destination stream as a complete copy of the source stream. @@ -640,43 +703,60 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, destination. */ -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +ZEXTERN int ZEXPORT deflateReset(z_streamp strm); /* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. The - stream will keep the same compression level and any other attributes that - may have been set by deflateInit2. + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. total_in, total_out, adler, and msg are initialized. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); +ZEXTERN int ZEXPORT deflateParams(z_streamp strm, + int level, + int strategy); /* Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be + interpretation of level and strategy is as in deflateInit2(). This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. - If the compression level is changed, the input available so far is - compressed with the old level (and may be flushed); the new level will take - effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to be - compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if - strm->avail_out was zero. -*/ - -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); + If the compression approach (which is a function of the level) or the + strategy is changed, and if there have been any deflate() calls since the + state was initialized or reset, then the input available so far is + compressed with the old level and strategy using deflate(strm, Z_BLOCK). + There are three approaches for the compression levels 0, 1..3, and 4..9 + respectively. The new level and strategy will take effect at the next call + of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune(z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain); /* Fine tune deflate's internal compression parameters. This should only be used by someone who understands the algorithm used by zlib's deflate for @@ -689,19 +769,57 @@ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. */ -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); +ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen); +ZEXTERN z_size_t ZEXPORT deflateBound_z(z_streamp strm, z_size_t sourceLen); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). -*/ + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. + + delfateBound_z() is the same, but takes and returns a size_t length. Note + that a long is 32 bits on Windows. +*/ + +ZEXTERN int ZEXPORT deflatePending(z_streamp strm, + unsigned *pending, + int *bits); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. If an int is 16 bits and memLevel is 9, then + it is possible for the number of pending bytes to not fit in an unsigned. In + that case Z_BUF_ERROR is returned and *pending is set to the maximum value + of an unsigned. + */ + +ZEXTERN int ZEXPORT deflateUsed(z_streamp strm, + int *bits); +/* + deflateUsed() returns in *bits the most recent number of deflate bits used + in the last byte when flushing to a byte boundary. The result is in 1..8, or + 0 if there has not yet been a flush. This helps determine the location of + the last bit of a deflate stream. + + deflateUsed returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); +ZEXTERN int ZEXPORT deflatePrime(z_streamp strm, + int bits, + int value); /* deflatePrime() inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits @@ -711,12 +829,13 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, than or equal to 16, and that many of the least significant bits of value will be inserted in the output. - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. */ -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); +ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm, + gz_headerp head); /* deflateSetHeader() provides gzip header information for when a gzip stream is requested by deflateInit2(). deflateSetHeader() may be called @@ -732,16 +851,17 @@ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). + the time set to zero, and os set to the current operating system, with no + extra, name, or comment fields. The gzip header is returned to the default + state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); +ZEXTERN int ZEXPORT inflateInit2(z_streamp strm, + int windowBits); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized @@ -766,7 +886,7 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to + recommended that a check value such as an Adler-32 or a CRC-32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. @@ -775,7 +895,12 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - crc32 instead of an adler32. + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will *not* automatically decode concatenated gzip members. + inflate() will return Z_STREAM_END at the end of the gzip member. The state + would need to be reset to continue decoding a subsequent gzip member. This + *must* be done if there is more data after a gzip member, in order for the + decompression to be compliant with the gzip standard (RFC 1952). inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the @@ -789,45 +914,65 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, deferred until inflate() is called. */ -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); +ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. + can be determined from the Adler-32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not + expected one (incorrect Adler-32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similarly, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync(z_streamp strm); /* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been - found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the - success case, the application may save the current current value of total_in + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. */ -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); +ZEXTERN int ZEXPORT inflateCopy(z_streamp dest, + z_streamp source); /* Sets the destination stream as a complete copy of the source stream. @@ -842,39 +987,44 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, destination. */ -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateReset(z_streamp strm); /* This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. The + but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. + total_in, total_out, adler, and msg are initialized. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, - int windowBits)); +ZEXTERN int ZEXPORT inflateReset2(z_streamp strm, + int windowBits); /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if the windowBits parameter is invalid. */ -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); +ZEXTERN int ZEXPORT inflatePrime(z_streamp strm, + int bits, + int value); /* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. + This function inserts bits in the inflate input stream. The intent is to + use inflatePrime() to start inflating at a bit position in the middle of a + byte. The provided bits will be used before any bytes are used from + next_in. This function should be used with raw inflate, before the first + inflate() call, after inflateInit2() or inflateReset(). It can also be used + after an inflate() return indicates the end of a deflate block or header + when using Z_BLOCK. bits must be less than or equal to 16, and that many of + the least significant bits of value will be inserted in the input. The + other bits in value can be non-zero, and will be ignored. If bits is negative, then the input stream bit buffer is emptied. Then inflatePrime() can be called again to put bits in the buffer. This is used @@ -882,10 +1032,18 @@ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, to feeding inflate codes. inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. + stream state was inconsistent, or if bits is out of range. If inflate was + in the middle of processing a header, trailer, or stored block lengths, then + it is possible for there to be only eight bits available in the bit buffer. + In that case, bits > 8 is considered out of range. However, when used as + outlined above, there will always be 16 bits available in the buffer for + insertion. As noted in its documentation above, inflate records the number + of bits in the bit buffer on return in data_type. 32 minus that is the + number of bits available for insertion. inflatePrime does not update + data_type with the new number of bits in buffer. */ -ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +ZEXTERN long ZEXPORT inflateMark(z_streamp strm); /* This function returns two values, one in the lower 16 bits of the return value, and the other in the remaining upper bits, obtained by shifting the @@ -909,12 +1067,12 @@ ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); location in the input stream can be determined from avail_in and data_type as noted in the description for the Z_BLOCK flush parameter for inflate. - inflateMark returns the value noted above or -1 << 16 if the provided + inflateMark returns the value noted above, or -65536 if the provided source stream state was inconsistent. */ -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); +ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm, + gz_headerp head); /* inflateGetHeader() requests that gzip header information be stored in the provided gz_header structure. inflateGetHeader() may be called after @@ -928,20 +1086,22 @@ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, The text, time, xflags, and os fields are filled in with the gzip header contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When any - of extra, name, or comment are not Z_NULL and the respective field is not - present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. + was valid if done is set to one.) The extra, name, and comment pointers + much each be either Z_NULL or point to space to store that information from + the header. If extra is not Z_NULL, then extra_max contains the maximum + number of bytes that can be written to extra. Once done is true, extra_len + contains the actual extra field length, and extra contains the extra field, + or that field truncated if extra_max is less than extra_len. If name is not + Z_NULL, then up to name_max characters, including the terminating zero, are + written there. If comment is not Z_NULL, then up to comm_max characters, + including the terminating zero, are written there. The application can tell + that the name or comment did not fit in the provided space by the absence of + a terminating zero. If any of extra, name, or comment are not present in + the header, then that field's pointer is set to Z_NULL. This allows the use + of deflateSetHeader() with the returned structure to duplicate the header. + Note that if those fields initially pointed to allocated memory, then the + application will need to save them elsewhere so that they can be eventually + freed. If inflateGetHeader is not used, then the header information is simply discarded. The header is always checked for validity, including the header @@ -954,8 +1114,8 @@ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, */ /* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); +ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits, + unsigned char FAR *window); Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized @@ -970,24 +1130,26 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + the parameters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); +typedef unsigned (*in_func)(void FAR *, + z_const unsigned char FAR * FAR *); +typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned); -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); +ZEXTERN int ZEXPORT inflateBack(z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc); /* inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. @@ -999,9 +1161,9 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the normal - behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those @@ -1010,12 +1172,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). @@ -1043,11 +1205,11 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() + assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm); /* All memory allocated by inflateBackInit() is freed. @@ -1055,7 +1217,7 @@ ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); state was inconsistent. */ -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +ZEXTERN uLong ZEXPORT zlibCompileFlags(void); /* Return flags indicating compile-time options. Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: @@ -1065,7 +1227,7 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); 7.6: size of z_off_t Compiler, assembler, and debug options: - 8: DEBUG + 8: ZLIB_DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) @@ -1087,15 +1249,17 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); 21: FASTEST -- deflate algorithm with only one, lowest compression level 22,23: 0 (reserved) - The sprintf variant used by gzprintf (zero is best): + The sprintf variant used by gzprintf (all zeros is best): 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() is not secure! 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + 27: 0 = gzprintf() present, 1 = not -- 1 means gzprintf() returns an error Remainder: - 27-31: 0 (reserved) + 28-31: 0 (reserved) */ +#ifndef Z_SOLO /* utility functions */ @@ -1104,62 +1268,83 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); stream-oriented functions. To simplify the interface, some default options are assumed (compression level and memory usage, standard memory allocation functions). The source code of these utility functions can be modified if - you need special options. + you need special options. The _z versions of the functions use the size_t + type for lengths. Note that a long is 32 bits on Windows. */ -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); +ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); +ZEXTERN int ZEXPORT compress_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); +ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level); +ZEXTERN int ZEXPORT compress2_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen, + int level); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. + compressed data. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen); +ZEXTERN z_size_t ZEXPORT compressBound_z(z_size_t sourceLen); /* compressBound() returns an upper bound on the compressed size after compress() or compress2() on sourceLen bytes. It would be used before a compress() or compress2() call to allocate the destination buffer. */ -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); +ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); +ZEXTERN int ZEXPORT uncompress_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t sourceLen); /* Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size + the byte length of the source buffer. On entry, *destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed buffer. + mechanism outside the scope of this compression library.) On exit, *destLen + is the actual size of the uncompressed data. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. */ +ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen); +ZEXTERN int ZEXPORT uncompress2_z(Bytef *dest, z_size_t *destLen, + const Bytef *source, z_size_t *sourceLen); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ /* gzip file access functions */ @@ -1170,42 +1355,73 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, wrapper, documented in RFC 1952, wrapped around a deflate stream. */ -typedef voidp gzFile; /* opaque gzip file descriptor */ +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode); + + Open the gzip (.gz) file at path for reading and decompressing, or + compressing and writing. The mode parameter is as in fopen ("rb" or "wb") + but can also include a compression level ("wb9") or a strategy: 'f' for + filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", + 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression + as in "wb9F". (See the description of deflateInit2 for more information + about the strategy parameter.) 'T' will request transparent writing or + appending with no compression and not using the gzip format. 'T' cannot be + used to force transparent reading. Transparent reading is automatically + performed if there is no gzip header at the start. Transparent reading can + be disabled with the 'G' option, which will instead return an error if there + is no gzip header. 'N' will open the file in non-blocking mode. - Opens a gzip (.gz) file for reading or writing. The mode parameter is as - in fopen ("rb" or "wb") but can also include a compression level ("wb9") or - a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only - compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' - for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) Also "a" - can be used instead of "w" to request that the gzip stream that will be - written be appended to the file. "+" will result in an error, since reading - and writing to the same gzip file is not supported. + 'a' can be used instead of 'w' to request that the gzip stream that will + be written be appended to the file. '+' will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + 'x' when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of 'e' when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. gzopen returns NULL if the file could not be opened, if there was insufficient memory to allocate the gzFile state, or if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). errno can be checked to determine if the reason gzopen failed was that the - file could not be opened. + file could not be opened. Note that if 'N' is in mode for non-blocking, the + open() itself can fail in order to not block. In that case gzopen() will + return NULL and errno will be EAGAIN or ENONBLOCK. The call to gzopen() can + then be re-tried. If the application would like to block on opening the + file, then it can use open() without O_NONBLOCK, and then gzdopen() with the + resulting file descriptor and 'N' in the mode, which will set it to non- + blocking. */ -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode); /* - gzdopen associates a gzFile with the file descriptor fd. File descriptors - are obtained from calls like open, dup, creat, pipe or fileno (if the file - has been previously opened with fopen). The mode parameter is as in gzopen. + Associate a gzFile with the file descriptor fd. File descriptors are + obtained from calls like open, dup, creat, pipe or fileno (if the file has + been previously opened with fopen). The mode parameter is as in gzopen. An + 'e' in mode will set fd's flag to close the file on an execve() call. An 'N' + in mode will set fd's non-blocking flag. The next call of gzclose on the returned gzFile will also close the file descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. gzdopen returns NULL if there was insufficient memory to allocate the gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not @@ -1214,16 +1430,15 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); will not detect if fd is invalid (unless fd is -1). */ -ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size); /* - Set the internal buffer size used by this library's functions. The - default buffer size is 8192 bytes. This function must be called after - gzopen() or gzdopen(), and before any other calls that read or write the - file. The buffer memory allocation is always deferred to the first read or - write. Two buffers are allocated, either both of the specified size when - writing, or one of the specified size and the other twice that size when - reading. A larger buffer size of, for example, 64K or 128K bytes will - noticeably increase the speed of decompression (reading). + Set the internal buffer size used by this library's functions for file to + size. The default buffer size is 8192 bytes. This function must be called + after gzopen() or gzdopen(), and before any other calls that read or write + the file. The buffer memory allocation is always deferred to the first read + or write. Three times that size in buffer space is allocated. A larger + buffer size of, for example, 64K or 128K bytes will noticeably increase the + speed of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). @@ -1231,127 +1446,237 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); too late. */ -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy); /* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. + Dynamically update the compression level and strategy for file. See the + description of deflateInit2 for the meaning of these parameters. Previously + provided data is flushed before applying the parameter changes. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. */ -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len); /* - Reads the given number of uncompressed bytes from the compressed file. If - the input file was not in gzip format, gzread copies the given number of - bytes into the buffer. + Read and decompress up to len uncompressed bytes from file into buf. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream, or failing that, reading the rest - of the input file directly without decompression. The entire input file - will be read if gzread is called until it returns less than the requested - len. + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread can be used to read a gzip file on a non-blocking device. If the + input stalls and there is no uncompressed data to return, then gzread() will + return -1, and errno will be EAGAIN or EWOULDBLOCK. gzread() can then be + called again. gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. If some data was read before an error, then that data is + returned until exhausted, after which the next call will signal the error. */ -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); +ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, + gzFile file); /* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes written or 0 in case of - error. + Read and decompress up to nitems items of size size from file into buf, + otherwise operating as gzread() does. This duplicates the interface of + stdio's fread(), with size_t request and return types. If the library + defines size_t, then z_size_t is identical to size_t. If not, then z_size_t + is an unsigned integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevertheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as that of fread() implementations in common libraries. This + could result in data loss if used with size != 1 when reading a concurrently + written file or a non-blocking file. In that case, use size == 1 or gzread() + instead. */ -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len); /* - Converts, formats, and writes the arguments to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or 0 in case of error. The number of - uncompressed bytes written is limited to 8191, or one less than the buffer - size given to gzbuffer(). The caller should assure that this limit is not - exceeded. If it is exceeded, then gzprintf() will return an error (0) with - nothing written. In this case, there may also be a buffer overflow with - unpredictable consequences, which is possible only if zlib was compiled with - the insecure functions sprintf() or vsprintf() because the secure snprintf() - or vsnprintf() functions were not available. This can be determined using - zlibCompileFlags(). + Compress and write the len uncompressed bytes at buf to file. gzwrite + returns the number of uncompressed bytes written, or 0 in case of error or + if len is 0. If the write destination is non-blocking, then gzwrite() may + return a number of bytes written that is not 0 and less than len. + + If len does not fit in an int, then 0 is returned and nothing is written. */ -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, + z_size_t nitems, gzFile file); /* - Writes the given null-terminated string to the compressed file, excluding + Compress and write nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. + + If writing a concurrently read file or a non-blocking file with size != 1, + a partial item could be written, with no way of knowing how much of it was + not written, resulting in data loss. In that case, use size == 1 or + gzwrite() instead. +*/ + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...); +#else +ZEXTERN int ZEXPORTVA gzprintf(); +#endif +/* + Convert, format, compress, and write the arguments (...) to file under + control of the string format, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. + + In that last case, there may also be a buffer overflow with unpredictable + consequences, which is possible only if zlib was compiled with the insecure + functions sprintf() or vsprintf(), because the secure snprintf() and + vsnprintf() functions were not available. That would only be the case for + a non-ANSI C compiler. zlib may have been built without gzprintf() because + secure functions were not available and having gzprintf() be insecure was + not an option, in which case, gzprintf() returns Z_STREAM_ERROR. All of + these possibilities can be determined using zlibCompileFlags(). + + If a Z_BUF_ERROR is returned, then nothing was written due to a stall on + the non-blocking write destination. +*/ + +ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s); +/* + Compress and write the given null-terminated string s to file, excluding the terminating null character. gzputs returns the number of characters written, or -1 in case of error. + The number of characters written may be less than the length of the string + if the write destination is non-blocking. + + If the length of the string does not fit in an int, then -1 is returned + and nothing is written. */ -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len); /* - Reads bytes from the compressed file until len-1 characters are read, or a - newline character is read and transferred to buf, or an end-of-file - condition is encountered. If any characters are read or if len == 1, the - string is terminated with a null character. If no characters are read due - to an end-of-file or len < 1, then the buffer is left untouched. + Read and decompress bytes from file into buf, until len-1 characters are + read, or until a newline character is read and transferred to buf, or an + end-of-file condition is encountered. If any characters are read or if len + is one, the string is terminated with a null character. If no characters + are read due to an end-of-file or len is less than one, then the buffer is + left untouched. gzgets returns buf which is a null-terminated string, or it returns NULL - for end-of-file or in case of error. If there was an error, the contents at - buf are indeterminate. + for end-of-file or in case of error. If some data was read before an error, + then that data is returned until exhausted, after which the next call will + return NULL to signal the error. + + gzgets can be used on a file being concurrently written, and on a non- + blocking device, both as for gzread(). However lines may be broken in the + middle, leaving it up to the application to reassemble them as needed. */ -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +ZEXTERN int ZEXPORT gzputc(gzFile file, int c); /* - Writes c, converted to an unsigned char, into the compressed file. gzputc + Compress and write c, converted to an unsigned char, into file. gzputc returns the value that was written, or -1 in case of error. */ -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +ZEXTERN int ZEXPORT gzgetc(gzFile file); /* - Reads one byte from the compressed file. gzgetc returns this byte or -1 - in case of end of file or error. + Read and decompress one byte from file. gzgetc returns this byte or -1 in + case of end of file or error. If some data was read before an error, then + that data is returned until exhausted, after which the next call will return + -1 to signal the error. + + This is implemented as a macro for speed. As such, it does not do all of + the checking the other functions do. I.e. it does not check to see if file + is NULL, nor whether the structure file points to has been clobbered or not. + + gzgetc can be used to read a gzip file on a non-blocking device. If the + input stalls and there is no uncompressed data to return, then gzgetc() will + return -1, and errno will be EAGAIN or EWOULDBLOCK. gzread() can then be + called again. */ -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); /* - Push one character back onto the stream to be read as the first character - on the next read. At least one character of push-back is allowed. + Push c back onto the stream for file to be read as the first character on + the next read. At least one character of push-back is always allowed. gzungetc() returns the character pushed, or -1 on failure. gzungetc() will fail if c is -1, and may fail if a character has been pushed but not read yet. If gzungetc is used immediately after gzopen or gzdopen, at least the output buffer size of pushed characters is allowed. (See gzbuffer above.) The pushed character will be discarded if the stream is repositioned with gzseek() or gzrewind(). + + gzungetc(-1, file) will force any pending seek to execute. Then gztell() + will report the position, even if the requested seek reached end of file. + This can be used to determine the number of uncompressed bytes in a gzip + file without having to read it into a buffer. */ -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +ZEXTERN int ZEXPORT gzflush(gzFile file, int flush); /* - Flushes all pending output into the compressed file. The parameter flush - is as in the deflate() function. The return value is the zlib error number - (see function gzerror below). gzflush is only permitted when writing. + Flush all pending output to file. The parameter flush is as in the + deflate() function. The return value is the zlib error number (see function + gzerror below). gzflush is only permitted when writing. If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such - concatented gzip streams. + concatenated gzip streams. gzflush should be called only when strictly necessary because it will degrade compression if called too often. */ /* -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); +ZEXTERN z_off_t ZEXPORT gzseek(gzFile file, + z_off_t offset, int whence); - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the + Set the starting position to offset relative to whence for the next gzread + or gzwrite on file. The offset represents a number of bytes in the uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. If the file is opened for reading, this function is emulated but can be extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek then compresses a sequence of zeroes up to the new - starting position. + starting position. For reading or writing, any actual seeking is deferred + until the next read or write operation, or close operation when writing. gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error, in @@ -1359,79 +1684,88 @@ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, would be before the current position. */ -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +ZEXTERN int ZEXPORT gzrewind(gzFile file); /* - Rewinds the given file. This function is supported only for reading. + Rewind file. This function is supported only for reading. - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). */ /* -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +ZEXTERN z_off_t ZEXPORT gztell(gzFile file); - Returns the starting position for the next gzread or gzwrite on the given - compressed file. This position represents a number of bytes in the - uncompressed data stream, and is zero when starting, even if appending or - reading a gzip stream from the middle of a file using gzdopen(). + Return the starting position for the next gzread or gzwrite on file. + This position represents a number of bytes in the uncompressed data stream, + and is zero when starting, even if appending or reading a gzip stream from + the middle of a file using gzdopen(). gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ /* -ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); +ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file); - Returns the current offset in the file being read or written. This offset - includes the count of bytes that precede the gzip stream, for example when - appending or when using gzdopen() for reading. When reading, the offset - does not include as yet unused buffered input. This information can be used - for a progress indicator. On error, gzoffset() returns -1. + Return the current compressed (actual) read or write offset of file. This + offset includes the count of bytes that precede the gzip stream, for example + when appending or when using gzdopen() for reading. When reading, the + offset does not include as yet unused buffered input. This information can + be used for a progress indicator. On error, gzoffset() returns -1. */ -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +ZEXTERN int ZEXPORT gzeof(gzFile file); /* - Returns true (1) if the end-of-file indicator has been set while reading, - false (0) otherwise. Note that the end-of-file indicator is set only if the - read tried to go past the end of the input, but came up short. Therefore, - just like feof(), gzeof() may return false even if there is no more data to - read, in the event that the last read request was for the exact number of - bytes remaining in the input file. This will happen if the input file size - is an exact multiple of the buffer size. + Return true (1) if the end-of-file indicator for file has been set while + reading, false (0) otherwise. Note that the end-of-file indicator is set + only if the read tried to go past the end of the input, but came up short. + Therefore, just like feof(), gzeof() may return false even if there is no + more data to read, in the event that the last read request was for the exact + number of bytes remaining in the input file. This will happen if the input + file size is an exact multiple of the buffer size. If gzeof() returns true, then the read functions will return no more data, unless the end-of-file indicator is reset by gzclearerr() and the input file has grown since the previous end of file was detected. */ -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +ZEXTERN int ZEXPORT gzdirect(gzFile file); /* - Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. This state can change from - false to true while reading the input file if the end of a gzip stream is - reached, but is followed by data that is not another gzip stream. + Return true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. If gzdirect() is used immediately after gzopen() or gzdopen() it will cause buffers to be allocated to allow reading the file to determine if it - is a gzip file. Therefore if gzbuffer() is used, it should be called before - gzdirect(). + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). If the input is being written concurrently or the device is non- + blocking, then gzdirect() may give a different answer once four bytes of + input have been accumulated, which is what is needed to confirm or deny a + gzip header. Before this, gzdirect() will return true (1). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) */ -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose(gzFile file); /* - Flushes all pending output if necessary, closes the compressed file and - deallocates the (de)compression state. Note that once file is closed, you + Flush all pending output for file, if necessary, close file and + deallocate the (de)compression state. Note that once file is closed, you cannot call gzerror with file, since its structures have been deallocated. gzclose must not be called more than once on the same file, just as free must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, or Z_OK on success. + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. */ -ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); -ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_r(gzFile file); +ZEXTERN int ZEXPORT gzclose_w(gzFile file); /* Same as gzclose(), but gzclose_r() is only for use when reading, and gzclose_w() is only for use when writing or appending. The advantage to @@ -1442,12 +1776,13 @@ ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); zlib library. */ -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum); /* - Returns the error message for the last error which occurred on the given - compressed file. errnum is set to zlib error number. If an error occurred - in the file system and not in the compression library, errnum is set to - Z_ERRNO and the application may consult errno to get the exact error code. + Return the error message for the last error which occurred on file. + If errnum is not NULL, *errnum is set to zlib error number. If an error + occurred in the file system and not in the compression library, *errnum is + set to Z_ERRNO and the application may consult errno to get the exact error + code. The application must not modify the returned string. Future calls to this function may invalidate the previously returned string. If file is @@ -1458,13 +1793,14 @@ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); functions above that do not distinguish those cases in their return values. */ -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +ZEXTERN void ZEXPORT gzclearerr(gzFile file); /* - Clears the error and end-of-file flags for file. This is analogous to the + Clear the error and end-of-file flags for file. This is analogous to the clearerr() function in stdio. This is useful for continuing to read a gzip file that is being written concurrently. */ +#endif /* !Z_SOLO */ /* checksum functions */ @@ -1474,13 +1810,14 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); library. */ -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is Z_NULL, this function returns the - required initial value for the checksum. + return the updated checksum. An Adler-32 value is in the range of a 32-bit + unsigned integer. If buf is Z_NULL, this function returns the required + initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed much faster. Usage example: @@ -1493,23 +1830,32 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (adler != original_adler) error(); */ +ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, + z_size_t len); /* -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); + Same as adler32(), but with a size_t length. Note that a long is 32 bits + on Windows. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, + z_off_t len2); Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. */ -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is Z_NULL, this function returns the required - initial value for the for the crc. Pre- and post-conditioning (one's - complement) is performed within this function so it shouldn't be done by the - application. + updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. + If buf is Z_NULL, this function returns the required initial value for the + crc. Pre- and post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the application. Usage example: @@ -1521,14 +1867,35 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); if (crc != original_crc) error(); */ +ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf, + z_size_t len); /* -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + Same as crc32(), but with a size_t length. Note that a long is 32 bits on + Windows. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2); Combine two CRC-32 check values into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, CRC-32 check values were calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. + len2. len2 must be non-negative, otherwise zero is returned. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2); + + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). len2 must be non-negative, otherwise zero is returned. +*/ + +ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op); +/* + Give the same result as crc32_combine(), using op in place of len2. op is + is generated from len2 by crc32_combine_gen(). This will be faster than + crc32_combine() if the generated op is used more than once. */ @@ -1537,32 +1904,73 @@ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) +ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateInit_(z_streamp strm, + const char *version, int stream_size); +ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size); +ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if @@ -1570,49 +1978,81 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, * functions are changed to 64 bits) -- in case these are set on systems * without large file support, _LFS64_LARGEFILE must also be true */ -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); + ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); #endif -#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# ifdef _LARGEFILE64_SOURCE - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# define z_crc32_combine_gen z_crc32_combine_gen64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# define crc32_combine_gen crc32_combine_gen64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); # endif #else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); #endif -/* hack for buggy compilers */ -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; -#endif +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); + +#endif /* !Z_SOLO */ /* undocumented functions */ -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); -ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN const char * ZEXPORT zError(int); +ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void); +ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int); +ZEXTERN int ZEXPORT inflateValidate(z_streamp, int); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp); +ZEXTERN int ZEXPORT inflateResetKeep(z_streamp); +ZEXTERN int ZEXPORT deflateResetKeep(z_streamp); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path, + const char *mode); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf(gzFile file, + const char *format, + va_list va); +# endif +#endif ABC_NAMESPACE_HEADER_END diff --git a/src/misc/zlib/zutil.c b/src/misc/zlib/zutil.c index fbf67f1b4f..c844b459f4 100644 --- a/src/misc/zlib/zutil.c +++ b/src/misc/zlib/zutil.c @@ -1,5 +1,5 @@ /* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2005, 2010 Jean-loup Gailly. + * Copyright (C) 1995-2026 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -12,34 +12,31 @@ #include "zutil.h" - ABC_NAMESPACE_IMPL_START - -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ +#ifndef Z_SOLO +# include "gzguts.h" #endif -const char * const z_errmsg[10] = { -"need dictionary", /* Z_NEED_DICT 2 */ -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -"incompatible version",/* Z_VERSION_ERROR (-6) */ -""}; - - -const char * ZEXPORT zlibVersion() -{ +z_const char * const z_errmsg[10] = { + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ + (z_const char *)"", /* Z_OK 0 */ + (z_const char *)"file error", /* Z_ERRNO (-1) */ + (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ + (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ + (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ + (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ + (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ + (z_const char *)"" +}; + + +const char * ZEXPORT zlibVersion(void) { return ZLIB_VERSION; } -uLong ZEXPORT zlibCompileFlags() -{ +uLong ZEXPORT zlibCompileFlags(void) { uLong flags; flags = 0; @@ -67,12 +64,14 @@ uLong ZEXPORT zlibCompileFlags() case 8: flags += 2 << 6; break; default: flags += 3 << 6; } -#ifdef DEBUG +#ifdef ZLIB_DEBUG flags += 1 << 8; #endif + /* #if defined(ASMV) || defined(ASMINF) flags += 1 << 9; #endif + */ #ifdef ZLIB_WINAPI flags += 1 << 10; #endif @@ -94,43 +93,49 @@ uLong ZEXPORT zlibCompileFlags() #ifdef FASTEST flags += 1L << 21; #endif -#ifdef STDC -# ifdef NO_vsnprintf - flags += 1L << 25; -# ifdef HAS_vsprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_vsnprintf_void - flags += 1L << 26; -# endif -# endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifdef NO_vsnprintf +# ifdef ZLIB_INSECURE + flags += 1L << 25; +# else + flags += 1L << 27; +# endif +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif #else - flags += 1L << 24; -# ifdef NO_snprintf - flags += 1L << 25; -# ifdef HAS_sprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_snprintf_void - flags += 1L << 26; -# endif -# endif + flags += 1L << 24; +# ifdef NO_snprintf +# ifdef ZLIB_INSECURE + flags += 1L << 25; +# else + flags += 1L << 27; +# endif +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif #endif return flags; } -#ifdef DEBUG - +#ifdef ZLIB_DEBUG +#include # ifndef verbose # define verbose 0 # endif int ZLIB_INTERNAL z_verbose = verbose; -void ZLIB_INTERNAL z_error (m) - char *m; -{ +void ZLIB_INTERNAL z_error(char *m) { fprintf(stderr, "%s\n", m); exit(1); } @@ -139,13 +144,12 @@ void ZLIB_INTERNAL z_error (m) /* exported to allow conversion of error code to string for compress() and * uncompress() */ -const char * ZEXPORT zError(int err) -{ +const char * ZEXPORT zError(int err) { return ERR_MSG(err); } -#if defined(_WIN32_WCE) - /* The Microsoft C Run-Time Library for Windows CE doesn't have +#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 + /* The older Microsoft C Run-Time Library for Windows CE doesn't have * errno. We define it as a global variable to simplify porting. * Its value is always 0 and should not be used. */ @@ -154,33 +158,37 @@ const char * ZEXPORT zError(int err) #ifndef HAVE_MEMCPY -void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) -{ - if (len == 0) return; - do { - *dest++ = *source++; /* ??? to be unrolled */ - } while (--len != 0); +void ZLIB_INTERNAL zmemcpy(void FAR *dst, const void FAR *src, z_size_t n) { + uchf *p = dst; + const uchf *q = src; + while (n) { + *p++ = *q++; + n--; + } } -int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) -{ - uInt j; - - for (j = 0; j < len; j++) { - if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; +int ZLIB_INTERNAL zmemcmp(const void FAR *s1, const void FAR *s2, z_size_t n) { + const uchf *p = s1, *q = s2; + while (n) { + if (*p++ != *q++) + return (int)p[-1] - (int)q[-1]; + n--; } return 0; } -void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) -{ +void ZLIB_INTERNAL zmemzero(void FAR *b, z_size_t len) { + uchf *p = b; if (len == 0) return; - do { - *dest++ = 0; /* ??? to be unrolled */ - } while (--len != 0); + while (len) { + *p++ = 0; + len--; + } } + #endif +#ifndef Z_SOLO #ifdef SYS16BIT @@ -213,11 +221,12 @@ local ptr_table table[MAX_PTR]; * a protected system like OS/2. Use Microsoft C instead. */ -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - voidpf buf = opaque; /* just to make some compilers happy */ +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { + voidpf buf; ulg bsize = (ulg)items*size; + (void)opaque; + /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ @@ -237,9 +246,11 @@ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) return buf; } -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) -{ +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { int n; + + (void)opaque; + if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; @@ -255,7 +266,6 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) next_ptr--; return; } - ptr = opaque; /* just to make some compilers happy */ Assert(0, "zcfree: ptr not found"); } @@ -272,15 +282,13 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) # define _hfree hfree #endif -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) -{ - if (opaque) opaque = 0; /* to make compiler happy */ +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) { + (void)opaque; return _halloc((long)items, size); } -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) -{ - if (opaque) opaque = 0; /* to make compiler happy */ +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { + (void)opaque; _hfree(ptr); } @@ -292,27 +300,25 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC -extern voidp malloc OF((uInt size)); -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); +extern voidp malloc(uInt size); +extern voidp calloc(uInt items, uInt size); +extern void free(voidpf ptr); #endif -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - if (opaque) items += size - size; /* make compiler happy */ +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { + (void)opaque; return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) -{ +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { + (void)opaque; free(ptr); - if (opaque) return; /* make compiler happy */ } #endif /* MY_ZCALLOC */ - +#endif /* !Z_SOLO */ ABC_NAMESPACE_IMPL_END diff --git a/src/misc/zlib/zutil.h b/src/misc/zlib/zutil.h index 26e37f31ce..a9ed7f0dc4 100644 --- a/src/misc/zlib/zutil.h +++ b/src/misc/zlib/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2010 Jean-loup Gailly. + * Copyright (C) 1995-2026 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -13,7 +13,7 @@ #ifndef ZUTIL_H #define ZUTIL_H -#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +#ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL @@ -21,7 +21,7 @@ #include "zlib.h" -#ifdef STDC +#if defined(STDC) && !defined(Z_SOLO) # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) # include # endif @@ -29,12 +29,18 @@ # include #endif -ABC_NAMESPACE_HEADER_START - #ifndef local # define local static #endif -/* compile with -Dlocal if your debugger can't find static symbols */ +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +ABC_NAMESPACE_HEADER_START + +extern const char deflate_copyright[]; +extern const char inflate_copyright[]; +extern const char inflate9_copyright[]; typedef unsigned char uch; typedef uch FAR uchf; @@ -42,17 +48,32 @@ typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; -extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC) +# include +# if (ULONG_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned long +# elif (ULLONG_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned long long +# elif (ULONG_LONG_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned long long +# elif (UINT_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned +# endif +#endif + +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] +#define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)] #define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) + return (strm->msg = ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ - +#if MAX_WBITS < 9 || MAX_WBITS > 15 +# error MAX_WBITS must be in 9..15 +#endif #ifndef DEF_WBITS # define DEF_WBITS MAX_WBITS #endif @@ -80,105 +101,93 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) # define OS_CODE 0x00 -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -ABC_NAMESPACE_HEADER_END -# include -ABC_NAMESPACE_HEADER_START +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include # endif -# else /* MSC or DJGPP */ -ABC_NAMESPACE_HEADER_END -# include -ABC_NAMESPACE_HEADER_START # endif #endif #ifdef AMIGA -# define OS_CODE 0x01 +# define OS_CODE 1 #endif #if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 +# define OS_CODE 2 # define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif +#endif + #if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 +# define OS_CODE 5 #endif #ifdef OS2 -# define OS_CODE 0x06 -# ifdef M_I86 -ABC_NAMESPACE_HEADER_END +# define OS_CODE 6 +# if defined(M_I86) && !defined(Z_SOLO) # include -ABC_NAMESPACE_HEADER_START # endif #endif -#if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 0x07 -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -ABC_NAMESPACE_HEADER_END -# include /* for fdopen */ -ABC_NAMESPACE_HEADER_START -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ -# endif -# endif +#if defined(MACOS) +# define OS_CODE 7 #endif -#ifdef TOPS20 -# define OS_CODE 0x0a +#if defined(__acorn) || defined(__riscos) +# define OS_CODE 13 #endif -#ifdef WIN32 -# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ -# define OS_CODE 0x0b -# endif +#if defined(WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 #endif -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0f +#ifdef _BEOS_ +# define OS_CODE 16 #endif -#if defined(_BEOS_) || defined(RISCOS) -# define fdopen(fd,mode) NULL /* No fdopen() */ +#ifdef __TOS_OS400__ +# define OS_CODE 18 #endif -#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX -# if defined(_WIN32_WCE) -# define fdopen(fd,mode) NULL /* No fdopen() */ -# ifndef _PTRDIFF_T_DEFINED - typedef int ptrdiff_t; -# define _PTRDIFF_T_DEFINED -# endif -# else -# define fdopen(fd,type) _fdopen(fd,type) -# endif +#ifdef __APPLE__ +# define OS_CODE 19 #endif -#if defined(__BORLANDC__) +#if defined(__BORLANDC__) && !defined(MSDOS) #pragma warn -8004 #pragma warn -8008 #pragma warn -8066 #endif /* provide prototypes for these when building zlib without LFS */ -#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#ifndef Z_LARGE64 + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); #endif /* common defaults */ #ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ +# define OS_CODE 3 /* assume Unix */ #endif #ifndef F_OPEN @@ -187,42 +196,7 @@ ABC_NAMESPACE_HEADER_START /* functions */ -#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif -#if defined(__CYGWIN__) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif -#ifndef HAVE_VSNPRINTF -# ifdef MSDOS - /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ -# define NO_vsnprintf -# endif -# ifdef __TURBOC__ -# define NO_vsnprintf -# endif -# ifdef WIN32 - /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) -# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) -# define vsnprintf _vsnprintf -# endif -# endif -# endif -# ifdef __SASC -# define NO_vsnprintf -# endif -#endif -#ifdef VMS -# define NO_vsnprintf -#endif - -#if defined(pyr) +#if defined(pyr) || defined(Z_SOLO) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) @@ -239,25 +213,23 @@ ABC_NAMESPACE_HEADER_START # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ # define zmemcpy _fmemcpy # define zmemcmp _fmemcmp -# define zmemzero(dest, len) _fmemset(dest, 0, (size_t)len) +# define zmemzero(dest, len) _fmemset(dest, 0, len) # else # define zmemcpy memcpy # define zmemcmp memcmp -# define zmemzero(dest, len) memset(dest, 0, (size_t)len) +# define zmemzero(dest, len) memset(dest, 0, len) # endif #else - void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); + void ZLIB_INTERNAL zmemcpy(void FAR *, const void FAR *, z_size_t); + int ZLIB_INTERNAL zmemcmp(const void FAR *, const void FAR *, z_size_t); + void ZLIB_INTERNAL zmemzero(void FAR *, z_size_t); #endif /* Diagnostic functions */ -#ifdef DEBUG - ABC_NAMESPACE_HEADER_END +#ifdef ZLIB_DEBUG # include -ABC_NAMESPACE_HEADER_START extern int ZLIB_INTERNAL z_verbose; - extern void ZLIB_INTERNAL z_error OF((char *m)); + extern void ZLIB_INTERNAL z_error(char *m); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} @@ -273,16 +245,91 @@ ABC_NAMESPACE_HEADER_START # define Tracecv(c,x) #endif - -voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, - unsigned size)); -void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, + unsigned size); + void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr); +#endif #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + ABC_NAMESPACE_HEADER_END +#ifdef Z_ONCE +/* + Create a local z_once() function depending on the availability of atomics. + */ + +/* Check for the availability of atomics. */ +#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ + !defined(__STDC_NO_ATOMICS__) + +#include +typedef struct { + atomic_flag begun; + atomic_int done; +} z_once_t; +#define Z_ONCE_INIT {ATOMIC_FLAG_INIT, 0} + +/* + Run the provided init() function exactly once, even if multiple threads + invoke once() at the same time. The state must be a once_t initialized with + Z_ONCE_INIT. + */ +local void z_once(z_once_t *state, void (*init)(void)) { + if (!atomic_load(&state->done)) { + if (atomic_flag_test_and_set(&state->begun)) + while (!atomic_load(&state->done)) + ; + else { + init(); + atomic_store(&state->done, 1); + } + } +} + +#else /* no atomics */ + +#warning zlib not thread-safe + +typedef struct z_once_s { + volatile int begun; + volatile int done; +} z_once_t; +#define Z_ONCE_INIT {0, 0} + +/* Test and set. Alas, not atomic, but tries to limit the period of + vulnerability. */ +local int test_and_set(int volatile *flag) { + int was; + + was = *flag; + *flag = 1; + return was; +} + +/* Run the provided init() function once. This is not thread-safe. */ +local void z_once(z_once_t *state, void (*init)(void)) { + if (!state->done) { + if (test_and_set(&state->begun)) + while (!state->done) + ; + else { + init(); + state->done = 1; + } + } +} + +#endif /* ?atomics */ + +#endif /* Z_ONCE */ + #endif /* ZUTIL_H */ diff --git a/src/opt/dau/dau.h b/src/opt/dau/dau.h index 82e9b83b28..37d24aa5ae 100644 --- a/src/opt/dau/dau.h +++ b/src/opt/dau/dau.h @@ -86,6 +86,7 @@ extern Abc_TtHieMan_t * Abc_TtHieManStart( int nVars, int nLevels ); extern void Abc_TtHieManStop(Abc_TtHieMan_t * p ); extern unsigned Abc_TtCanonicizeWrap(TtCanonicizeFunc func, Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int flag); extern unsigned Abc_TtCanonicizeAda(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int iThres); +extern unsigned Abc_TtCanonicizeCA(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int fCA); extern unsigned Abc_TtCanonicizeHie(Abc_TtHieMan_t * p, word * pTruthInit, int nVars, char * pCanonPerm, int fExact); /*=== dauCount.c ==========================================================*/ extern int Abc_TtCountOnesInCofsQuick( word * pTruth, int nVars, int * pStore ); diff --git a/src/opt/dau/dauGia.c b/src/opt/dau/dauGia.c index a49a253cd9..5bf81bdd96 100644 --- a/src/opt/dau/dauGia.c +++ b/src/opt/dau/dauGia.c @@ -562,6 +562,8 @@ void * Dsm_ManDeriveGia( void * pGia, int fUseMuxes ) assert( iLev == 1 + Abc_MaxInt(iLev0, iLev1) ); } */ + // propagate origins + Gia_ManOriginsDup( pNew, p ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); diff --git a/src/opt/dau/dauNpn.c b/src/opt/dau/dauNpn.c index f4a4bb5313..be9aae3ef5 100644 --- a/src/opt/dau/dauNpn.c +++ b/src/opt/dau/dauNpn.c @@ -1082,7 +1082,6 @@ Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int void Dau_CanonicizeArray( Vec_Wrd_t * vFuncs, int nVars, int fVerbose ) { abctime clkStart = Abc_Clock(); - extern unsigned Abc_TtCanonicizeCA(Abc_TtHieMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int iThres); if ( fVerbose ) printf( "Functions: %d (original) ", Vec_WrdSize(vFuncs) ); unsigned uCanonPhase; char pCanonPerm[16]; word Func; int i; Vec_WrdUniqify( vFuncs ); diff --git a/src/opt/eslim/areaEngine.cpp b/src/opt/eslim/areaEngine.cpp new file mode 100644 index 0000000000..8c3c106381 --- /dev/null +++ b/src/opt/eslim/areaEngine.cpp @@ -0,0 +1,163 @@ +/**CFile**************************************************************** + + FileName [areaEngine.cpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Implementation of area based SAT encoding.] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#include "areaEngine.hpp" + +ABC_NAMESPACE_IMPL_START +namespace eSLIM { + + AreaEngine::AreaEngine(const Relation& relation, const Subcircuit& subcir, const eSLIMConfig& cfg, eSLIMLog& log) + : RelationSynthesiser(relation, subcir, subcir.nodes.size(), cfg, log) { + for (int i = 0; i < subcir.inputs.size(); i++) { + input_index_map[subcir.inputs[i]] = i; + } + for (int i = 0; i < subcir.outputs.size(); i++) { + output_index_map[subcir.outputs[i]] = i; + } + if (subcir.forbidden_pairs.size() > 0) { + setupCycleConstraints(); + } + } + + eSLIMCirMan AreaEngine::synthesiseMinimumSizeCircuit(const Relation& relation, const Subcircuit& subcir, const eSLIMConfig& cfg, eSLIMLog& log) { + AreaEngine synth(relation, subcir, cfg, log); + std::vector last_model; + int replacement_size = 0; + for (int i = synth.max_size; i>=0; i--) { + double timeout = synth.getDynamicTimeout(i); + int status = synth.checkSize(i, timeout); + if (status == 10) { + last_model = synth.solver.getModel(); + i = synth.getSizeFromActivationVars(last_model); + replacement_size = i; + } else { + break; + } + } + if (last_model.empty()) { + // no replacement found + return eSLIMCirMan(0); + } else { + return synth.getReplacement(last_model, replacement_size); + } + } + + int AreaEngine::checkSize(unsigned int size) { + return checkSize(size, 0); + } + + int AreaEngine::checkSize(unsigned int size, double timeout) { + std::vector assumptions = getSizeAssumption(size); + int status = timeout == 0 ? solver.solve(assumptions) : solver.solve(timeout, assumptions); + logRun(status, size); + return status; + } + + void AreaEngine::setupCycleConstraints() { + assert (!subcir.forbidden_pairs.empty()); + setupConnectionVariables(); + if (subcir.forbidden_pairs.size() > 1) { + connectionVariablesForCombinedCycles(); + } + addCycleConstraints(); + } + + void AreaEngine::addCycleConstraints() { + for (auto const& [outp, inputs] : subcir.forbidden_pairs) { + for (int inp : inputs) { + int output_idx = output_index_map.at(outp); + for (int i = 0; i < max_size; i++) { + solver.addClause({-gate_activation_variables[i], -gate_output_variables[i][output_idx], -connection_variables.at(inp)[i + subcir.inputs.size()]}); + } + for (int i = 0; i < subcir.inputs.size(); i++) { + solver.addClause({-gate_output_variables[max_size + i][output_idx], -connection_variables.at(inp)[i]}); + } + } + } + } + + void AreaEngine::setupConnectionVariables() { + for (auto const& [out, inputs] : subcir.forbidden_pairs) { + for (int in : inputs) { + if (connection_variables.find(in) == connection_variables.end()) { + connection_variables[in] = getNewVariableVector(max_size + subcir.inputs.size()); + } + } + } + + for (const auto& [input_var, connection_vars] : connection_variables) { + int input_idx = input_index_map.at(input_var); + // An input is connected to itself + solver.addClause({connection_vars[input_idx]}); + for (int i = 0; i < max_size; i++) { + int activation_variable = gate_activation_variables[i]; + for (int j = 0; j < subcir.inputs.size(); j++) { + // if gate i uses input j and input j is connected to input_var then also gate i is connected to input_var + solver.addClause({-activation_variable, -selection_variables[i][j], -connection_vars[j], connection_vars[subcir.inputs.size() + i]}); + } + for (int j = 0; j < i; j++) { + // if gate i uses gate j and gate j is connected to input_var then also gate i is connected to input_var + solver.addClause({-activation_variable, -selection_variables[i][subcir.inputs.size() + j], -connection_vars[subcir.inputs.size() + j], connection_vars[subcir.inputs.size() + i]}); + } + } + } + } + + + void AreaEngine::connectionVariablesForCombinedCycles() { + assert (subcir.forbidden_pairs.size() > 1); + // Inputs are assigned to the outputs on which they depend + std::unordered_map> inputs_per_output; + // Inputs in pairs + std::unordered_set inputs_in_pairs; + for (auto const& [outp, inputs] : subcir.forbidden_pairs) { + for (int inp : inputs) { + if (inputs_per_output.find(outp) == inputs_per_output.end()) { + inputs_per_output[outp] = {inp}; + } else { + inputs_per_output[outp].insert(inp); + } + inputs_in_pairs.insert(inp); + } + } + for (const auto& [ov, inp] : inputs_per_output) { + for (int iv : inputs_in_pairs) { + if (inp.find(iv) == inp.end()) { + for (int k : inputs_per_output.at(ov)) { + for (int i = 0; i < max_size; i++) { + // Input k depends on output ov. + // If gate i represents output ov and gate i is connected to iv then also gate k is connected to iv. + solver.addClause({-gate_activation_variables[i], -gate_output_variables[i][output_index_map.at(ov)], + -connection_variables.at(iv)[subcir.inputs.size() + i], connection_variables.at(iv)[input_index_map.at(k)]}); + } + for (int i = 0; i < subcir.inputs.size(); i++) { + // Input k depends on output ov. + // If input i represents output ov and input i is connected to iv then gate k shall be connected to iv too. + solver.addClause({-gate_output_variables[max_size + i][output_index_map.at(ov)], -connection_variables.at(iv)[i], connection_variables.at(iv)[input_index_map.at(k)]}); + } + } + } + } + } + } + + +} +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/opt/eslim/areaEngine.hpp b/src/opt/eslim/areaEngine.hpp new file mode 100644 index 0000000000..594b22254d --- /dev/null +++ b/src/opt/eslim/areaEngine.hpp @@ -0,0 +1,63 @@ +/**CFile**************************************************************** + + FileName [areaEngine.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Implementation of area based SAT encoding.] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__OPT__ESLIM__AREAENGINE_hpp +#define ABC__OPT__ESLIM__AREAENGINE_hpp + +#include "misc/util/abc_global.h" + +#include "relationSynthesiser.hpp" + + +ABC_NAMESPACE_CXX_HEADER_START +namespace eSLIM { + + class AreaEngine : private RelationSynthesiser { + + public: + static eSLIMCirMan synthesiseMinimumSizeCircuit(const Relation& relation, const Subcircuit& subcir, const eSLIMConfig& cfg, eSLIMLog& log); + + private: + + std::unordered_map> connection_variables; + std::unordered_map input_index_map; + std::unordered_map output_index_map; + + AreaEngine(const Relation& relation, const Subcircuit& subcir, const eSLIMConfig& cfg, eSLIMLog& log); + + int checkSize(unsigned int size, double timeout); + int checkSize(unsigned int size); + + void setupCycleConstraints(); + void setupConnectionVariables(); + // If we have multiple cyclic pairs, different pairs may form form a cycle together + // Assume we have two different pairs (x,y) and (a,b) in potential_cycles. + // It can be the case that x is connected to b and a is connected to y. + // To rule out cycles of this kind we make use of the following idea: + // If (x,y) is in self.potential_cycles then there is a path from x to y that is not part of the current subcircuit. + // Now if b is connected to x, this means that y is also connected to b. + // Thus, all gates that use y as an input are connected to b. + void connectionVariablesForCombinedCycles(); + void addCycleConstraints(); + }; + +} +ABC_NAMESPACE_CXX_HEADER_END +#endif \ No newline at end of file diff --git a/src/opt/eslim/cadicalSolver.hpp b/src/opt/eslim/cadicalSolver.hpp new file mode 100644 index 0000000000..ece98efa95 --- /dev/null +++ b/src/opt/eslim/cadicalSolver.hpp @@ -0,0 +1,218 @@ +/**CFile**************************************************************** + + FileName [cadicalSolver.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Interface for Cadical SAT solver.] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__OPT__ESLIM__SATINTERFACE_h +#define ABC__OPT__ESLIM__SATINTERFACE_h + +#include +#include +#include +#include + +#include "sat/cadical/cadical.hpp" + +ABC_NAMESPACE_CXX_HEADER_START +namespace eSLIM { + + class CadicalSolver { + public: + ~CadicalSolver(); + void addClause(const std::vector& clause); + void addClause(std::vector&& clause); + void addCombinedClause(const std::vector& cl1, const std::vector& cl2, const std::vector& cl3); + void assume(const std::vector& assumptions); + int solve(double timeout, const std::vector& assumptions); + int solve(const std::vector& assumptions); + int solve(double timeout); + int solve(); + std::vector getFailed(const std::vector& assumptions); + bool isFailed(int lit); + std::vector getValues(const std::vector& variables); + bool getValue(int var); + std::vector getModel(); + double getRunTime() const; + + private: + void assumeAll(const std::vector& assumptions); + int val(int variable); + double last_runtime; + CaDiCaL::Solver solver; + + public: + class TimeoutTerminator : public CaDiCaL::Terminator { + public: + TimeoutTerminator(double max_runtime); + bool terminate(); + + private: + double max_runtime; //in seconds + std::chrono::time_point start = std::chrono::steady_clock::now(); + }; + + }; + + inline CadicalSolver::TimeoutTerminator::TimeoutTerminator(double max_runtime) : max_runtime(max_runtime) { + } + + inline bool CadicalSolver::TimeoutTerminator::terminate() { + auto current_time = std::chrono::steady_clock::now(); + std::chrono::duration elapsed_seconds = current_time - start; + return elapsed_seconds.count() > max_runtime; + } + + + + inline CadicalSolver::~CadicalSolver()=default; + + inline void CadicalSolver::addClause(const std::vector& clause) { + for (auto& l: clause) { + solver.add(l); + } + solver.add(0); + } + + inline void CadicalSolver::addClause(std::vector&& clause) { + for (auto& l: clause) { + solver.add(l); + } + solver.add(0); + } + + inline void CadicalSolver::addCombinedClause(const std::vector& cl1, const std::vector& cl2, const std::vector& cl3) { + for (auto& l: cl1) { + solver.add(l); + } + for (auto& l: cl2) { + solver.add(l); + } + for (auto& l: cl3) { + solver.add(l); + } + solver.add(0); + } + + inline void CadicalSolver::assume(const std::vector& assumptions) { + for (auto& l: assumptions) { + solver.assume(l); + } + } + + + inline void CadicalSolver::assumeAll(const std::vector& assumptions) { + solver.reset_assumptions(); + assume(assumptions); + } + + inline int CadicalSolver::solve(double timeout, const std::vector& assumptions) { + assumeAll(assumptions); + std::chrono::time_point start = std::chrono::steady_clock::now(); + TimeoutTerminator terminator(timeout); + solver.connect_terminator(&terminator); + int status = solver.solve(); + last_runtime = std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count(); + if (solver.state() == CaDiCaL::INVALID) { + std::cerr<<"Solver is in invalid state"<& assumptions) { + assumeAll(assumptions); + std::chrono::time_point start = std::chrono::steady_clock::now(); + int status = solver.solve(); + last_runtime = std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count(); + return status; + } + + inline int CadicalSolver::solve(double timeout) { + std::chrono::time_point start = std::chrono::steady_clock::now(); + TimeoutTerminator terminator(timeout); + solver.connect_terminator(&terminator); + int status = solver.solve(); + last_runtime = std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count(); + if (solver.state() == CaDiCaL::INVALID) { + std::cerr<<"Solver is in invalid state"< start = std::chrono::steady_clock::now(); + int status = solver.solve(); + last_runtime = std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count(); + return status; + } + + inline double CadicalSolver::getRunTime() const { + return last_runtime; + } + + inline std::vector CadicalSolver::getFailed(const std::vector& assumptions) { + std::vector failed_literals; + for (auto& l: assumptions) { + if (solver.failed(l)) { + failed_literals.push_back(l); + } + } + return failed_literals; + } + + inline bool CadicalSolver::isFailed(int lit) { + return solver.failed(lit); + } + + inline std::vector CadicalSolver::getValues(const std::vector& variables) { + std::vector assignment; + for (auto& v: variables) { + assignment.push_back(val(v)); + } + return assignment; + } + + inline bool CadicalSolver::getValue(int var) { + return val(var) > 0; + } + + inline std::vector CadicalSolver::getModel() { + std::vector assignment; + assignment.push_back(false); + for (int v = 1; v <= solver.vars(); v++) { + assignment.push_back(val(v) > 0); + } + return assignment; + } + + inline int CadicalSolver::val(int variable) { + auto l = solver.val(variable); + auto v = abs(l); + if (v == variable) { + return l; + } else { + return variable; + } + } + +} +ABC_NAMESPACE_CXX_HEADER_END +#endif \ No newline at end of file diff --git a/src/opt/eslim/delayEngine.cpp b/src/opt/eslim/delayEngine.cpp new file mode 100644 index 0000000000..5e92566cf9 --- /dev/null +++ b/src/opt/eslim/delayEngine.cpp @@ -0,0 +1,254 @@ +/**CFile**************************************************************** + + FileName [delayEngine.cpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Implementation of delay based SAT encoding.] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#include "delayEngine.hpp" + + +ABC_NAMESPACE_IMPL_START +namespace eSLIM { + + DelayEngine::DelayEngine( const Relation& relation, const Subcircuit& subcir, unsigned int max_size, const eSLIMConfig& cfg, eSLIMLog& log) + : RelationSynthesiser(relation, subcir, max_size, cfg, log) { + assert (subcir.forbidden_pairs.empty()); + symmetry_selector = getNewVariable(); + symmetry_selector_assignment = symmetry_selector; + std::set unique_ats_set (subcir.arrival_times.begin(), subcir.arrival_times.end()); + unique_arrival_times = std::vector (unique_ats_set.begin(), unique_ats_set.end()); + for (int i : subcir.arrival_times) { + auto it = unique_ats_set.find(i); + int idx = std::distance(unique_ats_set.begin(), it); + inputid2uniqueid.push_back(idx); + } + setupVariables(); + constrainDelayVariables(); + setupDelayConstraints(); + max_delay = delay_selectors.begin()->first; + } + + // do not enfore activation variables -> a minimum nof gates might forbid a realization with a certain depth. + eSLIMCirMan DelayEngine::synthesizeMinimumDelayCircuit(const Relation& relation, const Subcircuit& subcir, unsigned int delay, unsigned int max_size, const eSLIMConfig& cfg, eSLIMLog& log) { + DelayEngine synth(relation, subcir, max_size, cfg, log); + std::vector last_model = synth.reduceDelay(max_size, delay); + if (last_model.empty()) { + // no replacement found + return eSLIMCirMan(0); + } else { + int replacement_size = synth.getSizeFromActivationVars(last_model); + return synth.getReplacement(last_model, replacement_size); + } + } + + eSLIMCirMan DelayEngine::synthesizeMinimumDelayAreaCircuit(const Relation& relation, const Subcircuit& subcir, unsigned int delay, unsigned int max_size, const eSLIMConfig& cfg, eSLIMLog& log) { + DelayEngine synth(relation, subcir, max_size, cfg, log); + std::vector last_model = synth.reduceDelay(max_size, delay); + if (last_model.empty()) { + // We could not even find a replacement with the same delay as the original circuit (timeout) + // Hence, it is unlikely that we find a circuit that has the same delay but fewer gates + return eSLIMCirMan(0); + } + int replacement_size = synth.getSizeFromActivationVars(last_model); + int replacement_delay = synth.getDelayFromDelayVariables(last_model); + std::vector model = synth.reduceArea(replacement_delay, replacement_size - 1); + if (model.size() > 0) { + replacement_size = synth.getSizeFromActivationVars(model); + std::swap(last_model, model); + } + return synth.getReplacement(last_model, replacement_size); + } + + eSLIMCirMan DelayEngine::synthesizeMinimumAreaDelayCircuit(const Relation& relation, const Subcircuit& subcir, const eSLIMConfig& cfg, eSLIMLog& log) { + DelayEngine synth(relation, subcir, subcir.nodes.size(), cfg, log); + std::vector last_model = synth.reduceArea(synth.max_delay, subcir.nodes.size()); + if (last_model.empty()) { + // We could not even find a replacement with the same area as the original circuit (timeout) + // Hence, it is unlikely that we find a circuit that has the same area and a causes a smaller delay + return eSLIMCirMan(0); + } + int replacement_size = synth.getSizeFromActivationVars(last_model); + int replacement_delay = synth.getDelayFromDelayVariables(last_model); + assert (replacement_delay > 0 || replacement_size == 0); + if (replacement_delay > 0) { // a constant circuit has already optimal depth + std::vector model = synth.reduceDelay(replacement_size, replacement_delay - 1); + if (model.size() > 0) { + replacement_size = synth.getSizeFromActivationVars(model); + std::swap(last_model, model); + } + } + return synth.getReplacement(last_model, replacement_size); + } + + eSLIMCirMan DelayEngine::synthesizeMinimumAreaDelayConstraintCircuit(const Relation& relation, const Subcircuit& subcir, unsigned int delay, const eSLIMConfig& cfg, eSLIMLog& log) { + DelayEngine synth(relation, subcir, subcir.nodes.size(), cfg, log); + std::vector last_model = synth.reduceArea(delay, subcir.nodes.size()); + if (last_model.empty()) { + return eSLIMCirMan(0); + } else { + int replacement_size = synth.getSizeFromActivationVars(last_model); + return synth.getReplacement(last_model, replacement_size); + } + } + + std::vector DelayEngine::reduceArea(unsigned int max_delay, unsigned int initial_area) { + std::vector last_model; + for (int i = initial_area; i>=0; i--) { + double timeout = getDynamicTimeout(i); + int status = existsReplacement(i, max_delay, timeout); + if (status == 10) { + last_model = solver.getModel(); + i = getSizeFromActivationVars(last_model); // it is possible that more than one gate is reduced in an iteration + } else { + break; + } + } + return last_model; + } + + std::vector DelayEngine::reduceDelay(unsigned int max_size, unsigned int initial_delay) { + assert (delay_selectors.find(initial_delay) != delay_selectors.end()); + std::vector last_model; + for( auto it = delay_selectors.find(initial_delay); it != delay_selectors.end(); ++it ) { + int d = it->first; + double timeout = getDynamicTimeout(max_size); + int status = existsReplacement(max_size, d, timeout); + if (status == 10) { + last_model = solver.getModel(); + } else { + break; + } + } + return last_model; + } + + std::vector DelayEngine::getAssumptions(unsigned int delay) { + std::vector assumptions; + for (auto const& [d, ds] : delay_selectors) { + if (d > delay) { + assumptions.push_back(-ds); + } + } + return assumptions; + } + + std::vector DelayEngine::getAssumptions(unsigned int size, unsigned int delay) { + std::vector assumptions = getAssumptions(delay); + std::vector area_assumptions = getSizeAssumption(size); + assumptions.insert(assumptions.end(), area_assumptions.begin(), area_assumptions.end()); + return assumptions; + } + + unsigned int DelayEngine::getDelayFromDelayVariables(const std::vector& model) { + unsigned int delay = 0; + for (auto const& [d, dvars] : delays2delay_variables) { + for (int v : dvars) { + if (model[v]) { + return d; + } + } + } + return delay; + } + + int DelayEngine::existsReplacement(unsigned int delay, double timeout) { + std::vector assumptions = getAssumptions(delay); + int status = timeout == 0 ? solver.solve(assumptions) : solver.solve(timeout, assumptions); + unsigned int size = status == 10 ? getSizeFromActivationVars() : max_size; + logRun(status, size); + return status; + } + + int DelayEngine::existsReplacement(unsigned int size, unsigned int delay, double timeout) { + std::vector assumptions = getAssumptions(size, delay); + int status = timeout == 0 ? solver.solve(assumptions) : solver.solve(timeout, assumptions); + logRun(status, size); + return status; + } + + void DelayEngine::setupVariables() { + for (int i = 0; i < max_size; i++) { + std::vector> dvars; + for (int j = 0; j < unique_arrival_times.size(); j++) { + dvars.push_back(getNewVariableVector(i + 1)); + } + delay_variables.push_back(dvars); + } + for (int i = 0; i < subcir.outputs.size(); i++) { + std::vector> dvars; + for (int j = 0; j < unique_arrival_times.size(); j++) { + dvars.push_back(getNewVariableVector(max_size + 1)); + } + output_delays.push_back(dvars); + } + } + + int DelayEngine::getDelaySelector(int delay) { + if (delay_selectors.find(delay) == delay_selectors.end()) { + delay_selectors[delay] = getNewVariable(); + } + return delay_selectors[delay]; + } + + + void DelayEngine::constrainDelayVariables() { + for (int i = 0; i < max_size; i++) { + int activation_variable = gate_activation_variables[i]; + for (int j = 0; j < subcir.inputs.size(); j++) { + solver.addClause({-activation_variable, -selection_variables[i][j], delay_variables[i][inputid2uniqueid[j]][0]}); + } + for (int j = 0; j < unique_arrival_times.size(); j++) { + for (int k = 0; k < i; k++) { + int node_id = subcir.inputs.size() + k; + for (int l = 0; l <= k; l++) { + solver.addClause({-activation_variable, -selection_variables[i][node_id], -delay_variables[k][j][l], delay_variables[i][j][l+1]}); + } + solver.addClause({-activation_variable, -delay_variables[i][j][k+1], delay_variables[i][j][k]}); + } + } + } + for (int i = 0; i < subcir.outputs.size(); i++) { + for (int j = 0; j < subcir.inputs.size(); j++) { + solver.addClause({-gate_output_variables[max_size + j][i], output_delays[i][inputid2uniqueid[j]][0]}); + } + for (int j = 0; j < unique_arrival_times.size(); j++) { + for (int k = 0; k < max_size; k++) { + solver.addClause({-output_delays[i][j][k+1], output_delays[i][j][k]}); + for (int l = 0; l <= k; l++) { + solver.addClause({-gate_output_variables[k][i], -delay_variables[k][j][l], output_delays[i][j][l+1]}); + } + } + } + } + } + + void DelayEngine::setupDelayConstraints() { + for (int i = 0; i < unique_arrival_times.size(); i++) { + for (int o = 0; o < subcir.outputs.size(); o++) { + for (int d = 0; d <= max_size; d++) { + int delay = unique_arrival_times[i] + subcir.remaining_times[o] + d; + int ds = getDelaySelector(delay); + solver.addClause({ds, -output_delays[o][i][d]}); + + delays2delay_variables[delay].push_back(output_delays[o][i][d]); + } + } + } + } + +} +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/opt/eslim/delayEngine.hpp b/src/opt/eslim/delayEngine.hpp new file mode 100644 index 0000000000..66f9dc464e --- /dev/null +++ b/src/opt/eslim/delayEngine.hpp @@ -0,0 +1,81 @@ +/**CFile**************************************************************** + + FileName [delayEngine.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Implementation of delay based SAT encoding.] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__OPT__ESLIM__DELAYENGINE_hpp +#define ABC__OPT__ESLIM__DELAYENGINE_hpp + +#include + +#include "misc/util/abc_global.h" + +#include "relationSynthesiser.hpp" + + +ABC_NAMESPACE_CXX_HEADER_START +namespace eSLIM { + + class DelayEngine : public RelationSynthesiser { + + public: + // Find a replacement with at most max_size gates that yields minimum delay + static eSLIMCirMan synthesizeMinimumDelayCircuit(const Relation& relation, const Subcircuit& subcir, unsigned int delay, unsigned int max_size, const eSLIMConfig& cfg, eSLIMLog& log); + // Find a replacement with at most max_size gates that yields minimum delay. Among these circuits find one of minimum size + static eSLIMCirMan synthesizeMinimumDelayAreaCircuit(const Relation& relation, const Subcircuit& subcir, unsigned int delay, unsigned int max_size, const eSLIMConfig& cfg, eSLIMLog& log); + // First minimize area, then minimize delay + static eSLIMCirMan synthesizeMinimumAreaDelayCircuit(const Relation& relation, const Subcircuit& subcir, const eSLIMConfig& cfg, eSLIMLog& log); + // Find a smaller replacement that must not increase delay + static eSLIMCirMan synthesizeMinimumAreaDelayConstraintCircuit(const Relation& relation, const Subcircuit& subcir, unsigned int delay, const eSLIMConfig& cfg, eSLIMLog& log); + + private: + + std::vector unique_arrival_times; + std::vector inputid2uniqueid; + unsigned int max_delay; + int symmetry_selector; + int symmetry_selector_assignment; + // Indicate the length of the longest paths from inputs to gates + std::vector>> delay_variables; + std::vector>> output_delays; + + std::map> delay_selectors; + std::map, std::greater> delays2delay_variables; + + DelayEngine(const Relation& relation, const Subcircuit& subcir, unsigned int max_size, const eSLIMConfig& cfg, eSLIMLog& log); + int existsReplacement(unsigned int size, unsigned int delay, double timeout); + int existsReplacement(unsigned int delay, double timeout); + std::vector getAssumptions(unsigned int delay); + std::vector getAssumptions(unsigned int size, unsigned int delay); + void setupVariables(); + + unsigned int getDelayFromDelayVariables(const std::vector& model); + + std::vector reduceArea(unsigned int max_delay, unsigned int initial_area); + std::vector reduceDelay(unsigned int max_size, unsigned int initial_delay); + + int getDelaySelector(int delay); + void setupDelayConstraints(); + void constrainDelayVariables(); + + }; + + +} +ABC_NAMESPACE_CXX_HEADER_END +#endif \ No newline at end of file diff --git a/src/opt/eslim/eSLIM.cpp b/src/opt/eslim/eSLIM.cpp index 3eea6eaa1b..764c822e1c 100644 --- a/src/opt/eslim/eSLIM.cpp +++ b/src/opt/eslim/eSLIM.cpp @@ -12,204 +12,609 @@ Affiliation [University of Freiburg] - Date [Ver. 1.0. Started - March 2025.] + Date [Ver. 1.0. Started - April 2026.] - Revision [$Id: eSLIM.cpp,v 1.00 2025/03/17 00:00:00 Exp $] + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] ***********************************************************************/ + #include "utils.hpp" #include "eSLIMMan.hpp" #include "relationGeneration.hpp" -#include "selectionStrategy.hpp" +#include "selectionStrategies.hpp" +#include "windowMan.hpp" #include "misc/util/abc_namespaces.h" +#include "opt/mfs/mfs.h" +#include "base/main/main.h" #include "eSLIM.h" +#include "eslimCirMan.hpp" +#include "synthesisEngines.hpp" +#include "selectionStrategies.hpp" ABC_NAMESPACE_HEADER_START Gia_Man_t * Gia_ManDeepSyn( Gia_Man_t * pGia, int nIters, int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fChoices, int fVerbose ); + int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ); ABC_NAMESPACE_HEADER_END ABC_NAMESPACE_IMPL_START eSLIM::eSLIMConfig getCfg(const eSLIM_ParamStruct* params) { eSLIM::eSLIMConfig config; - config.extended_normality_processing = params->extended_normality_processing; config.apply_strash = params->apply_strash; config.fill_subcircuits = params->fill_subcircuits; config.fix_seed = params->fix_seed; config.trial_limit_active = params->trial_limit_active; config.timeout = params->timeout; config.iterations = params->iterations; - config.subcircuit_size_bound = params->subcircuit_size_bound; + config.subcircuit_max_size = params->subcircuit_max_size; + config.additional_gates = params->additional_gates; config.strash_intervall = params->strash_intervall; config.nselection_trials = params->nselection_trials; config.seed = params->seed; config.verbosity_level = params->verbosity_level; config.expansion_probability = params->expansion_probability; + config.approximate_relation = params->approximate_relation; + config.relation_tfo_bound = params->relation_tfo_bound; + config.generate_relation_with_tfi_limit = params->generate_relation_with_tfi_limit; + config.relation_tfi_bound = params->relation_tfi_bound; + config.nwindows = params->nWindows; + config.window_size = params->window_size; + + config.aig = params->aig; + config.gate_size = params->gate_size; + + if (params->use_taboo_list) { + config.apply_strash = false; + } + return config; } void seteSLIMParams(eSLIM_ParamStruct* params) { - params->forbidden_pairs = 1; - params->extended_normality_processing = 0; + params->fill_subcircuits = 0; params->apply_strash = 1; params->fix_seed = 0; params->trial_limit_active = 1; params->apply_inprocessing = 1; - params->timeout = 1620; - params->timeout_inprocessing = 180; + params->synthesis_approach = 0; + params->seed = 0; + params->verbosity_level = 1; + params->use_taboo_list = 0; + params->forward_search = 0; + + params->nWindows = 0; + params->window_size = 500; + + params->criticial_path_selection_bias = 0; + + params->timeout = 1800; params->iterations = 0; - params->subcircuit_size_bound = 6; + params->subcircuit_max_size = 6; + params->additional_gates = 0; params->strash_intervall = 100; params->nselection_trials = 100; params->nruns = 1; - params->mode = 0; - params->seed = 0; - params->verbosity_level = 1; - params->expansion_probability = 0.4; -} - -Gia_Man_t* selectApproach(Gia_Man_t* pGia, eSLIM::eSLIMConfig params, eSLIM::eSLIMLog& log, int approach, bool allow_forbidden_pairs) { - switch (approach) { - case 0 : - if (allow_forbidden_pairs) { - return eSLIM::eSLIM_Man::applyeSLIM(pGia, params, log); - } else { - return eSLIM::eSLIM_Man::applyeSLIM(pGia, params, log); - }; - case 1: - if (allow_forbidden_pairs) { - return eSLIM::eSLIM_Man::applyeSLIM(pGia, params, log); - } else { - return eSLIM::eSLIM_Man::applyeSLIM(pGia, params, log); - }; - case 2: - if (allow_forbidden_pairs) { - return eSLIM::eSLIM_Man::applyeSLIM(pGia, params, log); - } else { - return eSLIM::eSLIM_Man::applyeSLIM(pGia, params, log); - }; - default: - std::cerr << "eSLIM -- Invalid mode given\n"; - assert (false && "Invalid approach selected"); - return nullptr; - } + + params->expansion_probability = 0.5; + params->approximate_relation = 0; + params->relation_tfo_bound = 0; + params->generate_relation_with_tfi_limit = 0; + params->relation_tfi_bound = 0; + + params->aig = 1; + params->gate_size = 2; } -Gia_Man_t* runInprocessing(Gia_Man_t * pGia, const eSLIM_ParamStruct* params, unsigned int it) { - Gia_Man_t * tmp = Gia_ManDeepSyn( pGia, 1, ABC_INFINITY, params->timeout_inprocessing, 0, params->seed + it, 0, 0, 0); - if ( Gia_ManAndNum(pGia) > Gia_ManAndNum(tmp) ) { - Gia_ManStop( pGia ); - pGia = tmp; - } else { - Gia_ManStop( tmp ); +namespace eSLIM { + + class DeepsynInprocessor { + public: + DeepsynInprocessor(eSLIMConfig& config); + void setTimeout(int timeout) {this->timeout = timeout;} + void runInprocessing(eSLIMCirMan& es_man); + private: + eSLIMConfig& config; + int timeout; + }; + + class MfsInprocessor { + public: + MfsInprocessor(eSLIMConfig& config) {} + void runInprocessing(eSLIMCirMan& es_man); + }; + + class EmptyInprocessor { + public: + EmptyInprocessor(eSLIMConfig& config) {} + void runInprocessing(eSLIMCirMan& es_man) {} + }; + + template + class DelayInprocessor { + public: + DelayInprocessor(eSLIMConfig& config); + void setTimeout(int timeout) {this->timeout = timeout;} + void runInprocessing(eSLIMCirMan& es_man); + private: + eSLIMConfig& config; + int timeout; + }; + + class Resyn2Inprocessor { + public: + Resyn2Inprocessor(eSLIMConfig& config); + void runInprocessing(eSLIMCirMan& es_man); + private: + // eSLIMConfig& config; + }; + + + template + class eSLIMRun { + + public: + static Gia_Man_t* runeSLIM(Gia_Man_t* cir, const eSLIM_ParamStruct* params); + static Abc_Ntk_t * runeSLIM(Abc_Ntk_t * cir, const eSLIM_ParamStruct* params); + static Abc_Ntk_t * runeSLIMCells(Abc_Ntk_t * cir, const eSLIM_ParamStruct* params); + + private: + eSLIMCirMan es_man; + eSLIMConfig config; + eSLIMLog log; + Inprocessor inprocessor; + + int initial_area; + int initial_delay; + + int area_change_eslim = 0; + int area_change_inprocessing = 0; + + int delay_change_eslim = 0; + int delay_change_inprocessing = 0; + + int nruns = 0; + + eSLIMRun(Gia_Man_t* cir, const eSLIM_ParamStruct* params); + eSLIMRun(Abc_Ntk_t* cir, const eSLIM_ParamStruct* params, bool simplify); + + void setUpInprocessor(); + void runInprocessing(); + + void printSettings(); + void printLog(); + + void run(); + }; + + + template + eSLIMRun::eSLIMRun(Abc_Ntk_t* cir, const eSLIM_ParamStruct* params, bool simplify_circuit) + : es_man(cir, simplify_circuit), config(getCfg(params)), log(params->subcircuit_max_size), inprocessor(config) { + nruns = params->nruns; + config.aig = false; + config.apply_strash = false; } - return pGia; -} -void printSetting(const eSLIM_ParamStruct* params) { - std::cout << "Apply eSLIM (timeout: " << params->timeout << ") "; - if (params->apply_inprocessing) { - std::cout << "+ deepsyn (timeout: " << params->timeout_inprocessing << ") "; + template + eSLIMRun::eSLIMRun(Gia_Man_t* cir, const eSLIM_ParamStruct* params) + : es_man(cir), config(getCfg(params)), log(params->subcircuit_max_size), inprocessor(config) { + nruns = params->nruns; } - std::cout << params->nruns << " times.\n"; - if (params->iterations > 0) { - std::cout << "Stop eSLIM runs after " << params->iterations << " iterations.\n"; + + template + Gia_Man_t* eSLIMRun::runeSLIM(Gia_Man_t* cir, const eSLIM_ParamStruct* params) { + + eSLIMRun eslim_run(cir, params); + // It seems like the variables are freed by abc during preprocessing. Thus,we copy them + char* name = Abc_UtilStrsav( cir->pName ); + char* spec = Abc_UtilStrsav( cir->pSpec ); + eslim_run.run(); + Gia_Man_t* gia_res = eslim_run.es_man.eSLIMCirManToGia(); + gia_res->pName = name; + gia_res->pSpec = spec; + return gia_res; } - std::cout << "Consider subcircuits with up to " << params->subcircuit_size_bound << " gates.\n"; - printf("When expanding subcircuits, select gates with a probability of %.2f %%.\n", 100 * params->expansion_probability); - if (params->forbidden_pairs) { - std::cout << "Consider subcircuits containing gates, which are connected outside of the subcircuit.\n"; + + template + Abc_Ntk_t* eSLIMRun::runeSLIM(Abc_Ntk_t* cir, const eSLIM_ParamStruct* params) { + bool simplify_circuit = true; + eSLIMRun eslim_run(cir, params, simplify_circuit); + eslim_run.config.aig = false; + eslim_run.config.apply_strash = false; + eslim_run.run(); + Abc_Ntk_t* ntk_res = eslim_run.es_man.eSLIMCirManToNtk(); + ntk_res->pName = Extra_UtilStrsav(cir->pName); + ntk_res->pSpec = Extra_UtilStrsav(cir->pSpec); + return ntk_res; } - if (params->mode == 0) { - std::cout << "Use an incremental SAT encoding for exact synthesis and the SAT solver CaDiCaL.\n"; - } else { - std::cout << "Use a one-shot SAT encoding for exact synthesis and the SAT solver Kissat.\n"; + + template + Abc_Ntk_t * eSLIMRun::runeSLIMCells(Abc_Ntk_t * cir, const eSLIM_ParamStruct* params) { + bool simplify_circuit = false; + eSLIMRun eslim_run(cir, params, simplify_circuit); + eslim_run.config.aig = false; + eslim_run.config.apply_strash = false; + eslim_run.run(); + Abc_Ntk_t* ntk_res = eslim_run.es_man.eSLIMCirManToMappedNtk(); + if (!ntk_res) { + return ntk_res; + } + ntk_res->pName = Extra_UtilStrsav(cir->pName); + ntk_res->pSpec = Extra_UtilStrsav(cir->pSpec); + return ntk_res; } -} -Gia_Man_t* applyeSLIM(Gia_Man_t * pGia, const eSLIM_ParamStruct* params) { - eSLIM::eSLIMConfig config = getCfg(params); - config.verbosity_level = params->verbosity_level; + template + void eSLIMRun::run() { + if constexpr ( std::is_same_v || std::is_same_v, Inprocessor> || std::is_same_v, Inprocessor> ) { + int time_out_inprocessing; + if constexpr ( std::is_same_v ) { + time_out_inprocessing = config.timeout * 0.1; + } else { + time_out_inprocessing = config.timeout * 0.02; + } + config.timeout -= time_out_inprocessing; + inprocessor.setTimeout(time_out_inprocessing); + } - int eSLIM_reductions = 0; - int deepsyn_reductions = 0; + initial_area = es_man.getNofGates(); + initial_delay = es_man.getDepth(); + printSettings(); + for (int i = 0; i < nruns; i++) { - Gia_Man_t * pThis = Gia_ManDup(pGia); - eSLIM::eSLIMLog log(params->subcircuit_size_bound); - int initial_size = Gia_ManAndNum(pThis); - if (params->verbosity_level > 0) { - printSetting(params); - std::cout << "Initial size: " << initial_size << "\n"; + int size_iteration_start = es_man.getNofGates(); + int delay_iteration_start = es_man.getDepth(); + if (config.verbosity_level > 0) { + std::cout << "Start eslim run " << i + 1 << "\n"; + } + Approach::applyeSLIM(es_man, config, log); + int size_eslim = es_man.getNofGates(); + int delay_eslim = es_man.getDepth(); + area_change_eslim += size_eslim - size_iteration_start; + delay_change_eslim += delay_eslim - delay_iteration_start; + if (config.verbosity_level > 0) { + std::cout << "eslim -- size: " << size_eslim << " delay: " << delay_eslim << "\n"; + } + runInprocessing(); + if constexpr ( !std::is_same_v ) { + int size_inprocessing = es_man.getNofGates(); + int delay_inprocessing = es_man.getDepth(); + area_change_inprocessing += size_inprocessing - size_eslim; + delay_change_inprocessing += delay_inprocessing - delay_eslim; + if (config.verbosity_level > 0) { + std::cout << "inprocessing -- size: " << size_inprocessing << " delay: " << delay_inprocessing << "\n"; + } + } + if (config.fix_seed) { + config.seed++; + } + } + printLog(); } - for (unsigned int i = 0; i < params->nruns; i++) { - if (config.fix_seed) { - config.seed = params->seed + i; + + template + void eSLIMRun::printSettings() { + std::cout << "Apply eSLIM (timeout: " << config.timeout << ") "; + std::cout << nruns << " times.\n"; + if constexpr ( !std::is_same_v ) { + std::cout << "Apply inprocessing\n"; } - int size_iteration_start = Gia_ManAndNum(pThis); - if (params->verbosity_level > 0) { - std::cout << "Start eslim run " << i + 1 << "\n"; + if (config.iterations > 0) { + std::cout << "Stop eSLIM runs after " << config.iterations << " iterations.\n"; } - pThis = selectApproach(pThis, config, log, params->mode, params->forbidden_pairs); - int size_eslim = Gia_ManAndNum(pThis); - eSLIM_reductions += size_iteration_start - size_eslim; + std::cout << "Consider subcircuits with up to " << config.subcircuit_max_size << " gates.\n"; + printf("When expanding subcircuits, select gates with a probability of %.2f %%.\n", 100 * config.expansion_probability); + } + + template + void eSLIMRun::printLog() { + if (config.verbosity_level > 0) { + int size = es_man.getNofGates(); + int delay = es_man.getDepth(); + int total_area_change = area_change_eslim + area_change_inprocessing; + int total_delay_change = delay_change_eslim + delay_change_inprocessing; + std::cout << "Final size: " << size << " change: " << total_area_change << "\n"; + std::cout << "Final depth: " << delay << " change: " << total_delay_change << "\n"; + - if (params->apply_inprocessing) { - if (params->verbosity_level > 0) { - std::cout << "Start inprocessing run " << i + 1 << "\n"; + if constexpr ( !std::is_same_v ) { + + if (area_change_eslim <= 0) { + std::cout << "#Gates reduced by eSLIM: " << -area_change_eslim << "\n"; + } else { + std::cout << "#Gates introduced by eSLIM: " << area_change_eslim << "\n"; + } + if (area_change_inprocessing <= 0) { + std::cout << "#Gates reduced by inprocessing: " << -area_change_inprocessing << "\n"; + } else { + std::cout << "#Gates introduced by inprocessing: " << area_change_inprocessing << "\n"; + } + if (delay_change_eslim <= 0) { + std::cout << "Delay reduction eSLIM: " << -delay_change_eslim << "\n"; + } else { + std::cout << "Delay increase eSLIM: " << delay_change_eslim << "\n"; + } + if (delay_change_inprocessing <= 0) { + std::cout << "Delay reduction inprocessing: " << -delay_change_inprocessing << "\n"; + } else { + std::cout << "Delay increase inprocessing: " << delay_change_inprocessing << "\n"; + } } - pThis = runInprocessing(pThis, params, i); - if (params->verbosity_level > 0) { - std::cout << "Inprocessing: Initial size: " << size_eslim << " final size: " << Gia_ManAndNum(pThis) << "\n"; + } + if (config.verbosity_level > 1) { + std::cout << "Total #iterations: " << log.iteration_count << "\n"; + std::cout << "Total relation generation time (s): " << log.relation_generation_time << "\n"; + std::cout << "Total synthesis time (s): " << log.synthesis_time << "\n"; + std::cout << "#Iterations with forbidden pairs: " << log.subcircuits_with_forbidden_pairs << "\n"; + printf("Relation generation: #SAT-calls: %lu, Total SAT-time: %.2f sec, Max SAT-time: %.4f sec, Avg. SAT-time: %.4f sec\n", + log.nof_sat_calls_relation_generation, log.cummulative_sat_runtime_relation_generation, log.max_sat_runtime_relation_generation, + log.cummulative_sat_runtime_relation_generation/log.nof_sat_calls_relation_generation); + printf("Synthesis: #SAT-calls: %lu, Total SAT-time: %.2f sec, Max SAT-time: %.4f sec, Avg. SAT-time: %.4f sec\n", + log.nof_sat_calls_synthesis, log.cummulative_sat_runtime_synthesis / 1000, log.max_sat_runtime_synthesis / 1000, + log.cummulative_sat_runtime_synthesis / (log.nof_sat_calls_synthesis*1000)); + } + if (config.verbosity_level > 2) { + for (int i = 2; i < log.nof_analyzed_circuits_per_size.size(); i++) { + int replaced = log.nof_replaced_circuits_per_size.size() > i ? log.nof_replaced_circuits_per_size[i] : 0; + int reduced = log.nof_reduced_circuits_per_size.size() > i ? log.nof_reduced_circuits_per_size[i] : 0; + std::cout << "#gates: " << i << " - #analysed: " << log.nof_analyzed_circuits_per_size[i] << " - #replaced: " << replaced << " - #reduced: " << reduced; + std::cout << " - avg. relation time: "; + if (log.nof_relation_generations_per_size[i] == 0) { + std::cout << "-"; + } else { + printf("%.2f sec", static_cast(log.cummulative_relation_generation_times_per_size[i]) / (log.nof_relation_generations_per_size[i])); + } + std::cout << "\n"; } - deepsyn_reductions += size_eslim - Gia_ManAndNum(pThis); - } - } - if (params->verbosity_level > 0) { - int final_size = Gia_ManAndNum(pThis); - std::cout << "Final size: " << final_size << "\n"; - int total_reductions = eSLIM_reductions + deepsyn_reductions; - double reduction_ratio = 100 * static_cast(total_reductions) / initial_size; - printf("Total reduction: %d (%.2f %%)\n", total_reductions, reduction_ratio); - if (params->apply_inprocessing) { - std::cout << "#Gates reduced by eSLIM: " << eSLIM_reductions << " "; - std::cout << "#Gates reduced by deepsyn: " << deepsyn_reductions << "\n"; - } - } - - if (params->verbosity_level > 1) { - std::cout << "Total #iterations: " << log.iteration_count << "\n"; - std::cout << "Total relation generation time (s): " << log.relation_generation_time << "\n"; - std::cout << "Total synthesis time (s): " << log.synthesis_time << "\n"; - std::cout << "#Iterations with forbidden pairs: " << log.subcircuits_with_forbidden_pairs << "\n"; - } - if (params->verbosity_level > 2) { - for (int i = 2; i < log.nof_analyzed_circuits_per_size.size(); i++) { - int replaced = log.nof_replaced_circuits_per_size.size() > i ? log.nof_replaced_circuits_per_size[i] : 0; - int reduced = log.nof_reduced_circuits_per_size.size() > i ? log.nof_reduced_circuits_per_size[i] : 0; - std::cout << "#gates: " << i << " - #analysed: " << log.nof_analyzed_circuits_per_size[i] << " - #replaced: " << replaced << " - #reduced: " << reduced << "\n"; - } - if (params->mode == 0) { for (int i = 0; i < log.nof_sat_calls_per_size.size(); i++) { + std::cout << "#gates: " << i << " - avg. sat time: "; if (log.nof_sat_calls_per_size[i] == 0) { - std::cout << "#gates: " << i << " - avg. sat time: -\n"; + std::cout << "-"; } else { - std::cout << "#gates: " << i << " - avg. sat time: " << static_cast(log.cummulative_sat_runtimes_per_size[i]) / (1000 * log.nof_sat_calls_per_size[i]) << " sec\n"; + printf("%.2f sec", static_cast(log.cummulative_sat_runtimes_per_size[i]) / (1000 * log.nof_sat_calls_per_size[i])); } - } - for (int i = 0; i < log.nof_unsat_calls_per_size.size(); i++) { + std::cout << " / avg. unsat time: "; if (log.nof_unsat_calls_per_size[i] == 0) { - std::cout << "#gates: " << i << " - avg. unsat time: -\n"; + std::cout << "-"; } else { - std::cout << "#gates: " << i << " - avg. unsat time: " << static_cast(log.cummulative_unsat_runtimes_per_size[i]) / (1000* log.nof_unsat_calls_per_size[i]) << " sec\n"; + printf("%.2f sec", static_cast(log.cummulative_unsat_runtimes_per_size[i]) / (1000 * log.nof_unsat_calls_per_size[i])); } + std::cout << "\n"; } } } - return pThis; + + template + void eSLIMRun::runInprocessing() { + inprocessor.runInprocessing(es_man); + } + + template + void setUpInprocessor(); + + DeepsynInprocessor::DeepsynInprocessor(eSLIMConfig& config) + : config(config) { + } + + void DeepsynInprocessor::runInprocessing(eSLIMCirMan& es_man) { + Gia_Man_t* pGia = es_man.eSLIMCirManToGia(); + Gia_Man_t* tmp = Gia_ManDeepSyn( pGia, 1, ABC_INFINITY, timeout, 0, config.seed , 0, 0, 0); + if ( Gia_ManAndNum(pGia) > Gia_ManAndNum(tmp) ) { + es_man = eSLIMCirMan(tmp); + } + Gia_ManStop( tmp ); + Gia_ManStop( pGia ); + } + + void MfsInprocessor::runInprocessing(eSLIMCirMan& es_man) { + Abc_Ntk_t* pNtk = es_man.eSLIMCirManToNtk(); + int nnodes = Abc_NtkNodeNum(pNtk); + Mfs_Par_t Pars, * pPars = &Pars; + Abc_NtkMfsParsDefault( pPars ); + if ( Abc_NtkMfs( pNtk, pPars ) ) { + Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); + if (Abc_NtkNodeNum(pNtk) <= nnodes) { + es_man = eSLIMCirMan(pNtk, true); + } + } + Abc_NtkDelete(pNtk); + } + + template + DelayInprocessor::DelayInprocessor(eSLIMConfig& config) + : config(config) { + } + + template + void DelayInprocessor::runInprocessing(eSLIMCirMan& es_man) { + abctime clkStart = Abc_Clock(); + abctime nTimeToStop = clkStart + timeout * CLOCKS_PER_SEC; + Gia_Man_t* pGia = es_man.eSLIMCirManToGia(); + int nand = Gia_ManAndNum(pGia); + int nlevel = Gia_ManLevelNum(pGia); + char * resyn2 = "balance; rewrite; rewrite -z; balance; rewrite -z; balance"; + char Command[2000]; + sprintf( Command, "strash; if -g -K 6; %s; if -K 6", resyn2 ); + bool reset_batch_mode = false ; + if ( !Abc_FrameIsBatchMode() ) { + reset_batch_mode = true; + Abc_FrameSetBatchMode( 1 ); + } + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pGia ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), "&put") ) { + return; + } + while (Abc_Clock() <= nTimeToStop) { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return; + } + } + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), "&get") ) { + return; + } + if (reset_batch_mode) { + Abc_FrameSetBatchMode( 0 ); + } + Gia_Man_t* tmp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + if constexpr (!IncreaseSize) { + if (Gia_ManAndNum(tmp) > nand) { + return; + } + } + if (Gia_ManLevelNum(tmp) <= nlevel) { + es_man = eSLIMCirMan(tmp); + } + } + + Resyn2Inprocessor::Resyn2Inprocessor(eSLIMConfig& config) + // : config(config) + { + } + + void Resyn2Inprocessor::runInprocessing(eSLIMCirMan& es_man) { + Gia_Man_t* pGia = es_man.eSLIMCirManToGia(); + int nand = Gia_ManAndNum(pGia); + int nlevel = Gia_ManLevelNum(pGia); + char * resyn2 = "balance; rewrite; rewrite -z; balance; rewrite -z; balance"; + bool reset_batch_mode = false ; + if ( !Abc_FrameIsBatchMode() ) { + reset_batch_mode = true; + Abc_FrameSetBatchMode( 1 ); + } + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pGia ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), "&put") ) { + return; + } + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), resyn2) ) { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", resyn2 ); + return; + } + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), "&get") ) { + return; + } + if (reset_batch_mode) { + Abc_FrameSetBatchMode( 0 ); + } + Gia_Man_t* tmp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + if (Gia_ManAndNum(tmp) <= nand && Gia_ManLevelNum(tmp) <= nlevel) { + es_man = eSLIMCirMan(tmp); + } + } + + + + template + Circuitrepresentation* runeSLIM(Circuitrepresentation * cir, const eSLIM_ParamStruct* params) { + return eSLIMRun::runeSLIM(cir, params); + } + + template + Circuitrepresentation* toggleWindowing(Circuitrepresentation * cir, const eSLIM_ParamStruct* params) { + if (params->nWindows > 0) { + return runeSLIM>>(cir, params); + } else { + return runeSLIM>>(cir, params); + } + } + + + template + Circuitrepresentation* setTabooApproach(Circuitrepresentation * cir, const eSLIM_ParamStruct* params) { + if (params->use_taboo_list) { + return toggleWindowing(cir, params); + } else { + return toggleWindowing(cir, params); + } + } + + template + Circuitrepresentation* setBiasApproach(Circuitrepresentation * cir, const eSLIM_ParamStruct* params) { + if (params->criticial_path_selection_bias) { + return toggleWindowing(cir, params); + } else { + return setTabooApproach(cir, params); + } + } + + + + template + Circuitrepresentation* setSearchDirection(Circuitrepresentation * cir, const eSLIM_ParamStruct* params) { + if (params->forward_search) { + return setBiasApproach(cir, params); + } else { + return setBiasApproach(cir, params); + } + } + + template + Circuitrepresentation* setMinimizer(Circuitrepresentation * cir, const eSLIM_ParamStruct* params) { + switch (params->synthesis_approach) { + case 0: + if (params->apply_inprocessing) { + if constexpr ( std::is_same_v ) { + return setSearchDirection(cir, params); + } else { + return setSearchDirection(cir, params); + } + } + return setSearchDirection(cir, params); + case 1: + if constexpr ( std::is_same_v ) { + if (params->apply_inprocessing) { + return setSearchDirection(cir, params); + } + } + return setSearchDirection(cir, params); + case 2: + if constexpr ( std::is_same_v ) { + if (params->apply_inprocessing) { + return setSearchDirection, AreaDelayMinimizer, SubcircuitNoFBValidator>(cir, params); + } + } + return setSearchDirection(cir, params); + case 3: + if constexpr ( std::is_same_v ) { + if (params->apply_inprocessing) { + return setSearchDirection, DelayMinimizer, SubcircuitNoFBValidator>(cir, params); + } + } + return setSearchDirection(cir, params); + default: + assert(false); + return NULL; + } + } } -ABC_NAMESPACE_IMPL_END \ No newline at end of file +template +Circuitrepresentation* runeSLIM(Circuitrepresentation * cir, const eSLIM_ParamStruct* params) { + // Windowing does currently not support Deleyconstraints/Delayoptimisation + if (params->nWindows && params->synthesis_approach != 0) { + return NULL; + } + return eSLIM::setMinimizer(cir, params); +} + + +Gia_Man_t* applyeSLIM(Gia_Man_t * pGia, const eSLIM_ParamStruct* params) { + if (Gia_ManHasDangling(pGia)) { + std::cout << "Warning: Circuit must not contain dangling nodes.\n"; + return pGia; + } + return runeSLIM(pGia, params); +} + +Abc_Ntk_t* applyelSLIM(Abc_Ntk_t * ntk, const eSLIM_ParamStruct* params) { + return runeSLIM(ntk, params); +} + + + + +ABC_NAMESPACE_IMPL_END diff --git a/src/opt/eslim/eSLIM.h b/src/opt/eslim/eSLIM.h index 857e32f476..a0e96de71d 100644 --- a/src/opt/eslim/eSLIM.h +++ b/src/opt/eslim/eSLIM.h @@ -12,9 +12,9 @@ Affiliation [University of Freiburg] - Date [Ver. 1.0. Started - March 2025.] + Date [Ver. 1.0. Started - April 2026.] - Revision [$Id: eSLIM.h,v 1.00 2025/03/17 00:00:00 Exp $] + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] ***********************************************************************/ @@ -23,39 +23,52 @@ #include "misc/util/abc_namespaces.h" #include "aig/gia/gia.h" +#include "base/abc/abc.h" ABC_NAMESPACE_HEADER_START typedef struct eSLIM_ParamStruct_ eSLIM_ParamStruct; struct eSLIM_ParamStruct_ { - int forbidden_pairs; // Allow forbidden pairs in the selected subcircuits - int extended_normality_processing; // Additional checks for non normal subcircuits - int fill_subcircuits; // If a subcircuit has fewer than subcircuit_size_bound gates, try to fill it with rejected gates. + int fill_subcircuits; // If a subcircuit has fewer than subcircuit_max_size gates, try to fill it with rejected gates. int apply_strash; int fix_seed; int trial_limit_active; int apply_inprocessing; - + int synthesis_approach; + int seed; + int verbosity_level; + int approximate_relation; + int relation_tfo_bound; + int generate_relation_with_tfi_limit; + int relation_tfi_bound; + int use_taboo_list; + int forward_search; + int nWindows; + int window_size; + + int criticial_path_selection_bias; + + unsigned int timeout; // available time in seconds (soft limit) - unsigned int timeout_inprocessing; unsigned int iterations; // maximal number of iterations. No limit if 0 - unsigned int subcircuit_size_bound; // upper bound for the subcircuit sizes - unsigned int strash_intervall; - unsigned int nselection_trials; - unsigned int nruns; + unsigned int subcircuit_max_size; // upper bound for the subcircuit sizes + unsigned int additional_gates; // number of gates that may be introduced to reduce delay double expansion_probability; // the probability that a node is added to the subcircuit + unsigned int nruns; + + unsigned int strash_intervall; + unsigned int nselection_trials; - int mode; // 0: Cadical Incremental, 1: Kissat Oneshot - int seed; - int verbosity_level; + int gate_size; + int aig; }; void seteSLIMParams(eSLIM_ParamStruct* params); Gia_Man_t* applyeSLIM(Gia_Man_t * pGia, const eSLIM_ParamStruct* params); - Gia_Man_t* applyeSLIMIncremental(Gia_Man_t * pGia, const eSLIM_ParamStruct* params, unsigned int restarts, unsigned int deepsynTimeout); + Abc_Ntk_t* applyelSLIM(Abc_Ntk_t * ntk, const eSLIM_ParamStruct* params); //LUT-eSLIM ABC_NAMESPACE_HEADER_END diff --git a/src/opt/eslim/eSLIMMan.hpp b/src/opt/eslim/eSLIMMan.hpp index 22114dd093..562d33a804 100644 --- a/src/opt/eslim/eSLIMMan.hpp +++ b/src/opt/eslim/eSLIMMan.hpp @@ -26,67 +26,51 @@ #include #include "misc/util/abc_namespaces.h" -#include "misc/vec/vec.h" #include "aig/gia/gia.h" -#include "misc/util/utilTruth.h" // ioResub.h depends on utilTruth.h -#include "base/io/ioResub.h" -#include "aig/miniaig/miniaig.h" + +#include "eslimCirMan.hpp" +#include "relationGeneration.hpp" +#include "selectionStrategies.hpp" +#include "subcircuit.hpp" #include "utils.hpp" -#include "selectionStrategy.hpp" + ABC_NAMESPACE_CXX_HEADER_START namespace eSLIM { - template - class eSLIM_Man { + template + class eSLIM_Man { public: - static Gia_Man_t* applyeSLIM(Gia_Man_t * p, const eSLIMConfig& cfg, eSLIMLog& log); + static void applyeSLIM(eSLIMCirMan& cir, const eSLIMConfig& cfg, eSLIMLog& log); private: - eSLIM_Man(Gia_Man_t * gia_man, const eSLIMConfig& cfg, eSLIMLog& log); - Gia_Man_t* getCircuit(); - - void minimize(); - void findReplacement(); - Mini_Aig_t* findMinimumAig(const Subcircuit& subcir); + eSLIM_Man(eSLIMCirMan& es_man, const eSLIMConfig& cfg, eSLIMLog& log); - Vec_Wrd_t* getSimsIn(Abc_RData_t* relation); - Vec_Wrd_t* getSimsOut(Abc_RData_t* relation); - word getAllFalseBehaviour(const Subcircuit& subcir); - bool getAllFalseBehaviourRec(Gia_Obj_t * pObj); + void optimize(); - std::pair reduce( Vec_Wrd_t* vSimsDiv, Vec_Wrd_t* vSimsOut, const std::unordered_map>& forbidden_pairs, - int nVars, int nDivs, int nOuts, int initial_size); - Mini_Aig_t* computeReplacement( SynthesisEngine& syn_man, int size); - double getDynamicTimeout(int size); + void findReplacement(); + eSLIMCirMan computeReplacement(Subcircuit& subcir); + eSLIMCirMan synthesiseRelation(Subcircuit& subcir, const Relation& rel); - void insertReplacement(Mini_Aig_t* replacement, const Subcircuit& subcir); - std::vector processReplacement(Gia_Man_t* gia_man, Gia_Man_t* pNew, const Subcircuit& subcir, Mini_Aig_t* replacement, std::vector&& to_process, std::vector& replacement_values); - Vec_Int_t * processEncompassing(Gia_Man_t* gia_man, Gia_Man_t* pNew, Vec_Int_t* to_process); - int getInsertionLiteral(Gia_Man_t* gia_man, const Subcircuit& subcir, Mini_Aig_t* replacement, const std::vector& replacement_values, int fanin_lit); - Gia_Man_t* gia_man = nullptr; + eSLIMCirMan& es_man; + SelectionStrategy selection_strategy; const eSLIMConfig& cfg; eSLIMLog& log; - SelectionEngine subcircuit_selection; - + double relation_generation_time ; double synthesis_time ; - bool stopeSLIM=false; + bool stopeSLIM = false; + }; - template - inline Gia_Man_t* eSLIM_Man::getCircuit() { - return gia_man; - } } - ABC_NAMESPACE_CXX_HEADER_END #include "eSLIMMan.tpp" diff --git a/src/opt/eslim/eSLIMMan.tpp b/src/opt/eslim/eSLIMMan.tpp index 8eb46db5ca..f3f26c8034 100644 --- a/src/opt/eslim/eSLIMMan.tpp +++ b/src/opt/eslim/eSLIMMan.tpp @@ -14,79 +14,60 @@ Date [Ver. 1.0. Started - March 2025.] - Revision [$Id: eSLIMMan.tpp,v 1.00 2025/03/17 00:00:00 Exp $] + Revision [$Id: eSLIMMan.hpp,v 1.00 2025/03/17 00:00:00 Exp $] ***********************************************************************/ -#include -#include -#include -#include -#include -#include #include #include "eSLIMMan.hpp" -#include "synthesisEngine.hpp" -#include "relationGeneration.hpp" - - -ABC_NAMESPACE_HEADER_START - Mini_Aig_t * Mini_AigDupCompl( Mini_Aig_t * p, int ComplIns, int ComplOuts ); - int Exa6_ManFindPolar( word First, int nOuts ); - Vec_Wrd_t * Exa6_ManTransformInputs( Vec_Wrd_t * vIns ); - Vec_Wrd_t * Exa6_ManTransformOutputs( Vec_Wrd_t * vOuts, int nOuts ); -ABC_NAMESPACE_HEADER_END +#include "synthesisEngines.hpp" ABC_NAMESPACE_CXX_HEADER_START - namespace eSLIM { - template - Gia_Man_t* eSLIM_Man::applyeSLIM(Gia_Man_t * p, const eSLIMConfig& cfg, eSLIMLog& log) { - eSLIM_Man eslim(p, cfg, log); - eslim.minimize(); - return eslim.getCircuit(); + template + void eSLIM_Man::applyeSLIM(eSLIMCirMan& cir, const eSLIMConfig& cfg, eSLIMLog& log) { + eSLIM_Man eslim(cir, cfg, log); + eslim.optimize(); } - - - template - eSLIM_Man::eSLIM_Man(Gia_Man_t * pGia, const eSLIMConfig& cfg, eSLIMLog& log) - : gia_man(pGia), cfg(cfg), log(log), - subcircuit_selection(gia_man, cfg, log) { + template + eSLIM_Man::eSLIM_Man(eSLIMCirMan& es_man, const eSLIMConfig& cfg, eSLIMLog& log) + : es_man(es_man), selection_strategy(this->es_man, cfg, log), cfg(cfg), log(log) { if (cfg.fix_seed) { - subcircuit_selection.setSeed(cfg.seed); + selection_strategy.setSeed(cfg.seed); } relation_generation_time = log.relation_generation_time; synthesis_time = log.synthesis_time; } - - template - void eSLIM_Man::minimize() { + + + + template + void eSLIM_Man::optimize() { abctime clkStart = Abc_Clock(); abctime nTimeToStop = clkStart + cfg.timeout * CLOCKS_PER_SEC; unsigned int iteration = 0; unsigned int iterMax = cfg.iterations ? cfg.iterations - 1 : UINT_MAX; - int current_size = Gia_ManAndNum(gia_man); + int current_size = es_man.getNofGates(); + const char* node_type = cfg.aig ? "#and" : "#nd"; while (Abc_Clock() <= nTimeToStop && iteration <= iterMax && !stopeSLIM) { iteration++; findReplacement(); - if (Gia_ManHasDangling(gia_man)) { - Gia_Man_t* pTemp = gia_man; - gia_man = Gia_ManCleanup( pTemp ); - Gia_ManStop( pTemp ); - } if (cfg.apply_strash && iteration % cfg.strash_intervall == 0) { - Gia_Man_t* pTemp = gia_man; - gia_man = Gia_ManRehash( pTemp, 0 ); + Gia_Man_t* pTemp = es_man.eSLIMCirManToGia(); + Gia_Man_t* gia_man = Gia_ManRehash( pTemp, 0 ); Gia_ManStop( pTemp ); + es_man = eSLIMCirMan(gia_man); + Gia_ManStop( gia_man ); + selection_strategy.reset(); } if (cfg.verbosity_level > 0) { - int sz = Gia_ManAndNum(gia_man); + int sz = es_man.getNofGates(); if (sz < current_size) { current_size = sz; - printf("\rIteration %8d : #and = %7d elapsed time = %7.2f sec\n", iteration, sz, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC); + printf("\rIteration %8d : %s = %7d elapsed time = %7.2f sec\n", iteration, node_type, sz, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC); } else { printf("\rIteration %8d", iteration); fflush(stdout); @@ -95,8 +76,8 @@ namespace eSLIM { } log.iteration_count += iteration; if (cfg.verbosity_level > 0) { - int sz = Gia_ManAndNum(gia_man); - printf("\r#Iterations %8d #and = %7d elapsed time = %7.2f sec\n", iteration, sz, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC); + int sz = es_man.getNofGates(); + printf("\r#Iterations %8d %s = %7d elapsed time = %7.2f sec\n", iteration, node_type, sz, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC); if (cfg.verbosity_level > 1) { printf("Relation generation time: %.2f sec\n", log.relation_generation_time - relation_generation_time); printf("Synthesis time: %.2f sec\n", log.synthesis_time - synthesis_time); @@ -104,379 +85,57 @@ namespace eSLIM { } } - template - Vec_Wrd_t* eSLIM_Man::getSimsIn(Abc_RData_t* relation) { - Vec_Wrd_t* vSimsDiv = Vec_WrdStart( relation->nPats ); - for (int k = 0; k < relation->nIns; k++) { - for (int i = 0; i < relation->nPats; i++) { - if (Abc_RDataGetIn(relation, k, i)) { - // The first bit corresponds to the constant divisor thus we have +1 - Abc_InfoSetBit((unsigned *)Vec_WrdEntryP(vSimsDiv, i), 1+k); - } - } - } - return vSimsDiv; - } - - template - Vec_Wrd_t* eSLIM_Man::getSimsOut(Abc_RData_t* relation) { - Vec_Wrd_t* vSimsOut = Vec_WrdStart(relation->nPats); - for (int k = 0; k < (1 << relation->nOuts); k++) { - for (int i = 0; i < relation->nPats; i++) { - if (Abc_RDataGetOut(relation, k, i)) { - Abc_InfoSetBit((unsigned *)Vec_WrdEntryP(vSimsOut, i), k); - } - } - } - return vSimsOut; - } - - template - void eSLIM_Man::findReplacement() { - Subcircuit subcir = subcircuit_selection.getSubcircuit(); - if (!subcircuit_selection.getStatus()) { - if (cfg.trial_limit_active) { - stopeSLIM = true; - } - return; - } - Mini_Aig_t* replacement = findMinimumAig(subcir); - if (replacement != nullptr) { - insertReplacement(replacement, subcir); - Mini_AigStop(replacement); - } - subcir.free(); - } - - // Based on Exa_ManExactSynthesis6Int and Exa_ManExactSynthesis6 - template - Mini_Aig_t* eSLIM_Man::findMinimumAig(const Subcircuit& subcir) { - - if (subcir.forbidden_pairs.size() > 0) { - log.subcircuits_with_forbidden_pairs++; - } - + template + eSLIMCirMan eSLIM_Man::computeReplacement(Subcircuit& subcir) { abctime relation_generation_start = Abc_Clock(); - Abc_RData_t* relation = RelationGenerator::computeRelation(gia_man, subcir); + Relation rel = RelationGenerator::computeRelation(es_man, subcir, cfg, log); log.relation_generation_time += (double)1.0*(Abc_Clock() - relation_generation_start)/CLOCKS_PER_SEC; - - int nDivs = 0; - int nOuts = relation->nOuts; - int nVars = relation->nIns; - if ( nVars == 0 ) { - return nullptr; + log.cummulative_relation_generation_times_per_size[subcir.nodes.size()] += (double)1.0*(Abc_Clock() - relation_generation_start) / CLOCKS_PER_SEC; + log.nof_relation_generations_per_size[subcir.nodes.size()]++; + if (!rel.getStatus()) { + return eSLIMCirMan(0); } - // assert (nVars <= 8); - Vec_Wrd_t* vSimsDiv = getSimsIn(relation); - Vec_Wrd_t* vSimsOut = getSimsOut(relation); - - word original_all_false_behaviour = vSimsOut->pArray[0]; - // If the original circuit computed a non-normal circuit, but the relations allows to set the outputs to false in the all inputs false case - // ABC does not "negate" the relation but forces the circuit to yield (0,...,0) for (0,...,0). - // As a consequence it is not necessarily possible to find a same sized circuit. - // In order to prevent this behaviour, we first modify the relation such that for the (0,...,0) input pattern only the original output patterns is allowed. - vSimsOut->pArray[0] = getAllFalseBehaviour(subcir); - - int DivCompl = (int)Vec_WrdEntry(vSimsDiv, 0) >> 1; - int OutCompl = Exa6_ManFindPolar( Vec_WrdEntry(vSimsOut, 0), nOuts ); - Vec_Wrd_t* vSimsDiv2 = Exa6_ManTransformInputs( vSimsDiv ); - Vec_Wrd_t* vSimsOut2 = Exa6_ManTransformOutputs( vSimsOut, nOuts ); - Mini_Aig_t* pMini = nullptr; - int original_size = Vec_IntSize(subcir.nodes); - int size = original_size; - - if (log.nof_analyzed_circuits_per_size.size() < original_size + 1) { - log.nof_analyzed_circuits_per_size.resize(original_size + 1, 0); - log.nof_replaced_circuits_per_size.resize(original_size + 1, 0); - log.nof_reduced_circuits_per_size.resize(original_size + 1, 0); - } - log.nof_analyzed_circuits_per_size[original_size]++; - abctime synthesis_start = Abc_Clock(); - std::tie(size, pMini) = reduce(vSimsDiv2, vSimsOut2, subcir.forbidden_pairs, nVars, nDivs, nOuts, size); + eSLIMCirMan replacement = synthesiseRelation(subcir, rel); log.synthesis_time += (double)1.0*(Abc_Clock() - synthesis_start)/CLOCKS_PER_SEC; - - if (size > original_size) { - // Could not find a replacement. This can be caused by a timeout. - Abc_RDataStop(relation); - Vec_WrdFreeP( &vSimsDiv ); - Vec_WrdFreeP( &vSimsOut ); - Vec_WrdFreeP( &vSimsDiv2 ); - Vec_WrdFreeP( &vSimsOut2 ); - return nullptr; - } - - // It is possible that a better replacement is obtained with a non normal behaviour. - bool check_original_all_false_behaviour = cfg.extended_normality_processing && vSimsOut->pArray[0] != original_all_false_behaviour; - if (check_original_all_false_behaviour) { - vSimsOut->pArray[0] = original_all_false_behaviour; - int OutCompl_alt = Exa6_ManFindPolar( Vec_WrdEntry(vSimsOut, 0), nOuts ); - Vec_Wrd_t* vSimsOut2_alt = Exa6_ManTransformOutputs( vSimsOut, nOuts ); - abctime synthesis_start = Abc_Clock(); - // auto [sz, mini] = reduce(vSimsDiv2, vSimsOut2_alt, subcir.forbidden_pairs, nVars, nDivs, nOuts, size - 1, true); - auto result = reduce(vSimsDiv2, vSimsOut2_alt, subcir.forbidden_pairs, nVars, nDivs, nOuts, size - 1); - int sz = result.first; - Mini_Aig_t* mini = result.second; - log.synthesis_time += (double)1.0*(Abc_Clock() - synthesis_start)/CLOCKS_PER_SEC; - if (mini != nullptr) { - size = sz; - if (pMini) { - Mini_AigStop(pMini); - } - pMini = mini; - OutCompl = OutCompl_alt; - } - } - Abc_RDataStop(relation); - - if (pMini != nullptr) { - Mini_Aig_t* pTemp = pMini; - pMini = Mini_AigDupCompl(pTemp, DivCompl, OutCompl); - Mini_AigStop(pTemp); - - log.nof_replaced_circuits_per_size[original_size]++; - if (size < original_size) { - log.nof_reduced_circuits_per_size[original_size]++; - } - } - Vec_WrdFreeP( &vSimsDiv ); - Vec_WrdFreeP( &vSimsOut ); - Vec_WrdFreeP( &vSimsDiv2 ); - Vec_WrdFreeP( &vSimsOut2 ); - return pMini; + return replacement; } - template - word eSLIM_Man::getAllFalseBehaviour(const Subcircuit& subcir) { - Gia_ManIncrementTravId(gia_man); - Gia_Obj_t * pObj; - int i; - Gia_ManForEachObjVec( subcir.nodes, gia_man, pObj, i ) { - Gia_ObjSetTravIdCurrent(gia_man, pObj); - } - long assm_idx = 0; - Gia_ManForEachObjVecStart(subcir.io, gia_man, pObj, i, subcir.nof_inputs) { - int bit_idx = i - subcir.nof_inputs; - if (getAllFalseBehaviourRec(pObj)) { - assm_idx |= (1 << bit_idx); - } - } - return 1L << assm_idx; - } - template - bool eSLIM_Man::getAllFalseBehaviourRec(Gia_Obj_t * pObj) { - bool valuefanin0, valuefanin1; - if (Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin0(pObj))) { - valuefanin0 = getAllFalseBehaviourRec(Gia_ObjFanin0(pObj)); - } else { - valuefanin0 = false; - } - valuefanin0 = valuefanin0 != pObj->fCompl0; - if (Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin1(pObj))) { - valuefanin1 = getAllFalseBehaviourRec(Gia_ObjFanin1(pObj)); - } else { - valuefanin1 = false; - } - valuefanin1 = valuefanin1 != pObj->fCompl1; - return valuefanin0 && valuefanin1; + template + eSLIMCirMan eSLIM_Man::synthesiseRelation(Subcircuit& subcir, const Relation& rel) { + return SynthesisEngine::optimize(es_man, rel, subcir, cfg, log); } - template - int eSLIM_Man::getInsertionLiteral(Gia_Man_t* gia_man, const Subcircuit& subcir, Mini_Aig_t* replacement, const std::vector& replacement_values, int fanin_lit) { - int fanin_idx = Abc_Lit2Var(fanin_lit); - bool fanin_negated = Abc_LitIsCompl(fanin_lit); - int fanin_value; - if (fanin_idx == 0) { // constant fanin - fanin_value = 0; - } else if (fanin_idx <= subcir.nof_inputs) { - Gia_Obj_t* pObj = Gia_ManObj(gia_man, Vec_IntEntry(subcir.io, fanin_idx - 1)); - if (Gia_ObjIsTravIdCurrent(gia_man, pObj)) { //the node has already been added - fanin_value = Gia_ManObj(gia_man, Vec_IntEntry(subcir.io, fanin_idx - 1))->Value; - } else { - return -1; - } - } else { - if (replacement_values[fanin_idx - subcir.nof_inputs - 1] == -1) { - return -1; - } - fanin_value = replacement_values[fanin_idx - subcir.nof_inputs - 1]; - } - return Abc_LitNotCond( fanin_value, fanin_negated ); - } - template - std::vector eSLIM_Man::processReplacement(Gia_Man_t* gia_man, Gia_Man_t* pNew, const Subcircuit& subcir, Mini_Aig_t* replacement, std::vector&& to_process, std::vector& replacement_values) { - std::vector to_process_next_it; - for (int id : to_process) { - int fanin0 = getInsertionLiteral(gia_man, subcir, replacement, replacement_values, Mini_AigNodeFanin0( replacement, id)); - int fanin1 = getInsertionLiteral(gia_man, subcir, replacement, replacement_values, Mini_AigNodeFanin1( replacement, id)); - if (fanin0 == -1 || fanin1 == -1) { - to_process_next_it.push_back(id); - } else { - int idx = id - subcir.nof_inputs - 1; - replacement_values[idx] = Gia_ManAppendAnd2(pNew, fanin0, fanin1); - } + template + void eSLIM_Man::findReplacement() { + bool status = true; + if constexpr (SelectionStrategy::requiresRemainingTimes() || isDelayEngine::value) { + es_man.setupTimings(); } - int i, j = 0; - Mini_AigForEachPo(replacement, i) { - int old_id = Vec_IntEntry(subcir.io, j + subcir.nof_inputs); - j++; - Gia_Obj_t* obj = Gia_ManObj(gia_man, old_id); - int fanin0_lit = Mini_AigNodeFanin0( replacement, i); - int fanin0_idx = Abc_Lit2Var(fanin0_lit); - if (fanin0_idx == 0) { // constant fanin - obj->Value = Gia_ManConst0(gia_man)->Value; - } else if (fanin0_idx <= subcir.nof_inputs) { - Gia_Obj_t* fanin_obj = Gia_ManObj(gia_man, Vec_IntEntry(subcir.io, fanin0_idx - 1)); - if (Gia_ObjIsTravIdCurrent(gia_man, fanin_obj)) { - obj->Value = fanin_obj->Value; - } else { - continue; - } - } else { - if (replacement_values[fanin0_idx - subcir.nof_inputs - 1] == -1 ) { - continue; - } else { - obj->Value = replacement_values[fanin0_idx - subcir.nof_inputs - 1]; - } - } - Gia_ObjSetTravIdCurrent(gia_man, obj); - bool fanin0_negated = Abc_LitIsCompl(fanin0_lit); - if (fanin0_negated) { - obj->fMark0 = 1; - } - } - return to_process_next_it; - } - - template - Vec_Int_t * eSLIM_Man::processEncompassing(Gia_Man_t* gia_man, Gia_Man_t* pNew, Vec_Int_t * to_process) { - int i; - Gia_Obj_t * pObj; - Vec_Int_t * to_process_remaining = Vec_IntAlloc( Vec_IntSize(to_process) ); - Gia_ManForEachObjVec( to_process, gia_man, pObj, i ) { - if (Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin1(pObj))) { - Gia_ObjSetTravIdCurrent(gia_man, pObj); - bool fanin0_negated = Gia_ObjFaninC0(pObj) ^ Gia_ObjFanin0(pObj)->fMark0; - bool fanin1_negated = Gia_ObjFaninC1(pObj) ^ Gia_ObjFanin1(pObj)->fMark0; - int fanin0 = Abc_LitNotCond(Gia_ObjFanin0(pObj)->Value, fanin0_negated); - int fanin1 = Abc_LitNotCond(Gia_ObjFanin1(pObj)->Value, fanin1_negated); - pObj->Value = Gia_ManAppendAnd2( pNew, fanin0, fanin1); - } else { - Vec_IntPush(to_process_remaining, Gia_ObjId(gia_man, pObj)); - } - } - Vec_IntFree(to_process); - return to_process_remaining; - } - - template - void eSLIM_Man::insertReplacement(Mini_Aig_t* replacement, const Subcircuit& subcir) { - // A miniaig contains a constant node, nodes for each PI/PO and for each and. - int repalcement_size = Mini_AigNodeNum(replacement) - Vec_IntSize(subcir.io) - 1; - int size_diff = Vec_IntSize(subcir.nodes) - repalcement_size; - Gia_Man_t * pNew = Gia_ManStart( Gia_ManObjNum(gia_man) - size_diff ); - pNew->pName = Abc_UtilStrsav( gia_man->pName ); - pNew->pSpec = Abc_UtilStrsav( gia_man->pSpec ); - Gia_Obj_t * pObj; - int i; - Gia_ManConst0(gia_man)->Value = 0; - Gia_ManForEachPi( gia_man, pObj, i ) { - pObj->Value = Gia_ManAppendCi(pNew); - } - Gia_ManIncrementTravId(gia_man); - Gia_ManForEachObjVec( subcir.nodes, gia_man, pObj, i ) { - Gia_ObjSetTravIdCurrent(gia_man, pObj); - } - Gia_ManIncrementTravId(gia_man); - Gia_ManForEachPi( gia_man, pObj, i ) { - Gia_ObjSetTravIdCurrent(gia_man, pObj); - } - Vec_Int_t * to_process_encompassing = Vec_IntAlloc( gia_man->nObjs ); - Gia_ManForEachAnd( gia_man, pObj, i ) { - // nodes from the subcircuit shall not be added - if (Gia_ObjIsTravIdPrevious(gia_man, pObj)) { - continue; - } else if (Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin1(pObj))) { - pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - Gia_ObjSetTravIdCurrent(gia_man, pObj); - } else { - Vec_IntPush(to_process_encompassing, Gia_ObjId(gia_man, pObj)); - } - } - std::vector to_process_replacement; - Mini_AigForEachAnd(replacement, i) { - to_process_replacement.push_back(i); - } - std::vector replacement_values(to_process_replacement.size(), -1); - - while (Vec_IntSize(to_process_encompassing) > 0 || to_process_replacement.size() > 0) { - to_process_replacement = processReplacement(gia_man, pNew, subcir, replacement, std::move(to_process_replacement), replacement_values); - to_process_encompassing = processEncompassing(gia_man, pNew, to_process_encompassing); - } - Vec_IntFree(to_process_encompassing); - int po_idx = 0; - Mini_AigForEachPo(replacement, i) { - Gia_Obj_t* pObj = Gia_ManObj(gia_man, Vec_IntEntry(subcir.io, subcir.nof_inputs + po_idx)); - if (!Gia_ObjIsTravIdCurrent(gia_man, pObj)) { - int fanin_lit = Mini_AigNodeFanin0( replacement, i); - int fanin_idx = Abc_Lit2Var(fanin_lit); - assert (fanin_idx <= subcir.nof_inputs); - Gia_Obj_t* fanin_obj = Gia_ManObj(gia_man, Vec_IntEntry(subcir.io, fanin_idx - 1)); - pObj->Value = fanin_obj->Value; - if (Abc_LitIsCompl(fanin_lit)) { - pObj->fMark0 = 1; - } - Gia_ObjSetTravIdCurrent(gia_man, pObj); - } - po_idx++; - } - - Gia_ManForEachPo( gia_man, pObj, i ) { - assert(Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin0(pObj))); - bool fanin_negated = Gia_ObjFaninC0(pObj) ^ Gia_ObjFanin0(pObj)->fMark0; - int fanin0 = Abc_LitNotCond(Gia_ObjFanin0(pObj)->Value, fanin_negated); - pObj->Value = Gia_ManAppendCo( pNew, fanin0 ); - } - Gia_ManStop(gia_man); - gia_man = pNew; - } - - template - std::pair eSLIM_Man::reduce(Vec_Wrd_t* vSimsDiv, Vec_Wrd_t* vSimsOut, const std::unordered_map>& forbidden_pairs, - int nVars, int nDivs, int nOuts, int size) { - Y synth_man(vSimsDiv,vSimsOut,nVars,1+nVars+nDivs,nOuts,size, forbidden_pairs, log, cfg); - Mini_Aig_t* result = nullptr; - while (size >= 0) { - Mini_Aig_t* pTemp = computeReplacement(synth_man, size); - if (pTemp) { - if (result) { - Mini_AigStop(result); - } - result = pTemp; - size--; - } else { - break; + Subcircuit subcir = selection_strategy.getSubcircuit(status); + if (!status) { + if (cfg.trial_limit_active) { + stopeSLIM = true; } + return; } - return std::make_pair(size + 1, result); - } + eSLIMCirMan replacement = computeReplacement(subcir); - template - double eSLIM_Man::getDynamicTimeout(int size) { - if (this->log.nof_sat_calls_per_size[size] > cfg.minimum_dynamic_timeout_sample_size) { - return std::max(static_cast(cfg.minimum_sat_timeout), static_cast(log.cummulative_sat_runtimes_per_size[size]) / (1000*log.nof_sat_calls_per_size[size])); //logged timings are given in ms - } else { - return cfg.base_sat_timeout; + if (log.nof_analyzed_circuits_per_size.size() < subcir.nodes.size() + 1) { + log.nof_analyzed_circuits_per_size.resize(subcir.nodes.size() + 1, 0); + log.nof_replaced_circuits_per_size.resize(subcir.nodes.size() + 1, 0); + log.nof_reduced_circuits_per_size.resize(subcir.nodes.size() + 1, 0); } - } - - template - Mini_Aig_t* eSLIM_Man::computeReplacement(Y& syn_man, int size) { - return syn_man.getCircuit(size, getDynamicTimeout(size)); + log.nof_analyzed_circuits_per_size[subcir.nodes.size()]++; + log.subcircuits_with_forbidden_pairs += !subcir.forbidden_pairs.empty(); + if (replacement.getNofObjs() > 1) { //replacement found + log.nof_replaced_circuits_per_size[subcir.nodes.size()]++; + log.nof_reduced_circuits_per_size[subcir.nodes.size()] += (replacement.getNofGates() < subcir.nodes.size()); + es_man.replace(replacement, subcir); + } } } - ABC_NAMESPACE_CXX_HEADER_END \ No newline at end of file diff --git a/src/opt/eslim/eslimCirMan.cpp b/src/opt/eslim/eslimCirMan.cpp new file mode 100644 index 0000000000..f0dccccf20 --- /dev/null +++ b/src/opt/eslim/eslimCirMan.cpp @@ -0,0 +1,1129 @@ +/**CFile**************************************************************** + + FileName [eslimCirMan.cpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Internal circuit representation.] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#include +#include +#include +#include + +#include "eslimCirMan.hpp" +#include "subcircuit.hpp" +#include "tabooList.hpp" +#include "utils.hpp" + +#include "map/mio/mio.h" + +ABC_NAMESPACE_HEADER_START + void Mio_IntallSimpleLibrary(); + void * Abc_FrameReadLibGen(); +ABC_NAMESPACE_HEADER_END + +ABC_NAMESPACE_IMPL_START +namespace eSLIM { + + eSLIMCirObj::eSLIMCirObj(int id, std::vector&& fanins) + : node_id(id), fanins(fanins) { + } + + int eSLIMCirObj::getNFanins() const{ + return fanins.size(); + } + + int eSLIMCirObj::getTTLength() const { + return static_cast(1) << getNFanins(); + } + + unsigned int eSLIMCirObj::getId() const { + return id; + } + + + eSLIMCirMan::eSLIMCirMan(int nObjEstimate) { + nodes.reserve(1 + nObjEstimate); + std::unique_ptr pobj = std::make_unique(0, std::vector()); // const false node + nodes.push_back(std::move(pobj)); + } + + eSLIMCirMan::eSLIMCirMan(eSLIMCirMan& es_man, const Subcircuit& scir) + : eSLIMCirMan(scir.inputs.size() + scir.outputs.size() + scir.nodes.size()) { + for (int i = 0; i < scir.inputs.size(); i++) { + es_man.nodes[scir.inputs[i]]->value1 = addPi(); + } + for (int nd : scir.nodes) { + std::vector fanins; + for (auto f : es_man.nodes[nd]->fanins) { + fanins.push_back(f->value1); + } + es_man.nodes[nd]->value1 = addNode(fanins, es_man.nodes[nd]->tt); + } + for (int i = 0; i < scir.outputs.size(); i++) { + addPo(es_man.nodes[scir.outputs[i]]->value1,false); + } + } + + eSLIMCirMan::eSLIMCirMan(Gia_Man_t * pGia) : eSLIMCirMan(Gia_ManObjNum(pGia)) { + assert (!Gia_ManHasDangling(pGia)); + Gia_ManConst0(pGia)->Value = 0; + Gia_Obj_t * pObj; + int i; + Gia_ManForEachPi( pGia, pObj, i ) { + pObj->Value = addPi(); + } + Gia_ManIncrementTravId(pGia); + + Gia_ManForEachAnd( pGia, pObj, i ) { + ABC_UINT64_T tt = ttFromGiaObj(pGia, pObj); + if (!ttisnormal(tt)) { + Gia_ObjSetTravIdCurrent(pGia, pObj); // marked nodes are considered negated + tt = negateTT(tt, 2); + } + pObj->Value = addNode({static_cast(Gia_ObjFanin0(pObj)->Value), static_cast(Gia_ObjFanin1(pObj)->Value)}, tt); + } + + Gia_ManForEachPo( pGia, pObj, i ) { + bool po_is_negated = Gia_ObjFaninC0(pObj) != Gia_ObjIsTravIdCurrent(pGia, Gia_ObjFanin0(pObj)); + pObj->Value = addPo(Gia_ObjFanin0(pObj)->Value, po_is_negated); + } + } + + eSLIMCirMan::eSLIMCirMan(Abc_Ntk_t * pNtk, bool simplify) : eSLIMCirMan(Abc_NtkObjNum(pNtk)) { + assert(Abc_NtkIsLogic(pNtk)); + assert(Abc_NtkHasSop(pNtk)); + + Abc_NtkIncrementTravId(pNtk); + + std::unordered_map ids; + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachPi(pNtk, pObj, i) { + ids[pObj->Id] = addPi(); + } + + // Nodes are not necessarily topologically sorted. + // A po can be driven by another po + Abc_NtkForEachPo(pNtk, pObj, i) { + if (!Abc_ObjIsPo(Abc_ObjChild0(pObj))) { + insertNtkNodes(pNtk, Abc_ObjChild0(pObj)->Id, ids, simplify); + } + } + + // POs shall occur after the gates: + Abc_NtkForEachPo(pNtk, pObj, i) { + bool negated = false; + do { + int fc0 = Abc_ObjFaninC0(pObj); + pObj = Abc_ObjChild0(pObj); + negated ^= (fc0 ^ Abc_NodeIsTravIdCurrent(pObj)); + } while (Abc_ObjIsPo(pObj)); + addPo(ids.at(pObj->Id), negated); + } + } + + int eSLIMCirMan::insertNtkNodes(Abc_Ntk_t * pNtk, int node_id, std::unordered_map& ids, bool simplify) { + auto it = ids.find(node_id); + if (it != ids.end()) { + return it->second; + } + Abc_Obj_t * pObj = Abc_NtkObj(pNtk, node_id); + if (Vec_IntSize(&pObj->vFanins) == 0 ) { + ABC_UINT64_T tt = ttFromNtkObj(pNtk, pObj); + if (ttisnormal(tt)) { // const0 + ids[pObj->Id] = 0; + return 0; + } else if (simplify) { + ids[pObj->Id] = 0; + Abc_NodeSetTravIdCurrent(pObj); + return 0; + } + } + + std::vector fanins (Vec_IntSize(&pObj->vFanins), 0); + int j, f; + Vec_IntForEachEntry(&(pObj->vFanins), f, j) { + auto it = ids.find(f); + if (it == ids.end()) { + fanins[j] = insertNtkNodes(pNtk, f, ids, simplify); + } else { + fanins[j] = it->second; + } + } + + // the truth table must be computed after we traversed the fanins in order to take account for normalised gates + ABC_UINT64_T tt = ttFromNtkObj(pNtk, pObj); + if (simplify && Vec_IntSize(&pObj->vFanins) == 1) { + int id = fanins[0]; + if (!ttisnormal(tt)) { + Abc_NodeSetTravIdCurrent(pObj); + } + ids[pObj->Id] = id; + return id; + } + + // We normalise each gate + if (simplify && !ttisnormal(tt)) { + tt = negateTT(tt, Vec_IntSize(&pObj->vFanins)); + Abc_NodeSetTravIdCurrent(pObj); + } + int id = addNode(fanins, tt); + ids[pObj->Id] = id; + return id; + } + + + eSLIMCirObj* eSLIMCirMan::getpObj(int id) { + return nodes[id].get(); + } + + const eSLIMCirObj* eSLIMCirMan::getpObj(int id) const { + return nodes[id].get(); + } + + eSLIMCirObj* eSLIMCirMan::getPo(int id) { + return nodes[getNofObjs() - nof_pos - 1 + id].get(); + } + + const eSLIMCirObj& eSLIMCirMan::getObj(int id) const { + return *nodes[id].get(); + } + + int eSLIMCirMan::addPi() { + nof_pis++; + int id = nodes.size(); + std::unique_ptr pobj = std::make_unique(id, std::vector()); + pobj->tt = 2; + pobj->depth = 0; + pobj->id = last_node_id++; + nodes.push_back(std::move(pobj)); + return id; + } + + // If the fanin is negated we use the tt-member to indicate this negation + int eSLIMCirMan::addPo(int fanin, bool negated) { + nof_pos++; + // 1 represents negation and 2 projection + ABC_UINT64_T tt = negated ? 1 : 2; + // return addNode({fanin}, tt); + int id = addNode({fanin}, tt); + depth = std::max(depth, nodes.back()->depth); + return id; + } + + int eSLIMCirMan::addNode(const std::vector& fanins, ABC_UINT64_T tt) { + int id = nodes.size(); + std::vector pfan; + unsigned int max_fan_depth = 0; + for (int f : fanins) { + pfan.push_back(getpObj(f)); + max_fan_depth = pfan.back()->depth > max_fan_depth ? pfan.back()->depth : max_fan_depth; + } + std::unique_ptr pobj = std::make_unique(id, std::move(pfan)); + pobj->tt = tt; + pobj->depth = max_fan_depth + 1; + pobj->id = last_node_id++; + for (int f : fanins) { + getpObj(f)->fanouts.insert(pobj.get()); + } + nodes.push_back(std::move(pobj)); + return id; + } + + int eSLIMCirMan::getDepth() const { + return depth; + } + + void eSLIMCirMan::setupTimings() { + for (int i = 0; i < nodes.size(); i++) { + getpObj(i)->remaining_time = 0; + } + for (int i = nodes.size() - nof_pos - 1; i > 0; i--) { + eSLIMCirObj* pe = getpObj(i); + pe->remaining_time++; + for (int j = 0; j < pe->fanins.size(); j++) { + (pe->fanins[j])->remaining_time = std::max((pe->fanins[j])->remaining_time, pe->remaining_time); + } + } + } + + bool eSLIMCirMan::isConst(int id) const { + return id == 0; + } + + bool eSLIMCirMan::isConst(const eSLIMCirObj& obj) const { + return obj.node_id == 0; + } + + bool eSLIMCirMan::isPi(int id) const { + return id <= nof_pis; // 0 is the const0 node + } + + bool eSLIMCirMan::isPi(const eSLIMCirObj& obj) const { + return obj.node_id <= nof_pis; + } + + bool eSLIMCirMan::isOnCricticalPath(const eSLIMCirObj& obj) const { + return obj.depth + obj.remaining_time == depth; + } + + bool eSLIMCirMan::isPo(int id) const { + return id >= nodes.size() - nof_pos; + } + + bool eSLIMCirMan::isGate(int id) const { + return !isPi(id) && !isPo(id); + } + + int eSLIMCirMan::getNofObjs() const { + return nodes.size(); + } + + int eSLIMCirMan::getNofPis() const { + return nof_pis; + } + + int eSLIMCirMan::getNofPos() const { + return nof_pos; + } + + int eSLIMCirMan::getNofGates() const { + return nodes.size() - nof_pis - nof_pos - 1; + } + + void eSLIMCirMan::setTraversalId(eSLIMCirObj& obj) { + obj.trav_id = traversal_id; + } + + void eSLIMCirMan::setTraversalId(int n) { + getpObj(n)->trav_id = traversal_id; + } + + bool eSLIMCirMan::isCurrentTraversalId(int n) const { + return getpObj(n)->trav_id == traversal_id; + } + + bool eSLIMCirMan::isCurrentTraversalId(const eSLIMCirObj& obj) const { + return obj.trav_id == traversal_id; + } + + void eSLIMCirMan::setInTFI(eSLIMCirObj& obj) { + obj.inTFI = traversal_id; + } + + void eSLIMCirMan::setInTFO(eSLIMCirObj& obj) { + obj.inTFO = traversal_id; + } + + void eSLIMCirMan::setInSubcircuit(eSLIMCirObj& obj) { + obj.inSubcircuit = traversal_id; + } + + + bool eSLIMCirMan::inTFI(const eSLIMCirObj& obj) const { + return obj.inTFI == traversal_id; + } + + bool eSLIMCirMan::inTFO(const eSLIMCirObj& obj) const { + return obj.inTFO == traversal_id; + } + + bool eSLIMCirMan::inSubcircuit(const eSLIMCirObj& obj) const { + return obj.inSubcircuit == traversal_id; + } + + bool eSLIMCirMan::isTaboo(const eSLIMCirObj& obj, int taboo_time) const { + return obj.isTaboo != 0 && (traversal_id - obj.isTaboo < taboo_time); + } + + void eSLIMCirMan::setTaboo(eSLIMCirObj& obj) { + obj.isTaboo = traversal_id; + } + + void eSLIMCirMan::markSubcircuit(const std::vector& nodes) { + for (int n : nodes) { + setInSubcircuit(*getpObj(n)); + } + } + + void eSLIMCirMan::markCones(const std::vector& nodes) { + int min_node = *std::min_element(nodes.begin(), nodes.end()); + int max_node = *std::max_element(nodes.begin(), nodes.end()); + // mark TFI + for (int i = max_node; i >= getNofPis(); i--) { + if (inSubcircuit(*getpObj(i)) || inTFI(*getpObj(i))) { + for (auto& f : getpObj(i)->fanins) { + if (!inSubcircuit(*f)) { + setInTFI(*f); + } + } + } + } + // mark tfo + for (int i = min_node; i < getNofObjs(); i++) { + if (!inSubcircuit(*getpObj(i))) { + for (auto& f : getpObj(i)->fanins) { + if (inSubcircuit(*f) || inTFO(*f)) { + setInTFO(*getpObj(i)); + } + } + } + } + } + + ABC_UINT64_T eSLIMCirMan::ttFromGiaObj(Gia_Man_t * pGia, Gia_Obj_t * pObj) { + assert(Gia_ObjIsAnd(pObj)); + // A fanin is negated if is either negated in pGia or (exclusive) if it is marked + if (Gia_ObjFaninC0(pObj) != Gia_ObjIsTravIdCurrent(pGia, Gia_ObjFanin0(pObj))) { + if (Gia_ObjFaninC1(pObj) != Gia_ObjIsTravIdCurrent(pGia, Gia_ObjFanin1(pObj))) { + return 1; + } else { + return 4; + } + } else { + if (Gia_ObjFaninC1(pObj) != Gia_ObjIsTravIdCurrent(pGia, Gia_ObjFanin1(pObj))) { + return 2; + } else { + return 8; + } + } + } + + ABC_UINT64_T eSLIMCirMan::ttFromNtkObj(Abc_Ntk_t * pNtk, Abc_Obj_t * pObj) { + int j, f; + char * pSop = (char *)pObj->pData; + ABC_UINT64_T tt = sop2tt(pSop); + Vec_IntForEachEntry(&(pObj->vFanins), f, j) { + if (Abc_NodeIsTravIdCurrent(Abc_NtkObj(pNtk, f))) { + tt = ttNegateFanin(tt, j); + } + } + return tt; + } + + bool eSLIMCirMan::ttisnormal(ABC_UINT64_T tt) { + return !(tt & 1); + } + + ABC_UINT64_T eSLIMCirMan::negateTT(ABC_UINT64_T tt, unsigned int nfanin) { + assert (nfanin <= 6); + constexpr ABC_UINT64_T filters[7] {0x1ull, 0x3ull, 0xFull, 0xFFull, 0xFFFFull, 0xFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull}; + return ~tt & filters[nfanin]; + } + + ABC_UINT64_T eSLIMCirMan::ttNegateFanin(ABC_UINT64_T tt, unsigned int fan) { + assert (fan < 6); + constexpr ABC_UINT64_T filters1[6] = {0xAAAAAAAAAAAAAAAAull, 0xCCCCCCCCCCCCCCCCull, 0xF0F0F0F0F0F0F0F0ull, 0xFF00FF00FF00FF00ull, 0xFFFF0000FFFF0000ull, 0xFFFFFFFF00000000ull}; + constexpr ABC_UINT64_T filters2[6] = {0x5555555555555555ull, 0x3333333333333333ull, 0xF0F0F0F0F0F0F0Full, 0xFF00FF00FF00FFull, 0xFFFF0000FFFFull, 0xFFFFFFFFull}; + constexpr int shifts[6] = {1,2,4,8,16,32}; + ABC_UINT64_T x = tt & filters1[fan]; + ABC_UINT64_T y = tt & filters2[fan]; + return (x >> shifts[fan]) | (y << shifts[fan]); + } + + ABC_UINT64_T eSLIMCirMan::sop2tt(char * pSop) { + constexpr ABC_UINT64_T filters[7] {0x1ull, 0x3ull, 0xFull, 0xFFull, 0xFFFFull, 0xFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull}; + int nVars = Abc_SopGetVarNum(pSop); + ABC_UINT64_T tt = Abc_SopToTruth(pSop, nVars); + return tt & filters[nVars]; + } + + char* eSLIMCirMan::tt2sop(ABC_UINT64_T tt, int nVars, Mem_Flex_t * pMan) { + int bit_count = popcount(tt); + if (bit_count == 0) { + char* pSopCover = Abc_SopCreateConst0(pMan); + return pSopCover; + } else if (bit_count == 1 << nVars) { + char* pSopCover = Abc_SopCreateConst1(pMan); + return pSopCover; + } + char* pSopCover = Abc_SopStart( pMan, bit_count, nVars ); + int sop_id = 0; + for (int i = 0; i < (1 << nVars); i++) { + if ((tt >> i) & 1) { + for (int j = 0; j < nVars; j++) { + char bit = ((i >> j) & 1) ? '1' : '0'; + pSopCover[sop_id*(nVars + 3) + j] = bit; + } + pSopCover[sop_id*(nVars + 3) + nVars] = ' '; + pSopCover[sop_id*(nVars + 3) + nVars + 1] = '1'; + pSopCover[sop_id*(nVars + 3) + nVars + 2] = '\n'; + sop_id++; + } + } + pSopCover[sop_id*(nVars + 3)] = 0; + return pSopCover; + } + + + int eSLIMCirMan::addGiaGate(Gia_Man_t * pGia, int node_id, std::vector& node_ids, std::vector& is_node_negated) { + eSLIMCirObj* pe = getpObj(node_id); + // assert (pe->getNFanins() == 2); + int bit_count = popcount(pe->tt); + assert(ttisnormal(pe->tt)); + assert (bit_count > 0 || bit_count < 4); // the circuit shall not contain constants + ABC_UINT64_T tt = pe->tt; + bool negate_and = false; + bool is_xor = false; + bool fan1negated = false, fan2negated = false; + if (bit_count == 3) { // or gates are represented by negated and gates + tt = negateTT(pe->tt, 2); + negate_and = true; + fan1negated = true; + fan2negated = true; + } else if (pe->tt == 2) { + fan1negated = false; + fan2negated = true; + } else if (pe->tt == 4) { + fan1negated = true; + fan2negated = false; + } else if (pe->tt == 8) { + fan1negated = false; + fan2negated = false; + } else { + // XOR + assert (pe->tt == 6); + is_xor = true; + } + + int fan1 = node_ids[(pe->fanins[0])->node_id]; + int fan2 = node_ids[(pe->fanins[1])->node_id]; + + fan1negated = (fan1negated != is_node_negated[(pe->fanins[0])->node_id]); + fan2negated = (fan2negated != is_node_negated[(pe->fanins[1])->node_id]); + + // We need to remove gates with duplicate fanins. + // We do not use simplifyDuplicateFanins as it does not propagate duplicate fanins. + if (fan1 == fan2) { + if ((fan1negated != fan2negated ) || is_xor) { + assert (!negate_and); + node_ids[node_id] = const_false_id; + is_node_negated[node_id] = negate_and; + return const_false_id; + } else { + node_ids[node_id] = fan1; + // Gates are assumed to be normal -> x = !a && !a (x = !a || !a) is not possible. + is_node_negated[node_id] = is_node_negated[(pe->fanins[1])->node_id]; + return fan1; + } + } + + int id; + if (is_xor) { + id = Gia_ManAppendXor(pGia, Abc_LitNotCond(fan1, fan1negated), Abc_LitNotCond(fan2, fan2negated)); + // id = Gia_ManAppendXorReal(pGia, Abc_LitNotCond(fan1, fan1negated), Abc_LitNotCond(fan2, fan2negated)); + } else { + id = Gia_ManAppendAnd(pGia, Abc_LitNotCond(fan1, fan1negated), Abc_LitNotCond(fan2, fan2negated)); + } + + + node_ids[node_id] = id; + is_node_negated[node_id] = negate_and; + + return id; + } + + + Gia_Man_t* eSLIMCirMan::eSLIMCirManToGia() { + // simplifyDuplicateFanins(); + Gia_Man_t * pNew = Gia_ManStart( getNofObjs() ); + + std::vector node_ids(nodes.size(), 0); + std::vector is_node_negated(nodes.size(), false); + + for (int i = 1; i <= nof_pis; i++) { + int id = Gia_ManAppendCi(pNew); + node_ids[i] = id; + is_node_negated[i] = false; + } + + for (int i = nof_pis + 1; i < nodes.size() - nof_pos; i++) { + assert(nodes[i]->getNFanins() == 2); + addGiaGate( pNew, i, node_ids, is_node_negated ); + } + + for (int i = nodes.size() - nof_pos; i < nodes.size(); i++) { + eSLIMCirObj* pobj = getpObj(i); + bool fan_negated = ((pobj->tt == 1) != is_node_negated.at((pobj->fanins[0])->node_id)); + int fanin0 = Abc_LitNotCond(node_ids[(pobj->fanins[0])->node_id], fan_negated); + int id = Gia_ManAppendCo( pNew, fanin0 ); + node_ids[i] = id; + } + + return pNew; + } + + Abc_Ntk_t* eSLIMCirMan::eSLIMCirManToNtk() { + simplifyDuplicateFanins(); + Abc_Ntk_t* pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + std::vector ntk_objs; + // constant0 + Abc_Obj_t* pObj = Abc_NtkCreateNodeConst0(pNtk); + ntk_objs.push_back(pObj); + Nm_ManStoreIdName( pNtk->pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + + for (int i = 1; i <= nof_pis; i++) { + Abc_Obj_t* pObj = Abc_NtkCreatePi(pNtk); + ntk_objs.push_back(pObj); + Nm_ManStoreIdName( pNtk->pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + } + for (int i = nof_pis + 1; i < nodes.size() - nof_pos; i++) { + Abc_Obj_t* pObj = Abc_NtkCreateNode( pNtk ); + Nm_ManStoreIdName( pNtk->pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + ntk_objs.push_back(pObj); + char* sop = tt2sop(nodes[i]->tt, nodes[i]->fanins.size(), (Mem_Flex_t *)pNtk->pManFunc); + pObj->pData = sop; + for (auto f : nodes[i]->fanins) { + int fid = f->node_id; + Abc_ObjAddFanin(pObj, ntk_objs[fid]); + } + } + for (int i = nodes.size() - nof_pos; i < nodes.size(); i++) { + Abc_Obj_t* fobj; + int fid = nodes[i]->fanins[0]->node_id; + // bool use_pi_name = false; + if (nodes[i]->tt == 1) { // a negated po + char* sop = tt2sop(1, 1, (Mem_Flex_t *)pNtk->pManFunc); + fobj = Abc_NtkCreateNode( pNtk ); + Nm_ManStoreIdName( pNtk->pManName, fobj->Id, fobj->Type, Abc_ObjName(fobj), NULL ); + fobj->pData = sop; + Abc_ObjAddFanin(fobj, ntk_objs[fid]); + } else { + // We add buffer to simplify the handling of the SimpleCos condition + char* sop = tt2sop(2, 1, (Mem_Flex_t *)pNtk->pManFunc); + fobj = Abc_NtkCreateNode( pNtk ); + Nm_ManStoreIdName( pNtk->pManName, fobj->Id, fobj->Type, Abc_ObjName(fobj), NULL ); + fobj->pData = sop; + Abc_ObjAddFanin(fobj, ntk_objs[fid]); + } + Abc_Obj_t* pObj = Abc_NtkCreatePo(pNtk); + Nm_ManStoreIdName( pNtk->pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + Abc_ObjAddFanin(pObj, fobj); + } + + assert( Abc_NtkCiNum(pNtk) == nof_pis ); + assert( Abc_NtkCoNum(pNtk) == nof_pos ); + assert( Abc_NtkLatchNum(pNtk) == 0 ); + assert( Abc_NtkCheck(pNtk) ); + assert( Abc_NtkLogicHasSimpleCos(pNtk)); + return pNtk; + } + + Abc_Ntk_t* eSLIMCirMan::eSLIMCirManToMappedNtk() { + + Mio_IntallSimpleLibrary(); + Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); + + Abc_Ntk_t* pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_MAP, 1 ); + std::vector ntk_objs; + Abc_Obj_t* pObj = Abc_NtkCreateNode( pNtk ); + pObj->pData = Mio_LibraryReadGateByName( pLib, "zero", NULL ); + ntk_objs.push_back(pObj); + Nm_ManStoreIdName( pNtk->pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + Abc_Obj_t* const1 = Abc_NtkCreateNode( pNtk ); + const1->pData = Mio_LibraryReadGateByName( pLib, "one", NULL ); + // ntk_objs.push_back(pObj); + Nm_ManStoreIdName( pNtk->pManName, const1->Id, const1->Type, Abc_ObjName(const1), NULL ); + + for (int i = 1; i <= nof_pis; i++) { + Abc_Obj_t* pObj = Abc_NtkCreatePi(pNtk); + ntk_objs.push_back(pObj); + Nm_ManStoreIdName( pNtk->pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + } + + for (int i = nof_pis + 1; i < nodes.size() - nof_pos; i++) { + // Replace an inverted const false by const true + if (nodes[i]->tt == 1 && nodes[i]->fanins.size() == 1 && nodes[i]->fanins[0]->node_id == 0) { + ntk_objs.push_back(const1); + continue; + } + // if a gate has no fanins it must be const true (const false is handled separatley) + if (nodes[i]->fanins.size() == 0) { + assert (nodes[i]->tt == 1); + ntk_objs.push_back(const1); + continue; + } + Abc_Obj_t* pObj = Abc_NtkCreateNode( pNtk ); + Nm_ManStoreIdName( pNtk->pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + ntk_objs.push_back(pObj); + for (auto f : nodes[i]->fanins) { + int fid = f->node_id; + Abc_ObjAddFanin(pObj, ntk_objs[fid]); + } + switch (nodes[i]->tt) { + case 1: + if (nodes[i]->fanins.size() == 1) { + pObj->pData = Mio_LibraryReadGateByName( pLib, "inv", NULL ); + } else if (nodes[i]->fanins.size() == 2) { + pObj->pData = Mio_LibraryReadGateByName( pLib, "nor2", NULL ); + } else { + pObj->pData = Mio_LibraryReadGateByName( pLib, "nor3", NULL ); + } + break; + case 2: + pObj->pData = Mio_LibraryReadGateByName( pLib, "buf", NULL ); + break; + case 7: + if (nodes[i]->fanins.size() == 2) { + pObj->pData = Mio_LibraryReadGateByName( pLib, "nand2", NULL ); + } else { + pObj->pData = Mio_LibraryReadGateByName( pLib, "aoi21", NULL ); + } + break; + case 31: + pObj->pData = Mio_LibraryReadGateByName( pLib, "oai21", NULL ); + break; + case 127: + pObj->pData = Mio_LibraryReadGateByName( pLib, "nand3", NULL ); + break; + case 1911: + pObj->pData = Mio_LibraryReadGateByName( pLib, "aoi22", NULL ); + break; + case 4383: + pObj->pData = Mio_LibraryReadGateByName( pLib, "oai22", NULL ); + break; + + default: + std::cerr << "Error: A node with a function not part of the library was detected." << std::endl; + Abc_NtkDelete( pNtk ); + return NULL; + } + } + std::unordered_map negated_pos; + std::unordered_map buffers; + + for (int i = nodes.size() - nof_pos; i < nodes.size(); i++) { + Abc_Obj_t* fobj; + int fid = nodes[i]->fanins[0]->node_id; + if (nodes[i]->tt == 1) { // a negated po + if (fid == 0) { + fobj = const1; + } else { + if (negated_pos.find(fid) != negated_pos.end()) { + negated_pos[fid] = ntk_objs.size(); + Abc_Obj_t* pObj = Abc_NtkCreateNode( pNtk ); + Nm_ManStoreIdName( pNtk->pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + ntk_objs.push_back(pObj); + pObj->pData = Mio_LibraryReadGateByName( pLib, "inv", NULL ); + Abc_ObjAddFanin(pObj, ntk_objs[fid]); + } + fobj = ntk_objs[negated_pos[fid]]; + } + } else { + if (0 < fid && fid <= nof_pis) { + if (buffers.find(fid) == buffers.end()) { + Abc_Obj_t* pObj = Abc_NtkCreateNode( pNtk ); + Nm_ManStoreIdName( pNtk->pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + buffers[fid] = ntk_objs.size(); + ntk_objs.push_back(pObj); + pObj->pData = Mio_LibraryReadGateByName( pLib, "buf", NULL ); + Abc_ObjAddFanin(pObj, ntk_objs[fid]); + } + fobj = ntk_objs[buffers[fid]]; + } else { + fobj = ntk_objs[fid]; + } + } + Abc_Obj_t* pObj = Abc_NtkCreatePo(pNtk); + Nm_ManStoreIdName( pNtk->pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + Abc_ObjAddFanin(pObj, fobj); + } + + assert( Abc_NtkCiNum(pNtk) == nof_pis ); + assert( Abc_NtkCoNum(pNtk) == nof_pos ); + assert( Abc_NtkLatchNum(pNtk) == 0 ); + assert( Abc_NtkCheck(pNtk) ); + assert( Abc_NtkLogicHasSimpleCos(pNtk)); + return pNtk; + } + + void eSLIMCirMan::setMarks(eSLIMCirObj& pObj, int id) { + pObj.node_id = id; + pObj.depth = 0; + for (const auto& f : pObj.fanins) { + if (f->depth >= pObj.depth) { + pObj.depth = f->depth + 1; + } + } + setTraversalId(pObj); + } + + void eSLIMCirMan::moveNode(std::vector>& vec, std::unique_ptr& pobj) { + int id = vec.size(); + vec.push_back(std::move(pobj)); + pobj = nullptr; + setMarks(*vec.back(), id); + } + + void eSLIMCirMan::addFans(eSLIMCirObj* out, eSLIMCirObj* in, int fin_id) { + out->fanouts.insert(in); + in->fanins[fin_id] = out; + } + + void eSLIMCirMan::processNonGateRepFanin( eSLIMCirObj* obj, eSLIMCirObj* fan, int fid, std::vector>& sorted, + eSLIMCirMan& replacement, const std::unordered_map& out_map, const std::vector& in_vec) { + if (replacement.isConst(*fan)) { + addFans(sorted[0].get(), obj, fid); + } else { + int in_id = fan->node_id - 1; + addFans(in_vec[in_id], obj, fid); + insertSortedRec(in_vec[in_id], sorted, replacement, out_map, in_vec); + } + } + + void eSLIMCirMan::processRepFanin(eSLIMCirObj* obj, eSLIMCirObj* fan, int fid, std::vector>& sorted, + eSLIMCirMan& replacement, const std::unordered_map& out_map, const std::vector& in_vec) { + if (isCurrentTraversalId(*fan)) { + addFans(fan, obj, fid); + } else if (replacement.isPi(*fan)) { + processNonGateRepFanin(obj, fan, fid, sorted, replacement, out_map, in_vec); + } else { + fan->fanouts.clear(); // the ids changed, so we cannot reuse the set + addFans(fan, obj, fid); + insertSortedRecRep(fan, sorted, replacement, out_map, in_vec); + } + } + + void eSLIMCirMan::processRepPo( eSLIMCirObj* obj, eSLIMCirObj* scir_out, int fid, std::vector>& sorted, + eSLIMCirMan& replacement, const std::unordered_map& out_map, const std::vector& in_vec) { + int out_id = out_map.at(scir_out->node_id); + int out_node_id = replacement.nodes.size() - replacement.getNofPos() + out_id; + auto rf = replacement.nodes[out_node_id]->fanins[0]; + processRepFanin(obj, rf, fid, sorted, replacement, out_map, in_vec); + } + + void eSLIMCirMan::insertSorted( eSLIMCirObj* obj, std::vector>& sorted, + eSLIMCirMan& replacement, const std::unordered_map& out_map, const std::vector& in_vec) { + auto f = obj->fanins[0]; + if (inSubcircuit(*f)) { + processRepPo(obj, f, 0, sorted, replacement, out_map, in_vec); + } else { + insertSortedRec(f, sorted, replacement, out_map, in_vec); + } + } + + void eSLIMCirMan::insertSortedRec(eSLIMCirObj* obj, std::vector>& sorted, + eSLIMCirMan& replacement, const std::unordered_map& out_map, const std::vector& in_vec) { + if (isPi(*obj) || isCurrentTraversalId(*obj)) { + return; + } + for (int i = 0; i < obj->fanins.size(); i++) { + auto f = obj->fanins[i]; + if (inSubcircuit(*f)) { + processRepPo(obj, f, i, sorted, replacement, out_map, in_vec); + } else { + insertSortedRec(f, sorted, replacement, out_map, in_vec); + } + } + moveNode(sorted, nodes[obj->node_id]); + } + + void eSLIMCirMan::insertSortedRecRep( eSLIMCirObj* obj, std::vector>& sorted, + eSLIMCirMan& replacement, const std::unordered_map& out_map, const std::vector& in_vec) { + assert(!isCurrentTraversalId(*obj)); + for (int i = 0; i < obj->fanins.size(); i++) { + auto f = obj->fanins[i]; + if (!isCurrentTraversalId(*f)) { + if (replacement.isPi(*f)) { + processNonGateRepFanin(obj, f, i, sorted, replacement, out_map, in_vec); + } else { + f->fanouts.clear(); + f->fanouts.insert(obj); + insertSortedRecRep(f, sorted, replacement, out_map, in_vec); + } + } else { + f->fanouts.insert(obj); + } + } + if (taboo != nullptr) { + taboo->addNode(replacement.nodes[obj->node_id].get()); + } + moveNode(sorted, replacement.nodes[obj->node_id]); + } + + // We want to preserve the invariant that nodes are topological sorted. + // Even if we replace a subcircuit by a same sized circuit it is not necessarily possible + // to simply replace the old nodes by the new nodes, while preserving the order. + // We can only process circuits with thousands (maybe tenthousends) nodes. + // For such sizes the replacement should be reasonable fast. + void eSLIMCirMan::replace(eSLIMCirMan& replacement, const Subcircuit& subcir) { + clearFanouts(subcir); + setupMarksForReplacement(replacement); + if (taboo != nullptr) { + taboo->discardSubcircuit(subcir); + } + std::vector> nodes_aux = replaceInternal(replacement, subcir); + int size_diff = subcir.nodes.size() - replacement.getNofGates(); + if (nodes_aux.size() + size_diff != nodes.size()) { + int nredundant = processRedundant(subcir); + assert(nodes_aux.size() + size_diff + nredundant == nodes.size()); + } + std::swap(nodes, nodes_aux); + } + + void eSLIMCirMan::setupMarksForReplacement(eSLIMCirMan& replacement) { + for (int i = replacement.getNofPis() + 1; i < replacement.getNofObjs() - replacement.getNofPos(); i++) { + replacement.nodes[i]->isTaboo = traversal_id; + replacement.nodes[i]->id = last_node_id++; + } + } + + void eSLIMCirMan::clearFanouts(const Subcircuit& subcir) { + for (int n : subcir.nodes) { + eSLIMCirObj* obj = nodes[n].get(); + nodes[0]->fanouts.erase(obj); + for (int i : subcir.inputs) { + nodes[i]->fanouts.erase(obj); + } + } + } + + std::vector> eSLIMCirMan::replaceInternal(eSLIMCirMan& replacement, const Subcircuit& subcir) { + std::unordered_map out_map; + for (int i = 0; i < subcir.outputs.size(); i++) { + out_map[subcir.outputs[i]] = i; + } + std::vector invec; + for (int i = 0; i < subcir.inputs.size(); i++) { + invec.push_back(nodes[subcir.inputs[i]].get()); + } + + int size_diff = subcir.nodes.size() - replacement.getNofGates(); + std::vector> nodes_aux; + nodes_aux.reserve(getNofObjs() - size_diff); + for (int i = 0; i <= getNofPis(); i++) { // "<=" because of the constant node + moveNode(nodes_aux, nodes[i]); + } + + // it is possible that after the insertion no Po is reachable from some nodes. + // These nodes can be remove. + for (int i = 1; i <= getNofPos(); i++) { + insertSorted(nodes[nodes.size() - i].get(), nodes_aux, replacement, out_map, invec); + } + assert (nodes_aux.size() <= nodes.size()); + int current_depth = 0; + for (int i = 0; i < getNofPos(); i++) { + int po_id = getNofObjs() - getNofPos() + i; + moveNode(nodes_aux, nodes[po_id]); + current_depth = std::max(current_depth, nodes_aux.back()->depth); + } + depth = current_depth; + return nodes_aux; + } + + int eSLIMCirMan::processRedundant(const Subcircuit& subcir) { + int nredundant = 0; + std::vector to_process (subcir.inputs.begin(), subcir.inputs.end()); + std::unordered_set seen (subcir.inputs.begin(), subcir.inputs.end()); + while (to_process.size() > 0) { + int nd = to_process.back(); + to_process.pop_back(); + if (nodes[nd] != nullptr && !inSubcircuit(*nodes[nd])) { + // This is a redundant node that can be discarded + nredundant++; + auto ptr = nodes[nd].get(); + if (taboo != nullptr) { + taboo->removeRedundantNode(ptr); + } + for (auto& f : nodes[nd]->fanins) { + f->fanouts.erase(nodes[nd].get()); + // in the dfs traversal the node was not copied + if (!isCurrentTraversalId(*f)) { + auto [it, inserted] = seen.insert(f->node_id); + if (inserted) { // the node was not seen before + to_process.push_back(f->node_id); + } + } + } + } + } + return nredundant; + } + + void eSLIMCirMan::applyLevelBasedOrdering() { + std::sort(nodes.begin() + getNofPis() + 1, nodes.begin() + getNofObjs() - getNofPos(), + [](const std::unique_ptr& a, const std::unique_ptr& b) { + return a->depth < b->depth || (a->depth == b->depth && a->id < b->id); + } + ); + } + + // Reorders the nodes to an alternative topological order. + void eSLIMCirMan::applyDFSOrdering(const std::vector& po_nodes) { + incrementTraversalId(); + std::vector> nodes_reordered; + nodes_reordered.reserve(nodes.size()); + for (int i = 0; i <= nof_pis; i++) { + setTraversalId(*nodes[i]); + nodes_reordered.push_back(std::move(nodes[i])); + } + for (int i = 0; i < nof_pos; i++) { + int po_id = po_nodes[i]; + applyDFSOrderingRec(nodes[po_id]->fanins[0], nodes_reordered); + } + for (int i = 0; i < nof_pos; i++) { + int po_id = getNofObjs() - getNofPos() + i; + nodes_reordered.push_back(std::move(nodes[po_id])); + } + std::swap(nodes, nodes_reordered); + } + + void eSLIMCirMan::applyDFSOrderingRec(eSLIMCirObj* obj, std::vector>& sorted) { + if (!isCurrentTraversalId(*obj)) { + setTraversalId(*obj); + for (auto& fan : obj->fanins) { + applyDFSOrderingRec(fan, sorted); + } + auto& pobj = nodes[obj->node_id]; + pobj->node_id = sorted.size(); + sorted.push_back(std::move(pobj)); + } + } + + void eSLIMCirMan::print() const { + std::cout << "Inputs:"; + for (int i = 1; i <= nof_pis; i++) { + std::cout << " " << i; + } + std::cout << "\n"; + for (int i = nof_pis + 1; i < getNofObjs() - getNofPos(); i++) { + std::cout << nodes[i]->node_id << " :"; + for (auto& f : nodes[i]->fanins) { + std::cout << " " << f->node_id; + } + std::cout << " - " << nodes[i]->tt << "\n"; + } + std::cout << "Outputs:"; + for (int i = getNofObjs() - getNofPos(); i < getNofObjs(); i++) { + std::cout << " " << nodes[i]->fanins[0]->node_id; + } + std::cout << "\n"; + } + + void eSLIMCirMan::print(const Subcircuit& scir) const { + std::cout << "Inputs:"; + for (int i : scir.inputs) { + std::cout << " " << i; + } + std::cout << "\n"; + for (int nd : scir.nodes) { + std::cout << nodes[nd]->node_id << " :"; + for (auto& f : nodes[nd]->fanins) { + std::cout << " " << f->node_id; + } + std::cout << " - " << nodes[nd]->tt << "\n"; + } + std::cout << "Outputs:"; + for (int o : scir.outputs) { + std::cout << " " << o; + } + std::cout << "\nForbidden pairs:"; + for (const auto & [out,inps] : scir.forbidden_pairs) { + std::cout << "\n" << out << " :"; + for (int inp : inps) { + std::cout << " " << inp; + } + } + std::cout << "\n"; + } + + eSLIMCirMan eSLIMCirMan::duplicate() const { + eSLIMCirMan dup(getNofObjs()); + for (int i = 0; i < getNofPis(); i++) { + dup.addPi(); + } + for (int i = getNofPis() + 1; i < getNofObjs() - getNofPos(); i++) { + std::vector fanins; + for (const auto& f : nodes[i]->fanins) { + fanins.push_back(f->node_id); + } + dup.addNode(fanins, nodes[i]->tt); + } + for (int i = getNofObjs() - getNofPos(); i < getNofObjs(); i++) { + const auto& obj = nodes[i]->fanins[0]; + dup.addPo(obj->node_id, obj->tt == 1); + } + return dup; + } + + void eSLIMCirMan::simplifyDuplicateFanins() { + std::unordered_map fanins; + for (int i = getNofPis() + 1; i < getNofObjs() - getNofPos(); i++) { + fanins.clear(); + for (auto it = nodes[i]->fanins.begin(); it != nodes[i]->fanins.end(); ) { + int fanin_id = std::distance(nodes[i]->fanins.begin(), it); + if (!fanins[(*it)->node_id]) { + fanins[(*it)->node_id] = fanin_id + 1; // 0 should indicate that this node_id was not yet considered + it++; + } else { + nodes[i]->tt = removeInputFromTT(nodes[i]->tt, fanins[(*it)->node_id] - 1, fanin_id); + // In general, we do not expect many duplicate fanins. + // Hence, we immediatley delete from the vector. + it = nodes[i]->fanins.erase(it); + } + } + } + } + + ABC_UINT64_T eSLIMCirMan::compressTT(ABC_UINT64_T tt, unsigned int input) { + static constexpr ABC_UINT64_T filters1[] {0x1111111111111111ull, 0x303030303030303ull, 0xF000F000F000Full, 0xFF000000FFull, 0xFFFFull}; + static constexpr ABC_UINT64_T filters2[] {0x4444444444444444ull, 0x3030303030303030ull, 0xF000F000F000F00ull, 0xFF000000FF0000ull, 0xFFFF00000000ull}; + static constexpr int shifts[] {1,2,4,8,16}; + if (input == 5) { + return tt & 0xFFFFFFFFull; + } + for (int i = input; i < 5; i++) { + tt = (tt & filters1[i]) | ((tt & filters2[i]) >> shifts[i]); + } + return tt; + } + + // we drop the lines from the tt where the values for inputs first_occurrence and second_occurrence do not coincide. Then we compress the tt. + ABC_UINT64_T eSLIMCirMan::removeInputFromTT(ABC_UINT64_T tt, unsigned int first_occurrence, unsigned int second_occurrence) { + assert (first_occurrence < 6 && second_occurrence && first_occurrence < second_occurrence); // we can only represent 6-input functions with the 64-bit ints + + // filter that gives all the tt-lines with the ith input is true + static constexpr ABC_UINT64_T isTruePatterns[] {0xAAAAAAAAAAAAAAAAull, 0xCCCCCCCCCCCCCCCCull, 0xF0F0F0F0F0F0F0F0ull, 0xFF00FF00FF00FF00ull, 0xFFFF0000FFFF0000ull, 0xFFFFFFFF00000000ull}; + // filter that gives all the tt-lines with the ith input is false + static constexpr ABC_UINT64_T isFalsePatterns[] {0x5555555555555555ull, 0x3333333333333333ull, 0xF0F0F0F0F0F0F0Full, 0xFF00FF00FF00FFull, 0xFFFF0000FFFFull, 0xFFFFFFFFull}; + // the first tt-line where the ith input is true + static constexpr unsigned char firstTrueIn1[] {1, 2, 4, 8, 16, 32}; + + ABC_UINT64_T true_filter = isTruePatterns[first_occurrence] & isTruePatterns[second_occurrence]; + ABC_UINT64_T false_filter = isFalsePatterns[first_occurrence] & isFalsePatterns[second_occurrence]; + // the first line of the tt where both considered inputs are true + unsigned int shift = lsb(true_filter) - firstTrueIn1[first_occurrence]; + + ABC_UINT64_T true_positions = tt & true_filter; + ABC_UINT64_T false_positions = tt & false_filter; + ABC_UINT64_T tt_new = false_positions | (true_positions >> shift); + + return compressTT(tt_new, second_occurrence); + } + + + void eSLIMCirMan::registerTabooList(TabooList* taboo) { + this->taboo = taboo; + } + + void eSLIMCirMan::unregisterTabooList() { + this->taboo = nullptr; + } + + +} +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/opt/eslim/eslimCirMan.hpp b/src/opt/eslim/eslimCirMan.hpp new file mode 100644 index 0000000000..49a8adce84 --- /dev/null +++ b/src/opt/eslim/eslimCirMan.hpp @@ -0,0 +1,234 @@ +/**CFile**************************************************************** + + FileName [eslimCirMan.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Internal circuit representation.] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__OPT__ESLIM__ESLIMCIRMAN_hpp +#define ABC__OPT__ESLIM__ESLIMCIRMAN_hpp + +#include +#include +#include +#include + +#include "aig/gia/gia.h" +#include "base/abc/abc.h" +#include "misc/util/abc_namespaces.h" +#include "misc/util/abc_global.h" + + + +ABC_NAMESPACE_CXX_HEADER_START +namespace eSLIM { + + class Subcircuit; + class eSLIMCirMan; + class TabooList; + template class WindowMan; + + // Nodes must not have more than 6 fanins + class eSLIMCirObj { + + private: + + // This comparator is used in sets of pointers to nodes. + // As the order does not really matter, the comparator could be replaced by comparing addresses. + // This would slightly simplify the code as we would not need to change the fanouts of replacement circuits + // (unlike to the ids the addresses of the nodes in the replacement do not change during the replacement). + // Nevertheless, we use this iterator to make iteration orders more predictable. + struct eSLIMObjComp { + bool operator()(eSLIMCirObj* a, eSLIMCirObj* b) const { + return a->getId() < b->getId(); + } + }; + + public: + + eSLIMCirObj(int id, std::vector&& fanins); + int getNFanins() const; + int getTTLength() const; + unsigned int getId() const; + + int node_id; + std::vector fanins; + std::set fanouts; + ABC_UINT64_T tt; //truth table representing the function + int depth = 0; // the step from a input/gate node to an output node is also counted -> depth differs from depths in abc + int remaining_time = 0; + + int value1 = 0; + + private: + unsigned int id = 0; + // set traversal_id + unsigned int trav_id = 0; + unsigned int inSubcircuit = 0; + unsigned int inTFI = 0; + unsigned int inTFO = 0; + unsigned int isTaboo = 0; + + friend eSLIMCirMan; + friend TabooList; + }; + + class eSLIMCirMan { + + public: + + eSLIMCirMan(int nObjEstimate); + eSLIMCirMan(Gia_Man_t * pGia); + eSLIMCirMan(Abc_Ntk_t * pNtk, bool simplify); + eSLIMCirMan(eSLIMCirMan& es_man, const Subcircuit& scir); + + // normalises the aig + // static eSLIMCirMan eSLIMCirManFromGia(Gia_Man_t * pGia); + static ABC_UINT64_T negateTT(ABC_UINT64_T tt, unsigned int nfanin); + static ABC_UINT64_T ttNegateFanin(ABC_UINT64_T tt, unsigned int fan); + static bool ttisnormal(ABC_UINT64_T tt); + + void registerTabooList(TabooList* taboo); + void unregisterTabooList(); + + void replace(eSLIMCirMan& replacement, const Subcircuit& subcir); + + + Gia_Man_t* eSLIMCirManToGia(); + Abc_Ntk_t* eSLIMCirManToNtk(); + Abc_Ntk_t* eSLIMCirManToMappedNtk(); + void setupTimings(); + + bool isConst(int id) const; + bool isPi(int id) const; // or constant node + bool isPo(int id) const; + bool isGate(int id) const; + + bool isConst(const eSLIMCirObj&) const; + bool isPi(const eSLIMCirObj&) const; + + bool isOnCricticalPath(const eSLIMCirObj&) const; + + int getNofObjs() const; + int getNofPis() const; + int getNofPos() const; + int getNofGates() const; + + int getDepth() const; + + const eSLIMCirObj& getObj(int id) const; + + void incrementTraversalId() {traversal_id++;} + void setTraversalId(eSLIMCirObj& obj); + void setTraversalId(int n); + bool isCurrentTraversalId(const eSLIMCirObj& obj) const; + bool isCurrentTraversalId(int n) const; + + void setInSubcircuit(eSLIMCirObj& obj); + void setInTFI(eSLIMCirObj& obj); + void setInTFO(eSLIMCirObj& obj); + bool inSubcircuit(const eSLIMCirObj& obj) const; + bool inTFI(const eSLIMCirObj& obj) const; + bool inTFO(const eSLIMCirObj& obj) const; + + void markSubcircuit(const std::vector& nodes); + void markCones(const std::vector& nodes); + + int addPi(); + int addPo(int fanin, bool negated); + int addNode(const std::vector& fanins, ABC_UINT64_T tt); + + void print() const; + void print(const Subcircuit& scir) const; + eSLIMCirMan duplicate() const; + + private: + + bool isTaboo(const eSLIMCirObj& obj, int taboo_time) const; + void setTaboo(eSLIMCirObj& obj); + + eSLIMCirObj* getpObj(int id); + const eSLIMCirObj* getpObj(int id) const; + + eSLIMCirObj* getPo(int id); + + static ABC_UINT64_T ttFromGiaObj(Gia_Man_t * pGia, Gia_Obj_t * pObj); + static ABC_UINT64_T ttFromNtkObj(Abc_Ntk_t * pNtk, Abc_Obj_t * pObj); + + std::vector> replaceInternal(eSLIMCirMan& replacement, const Subcircuit& subcir); + void setupMarksForReplacement(eSLIMCirMan& replacement); + void clearFanouts(const Subcircuit& subcir); + + void insertSorted(eSLIMCirObj* obj, std::vector>& sorted, + eSLIMCirMan& replacement, const std::unordered_map& out_map, const std::vector& in_vec); + void insertSortedRec( eSLIMCirObj* obj, std::vector>& sorted, + eSLIMCirMan& replacement, const std::unordered_map& out_map, const std::vector& in_vec); + + void insertSortedRecRep(eSLIMCirObj* obj, std::vector>& sorted, + eSLIMCirMan& replacement, const std::unordered_map& out_map, const std::vector& in_vec); + void processRepFanin( eSLIMCirObj* obj, eSLIMCirObj* fan, int fid, std::vector>& sorted, + eSLIMCirMan& replacement, const std::unordered_map& out_map, const std::vector& in_vec); + void processRepPo( eSLIMCirObj* obj, eSLIMCirObj* fan, int fid, std::vector>& sorted, + eSLIMCirMan& replacement, const std::unordered_map& out_map, const std::vector& in_vec); + void processNonGateRepFanin(eSLIMCirObj* obj, eSLIMCirObj* fan, int fid, std::vector>& sorted, + eSLIMCirMan& replacement, const std::unordered_map& out_map, const std::vector& in_vec); + void addFans(eSLIMCirObj* out, eSLIMCirObj* in, int fin_id); + + + int addGiaGate(Gia_Man_t * pGia, int node_id, std::vector& node_ids, std::vector& is_node_negated); + static ABC_UINT64_T sop2tt(char * pSop); + static char* tt2sop(ABC_UINT64_T tt, int nVars, Mem_Flex_t * pMan); + + int insertNtkNodes(Abc_Ntk_t * pNtk, int node_id, std::unordered_map& ids, bool simplify); + + int processRedundant(const Subcircuit& subcir); + void moveNode(std::vector>& vec, std::unique_ptr& pobj); + void setMarks(eSLIMCirObj& pObj, int id); + + // The nodes vector contains nodes in topological order. + // This does not necessarily ensure that if a < b we have lv(a) < lv(b) (lv: the level/depth of the node) + // If nodes are sorted according to their levels i.e. a <= b iff lv(a) <= lv(b) then the nodes are also topologically sorted. + void applyLevelBasedOrdering(); + void applyDFSOrdering(const std::vector& po_nodes); // po_nodes must contain the node_id of each primary output + void applyDFSOrderingRec(eSLIMCirObj* obj, std::vector>& sorted); + + // remove repeated fanins + // The Gia representation does not allow repeated fanins. + void simplifyDuplicateFanins(); + ABC_UINT64_T removeInputFromTT(ABC_UINT64_T tt, unsigned int first_occurrence, unsigned int second_occurrence); + ABC_UINT64_T compressTT(ABC_UINT64_T tt, unsigned int input); + + unsigned int nof_pis = 0; + unsigned int nof_pos = 0; + std::vector> nodes; + unsigned int last_node_id = 0; + + static constexpr int const_false_id = 0; + unsigned int traversal_id = 0; + + int depth = 0; + + TabooList* taboo = nullptr; + + friend TabooList; + template friend class WindowMan; + + }; + +} +ABC_NAMESPACE_CXX_HEADER_END + +#endif \ No newline at end of file diff --git a/src/opt/eslim/module.make b/src/opt/eslim/module.make index f300a42315..e9106a941b 100644 --- a/src/opt/eslim/module.make +++ b/src/opt/eslim/module.make @@ -1,2 +1,7 @@ -SRC += src/opt/eslim/relationGeneration.cpp \ - src/opt/eslim/eSLIM.cpp \ No newline at end of file +SRC += src/opt/eslim/eSLIM.cpp \ + src/opt/eslim/eslimCirMan.cpp \ + src/opt/eslim/relationGeneration.cpp \ + src/opt/eslim/subcircuit.cpp \ + src/opt/eslim/relationSynthesiser.cpp \ + src/opt/eslim/areaEngine.cpp \ + src/opt/eslim/delayEngine.cpp \ diff --git a/src/opt/eslim/relationGeneration.cpp b/src/opt/eslim/relationGeneration.cpp index 66dc11effb..89fc4fd4c9 100644 --- a/src/opt/eslim/relationGeneration.cpp +++ b/src/opt/eslim/relationGeneration.cpp @@ -6,167 +6,419 @@ PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] - Synopsis [Procedures for computing Boolean relations.] + Synopsis [SAT-based computation of Boolean relations.] Author [Franz-Xaver Reichl] Affiliation [University of Freiburg] - Date [Ver. 1.0. Started - March 2025.] + Date [Ver. 1.0. Started - April 2026.] - Revision [$Id: relationGeneration.cpp,v 1.00 2025/03/17 00:00:00 Exp $] + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] ***********************************************************************/ #include +#include -#include "misc/vec/vec.h" -#include "sat/cnf/cnf.h" -#include "sat/bsat/satSolver.h" +#include "misc/util/abc_global.h" #include "relationGeneration.hpp" -ABC_NAMESPACE_HEADER_START - void * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fMapping, int fVerbose ); - void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit ); - Vec_Int_t * Gia_ManCollectNodeTfos( Gia_Man_t * p, int * pNodes, int nNodes ); - Vec_Int_t * Gia_ManCollectNodeTfis( Gia_Man_t * p, Vec_Int_t * vNodes ); -ABC_NAMESPACE_HEADER_END ABC_NAMESPACE_IMPL_START +namespace eSLIM { -namespace eSLIM { + Relation::Relation(int nfanins) : output_patterns(1 << nfanins) { - RelationGeneratorABC::RelationGeneratorABC(Gia_Man_t* pGia, const Subcircuit& subcir) - : RelationGenerator(pGia, subcir) { + } - // for (const auto& [out, inputs] : subcir.forbidden_pairs) { - for (const auto& it: subcir.forbidden_pairs) { - const auto& inputs = it.second; - inputs_in_forbidden_pairs.insert(inputs.begin(), inputs.end()); + void Relation::addOutputPattern(int inputidx, std::vector&& pattern) { + lines_with_pattern += output_patterns[inputidx].empty(); + output_patterns[inputidx].push_back(pattern); + } + + RelationGenerator::RelationGenerator( const eSLIMCirMan& cir, const Subcircuit& subcir, + const eSLIMConfig& cfg, eSLIMLog& log) + : cir(cir), subcir(subcir), cfg(cfg), log(log), + gate2varref(cir.getNofObjs() - cir.getNofPos()), + gate2varcone(cir.getNofObjs() - cir.getNofPos()) { + setupEncoding(); + } + + Relation RelationGenerator::computeRelation(const eSLIMCirMan& cir, const Subcircuit& subcir, + const eSLIMConfig& cfg, eSLIMLog& log) { + RelationGenerator rgen(cir, subcir, cfg, log); + return rgen.getRelation(); + } + + int RelationGenerator::getNewVar() { + return max_var++; } -} - Vec_Int_t* RelationGeneratorABC::getRelationImpl() { - abctime clkStart = Abc_Clock(); - int nTimeOut = 600, nConfLimit = 1000000; - int i, iNode, iSatVar, Iter, Mask, nSolutions = 0, RetValue = 0; - // --------------- Modification --------------- - Gia_Man_t* pMiter = generateMiter(); - // --------------- Modification --------------- - Cnf_Dat_t * pCnf = (Cnf_Dat_t*)Mf_ManGenerateCnf( pMiter, 8, 0, 0, 0, 0 ); - sat_solver * pSat = (sat_solver*)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); - int iLit = Abc_Var2Lit( 1, 0 ); // enumerating the care set (the miter output is 1) - int status = sat_solver_addclause( pSat, &iLit, &iLit + 1 ); assert( status ); - Vec_Int_t * vSatVars = Vec_IntAlloc( Vec_IntSize(subcir.io) ); - Vec_IntForEachEntry( subcir.io, iNode, i ) - Vec_IntPush( vSatVars, i < subcir.nof_inputs ? 2+i : pCnf->nVars-Vec_IntSize(subcir.io)+i ); - Vec_Int_t * vLits = Vec_IntAlloc( 100 ); - Vec_Int_t * vRes = Vec_IntAlloc( 1000 ); - for ( Iter = 0; Iter < 1000000; Iter++ ) - { - int status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); - if ( status == l_False ) { RetValue = 1; break; } - if ( status == l_Undef ) { RetValue = 0; break; } - nSolutions++; - // extract SAT assignment - Mask = 0; - Vec_IntClear( vLits ); - Vec_IntForEachEntry( vSatVars, iSatVar, i ) { - Vec_IntPush( vLits, Abc_Var2Lit(iSatVar, sat_solver_var_value(pSat, iSatVar)) ); - if ( sat_solver_var_value(pSat, iSatVar) ) - Mask |= 1 << (Vec_IntSize(subcir.io)-1-i); + void RelationGenerator::setupEncoding() { + if (cfg.approximate_relation) { + if (cfg.generate_relation_with_tfi_limit) { + encodeCircuitApproximativeBoundedTFI(); + } else { + encodeCircuitApproximative(); + } + } else { + // encodeCircuitFull(); + encodeCircuitAffected(); + } + } + + void RelationGenerator::encodeGate(const eSLIMCirObj& obj, int var, const std::vector& gate2var) { + int bc = popcount(obj.tt); + int tt_length = obj.getTTLength(); + if (bc == 0) { + solver.addClause({-var}); + } else if (bc == tt_length) { + solver.addClause({var}); + } else if (bc == 1) { + return getGateEncodingUnique(obj, var, gate2var, true); + } else if (bc == tt_length - 1) { + return getGateEncodingUnique(obj, var, gate2var, false); + } else { + return getGateEncodingNaive(obj, var, gate2var); + } + } + + void RelationGenerator::getGateEncodingUnique(const eSLIMCirObj& obj, int var, const std::vector& gate2var, bool unique_bit) { + ABC_UINT64_T tt = obj.tt; + if (!unique_bit) { + tt = eSLIMCirMan::negateTT(tt, obj.getNFanins()); + } + int bit_index = lsb(tt); + std::vector clause; + int lit = unique_bit ? -var : var; + for (int i = 0; i < obj.getNFanins(); i++) { + if ((bit_index >> i) & 1 ) { + clause.push_back(-gate2var[obj.fanins[i]->node_id]); + solver.addClause({gate2var[obj.fanins[i]->node_id], lit}); + } else { + clause.push_back(gate2var[obj.fanins[i]->node_id]); + solver.addClause({-gate2var[obj.fanins[i]->node_id], lit}); + } + } + clause.push_back(-lit); + solver.addClause(clause); + } + + void RelationGenerator::getGateEncodingNaive(const eSLIMCirObj& obj, int var, const std::vector& gate2var) { + int tt_length = obj.getTTLength(); + int nfans = obj.getNFanins(); + std::vector clause; + clause.reserve(nfans+1); + for (int i = 0; i < tt_length; i++) { + clause.clear(); + for (int j = 0; j < nfans; j++) { + if ((i >> j) & 1 ) { + clause.push_back(-gate2var[obj.fanins[j]->node_id]); + } else { + clause.push_back(gate2var[obj.fanins[j]->node_id]); } - Vec_IntPush( vRes, Mask ); - if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) ) - { RetValue = 1; break; } - if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = 0; break; } - } - // complement the set of input/output minterms - Vec_Int_t * vBits = Vec_IntStart( 1 << Vec_IntSize(subcir.io) ); - Vec_IntForEachEntry( vRes, Mask, i ) - Vec_IntWriteEntry( vBits, Mask, 1 ); - Vec_IntClear( vRes ); - Vec_IntForEachEntry( vBits, Mask, i ) - if ( !Mask ) - Vec_IntPush( vRes, i ); - Vec_IntFree( vBits ); - // cleanup - Vec_IntFree( vLits ); - Vec_IntFree( vSatVars ); - sat_solver_delete( pSat ); - Gia_ManStop( pMiter ); - Cnf_DataFree( pCnf ); - if ( RetValue == 0 ) - Vec_IntFreeP( &vRes ); - return vRes; - } - - Gia_Man_t * RelationGeneratorABC::generateMiter() { - Vec_Int_t * vInsOuts = subcir.io; - int nIns = subcir.nof_inputs; - - Vec_Int_t * vTfo = Gia_ManCollectNodeTfos( pGia, Vec_IntEntryP(vInsOuts, nIns), Vec_IntSize(vInsOuts)-nIns ); - Vec_Int_t * vTfi = Gia_ManCollectNodeTfis( pGia, vTfo ); - Vec_Int_t * vInLits = Vec_IntAlloc( nIns ); - Vec_Int_t * vOutLits = Vec_IntAlloc( Vec_IntSize(vInsOuts) - nIns ); - Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iLit = 0; - Gia_ManFillValue( pGia ); - pNew = Gia_ManStart( 1000 ); - pNew->pName = Abc_UtilStrsav( pGia->pName ); - Gia_ManHashAlloc( pNew ); - Gia_ManForEachObjVec( vTfi, pGia, pObj, i ) - if ( Gia_ObjIsCi(pObj) ) - pObj->Value = Gia_ManAppendCi(pNew); - for ( i = 0; i < Vec_IntSize(vInsOuts)-nIns; i++ ) - Vec_IntPush( vInLits, Gia_ManAppendCi(pNew) ); - Gia_ManForEachObjVec( vTfi, pGia, pObj, i ) - if ( Gia_ObjIsAnd(pObj) ) - pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - Gia_ManForEachObjVec( vTfo, pGia, pObj, i ) - if ( Gia_ObjIsCo(pObj) ) - pObj->Value = Gia_ObjFanin0Copy(pObj); - Gia_ManForEachObjVec( vInsOuts, pGia, pObj, i ) - if ( i < nIns ) - Vec_IntPush( vOutLits, pObj->Value ); - else - pObj->Value = Vec_IntEntry( vInLits, i-nIns ); + } + bool polarity = (obj.tt >> i) & 1; + if (polarity) { + clause.push_back(var); + } else { + clause.push_back(-var); + } + solver.addClause(clause); + } + } + + + void RelationGenerator::encodeCircuitAffected() { + setupConstantGate(); + std::vector compare_nodes; + for (int i = cir.getNofObjs() - cir.getNofPos(); i < cir.getNofObjs(); i++) { + const auto obj = cir.getObj(i); + int fid = obj.fanins[0]->node_id; + // multiple POs can use the same fanin + // if gate2varref[fid] is not 0 we have already seen it + if (cir.inTFO(obj) && !gate2varref[fid]) { + gate2varref[fid] = getNewVar(); + gate2varcone[fid] = getNewVar(); + compare_nodes.push_back(fid); + } + } + setupEqualityConstraints(compare_nodes); + + for (int i = cir.getNofObjs() - cir.getNofPos() - 1; i > cir.getNofPis(); i--) { + if (gate2varref[i]) { // the gate is connected to a PO that is in the TFO of the subcircuit + const auto obj = cir.getObj(i); + for (const auto& f : obj.fanins) { + int fid = f->node_id; + if (gate2varref[fid] == 0) { + gate2varref[fid] = getNewVar(); + } + } + encodeGate(obj, gate2varref[i], gate2varref); + + if (cir.inTFO(obj) && !cir.inSubcircuit(obj)) { + // For an input in a forbidden pair no successors needs to be processed before + gate2varcone[i] = gate2varcone[i] ? gate2varcone[i] : getNewVar(); + for (const auto& f : obj.fanins) { + int fid = f->node_id; + if (cir.inSubcircuit(*f) || cir.inTFO(*f)) { + if (gate2varcone[fid] == 0) { + gate2varcone[fid] = getNewVar(); + } + } else { + gate2varcone[fid] = gate2varref[fid]; + } + } + encodeGate(obj, gate2varcone[i], gate2varcone); + } else if (gate2varcone[i] == 0) { + gate2varcone[i] = gate2varref[i]; + } + } + } - Gia_ManIncrementTravId(pGia); - Gia_ManForEachObjVec( subcir.nodes, pGia, pObj, i ) { - Gia_ObjSetTravIdCurrent(pGia, pObj); - } - - Gia_ManForEachObjVec( vTfo, pGia, pObj, i ) - // in case there are forbidden pairs we have to ensure that nodes from the sucircuit are not added - if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsTravIdCurrent(pGia, pObj) ) - pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); - Gia_ManForEachObjVec( vTfo, pGia, pObj, i ) - if ( Gia_ObjIsCo(pObj) ) - iLit = Gia_ManHashOr( pNew, iLit, Gia_ManHashXor(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) ); - // --------------- Modification --------------- - // In case there are forbidden pairs, the outputs of the subcircuit influence the inputs of the subcircuit. - // Therefore, we need the values of the inputs in the version of the circuit that is affected by the new outputs. - for (int inp : inputs_in_forbidden_pairs) { - int node_id = Vec_IntEntry(vInsOuts, inp); - pObj = Gia_ManObj(pGia, node_id); - Vec_IntWriteEntry(vOutLits, inp, pObj->Value); - } - // --------------- Modification --------------- - Gia_ManAppendCo( pNew, iLit ); - Vec_IntForEachEntry( vOutLits, iLit, i ) - Gia_ManAppendCo( pNew, iLit ); - Vec_IntFree( vTfo ); - Vec_IntFree( vTfi ); - Vec_IntFree( vInLits ); - Vec_IntFree( vOutLits ); - pNew = Gia_ManCleanup( pTemp = pNew ); - Gia_ManStop( pTemp ); - Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); - return pNew; - } - -} + for (int i = 1; i <= cir.getNofPis(); i++) { + if (gate2varref[i] != 0) { + cone_input_variables.push_back(gate2varref[i]); + // Simplifies handling of variables + if (gate2varcone[i] == 0) { + gate2varcone[i] = gate2varref[i]; + } + } + } + } + + + void RelationGenerator::encodeCircuitApproximative() { + setupConstantGate(); + std::vector compare_nodes = markRestrictedCone(); + int max_node = *std::max_element(compare_nodes.begin(), compare_nodes.end()); + for (int i = max_node; i > cir.getNofPis(); i--) { + const auto obj = cir.getObj(i); + if (gate2varref[i] != 0) { + for (auto& f : obj.fanins ) { + if (gate2varref[f->node_id] == 0) { + gate2varref[f->node_id] = getNewVar(); + gate2varcone[f->node_id] = gate2varref[f->node_id]; + } + } + encodeGate(obj, gate2varref[i], gate2varref); + if (!cir.inSubcircuit(obj) && gate2varcone[i] != gate2varref[i]) { + encodeGate(obj, gate2varcone[i], gate2varcone); + } + } + } + for (int i = 1; i <= cir.getNofPis(); i++) { + if (gate2varref[i] != 0) { + cone_input_variables.push_back(gate2varref[i]); + } + } + setupEqualityConstraints(compare_nodes); + } + void RelationGenerator::encodeCircuitApproximativeBoundedTFI() { + setupConstantGate(); + std::vector compare_nodes = markRestrictedCone(); + std::vector counts(cir.getNofObjs() - cir.getNofPos()); + int max_node = *std::max_element(compare_nodes.begin(), compare_nodes.end()); + for (int i = max_node; i > cir.getNofPis(); i--) { + const auto obj = cir.getObj(i); + if (gate2varref[i] != 0) { + if (cir.inTFO(obj) || cir.inSubcircuit(obj)) { + counts[i] = cfg.relation_tfi_bound + 1; + } else if (counts[i] == 0) { + cone_input_variables.push_back(gate2varref[i]); + continue; + } + for (auto& f : obj.fanins ) { + if (gate2varref[f->node_id] == 0) { + gate2varref[f->node_id] = getNewVar(); + gate2varcone[f->node_id] = gate2varref[f->node_id]; + counts[f->node_id] = std::max(counts[f->node_id], static_cast(counts[i] - 1)); + } + } + encodeGate(obj, gate2varref[i], gate2varref); + if (!cir.inSubcircuit(obj) && gate2varcone[i] != gate2varref[i]) { + encodeGate(obj, gate2varcone[i], gate2varcone); + } + } + } + for (int i = 1; i <= cir.getNofPis(); i++) { + if (gate2varref[i] != 0) { + cone_input_variables.push_back(gate2varref[i]); + } + } + setupEqualityConstraints(compare_nodes); + } + + std::vector RelationGenerator::markRestrictedCone() { + std::vector counts(cir.getNofObjs() - cir.getNofPos()); + for (int i : subcir.outputs) { + gate2varref[i] = getNewVar(); + gate2varcone[i] = getNewVar(); + counts[i] = cfg.relation_tfo_bound; + } + if (cfg.relation_tfo_bound == 0) { + std::vector nodes(subcir.outputs.begin(), subcir.outputs.end()); + return nodes; + } + std::vector nodes; + for (int i = subcir.outputs[0] + 1; i < cir.getNofObjs() - cir.getNofPos(); i++) { //outputs are ordered + const auto obj = cir.getObj(i); + if (!cir.inTFO(obj) || cir.inSubcircuit(obj)) { + continue; + } + unsigned char x = 0; + for (auto& f : obj.fanins) { + x = std::max(x, counts[f->node_id]); + } + if (x > 0) { + gate2varcone[i] = getNewVar(); + gate2varref[i] = getNewVar(); + counts[i] = x - 1; + if (x == 1) { + nodes.push_back(i); + } + } + } + std::set used; + for (int i = cir.getNofObjs() - cir.getNofPos(); i < cir.getNofObjs(); i++) { + const auto obj = cir.getObj(i); + if (cir.inTFO(obj) && counts[obj.fanins[0]->node_id] > 0 && used.find(obj.fanins[0]->node_id) == used.end()) { + nodes.push_back(obj.fanins[0]->node_id); + used.insert(obj.fanins[0]->node_id); + } + } + return nodes; + } + + void RelationGenerator::setupConstantGate() { + int const_var = getNewVar(); + gate2varref[0] = const_var; + gate2varcone[0] = const_var; + solver.addClause({-const_var}); + } + + void RelationGenerator::setupEqualityConstraints(const std::vector& nodes) { + mode_selection_variable = getNewVar(); + std::vector one_different {-mode_selection_variable}; + for (int cnd : nodes) { + int eq_var = getNewVar(); + equality_variables.push_back(eq_var); + getEqualityClauses(gate2varref[cnd], gate2varcone[cnd], eq_var); + one_different.push_back(-eq_var); + } + solver.addClause(one_different); + } + + + void RelationGenerator::getEqualityClauses(int x, int y, int aux) { + solver.addClause({x, -y, -aux}); + solver.addClause({-x, y, -aux}); + solver.addClause({x, y, aux}); + solver.addClause({-x, -y, aux}); + } + + int RelationGenerator::findConflict(double& timeout, int mode_selection) { + abctime time_start = Abc_Clock(); + int solver_status = solver.solve(timeout, {mode_selection}); + double solver_time = (double)1.0*(Abc_Clock() - time_start)/CLOCKS_PER_SEC; + log.cummulative_sat_runtime_relation_generation += solver_time; + log.max_sat_runtime_relation_generation = std::max(log.max_sat_runtime_relation_generation, solver_time); + // log.cummulative_sat_runtime_relation_generation += solver.getRunTime(); + log.nof_sat_calls_relation_generation++; + return solver_status; + } + + int RelationGenerator::reduceConflict(double& timeout, const std::vector& cone_input, + const std::vector& subcircuit_output, const std::vector& equality) { + solver.assume(cone_input); + solver.assume(subcircuit_output); + solver.assume(equality); + abctime time_start = Abc_Clock(); + int status = solver.solve(timeout); + double solver_time = (double)1.0*(Abc_Clock() - time_start)/CLOCKS_PER_SEC; + log.cummulative_sat_runtime_relation_generation += solver_time; + log.max_sat_runtime_relation_generation = std::max(log.max_sat_runtime_relation_generation, solver_time); + // log.cummulative_sat_runtime_relation_generation += solver.getRunTime(); + log.nof_sat_calls_relation_generation++; + return status; + } + + Relation RelationGenerator::getRelation() { + std::vector subcircuit_input_variables; + subcircuit_input_variables.reserve(subcir.inputs.size()); + for (int sin : subcir.inputs) { + int var = gate2varcone[sin]; + subcircuit_input_variables.push_back(var); + } + std::vector subcircuit_output_variables; + subcircuit_output_variables.reserve(subcir.outputs.size()); + // outputs in forbidden pairs must not removed + std::vector outputs_to_keep(subcir.outputs.size(), false); + for (int i = 0; i < subcir.outputs.size(); i++) { + int sout = subcir.outputs[i]; + int var = gate2varcone[sout]; + subcircuit_output_variables.push_back(var); + if (subcir.forbidden_pairs.find(sout) != subcir.forbidden_pairs.end()) { + outputs_to_keep[i] = true; + } + } + + Relation rel(subcir.inputs.size()); + + int solver_status; + double timeout = cfg.relation_generation_timeout; + abctime time_start = Abc_Clock(); + while( (solver_status=findConflict(timeout, mode_selection_variable)) == 10) { + timeout -= (double)1.0*(Abc_Clock() - time_start)/CLOCKS_PER_SEC; + time_start = Abc_Clock(); + if (timeout <= 0) { + rel.status = false; + return rel; + } + std::vector cone_in_assm = solver.getValues(cone_input_variables); + std::vector sin_assm = solver.getValues(subcircuit_input_variables); + std::vector sout_assm = solver.getValues(subcircuit_output_variables); + int status = reduceConflict(timeout, cone_in_assm, sout_assm, equality_variables); + if (status != 20) { + assert (status != 10); + rel.status = false; + return rel; + } + assert (status == 20); + std::vector blocking_clause {-mode_selection_variable}; + for (int i = 0; i < subcir.inputs.size(); i++) { + blocking_clause.push_back(-sin_assm[i]); + } + std::vector pattern (2*subcir.outputs.size(), false); + for (int i = 0; i < subcir.outputs.size(); i++) { + if (solver.isFailed(sout_assm[i]) || outputs_to_keep[i]) { + pattern[2*i] = true; + pattern[2*i + 1] = sout_assm[i] < 0; // at least one output must be assigned differently in order to preserve the function + blocking_clause.push_back(-sout_assm[i]); + } + } + solver.addClause(blocking_clause); + rel.addOutputPattern(assignment2bvindex(sin_assm), std::move(pattern)); + } + if (solver_status != 20) { + rel.status = false; + } + return rel; + } + + int RelationGenerator::assignment2bvindex(const std::vector& assm) { + int idx = 0; + for (int i = 0; i < assm.size(); i++) { + if (assm[i] > 0) { + idx |= 1 << i; + } + } + return idx; + } + +} ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/opt/eslim/relationGeneration.hpp b/src/opt/eslim/relationGeneration.hpp index 28d8dc512b..c2d95d499c 100644 --- a/src/opt/eslim/relationGeneration.hpp +++ b/src/opt/eslim/relationGeneration.hpp @@ -6,190 +6,114 @@ PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] - Synopsis [Procedures for computing Boolean relations.] + Synopsis [SAT-based computation of Boolean relations.] Author [Franz-Xaver Reichl] Affiliation [University of Freiburg] - Date [Ver. 1.0. Started - March 2025.] + Date [Ver. 1.0. Started - April 2026.] - Revision [$Id: relationGeneration.hpp,v 1.00 2025/03/17 00:00:00 Exp $] + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] ***********************************************************************/ -#ifndef ABC__OPT__ESLIM__RELATIONGENERATION_h -#define ABC__OPT__ESLIM__RELATIONGENERATION_h +#ifndef ABC__OPT__ESLIM__RELATIONGENERATION_hpp +#define ABC__OPT__ESLIM__RELATIONGENERATION_hpp #include #include -#include #include "misc/util/abc_namespaces.h" -#include -#include "aig/gia/gia.h" -#include "misc/util/utilTruth.h" // ioResub.h depends on utilTruth.h -#include "base/io/ioResub.h" +#include "eslimCirMan.hpp" +#include "cadicalSolver.hpp" +#include "subcircuit.hpp" #include "utils.hpp" -// #include "satInterfaces.hpp" - ABC_NAMESPACE_CXX_HEADER_START - namespace eSLIM { - template + class RelationGenerator; + + class Relation{ + + public: + Relation(int nfanins); + const std::vector>& getPattern(int id) const {return output_patterns[id];} + int getNPatterns() const {return output_patterns.size();} + int getPatternSize(int id) const {return output_patterns[id].size();} + unsigned int getNLinesWithPattern() const {return lines_with_pattern;} + bool getStatus() const {return status;} + + + private: + + // Each entry of the first vector level corresponds to an input assignment. + // The second level lists all conflicting output assignments. + // The third lists the individual conflicting output assignments. + // One output is represented by two bits, the first bit determines if this output is present the conflicting output assignments + // and the second indicate if it is true or false + void addOutputPattern(int inputidx, std::vector&& pattern); + std::vector>> output_patterns; + + unsigned int lines_with_pattern = 0; + bool status = true; + + + friend RelationGenerator; + }; + class RelationGenerator { public: - static Abc_RData_t* computeRelation(Gia_Man_t* gia_man, const Subcircuit& subcir); + static Relation computeRelation(const eSLIMCirMan& cir, const Subcircuit& subcir, const eSLIMConfig& cfg, eSLIMLog& log); private: - Gia_Man_t* pGia; + const eSLIMCirMan& cir; const Subcircuit& subcir; - - RelationGenerator(Gia_Man_t* pGia, const Subcircuit& subcir); - void setup(); - Vec_Int_t* getRelation(); - - static Abc_RData_t* constructABCRelationRepresentation(Vec_Int_t * patterns, int nof_inputs, int nof_outputs); - // Reimplementation with disabled prints - // We do not want to modify code in other parts of ABC - static Abc_RData_t * Abc_RData2Rel( Abc_RData_t * p ); - - friend Derived; - }; + const eSLIMConfig& cfg; + eSLIMLog& log; - // The class almost entirely duplicates the functionality provided by Gia_ManGenIoCombs in giaQBF.c - // But the implementation in this class allows to take forbidden pairs into account. - class RelationGeneratorABC : public RelationGenerator { + int max_var = 1; + + std::vector gate2varref; + std::vector gate2varcone; + std::vector equality_variables; + std::vector cone_input_variables; + int mode_selection_variable; - private: - RelationGeneratorABC(Gia_Man_t* pGia, const Subcircuit& subcir); - void setupImpl() {}; - Vec_Int_t* getRelationImpl(); - Gia_Man_t * generateMiter(); - std::unordered_set inputs_in_forbidden_pairs; - - friend RelationGenerator; - }; + CadicalSolver solver; + RelationGenerator(const eSLIMCirMan& cir, const Subcircuit& subcir, const eSLIMConfig& cfg, eSLIMLog& log); + void setupEncoding(); - // Add other engine for the generation of relations - // class MyRelationGenerator : public RelationGenerator { - // private: - // void setupImpl() - // Vec_Int_t* getRelationImpl(); - // friend RelationGenerator; - // }; - - - template - inline RelationGenerator::RelationGenerator(Gia_Man_t* pGia, const Subcircuit& subcir) - : pGia(pGia), subcir(subcir) { - } - - template - inline Abc_RData_t* RelationGenerator::computeRelation(Gia_Man_t* gia_man, const Subcircuit& subcir) { - T generator(gia_man, subcir); - generator.setup(); - Vec_Int_t* relation_patterns_masks = generator.getRelation(); - if ( relation_patterns_masks == NULL ) { - return nullptr; - } - int nof_inputs = subcir.nof_inputs; - int nof_outputs = Vec_IntSize(subcir.io) - subcir.nof_inputs; - Abc_RData_t* r = constructABCRelationRepresentation(relation_patterns_masks, nof_inputs, nof_outputs); - Vec_IntFree(relation_patterns_masks); - return r; - } - - template - inline Abc_RData_t* RelationGenerator::constructABCRelationRepresentation(Vec_Int_t * patterns, int nof_inputs, int nof_outputs) { - int i, mask; - int nof_vars = nof_inputs + nof_outputs; - Abc_RData_t* p = Abc_RDataStart( nof_inputs, nof_outputs, Vec_IntSize(patterns) ); - Vec_IntForEachEntry( patterns, mask, i ) { - for ( int k = 0; k < nof_vars; k++ ) { - if ( (mask >> (nof_vars-1-k)) & 1 ) { - if ( k < nof_inputs ) { - Abc_RDataSetIn( p, k, i ); - } else { - Abc_RDataSetOut( p, 2*(k-nof_inputs)+1, i ); - } - } else { - if ( k >= nof_inputs ) { - Abc_RDataSetOut( p, 2*(k-nof_inputs), i ); - } - } - } - } - Abc_RData_t* p2 = Abc_RData2Rel(p); - Abc_RDataStop(p); - return p2; - } - - template - inline Abc_RData_t * RelationGenerator::Abc_RData2Rel( Abc_RData_t * p ) { - assert( p->nIns < 64 ); - assert( p->nOuts < 32 ); - int w; - Vec_Wrd_t * vSimsIn2 = Vec_WrdStart( 64*p->nSimWords ); - Vec_Wrd_t * vSimsOut2 = Vec_WrdStart( 64*p->nSimWords ); - for ( w = 0; w < p->nIns; w++ ) - Abc_TtCopy( Vec_WrdEntryP(vSimsIn2, w*p->nSimWords), Vec_WrdEntryP(p->vSimsIn, w*p->nSimWords), p->nSimWords, 0 ); - for ( w = 0; w < p->nOuts; w++ ) - Abc_TtCopy( Vec_WrdEntryP(vSimsOut2, w*p->nSimWords), Vec_WrdEntryP(p->vSimsOut, (2*w+1)*p->nSimWords), p->nSimWords, 0 ); - Vec_Wrd_t * vTransIn = Vec_WrdStart( 64*p->nSimWords ); - Vec_Wrd_t * vTransOut = Vec_WrdStart( 64*p->nSimWords ); - Extra_BitMatrixTransposeP( vSimsIn2, p->nSimWords, vTransIn, 1 ); - Extra_BitMatrixTransposeP( vSimsOut2, p->nSimWords, vTransOut, 1 ); - Vec_WrdShrink( vTransIn, p->nPats ); - Vec_WrdShrink( vTransOut, p->nPats ); - Vec_Wrd_t * vTransInCopy = Vec_WrdDup(vTransIn); - Vec_WrdUniqify( vTransInCopy ); - // if ( Vec_WrdSize(vTransInCopy) == p->nPats ) - // printf( "This resub problem is not a relation.\n" ); - // create the relation - Abc_RData_t * pNew = Abc_RDataStart( p->nIns, 1 << (p->nOuts-1), Vec_WrdSize(vTransInCopy) ); - pNew->nOuts = p->nOuts; - int i, k, n, iLine = 0; word Entry, Entry2; - Vec_WrdForEachEntry( vTransInCopy, Entry, i ) { - for ( n = 0; n < p->nIns; n++ ) - if ( (Entry >> n) & 1 ) - Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(pNew->vSimsIn, n*pNew->nSimWords), iLine ); - Vec_WrdForEachEntry( vTransIn, Entry2, k ) { - if ( Entry != Entry2 ) - continue; - Entry2 = Vec_WrdEntry( vTransOut, k ); - assert( Entry2 < (1 << p->nOuts) ); - Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(pNew->vSimsOut, Entry2*pNew->nSimWords), iLine ); - } - iLine++; - } - assert( iLine == pNew->nPats ); - Vec_WrdFree( vTransOut ); - Vec_WrdFree( vTransInCopy ); - Vec_WrdFree( vTransIn ); - Vec_WrdFree( vSimsIn2 ); - Vec_WrdFree( vSimsOut2 ); - return pNew; - } - - template - inline void RelationGenerator::setup() { - static_cast(this)->setupImpl(); - } - - template - inline Vec_Int_t* RelationGenerator::getRelation() { - return static_cast(this)->getRelationImpl(); - } -} + void encodeCircuitAffected(); + void encodeCircuitApproximative(); + void encodeCircuitApproximativeBoundedTFI(); + std::vector markRestrictedCone(); + void setupConstantGate(); + void setupEqualityConstraints(const std::vector& nodes); + + Relation getRelation(); + void encodeGate(const eSLIMCirObj& obj, int var, const std::vector& gate2var); + void getGateEncodingUnique(const eSLIMCirObj& obj, int var, const std::vector& gate2var, bool unique_bit); + void getGateEncodingNaive(const eSLIMCirObj& obj, int var, const std::vector& gate2var); + void getEqualityClauses(int x, int y, int aux); + int assignment2bvindex(const std::vector& assm); + + int findConflict(double& timeout, int mode_selection); + int reduceConflict(double& timeout, const std::vector& cone_input, const std::vector& subcircuit_output, const std::vector& equality); + + + int getNewVar(); + + }; + +} ABC_NAMESPACE_CXX_HEADER_END -#endif +#endif \ No newline at end of file diff --git a/src/opt/eslim/relationSynthesiser.cpp b/src/opt/eslim/relationSynthesiser.cpp new file mode 100644 index 0000000000..7fd507fe9a --- /dev/null +++ b/src/opt/eslim/relationSynthesiser.cpp @@ -0,0 +1,617 @@ +/**CFile**************************************************************** + + FileName [relationSynthesiser.cpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Base class for SAT-based synthesis] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#include + +#include "relationSynthesiser.hpp" + + +ABC_NAMESPACE_IMPL_START +namespace eSLIM { + + RelationSynthesiser::RelationSynthesiser(const Relation& relation, const Subcircuit& subcir, unsigned int max_size, const eSLIMConfig& cfg, eSLIMLog& log) + : subcir(subcir), max_size(max_size), + relation(relation), config(cfg), log(log) { + setupEncoding(); + } + + double RelationSynthesiser::getDynamicTimeout(int size) { + if (log.nof_sat_calls_per_size[size] > config.minimum_dynamic_timeout_sample_size) { + return std::max(static_cast(config.minimum_sat_timeout), static_cast(log.cummulative_sat_runtimes_per_size[size]) / (1000*log.nof_sat_calls_per_size[size])); //logged timings are given in ms + } else { + return config.base_sat_timeout; + } + } + + unsigned int RelationSynthesiser::getSizeFromActivationVars(const std::vector& model) { + unsigned int sz = 0; + for (int i = 0; i < max_size; i++) { + if (model[gate_activation_variables[i]]) { + sz++; + } else { + break; + } + } + return sz; + } + + unsigned int RelationSynthesiser::getSizeFromActivationVars() { + unsigned int sz = 0; + for (int i = 0; i < max_size; i++) { + if (solver.getValue(gate_activation_variables[i])) { + sz++; + } else { + break; + } + } + return sz; + } + + void RelationSynthesiser::logRun(int status, unsigned int size) { + log.cummulative_sat_runtime_synthesis += solver.getRunTime(); + log.max_sat_runtime_synthesis = std::max(log.max_sat_runtime_synthesis, solver.getRunTime()); + + log.nof_sat_calls_synthesis++; + if (status == 10) { + log.cummulative_sat_runtimes_per_size[size] += solver.getRunTime(); + log.nof_sat_calls_per_size[size] ++; + } else if (status == 20) { //if the solver does not report sat the formula is unsat or there was a timeout + log.cummulative_unsat_runtimes_per_size[size] += solver.getRunTime(); + log.nof_unsat_calls_per_size[size] ++; + } + } + + std::vector RelationSynthesiser::getSizeAssumption(int size) { + std::vector assumptions; + assumptions.reserve(max_size - size); + for (int i = size; i < max_size; i++) { + assumptions.push_back(-gate_activation_variables[i]); + } + return assumptions; + } + + eSLIMCirMan RelationSynthesiser::getReplacement(const std::vector& model, int size) { + assert (model.size() > 0); + eSLIMCirMan circ(subcir.inputs.size() + subcir.outputs.size() + size); + for (int i = 0; i < subcir.inputs.size(); i++) { + circ.addPi(); + } + + for (int i = 0; i < size; i++) { + std::vector fanins; + for (int j = 0; j < selection_variables[i].size(); j++) { + if (model[selection_variables[i][j]]) { + fanins.push_back(j+1); + } + } + ABC_UINT64_T tt = 0; + for (int j = 0; j < gate_definition_variables[i].size(); j++) { + int idx = j + 1; + if (model[gate_definition_variables[i][j]]) { + tt |= static_cast(1) << idx; + } + } + circ.addNode(fanins, tt); + } + + // outputs + for (int i = 0; i < subcir.outputs.size(); i++) { + for (int j = 0; j < max_size; j++) { + if (model[gate_output_variables[j][i]]) { + circ.addPo(subcir.inputs.size() + j + 1, false); + goto end; + } + } + for (int j = 0; j < subcir.inputs.size(); j++) { + if (model[gate_output_variables[max_size + j][i]]) { + circ.addPo(j + 1, false); + goto end; + } + } + if (model[gate_output_variables.back()[i]]) { + circ.addPo(0, false); + } + end:; + } + return circ; + } + + void RelationSynthesiser::setupEncoding() { + setupVariables(); + setupStructuralConstraints(); + setupSymmetryBreaking(); + setupEquivalenceConstraints(); + } + + void RelationSynthesiser::setupVariables() { + gate_activation_variables.reserve(max_size); + selection_variables.reserve(max_size); + gate_definition_variables.reserve(max_size); + gate_variables.reserve(max_size); + is_ith_fanin_variable.reserve(max_size); + for (int i = 0; i < max_size; i++) { + gate_activation_variables.push_back(getNewVariable()); + selection_variables.push_back(getNewVariableVector(subcir.inputs.size() + i)); + gate_definition_variables.push_back(getNewVariableVector(pow2(config.gate_size) - 1)); + // The replacement circuit shall be normal so we ignore the all-false-behaviour + int normality_offset = relation.getPatternSize(0) > 0; + gate_variables.push_back(getNewVariableVector(relation.getNLinesWithPattern() - normality_offset)); + + std::vector> fanin_vars; + for (int j = 0; j < config.gate_size; j++) { + std::vector fvs(subcir.inputs.size() + i, 0); + for (int k = j; k < subcir.inputs.size() + i - config.gate_size + j + 1; k++) { + fvs[k] = getNewVariable(); + } + fanin_vars.push_back(fvs); + } + is_ith_fanin_variable.push_back(fanin_vars); + } + gate_output_variables.reserve(max_size + subcir.inputs.size() + 1); + for (int i = 0; i < max_size + subcir.inputs.size() + 1; i++) { + gate_output_variables.push_back(getNewVariableVector(subcir.outputs.size())); + } + } + + void RelationSynthesiser::setupStructuralConstraints() { + constrainSelectionVariables(); + constraintGateOutputVariables(); + setupActivationCompatibilityConstraints(); + if (config.aig) { + setupAigerConstraints(); + } + } + + void RelationSynthesiser::setupSymmetryBreaking() { + addNonTrivialConstraint(); + addUseAllStepsConstraint(); + // addNoReapplicationConstraint(); + // addOrderedStepsConstraint(); + } + + void RelationSynthesiser::setupIsFaninVariables(int gtidx, const std::vector>& counter_vars) { + // If we have 3 inputs and gates with two fanins then the first fanin of the first gate can be input 1 or 2 but not input 3. + int noptions = subcir.inputs.size() + gtidx - config.gate_size + 1; + for (int i = 0; i < config.gate_size; i++) { + solver.addClause({-counter_vars[i][i], is_ith_fanin_variable[gtidx][i][i]}); + solver.addClause({counter_vars[i][i], -is_ith_fanin_variable[gtidx][i][i]}); + int offset = (i == config.gate_size - 1); // we do not use block variables for the last selection variables + for (int j = i + 1; j < i + noptions - offset; j++) { + solver.addClause({counter_vars[j - 1][i], counter_vars[j][i], -is_ith_fanin_variable[gtidx][i][j]}); + solver.addClause({counter_vars[j - 1][i], -counter_vars[j][i], is_ith_fanin_variable[gtidx][i][j]}); + } + } + solver.addClause({selection_variables[gtidx].back(), -is_ith_fanin_variable[gtidx].back().back()}); + solver.addClause({-selection_variables[gtidx].back(), is_ith_fanin_variable[gtidx].back().back()}); + } + + void RelationSynthesiser::constrainSelectionVariables() { + int start = 0; + // if the subcircuit has k inputs and gates have k fanins each input is a fanin of the first gate + if (selection_variables[0].size() == config.gate_size) { + start = 1; + for (int j = 0; j < config.gate_size; j++) { + solver.addClause({selection_variables[0][j]}); + solver.addClause({is_ith_fanin_variable[0][j][j]}); + } + } + for (int i = start; i < max_size; i++) { + std::vector> counter_vars = addSequentialCounter(selection_variables[i], config.gate_size); + setupIsFaninVariables(i, counter_vars); + } + } + + void RelationSynthesiser::constraintGateOutputVariables() { + // If the activation variable is false then the gate must not be an output + for (int i = 0; i < max_size; i++) { + for (int v : gate_output_variables[i]) { + solver.addClause({gate_activation_variables[i], -v}); + } + } + for (int i = 0; i < subcir.outputs.size(); i++) { + std::vector clause; + clause.reserve(max_size + subcir.inputs.size() + 1); + for (int j = 0; j < max_size + subcir.inputs.size() + 1; j++) { + clause.push_back(gate_output_variables[j][i]); + } + addCardinalityConstraint(clause, 1); + } + } + + void RelationSynthesiser::addGateValueConstraint(int gtidx, int gt_val, const std::vector& fanin_variables) { + // If all fanins are 0, then the gate yields 0 + std::vector clause {-gate_activation_variables[gtidx]}; + clause.reserve(config.gate_size + 3); + for (int j = 0; j < config.gate_size; j++) { + clause.push_back(fanin_variables[j]); + } + clause.push_back(-gt_val); + solver.addClause(clause); + clause.push_back(0); + + for (int i = 1; i < pow2(config.gate_size); i++) { // we consider normal gates -> the all-0-behaviour does not need to be considered + for (int j = 0; j < config.gate_size; j++) { + clause[j + 1] = abs(clause[j + 1]) * (1-2*getTTValue(i, j)); + } + int gdv = gate_definition_variables[gtidx][i - 1]; // we do not use a gdv for the all-0-behaviour + clause[config.gate_size + 1] = -gdv; + clause[config.gate_size + 2] = gt_val; + solver.addClause(clause); + clause[config.gate_size + 1] = gdv; + clause[config.gate_size + 2] = -gt_val; + solver.addClause(clause); + } + } + + std::vector RelationSynthesiser::setupFaninVariables(int gtidx, int tt_line, int pidx) { + int noptions = subcir.inputs.size() + gtidx - config.gate_size + 1; + std::vector fanin_variables = getNewVariableVector(config.gate_size); + for (int i = 0; i < config.gate_size; i++) { + int bound = i + noptions < subcir.inputs.size() ? i + noptions : subcir.inputs.size(); + for (int j = i; j < bound; j++) { + if (getTTValue(tt_line, j)) { + solver.addClause({-is_ith_fanin_variable[gtidx][i][j], fanin_variables[i]}); + } else { + solver.addClause({-is_ith_fanin_variable[gtidx][i][j], -fanin_variables[i]}); + } + } + for (int j = subcir.inputs.size(); j < i + noptions; j++) { + solver.addClause({-is_ith_fanin_variable[gtidx][i][j], gate_variables[j - subcir.inputs.size()][pidx], -fanin_variables[i]}); + solver.addClause({-is_ith_fanin_variable[gtidx][i][j], -gate_variables[j - subcir.inputs.size()][pidx], fanin_variables[i]}); + } + } + return fanin_variables; + } + + void RelationSynthesiser::setupGateValues() { + int pidx = 0; + for (int i = 1; i < relation.getNPatterns(); i++) { + if (relation.getPatternSize(i) > 0) { + for (int j = 0; j < max_size; j++) { + std::vector fanin_variables = setupFaninVariables(j, i, pidx); + addGateValueConstraint(j, gate_variables[j][pidx], fanin_variables); + } + pidx++; + } + } + } + + void RelationSynthesiser::setupEquivalenceConstraints() { + setupGateValues(); + // normal circuit: all-0-behaviour is ignored + int pidx = 0; + for (int i = 1; i < relation.getNPatterns(); i++) { + std::vector output_vars (subcir.outputs.size(), 0); + const auto& patterns = relation.getPattern(i); + for (const auto& p : patterns) { + assert(2 * subcir.outputs.size() == p.size()); + std::vector cl; + for (int j = 0; j < subcir.outputs.size(); j++) { + if (p[2*j]) { + if (output_vars[j] == 0) { + output_vars[j] = setupOutputVariable(j, i, pidx); + } + if (p[2*j + 1]) { + cl.push_back(output_vars[j]); + } else { + cl.push_back(-output_vars[j]); + } + } + } + solver.addClause(cl); + } + pidx += !patterns.empty(); + } + } + + void RelationSynthesiser::setupActivationCompatibilityConstraints() { + for (int i = 1; i < max_size; i++) { + solver.addClause({-gate_activation_variables[i], gate_activation_variables[i-1]}); + } + } + + int RelationSynthesiser::setupOutputVariable(int output_index, int tt_index, int pattern_idx) { + int var = getNewVariable(); + std::vector clause; + for (int i = 0; i < max_size; i++) { + clause.assign({-gate_activation_variables[i], -gate_output_variables[i][output_index], -gate_variables[i][pattern_idx], var}); + solver.addClause(clause); + clause[2] = -clause[2]; + clause[3] = -clause[3]; + solver.addClause(clause); + } + + for (int i = 0; i < subcir.inputs.size(); i++) { + if (getTTValue(tt_index, i)) { + clause.assign({-gate_output_variables[i + max_size][output_index], var}); + } else { + clause.assign({-gate_output_variables[i + max_size][output_index], -var}); + } + solver.addClause(clause); + } + + clause.assign({-gate_output_variables.back()[output_index], -var}); + solver.addClause(clause); + return var; + } + + void RelationSynthesiser::setupAigerConstraints() { + assert (config.gate_size == 2); + for (int i = 0; i < max_size; i++) { + solver.addClause({-gate_definition_variables[i][0], -gate_definition_variables[i][1], gate_definition_variables[i][2]}); + } + } + + void RelationSynthesiser::addCardinalityConstraint(const std::vector& vars, unsigned int cardinality, int activator) { + assert (cardinality > 0); + assert (vars.size() >= cardinality); + if (vars.size() == cardinality) { + std::vector clause; + if (activator != 0) { + clause.push_back(activator); + } + for (int var : vars) { + clause.push_back(var); + solver.addClause(clause); + clause.pop_back(); + } + } else { + // CHECK: is the naive encoding better? + if (activator == 0) { + if (cardinality == 1) { + addNaiveIs1CardinalityConstraint(vars); + } else if (cardinality == 2) { + addNaiveIs2CardinalityConstraint(vars); + } else { + addSequentialCounter(vars, cardinality, activator); + } + } else { + addSequentialCounter(vars, cardinality, activator); + } + } + } + + // see Carsten Sinz: Towards an Optimal CNF Encoding of Boolean Cardinality Constraints + // As we want that exactly cardinality many variables are set to true we need additional constraints. + // Because of this reason we cannot use the single polarity encoding presented in the paper + std::vector> RelationSynthesiser::addSequentialCounter(const std::vector& vars, unsigned int cardinality, int activator) { + std::vector> component_outputs; + component_outputs.push_back({vars.front()}); + assert (vars.size() > cardinality); + for (int i = 1; i < vars.size() - 1; i++) { + std::vector current_component_outputs; + int v = vars[i]; + int in_var = v; + for (int j = 0; j < component_outputs.back().size(); j++) { + int orv = getNewVariable(); + defineDisjunction(orv, {in_var, component_outputs.back()[j]}, activator); + current_component_outputs.push_back(orv); + if (j < cardinality - 1) { + in_var = getNewVariable(); + defineConjunction(in_var, {v, component_outputs.back()[j]}, activator); + } else { + solver.addClause({-component_outputs.back().back(), -v}); + } + } + if (component_outputs.back().size() < cardinality) { + current_component_outputs.push_back(in_var); + } + component_outputs.push_back(current_component_outputs); + } + + solver.addClause({-component_outputs.back().back(), -vars.back()}); + + // Either subcircuit_outputs.back() is true or subcircuit_outputs[-2] and vars.back() is true + std::vector clause {component_outputs.back().back(), vars.back()}; + solver.addClause(clause); + if (cardinality > 1) { + clause.pop_back(); + clause.push_back(component_outputs.back()[component_outputs.back().size() - 2]); + solver.addClause(clause); + } + return component_outputs; + } + + void RelationSynthesiser::addNaiveIs1CardinalityConstraint(const std::vector& vars) { + solver.addClause(vars); + for (int i = 0; i < vars.size(); i++) { + for (int j = i + 1; j < vars.size(); j++) { + solver.addClause({-vars[i], -vars[j]}); + } + } + } + + void RelationSynthesiser::addNaiveIs2CardinalityConstraint(const std::vector& vars) { + std::vector cl; + cl.reserve(vars.size() - 1); + for (int i = 0; i < vars.size(); i++) { + for (int j = 0; j < i; j++) { + cl.push_back(vars[j]); + } + for (int j = i + 1; j < vars.size(); j++) { + cl.push_back(vars[j]); + } + solver.addClause(cl); + cl.clear(); + + for (int j = i + 1; j < vars.size(); j++) { + for (int k = j + 1; k < vars.size(); k++) { + solver.addClause({-vars[i], -vars[j], -vars[k]}); + } + } + } + } + + void RelationSynthesiser::defineConjunction(int var, std::vector&& literals, int activator) { + std::vector big_clause, small_clause; + if (activator != 0) { + big_clause.reserve(literals.size() + 2); + small_clause.reserve(3); + big_clause.push_back(activator); + small_clause.push_back(activator); + } else { + big_clause.reserve(literals.size() + 1); + small_clause.reserve(2); + } + big_clause.push_back(var); + small_clause.push_back(-var); + for (int lit : literals) { + big_clause.push_back(-lit); + small_clause.push_back(lit); + solver.addClause(small_clause); + small_clause.pop_back(); + } + solver.addClause(big_clause); + } + + void RelationSynthesiser::defineDisjunction(int var, std::vector&& literals, int activator) { + std::vector clause; + literals.push_back(-var); + if (activator != 0) { + literals.push_back(activator); + solver.addClause(literals); + literals.pop_back(); + clause.reserve(3); + clause.push_back(activator); + } else { + clause.reserve(2); + solver.addClause(literals); + } + literals.pop_back(); + clause.push_back(var); + for (int lit : literals) { + clause.push_back(-lit); + solver.addClause(clause); + clause.pop_back(); + } + } + + void RelationSynthesiser::addNonTrivialConstraint() { + for (int i = 0; i < max_size; i++) { + // We do not allow constant gates + solver.addClause(gate_definition_variables[i]); + // We exclude gates representing the projection to one of its inputs + for (int j = 0; j < config.gate_size; j++) { + int start = pow2(config.gate_size - j); + int block_length = pow2(config.gate_size - j - 1); + std::vector clause; + clause.reserve(pow2(config.gate_size) - 1); + for (int k = 0; k < pow2(j); k++) { + for (int l = k * start - (k == 0 ? 0 : 1); l < k * start + block_length -1; l++) { + clause.push_back(gate_definition_variables[i][l]); + } + for (int l = k * start + block_length - 1; l < (k + 1) * start - 1; l++) { + clause.push_back(-gate_definition_variables[i][l]); + } + } + solver.addClause(clause); + } + } + } + + // Every gate is either an output or an input of another gate + void RelationSynthesiser::addUseAllStepsConstraint() { + for (int i = 0; i < max_size; i++) { + std::vector clause (gate_output_variables[i].begin(), gate_output_variables[i].end()); + clause.reserve(max_size - i + 1); + for (int j = i + 1; j < max_size; j++) { + // clause.push_back(selection_variables[j][subcir.inputs.size() + i]); + int isused = getNewVariable(); + // The gate is used by another (active) gate. + solver.addClause({-isused, selection_variables[j][subcir.inputs.size() + i]}); + solver.addClause({-isused, gate_activation_variables[j]}); + clause.push_back(isused); + } + clause.push_back(-gate_activation_variables[i]); + solver.addClause(clause); + } + } + + + // Suppose gate i has inputs i1,...,in and gate j uses i as an input. + // Then the other n-1 inputs of j shall not be contained in the inputs of i. + // Otherwise j could be directly represented by a gate with inputs i1,...,in + void RelationSynthesiser::addNoReapplicationConstraint() { + std::vector filter(config.gate_size, 1); + // A 1 at index i indicates that the ith node is used as an input. + // By using prev_permutation we get all possible permutations of the filter + filter.resize(subcir.inputs.size() + max_size - 1); + std::vector indices(config.gate_size,0); + // int tt_size = RelationSynthesiser::pow2(subcir.inputs.size()) - 1; + do { + indices.clear(); + for (int i = 0; i < subcir.inputs.size() + max_size - 1; i++) { + if (filter[i]) { + indices.push_back(i); + } + } + int first_gate = getPotentialSuccessors(indices); + for (int i = first_gate; i < max_size; i++) { + std::vector clause; + clause.reserve(subcir.inputs.size() + max_size); + for (int idx : indices) { + clause.push_back(-selection_variables[i][idx]); + } + int start_with = clause.size(); + for (int j = i + 1; j < max_size; j++) { + // gate j has inputs.size() + j potential inputs + clause.resize(subcir.inputs.size() + j + 1, 0); + clause[start_with] = -selection_variables[j][subcir.inputs.size() + i]; + clause[start_with + 1] = -gate_activation_variables[j]; + int k = 0, l = 0, m = 0; + // while (k < inputs.size() + j && l < indices.size()) { + while (k < subcir.inputs.size() + j) { + if (l >= indices.size() || k < indices[l]) { + if (k != subcir.inputs.size() + i) { + clause[start_with + m + 2] = selection_variables[j][k]; + m++; + } + k++; + } else if (k > indices[l]) { + l++; + } else { + k++; + l++; + } + } + solver.addClause(clause); + } + } + } while (std::prev_permutation(filter.begin(), filter.end())); + } + + // Order steps according to their inputs. + // If step i has input j then step i+1 must have an input >=j + void RelationSynthesiser::addOrderedStepsConstraint() { + for (int i = 0; i < max_size - 1; i++) { + for (int j = 0; j < subcir.inputs.size() + i; j++) { + std::vector clause {-gate_activation_variables[i+1], -selection_variables[i][j]}; + clause.reserve(subcir.inputs.size() + i - j + 3); + for (int k = j; k < subcir.inputs.size() + i + 1; k++) { + clause.push_back(selection_variables[i+1][k]); + } + solver.addClause(clause); + } + } + } + + +} +ABC_NAMESPACE_IMPL_END diff --git a/src/opt/eslim/relationSynthesiser.hpp b/src/opt/eslim/relationSynthesiser.hpp new file mode 100644 index 0000000000..c1f170c7f1 --- /dev/null +++ b/src/opt/eslim/relationSynthesiser.hpp @@ -0,0 +1,145 @@ +/**CFile**************************************************************** + + FileName [relationSynthesiser.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Base class for SAT-based synthesis] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__OPT__ESLIM__RELATIONSYNTHESISER_hpp +#define ABC__OPT__ESLIM__RELATIONSYNTHESISER_hpp + +#include +#include + +#include "misc/util/abc_global.h" + +#include "relationGeneration.hpp" +#include "subcircuit.hpp" +#include "cadicalSolver.hpp" +#include "utils.hpp" + +ABC_NAMESPACE_CXX_HEADER_START +namespace eSLIM { + + class RelationSynthesiser { + + protected: + CadicalSolver solver; + const Subcircuit& subcir; + unsigned int max_size; // The maximal circuit size that can be checked + + std::vector gate_activation_variables; + std::vector> selection_variables; + std::vector> gate_output_variables; + + RelationSynthesiser(const Relation& relation, const Subcircuit& subcir, unsigned int max_size, const eSLIMConfig& cfg, eSLIMLog& log); + int getNewVariable(); + std::vector getNewVariableVector(unsigned int size); + + std::vector getSizeAssumption(int size); + double getDynamicTimeout(int size); + unsigned int getSizeFromActivationVars(const std::vector& model); + unsigned int getSizeFromActivationVars(); + void logRun(int status, unsigned int size); + eSLIMCirMan getReplacement(const std::vector& model, int size); + + + private: + const Relation& relation; + const eSLIMConfig& config; + eSLIMLog& log; + + int max_var = 0; // The maximal variable occurring in inputs/outputs + + std::vector>> is_ith_fanin_variable; + std::vector> gate_definition_variables; + std::vector> gate_variables; + + + void setupEncoding(); + void setupVariables(); + void setupStructuralConstraints(); + + void setupSymmetryBreaking(); + void setupGateValues(); + std::vector setupFaninVariables(int gtidx, int tt_line, int pidx); + void setupEquivalenceConstraints(); + void setupActivationCompatibilityConstraints(); + void setupIsFaninVariables(int gtidx, const std::vector>& counter_vars); + + void constrainSelectionVariables(); + void constraintGateOutputVariables(); + void addGateValueConstraint(int gtidx, int gt_val, const std::vector& fanin_variables); + void setupCycleConstraints(); + void setupAigerConstraints(); + + int setupOutputVariable(int output_index, int tt_index, int pattern_idx); + + void addNonTrivialConstraint(); + void addUseAllStepsConstraint(); + void addNoReapplicationConstraint(); + void addOrderedStepsConstraint(); + + // activator = 0: do not use an activation variable + void addCardinalityConstraint(const std::vector& vars, unsigned int cardinality, int activator = 0); + std::vector> addSequentialCounter(const std::vector& vars, unsigned int cardinality, int activator = 0); + + void addNaiveIs1CardinalityConstraint(const std::vector& vars); + void addNaiveIs2CardinalityConstraint(const std::vector& vars); + + void defineConjunction(int var, std::vector&& literals, int activator); + void defineDisjunction(int var, std::vector&& literals, int activator); + + // computes the index of the first gate that can used the indexed nodes as inputs + // indices must be ordered + int getPotentialSuccessors(const std::vector& indices) const; + + static bool getTTValue(int tt_line, int var); + static unsigned int pow2(int x); + + }; + + inline int RelationSynthesiser::getNewVariable() { + return ++max_var; + } + + inline std::vector RelationSynthesiser::getNewVariableVector(unsigned int size) { + std::vector vars; + vars.reserve(size); + for (int i = 0; i < size; i++) { + vars.push_back(getNewVariable()); + } + return vars; + } + + inline int RelationSynthesiser::getPotentialSuccessors(const std::vector& indices) const { + if (indices.back() < subcir.inputs.size()) { + return 0; + } + return indices.back() - subcir.inputs.size() + 1; + } + + inline bool RelationSynthesiser::getTTValue(int tt_line, int var) { + return (tt_line >> var) & 1; + } + + inline unsigned int RelationSynthesiser::pow2(int x) { + return 1u << x; + } + +} +ABC_NAMESPACE_CXX_HEADER_END +#endif \ No newline at end of file diff --git a/src/opt/eslim/satInterfaces.hpp b/src/opt/eslim/satInterfaces.hpp deleted file mode 100644 index 3300d9e593..0000000000 --- a/src/opt/eslim/satInterfaces.hpp +++ /dev/null @@ -1,196 +0,0 @@ -/**CFile**************************************************************** - - FileName [satInterfaces.hpp] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] - - Synopsis [Interface to SAT solvers.] - - Author [Franz-Xaver Reichl] - - Affiliation [University of Freiburg] - - Date [Ver. 1.0. Started - March 2025.] - - Revision [$Id: satInterfaces.hpp,v 1.00 2025/03/17 00:00:00 Exp $] - -***********************************************************************/ - -#ifndef ABC__OPT__ESLIM__SATINTERFACE_h -#define ABC__OPT__ESLIM__SATINTERFACE_h - -#include -#include -#include - -#include "misc/util/abc_namespaces.h" -#include "misc/vec/vec.h" -#include "sat/kissat/kissat.h" -#include "sat/cadical/cadical.hpp" - -ABC_NAMESPACE_CXX_HEADER_START - -namespace eSLIM { - - class CadicalSolver { - public: - void addClause(int * pLits, int nLits ); - void assume(const std::vector& assumptions); - int solve(double timeout); - int solve(); - Vec_Int_t* getModelVec(); - double getRunTime() const; - - private: - int val(int variable); - double last_runtime; - CaDiCaL::Solver solver; - - public: - class TimeoutTerminator : public CaDiCaL::Terminator { - public: - TimeoutTerminator(double max_runtime); - bool terminate(); - - private: - double max_runtime; //in seconds - std::chrono::time_point start = std::chrono::steady_clock::now(); - }; - }; - - class KissatSolver { - public: - KissatSolver(); - ~KissatSolver(); - void init(int max_var); - void addClause(int * pLits, int nLits ); - int solve(); - // int solve(int timeout); - Vec_Int_t* getModelVec(); - - private: - - int max_var = 0; - int val(int variable); - kissat * solver = nullptr; - }; - - inline CadicalSolver::TimeoutTerminator::TimeoutTerminator(double max_runtime) : max_runtime(max_runtime) {} - - inline bool CadicalSolver::TimeoutTerminator::terminate() { - auto current_time = std::chrono::steady_clock::now(); - std::chrono::duration elapsed_seconds = current_time - start; - return elapsed_seconds.count() > max_runtime; - } - - inline double CadicalSolver::getRunTime() const { - return last_runtime; - } - - inline void CadicalSolver::addClause(int * pLits, int nLits ) { - for ( int i = 0; i < nLits; i++ ) { - if (pLits[i] == 0) { - continue;; - } - solver.add(Abc_LitIsCompl(pLits[i]) ? -Abc_Lit2Var(pLits[i]) : Abc_Lit2Var(pLits[i])); - } - solver.add(0); - } - - inline void CadicalSolver::assume(const std::vector& assumptions) { - for (auto& l: assumptions) { - solver.assume(l); - } - } - - inline int CadicalSolver::solve() { - std::chrono::time_point start = std::chrono::steady_clock::now(); - int status = solver.solve(); - last_runtime = std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count(); - return status; - } - - inline int CadicalSolver::solve(double timeout) { - std::chrono::time_point start = std::chrono::steady_clock::now(); - TimeoutTerminator terminator(timeout); - solver.connect_terminator(&terminator); - int status = solver.solve(); - last_runtime = std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count(); - if (solver.state() == CaDiCaL::INVALID) { - std::cerr<<"Solver is in invalid state"< 0 ); - } - return assignment; - } - - inline int CadicalSolver::val(int variable) { - auto l = solver.val(variable); - auto v = abs(l); - if (v == variable) { - return l; - } else { - return variable; - } - } - - inline KissatSolver::KissatSolver() { - solver = kissat_init(); - } - - inline KissatSolver::~KissatSolver() { - kissat_release(solver); - } - - inline void KissatSolver::init(int max_var) { - this->max_var = max_var; - kissat_reserve(solver, max_var); - } - - inline void KissatSolver::addClause(int * pLits, int nLits ) { - for ( int i = 0; i < nLits; i++ ) { - if (pLits[i] == 0) { - continue; - } - kissat_add (solver, Abc_LitIsCompl(pLits[i]) ? -Abc_Lit2Var(pLits[i]) : Abc_Lit2Var(pLits[i])); - } - kissat_add (solver, 0); - } - - inline int KissatSolver::solve() { - int status = kissat_solve(solver); - return status; - } - - inline int KissatSolver::val(int variable) { - int l = kissat_value (solver, variable); - auto v = abs(l); - if (v == variable) { - return l; - } else { - return variable; - } - } - - inline Vec_Int_t* KissatSolver::getModelVec() { - Vec_Int_t* assignment = Vec_IntAlloc( max_var ); - for (int v = 1; v <= max_var; v++) { - Vec_IntSetEntryFull( assignment, Abc_AbsInt(val(v)), val(v) > 0 ); - } - return assignment; - } -} - -ABC_NAMESPACE_CXX_HEADER_END - -#endif \ No newline at end of file diff --git a/src/opt/eslim/selectionStrategies.hpp b/src/opt/eslim/selectionStrategies.hpp new file mode 100644 index 0000000000..105ef3be1b --- /dev/null +++ b/src/opt/eslim/selectionStrategies.hpp @@ -0,0 +1,181 @@ +/**CFile**************************************************************** + + FileName [selectionStrategies.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Subcircuit selection] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__OPT__ESLIM__SELECTIONSTRATEGIES_hpp +#define ABC__OPT__ESLIM__SELECTIONSTRATEGIES_hpp + +#include +#include +#include + +#include "misc/util/abc_namespaces.h" + +#include "eslimCirMan.hpp" +#include "subcircuit.hpp" +#include "utils.hpp" +#include "tabooList.hpp" + +ABC_NAMESPACE_CXX_HEADER_START +namespace eSLIM { + + struct SubcircuitValidator { + public: + SubcircuitValidator(const eSLIMConfig& cf); + bool check(const Subcircuit& candidate) const; + + private: + const eSLIMConfig& cfg; + static constexpr unsigned int min_size = 2; + static constexpr unsigned int max_ninputs = 10; + + }; + + struct SubcircuitNoFBValidator : public SubcircuitValidator { + public: + using SubcircuitValidator::SubcircuitValidator; + bool check(const Subcircuit& candidate) const; + }; + + class ForwardSearch { + public: + ForwardSearch(eSLIMCirMan& es_man); + auto getNextBegin(const eSLIMCirObj& obj); + auto getNextEnd(const eSLIMCirObj& obj); + bool check(const eSLIMCirObj& obj) const; + private: + eSLIMCirMan& es_man; + }; + + class BackwardSearch { + public: + BackwardSearch(eSLIMCirMan& es_man); + auto getNextBegin(const eSLIMCirObj& obj); + auto getNextEnd(const eSLIMCirObj& obj); + bool check(const eSLIMCirObj& obj) const; + private: + eSLIMCirMan& es_man; + }; + + class BaseRootSelector { + public: + BaseRootSelector(eSLIMCirMan& es_man, const eSLIMConfig& cfg); + int getRoot(std::mt19937& rng); + void reset() {} + + private: + unsigned int getUniformRandomNumber(std::mt19937& rng, unsigned int lower, unsigned int upper); // requires lower < upper + + eSLIMCirMan& es_man; + // const eSLIMConfig& cfg; + std::uniform_int_distribution udistr; + }; + + class TabooRootSelector { + public: + TabooRootSelector(eSLIMCirMan& es_man, const eSLIMConfig& cfg); + ~TabooRootSelector(); + int getRoot(std::mt19937& rng); + void reset(); + + private: + eSLIMCirMan& es_man; + + + protected: + const eSLIMConfig& cfg; + TabooList taboo; + + }; + + class CriticalPathSelector : public TabooRootSelector { + public: + using TabooRootSelector::TabooRootSelector; + int getRoot(std::mt19937& rng); + }; + + struct BaseCandidateNodeConstraint { + static bool check(int to_check, const eSLIMCirMan& cir, const std::set& subcircuit); + }; + + struct SingleOutputCandidateNodeConstraint { + static bool check(int to_check, const eSLIMCirMan& cir, const std::set& subcircuit); + }; + + struct NoBiasSelector { + static bool useBias(const eSLIMCirMan& es_man, const eSLIMCirObj& obj) {return false;} + }; + + struct CriticalPathBiasSelector { + static bool useBias(const eSLIMCirMan& es_man, const eSLIMCirObj& obj) {return es_man.isOnCricticalPath(obj);} + }; + + template + class RandomizedBFSSelection { + + public: + RandomizedBFSSelection(eSLIMCirMan& es_man, const eSLIMConfig& cfg, eSLIMLog& log); + Subcircuit getSubcircuit(bool& status); // status indicates if the search was successful + void setSeed(int seed); + void reset(); + + static constexpr bool requiresRemainingTimes() {return std::is_same_v;} + + private: + + std::set computeSubcircuitCandidate(); + int selectRoot(); + void processCandidateNode(int candidate, std::set& subcircuit, std::queue& candidates); + bool getRandomBool(); + bool getBiasedRandomBool(); + + eSLIMCirMan& es_man; + const eSLIMConfig& cfg; + static constexpr unsigned int min_size = 2; + static constexpr unsigned int max_ninputs = 10; + + eSLIMLog& log; + Validator validator; + RootSelector root_selector; + SearchDirection search_direction; + + std::mt19937 rng; + std::bernoulli_distribution bdist; + std::bernoulli_distribution biased_bdist; + }; + + + + using RamdomizedBFS=RandomizedBFSSelection; + using RamdomizedBFSForward=RandomizedBFSSelection; + using RandomizedBFSNoFB=RandomizedBFSSelection; + using RamdomizedBFSTaboo=RandomizedBFSSelection; + using RamdomizedBFSTabooForward=RandomizedBFSSelection; + using RamdomizedBFSTabooNoFB=RandomizedBFSSelection; + + using SingleOutputBFS = RandomizedBFSSelection; + + +} +ABC_NAMESPACE_CXX_HEADER_END + + +#include "selectionStrategies.tpp" + +#endif \ No newline at end of file diff --git a/src/opt/eslim/selectionStrategies.tpp b/src/opt/eslim/selectionStrategies.tpp new file mode 100644 index 0000000000..085b6126ef --- /dev/null +++ b/src/opt/eslim/selectionStrategies.tpp @@ -0,0 +1,226 @@ +/**CFile**************************************************************** + + FileName [selectionStrategies.tpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Subcircuit selection] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#include "selectionStrategies.hpp" + +ABC_NAMESPACE_CXX_HEADER_START +namespace eSLIM { + + inline SubcircuitValidator::SubcircuitValidator(const eSLIMConfig& cfg) : cfg(cfg) { + + } + + inline bool SubcircuitValidator::check(const Subcircuit& candidate) const { + return candidate.inputs.size() <= max_ninputs && candidate.inputs.size() >= cfg.gate_size; + } + + inline bool SubcircuitNoFBValidator::check(const Subcircuit& candidate) const { + return SubcircuitValidator::check(candidate) && candidate.forbidden_pairs.empty(); + } + + inline ForwardSearch::ForwardSearch(eSLIMCirMan& es_man) : es_man(es_man) { + } + + inline auto ForwardSearch::getNextBegin(const eSLIMCirObj& obj) { + return obj.fanouts.begin(); + } + + inline auto ForwardSearch::getNextEnd(const eSLIMCirObj& obj) { + return obj.fanouts.end(); + } + + inline bool ForwardSearch::check(const eSLIMCirObj& obj) const { + return !es_man.isPo(obj.node_id); + } + + inline BackwardSearch::BackwardSearch(eSLIMCirMan& es_man) : es_man(es_man) { + } + + inline auto BackwardSearch::getNextBegin(const eSLIMCirObj& obj) { + return obj.fanins.begin(); + } + + inline auto BackwardSearch::getNextEnd(const eSLIMCirObj& obj) { + return obj.fanins.end(); + } + + inline bool BackwardSearch::check(const eSLIMCirObj& obj) const { + return !es_man.isPi(obj.node_id); + } + + // inline BaseRootSelector::BaseRootSelector(eSLIMCirMan& es_man, const eSLIMConfig& cfg) : es_man(es_man), cfg(cfg) { + inline BaseRootSelector::BaseRootSelector(eSLIMCirMan& es_man, const eSLIMConfig& cfg) : es_man(es_man) { + + } + + inline TabooRootSelector::TabooRootSelector(eSLIMCirMan& es_man, const eSLIMConfig& cfg) : es_man(es_man), cfg(cfg), taboo(es_man) { + es_man.registerTabooList(&taboo); + } + + inline TabooRootSelector::~TabooRootSelector() { + es_man.unregisterTabooList(); + } + + + inline unsigned int BaseRootSelector::getUniformRandomNumber(std::mt19937& rng, unsigned int lower, unsigned int upper) { + udistr.param(std::uniform_int_distribution::param_type(lower, upper)); + return udistr(rng); + } + + inline int BaseRootSelector::getRoot(std::mt19937& rng) { + int min_id = es_man.getNofPis() + 1; + int max_id = es_man.getNofObjs() - es_man.getNofPos() - 1; + return getUniformRandomNumber(rng, min_id, max_id); + } + + + inline int TabooRootSelector::getRoot(std::mt19937& rng) { + return taboo.getRandomNonTaboo(rng, cfg.taboo_ratio, cfg.taboo_time); + } + + inline void TabooRootSelector::reset() { + taboo.reset(); + es_man.registerTabooList(&taboo); + } + + inline int CriticalPathSelector::getRoot(std::mt19937& rng) { + return taboo.getBiasedRandomNonTaboo(rng, cfg.bias, cfg.taboo_ratio, cfg.taboo_time); + } + + inline bool BaseCandidateNodeConstraint::check(int to_check, const eSLIMCirMan& cir, const std::set& subcircuit) { + return subcircuit.find(to_check) == subcircuit.end(); + } + + inline bool SingleOutputCandidateNodeConstraint::check(int to_check, const eSLIMCirMan& cir, const std::set& subcircuit) { + if (subcircuit.find(to_check) != subcircuit.end()) { + return false; + } + const auto& obj = cir.getObj(to_check); + for (const auto& fo : obj.fanouts) { + // The node has a fanout that is not yet in the subcircuit + if (subcircuit.find(fo->node_id) == subcircuit.end()) { + return false; + } + } + return true; + } + + template + RandomizedBFSSelection::RandomizedBFSSelection(eSLIMCirMan& es_man, const eSLIMConfig& cfg, eSLIMLog& log) + : es_man(es_man), cfg(cfg), log(log), validator(cfg), root_selector(es_man, cfg), search_direction(es_man), + bdist(cfg.expansion_probability), biased_bdist(std::min(1., cfg.expansion_probability*1.5)) { + } + + template + void RandomizedBFSSelection::setSeed(int seed) { + rng.seed(seed); + } + + template + bool RandomizedBFSSelection::getRandomBool() { + return bdist(rng); + } + + template + bool RandomizedBFSSelection::getBiasedRandomBool() { + return biased_bdist(rng); + } + + template + int RandomizedBFSSelection::selectRoot() { + return root_selector.getRoot(rng); + } + + template + void RandomizedBFSSelection::reset() { + root_selector.reset(); + } + + template + std::set RandomizedBFSSelection::computeSubcircuitCandidate() { + std::set scir; + int root_id = selectRoot(); + std::queue candidates; + processCandidateNode(root_id, scir, candidates); + std::queue rejected_nodes; + while (!candidates.empty() && scir.size() < cfg.subcircuit_max_size) { + int c = candidates.front(); + candidates.pop(); + if (CandidateNodeConstraint::check(c, es_man, scir)) { + bool add_node; + if (BiasSelector::useBias(es_man, es_man.getObj(c))) { + add_node = getBiasedRandomBool(); + } else { + add_node = getRandomBool(); + } + if (add_node) { + processCandidateNode(c, scir, candidates); + } else { + rejected_nodes.push(c); + } + } + } + if (this->cfg.fill_subcircuits) { + while (!rejected_nodes.empty() && scir.size() < cfg.subcircuit_max_size) { + int c = rejected_nodes.front(); + rejected_nodes.pop(); + if (CandidateNodeConstraint::check(c, es_man, scir)) { + processCandidateNode(c, scir, rejected_nodes); + } + } + } + return scir; + } + + template + void RandomizedBFSSelection::processCandidateNode(int node, std::set& subcircuit, std::queue& candidates) { + subcircuit.insert(node); + auto& obj = es_man.getObj(node); + for (auto it = search_direction.getNextBegin(obj); it != search_direction.getNextEnd(obj); it++) { + const auto& f = *it; + if (search_direction.check(*f)) { + candidates.push(f->node_id); + } + } + } + + template + Subcircuit RandomizedBFSSelection::getSubcircuit(bool& status) { + std::set scir; + status = false; + for (int i = 1; i < cfg.nselection_trials; i++) { + scir = computeSubcircuitCandidate(); + if (scir.size() < min_size) { + scir.clear(); + continue; + } + es_man.incrementTraversalId(); + Subcircuit candidate = Subcircuit::getSubcircuit(es_man, scir); + if (validator.check(candidate)) { + status = true; + return candidate; + } + } + return Subcircuit::getEmptySubcircuit(); + } + + +} +ABC_NAMESPACE_CXX_HEADER_END \ No newline at end of file diff --git a/src/opt/eslim/selectionStrategy.hpp b/src/opt/eslim/selectionStrategy.hpp deleted file mode 100644 index 29650a5d78..0000000000 --- a/src/opt/eslim/selectionStrategy.hpp +++ /dev/null @@ -1,154 +0,0 @@ -/**CFile**************************************************************** - - FileName [selectionStrategy.hpp] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] - - Synopsis [Procedures for selecting subcircuits.] - - Author [Franz-Xaver Reichl] - - Affiliation [University of Freiburg] - - Date [Ver. 1.0. Started - March 2025.] - - Revision [$Id: selectionStrategy.hpp,v 1.00 2025/03/17 00:00:00 Exp $] - -***********************************************************************/ - -#ifndef ABC__OPT__ESLIM__SELECTIONSTRATEGY_h -#define ABC__OPT__ESLIM__SELECTIONSTRATEGY_h - -#include -#include - -#include "misc/util/abc_namespaces.h" -#include "misc/vec/vec.h" -#include "aig/gia/gia.h" - -#include "utils.hpp" - -ABC_NAMESPACE_CXX_HEADER_START - -namespace eSLIM { - - template - class SelectionStrategy { - public: - Subcircuit getSubcircuit(); - bool getStatus() {return status;}; - void setSeed(int seed); - - protected: - SelectionStrategy(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log); - unsigned int getUniformRandomNumber(unsigned int lower, unsigned int upper); // requires lower < upper - bool getRandomBool(); - int getSubcircuitIO(Vec_Int_t* subcircuit, Vec_Int_t* io); - // The resulting map assigns inputs of the subcircuit to outputs of the subcircuit s.t. each associated input is reachable from the output - std::unordered_map> computeForbiddenPairs(const Subcircuit& subcir); - - Gia_Man_t*& gia_man; - const eSLIMConfig& cfg; - eSLIMLog& log; - - private: - - bool filterSubcircuit(const Subcircuit& subcir); - void forbiddenPairsRec(Gia_Obj_t * pObj, int input, int min_level, std::unordered_map>& pairs, const std::unordered_map& out_ids ); - - bool status = true; //set to false if selection fails too often - static constexpr unsigned int min_size = 2; - - std::mt19937 rng; - std::bernoulli_distribution bdist; - std::uniform_int_distribution udistr; - - }; - - template - class randomizedBFS : public SelectionStrategy { - private: - randomizedBFS(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log); - Subcircuit findSubcircuit(); - int selectRoot(); - void checkCandidate(Subcircuit& subcircuit, std::queue& candidate, std::queue& rejected, bool add); - const int nPis; - const int nPos; - friend SelectionStrategy; - friend T; - }; - - class randomizedBFSFP : public randomizedBFS { - public : - randomizedBFSFP(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log); - private: - Subcircuit getSubcircuitImpl(); - bool filterSubcircuitImpl(const Subcircuit& subcir); - - friend SelectionStrategy; - }; - - class randomizedBFSnoFP : public randomizedBFS { - public: - randomizedBFSnoFP(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log); - private: - Subcircuit getSubcircuitImpl() {return findSubcircuit();}; - bool filterSubcircuitImpl(const Subcircuit& subcir); - bool filterSubcircuitRec(Gia_Obj_t * pObj, unsigned int min_level); - - friend SelectionStrategy; - }; - - - template - SelectionStrategy::SelectionStrategy(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log) - : gia_man(gia_man), cfg(cfg), log(log), rng(std::random_device()()), bdist(cfg.expansion_probability) { - } - - template - void SelectionStrategy::setSeed(int seed) { - rng.seed(seed); - } - - template - unsigned int SelectionStrategy::getUniformRandomNumber(unsigned int lower, unsigned int upper) { - udistr.param(std::uniform_int_distribution::param_type(lower, upper)); - return udistr(rng); - } - - template - bool SelectionStrategy::getRandomBool() { - return bdist(rng); - } - - template - randomizedBFS::randomizedBFS(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log) - : SelectionStrategy(gia_man, cfg, log), nPis(Gia_ManPiNum(gia_man)), nPos(Gia_ManPoNum(gia_man)) { - } - - inline randomizedBFSFP::randomizedBFSFP(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log) - : randomizedBFS(gia_man, cfg, log){ - } - - inline Subcircuit randomizedBFSFP::getSubcircuitImpl() { - Subcircuit subcir = findSubcircuit(); - subcir.forbidden_pairs = computeForbiddenPairs(subcir); - return subcir; - } - - inline randomizedBFSnoFP::randomizedBFSnoFP(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log) - : randomizedBFS(gia_man, cfg, log) { - } - - inline bool randomizedBFSFP::filterSubcircuitImpl(const Subcircuit& subcir) { - return true; - } -} - -ABC_NAMESPACE_CXX_HEADER_END - -#include "selectionStrategy.tpp" - -#endif \ No newline at end of file diff --git a/src/opt/eslim/selectionStrategy.tpp b/src/opt/eslim/selectionStrategy.tpp deleted file mode 100644 index 94f656a5b3..0000000000 --- a/src/opt/eslim/selectionStrategy.tpp +++ /dev/null @@ -1,233 +0,0 @@ -/**CFile**************************************************************** - - FileName [selectionStrategy.tpp] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] - - Synopsis [Procedures for selecting subcircuits.] - - Author [Franz-Xaver Reichl] - - Affiliation [University of Freiburg] - - Date [Ver. 1.0. Started - March 2025.] - - Revision [$Id: selectionStrategy.tpp,v 1.00 2025/03/17 00:00:00 Exp $] - -***********************************************************************/ - -#include - -#include "misc/util/abc_namespaces.h" - -#include "selectionStrategy.hpp" - -ABC_NAMESPACE_CXX_HEADER_START - -namespace eSLIM { - - template - Subcircuit SelectionStrategy::getSubcircuit() { - for (int i = 0; i < cfg.nselection_trials; i++) { - Subcircuit subcir = static_cast(this)->getSubcircuitImpl(); - if (filterSubcircuit(subcir)) { - return subcir; - } else { - subcir.free(); - } - } - status = false; - Subcircuit empty_subcir; - return empty_subcir; - } - - template - bool SelectionStrategy::filterSubcircuit(const Subcircuit& subcir) { - // if (subcir.nof_inputs > 8) { - if (subcir.nof_inputs > 10) { - return false; - } - // ABC internally requires that the subcircuit has not more than 6 outputs (e.g. generateMinterm) - if (Vec_IntSize(subcir.io)-subcir.nof_inputs > 6) { - return false; - } - if (Vec_IntSize(subcir.nodes) < min_size) { - return false; - } - return static_cast(this)->filterSubcircuitImpl(subcir); - } - - template - int SelectionStrategy::getSubcircuitIO(Vec_Int_t* subcircuit, Vec_Int_t* io) { - assert(Vec_IntSize(io) == 0); - Gia_ManIncrementTravId(gia_man); - Gia_Obj_t * pObj; - int i; - Gia_ManForEachObjVec( subcircuit, gia_man, pObj, i ) { - Gia_ObjSetTravIdCurrent(gia_man, pObj); - } - Gia_ManIncrementTravId(gia_man); - - // inputs - Gia_ManForEachObjVec( subcircuit, gia_man, pObj, i ) { - // fanin0 is not in the subcircuit and was not considered yet - if (!Gia_ObjIsTravIdPrevious(gia_man, Gia_ObjFanin0(pObj)) && !Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin0(pObj))) { - Gia_ObjSetTravIdCurrent(gia_man, Gia_ObjFanin0(pObj)); - Vec_IntPush(io, Gia_ObjId(gia_man, Gia_ObjFanin0(pObj))); - } - // fanin1 is not in the subcircuit and was not considered yet - if (!Gia_ObjIsTravIdPrevious(gia_man, Gia_ObjFanin1(pObj)) && !Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin1(pObj))) { - Gia_ObjSetTravIdCurrent(gia_man, Gia_ObjFanin1(pObj)); - Vec_IntPush(io, Gia_ObjId(gia_man, Gia_ObjFanin1(pObj))); - } - } - int nof_inputs = Vec_IntSize(io); - - // outputs - Gia_ManForEachAnd( gia_man, pObj, i ) { - // If there is an object that is not contained in the subcircuit that has a fanin in the subcircuit then this fanin is an output - if (!Gia_ObjIsTravIdPrevious(gia_man, pObj)) { - if (Gia_ObjIsTravIdPrevious(gia_man, Gia_ObjFanin0(pObj))) { - Gia_ObjSetTravIdCurrent(gia_man, Gia_ObjFanin0(pObj)); - Vec_IntPush(io, Gia_ObjId(gia_man, Gia_ObjFanin0(pObj))); - } - if (Gia_ObjIsTravIdPrevious(gia_man, Gia_ObjFanin1(pObj))) { - Gia_ObjSetTravIdCurrent(gia_man, Gia_ObjFanin1(pObj)); - Vec_IntPush(io, Gia_ObjId(gia_man, Gia_ObjFanin1(pObj))); - } - } - } - - Gia_ManForEachPo( gia_man, pObj, i ) { - if (Gia_ObjIsTravIdPrevious(gia_man, Gia_ObjFanin0(pObj))) { - Gia_ObjSetTravIdCurrent(gia_man, Gia_ObjFanin0(pObj)); - Vec_IntPush(io, Gia_ObjId(gia_man, Gia_ObjFanin0(pObj))); - } - } - return nof_inputs; - } - - template - std::unordered_map> SelectionStrategy::computeForbiddenPairs(const Subcircuit& subcir) { - Gia_Obj_t * pObj; - int i; - unsigned int min_output_level = Gia_ManLevelNum(gia_man); - Gia_ManIncrementTravId(gia_man); - std::unordered_map out_id; - Gia_ManForEachObjVecStart(subcir.io, gia_man, pObj, i, subcir.nof_inputs) { - min_output_level = Gia_ObjLevel(gia_man, pObj) < min_output_level ? Gia_ObjLevel(gia_man, pObj) : min_output_level; - Gia_ObjSetTravIdCurrent(gia_man, pObj); - auto id = Gia_ObjId(gia_man, pObj); - out_id[id] = i - subcir.nof_inputs; - } - std::unordered_map> forbidden_pairs; - Gia_ManForEachObjVecStop(subcir.io, gia_man, pObj, i, subcir.nof_inputs) { - forbiddenPairsRec(pObj, i, min_output_level, forbidden_pairs, out_id); - } - return forbidden_pairs; - } - - template - void SelectionStrategy::forbiddenPairsRec(Gia_Obj_t * pObj, int input, int min_level, std::unordered_map>& pairs, const std::unordered_map& out_id) { - if (Gia_ObjIsTravIdCurrent(gia_man, pObj)) { - auto id = Gia_ObjId(gia_man, pObj); - pairs[out_id.at(id)].insert(input); - return; - } - if (Gia_ObjLevel(gia_man, pObj) < min_level) { - return; - } - forbiddenPairsRec(Gia_ObjFanin0(pObj), input, min_level, pairs, out_id); - forbiddenPairsRec(Gia_ObjFanin1(pObj), input, min_level, pairs, out_id); - } - - template - int randomizedBFS::selectRoot() { - int nof_objs = Gia_ManObjNum(this->gia_man); - int root_id = this->getUniformRandomNumber(this->nPis + 1, nof_objs - this->nPos - 1); - return root_id; - } - - template - void randomizedBFS::checkCandidate(Subcircuit& subcircuit, std::queue& candidates, std::queue& rejected, bool add) { - int obj_id = candidates.front(); - candidates.pop(); - Gia_Obj_t * gia_obj = Gia_ManObj(this->gia_man, obj_id); - if (Gia_ObjIsAnd(gia_obj) && !Gia_ObjIsTravIdCurrent(this->gia_man, gia_obj)) { - if (add) { - Gia_ObjSetTravIdCurrent(this->gia_man, gia_obj); - Vec_IntPush(subcircuit.nodes, obj_id); - candidates.push(Gia_ObjFaninId0(gia_obj, obj_id)); - candidates.push(Gia_ObjFaninId1(gia_obj, obj_id)); - } else { - rejected.push(obj_id); - } - } - } - - template - Subcircuit randomizedBFS::findSubcircuit() { - Subcircuit result; - assert (Gia_ManIsNormalized(this->gia_man)); - int root_id = selectRoot(); - Gia_Obj_t * gia_obj = Gia_ManObj(this->gia_man, root_id); - assert (Gia_ObjIsAnd(gia_obj)); - result.nodes = Vec_IntAlloc(this->cfg.subcircuit_size_bound); - result.io = Vec_IntAlloc(this->cfg.subcircuit_size_bound); - - Vec_IntPush(result.nodes, root_id); - - std::queue candidates; - candidates.push(Gia_ObjFaninId0(gia_obj, root_id)); - candidates.push(Gia_ObjFaninId1(gia_obj, root_id)); - std::queue rejected_nodes; - - Gia_ManIncrementTravId(this->gia_man); - - while (!candidates.empty() && Vec_IntSize(result.nodes) < this->cfg.subcircuit_size_bound) { - checkCandidate(result, candidates, rejected_nodes, this->getRandomBool()); - } - - if (this->cfg.fill_subcircuits) { - while (!rejected_nodes.empty() && Vec_IntSize(result.nodes) < this->cfg.subcircuit_size_bound) { - checkCandidate(result, rejected_nodes, rejected_nodes, true); - } - } - result.nof_inputs = this->getSubcircuitIO(result.nodes, result.io); - return result; - } - - inline bool randomizedBFSnoFP::filterSubcircuitImpl(const Subcircuit& subcir) { - Gia_Obj_t * pObj; - int i; - unsigned int min_output_level = Gia_ManLevelNum(gia_man); - Gia_ManIncrementTravId(gia_man); - Gia_ManForEachObjVecStart(subcir.io, gia_man, pObj, i, subcir.nof_inputs) { - min_output_level = Gia_ObjLevel(gia_man, pObj) < min_output_level ? Gia_ObjLevel(gia_man, pObj) : min_output_level; - Gia_ObjSetTravIdCurrent(gia_man, pObj); - } - Gia_ManIncrementTravId(gia_man); - Gia_ManForEachObjVecStop(subcir.io, gia_man, pObj, i, subcir.nof_inputs) { - if (!filterSubcircuitRec(pObj, min_output_level)) { - return false; - } - } - return true; - } - - inline bool randomizedBFSnoFP::filterSubcircuitRec(Gia_Obj_t * pObj, unsigned int min_level) { - if (Gia_ObjIsTravIdPrevious(gia_man, pObj)) { - return false; - } else if (Gia_ObjIsTravIdCurrent(gia_man, pObj)) { - return true; - } else if (Gia_ObjLevel(gia_man, pObj) < min_level) { - return true; - } - Gia_ObjSetTravIdCurrent(gia_man, pObj); - return filterSubcircuitRec(Gia_ObjFanin0(pObj), min_level) && filterSubcircuitRec(Gia_ObjFanin1(pObj), min_level); - } -} - -ABC_NAMESPACE_CXX_HEADER_END \ No newline at end of file diff --git a/src/opt/eslim/subcircuit.cpp b/src/opt/eslim/subcircuit.cpp new file mode 100644 index 0000000000..83f639681c --- /dev/null +++ b/src/opt/eslim/subcircuit.cpp @@ -0,0 +1,132 @@ +/**CFile**************************************************************** + + FileName [subcircuit.cpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Subcircuit representation] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#include +#include +#include + +#include "subcircuit.hpp" + + +ABC_NAMESPACE_IMPL_START +namespace eSLIM { + + Subcircuit Subcircuit::getSubcircuit(eSLIMCirMan& es_man, const std::set& nodes) { + Subcircuit scir = getSubcircuitBare(es_man, nodes.begin(), nodes.end()); + es_man.markCones(scir.nodes); + scir.setForbiddenPairs(es_man); + return scir; + } + + Subcircuit Subcircuit::getEmptySubcircuit() { + Subcircuit scir; + return scir; + } + + + + void Subcircuit::setIO(eSLIMCirMan& es_man) { + std::set input_set; + std::set output_set; + for (int n : nodes) { + const auto& obj = es_man.getObj(n); + for (const auto& f : obj.fanins) { + if (!es_man.inSubcircuit(*f) && !es_man.isConst(*f)) { + input_set.insert(f->node_id); + } + } + for (const auto& f : obj.fanouts) { + if (!es_man.inSubcircuit(*f)) { + output_set.insert(obj.node_id); + } + } + } + inputs.insert(inputs.end(), input_set.begin(), input_set.end()); + outputs.insert(outputs.end(), output_set.begin(), output_set.end()); + } + + void Subcircuit::setForbiddenPairs(const eSLIMCirMan& es_man) { + std::unordered_set seen; + for (int inp : inputs) { + getForbiddenPairsRec(inp, seen, es_man.getObj(inp), es_man); + seen.clear(); + } + } + + void Subcircuit::getForbiddenPairsRec(int inp, std::unordered_set& seen, const eSLIMCirObj& obj, const eSLIMCirMan& es_man) { + if (seen.find(obj.node_id) != seen.end()) { + return; + } + seen.insert(obj.node_id); + for (const auto& f : obj.fanins) { + if (es_man.inSubcircuit(*f)) { + forbidden_pairs[f->node_id].emplace(inp); + } else if (es_man.inTFI(*f) && es_man.inTFO(*f)) { + getForbiddenPairsRec(inp, seen, *f, es_man); + } + } + } + + int Subcircuit::setupTimings(eSLIMCirMan& es_man) { + // es_man.setupTimings(); + for (int in : inputs) { + arrival_times.push_back(es_man.getObj(in).depth); + } + int max_crossing_path = 0; + for (int out : outputs) { + remaining_times.push_back(es_man.getObj(out).remaining_time); + max_crossing_path = std::max(max_crossing_path, es_man.getObj(out).remaining_time + es_man.getObj(out).depth); + } + return max_crossing_path; + } + + void Subcircuit::print() const { + std::cout << "Inputs:"; + for (int i : inputs) { + std::cout << " " << i; + } + std::cout << "\nOutputs:"; + for (int o : outputs) { + std::cout << " " << o; + } + std::cout << "\nArrival times:"; + for (int ar : arrival_times) { + std::cout << " " << ar; + } + std::cout << "\nRemaining times:"; + for (int re : remaining_times) { + std::cout << " " << re; + } + std::cout << "\nNodes:"; + for (int n : nodes) { + std::cout << " " << n; + } + std::cout << "\nForbidden pairs:"; + for (const auto & [out,inps] : forbidden_pairs) { + std::cout << "\n" << out << " :"; + for (int inp : inps) { + std::cout << " " << inp; + } + } + std::cout << "\n"; + } + +} +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/opt/eslim/subcircuit.hpp b/src/opt/eslim/subcircuit.hpp new file mode 100644 index 0000000000..e22640c2a8 --- /dev/null +++ b/src/opt/eslim/subcircuit.hpp @@ -0,0 +1,80 @@ +/**CFile**************************************************************** + + FileName [subcircuit.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Subcircuit representation] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__OPT__ESLIM__SUBCIRCUIT_hpp +#define ABC__OPT__ESLIM__SUBCIRCUIT_hpp + +#include +#include +#include +#include + +#include "misc/util/abc_namespaces.h" + +#include "eslimCirMan.hpp" + +ABC_NAMESPACE_CXX_HEADER_START +namespace eSLIM { + + class Subcircuit { + + public: + template + static Subcircuit getSubcircuitBare(eSLIMCirMan& es_man, It begin, It end); + static Subcircuit getSubcircuit(eSLIMCirMan& es_man, const std::set& nodes); + static Subcircuit getEmptySubcircuit(); + + int setupTimings(eSLIMCirMan& es_man); + + std::vector nodes; + std::vector inputs; + std::vector outputs; + // Assigns the inputs of the subcircuit that can be reached from an output x to x. + std::unordered_map> forbidden_pairs; + + std::vector arrival_times; + std::vector remaining_times; + + void print() const; + + private: + template + Subcircuit(eSLIMCirMan& es_man, It begin, It end); + Subcircuit() = default; + void setIO(eSLIMCirMan& es_man); + void setForbiddenPairs(const eSLIMCirMan& es_man); + void getForbiddenPairsRec(int inp, std::unordered_set& seen, const eSLIMCirObj& obj, const eSLIMCirMan& es_man); + }; + + template + Subcircuit::Subcircuit(eSLIMCirMan& es_man, It begin, It end) : nodes(begin, end) { + es_man.markSubcircuit(this->nodes); + setIO(es_man); + } + + template + Subcircuit Subcircuit::getSubcircuitBare(eSLIMCirMan& es_man, It begin, It end) { + Subcircuit scir(es_man, begin, end); + return scir; + } + +} +ABC_NAMESPACE_CXX_HEADER_END +#endif \ No newline at end of file diff --git a/src/opt/eslim/synthesisEngine.hpp b/src/opt/eslim/synthesisEngine.hpp deleted file mode 100644 index d061e761ba..0000000000 --- a/src/opt/eslim/synthesisEngine.hpp +++ /dev/null @@ -1,240 +0,0 @@ -/**CFile**************************************************************** - - FileName [synthesisEngine.hpp] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] - - Synopsis [Procedures for synthesising Boolean relations.] - - Author [Franz-Xaver Reichl] - - Affiliation [University of Freiburg] - - Date [Ver. 1.0. Started - March 2025.] - - Revision [$Id: synthesisEngine.hpp,v 1.00 2025/03/17 00:00:00 Exp $] - -***********************************************************************/ - -#ifndef ABC__OPT__ESLIM__SYNTHESISENGINE_h -#define ABC__OPT__ESLIM__SYNTHESISENGINE_h - -#include -#include -#include -#include - -#include "misc/util/abc_namespaces.h" -#include "aig/miniaig/miniaig.h" -#include "misc/vec/vec.h" - -#include "satInterfaces.hpp" - -ABC_NAMESPACE_CXX_HEADER_START - -#define MAJ_NOBJS 64 // Const0 + Const1 + nVars + nNodes - -namespace eSLIM { - - // Based on Exa6_ManGenStart - template - class exactSynthesisEngine { - - private: - Vec_Wrd_t * vSimsIn; // input signatures (nWords = 1, nIns <= 64) - Vec_Wrd_t * vSimsOut; // output signatures (nWords = 1, nOuts <= 6) - int nIns; - int nDivs; // divisors (const + inputs + tfi + sidedivs) - int nNodes; - int nOuts; - int nObjs; - int VarMarks[MAJ_NOBJS][2][MAJ_NOBJS] = {}; // default init the array - int nCnfVars; - int nCnfVars2; - int nCnfClauses; - - // Assign outputs to their connectivity variables - std::unordered_map> connection_variables; - const std::unordered_map>& forbidden_pairs; - eSLIMLog& log; - const eSLIMConfig& cfg; - - exactSynthesisEngine( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, - const std::unordered_map>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg); - int addClause(int lit1, int lit2, int lit3, int lit4); - static bool isNormalized( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut ); - int markup(); - int findFanin( Vec_Int_t * vValues, int i, int k, int nof_objs); - Mini_Aig_t * getAig(Vec_Int_t * assignment, int size); - Mini_Aig_t * getAig(Vec_Int_t * assignment); - void generateCNF(int fOrderNodes, int fUniqFans); - int startEncoding(int fOrderNodes, int fUniqFans ); - void generateMinterm( int iMint); - - int getGateEnablingLiteral(int index, bool negated); - int getAuxilaryVariableCount(); - - void introduceConnectionVariables(); - void setupConnectionVariables(); - void addConnectivityConstraints(); - void addCombinedCycleConstraints(); - std::unordered_map> computeNotInPair(const std::unordered_map>& pairs); - - int prepareLits(int * pLits, int& nLits); - - friend Derived; - }; - - // applies Cadical incrementally - class CadicalEngine : public exactSynthesisEngine { - - public: - CadicalEngine(Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, - const std::unordered_map>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg); - Mini_Aig_t* getCircuit(int size, double timeout); - - private: - using exactSynthesisEngine::addClause; - std::vector gate_enabling_assumptions; - CadicalSolver solver; - - - int addClause( int * pLits, int nLits ); - Vec_Int_t * solve(int size, double timeout); - int getAuxilaryVariableCountDerived(); - int getGateEnablingLiteralImpl(int index, bool negated); - void addAssumptions(int size); - void addGateDeactivatedConstraint(int out); - - std::vector getAssumptions(int size); - - friend exactSynthesisEngine; - }; - - class OneshotEngine { - protected: - int getAuxilaryVariableCountDerived() {return 0;}; - int getGateEnablingLiteralImpl(int index, bool negated) {return 0;}; - // void addAssumptions(int size) {}; - void addGateDeactivatedConstraint(int idx) {}; - }; - - template - class OneshotManager { - public: - OneshotManager(Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int maxnNodes, - const std::unordered_map>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg); - Mini_Aig_t* getCircuit(int size, double timeout); - - private: - T getOneshotEngine(int size); - - Vec_Wrd_t * vSimsIn; // input signatures (nWords = 1, nIns <= 64) - Vec_Wrd_t * vSimsOut; // output signatures (nWords = 1, nOuts <= 6) - int nIns; - int nDivs; // divisors (const + inputs + tfi + sidedivs) - int maxnNodes; - int nOuts; - - const std::unordered_map>& forbidden_pairs; - eSLIMLog& log; - const eSLIMConfig& cfg; - }; - - class CadicalEngineOneShot : public exactSynthesisEngine, public OneshotEngine { - - public: - CadicalEngineOneShot( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, - const std::unordered_map>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg); - Mini_Aig_t* getCircuit(int size, double timeout); - - private: - using exactSynthesisEngine::addClause; - - int addClause( int * pLits, int nLits ); - Vec_Int_t * solve(int size, double timeout); - - CadicalSolver solver; - - friend exactSynthesisEngine; - }; - - class KissatEngineOneShot : public exactSynthesisEngine, public OneshotEngine { - - public: - KissatEngineOneShot( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, - const std::unordered_map>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg); - Mini_Aig_t* getCircuit(int size, double timeout); - - private: - using exactSynthesisEngine::addClause; - - int addClause( int * pLits, int nLits ); - Vec_Int_t * solve(int size, double timeout); - - KissatSolver solver; - - friend exactSynthesisEngine; - }; - - - class KissatCmdEngine : public exactSynthesisEngine, public OneshotEngine { - - public: - KissatCmdEngine( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, - const std::unordered_map>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg); - Mini_Aig_t* getCircuit(int size, double timeout); - - private: - using exactSynthesisEngine::addClause; - - - int addClause( int * pLits, int nLits ); - Vec_Int_t * solve(int size, double timeout); - - FILE * encoding_file; - - // Ensure that there is no file with the same name in the diretory - constexpr static char * pFileNameIn = "_temp_.cnf"; - constexpr static char * pFileNameOut = "_temp_out.cnf"; - - #ifdef WIN32 - constexpr static char * pKissat = "kissat.exe"; - #else - constexpr static char * pKissat = "kissat"; - #endif - - friend exactSynthesisEngine; - }; - - - template - inline int exactSynthesisEngine::addClause(int lit1, int lit2, int lit3, int lit4) { - int clause[4] = {lit1, lit2, lit3, lit4}; - return static_cast(this)->addClause(clause, 4); - } - - template - inline int exactSynthesisEngine::getGateEnablingLiteral(int index, bool negated) { - return static_cast(this)->getGateEnablingLiteralImpl(index, negated); - } - - template - inline int exactSynthesisEngine::getAuxilaryVariableCount() { - int ncvars = connection_variables.empty() ? 0 : connection_variables.begin()->second.size() * connection_variables.size(); - return ncvars + static_cast(this)->getAuxilaryVariableCountDerived(); - } - - typedef OneshotManager CadicalOneShot; - typedef OneshotManager KissatOneShot; - typedef OneshotManager KissatCmdOneShot; - -} - -ABC_NAMESPACE_CXX_HEADER_END - -#include "synthesisEngine.tpp" - -#endif \ No newline at end of file diff --git a/src/opt/eslim/synthesisEngine.tpp b/src/opt/eslim/synthesisEngine.tpp deleted file mode 100644 index ef94d92268..0000000000 --- a/src/opt/eslim/synthesisEngine.tpp +++ /dev/null @@ -1,632 +0,0 @@ -/**CFile**************************************************************** - - FileName [synthesisEngine.tpp] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] - - Synopsis [Procedures for synthesising Boolean relations.] - - Author [Franz-Xaver Reichl] - - Affiliation [University of Freiburg] - - Date [Ver. 1.0. Started - March 2025.] - - Revision [$Id: synthesisEngine.tpp,v 1.00 2025/03/17 00:00:00 Exp $] - -***********************************************************************/ - -#include -#ifdef WIN32 - #include - #define unlink _unlink -#else - #include -#endif - -#include "misc/util/utilTruth.h" - -#include "synthesisEngine.hpp" -#include "utils.hpp" - -ABC_NAMESPACE_HEADER_START - Vec_Int_t * Exa4_ManParse( char * pFileName ); -ABC_NAMESPACE_HEADER_END - -ABC_NAMESPACE_CXX_HEADER_START - -namespace eSLIM { - - template - exactSynthesisEngine::exactSynthesisEngine( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, - const std::unordered_map>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg) - : vSimsIn(vSimsIn), vSimsOut(vSimsOut), nIns(nIns), nDivs(nDivs), nNodes(nNodes), - nOuts(nOuts), forbidden_pairs(forbidden_pairs), log(log), cfg(cfg) { - assert( Vec_WrdSize(vSimsIn) == Vec_WrdSize(vSimsOut) ); - nObjs = nDivs + nNodes + nOuts; - nCnfVars = markup(); - introduceConnectionVariables(); - nCnfVars2 = 0; - nCnfClauses = 0; - assert( nObjs < 64 ); - } - - template - bool exactSynthesisEngine::isNormalized( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut ) { - int i, Count = 0; word Temp; - Vec_WrdForEachEntry( vSimsIn, Temp, i ) { - if ( Temp & 1 ) { - Count++; - } - } - if ( Count ) { - return false; - } - if ( !(Vec_WrdEntry(vSimsOut, 0) & 1) ) { - return false; - } - return true; - } - - template - int exactSynthesisEngine::markup() { - int i, k, j, nVars[3] = {1 + 3*nNodes, 0, 3*nNodes*Vec_WrdSize(vSimsIn)}; - assert( nObjs <= MAJ_NOBJS ); - for ( i = nDivs; i < nDivs + nNodes; i++ ) { - for ( k = 0; k < 2; k++ ) { - for ( j = 1+!k; j < i-k; j++ ) { - VarMarks[i][k][j] = nVars[0] + nVars[1]++; - } - } - } - for ( i = nDivs + nNodes; i < nObjs; i++ ) { - for ( j = 0; j < nDivs + nNodes; j++ ) { - VarMarks[i][0][j] = nVars[0] + nVars[1]++; - } - } - return nVars[0] + nVars[1] + nVars[2]; - } - - template - int exactSynthesisEngine::findFanin( Vec_Int_t * vValues, int i, int k, int nof_objs ) { - int j, Count = 0, iVar = -1; - for ( j = 0; j < nof_objs; j++ ) { - if ( VarMarks[i][k][j] && Vec_IntEntry(vValues, VarMarks[i][k][j]) ){ - iVar = j; - Count++; - } - } - assert( Count == 1 ); - return iVar; - } - - template - Mini_Aig_t * exactSynthesisEngine::getAig(Vec_Int_t * vValues) { - return getAig(vValues, nNodes); - } - - template - Mini_Aig_t * exactSynthesisEngine::getAig(Vec_Int_t * vValues, int size) { - assert (size >= 0 && size <= nNodes && "Invalid size for AIG construction given."); - int i, k, Compl[MAJ_NOBJS] = {0}; - int nof_Objs = nDivs + size + nOuts; - Mini_Aig_t * pMini = Mini_AigStartSupport( nDivs-1, nof_Objs ); - for ( i = nDivs; i < nDivs + size; i++ ) { - int iNodes[2] = {0}; - int iVarStart = 1 + 3*(i - nDivs);// - int Val1 = Vec_IntEntry(vValues, iVarStart); - int Val2 = Vec_IntEntry(vValues, iVarStart+1); - int Val3 = Vec_IntEntry(vValues, iVarStart+2); - Compl[i] = Val1 && Val2 && Val3; - for ( k = 0; k < 2; k++ ) { - int iNode = findFanin(vValues, i, !k, nof_Objs); - int fComp = k ? !Val1 && Val2 && !Val3 : Val1 && !Val2 && !Val3; - iNodes[k] = Abc_Var2Lit(iNode, fComp ^ Compl[iNode]); - } - if ( Val1 && Val2 ) { - if ( Val3 ) { - Mini_AigOr( pMini, iNodes[0], iNodes[1] ); - } else { - Mini_AigXorSpecial( pMini, iNodes[0], iNodes[1] ); - } - } else { - Mini_AigAnd( pMini, iNodes[0], iNodes[1] ); - } - } - for ( i = nDivs + nNodes; i < nObjs; i++ ) { - int iVar = findFanin( vValues, i, 0, nof_Objs); - Mini_AigCreatePo( pMini, Abc_Var2Lit(iVar, Compl[iVar]) ); - } - assert( nof_Objs == Mini_AigNodeNum(pMini) ); - return pMini; - } - - template - void exactSynthesisEngine::generateCNF( int fOrderNodes, int fUniqFans ) { - int m; - startEncoding( fOrderNodes, fUniqFans ); - // Ignore pattern for all false input pattern (as we start with m=1) - for ( m = 1; m < Vec_WrdSize(vSimsIn); m++ ) { - generateMinterm( m ); - } - - if (forbidden_pairs.size() > 0) { - addConnectivityConstraints(); - } - } - - template - void exactSynthesisEngine::introduceConnectionVariables() { - std::unordered_set inputs_in_pairs; - // for (const auto& [out, inputs] : forbidden_pairs) { - for (const auto& it: forbidden_pairs) { - const auto& inputs = it.second; - inputs_in_pairs.insert(inputs.begin(), inputs.end()); - } - int nCVars = nObjs - 1; // The constant node does not depend on any node - for (int in : inputs_in_pairs) { - connection_variables.emplace(in, std::vector (nCVars, 0)); - std::iota(connection_variables[in].begin(), connection_variables[in].end(), nCnfVars); - nCnfVars += nCVars; - } - } - - template - void exactSynthesisEngine::setupConnectionVariables() { - // for (const auto& [in, cvars] : connection_variables) { - for (const auto& it: connection_variables) { - const auto& in = it.first; - const auto& cvars = it.second; - addClause(Abc_Var2Lit(cvars[in],0),0,0,0); - for (int i = nDivs; i < nDivs + nNodes; i++ ) { - int gate_idx = i - nDivs; - for (int j = 1; j < i - 1; j++) { - addClause(Abc_Var2Lit(VarMarks[i][0][j + 1], 1), Abc_Var2Lit(cvars[j], 1), Abc_Var2Lit(cvars[i - 1], 0), getGateEnablingLiteral(gate_idx, 1)); - addClause(Abc_Var2Lit(VarMarks[i][1][j], 1), Abc_Var2Lit(cvars[j - 1], 1), Abc_Var2Lit(cvars[i - 1], 0), getGateEnablingLiteral(gate_idx, 1)); - } - } - for (int i = nDivs + nNodes; i < nObjs; i++) { - for (int j = 1; j < nDivs + nNodes; j++) { - addClause(Abc_Var2Lit(VarMarks[i][0][j], 1), Abc_Var2Lit(cvars[j - 1], 1), Abc_Var2Lit(cvars[i - 1], 0),0); - } - } - } - } - - template - void exactSynthesisEngine::addConnectivityConstraints() { - assert (forbidden_pairs.size() > 0 && "Connectivity constraints are only needed if there are forbidden pairs."); - setupConnectionVariables(); - // If there are forbidden pairs for more than one input it is possible that a loop is obtained via two pairs - if (forbidden_pairs.size() > 1) { - addCombinedCycleConstraints(); - } - - // for (const auto& [out, inputs] : forbidden_pairs) { - for (const auto& it: forbidden_pairs) { - const auto& out = it.first; - const auto& inputs = it.second; - for (int in : inputs) { - const auto& cvars = connection_variables.at(in); - int out_obj_idx = nDivs + nNodes + out; - addClause(Abc_Var2Lit(cvars[out_obj_idx - 1], 1), 0, 0, 0); - } - } - } - - template - void exactSynthesisEngine::addCombinedCycleConstraints() { - assert (forbidden_pairs.size() > 1 && "Combined connectivity constraints are only needed if there are forbidden pairs for multiple inputs."); - std::unordered_map> not_in_pair = computeNotInPair(forbidden_pairs); - - // for (const auto& [out, inputs] : not_in_pair) { - for (const auto& it: not_in_pair) { - const auto& out = it.first; - const auto& inputs = it.second; - for (int in : inputs) { - const auto& cvars = connection_variables.at(in); - int out_obj_idx = nDivs + nNodes + out; - for (int in2 : forbidden_pairs.at(out)) { - addClause(Abc_Var2Lit(cvars[out_obj_idx - 1], 1), Abc_Var2Lit(cvars[in2], 0),0,0); - } - } - } - } - - template - std::unordered_map> exactSynthesisEngine::computeNotInPair(const std::unordered_map>& pairs) { - std::unordered_set all_inputs_in_pairs; - // for (const auto& [out, in] : pairs) { - for (const auto& it: pairs) { - const auto& in = it.second; - all_inputs_in_pairs.insert(in.begin(), in.end()); - } - std::unordered_map> not_in_pair; - // for (const auto& [out, in] : pairs) { - for (const auto& it: pairs) { - const auto& out = it.first; - const auto& in = it.second; - if (in.size() == all_inputs_in_pairs.size()) { - continue; - } - for (int i : all_inputs_in_pairs) { - if (in.find(i) == in.end()) { - not_in_pair[out].insert(i); - } - } - } - return not_in_pair; - } - - template - int exactSynthesisEngine::startEncoding(int fOrderNodes, int fUniqFans ) - { - int pLits[2*MAJ_NOBJS], i, j, k, n, m, nLits; - for ( i = nDivs; i < nDivs + nNodes; i++ ) - { - int gate_idx = i - nDivs; - int iVarStart = 1 + 3*(i - nDivs);// - for ( k = 0; k < 2; k++ ) - { - nLits = 0; - for ( j = 0; j < nObjs; j++ ) - if ( VarMarks[i][k][j] ) - pLits[nLits++] = Abc_Var2Lit( VarMarks[i][k][j], 0 ); - assert( nLits > 0 ); - static_cast(this)->addClause( pLits, nLits ); - for ( n = 0; n < nLits; n++ ) - for ( m = n+1; m < nLits; m++ ) - addClause( Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), getGateEnablingLiteral(gate_idx, 1), 0 ); - if ( k == 1 ) - break; - for ( j = 0; j < nObjs; j++ ) if ( VarMarks[i][0][j] ) - for ( n = j; n < nObjs; n++ ) if ( VarMarks[i][1][n] ) - addClause( Abc_Var2Lit(VarMarks[i][0][j], 1), Abc_Var2Lit(VarMarks[i][1][n], 1), getGateEnablingLiteral(gate_idx, 1), 0 ); - } - if ( fOrderNodes ) - for ( j = nDivs; j < i; j++ ) - for ( n = 0; n < nObjs; n++ ) if ( VarMarks[i][0][n] ) - for ( m = n+1; m < nObjs; m++ ) if ( VarMarks[j][0][m] ) - addClause( Abc_Var2Lit(VarMarks[i][0][n], 1), Abc_Var2Lit(VarMarks[j][0][m], 1), getGateEnablingLiteral(gate_idx, 1), 0 ); - for ( j = nDivs; j < i; j++ ) - for ( k = 0; k < 2; k++ ) if ( VarMarks[i][k][j] ) - for ( n = 0; n < nObjs; n++ ) if ( VarMarks[i][!k][n] ) - for ( m = 0; m < 2; m++ ) if ( VarMarks[j][m][n] ) - addClause( Abc_Var2Lit(VarMarks[i][k][j], 1), Abc_Var2Lit(VarMarks[i][!k][n], 1), Abc_Var2Lit(VarMarks[j][m][n], 1), getGateEnablingLiteral(gate_idx, 1) ); - for ( k = 0; k < 3; k++ ) - addClause( Abc_Var2Lit(iVarStart, k==1), Abc_Var2Lit(iVarStart+1, k==2), Abc_Var2Lit(iVarStart+2, k!=0), getGateEnablingLiteral(gate_idx, 1)); - if ( !cfg.allow_xors ) - addClause( Abc_Var2Lit(iVarStart, 1), Abc_Var2Lit(iVarStart+1, 1), Abc_Var2Lit(iVarStart+2, 0), getGateEnablingLiteral(gate_idx, 1)); - - } - for ( i = nDivs; i < nDivs + nNodes; i++ ) - { - int gate_idx = i - nDivs; - nLits = 0; - for ( k = 0; k < 2; k++ ) - for ( j = i+1; j < nObjs; j++ ) - if ( VarMarks[j][k][i] ) - pLits[nLits++] = Abc_Var2Lit( VarMarks[j][k][i], 0 ); - if ( fUniqFans ) - for ( n = 0; n < nLits; n++ ) - for ( m = n+1; m < nLits; m++ ) - addClause( Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), getGateEnablingLiteral(gate_idx, 1), 0 ); - } - for ( i = nDivs + nNodes; i < nObjs; i++ ) - { - static_cast(this)->addGateDeactivatedConstraint(i); - nLits = 0; - for ( j = 0; j < nDivs + nNodes; j++ ) if ( VarMarks[i][0][j] ) { - pLits[nLits++] = Abc_Var2Lit( VarMarks[i][0][j], 0 ); - } - static_cast(this)->addClause( pLits, nLits ); - for ( n = 0; n < nLits; n++ ) - for ( m = n+1; m < nLits; m++ ) - addClause( Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0 ); - } - return 1; - } - - template - void exactSynthesisEngine::generateMinterm( int iMint) { - int internalCnfVars = nCnfVars - getAuxilaryVariableCount(); // for each gate we add an assumption - int iNodeVar = internalCnfVars + 3*nNodes*(iMint - Vec_WrdSize(vSimsIn)); - int iOutMint = Abc_Tt6FirstBit( Vec_WrdEntry(vSimsOut, iMint) ); - int fOnlyOne = Abc_TtSuppOnlyOne( (int)Vec_WrdEntry(vSimsOut, iMint) ); - int i, k, n, j, VarVals[MAJ_NOBJS]; - int fAllOnes = Abc_TtCountOnes( Vec_WrdEntry(vSimsOut, iMint) ) == (1 << nOuts); - if ( fAllOnes ) - return; - assert( nObjs <= MAJ_NOBJS ); - assert( iMint < Vec_WrdSize(vSimsIn) ); - assert( nOuts <= 6 ); - for ( i = 0; i < nDivs; i++ ) { - VarVals[i] = (Vec_WrdEntry(vSimsIn, iMint) >> i) & 1; - } - for ( i = 0; i < nNodes; i++ ) { - VarVals[nDivs + i] = Abc_Var2Lit(iNodeVar + 3*i + 2, 0); - } - if ( fOnlyOne ) { - for ( i = 0; i < nOuts; i++ ) - VarVals[nDivs + nNodes + i] = (iOutMint >> i) & 1; - } else { - word t = Abc_Tt6Stretch( Vec_WrdEntry(vSimsOut, iMint), nOuts ); - int i, c, nCubes = 0, pCover[100], pLits[10]; - int iOutVar = nCnfVars + nCnfVars2; nCnfVars2 += nOuts; - for ( i = 0; i < nOuts; i++ ) { - VarVals[nDivs + nNodes + i] = Abc_Var2Lit(iOutVar + i, 0); - } - assert( t ); - if ( ~t ) { - Abc_Tt6IsopCover( ~t, ~t, nOuts, pCover, &nCubes ); - for ( c = 0; c < nCubes; c++ ) { - int nLits = 0; - for ( i = 0; i < nOuts; i++ ) { - int iLit = (pCover[c] >> (2*i)) & 3; - if ( iLit == 1 || iLit == 2 ) - pLits[nLits++] = Abc_Var2Lit(iOutVar + i, iLit != 1); - } - static_cast(this)->addClause( pLits, nLits ); - } - } - } - - for ( i = nDivs; i < nDivs + nNodes; i++ ) { - int iVarStart = 1 + 3*(i - nDivs);// - int iBaseVarI = iNodeVar + 3*(i - nDivs); - for ( k = 0; k < 2; k++ ) { - for ( j = 0; j < i; j++ ) { - if ( VarMarks[i][k][j] ) { - for ( n = 0; n < 2; n++ ) { - addClause( Abc_Var2Lit(VarMarks[i][k][j], 1), Abc_Var2Lit(iBaseVarI + k, n), Abc_LitNotCond(VarVals[j], !n), 0); - } - } - } - } - for ( k = 0; k < 4; k++ ) { - for ( n = 0; n < 2; n++ ) { - addClause( Abc_Var2Lit(iBaseVarI + 0, k&1), Abc_Var2Lit(iBaseVarI + 1, k>>1), Abc_Var2Lit(iBaseVarI + 2, !n), Abc_Var2Lit(k ? iVarStart + k-1 : 0, n)); - } - } - } - for ( i = nDivs + nNodes; i < nObjs; i++ ) { - for ( j = 0; j < nDivs + nNodes; j++ ) { - if ( VarMarks[i][0][j] ) { - for ( n = 0; n < 2; n++ ) { - addClause( Abc_Var2Lit(VarMarks[i][0][j], 1), Abc_LitNotCond(VarVals[j], n), Abc_LitNotCond(VarVals[i], !n), 0); - } - } - } - } - } - - template - int exactSynthesisEngine::prepareLits(int * pLits, int& nLits) { - int k = 0; - for ( int i = 0; i < nLits; i++ ) { - if ( pLits[i] == 1 ) - return 0; - else if ( pLits[i] == 0 ) - continue; - else if ( pLits[i] <= 2*(nCnfVars + nCnfVars2) ) - pLits[k++] = pLits[i]; - else assert( 0 ); - } - nLits = k; - return 1; - } - - inline CadicalEngine::CadicalEngine(Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, - const std::unordered_map>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg) - : exactSynthesisEngine(vSimsIn, vSimsOut, nIns, nDivs, nOuts, nNodes, forbidden_pairs, log, cfg) { - gate_enabling_assumptions.reserve(nNodes); - for (int i = 0; i < nNodes; i++) { - gate_enabling_assumptions.push_back(nCnfVars + i); - } - nCnfVars += nNodes; - generateCNF(0, 0); - } - - inline int CadicalEngine::addClause( int * pLits, int nLits ) { - if (prepareLits(pLits, nLits) == 0) { - return 0; - } - assert( nLits > 0 ); - solver.addClause(pLits, nLits); - return 1; - } - - inline Vec_Int_t * CadicalEngine::solve( int size, double timeout) { - std::vector assumptions = getAssumptions(size); - solver.assume(assumptions); - int status = timeout > 0 ? solver.solve(timeout) : solver.solve(); - Vec_Int_t * vRes = status == 10 ? solver.getModelVec() : nullptr; - if (status == 10) { - log.cummulative_sat_runtimes_per_size[size] += solver.getRunTime(); - log.nof_sat_calls_per_size[size] ++; - } else if (status == 20) { - log.cummulative_unsat_runtimes_per_size[size] += solver.getRunTime(); - log.nof_unsat_calls_per_size[size] ++; - } - return vRes; - } - - Mini_Aig_t* CadicalEngine::getCircuit(int size, double timeout) { - addAssumptions(size); - Vec_Int_t * vValues = solve(size, timeout); - Mini_Aig_t * pMini = vValues ? getAig(vValues, size) : nullptr; - Vec_IntFreeP( &vValues ); - return pMini; - } - - inline std::vector CadicalEngine::getAssumptions(int size) { - std::vector assumptions(nNodes); - for (int i = 0; i < size; i++) { - assumptions[i] = gate_enabling_assumptions[i]; - } - for (int i = size; i < nNodes; i++) { - assumptions[i] = -gate_enabling_assumptions[i]; - } - return assumptions; - } - - inline void CadicalEngine::addGateDeactivatedConstraint(int out_idx) { - for (int j = nDivs; j < nDivs + nNodes; j++ ) { - int gate_idx = j - nDivs; - // if a gate is disabled then it shall not be an output - addClause( Abc_Var2Lit(VarMarks[out_idx][0][j],1), Abc_Var2Lit( gate_enabling_assumptions[gate_idx], 0 ), 0, 0 ); - } - } - - inline int CadicalEngine::getGateEnablingLiteralImpl(int index, bool negated) { - return Abc_Var2Lit( gate_enabling_assumptions[index], negated ); - } - - inline int CadicalEngine::getAuxilaryVariableCountDerived() { - return nNodes; // We add an assumption for each gate - } - - inline void CadicalEngine::addAssumptions(int size) { - solver.assume(getAssumptions(size)); - } - - template - OneshotManager::OneshotManager(Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int maxnNodes, - const std::unordered_map>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg) - : vSimsIn(vSimsIn), vSimsOut(vSimsOut), nIns(nIns), nDivs(nDivs), maxnNodes(maxnNodes), nOuts(nOuts), forbidden_pairs(forbidden_pairs), log(log), cfg(cfg) { - } - - template - T OneshotManager::getOneshotEngine(int size) { - assert(size <= maxnNodes); - T oneshotEngine(vSimsIn, vSimsOut, nIns, nDivs, nOuts, size, forbidden_pairs, log, cfg); - return oneshotEngine; - } - - template - Mini_Aig_t* OneshotManager::getCircuit(int size, double timeout) { - T synth = getOneshotEngine(size); - return synth.getCircuit(size, timeout); - } - - inline CadicalEngineOneShot::CadicalEngineOneShot( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, - const std::unordered_map>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg) - : exactSynthesisEngine(vSimsIn, vSimsOut, nIns, nDivs, nOuts, nNodes, forbidden_pairs, log, cfg) { - } - - inline Vec_Int_t* CadicalEngineOneShot::solve( int size, double timeout) { - int status = timeout > 0 ? solver.solve(timeout) : solver.solve(); - Vec_Int_t * vRes = status != 10 ? nullptr : solver.getModelVec(); - return vRes; - } - - Mini_Aig_t* CadicalEngineOneShot::getCircuit(int size, double timeout) { - generateCNF(0, 0); - Vec_Int_t * vValues = solve(size, timeout); - Mini_Aig_t * pMini = vValues ? getAig(vValues, size) : nullptr; - Vec_IntFreeP( &vValues ); - return pMini; - } - - inline int CadicalEngineOneShot::addClause( int * pLits, int nLits ) { - if (prepareLits(pLits, nLits) == 0) { - return 0; - } - assert( nLits > 0 ); - solver.addClause(pLits, nLits); - return 1; - } - - inline KissatEngineOneShot::KissatEngineOneShot(Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, - const std::unordered_map>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg) - : exactSynthesisEngine(vSimsIn, vSimsOut, nIns, nDivs, nOuts, nNodes, forbidden_pairs, log, cfg) { - } - - Mini_Aig_t* KissatEngineOneShot::getCircuit(int size, double timeout) { - solver.init(nCnfVars); - generateCNF(0, 0); - Vec_Int_t * vValues = solve(size, timeout); - Mini_Aig_t * pMini = vValues ? getAig(vValues, size) : nullptr; - Vec_IntFreeP( &vValues ); - return pMini; - } - - inline Vec_Int_t *KissatEngineOneShot::solve( int size, double timeout) { - // TODO: The used interface does not yet allow timeouts - int status = solver.solve(); - Vec_Int_t * vRes = status != 10 ? nullptr : solver.getModelVec(); - return vRes; - } - - inline int KissatEngineOneShot::addClause( int * pLits, int nLits ) { - if (prepareLits(pLits, nLits) == 0) { - return 0; - } - assert( nLits > 0 ); - solver.addClause(pLits, nLits); - return 1; - } - - inline KissatCmdEngine::KissatCmdEngine(Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, - const std::unordered_map>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg) - : exactSynthesisEngine(vSimsIn, vSimsOut, nIns, nDivs, nOuts, nNodes, forbidden_pairs, log, cfg) { - } - - Mini_Aig_t* KissatCmdEngine::getCircuit(int size, double timeout) { - encoding_file = fopen( pFileNameIn, "wb" ); - fputs( "p cnf \n", encoding_file ); - generateCNF(0, 0); - Vec_Int_t * vValues = solve(size, timeout); - Mini_Aig_t * pMini = vValues ? getAig(vValues, size) : nullptr; - Vec_IntFreeP( &vValues ); - return pMini; - } - - inline int KissatCmdEngine::addClause( int * pLits, int nLits ) { - if (prepareLits(pLits, nLits) == 0) { - return 0; - } - assert( nLits > 0 ); - if ( encoding_file ) { - nCnfClauses++; - for ( int i = 0; i < nLits; i++ ) { - fprintf( encoding_file, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i]) ); - } - fprintf( encoding_file, "0\n" ); - } - return 1; - } - - inline Vec_Int_t * KissatCmdEngine::solve(int size, double timeout) { - rewind( encoding_file ); - fprintf( encoding_file, "p cnf %d %d", nCnfVars + nCnfVars2, nCnfClauses ); - fclose( encoding_file ); - encoding_file = nullptr; - - char Command[1000], * pCommand = (char *)&Command; - - // TODO: - // if ( TimeOut ) - // sprintf( pCommand, "%s --time=%d -q %s > %s", pKissat, TimeOut, pFileNameIn, pFileNameOut ); - // else - // sprintf( pCommand, "%s -q %s > %s", pKissat, pFileNameIn, pFileNameOut ); - - sprintf( pCommand, "%s -q %s > %s", pKissat, pFileNameIn, pFileNameOut ); -#ifdef __wasm - if ( 1 ) { -#else - if ( system( pCommand ) == -1 ) { -#endif - std::cerr << "Command " << pCommand << " failed\n"; - return nullptr; - } - Vec_Int_t * vRes = Exa4_ManParse( pFileNameOut ); - unlink( pFileNameIn ); - return vRes; - } - -} - -ABC_NAMESPACE_CXX_HEADER_END \ No newline at end of file diff --git a/src/opt/eslim/synthesisEngines.hpp b/src/opt/eslim/synthesisEngines.hpp new file mode 100644 index 0000000000..5f65139986 --- /dev/null +++ b/src/opt/eslim/synthesisEngines.hpp @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [synthesisEngines.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Synthesis engines] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__OPT__ESLIM__SYNTHESISENGINES_hpp +#define ABC__OPT__ESLIM__SYNTHESISENGINES_hpp + + +#include "misc/util/abc_global.h" + +#include "eslimCirMan.hpp" +#include "areaEngine.hpp" +#include "delayEngine.hpp" + + +ABC_NAMESPACE_CXX_HEADER_START +namespace eSLIM { + + class Relation; + class Subcircuit; + class eSLIMConfig; + class eSLIMLog; + + class AreaMinimizer { + public: + static eSLIMCirMan optimize(const eSLIMCirMan& encompassing, const Relation& relation, const Subcircuit& subcir, + const eSLIMConfig& cfg, eSLIMLog& log) { + return AreaEngine::synthesiseMinimumSizeCircuit(relation, subcir, cfg, log); + } + private: + AreaMinimizer() = default; + }; + + class AreaDelayConstraintMinimizer { + public: + static eSLIMCirMan optimize(eSLIMCirMan& encompassing, const Relation& relation, Subcircuit& subcir, + const eSLIMConfig& cfg, eSLIMLog& log) { + subcir.setupTimings(encompassing); + return DelayEngine::synthesizeMinimumAreaDelayConstraintCircuit(relation, subcir, encompassing.getDepth(), cfg, log); + } + private: + AreaDelayConstraintMinimizer() = default; + }; + + class AreaDelayMinimizer { + public: + static eSLIMCirMan optimize(eSLIMCirMan& encompassing, const Relation& relation, Subcircuit& subcir, + const eSLIMConfig& cfg, eSLIMLog& log) { + subcir.setupTimings(encompassing); + return DelayEngine::synthesizeMinimumAreaDelayCircuit(relation, subcir, cfg, log); + } + private: + AreaDelayMinimizer() = default; + }; + + class DelayMinimizer { + public: + static eSLIMCirMan optimize(eSLIMCirMan& encompassing, const Relation& relation, Subcircuit& subcir, + const eSLIMConfig& cfg, eSLIMLog& log) { + int max_crossing_path = subcir.setupTimings(encompassing); + unsigned int max_size = std::min(cfg.subcircuit_max_size, static_cast(subcir.nodes.size() + cfg.additional_gates)); + return DelayEngine::synthesizeMinimumDelayCircuit(relation, subcir, max_crossing_path, max_size, cfg, log); + } + private: + DelayMinimizer() = default; + }; + + class DelayAreaMinimizer { + public: + static eSLIMCirMan optimize(eSLIMCirMan& encompassing, const Relation& relation, Subcircuit& subcir, + const eSLIMConfig& cfg, eSLIMLog& log) { + int max_crossing_path = subcir.setupTimings(encompassing); + unsigned int max_size = std::min(cfg.subcircuit_max_size, static_cast(subcir.nodes.size() + cfg.additional_gates)); + return DelayEngine::synthesizeMinimumDelayAreaCircuit(relation, subcir, max_crossing_path, max_size, cfg, log); + } + private: + DelayAreaMinimizer() = default; + }; + + + template + struct isDelayEngine : std::integral_constant< bool, + std::is_same::type>::value + || std::is_same::type>::value + || std::is_same::type>::value + || std::is_same::type>::value + > {}; + + static_assert(!isDelayEngine::value); + static_assert(isDelayEngine::value); + static_assert(isDelayEngine::value); + static_assert(isDelayEngine::value); + static_assert(isDelayEngine::value); + + +} + +ABC_NAMESPACE_CXX_HEADER_END +#endif \ No newline at end of file diff --git a/src/opt/eslim/tabooList.hpp b/src/opt/eslim/tabooList.hpp new file mode 100644 index 0000000000..02f562e863 --- /dev/null +++ b/src/opt/eslim/tabooList.hpp @@ -0,0 +1,178 @@ +/**CFile**************************************************************** + + FileName [tabooList.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Taboo list for subcircuit selection.] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__OPT__ESLIM__TABOOLIST_hpp +#define ABC__OPT__ESLIM__TABOOLIST_hpp + +#include +#include +#include + +#include "misc/util/abc_namespaces.h" + +#include "eslimCirMan.hpp" +#include "subcircuit.hpp" + +ABC_NAMESPACE_CXX_HEADER_START +namespace eSLIM { + + class TabooList { + + public: + TabooList(const eSLIMCirMan& es_man); + int getRandomNonTaboo(std::mt19937& rng, double taboo_ratio, unsigned int taboo_time); + template + int getBiasedRandomNonTaboo(std::mt19937& rng, unsigned int bias, double taboo_ratio, unsigned int taboo_time); + void reset(); + + private: + struct eSLIMCirObjCompBase { + bool operator()(eSLIMCirObj* a, eSLIMCirObj* b) const { + return a->getId() < b->getId(); + } + }; + + struct eSLIMCirObjComp { + bool operator()(eSLIMCirObj* a, eSLIMCirObj* b) const { + return a->isTaboo < b->isTaboo || (a->isTaboo == b->isTaboo && eSLIMCirObjCompBase()(a,b)); + } + }; + + void updateTaboo(double taboo_ratio, unsigned int taboo_time); + void registerReplacement(eSLIMCirMan& replacement, const Subcircuit& subcir); + void discardSubcircuit(const Subcircuit& subcir); + void removeRedundantNode(eSLIMCirObj* nptr); + void fill(); + + void addNode(eSLIMCirObj* pobj); + void discardNode(eSLIMCirObj* pobj); + void addNonTaboo(eSLIMCirObj* pobj); + void removeNonTaboo(eSLIMCirObj* pobj); + + + const eSLIMCirMan& es_man; + std::set taboo_nodes; + std::set non_taboo_nodes; + + friend eSLIMCirMan; + }; + + inline TabooList::TabooList(const eSLIMCirMan& es_man) + : es_man(es_man) { + fill(); + } + + inline void TabooList::fill() { + for (int i = es_man.getNofPis() + 1; i < es_man.getNofObjs()-es_man.getNofPos(); i++) { + auto pObj = es_man.nodes[i].get(); + addNonTaboo(pObj); + } + } + + inline void TabooList::reset() { + taboo_nodes.clear(); + non_taboo_nodes.clear(); + fill(); + } + + inline void TabooList::updateTaboo(double taboo_ratio, unsigned int taboo_time) { + assert (taboo_ratio > 0 && taboo_ratio < 1); + auto it = taboo_nodes.begin(); + while (it != taboo_nodes.end()) { + if (!es_man.isTaboo(*(*it), taboo_time)) { + addNonTaboo(*it); + it = taboo_nodes.erase(it); + } else if (taboo_nodes.size() > static_cast(es_man.getNofGates()) * taboo_ratio) { + addNonTaboo(*it); + it = taboo_nodes.erase(it); + } else { + return; + } + } + } + + inline void TabooList::registerReplacement(eSLIMCirMan& replacement, const Subcircuit& subcir) { + discardSubcircuit(subcir); + for (int i = replacement.getNofPis() + 1; i < replacement.getNofObjs() - replacement.getNofPos(); i++) { + auto pObj = replacement.nodes[i].get(); + taboo_nodes.insert(pObj); + } + } + + inline void TabooList::discardSubcircuit(const Subcircuit& subcir) { + for (int nd : subcir.nodes) { + discardNode(es_man.nodes[nd].get()); + } + } + + inline void TabooList::removeRedundantNode(eSLIMCirObj* nptr) { + discardNode(nptr); + } + + + inline int TabooList::getRandomNonTaboo(std::mt19937& rng, double taboo_ratio, unsigned int taboo_time) { + updateTaboo(taboo_ratio, taboo_time); + assert(non_taboo_nodes.size() > 0); + std::uniform_int_distribution udistr(0, non_taboo_nodes.size() - 1); + int rv = udistr(rng); + auto it = non_taboo_nodes.begin(); + std::advance(it, rv); + return (*it)->node_id; + } + + template + int TabooList::getBiasedRandomNonTaboo(std::mt19937& rng, unsigned int bias, double taboo_ratio, unsigned int taboo_time) { + updateTaboo(taboo_ratio, taboo_time); + std::vector weights; + weights.reserve(non_taboo_nodes.size()); + for (const auto& pObj : non_taboo_nodes) { + if (BiasCondition::useBias(es_man, *pObj)) { + weights.push_back(bias); + } else { + weights.push_back(1); + } + } + std::discrete_distribution ddistr(weights.begin(), weights.end()); + int rv = ddistr(rng); + auto it = non_taboo_nodes.begin(); + std::advance(it, rv); + return (*it)->node_id; + } + + inline void TabooList::addNode(eSLIMCirObj* pobj) { + taboo_nodes.insert(pobj); + } + + inline void TabooList::discardNode(eSLIMCirObj* pobj) { + removeNonTaboo(pobj); + taboo_nodes.erase(pobj); + } + + inline void TabooList::addNonTaboo(eSLIMCirObj* pobj) { + non_taboo_nodes.insert(pobj); + } + + inline void TabooList::removeNonTaboo(eSLIMCirObj* pobj) { + non_taboo_nodes.erase(pobj); + } + +} +ABC_NAMESPACE_CXX_HEADER_END +#endif \ No newline at end of file diff --git a/src/opt/eslim/utils.hpp b/src/opt/eslim/utils.hpp index fb942c417b..b4beb33f07 100644 --- a/src/opt/eslim/utils.hpp +++ b/src/opt/eslim/utils.hpp @@ -6,48 +6,118 @@ PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] - Synopsis [Utilities for the eSLIM package.] + Synopsis [Utilities] Author [Franz-Xaver Reichl] Affiliation [University of Freiburg] - Date [Ver. 1.0. Started - March 2025.] + Date [Ver. 1.0. Started - April 2026.] - Revision [$Id: utils.hpp,v 1.00 2025/03/17 00:00:00 Exp $] + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] ***********************************************************************/ -#ifndef ABC__OPT__ESLIM__UTILS_h -#define ABC__OPT__ESLIM__UTILS_h +#ifndef ABC__OPT__ESLIM__UTILS_hpp +#define ABC__OPT__ESLIM__UTILS_hpp #include #include #include -#include "misc/util/abc_namespaces.h" -#include "misc/vec/vec.h" -#include "aig/gia/gia.h" +#include "misc/util/abc_global.h" + +#if __cplusplus >= 202002L + // C++20 (and later) code + #include +#endif + +#if __cplusplus >= 202002L + // // C++20 (and later) code + // #include + #define popcount(x) std::popcount(x) +#elif defined(__GNUC__) + #define popcount(x) __builtin_popcountll(x) +// #elif defined(_MSC_VER) +#elif defined(_WIN64) + #define popcount(x) __popcnt64(x) +#else + + inline int popcount64Impl(ABC_UINT64_T x) { + // Constants are 64-bit masks + const ABC_UINT64_T m1 = 0x5555555555555555; + const ABC_UINT64_T m2 = 0x3333333333333333; + const ABC_UINT64_T m3 = 0x0F0F0F0F0F0F0F0F; + const ABC_UINT64_T m4 = 0x0101010101010101; + x = x - ((x >> 1) & m1); + x = (x & m2) + ((x >> 2) & m2); + x = (x + (x >> 4)) & m3; + return (x * m4) >> 56; + } + #define popcount(x) popcount64Impl(x) -ABC_NAMESPACE_CXX_HEADER_START +#endif +ABC_NAMESPACE_CXX_HEADER_START namespace eSLIM { - struct eSLIMConfig { - bool extended_normality_processing = false; + inline int lsb(ABC_UINT64_T tt) { + #if __cplusplus >= 202002L + if (tt == 0) { + return -1; + } + return std::countr_zero(tt); + #elif defined(__GNUC__) + return __builtin_ffsl(tt) - 1; + // #elif defined(_MSC_VER) + #elif defined(_WIN64) + if (tt == 0) { + return -1; + } + int x = 0; + bool status = _BitScanForward64(x, tt); + return x; + #else + if (tt == 0) { + return -1; + } + ABC_UINT64_T lsb = tt & -tt; + const ABC_UINT64_T debruijn = 0x03f79d71b4cb0a89ULL; + ABC_UINT64_T scrambled = (lsb * debruijn) >> 58; + const int index64[64] = { + 0, 1, 48, 2, 57, 49, 28, 3, 61, 58, 50, 42, 29, 17, 4, 62, + 55, 59, 36, 53, 51, 43, 22, 30, 18, 12, 5, 63, 35, 56, 60, 54, + 37, 52, 44, 27, 23, 31, 19, 8, 13, 6, 64, 32, 47, 38, 45, 21, + 26, 24, 39, 16, 7, 64, 33, 46, 20, 25, 41, 15, 64, 34, 40, 64 + }; + return index64[scrambled]; + #endif + } + + struct eSLIMConfig { + bool aig = true; + int gate_size = 2; + bool apply_strash = true; bool fix_seed = false; bool fill_subcircuits = false; bool trial_limit_active = true; - bool allow_xors = false; + bool allow_xors = false; unsigned int timeout = 3600; unsigned int iterations = 0; - unsigned int subcircuit_size_bound = 6; + unsigned int subcircuit_max_size = 6; + unsigned int additional_gates = 0; unsigned int strash_intervall = 100; int seed = 0; - unsigned int nselection_trials = 100; - double expansion_probability = 0.6; + unsigned int nselection_trials = 120; + double expansion_probability = 0.5; + unsigned int bias = 2; + unsigned int nwindows = 1; + unsigned int window_size = 500; + + unsigned int taboo_time = 100; + double taboo_ratio = 0.5; // times given in sec int minimum_sat_timeout = 1; @@ -55,49 +125,73 @@ namespace eSLIM { int minimum_dynamic_timeout_sample_size = 50; double dynamic_timeout_buffer_factor = 1.4; + int relation_generation_timeout = 180; + bool approximate_relation = false; // Compute an overapproximation of the relation that may not use all don't cares by limiting the tfo of the subcircuit + bool generate_relation_with_tfi_limit = false; // If approximate_relation is true, also limit the tfi of the subcircuit + unsigned int relation_tfi_bound = 0; + unsigned int relation_tfo_bound = 0; + int verbosity_level = 0; }; - struct eSLIMLog { - unsigned int iteration_count = 0; - double relation_generation_time = 0; - double synthesis_time = 0; - unsigned int subcircuits_with_forbidden_pairs = 0; + class eSLIMLog { - std::vector nof_analyzed_circuits_per_size; - std::vector nof_replaced_circuits_per_size; - std::vector nof_reduced_circuits_per_size; + public: + unsigned int iteration_count = 0; + double relation_generation_time = 0; + double synthesis_time = 0; + unsigned int subcircuits_with_forbidden_pairs = 0; - std::vector cummulative_sat_runtimes_per_size; - std::vector nof_sat_calls_per_size; - std::vector cummulative_unsat_runtimes_per_size; - std::vector nof_unsat_calls_per_size; + std::vector nof_analyzed_circuits_per_size; + std::vector nof_replaced_circuits_per_size; + std::vector nof_reduced_circuits_per_size; - eSLIMLog(int size); - }; + std::vector cummulative_sat_runtimes_per_size; + std::vector nof_sat_calls_per_size; + std::vector cummulative_unsat_runtimes_per_size; + std::vector nof_unsat_calls_per_size; + std::vector cummulative_relation_generation_times_per_size; + std::vector nof_relation_generations_per_size; + + double cummulative_sat_runtime_synthesis = 0; // msec + double max_sat_runtime_synthesis = 0; // msec + ABC_UINT64_T nof_sat_calls_synthesis = 0; - struct Subcircuit { - Vec_Int_t* nodes; - Vec_Int_t* io; - unsigned int nof_inputs; - std::unordered_map> forbidden_pairs; - void free(); + double cummulative_sat_runtime_relation_generation = 0; // sec + double max_sat_runtime_relation_generation = 0; // sec + ABC_UINT64_T nof_sat_calls_relation_generation = 0; + + eSLIMLog(int size); + int getSize() const; + void resize(int size); }; - inline void Subcircuit::free() { - Vec_IntFree(nodes); - Vec_IntFree(io); - } inline eSLIMLog::eSLIMLog(int size) : nof_analyzed_circuits_per_size(size + 1, 0), nof_replaced_circuits_per_size(size + 1, 0), - nof_reduced_circuits_per_size(size + 1, 0), cummulative_sat_runtimes_per_size(size + 1, 0), - nof_sat_calls_per_size(size + 1, 0), cummulative_unsat_runtimes_per_size(size + 1, 0), - nof_unsat_calls_per_size(size + 1, 0) { + nof_reduced_circuits_per_size(size + 1, 0), + cummulative_sat_runtimes_per_size(size + 1, 0), nof_sat_calls_per_size(size + 1, 0), + cummulative_unsat_runtimes_per_size(size + 1, 0), nof_unsat_calls_per_size(size + 1, 0), + cummulative_relation_generation_times_per_size(size + 1, 0), nof_relation_generations_per_size(size + 1, 0) { } -} + inline int eSLIMLog::getSize() const { + return nof_analyzed_circuits_per_size.size() - 1; + } -ABC_NAMESPACE_CXX_HEADER_END + inline void eSLIMLog::resize(int size) { + int sz = size + 1; + nof_analyzed_circuits_per_size.resize(sz); + nof_replaced_circuits_per_size.resize(sz); + nof_reduced_circuits_per_size.resize(size); + cummulative_sat_runtimes_per_size.resize(sz); + nof_sat_calls_per_size.resize(sz); + cummulative_unsat_runtimes_per_size.resize(sz); + nof_unsat_calls_per_size.resize(sz); + cummulative_relation_generation_times_per_size.resize(sz); + nof_relation_generations_per_size.resize(sz); + } +} +ABC_NAMESPACE_CXX_HEADER_END #endif \ No newline at end of file diff --git a/src/opt/eslim/windowMan.hpp b/src/opt/eslim/windowMan.hpp new file mode 100644 index 0000000000..0ab59fb04e --- /dev/null +++ b/src/opt/eslim/windowMan.hpp @@ -0,0 +1,79 @@ +/**CFile**************************************************************** + + FileName [windowMan.hpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Basic implementation of a window manager.] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__OPT__ESLIM__WINDOWMAN_hpp +#define ABC__OPT__ESLIM__WINDOWMAN_hpp + +#include + +#include "misc/util/abc_global.h" + +#include "eslimCirMan.hpp" +#include "utils.hpp" + + +ABC_NAMESPACE_CXX_HEADER_START +namespace eSLIM { + + // The parallelisation strategy implemented in this class is rather easy and mainly intended to demonstrate + // how the eslim package could make use of parallel computing + template + class WindowMan { + + public: + void static applyeSLIM(eSLIMCirMan& es_man, eSLIMConfig& cfg, eSLIMLog& log); + + private: + + WindowMan(eSLIMCirMan& es_man, const eSLIMConfig& cfg, eSLIMLog& log); + eSLIMCirMan getCircuit(); + + void setupWindows(); + void computeWindow(const std::vector& gate_ids, int node_begin, int node_end); + void reorderCircuit(); + + void runParallel(); + eSLIMCirMan recombineWindows(); + void addEncompassing(eSLIMCirMan& es_man, int node_begin, int node_end); + void addWindow(eSLIMCirMan& es_man, int wid); + + void combineLogs(); + + + int nwindows = 0; + eSLIMCirMan& es_man; + const eSLIMConfig& cfg; + eSLIMLog& log; + std::vector wlogs; + std::mt19937 rng; + + std::vector windows; + std::vector scirs; + std::vector node_ranges_begin; + std::vector node_ranges_end; + + }; + +} +ABC_NAMESPACE_CXX_HEADER_END + +#include "windowMan.tpp" + +#endif \ No newline at end of file diff --git a/src/opt/eslim/windowMan.tpp b/src/opt/eslim/windowMan.tpp new file mode 100644 index 0000000000..c540988a38 --- /dev/null +++ b/src/opt/eslim/windowMan.tpp @@ -0,0 +1,221 @@ +/**CFile**************************************************************** + + FileName [windowMan.tpp] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).] + + Synopsis [Basic implementation of a window manager.] + + Author [Franz-Xaver Reichl] + + Affiliation [University of Freiburg] + + Date [Ver. 1.0. Started - April 2026.] + + Revision [$Id: eSLIM.cpp,v 1.00 2025/04/14 00:00:00 Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef ABC_USE_PTHREADS + #include +#endif + +#include "windowMan.hpp" +#include "subcircuit.hpp" + + +ABC_NAMESPACE_IMPL_START +namespace eSLIM { + + template + void WindowMan::applyeSLIM(eSLIMCirMan& es_man, eSLIMConfig& cfg, eSLIMLog& log) { + int v = cfg.verbosity_level; + cfg.verbosity_level = 0; + WindowMan win_man(es_man, cfg, log); + win_man.setupWindows(); + win_man.runParallel(); + cfg.verbosity_level = v; + // eSLIMCirMan combined = win_man.recombineWindows(); + // std::swap(es_man, combined); + es_man = win_man.recombineWindows(); + } + + template + WindowMan::WindowMan(eSLIMCirMan& es_man, const eSLIMConfig& cfg, eSLIMLog& log) + : es_man(es_man), cfg(cfg), log(log) { + if (cfg.fix_seed) { + rng.seed(cfg.seed); + } + } + + template + void WindowMan::setupWindows() { + reorderCircuit(); + unsigned int nmax_windows = std::ceil(static_cast(es_man.getNofGates()) / cfg.window_size); + nwindows = std::min(nmax_windows, cfg.nwindows); + std::vector gate_ids(es_man.getNofGates()); + std::iota(gate_ids.begin(), gate_ids.end(), es_man.getNofPis() + 1); + std::vector window_ids (nmax_windows); + std::iota(window_ids.begin(), window_ids.end(), 0); + std::vector selected_window_ids; + selected_window_ids.reserve(nwindows); + std::sample(window_ids.begin(), window_ids.end(), std::back_inserter(selected_window_ids), nwindows, rng); + for (int i = 0; i < nwindows; i++) { + int begin_idx = selected_window_ids[i]*cfg.window_size; + // int end_idx = selected_window_ids[i] == nmax_windows ? gate_ids.size() : selected_window_ids[i+1]*cfg.window_size; + // int end_idx = selected_window_ids[i] == nmax_windows - 1 ? gate_ids.size() : begin_idx + cfg.window_size; + int end_idx = begin_idx + cfg.window_size; + computeWindow(gate_ids, begin_idx, end_idx); + wlogs.emplace_back(log.getSize()); + } + } + + template + void WindowMan::reorderCircuit() { + std::vector pos; + pos.reserve(es_man.getNofPos()); + for (int i = es_man.getNofObjs() - es_man.getNofPos(); i < es_man.getNofObjs(); i++) { + pos.push_back(i); + } + std::shuffle(pos.begin(), pos.end(), rng); + es_man.applyDFSOrdering(pos); + } + + template + void WindowMan::computeWindow(const std::vector& gate_ids, int node_begin, int node_end) { + es_man.incrementTraversalId(); // needed for the insubcircuit marks + int end_node; + if (node_end >= gate_ids.size()) { + node_end = gate_ids.size(); + end_node = gate_ids.back() + 1; + } else { + end_node = gate_ids[node_end]; + } + Subcircuit scir = Subcircuit::getSubcircuitBare(es_man, gate_ids.begin() + node_begin, gate_ids.begin() + node_end); + scirs.push_back(scir); + windows.emplace_back(es_man, scir); + node_ranges_begin.push_back(gate_ids[node_begin]); + node_ranges_end.push_back(end_node); + } + + + template + void WindowMan::runParallel() { + #ifdef ABC_USE_PTHREADS + std::vector eslim_threads; + eslim_threads.reserve(nwindows); + for (int i = 0; i < nwindows; i++) { + std::thread esman_thread(eSLIM_Man::applyeSLIM, std::ref(windows[i]), std::ref(cfg), std::ref(wlogs[i])); + eslim_threads.push_back(std::move(esman_thread)); + + } + for(auto& t: eslim_threads) { + t.join(); + } + #else + std::cout << "PThreads not available, minimize random window.\n"; + std::uniform_int_distribution<> udist(0, windows.size() - 1); + int wid = udist(rng); + eSLIM_Man::applyeSLIM(windows[wid], cfg, wlogs[wid]); + #endif + } + + template + eSLIMCirMan WindowMan::recombineWindows() { + combineLogs(); + eSLIMCirMan combined(es_man.getNofObjs()); + for (int i = 1; i <= es_man.getNofPis(); i++) { + es_man.nodes[i]->value1 = combined.addPi(); //node 0 is the constant node + } + int block_begin = es_man.getNofPis() + 1; + for (int i = 0; i < nwindows; i++) { + // windows[i].print(); + int block_end = node_ranges_begin[i]; + addEncompassing(combined, block_begin, block_end); + addWindow(combined, i); + block_begin = node_ranges_end[i]; + } + if (node_ranges_end.back() < es_man.getNofObjs() - es_man.getNofPos()) { + addEncompassing(combined, node_ranges_end.back(), es_man.getNofObjs() - es_man.getNofPos()); + } + for (int i = 0; i < es_man.getNofPos(); i++) { + int nd_id = es_man.getNofObjs() - es_man.getNofPos() + i; + auto& nd = es_man.nodes[nd_id]; + bool is_negated = nd->tt == 1; + combined.addPo(nd->fanins[0]->value1, is_negated); + } + return combined; + } + + template + void WindowMan::addEncompassing(eSLIMCirMan& combined, int node_begin, int node_end) { + for (int i = node_begin; i < node_end; i++) { + auto& nd = es_man.nodes[i]; + std::vector fanins; + fanins.reserve(nd->fanins.size()); + for (int i = 0; i < nd->fanins.size(); i++) { + fanins.push_back(nd->fanins[i]->value1); + } + nd->value1 = combined.addNode(fanins, nd->tt); + } + } + + template + void WindowMan::addWindow(eSLIMCirMan& combined, int wid) { + for (int i = 1; i <= windows[wid].getNofPis(); i++) { + windows[wid].nodes[i]->value1 = es_man.nodes[scirs[wid].inputs[i-1]]->value1; + } + for (int i = windows[wid].getNofPis() + 1; i < windows[wid].getNofObjs() - windows[wid].getNofPos(); i++) { + auto& nd = windows[wid].nodes[i]; + std::vector fanins; + fanins.reserve(nd->fanins.size()); + for (int i = 0; i < nd->fanins.size(); i++) { + fanins.push_back(nd->fanins[i]->value1); + } + nd->value1 = combined.addNode(fanins, nd->tt); + } + for (int i = 0; i < windows[wid].getNofPos(); i++) { + auto& out_nd = windows[wid].nodes[windows[wid].getNofObjs() - windows[wid].getNofPos() + i]; + es_man.nodes[scirs[wid].outputs[i]]->value1 = out_nd->fanins[0]->value1; + } + } + + + template + void WindowMan::combineLogs() { + for (const auto& wl : wlogs) { + int wl_size = wl.getSize(); + if (log.getSize() < wl_size) { + log.resize(wl_size); + } + log.iteration_count += wl.iteration_count; + log.relation_generation_time += wl.relation_generation_time; + log.synthesis_time += wl.synthesis_time; + log.subcircuits_with_forbidden_pairs += wl.subcircuits_with_forbidden_pairs; + + for (int i = 0; i <= wl_size; i++) { + log.nof_analyzed_circuits_per_size[i] += wl.nof_analyzed_circuits_per_size[i]; + log.nof_replaced_circuits_per_size[i] += wl.nof_replaced_circuits_per_size[i]; + log.nof_reduced_circuits_per_size[i] += wl.nof_reduced_circuits_per_size[i]; + log.cummulative_sat_runtimes_per_size[i] += wl.cummulative_sat_runtimes_per_size[i]; + log.nof_sat_calls_per_size[i] += wl.nof_sat_calls_per_size[i]; + log.cummulative_unsat_runtimes_per_size[i] += wl.cummulative_unsat_runtimes_per_size[i]; + log.nof_unsat_calls_per_size[i] += wl.nof_unsat_calls_per_size[i]; + log.cummulative_relation_generation_times_per_size[i] += wl.cummulative_relation_generation_times_per_size[i]; + log.nof_relation_generations_per_size[i] += wl.nof_relation_generations_per_size[i]; + } + } + } + +} +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/src/opt/fret/fretMain.c b/src/opt/fret/fretMain.c index f742cda032..e7995bf52f 100644 --- a/src/opt/fret/fretMain.c +++ b/src/opt/fret/fretMain.c @@ -202,8 +202,9 @@ Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, pNtk = Abc_FlowRetime_NtkSilentRestrash( pNtk, 1 ); } + i = Abc_NtkLevel(pNtk); vprintf("\tfinal reg count = %d\n", Abc_NtkLatchNum(pNtk)); - vprintf("\tfinal levels = %d\n", Abc_NtkLevel(pNtk)); + vprintf("\tfinal levels = %d\n", i); #if defined(DEBUG_CHECK) Abc_NtkDoCheck( pNtk ); @@ -1380,4 +1381,3 @@ void Abc_ObjPrintNeighborhood( Abc_Obj_t *pObj, int depth ) { Vec_PtrFree(vNodes); } ABC_NAMESPACE_IMPL_END - diff --git a/src/opt/fret/fretTime.c b/src/opt/fret/fretTime.c index 9d55fc929f..67fcabf8c1 100644 --- a/src/opt/fret/fretTime.c +++ b/src/opt/fret/fretTime.c @@ -94,14 +94,13 @@ void Abc_FlowRetime_ConstrainConserv( Abc_Ntk_t * pNtk ) { // clear all exact constraints pManMR->nExactConstraints = 0; - while( Vec_PtrSize( pManMR->vExactNodes )) { - pObj = (Abc_Obj_t*)Vec_PtrPop( pManMR->vExactNodes ); - + Abc_NtkForEachObj( pNtk, pObj, i ) { if ( Vec_PtrSize( FTIMEEDGES(pObj) )) { pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) ); ABC_FREE( pArray ); } } + Vec_PtrClear( pManMR->vExactNodes ); #if !defined(IGNORE_TIMING) if (pManMR->fIsForward) { diff --git a/src/opt/lpk/lpkCut.c b/src/opt/lpk/lpkCut.c index 41cfaed5f5..f19decff02 100644 --- a/src/opt/lpk/lpkCut.c +++ b/src/opt/lpk/lpkCut.c @@ -141,7 +141,7 @@ unsigned * Lpk_CutTruth_rec( Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars, Vec_ assert( !Hop_IsComplement(pObj) ); if ( pObj->pData ) { - assert( ((unsigned)(ABC_PTRUINT_T)pObj->pData) & 0xffff0000 ); + assert( ((ABC_PTRUINT_T)pObj->pData) > 0xffff ); // catch small int values return (unsigned *)pObj->pData; } // get the plan for a new truth table @@ -197,7 +197,7 @@ unsigned * Lpk_CutTruth( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fInv ) // set the initial truth tables at the fanins Abc_ObjForEachFanin( pObj, pFanin, k ) { - assert( ((unsigned)(ABC_PTRUINT_T)pFanin->pCopy) & 0xffff0000 ); + assert( ((ABC_PTRUINT_T)pFanin->pCopy) > 0xffff ); // catch small int values or NULL Hop_ManPi( pManHop, k )->pData = pFanin->pCopy; } // compute the truth table of internal nodes diff --git a/src/opt/ufar/UfarCmd.cpp b/src/opt/ufar/UfarCmd.cpp index 6ac2320ff4..6270cbb599 100755 --- a/src/opt/ufar/UfarCmd.cpp +++ b/src/opt/ufar/UfarCmd.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "base/wlc/wlc.h" #include "aig/gia/giaAig.h" @@ -30,6 +31,22 @@ ABC_NAMESPACE_IMPL_START using namespace std; static UFAR::UfarManager ufar_manager; +typedef struct Ufar_StopCtx_t_ +{ + int (*pFuncStop)(int); + int nTimeOut; + int fActive; + timeval TimeStart; +} Ufar_StopCtx_t; +#if defined(_MSC_VER) +__declspec(thread) static Ufar_StopCtx_t g_UfarStopCtx = { NULL, 0, 0, {0, 0} }; +#elif defined(__cplusplus) && __cplusplus >= 201103L +static thread_local Ufar_StopCtx_t g_UfarStopCtx = { NULL, 0, 0, {0, 0} }; +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +static _Thread_local Ufar_StopCtx_t g_UfarStopCtx = { NULL, 0, 0, {0, 0} }; +#else +static __thread Ufar_StopCtx_t g_UfarStopCtx = { NULL, 0, 0, {0, 0} }; +#endif static int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAnalyzeCex( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -40,6 +57,357 @@ static int Abc_CommandProveUsingUif( Abc_Frame_t * pAbc, int argc, char ** argv static inline Wlc_Ntk_t * Wlc_AbcGetNtk( Abc_Frame_t * pAbc ) { return (Wlc_Ntk_t *)pAbc->pAbcWlc; } static inline void Wlc_AbcFreeNtk( Abc_Frame_t * pAbc ) { if ( pAbc->pAbcWlc ) Wlc_NtkFree(Wlc_AbcGetNtk(pAbc)); } static inline void Wlc_AbcUpdateNtk( Abc_Frame_t * pAbc, Wlc_Ntk_t * pNtk ) { Wlc_AbcFreeNtk(pAbc); pAbc->pAbcWlc = pNtk; } +static inline long long Ufar_ElapsedUsec( const timeval & Start, const timeval & Stop ) { return 1000000ll * (long long)(Stop.tv_sec - Start.tv_sec) + (long long)(Stop.tv_usec - Start.tv_usec); } + +static int Ufar_StopWithTimeout( int RunId ) +{ + if ( g_UfarStopCtx.pFuncStop && g_UfarStopCtx.pFuncStop(RunId) ) + return 1; + if ( g_UfarStopCtx.fActive && g_UfarStopCtx.nTimeOut > 0 ) + { + timeval Now; + gettimeofday( &Now, NULL ); + if ( Ufar_ElapsedUsec(g_UfarStopCtx.TimeStart, Now) >= 1000000ll * (long long)g_UfarStopCtx.nTimeOut ) + return 1; + } + return 0; +} + +struct Ufar_StopScope_t +{ + Ufar_StopCtx_t Saved; + Ufar_StopScope_t( int (*pFuncStop)(int), int nTimeOut ) + { + Saved = g_UfarStopCtx; + g_UfarStopCtx.pFuncStop = pFuncStop; + g_UfarStopCtx.nTimeOut = nTimeOut; + g_UfarStopCtx.fActive = 1; + gettimeofday( &g_UfarStopCtx.TimeStart, NULL ); + } + ~Ufar_StopScope_t() + { + g_UfarStopCtx = Saved; + } +}; + +static string Ufar_GetStatusName( Wlc_Ntk_t * pNtk ) +{ + if ( pNtk == NULL || Wlc_NtkPoNum(pNtk) == 0 ) + return "result"; + if ( Wlc_NtkPoNum(pNtk) == 1 ) + return Wlc_ObjName( pNtk, Wlc_ObjId(pNtk, Wlc_NtkPo(pNtk, 0)) ); + + string Name0 = Wlc_ObjName( pNtk, Wlc_ObjId(pNtk, Wlc_NtkPo(pNtk, 0)) ); + string Name1 = Wlc_ObjName( pNtk, Wlc_ObjId(pNtk, Wlc_NtkPo(pNtk, 1)) ); + return Name0 + "_xor_" + Name1; +} + +static void Ufar_DumpStatusLog( const string & FileName, int RetValue, const string & StatusName ) +{ + FILE * pFile; + if ( FileName.empty() || FileName == "none" ) + return; + pFile = fopen( FileName.c_str(), "wb" ); + if ( pFile == NULL ) + { + cout << "Cannot open file \"" << FileName << "\" for writing." << endl; + return; + } + if ( RetValue == 1 ) + fprintf( pFile, "STATUS: UNSAT " ); + else if ( RetValue == 0 ) + fprintf( pFile, "STATUS: SAT " ); + else + fprintf( pFile, "STATUS: ABORTED " ); + fprintf( pFile, "%s\n", StatusName.c_str() ); + fclose( pFile ); +} + +static void Ufar_SetDefaultParams( UFAR::UfarManager::Params & Params, int nTimeOut, int fVerbose, int (*pFuncStop)(int), int RunId ) +{ + Params = UFAR::UfarManager::Params(); + Params.RunId = RunId; + Params.pFuncStop = pFuncStop; + if ( nTimeOut > 0 ) + Params.nTimeout = nTimeOut; + Params.iVerbosity = fVerbose ? 1 : 0; +} +static void Ufar_AddOptions( OptMgr & opt_mgr, const UFAR::UfarManager::Params & Params ) +{ + opt_mgr.AddOpt("--norm", Params.fNorm ? "yes" : "no", "", "toggle using data type normalization"); + opt_mgr.AddOpt("--adder", "no", "", "toggle including adders"); + opt_mgr.AddOpt("--cexmin", Params.fCexMin ? "yes" : "no", "", "toggle using CEX minimization"); + opt_mgr.AddOpt("--sim", "none", "str", "use simulation and specify its setting"); + opt_mgr.AddOpt("-v", to_string(Params.iVerbosity), "num", "specify verbosity level"); + opt_mgr.AddOpt("--seq", to_string(Params.nSeqLookBack), "num", "specify the number of look-back frames (0 = no sequential UIF)"); + opt_mgr.AddOpt("--profile", "no", "", "dump time distribution"); + opt_mgr.AddOpt("--pba_uif", Params.fPbaUif ? "yes" : "no", "", "toggle using proof-based refinement for UIF pairs"); + opt_mgr.AddOpt("--lazysim", Params.fLazySim ? "yes" : "no", "", "toggle applying UIF pairs based on simulation"); + opt_mgr.AddOpt("--pbasim", Params.fPbaSim ? "yes" : "no", "", "toggle combining pba and sim"); + opt_mgr.AddOpt("--pbacex", Params.fPbaCex ? "yes" : "no", "", "toggle combining pba and cex"); + opt_mgr.AddOpt("--satmin", Params.fSatMin ? "yes" : "no", "", "toggle using sat-min in pba"); + opt_mgr.AddOpt("--cbawb", Params.fCbaWb ? "yes" : "no", "", "toggle using cex-based refinement for white boxing"); + opt_mgr.AddOpt("--grey", Params.fGrey ? "yes" : "no", "", "toggle using grey-box constraints"); + opt_mgr.AddOpt("--grey2", to_string(Params.nGrey), "float", "specify the greyness threshold"); + opt_mgr.AddOpt("--allwb", Params.fAllWb ? "yes" : "no", "", "start with all operators white-boxed (no initial abstraction)"); + opt_mgr.AddOpt("--crossonly", Params.fCrossOnly ? "yes" : "no", "", "allow UIF pairs only across LHS/RHS cones of the miter"); + opt_mgr.AddOpt("--crossstats", "no", "", "print multiplier counts in LHS/RHS/shared cones and exit"); + opt_mgr.AddOpt("--dump", "none", "str", "specify file name"); + opt_mgr.AddOpt("--dump-log", "none", "str", "write status log"); + opt_mgr.AddOpt("--dump-first-aig", "none", "str", "dump first internal bit-blasted AIG and exit"); + opt_mgr.AddOpt("--dump-abs", "none", "str", "specify file name"); + opt_mgr.AddOpt("--par", "none", "str", "use parallel solvers"); + opt_mgr.AddOpt("--solver", "none", "str", "external solver command line"); + opt_mgr.AddOpt("--dump_states", "none", "str", "specify the name for the states file"); + opt_mgr.AddOpt("--read_states", "none", "str", "specify the name for the states file"); + opt_mgr.AddOpt("--sp", Params.fSuper_prove ? "yes" : "no", "", "toggle using super_prove"); + opt_mgr.AddOpt("--simp", Params.fSimple ? "yes" : "no", "", "toggle using simple (prove)"); + opt_mgr.AddOpt("--syn", Params.fSyn ? "yes" : "no", "", "toggle using simple synthesis"); + opt_mgr.AddOpt("--pth", Params.fPthread ? "yes" : "no", "", "toggle using pthreads"); + opt_mgr.AddOpt("--onewb", to_string(Params.iOneWb), "int", "specify the mode for one-white-boxing"); + opt_mgr.AddOpt("--initallpairs", to_string(Params.nInitAllPairsLimit), "num", "pre-seed all compatible UIF pairs when #ops <= this limit (0=off)"); + opt_mgr.AddOpt("--initnear", to_string(Params.nInitNearMults), "num", "pre-seed UIF pairs among up to this many multipliers closest to output"); + opt_mgr.AddOpt("--timeout", to_string(Params.nTimeout), "num", "specify the timeout (sec)"); + opt_mgr.AddOpt("--exp", to_string(Params.iExp), "int", "specify the exp mode"); + opt_mgr.AddOpt("--miter", "yes", "", "toggle mitering the problem"); + opt_mgr.AddOpt("--under", "-1", "num", "try under-approximation with the given size"); +} +static void Ufar_ApplyOptions( OptMgr & opt_mgr, UFAR::UfarManager::Params & Params, set & set_op_types, string & firstAigDumpFile, string & dumpLogFile, int & fNeedMiter, int & fCrossStats, int & UnderSize ) +{ + firstAigDumpFile = ""; + dumpLogFile = opt_mgr["--dump-log"] ? opt_mgr.GetOptVal("--dump-log") : ""; + fNeedMiter = !opt_mgr["--miter"]; + fCrossStats = opt_mgr["--crossstats"] ? 1 : 0; + UnderSize = opt_mgr["--under"] ? stoi(opt_mgr.GetOptVal("--under")) : -1; + + if(opt_mgr["--norm"]) + Params.fNorm ^= 1; + if(opt_mgr["--cexmin"]) + Params.fCexMin ^= 1; + if(opt_mgr["--pba_uif"]) + Params.fPbaUif ^= 1; + if(opt_mgr["--pbasim"]) + Params.fPbaSim ^= 1; + if(opt_mgr["--pbacex"]) + Params.fPbaCex ^= 1; + if(opt_mgr["--satmin"]) + Params.fSatMin ^= 1; + if(opt_mgr["--cbawb"]) + Params.fCbaWb ^= 1; + if(opt_mgr["--grey"]) + Params.fGrey ^= 1; + if(opt_mgr["--allwb"]) + Params.fAllWb ^= 1; + if(opt_mgr["--crossonly"]) + Params.fCrossOnly ^= 1; + if(opt_mgr["--grey2"]) + Params.nGrey = stof(opt_mgr.GetOptVal("--grey2")); + if(opt_mgr["--sp"]) + Params.fSuper_prove ^= 1; + if(opt_mgr["--simp"]) + Params.fSimple ^= 1; + if(opt_mgr["--syn"]) + Params.fSyn ^= 1; + if(opt_mgr["--pth"]) + Params.fPthread ^= 1; + if(opt_mgr["--onewb"]) + Params.iOneWb = stoi(opt_mgr.GetOptVal("--onewb")); + if(opt_mgr["--initallpairs"]) + Params.nInitAllPairsLimit = stoi(opt_mgr.GetOptVal("--initallpairs")); + if(opt_mgr["--initnear"]) + Params.nInitNearMults = stoi(opt_mgr.GetOptVal("--initnear")); + if(opt_mgr["--exp"]) + Params.iExp = stoi(opt_mgr.GetOptVal("--exp")); + if(opt_mgr["--par"]) + Params.parSetting = opt_mgr.GetOptVal("--par"); + if(opt_mgr["--solver"]) + Params.solverSetting = opt_mgr.GetOptVal("--solver"); + if(opt_mgr["--sim"]) + Params.simSetting = opt_mgr.GetOptVal("--sim"); + if(opt_mgr["--dump_states"]) { + smatch sub_match; + string option = opt_mgr.GetOptVal("--dump_states"); + if(regex_search(option, sub_match, regex(R"(/?(\w+\.v)$)"))) + Params.fileStatesOut = sub_match[1].str(); + else + Params.fileStatesOut = opt_mgr.GetOptVal("--dump_states"); + } + if(opt_mgr["--read_states"]) + Params.fileStatesIn = opt_mgr.GetOptVal("--read_states"); + if(opt_mgr["--lazysim"]) + Params.fLazySim ^= 1; + if(opt_mgr["-v"]) + Params.iVerbosity = stoi(opt_mgr.GetOptVal("-v")); + if(opt_mgr["--timeout"]) + Params.nTimeout = stoi(opt_mgr.GetOptVal("--timeout")); + if(opt_mgr["--seq"]) + Params.nSeqLookBack = stoi(opt_mgr.GetOptVal("--seq")); + if(opt_mgr["--dump-abs"]) { + smatch sub_match; + string option = opt_mgr.GetOptVal("--dump-abs"); + if(regex_search(option, sub_match, regex(R"(/?(\w+)\.v$)"))) + Params.fileAbs = sub_match[1].str(); + else + Params.fileAbs = opt_mgr.GetOptVal("--dump-abs"); + } + if(opt_mgr["--dump"]) { + smatch sub_match; + string option = opt_mgr.GetOptVal("--dump"); + if(regex_search(option, sub_match, regex(R"(/?(\w+\.v)$)"))) + Params.fileName = sub_match[1].str(); + else + Params.fileName = opt_mgr.GetOptVal("--dump"); + } + if ( opt_mgr["--dump-first-aig"] ) + firstAigDumpFile = opt_mgr.GetOptVal("--dump-first-aig"); + set_op_types.insert(WLC_OBJ_ARI_MULTI); + if (opt_mgr["--adder"]) + set_op_types.insert(WLC_OBJ_ARI_ADD); +} +static bool Ufar_TokenizeArgs( const char * pArgs, vector & Tokens ) +{ + string Cur; + char Quote = 0; + if ( pArgs == NULL ) + return true; + for ( ; *pArgs; ++pArgs ) + { + unsigned char c = (unsigned char)*pArgs; + if ( Quote ) + { + if ( c == (unsigned char)Quote ) + Quote = 0; + else if ( c == '\\' && pArgs[1] ) + Cur += *++pArgs; + else + Cur += (char)c; + continue; + } + if ( c == '"' || c == '\'' ) + { + Quote = (char)c; + continue; + } + if ( isspace(c) ) + { + if ( !Cur.empty() ) + { + Tokens.push_back( Cur ); + Cur.clear(); + } + continue; + } + if ( c == '\\' && pArgs[1] ) + { + Cur += *++pArgs; + continue; + } + Cur += (char)c; + } + if ( Quote ) + return false; + if ( !Cur.empty() ) + Tokens.push_back( Cur ); + return true; +} + +static inline void Ufar_TrimString( string & s ) +{ + while ( !s.empty() && isspace((unsigned char)s.front()) ) + s.erase( s.begin() ); + while ( !s.empty() && isspace((unsigned char)s.back()) ) + s.pop_back(); +} + +static bool Ufar_ExtractSolverArg( const char * pArgs, string & ArgsWithoutSolver, string & SolverArg ) +{ + string Args = pArgs ? pArgs : ""; + size_t i = 0, n = Args.size(); + ArgsWithoutSolver = Args; + SolverArg.clear(); + while ( i < n ) + { + while ( i < n && isspace((unsigned char)Args[i]) ) + i++; + if ( i == n ) + break; + size_t TokenStart = i; + char Quote = 0; + string Token; + while ( i < n ) + { + unsigned char c = (unsigned char)Args[i]; + if ( Quote ) + { + if ( c == (unsigned char)Quote ) + Quote = 0; + else if ( c == '\\' && i + 1 < n ) + Token += Args[++i]; + else + Token += (char)c; + i++; + continue; + } + if ( c == '"' || c == '\'' ) + { + Quote = (char)c; + i++; + continue; + } + if ( isspace(c) ) + break; + if ( c == '\\' && i + 1 < n ) + { + Token += Args[++i]; + i++; + continue; + } + Token += (char)c; + i++; + } + if ( Token == "--solver" ) + { + size_t ValueStart = i; + while ( ValueStart < n && isspace((unsigned char)Args[ValueStart]) ) + ValueStart++; + if ( ValueStart == n ) + return false; + string Prefix = Args.substr( 0, TokenStart ); + string Suffix; + if ( Args[ValueStart] == '"' || Args[ValueStart] == '\'' ) + { + char ValueQuote = Args[ValueStart++]; + size_t k = ValueStart; + while ( k < n ) + { + unsigned char c = (unsigned char)Args[k]; + if ( c == (unsigned char)ValueQuote ) + { + k++; + break; + } + if ( c == '\\' && k + 1 < n ) + SolverArg += Args[++k]; + else + SolverArg += (char)c; + k++; + } + Suffix = Args.substr( k ); + } + else + { + SolverArg = Args.substr( ValueStart ); + } + Ufar_TrimString( SolverArg ); + ArgsWithoutSolver = Prefix + Suffix; + Ufar_TrimString( ArgsWithoutSolver ); + return !SolverArg.empty(); + } + while ( i < n && isspace((unsigned char)Args[i]) ) + i++; + } + return false; +} void Ufar_Init(Abc_Frame_t *pAbc) @@ -51,39 +419,169 @@ void Ufar_Init(Abc_Frame_t *pAbc) //Cmd_CommandAdd( pAbc, "Word level Prove", "%%miter", Abc_CommandCreateMiter, 0 ); } -int Ufar_ProveWithTimeout( Wlc_Ntk_t * pNtk, int nTimeOut, int fVerbose, int (*pFuncStop)(int), int RunId ) +int Ufar_ProveWithTimeout( Wlc_Ntk_t * pNtk, int nTimeOut, int fVerbose, int (*pFuncStop)(int), int RunId, const char * pArgs ) { UFAR::UfarManager manager; timeval t1; + vector Tokens; + vector Argv; set set_op_types; - Wlc_Ntk_t * pUse = pNtk; + string ArgsWithoutSolver, SolverArg; + string firstAigDumpFile, dumpLogFile; + string statusName; + int fNeedMiter = 1, fCrossStats = 0, UnderSize = -1; + Wlc_Ntk_t * pUse = pNtk, * pNew = NULL; int RetValue = -1; if ( pNtk == NULL ) return -1; - if ( Wlc_NtkPoNum(pUse) == 2 ) + Ufar_SetDefaultParams( manager.params, nTimeOut, fVerbose, pFuncStop, RunId ); + if ( pArgs && pArgs[0] ) + { + const char * pParseArgs = pArgs; + if ( Ufar_ExtractSolverArg(pArgs, ArgsWithoutSolver, SolverArg) ) + pParseArgs = ArgsWithoutSolver.c_str(); + OptMgr opt_mgr("%ufar"); + Ufar_AddOptions( opt_mgr, manager.params ); + if ( !Ufar_TokenizeArgs(pParseArgs, Tokens) ) + { + cout << "Cannot parse internal %ufar option string." << endl; + return -1; + } + Argv.reserve( Tokens.size() + 1 ); + Argv.push_back( (char *)"%ufar" ); + for ( size_t i = 0; i < Tokens.size(); i++ ) + Argv.push_back( (char *)Tokens[i].c_str() ); + if ( !opt_mgr.Parse((int)Argv.size(), Argv.data()) ) + { + opt_mgr.PrintUsage(); + return -1; + } + Ufar_ApplyOptions( opt_mgr, manager.params, set_op_types, firstAigDumpFile, dumpLogFile, fNeedMiter, fCrossStats, UnderSize ); + if ( !SolverArg.empty() ) + manager.params.solverSetting = SolverArg; + } + else + set_op_types.insert( WLC_OBJ_ARI_MULTI ); + Ufar_StopScope_t StopScope( manager.params.pFuncStop, (int)manager.params.nTimeout ); + manager.params.pFuncStop = Ufar_StopWithTimeout; + if ( fNeedMiter ) { - pUse = UFAR::CreateMiter( pUse, 0 ); - if ( pUse == NULL ) + if ( Wlc_NtkPoNum(pUse) == 2 ) + { + pNew = UFAR::CreateMiter( pUse, 0 ); + if ( pUse != pNtk ) + Wlc_NtkFree( pUse ); + pUse = pNew; + if ( pUse == NULL ) + return -1; + } + else if ( Wlc_NtkPoNum(pUse) != 1 ) + { return -1; + } } else if ( Wlc_NtkPoNum(pUse) != 1 ) return -1; - set_op_types.insert( WLC_OBJ_ARI_MULTI ); + statusName = Ufar_GetStatusName( pUse ); + if ( manager.params.fNorm ) + { + pNew = UFAR::NormalizeDataTypes( pUse, set_op_types, true ); + if ( pUse != pNtk ) + Wlc_NtkFree( pUse ); + pUse = pNew; + } + if ( fCrossStats ) + { + Wlc_Ntk_t * pCur = pUse; + if ( Wlc_NtkPoNum(pCur) != 2 ) + { + cout << "CrossStats requires dual outputs before mitering.\n"; + if ( pUse != pNtk ) + Wlc_NtkFree( pUse ); + return -1; + } + int nObjs = Wlc_NtkObjNumMax(pCur); + vector vConeL(nObjs, 0), vConeR(nObjs, 0); + auto mark_cone = [&]( int iStart, vector& vMark ) + { + if ( iStart < 0 || iStart >= nObjs ) + return; + vector stack(1, iStart); + while ( !stack.empty() ) + { + int iObj = stack.back(); + stack.pop_back(); + if ( iObj < 0 || iObj >= nObjs || vMark[iObj] ) + continue; + vMark[iObj] = 1; + Wlc_Obj_t * pObjT = Wlc_NtkObj(pCur, iObj); + if ( pObjT->Type == WLC_OBJ_FO ) + { + Wlc_Obj_t * pFi = Wlc_ObjFo2Fi(pCur, pObjT); + stack.push_back( Wlc_ObjId(pCur, pFi) ); + } + int iFanin, k; + Wlc_ObjForEachFanin( pObjT, iFanin, k ) + stack.push_back(iFanin); + } + }; + int iRootL = Wlc_ObjFaninId0( Wlc_NtkPo(pCur, 0) ); + int iRootR = Wlc_ObjFaninId0( Wlc_NtkPo(pCur, 1) ); + mark_cone(iRootL, vConeL); + mark_cone(iRootR, vConeR); + + int nL = 0, nR = 0, nB = 0, nN = 0; + Wlc_Obj_t * pObjT; int iObj; + Wlc_NtkForEachObj( pCur, pObjT, iObj ) + { + if ( pObjT->Type != WLC_OBJ_ARI_MULTI ) + continue; + bool fL = vConeL[iObj] != 0; + bool fR = vConeR[iObj] != 0; + if ( fL && fR ) nB++; + else if ( fL ) nL++; + else if ( fR ) nR++; + else nN++; + } + cout << "UIF_PROVE : CrossStats: L=" << nL + << " R=" << nR + << " BOTH=" << nB + << " NONE=" << nN + << " TOTAL=" << (nL + nR + nB + nN) << endl; + if ( pUse != pNtk ) + Wlc_NtkFree( pUse ); + return -1; + } if ( !UFAR::HasOperator( pUse, set_op_types ) ) { if ( pUse != pNtk ) Wlc_NtkFree( pUse ); return -1; } - manager.params = UFAR::UfarManager::Params(); - manager.params.RunId = RunId; - manager.params.pFuncStop = pFuncStop; - if ( nTimeOut > 0 ) - manager.params.nTimeout = nTimeOut; - manager.params.iVerbosity = fVerbose ? 1 : 0; + if ( UnderSize >= 0 ) + { + pNew = UFAR::MakeUnderApprox( pUse, UnderSize ); + if ( pUse != pNtk ) + Wlc_NtkFree( pUse ); + pUse = pNew; + pNew = UFAR::MakeUnderApprox2( pUse, set_op_types, UnderSize ); + if ( pUse != pNtk ) + Wlc_NtkFree( pUse ); + pUse = pNew; + } + if ( !firstAigDumpFile.empty() && firstAigDumpFile != "none" ) + { + Gia_Man_t * pGia = UFAR::BitBlast( pUse ); + Gia_AigerWriteSimple( pGia, (char *)firstAigDumpFile.c_str() ); + Gia_ManStop( pGia ); + if ( pUse != pNtk ) + Wlc_NtkFree( pUse ); + return -1; + } gettimeofday( &t1, NULL ); manager.Initialize( pUse, set_op_types ); RetValue = manager.PerformUIFProve( t1 ); + Ufar_DumpStatusLog( dumpLogFile, RetValue, statusName ); if ( pUse != pNtk ) Wlc_NtkFree( pUse ); return RetValue; @@ -127,138 +625,22 @@ static int Abc_CommandProveUsingUif( Abc_Frame_t * pAbc, int argc, char ** argv ufar_manager.params = UFAR::UfarManager::Params(); OptMgr opt_mgr(argv[0]); - opt_mgr.AddOpt("--norm", ufar_manager.params.fNorm ? "yes" : "no", "", "toggle using data type normalization"); - opt_mgr.AddOpt("--adder", "no", "", "toggle including adders"); - opt_mgr.AddOpt("--cexmin", ufar_manager.params.fCexMin ? "yes" : "no", "", "toggle using CEX minimization"); - opt_mgr.AddOpt("--sim", "none", "str", "use simulation and specify its setting"); - opt_mgr.AddOpt("-v", to_string(ufar_manager.params.iVerbosity), "num", "specify verbosity level"); - opt_mgr.AddOpt("--seq", to_string(ufar_manager.params.nSeqLookBack), "num", "specify the number of look-back frames (0 = no sequential UIF)"); - opt_mgr.AddOpt("--profile", "no", "", "dump time distribution"); - opt_mgr.AddOpt("--pba_uif", ufar_manager.params.fPbaUif ? "yes" : "no", "", "toggle using proof-based refinement for UIF pairs"); - opt_mgr.AddOpt("--lazysim", ufar_manager.params.fLazySim ? "yes" : "no", "", "toggle applying UIF pairs based on simulation"); - opt_mgr.AddOpt("--pbasim", ufar_manager.params.fPbaSim ? "yes" : "no", "", "toggle combining pba and sim"); - opt_mgr.AddOpt("--pbacex", ufar_manager.params.fPbaCex ? "yes" : "no", "", "toggle combining pba and cex"); - opt_mgr.AddOpt("--satmin", ufar_manager.params.fSatMin ? "yes" : "no", "", "toggle using sat-min in pba"); - opt_mgr.AddOpt("--cbawb", ufar_manager.params.fCbaWb ? "yes" : "no", "", "toggle using cex-based refinement for white boxing"); - opt_mgr.AddOpt("--grey", ufar_manager.params.fGrey ? "yes" : "no", "", "toggle using grey-box constraints"); - opt_mgr.AddOpt("--grey2", to_string(ufar_manager.params.nGrey), "float", "specify the greyness threshold"); - opt_mgr.AddOpt("--allwb", ufar_manager.params.fAllWb ? "yes" : "no", "", "start with all operators white-boxed (no initial abstraction)"); - opt_mgr.AddOpt("--crossonly", ufar_manager.params.fCrossOnly ? "yes" : "no", "", "allow UIF pairs only across LHS/RHS cones of the miter"); - opt_mgr.AddOpt("--crossstats", "no", "", "print multiplier counts in LHS/RHS/shared cones and exit"); - opt_mgr.AddOpt("--dump", "none", "str", "specify file name"); - opt_mgr.AddOpt("--dump-first-aig", "none", "str", "dump first internal bit-blasted AIG and exit"); - opt_mgr.AddOpt("--dump-abs", "none", "str", "specify file name"); - opt_mgr.AddOpt("--par", "none", "str", "use parallel solvers"); - opt_mgr.AddOpt("--solver", "none", "str", "external solver command line"); - opt_mgr.AddOpt("--dump_states", "none", "str", "specify the name for the states file"); - opt_mgr.AddOpt("--read_states", "none", "str", "specify the name for the states file"); - opt_mgr.AddOpt("--sp", ufar_manager.params.fSuper_prove ? "yes" : "no", "", "toggle using super_prove"); - opt_mgr.AddOpt("--simp", ufar_manager.params.fSimple ? "yes" : "no", "", "toggle using simple (prove)"); - opt_mgr.AddOpt("--syn", ufar_manager.params.fSyn ? "yes" : "no", "", "toggle using simple synthesis"); - opt_mgr.AddOpt("--pth", ufar_manager.params.fPthread ? "yes" : "no", "", "toggle using pthreads"); - opt_mgr.AddOpt("--onewb", to_string(ufar_manager.params.iOneWb), "int", "specify the mode for one-white-boxing"); - opt_mgr.AddOpt("--initallpairs", to_string(ufar_manager.params.nInitAllPairsLimit), "num", "pre-seed all compatible UIF pairs when #ops <= this limit (0=off)"); - opt_mgr.AddOpt("--initnear", to_string(ufar_manager.params.nInitNearMults), "num", "pre-seed UIF pairs among up to this many multipliers closest to output"); - opt_mgr.AddOpt("--timeout", to_string(ufar_manager.params.nTimeout), "num", "specify the timeout (sec)"); - opt_mgr.AddOpt("--exp", to_string(ufar_manager.params.iExp), "int", "specify the exp mode"); - opt_mgr.AddOpt("--miter", "yes", "", "toggle mitering the problem"); - opt_mgr.AddOpt("--under", "-1", "num", "try under-approximation with the given size"); + set set_op_types; + string firstAigDumpFile = ""; + string dumpLogFile = ""; + int fNeedMiter = 1, fCrossStats = 0, UnderSize = -1; + Ufar_AddOptions( opt_mgr, ufar_manager.params ); if(!opt_mgr.Parse(argc, argv)) { opt_mgr.PrintUsage(); cout << "\n This command was developed by Yen-Sheng Ho at UC Berkeley in 2015.\n"; cout << " https://people.eecs.berkeley.edu/~alanmi/publications/2016/fmcad16_uif.pdf \n"; return 0; } - - if(opt_mgr["--norm"]) - ufar_manager.params.fNorm ^= 1; - if(opt_mgr["--cexmin"]) - ufar_manager.params.fCexMin ^= 1; - if(opt_mgr["--pba_uif"]) - ufar_manager.params.fPbaUif ^= 1; - if(opt_mgr["--pbasim"]) - ufar_manager.params.fPbaSim ^= 1; - if(opt_mgr["--pbacex"]) - ufar_manager.params.fPbaCex ^= 1; - if(opt_mgr["--satmin"]) - ufar_manager.params.fSatMin ^= 1; - if(opt_mgr["--cbawb"]) - ufar_manager.params.fCbaWb ^= 1; - if(opt_mgr["--grey"]) - ufar_manager.params.fGrey ^= 1; - if(opt_mgr["--allwb"]) - ufar_manager.params.fAllWb ^= 1; - if(opt_mgr["--crossonly"]) - ufar_manager.params.fCrossOnly ^= 1; - if(opt_mgr["--grey2"]) - ufar_manager.params.nGrey = stof(opt_mgr.GetOptVal("--grey2")); - if(opt_mgr["--sp"]) - ufar_manager.params.fSuper_prove ^= 1; - if(opt_mgr["--simp"]) - ufar_manager.params.fSimple ^= 1; - if(opt_mgr["--syn"]) - ufar_manager.params.fSyn ^= 1; - if(opt_mgr["--pth"]) - ufar_manager.params.fPthread ^= 1; - if(opt_mgr["--onewb"]) - ufar_manager.params.iOneWb = stoi(opt_mgr.GetOptVal("--onewb")); - if(opt_mgr["--initallpairs"]) - ufar_manager.params.nInitAllPairsLimit = stoi(opt_mgr.GetOptVal("--initallpairs")); - if(opt_mgr["--initnear"]) - ufar_manager.params.nInitNearMults = stoi(opt_mgr.GetOptVal("--initnear")); - if(opt_mgr["--exp"]) - ufar_manager.params.iExp = stoi(opt_mgr.GetOptVal("--exp")); - if(opt_mgr["--par"]) - ufar_manager.params.parSetting = opt_mgr.GetOptVal("--par"); - if(opt_mgr["--solver"]) - ufar_manager.params.solverSetting = opt_mgr.GetOptVal("--solver"); - if(opt_mgr["--sim"]) - ufar_manager.params.simSetting = opt_mgr.GetOptVal("--sim"); - if(opt_mgr["--dump_states"]) { - smatch sub_match; - string option = opt_mgr.GetOptVal("--dump_states"); - if(regex_search(option, sub_match, regex(R"(/?(\w+\.v)$)"))) - ufar_manager.params.fileStatesOut = sub_match[1].str(); - else - ufar_manager.params.fileStatesOut = opt_mgr.GetOptVal("--dump_states"); - } - if(opt_mgr["--read_states"]) - ufar_manager.params.fileStatesIn = opt_mgr.GetOptVal("--read_states"); - if(opt_mgr["--lazysim"]) - ufar_manager.params.fLazySim ^= 1; - if(opt_mgr["-v"]) - ufar_manager.params.iVerbosity = stoi(opt_mgr.GetOptVal("-v")); - if(opt_mgr["--timeout"]) - ufar_manager.params.nTimeout = stoi(opt_mgr.GetOptVal("--timeout")); - if(opt_mgr["--seq"]) - ufar_manager.params.nSeqLookBack = stoi(opt_mgr.GetOptVal("--seq")); - if(opt_mgr["--dump-abs"]) { - smatch sub_match; - string option = opt_mgr.GetOptVal("--dump-abs"); - if(regex_search(option, sub_match, regex(R"(/?(\w+)\.v$)"))) - ufar_manager.params.fileAbs = sub_match[1].str(); - else - ufar_manager.params.fileAbs = opt_mgr.GetOptVal("--dump-abs"); - } - if(opt_mgr["--dump"]) { - smatch sub_match; - string option = opt_mgr.GetOptVal("--dump"); - if(regex_search(option, sub_match, regex(R"(/?(\w+\.v)$)"))) - ufar_manager.params.fileName = sub_match[1].str(); - else - ufar_manager.params.fileName = opt_mgr.GetOptVal("--dump"); - } - string firstAigDumpFile = ""; - if ( opt_mgr["--dump-first-aig"] ) - firstAigDumpFile = opt_mgr.GetOptVal("--dump-first-aig"); + Ufar_ApplyOptions( opt_mgr, ufar_manager.params, set_op_types, firstAigDumpFile, dumpLogFile, fNeedMiter, fCrossStats, UnderSize ); // ufar_manager.DumpParams(); LogT::prefix = "UIF_PROVE"; - - set set_op_types; - set_op_types.insert(WLC_OBJ_ARI_MULTI); - if (opt_mgr["--adder"]) - set_op_types.insert(WLC_OBJ_ARI_ADD); + string statusName = Ufar_GetStatusName( Wlc_AbcGetNtk(pAbc) ); if (!UFAR::HasOperator(Wlc_AbcGetNtk(pAbc), set_op_types)) { cout << "There is no operator for UIF.\n"; return 0; @@ -268,7 +650,7 @@ static int Abc_CommandProveUsingUif( Abc_Frame_t * pAbc, int argc, char ** argv timeval t1, t2; gettimeofday(&t1, NULL); - if (!opt_mgr["--miter"]) { + if (fNeedMiter) { if (Wlc_NtkPoNum(Wlc_AbcGetNtk(pAbc)) != 2) { cout << "The current design doesn't have dual outputs.\n"; return 0; @@ -282,7 +664,7 @@ static int Abc_CommandProveUsingUif( Abc_Frame_t * pAbc, int argc, char ** argv Wlc_AbcUpdateNtk(pAbc, pNew); } - if ( opt_mgr["--crossstats"] ) + if ( fCrossStats ) { Wlc_Ntk_t * pCur = Wlc_AbcGetNtk(pAbc); if ( Wlc_NtkPoNum(pCur) != 2 ) @@ -344,10 +726,10 @@ static int Abc_CommandProveUsingUif( Abc_Frame_t * pAbc, int argc, char ** argv return 0; } - if (opt_mgr["--under"]) { - pNew = UFAR::MakeUnderApprox(Wlc_AbcGetNtk(pAbc), stoi(opt_mgr.GetOptVal("--under"))); + if ( UnderSize >= 0 ) { + pNew = UFAR::MakeUnderApprox(Wlc_AbcGetNtk(pAbc), UnderSize); Wlc_AbcUpdateNtk(pAbc, pNew); - pNew = UFAR::MakeUnderApprox2(Wlc_AbcGetNtk(pAbc), set_op_types, stoi(opt_mgr.GetOptVal("--under"))); + pNew = UFAR::MakeUnderApprox2(Wlc_AbcGetNtk(pAbc), set_op_types, UnderSize); Wlc_AbcUpdateNtk(pAbc, pNew); Wlc_WriteVer(Wlc_AbcGetNtk(pAbc), "UND.v", 0, 0); } @@ -372,6 +754,7 @@ static int Abc_CommandProveUsingUif( Abc_Frame_t * pAbc, int argc, char ** argv } else { LOG(0) << "Undecided by UIF."; } + Ufar_DumpStatusLog( dumpLogFile, ret, statusName ); gettimeofday(&t2, NULL); unsigned tTotal = elapsed_time_usec(t1, t2); diff --git a/src/opt/ufar/UfarCmd.h b/src/opt/ufar/UfarCmd.h index 52dfc8bb85..b44863ca33 100755 --- a/src/opt/ufar/UfarCmd.h +++ b/src/opt/ufar/UfarCmd.h @@ -15,7 +15,7 @@ ABC_NAMESPACE_HEADER_START void Ufar_Init(Abc_Frame_t *pAbc); typedef struct Wlc_Ntk_t_ Wlc_Ntk_t; -extern int Ufar_ProveWithTimeout( Wlc_Ntk_t * pNtk, int nTimeOut, int fVerbose, int (*pFuncStop)(int), int RunId ); +extern int Ufar_ProveWithTimeout( Wlc_Ntk_t * pNtk, int nTimeOut, int fVerbose, int (*pFuncStop)(int), int RunId, const char * pArgs ); ABC_NAMESPACE_HEADER_END diff --git a/src/opt/untk/NtkNtk.cpp b/src/opt/untk/NtkNtk.cpp index b0cb5bd15d..6fc3700b31 100755 --- a/src/opt/untk/NtkNtk.cpp +++ b/src/opt/untk/NtkNtk.cpp @@ -805,7 +805,8 @@ Wlc_Ntk_t * AddConstFlops( Wlc_Ntk_t * pNtk, const set& types ) Wlc_Ntk_t * p = Wlc_NtkDupDfsSimple(pNtk); Wlc_NtkCleanCopy( p ); int nOrigObjNum = Wlc_NtkObjNumMax(p); - Wlc_NtkTransferNames( p, pNtk ); + if ( !Wlc_NtkHasNameId(p) && Wlc_NtkHasNameId(pNtk) ) + Wlc_NtkTransferNames( p, pNtk ); Wlc_Obj_t * pObj; int i, iObjConst0; @@ -872,7 +873,8 @@ Wlc_Ntk_t * AddConstFlops( Wlc_Ntk_t * pNtk, const set& types ) ModifyMarkedNodes(p, nOrigObjNum, create_ff_and_mux); Wlc_Ntk_t * pNew = Wlc_NtkDupDfsSimple( p ); - Wlc_NtkTransferNames( pNew, p ); + if ( !Wlc_NtkHasNameId(pNew) && Wlc_NtkHasNameId(p) ) + Wlc_NtkTransferNames( pNew, p ); Wlc_NtkFree( p ); @@ -1058,7 +1060,8 @@ Wlc_Ntk_t * NormalizeDataTypes(Wlc_Ntk_t * p, const set& types, bool f Wlc_Ntk_t *pNtk, *pNew; pNtk = Wlc_NtkDupDfsSimple(p); - Wlc_NtkTransferNames( pNtk, p ); + if ( !Wlc_NtkHasNameId(pNtk) && Wlc_NtkHasNameId(p) ) + Wlc_NtkTransferNames( pNtk, p ); Wlc_Obj_t *pObj; int i, iFanin0, iFanin1; @@ -1117,7 +1120,8 @@ Wlc_Ntk_t * NormalizeDataTypes(Wlc_Ntk_t * p, const set& types, bool f Vec_IntFree(vFanins); pNew = Wlc_NtkDupDfsSimple(pNtk); - Wlc_NtkTransferNames( pNew, pNtk ); + if ( !Wlc_NtkHasNameId(pNew) && Wlc_NtkHasNameId(pNtk) ) + Wlc_NtkTransferNames( pNew, pNtk ); Wlc_NtkFree(pNtk); return pNew; @@ -1266,14 +1270,22 @@ static inline int run_external_solver_on_aig( Abc_Ntk_t * pAbcNtk, const string& Io_Write( pAbcNtk, (char *)pAigFile, IO_FILE_AIGER ); std::remove( "status.txt" ); std::remove( "log.txt" ); - string command = solverCmd; - if ( command.find(pAigFile) == string::npos ) - command += string(" ") + pAigFile; + string solverCall = solverCmd; + string command; + if ( solverCall.find(pAigFile) == string::npos ) + solverCall += string(" ") + pAigFile; if ( nRuntimeLimitSec > 0 ) - command += " " + to_string(nRuntimeLimitSec); + solverCall += " " + to_string(nRuntimeLimitSec); + command = solverCall; + if ( nRuntimeLimitSec > 0 ) + command = "timeout " + to_string(nRuntimeLimitSec) + " " + command; command += " > log.txt 2>&1"; LOG(1) << "UFAR external solver: launching command instead of PDR: " << command; +#ifdef __wasm + int res = -1; +#else int res = system( command.c_str() ); +#endif std::remove( pAigFile ); return res; } diff --git a/src/proof/abs/absGla.c b/src/proof/abs/absGla.c index 9f1a8a31e9..72863fe731 100644 --- a/src/proof/abs/absGla.c +++ b/src/proof/abs/absGla.c @@ -1847,7 +1847,8 @@ int Gia_ManPerformGla( Gia_Man_t * pAig, Abs_Par_t * pPars ) } } finish: - Prf_ManStopP( &p->pSat->pPrf2 ); + if ( p->pSat ) + Prf_ManStopP( &p->pSat->pPrf2 ); // cancel old one if it is proving if ( iFrameTryToProve >= 0 ) Gia_GlaProveCancel( pPars->fVerbose ); @@ -1860,9 +1861,9 @@ int Gia_ManPerformGla( Gia_Man_t * pAig, Abs_Par_t * pPars ) { Vec_IntFreeP( &pAig->vGateClasses ); pAig->vGateClasses = Ga2_ManAbsTranslate( p ); - if ( p->pPars->nTimeOut && Abc_Clock() >= p->pSat->nRuntimeLimit ) + if ( p->pSat && p->pPars->nTimeOut && Abc_Clock() >= p->pSat->nRuntimeLimit ) Abc_Print( 1, "GLA reached timeout %d sec in frame %d with a %d-stable abstraction. ", p->pPars->nTimeOut, p->pPars->iFrameProved+1, p->pPars->nFramesNoChange ); - else if ( pPars->nConfLimit && sat_solver2_nconflicts(p->pSat) >= pPars->nConfLimit ) + else if ( p->pSat && pPars->nConfLimit && sat_solver2_nconflicts(p->pSat) >= pPars->nConfLimit ) Abc_Print( 1, "GLA exceeded %d conflicts in frame %d with a %d-stable abstraction. ", pPars->nConfLimit, p->pPars->iFrameProved+1, p->pPars->nFramesNoChange ); else if ( pPars->nRatioMin2 && Vec_IntSize(p->vAbs) >= p->nMarked * pPars->nRatioMin2 / 100 ) Abc_Print( 1, "GLA found that the size of abstraction exceeds %d %% in frame %d during refinement. ", pPars->nRatioMin2, p->pPars->iFrameProved+1 ); @@ -1893,7 +1894,8 @@ int Gia_ManPerformGla( Gia_Man_t * pAig, Abs_Par_t * pPars ) ABC_PRTP( "Runtime: Refinement ", p->timeCex, Abc_Clock() - clk ); ABC_PRTP( "Runtime: Other ", p->timeOther, Abc_Clock() - clk ); ABC_PRTP( "Runtime: TOTAL ", Abc_Clock() - clk, Abc_Clock() - clk ); - Ga2_ManReportMemory( p ); + if ( p->pSat ) + Ga2_ManReportMemory( p ); } // Ga2_ManDumpStats( p->pGia, p->pPars, p->pSat, p->pPars->iFrameProved, 0 ); Ga2_ManStop( p ); diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h index e360bb99da..6c75447a09 100644 --- a/src/proof/cec/cec.h +++ b/src/proof/cec/cec.h @@ -167,6 +167,10 @@ struct Cec_ParCor_t_ // int fFirstStop; // stop on the first sat output int fUseSmartCnf; // use smart CNF computation int fStopWhenGone; // quit when PO is not a candidate constant + int fIncremental; // integrated incremental mode for &scorr + int fIncrSim; // persistent CEX-TFO-only resimulation after SAT + int fDynSrm; // persistent dynamic SRM and true-unroll resimulation + int fSkipFailResim;// skip resim in rounds with no real CEX (only timeout/fail) int fVerboseFlops; // verbose stats int fVeryVerbose; // verbose stats int fVerbose; // verbose stats diff --git a/src/proof/cec/cecClass.c b/src/proof/cec/cecClass.c index 60fdbc8952..8ee64339ef 100644 --- a/src/proof/cec/cecClass.c +++ b/src/proof/cec/cecClass.c @@ -32,6 +32,11 @@ static inline void Cec_ObjSetSim( Cec_ManSim_t * p, int Id, int n ) { p-> static inline float Cec_MemUsage( Cec_ManSim_t * p ) { return 1.0*p->nMemsMax*(p->pPars->nWords+1)/(1<<20); } +void Cec_ManSimMemRelink( Cec_ManSim_t * p ); +unsigned * Cec_ManSimSimRef( Cec_ManSim_t * p, int i ); +unsigned * Cec_ManSimSimDeref( Cec_ManSim_t * p, int i ); +void Cec_ManSimProcessRefined( Cec_ManSim_t * p, Vec_Int_t * vRefined ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -310,6 +315,106 @@ int Cec_ManSimClassRefineOne( Cec_ManSim_t * p, int i ) return Cec_ManSimClassRefineOne_rec( p, i ); } +static void Cec_ManSimLoadMappedValue( Cec_ManSim_t * p, int ObjId, + unsigned * pValues, int Lit, int nWords ) +{ + unsigned * pSim = Cec_ManSimSimRef( p, ObjId ); + unsigned * pValue = pValues + (size_t)Abc_Lit2Var(Lit) * nWords; + int w; + // External values are consumed only by class refinement, not by the + // reference-counted AIG simulation below. One matching dereference should + // therefore release this entry regardless of the host node's fanout count. + pSim[0] = 1; + if ( Abc_LitIsCompl(Lit) ) + for ( w = 0; w < nWords; w++ ) + pSim[w+1] = ~pValue[w]; + else + for ( w = 0; w < nWords; w++ ) + pSim[w+1] = pValue[w]; +} + +/**Function************************************************************* + + Synopsis [Refines classes using externally simulated host-object values.] + + Description [vLits maps host object IDs to literals in pValues. This entry + point lets an unrolled SRM-side simulator reuse the established + class partitioning code without simulating the host AIG again.] + + SideEffects [May split equivalence classes in p->pAig.] + + SeeAlso [Cec_ManSimSimulateRound] + +***********************************************************************/ +int Cec_ManSimRefineMappedFrame( Cec_ManSim_t * p, unsigned * pValues, + Vec_Int_t * vLits, int iBase, int nWords ) +{ + Gia_Obj_t * pObj; + Vec_Int_t * vHeads = Vec_IntAlloc( 64 ); + int i, k, Ent, Lit, nChanges = 0; + assert( Vec_IntSize(vLits) >= iBase + Gia_ManObjNum(p->pAig) ); + p->nWords = nWords; + if ( p->nWordsOld != p->nWords ) + Cec_ManSimMemRelink( p ); + Vec_IntClear( p->vRefinedC ); + + // Snapshot the current heads before any class is split. + Gia_ManForEachObj1( p->pAig, pObj, i ) + if ( Gia_ObjIsHead(p->pAig, i) ) + Vec_IntPush( vHeads, i ); + + // Candidate constants are partitioned by their true simulated values. + Gia_ManForEachObj1( p->pAig, pObj, i ) + { + if ( !Gia_ObjIsConst(p->pAig, i) ) + continue; + Lit = Vec_IntEntry( vLits, iBase + i ); + assert( Lit >= 0 ); + Cec_ManSimLoadMappedValue( p, i, pValues, Lit, nWords ); + if ( !Cec_ManSimCompareConst(Cec_ObjSim(p, i), nWords) ) + Vec_IntPush( p->vRefinedC, i ); + else + Cec_ManSimSimDeref( p, i ); + } + + // Load one class at a time so the simulation manager's recyclable storage + // remains proportional to the largest class rather than to the whole AIG. + Vec_IntForEachEntry( vHeads, i, k ) + { + if ( !Gia_ObjIsHead(p->pAig, i) ) + continue; + Vec_IntClear( p->vClassTemp ); + Gia_ClassForEachObj( p->pAig, i, Ent ) + { + Lit = Vec_IntEntry( vLits, iBase + Ent ); + assert( Lit >= 0 ); + Cec_ManSimLoadMappedValue( p, Ent, pValues, Lit, nWords ); + Vec_IntPush( p->vClassTemp, Ent ); + } + nChanges += Cec_ManSimClassRefineOne( p, i ); + Vec_IntForEachEntry( p->vClassTemp, Ent, Lit ) + Cec_ManSimSimDeref( p, Ent ); + } + if ( p->pPars->fConstCorr ) + { + Vec_IntForEachEntry( p->vRefinedC, i, k ) + { + Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); + Cec_ManSimSimDeref( p, i ); + } + nChanges += Vec_IntSize( p->vRefinedC ); + Vec_IntClear( p->vRefinedC ); + } + if ( Vec_IntSize(p->vRefinedC) > 0 ) + { + nChanges += Vec_IntSize( p->vRefinedC ); + Cec_ManSimProcessRefined( p, p->vRefinedC ); + } + assert( p->nMems == 1 ); + Vec_IntFree( vHeads ); + return nChanges; +} + /**Function************************************************************* Synopsis [Refines one equivalence class.] @@ -665,7 +770,7 @@ int Cec_ManSimAnalyzeOutputs( Cec_ManSim_t * p ) SeeAlso [] ***********************************************************************/ -int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos ) +static int Cec_ManSimSimulateRoundInt( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos, unsigned * pSave ) { Gia_Obj_t * pObj; unsigned * pRes0, * pRes1, * pRes; @@ -751,6 +856,12 @@ int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * for ( w = 1; w <= p->nWords; w++ ) pRes[w] = pRes0[w] & pRes1[w]; } + if ( pSave ) + { + unsigned * pWord = pSave + (i >> 5); + unsigned Bit = 1u << (i & 31); + *pWord = (*pWord & ~Bit) | ((pRes[1] & 1) ? Bit : 0); + } references: // if this node is candidate constant, collect it @@ -808,6 +919,17 @@ int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * return Cec_ManSimAnalyzeOutputs( p ); } +int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos ) +{ + return Cec_ManSimSimulateRoundInt( p, vInfoCis, vInfoCos, NULL ); +} + +int Cec_ManSimSimulateRoundSavePhase( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos, unsigned * pSave ) +{ + assert( pSave != NULL ); + return Cec_ManSimSimulateRoundInt( p, vInfoCis, vInfoCos, pSave ); +} + /**Function************************************************************* diff --git a/src/proof/cec/cecCore.c b/src/proof/cec/cecCore.c index fdba94f005..3365046b90 100644 --- a/src/proof/cec/cecCore.c +++ b/src/proof/cec/cecCore.c @@ -195,6 +195,7 @@ void Cec_ManCorSetDefaultParams( Cec_ParCor_t * p ) p->fLatchCorr = 0; // consider only latch outputs p->fConstCorr = 0; // consider only constants p->fUseRings = 1; // combine classes into rings + p->fSkipFailResim = 0; // skip resim when a round has no real CEX (only timeout/fail) p->fUseCSat = 1; // use circuit-based solver // p->fFirstStop = 0; // stop on the first sat output p->fUseSmartCnf = 0; // use smart CNF computation diff --git a/src/proof/cec/cecCorr.c b/src/proof/cec/cecCorr.c index 0496b2e49b..40ecc228f3 100644 --- a/src/proof/cec/cecCorr.c +++ b/src/proof/cec/cecCorr.c @@ -34,7 +34,9 @@ static inline int Cec_ParCorShouldStop( Cec_ParCor_t * pPars ) /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ); +// Shared with cecCorrIncr.c (declared in cecInt.h). +extern void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ); +extern int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -45,13 +47,13 @@ static void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_ Synopsis [Computes the real value of the literal w/o spec reduction.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -static inline int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) +int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) { if ( Gia_ObjIsAnd(pObj) ) { @@ -75,7 +77,7 @@ static inline int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_ Synopsis [Recursively performs speculative reduction for the object.] Description [] - + SideEffects [] SeeAlso [] @@ -104,7 +106,7 @@ void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pOb Synopsis [Derives SRM for signal correspondence.] Description [] - + SideEffects [] SeeAlso [] @@ -221,7 +223,7 @@ Gia_Man_t * Gia_ManCorrSpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_I Synopsis [Derives SRM for signal correspondence.] Description [] - + SideEffects [] SeeAlso [] @@ -290,7 +292,7 @@ Gia_Man_t * Gia_ManCorrSpecReduceInit( Gia_Man_t * p, int nFrames, int nPrefix, Synopsis [Initializes simulation info for lcorr/scorr counter-examples.] Description [] - + SideEffects [] SeeAlso [] @@ -497,6 +499,53 @@ int Cec_ManLoadCounterExamples( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iS return iStart; } +/**Function************************************************************* + + Synopsis [Performs bitpacking of counter-examples and records bit lanes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_ManLoadCounterExamplesMapped( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart, Vec_Int_t * vOutBits ) +{ + Vec_Int_t * vPat; + Vec_Ptr_t * vPres; + int nWords = Vec_PtrReadWordsSimInfo(vInfo); + int nBits = 32 * nWords; + int k, nSize, Out; + Vec_IntClear( vOutBits ); + vPat = Vec_IntAlloc( 100 ); + vPres = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), nWords ); + Vec_PtrCleanSimInfo( vPres, 0, nWords ); + while ( iStart < Vec_IntSize(vCexStore) ) + { + Out = Vec_IntEntry( vCexStore, iStart++ ); + nSize = Vec_IntEntry( vCexStore, iStart++ ); + if ( nSize <= 0 ) + continue; + Vec_IntClear( vPat ); + for ( k = 0; k < nSize; k++ ) + Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) ); + for ( k = 1; k < nBits; k++ ) + if ( Cec_ManLoadCounterExamplesTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) ) + break; + if ( k < nBits ) + { + Vec_IntPush( vOutBits, Out ); + Vec_IntPush( vOutBits, k ); + } + if ( k == nBits-1 ) + break; + } + Vec_PtrFree( vPres ); + Vec_IntFree( vPat ); + return iStart; +} + /**Function************************************************************* Synopsis [Performs bitpacking of counter-examples.] @@ -538,6 +587,53 @@ int Cec_ManLoadCounterExamples2( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int i return iStart; } +/**Function************************************************************* + + Synopsis [Classifies vCexStore entries by SAT outcome.] + + Description [Each entry is (Out, nLits[, lit0, ..., lit{nLits-1}]). + nLits > 0 -> real SAT CEX with usable literals; + nLits == 0 -> trivial SAT (e.g. SRM PO became const 1); + nLits == -1 -> timeout/fail, no CEX. + Counts are written via the out-pointers (any may be NULL). + Returns 1 iff there is at least one entry usable for resim + (real or trivial), preserving the prior skip-failed-resim + semantics where only timeout-only stores get skipped.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Cec_ManCexStoreClassify( Vec_Int_t * vCexStore, int * pnReal, int * pnTriv, int * pnFail ) +{ + int iStart = 0, nSize, nReal = 0, nTriv = 0, nFail = 0; + while ( iStart < Vec_IntSize(vCexStore) ) + { + iStart++; // output number + assert( iStart < Vec_IntSize(vCexStore) ); + nSize = Vec_IntEntry( vCexStore, iStart++ ); + if ( nSize > 0 ) + { + nReal++; + iStart += nSize; + } + else if ( nSize == 0 ) + { + nTriv++; + } + else + { + assert( nSize == -1 ); + nFail++; + } + } + if ( pnReal ) *pnReal = nReal; + if ( pnTriv ) *pnTriv = nTriv; + if ( pnFail ) *pnFail = nFail; + return (nReal + nTriv) > 0; +} + /**Function************************************************************* Synopsis [Resimulates counter-examples derived by the SAT solver.] @@ -549,33 +645,104 @@ int Cec_ManLoadCounterExamples2( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int i SeeAlso [] ***********************************************************************/ -int Cec_ManResimulateCounterExamples( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames ) -{ - Vec_Int_t * vPairs; - Vec_Ptr_t * vSimInfo; - int RetValue = 0, iStart = 0; - vPairs = Gia_ManCorrCreateRemapping( pSim->pAig ); - Gia_ManCreateValueRefs( pSim->pAig ); +static int Cec_ManResimulateCounterExamplesSeed( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames, Cec_SeedSim_t * pSeed, Vec_Int_t * vOutputs ) +{ + Vec_Int_t * vPairs = NULL; + Vec_Int_t * vOutBits = NULL; + Vec_Ptr_t * vSimInfo = NULL; + int RetValue = 0, iStart = 0, fValueRefs = 0; + if ( pSeed ) + Cec_SeedSimBeginCall( pSeed ); // reset per-call local/full/maxdirty counters // pSim->pPars->nWords = 63; pSim->pPars->nFrames = nFrames; - vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pSim->pAig) + Gia_ManPiNum(pSim->pAig) * nFrames, pSim->pPars->nWords ); + if ( pSeed ) + { + Cec_SeedSimEnsurePersistent( pSeed, pSim ); + // Defer the (possibly full-unroll-sized) class cone: it is built lazily + // inside Cec_SeedSimTryBatch() only once a batch passes the density gate, + // so rounds that fall back to full resim never pay for it. + pSeed->fUseCone = 0; + vSimInfo = pSeed->vSimInfo; + vOutBits = Vec_IntAlloc( 1000 ); + } + else + { + Gia_ManCreateValueRefs( pSim->pAig ); + fValueRefs = 1; + vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pSim->pAig) + Gia_ManPiNum(pSim->pAig) * nFrames, pSim->pPars->nWords ); + } + vPairs = Gia_ManCorrCreateRemapping( pSim->pAig ); while ( iStart < Vec_IntSize(vCexStore) ) { - Cec_ManStartSimInfo( vSimInfo, Gia_ManRegNum(pSim->pAig) ); - iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart ); -// iStart = Cec_ManLoadCounterExamples2( vSimInfo, vCexStore, iStart ); -// Gia_ManCorrRemapSimInfo( pSim->pAig, vSimInfo ); - Gia_ManCorrPerformRemapping( vPairs, vSimInfo ); - RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo ); + if ( pSeed ) + { + int LocalStatus; + iStart = Cec_SeedSimLoadPersistentBatch( + pSeed, vCexStore, iStart, vPairs, vOutBits ); + if ( pSeed->nFallbackCooldown > 0 ) + { + Cec_SeedSimBypassBatch( pSeed, Vec_IntSize(vOutBits) / 2 ); + pSeed->nFallbackCooldown--; + } + else if ( (LocalStatus = Cec_SeedSimTryBatch( + pSeed, pSim, vSimInfo, vOutputs, vOutBits, nFrames )) == + CEC_SEEDSIM_RESULT_LOCAL ) + { + pSeed->nFallbackStreak = 0; + pSeed->nFallbackCooldown = 0; + continue; + } + else if ( LocalStatus == CEC_SEEDSIM_RESULT_FULL_WIDE ) + { + int Shift; + pSeed->nFallbackStreak++; + Shift = Abc_MinInt( pSeed->nFallbackStreak - 1, 3 ); + pSeed->nFallbackCooldown = + Abc_MinInt( (1 << Shift) - 1, + CEC_SEEDSIM_MAX_FALLBACK_BACKOFF ); + } + else + { + pSeed->nFallbackStreak = 0; + pSeed->nFallbackCooldown = 0; + } + } + else + { + Cec_ManStartSimInfo( vSimInfo, Gia_ManRegNum(pSim->pAig) ); + iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart ); + Gia_ManCorrPerformRemapping( vPairs, vSimInfo ); + } + // The local path returned above. Reaching here means standard full + // resimulation, either outside incremental mode or as a fallback. + if ( pSeed ) + { + if ( !fValueRefs ) + { + Gia_ManCreateValueRefs( pSim->pAig ); + fValueRefs = 1; + } + RetValue |= Cec_ManSeqResimulateSeed( pSim, vSimInfo, pSeed ); + Cec_SeedSimRestorePersistentInputs( pSeed ); + } + else + RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo ); // Cec_ManSeqResimulateInfo( pSim->pAig, vSimInfo, NULL ); } //Gia_ManEquivPrintOne( pSim->pAig, 85, 0 ); assert( iStart == Vec_IntSize(vCexStore) ); - Vec_PtrFree( vSimInfo ); - Vec_IntFree( vPairs ); + Vec_IntFreeP( &vOutBits ); + if ( !pSeed ) + Vec_PtrFree( vSimInfo ); + Vec_IntFreeP( &vPairs ); return RetValue; } +int Cec_ManResimulateCounterExamples( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames ) +{ + return Cec_ManResimulateCounterExamplesSeed( pSim, vCexStore, nFrames, NULL, NULL ); +} + /**Function************************************************************* Synopsis [Resimulates counter-examples derived by the SAT solver.] @@ -605,12 +772,102 @@ int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexS return RetValue; } +/**Function************************************************************* + + Synopsis [Checks whether two endpoints are still in the same class.] + + Description [Ring mode needs special handling for the closing edge + tail -> head because Gia_ObjHasSameRepr() compares raw + representatives and the head stores GIA_VOID.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Cec_ManObjsStillMerged( Gia_Man_t * p, int iRepr, int iObj, int fRings ) +{ + int iReprRoot, iObjRoot; + if ( !fRings ) + return Gia_ObjHasSameRepr( p, iRepr, iObj ); + if ( iRepr == 0 ) + return Gia_ObjIsConst( p, iObj ); + if ( iObj == 0 ) + return Gia_ObjIsConst( p, iRepr ); + if ( !Gia_ObjIsClass( p, iRepr ) || !Gia_ObjIsClass( p, iObj ) ) + return 0; + iReprRoot = Gia_ObjIsHead( p, iRepr ) ? iRepr : Gia_ObjRepr( p, iRepr ); + iObjRoot = Gia_ObjIsHead( p, iObj ) ? iObj : Gia_ObjRepr( p, iObj ); + return iReprRoot == iObjRoot && iReprRoot != GIA_VOID; +} + +static int Cec_ManObjToSplit( Gia_Man_t * p, int iRepr, int iObj, int fRings ) +{ + // For the ring closing edge (tail, head), split the tail. Splitting the + // head is also correct, but it changes the representative of the whole + // remaining class and creates a much larger incremental seed set. + if ( fRings && iObj > 0 && Gia_ObjIsHead( p, iObj ) && Gia_ObjIsClass( p, iRepr ) ) + return iRepr; + return iObj; +} + +/**Function************************************************************* + + Synopsis [Directly splits pairs whose SAT result was trivial (nLits==0).] + + Description [A trivial SAT (e.g. SRM PO became const 1) is a real + disproval but carries no CEX literals, so Cec_ManResimulateCounterExamples + cannot break the pair -- only random filler can, and usually does not. + Splitting these pairs directly is sound (SAT proved disequivalence) and + recovers work that the standard resim path leaves on the table. + + Only nLits==0 entries are touched; nLits>0 entries are left for resim to + refine, matching the established behaviour in Gia_ManCheckRefinements + that avoids force-splitting CEX-bearing SAT pairs (token_ring regression). + + Returns the number of pairs actually split this call.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Cec_ManTrivialSatSplit( Gia_Man_t * pAig, Cec_ManSim_t * pSim, + Vec_Int_t * vCexStore, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, int fRings ) +{ + int iStart = 0, Out, nSize, iRepr, iObj, iSplit, Count = 0; + while ( iStart < Vec_IntSize(vCexStore) ) + { + Out = Vec_IntEntry( vCexStore, iStart++ ); + assert( iStart < Vec_IntSize(vCexStore) ); + nSize = Vec_IntEntry( vCexStore, iStart++ ); + if ( nSize > 0 ) + { + iStart += nSize; + continue; + } + if ( nSize < 0 ) + continue; + // nSize == 0 -> trivial SAT, no CEX literals. + assert( Out < Vec_StrSize(vStatus) ); + assert( Vec_StrEntry(vStatus, Out) == 0 ); + iRepr = Vec_IntEntry( vOutputs, 2*Out ); + iObj = Vec_IntEntry( vOutputs, 2*Out + 1 ); + if ( !Cec_ManObjsStillMerged( pAig, iRepr, iObj, fRings ) ) + continue; + iSplit = Cec_ManObjToSplit( pAig, iRepr, iObj, fRings ); + if ( Cec_ManSimClassRemoveOne( pSim, iSplit ) ) + Count++; + } + return Count; +} + /**Function************************************************************* Synopsis [Updates equivalence classes by marking those that timed out.] - Description [Returns 1 if all ndoes are proved.] - + Description [Returns 1 if all nodes are proved.] + SideEffects [] SeeAlso [] @@ -714,6 +971,7 @@ Gia_Man_t * Gia_ManCorrReduce( Gia_Man_t * p ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Gia_ManOriginsDup( pNew, p ); return pNew; } @@ -762,6 +1020,7 @@ void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIte Abc_Print( 1, "p =%6d d =%6d f =%6d ", nProve, nDispr, nFail ); Abc_Print( 1, "%c ", Gia_ObjIsConst( p, Gia_ObjFaninId0p(p, Gia_ManPo(p, 0)) ) ? '+' : '-' ); Abc_PrintTime( 1, "T", Time ); + fflush( stdout ); } int Cec_ManCountLits( Gia_Man_t * p ) { @@ -791,7 +1050,7 @@ int Cec_ManCountLits( Gia_Man_t * p ) ***********************************************************************/ void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPrefs ) -{ +{ Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; Vec_Str_t * vStatus; @@ -799,7 +1058,16 @@ void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPr Vec_Int_t * vCexStore; Cec_ManSim_t * pSim; Gia_Man_t * pSrm; - int fChanges, RetValue, i; + int fChanges, i; + int nBmcResimFrames = pPars->nFrames + 1 + nPrefs; + int fBmcPersist = 0; + // BMC SRM is keyed only on pReprs (Gia_ManCorrSpecReduceInit ignores + // its fRings flag). So the incremental filter only needs pReprs-based + // seeds; pNexts changes cannot affect this SRM and there are no ring + // closing edges to reprove -- BMC is structurally simpler than the + // main inductive loop. + Cec_IncrMgr_t * pBmcMgr = NULL; + Cec_DynSrm_t * pBmcDynSrm = NULL; // prepare simulation manager Cec_ManSimSetDefaultParams( pParsSim ); pParsSim->nWords = pPars->nWords; @@ -812,29 +1080,102 @@ void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPr Cec_ManSatSetDefaultParams( pParsSat ); pParsSat->nBTLimit = pPars->nBTLimit; pParsSat->fVerbose = pPars->fVerbose; + if ( pPars->fIncremental ) + { + pBmcMgr = Cec_IncrMgrAlloc( pAig, pPars->nFrames + nPrefs ); + Cec_IncrMgrSnapshotClasses( pBmcMgr ); + } + if ( pPars->fDynSrm && pBmcMgr ) + pBmcDynSrm = Cec_DynSrmAlloc( pAig, pBmcMgr ); + fBmcPersist = ( pBmcDynSrm != NULL && pPars->fUseCSat ); fChanges = 1; for ( i = 0; fChanges && (!pPars->nLimitMax || i < pPars->nLimitMax); i++ ) { + int * pTfoMask = NULL; + int nReprSeeds = 0, nTotalPairs = 0, nActivePairs = 0; + int nBmcPos = 0; if ( Cec_ParCorShouldStop( pPars ) ) break; abctime clkBmc = Abc_Clock(); fChanges = 0; - pSrm = Gia_ManCorrSpecReduceInit( pAig, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); - if ( Gia_ManPoNum(pSrm) == 0 ) + // BMC SRM is non-ring (Gia_ManCorrSpecReduceInit ignores fRings); + // the incremental mask filters on pReprs-derived endpoints only. + if ( pBmcMgr && i > 0 ) { - Gia_ManStop( pSrm ); + nReprSeeds = Cec_IncrMgrComputeSeeds( pBmcMgr ); + if ( nReprSeeds == 0 ) + { + // No pReprs change. BMC SRM topology is unchanged. + break; + } + Cec_IncrMgrComputeTfo( pBmcMgr ); + // BMC SRM is non-ring; pass fRings=0 so we count (head, member) + // pairs only and skip any ring-edge bookkeeping. + if ( pBmcDynSrm ) + Cec_DynSrmCountActivePairs( pBmcDynSrm, 0, pBmcMgr->pTfoMark, &nTotalPairs, &nActivePairs ); + else + Cec_IncrMgrCountActivePairs( pBmcMgr, 0, pBmcMgr->pTfoMark, &nTotalPairs, &nActivePairs ); + if ( nActivePairs == 0 ) + break; + // Same fallback heuristic as the main loop: above ~70% active, + // the mask plus emission filter costs more than just rebuilding + // the full SRM. + if ( !( nTotalPairs > 0 && (ABC_INT64_T)10 * nActivePairs > (ABC_INT64_T)7 * nTotalPairs ) ) + pTfoMask = pBmcMgr->pTfoMark; + } + pSrm = NULL; + if ( fBmcPersist ) + Cec_DynSrmBuildCoreInit( pBmcDynSrm, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pTfoMask, pTfoMask ? CEC_EMIT_ACTIVE : CEC_EMIT_ALL ); + else if ( pBmcDynSrm ) + pSrm = Cec_DynSrmBuildInit( pBmcDynSrm, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pTfoMask, pTfoMask ? CEC_EMIT_ACTIVE : CEC_EMIT_ALL ); + else if ( pTfoMask ) + pSrm = Gia_ManCorrSpecReduceInit_Active( pAig, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pTfoMask ); + else + pSrm = Gia_ManCorrSpecReduceInit( pAig, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); + nBmcPos = fBmcPersist ? Vec_IntSize(Cec_DynSrmOutLits(pBmcDynSrm)) : Gia_ManCoNum(pSrm); + if ( pTfoMask && pPars->fVeryVerbose ) + Abc_Print( 1, " [bmc-incr i=%d repr=%d active=%d/%d POs=%d]\n", + i, nReprSeeds, nActivePairs, nTotalPairs, nBmcPos ); + // Snapshot after SRM construction, before SAT/refine: this is the + // class state whose pairs were just emitted. The next iteration's + // diff vs this snapshot tells us which pairs are stale. + if ( pBmcMgr ) + Cec_IncrMgrSnapshotClasses( pBmcMgr ); + if ( nBmcPos == 0 ) + { + if ( pSrm ) + Gia_ManStop( pSrm ); Vec_IntFree( vOutputs ); break; - } + } pParsSat->nBTLimit *= 10; - if ( pPars->fUseCSat ) + if ( fBmcPersist ) + vCexStore = Cec_DynSrmSolve( pBmcDynSrm, pPars->nBTLimit, &vStatus ); + else if ( pPars->fUseCSat ) vCexStore = Tas_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); else vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); // refine classes with these counter-examples if ( Vec_IntSize(vCexStore) ) { - RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nPrefs ); + int nCexReal = 0, nCexTriv = 0; + // classify CEX entries: real (nLits>0) / trivial (==0) / fail (==-1) + Cec_ManCexStoreClassify( vCexStore, &nCexReal, &nCexTriv, NULL ); + // only invoke resim when there is a real CEX (nLits>0). Trivial + // (nLits==0) and fail (==-1) entries carry no literals; trivial + // pairs are handled by direct split below, fail pairs by chk. + if ( nCexReal > 0 || !pPars->fSkipFailResim ) + { + // Keep BMC/init CEX resimulation on the canonical full path even + // in incremental mode. BMC counterexamples are partial models + // of frame/prefix-specific SAT obligations; retaining them as a + // persistent simulation background over-refines classes and can + // significantly hurt gate QoR. The main correspondence loop + // below still uses event resim for ordinary refinement batches. + Cec_ManResimulateCounterExamples( pSim, vCexStore, nBmcResimFrames ); + } + if ( nCexTriv > 0 ) + Cec_ManTrivialSatSplit( pAig, pSim, vCexStore, vStatus, vOutputs, pPars->fUseRings ); Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); fChanges = 1; } @@ -843,11 +1184,14 @@ void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPr // recycle Vec_IntFree( vCexStore ); Vec_StrFree( vStatus ); - Gia_ManStop( pSrm ); + if ( pSrm ) + Gia_ManStop( pSrm ); Vec_IntFree( vOutputs ); if ( Cec_ParCorShouldStop( pPars ) ) break; } + Cec_DynSrmFree( pBmcDynSrm ); + Cec_IncrMgrFree( pBmcMgr ); Cec_ManSimStop( pSim ); } @@ -944,10 +1288,19 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; Cec_ManSim_t * pSim; Gia_Man_t * pSrm; - int r, RetValue, nPrev[4] = {0}; + int r, nPrev[4] = {0}; abctime clkTotal = Abc_Clock(); abctime clkSat = 0, clkSim = 0, clkSrm = 0; abctime clk2, clk = Abc_Clock(); + // Incremental active-list manager (NULL if -i not set) + Cec_IncrMgr_t * pMgr = NULL; + // Persistent dynamic SRM construction manager (NULL outside incremental mode). + Cec_DynSrm_t * pDynSrm = NULL; + int fPersist = 0; // incremental + circuit-SAT: solve persistent pCore directly + // Unified CEX event-resimulation manager (NULL outside incremental mode). + Cec_SeedSim_t * pSeedSim = NULL; + abctime clkIncr = 0; + int nIncrSkipped = 0, nIncrFallback = 0; if ( Gia_ManRegNum(pAig) == 0 ) { Abc_Print( 1, "Cec_ManLatchCorrespondence(): Not a sequential AIG.\n" ); @@ -978,9 +1331,9 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) pParsSat->nBTLimit = Abc_MinInt( pParsSat->nBTLimit, 1000 ); if ( pPars->fVerbose ) { - Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Fr = %d. Lcorr = %d. Ring = %d. CSat = %d.\n", + Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Fr = %d. Lcorr = %d. Ring = %d. CSat = %d. Incr = %d. Dyn = %d.\n", Gia_ManObjNum(pAig), Gia_ManAndNum(pAig), - pPars->nBTLimit, pPars->nFrames, pPars->fLatchCorr, pPars->fUseRings, pPars->fUseCSat ); + pPars->nBTLimit, pPars->nFrames, pPars->fLatchCorr, pPars->fUseRings, pPars->fUseCSat, pPars->fIncremental, pPars->fDynSrm ); Cec_ManRefinedClassPrintStats( pAig, NULL, 0, Abc_Clock() - clk ); } // check the base case @@ -994,43 +1347,140 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) if ( pPars->nStepsMax == 0 ) { Abc_Print( 1, "Stopped signal correspondence after BMC.\n" ); + fflush( stdout ); Cec_ManSimStop( pSim ); return 1; } + if ( pPars->fIncremental ) + { + pMgr = Cec_IncrMgrAlloc( pAig, pPars->nFrames ); + Cec_IncrMgrSnapshotClasses( pMgr ); + } + if ( pPars->fDynSrm && pMgr ) + pDynSrm = Cec_DynSrmAlloc( pAig, pMgr ); + // Incremental persistence path: solve the persistent COless pCore directly (circuit + // SAT only), skipping the per-round throwaway view that BuildView copies. + fPersist = ( pDynSrm != NULL && pPars->fUseCSat ); + // Resident local-sim manager sized for the main-loop resim depth. + if ( pPars->fIncrSim ) + pSeedSim = Cec_SeedSimAlloc( pAig, pPars->nFrames + 1 + nAddFrames, pPars->nFrames, pParsSim->nWords ); // perform refinement of equivalence classes for ( r = 0; r < nIterMax; r++ ) - { + { if ( Cec_ParCorShouldStop( pPars ) ) { Cec_ManSimStop( pSim ); + Cec_DynSrmFree( pDynSrm ); + Cec_IncrMgrFree( pMgr ); + Cec_SeedSimFree( pSeedSim ); return 1; } if ( pPars->nStepsMax == r ) { Cec_ManSimStop( pSim ); + Cec_DynSrmFree( pDynSrm ); + Cec_IncrMgrFree( pMgr ); + Cec_SeedSimFree( pSeedSim ); Abc_Print( 1, "Stopped signal correspondence after %d refiment iterations.\n", r ); + fflush( stdout ); return 1; } clk = Abc_Clock(); - // perform speculative reduction + // perform speculative reduction (with optional active-list filter) clk2 = Abc_Clock(); - pSrm = Gia_ManCorrSpecReduce( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); - assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == Gia_ManRegNum(pAig)+(pPars->nFrames+!pPars->fLatchCorr)*Gia_ManPiNum(pAig) ); + { + int * pTfoMask = NULL; + int nReprSeeds = 0, nNextChanges = 0; + int nTotalPairs = 0, nActivePairs = 0; + // Decide whether to apply incremental TFO mask this iteration. + // Skip on r==0 because the first full SRM establishes the cache. + if ( pMgr && r > 0 ) + { + abctime clkI = Abc_Clock(); + nReprSeeds = Cec_IncrMgrComputeSeeds( pMgr ); + nNextChanges = pPars->fUseRings ? Cec_IncrMgrCountNextChanges( pMgr ) : 0; + if ( nReprSeeds == 0 && nNextChanges == 0 ) + { + // No class-state change since the full/active SRM just + // proved these pairs; this is true convergence. + clkIncr += Abc_Clock() - clkI; + clkSrm += Abc_Clock() - clk2; + break; + } + else + { + Cec_IncrMgrComputeTfo( pMgr ); + if ( pDynSrm ) + Cec_DynSrmCountActivePairs( pDynSrm, pPars->fUseRings, pMgr->pTfoMark, &nTotalPairs, &nActivePairs ); + else + Cec_IncrMgrCountActivePairs( pMgr, pPars->fUseRings, pMgr->pTfoMark, &nTotalPairs, &nActivePairs ); + if ( nActivePairs == 0 ) + { + // Classes changed, but no remaining candidate pair + // depends on the changes and no new ring edge exists. + clkIncr += Abc_Clock() - clkI; + clkSrm += Abc_Clock() - clk2; + break; + } + // Fallback is based on emitted candidate pairs, not seed count. + // Above ~70% active pairs, full SRM is usually cheaper. + else if ( nTotalPairs > 0 && (ABC_INT64_T)10 * nActivePairs > (ABC_INT64_T)7 * nTotalPairs ) + { + nIncrFallback++; + } + else + { + pTfoMask = pMgr->pTfoMark; + nIncrSkipped += nTotalPairs - nActivePairs; + } + } + clkIncr += Abc_Clock() - clkI; + } + + // Incremental persistence under circuit-SAT: build the COless pCore and solve + // its root literals directly below; skip the per-round throwaway view. + if ( fPersist ) + { + Cec_DynSrmBuildCore( pDynSrm, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings, pTfoMask, pTfoMask ? CEC_EMIT_ACTIVE : CEC_EMIT_ALL ); + pSrm = NULL; + } + else if ( pDynSrm ) + pSrm = Cec_DynSrmBuild( pDynSrm, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings, pTfoMask, pTfoMask ? CEC_EMIT_ACTIVE : CEC_EMIT_ALL ); + else if ( pTfoMask ) + pSrm = Gia_ManCorrSpecReduce_Emit( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings, pTfoMask, pMgr, CEC_EMIT_ACTIVE, NULL ); + else + pSrm = Gia_ManCorrSpecReduce( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); + if ( pTfoMask && pPars->fVeryVerbose ) + Abc_Print( 1, " [incr r=%d repr=%d next=%d tfo=%d active=%d/%d POs=%d]\n", + r, nReprSeeds, nNextChanges, + Vec_IntSize(pMgr->vTfoNodes), nActivePairs, nTotalPairs, + fPersist ? Vec_IntSize(Cec_DynSrmOutLits(pDynSrm)) : Gia_ManCoNum(pSrm) ); + // Snapshot after SRM construction: the active builder still needs + // the old pNexts snapshot to recognize newly-created ring edges. + // SAT/sim refinement below is what creates the next iteration's diff. + if ( pMgr ) + Cec_IncrMgrSnapshotClasses( pMgr ); + } + assert( fPersist || (Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == Gia_ManRegNum(pAig)+(pPars->nFrames+!pPars->fLatchCorr)*Gia_ManPiNum(pAig)) ); clkSrm += Abc_Clock() - clk2; - if ( Gia_ManCoNum(pSrm) == 0 ) + if ( (fPersist ? Vec_IntSize(Cec_DynSrmOutLits(pDynSrm)) : Gia_ManCoNum(pSrm)) == 0 ) { Vec_IntFree( vOutputs ); - Gia_ManStop( pSrm ); + if ( pSrm ) + Gia_ManStop( pSrm ); break; } //Gia_DumpAiger( pSrm, "corrsrm", r, 2 ); // found counter-examples to speculation clk2 = Abc_Clock(); - if ( pPars->fUseCSat ) + if ( fPersist ) + vCexStore = Cec_DynSrmSolve( pDynSrm, pPars->nBTLimit, &vStatus ); + else if ( pPars->fUseCSat ) vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0, 0 ); else vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); - Gia_ManStop( pSrm ); + if ( pSrm ) + Gia_ManStop( pSrm ); clkSat += Abc_Clock() - clk2; if ( Vec_IntSize(vCexStore) == 0 ) { @@ -1043,10 +1493,21 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) // refine classes with these counter-examples clk2 = Abc_Clock(); - RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames ); - Vec_IntFree( vCexStore ); - clkSim += Abc_Clock() - clk2; - Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); + { + int nCexReal = 0, nCexTriv = 0; + Cec_ManCexStoreClassify( vCexStore, &nCexReal, &nCexTriv, NULL ); + if ( nCexReal > 0 || !pPars->fSkipFailResim ) + { + Cec_ManResimulateCounterExamplesSeed( pSim, + vCexStore, pPars->nFrames + 1 + nAddFrames, + pSeedSim, vOutputs ); + } + if ( nCexTriv > 0 ) + Cec_ManTrivialSatSplit( pAig, pSim, vCexStore, vStatus, vOutputs, pPars->fUseRings ); + Vec_IntFree( vCexStore ); + clkSim += Abc_Clock() - clk2; + Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); + } if ( pPars->fVerbose ) Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, Abc_Clock() - clk ); Vec_StrFree( vStatus ); @@ -1055,6 +1516,9 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) if ( Cec_ParCorShouldStop( pPars ) ) { Cec_ManSimStop( pSim ); + Cec_DynSrmFree( pDynSrm ); + Cec_IncrMgrFree( pMgr ); + Cec_SeedSimFree( pSeedSim ); return 1; } // quit if const is no longer there @@ -1062,7 +1526,11 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) { printf( "Iterative refinement is stopped after iteration %d\n", r ); printf( "because the property output is no longer a candidate constant.\n" ); + fflush( stdout ); Cec_ManSimStop( pSim ); + Cec_DynSrmFree( pDynSrm ); + Cec_IncrMgrFree( pMgr ); + Cec_SeedSimFree( pSeedSim ); return 0; } if ( pPars->nLimitMax ) @@ -1072,7 +1540,11 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) { printf( "Iterative refinement is stopped after iteration %d\n", r ); printf( "because refinement does not proceed quickly.\n" ); + fflush( stdout ); Cec_ManSimStop( pSim ); + Cec_DynSrmFree( pDynSrm ); + Cec_IncrMgrFree( pMgr ); + Cec_SeedSimFree( pSeedSim ); ABC_FREE( pAig->pReprs ); ABC_FREE( pAig->pNexts ); return 0; @@ -1100,10 +1572,21 @@ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) ABC_PRTP( "Sat ", clkSat, clkTotal ); ABC_PRTP( "Sim ", clkSim, clkTotal ); ABC_PRTP( "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal ); + if ( pMgr ) + { + ABC_PRTP( "Incr ", clkIncr, clkTotal ); + Abc_Print( 1, "Incr: fallback rounds = %d, skipped candidate pairs = %d\n", nIncrFallback, nIncrSkipped ); + } + if ( pDynSrm ) + Cec_DynSrmPrintStats( pDynSrm ); Abc_PrintTime( 1, "TOTAL", clkTotal ); + fflush( stdout ); } + Cec_IncrMgrFree( pMgr ); + Cec_DynSrmFree( pDynSrm ); + Cec_SeedSimFree( pSeedSim ); return 1; -} +} /**Function************************************************************* @@ -1299,42 +1782,107 @@ Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) SeeAlso [] ***********************************************************************/ -Vec_Wec_t * Gia_ManCreateRegSupps( Gia_Man_t * p, int fVerbose ) +static inline void Gia_ManStopFlopSuppAdd( int * pReg0, int * pReg1, int * pnRegs, int Reg ) { - abctime clk = Abc_Clock(); - Gia_Obj_t * pObj; int i, Id; - Vec_Wec_t * vSuppsR = Vec_WecStart( Gia_ManRegNum(p) ); - Vec_Wec_t * vSupps = Vec_WecStart( Gia_ManObjNum(p) ); - Gia_ManForEachRo( p, pObj, i ) - Vec_IntPush( Vec_WecEntry(vSupps, Gia_ObjId(p, pObj)), i ); - Gia_ManForEachAnd( p, pObj, Id ) - Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Gia_ObjFaninId0(pObj, Id)), - Vec_WecEntry(vSupps, Gia_ObjFaninId1(pObj, Id)), - Vec_WecEntry(vSupps, Id) ); - Gia_ManForEachRi( p, pObj, i ) - Vec_IntAppend( Vec_WecEntry(vSuppsR, i), Vec_WecEntry(vSupps, Gia_ObjFaninId0p(p, pObj)) ); - Vec_WecFree( vSupps ); - if ( fVerbose ) - Abc_PrintTime( 1, "Support computation", Abc_Clock() - clk ); - return vSuppsR; + if ( *pnRegs == 3 ) + return; + if ( *pnRegs == 0 ) + { + *pReg0 = Reg; + *pnRegs = 1; + return; + } + if ( *pnRegs == 1 ) + { + if ( *pReg0 == Reg ) + return; + *pReg1 = Reg; + *pnRegs = 2; + return; + } + assert( *pnRegs == 2 ); + if ( *pReg0 == Reg || *pReg1 == Reg ) + return; + *pnRegs = 3; } Vec_Int_t * Gia_ManFindStopFlops( Gia_Man_t * p, int nFlopIncFreq, int fVerbose ) { - Vec_Int_t * vRes = NULL, * vTemp; int i, k, Spot, Temp, nItems = 0; - Vec_Wec_t * vSupps = Gia_ManCreateRegSupps( p, fVerbose ); + abctime clk = Abc_Clock(); + Gia_Obj_t * pObj; + Vec_Int_t * vRes = NULL; Vec_Int_t * vNexts = Vec_IntStartFull( Gia_ManRegNum(p) ); Vec_Int_t * vAvail = Vec_IntStart( Gia_ManRegNum(p) ); Vec_Int_t * vHeads = Vec_IntAlloc( 10 ); - Vec_WecForEachLevel( vSupps, vTemp, i ) { - if ( Vec_IntSize(vTemp) > 2 ) - continue; - if ( (Spot = Vec_IntFind(vTemp, i)) >= 0 ) - Vec_IntDrop( vTemp, Spot ); - if ( Vec_IntSize(vTemp) != 1 ) + unsigned char * pSuppN = ABC_CALLOC( unsigned char, Gia_ManObjNum(p) ); + int * pSupp0 = ABC_ALLOC( int, Gia_ManObjNum(p) ); + int * pSupp1 = ABC_ALLOC( int, Gia_ManObjNum(p) ); + int i, k, Id, Fan0, Fan1, Count, Next, Spot, Temp, nItems = 0; + + // Track at most two distinct flop supports per node; value 3 means "many". + Gia_ManForEachRo( p, pObj, i ) + { + Id = Gia_ObjId( p, pObj ); + pSuppN[Id] = 1; + pSupp0[Id] = i; + } + Gia_ManForEachAnd( p, pObj, Id ) + { + int Reg0 = -1, Reg1 = -1, nRegs = 0; + Fan0 = Gia_ObjFaninId0( pObj, Id ); + Fan1 = Gia_ObjFaninId1( pObj, Id ); + if ( pSuppN[Fan0] == 3 || pSuppN[Fan1] == 3 ) + { + pSuppN[Id] = 3; continue; - Vec_IntWriteEntry( vNexts, i, Vec_IntEntry(vTemp, 0) ); - Vec_IntWriteEntry( vAvail, Vec_IntEntry(vTemp, 0), 1 ); + } + if ( pSuppN[Fan0] > 0 ) + { + Gia_ManStopFlopSuppAdd( &Reg0, &Reg1, &nRegs, pSupp0[Fan0] ); + if ( pSuppN[Fan0] > 1 ) + Gia_ManStopFlopSuppAdd( &Reg0, &Reg1, &nRegs, pSupp1[Fan0] ); + } + if ( pSuppN[Fan1] > 0 ) + { + Gia_ManStopFlopSuppAdd( &Reg0, &Reg1, &nRegs, pSupp0[Fan1] ); + if ( pSuppN[Fan1] > 1 ) + Gia_ManStopFlopSuppAdd( &Reg0, &Reg1, &nRegs, pSupp1[Fan1] ); + } + pSuppN[Id] = nRegs; + if ( nRegs > 0 ) + pSupp0[Id] = Reg0; + if ( nRegs > 1 ) + pSupp1[Id] = Reg1; } + if ( fVerbose ) + { + Abc_PrintTime( 1, "Support computation", Abc_Clock() - clk ); + fflush( stdout ); + } + + Gia_ManForEachRi( p, pObj, i ) + { + Id = Gia_ObjFaninId0p( p, pObj ); + Count = pSuppN[Id]; + Next = -1; + if ( Count == 1 ) + Next = pSupp0[Id] == i ? -1 : pSupp0[Id]; + else if ( Count == 2 ) + { + if ( pSupp0[Id] == i && pSupp1[Id] != i ) + Next = pSupp1[Id]; + else if ( pSupp1[Id] == i && pSupp0[Id] != i ) + Next = pSupp0[Id]; + } + if ( Next >= 0 ) + { + Vec_IntWriteEntry( vNexts, i, Next ); + Vec_IntWriteEntry( vAvail, Next, 1 ); + } + } + ABC_FREE( pSuppN ); + ABC_FREE( pSupp0 ); + ABC_FREE( pSupp1 ); + Vec_IntForEachEntry( vNexts, Spot, i ) if ( Spot >= 0 && Vec_IntEntry(vAvail, i) == 0 ) Vec_IntPush( vHeads, i ); @@ -1366,11 +1914,13 @@ Vec_Int_t * Gia_ManFindStopFlops( Gia_Man_t * p, int nFlopIncFreq, int fVerbose } } if ( fVerbose && vRes ) + { printf( "Detected %d sequence%s containing %d flops.\n", nItems, nItems > 1 ? "s":"", Vec_IntSize(vRes) ); + fflush( stdout ); + } Vec_IntFree( vNexts ); Vec_IntFree( vAvail ); Vec_IntFree( vHeads ); - Vec_WecFree( vSupps ); return vRes; } Gia_Man_t * Gia_ManDupStopsAdd( Gia_Man_t * p, Vec_Int_t * vStops ) diff --git a/src/proof/cec/cecCorrDyn.c b/src/proof/cec/cecCorrDyn.c new file mode 100644 index 0000000000..2d9beca7f7 --- /dev/null +++ b/src/proof/cec/cecCorrDyn.c @@ -0,0 +1,698 @@ +/**CFile**************************************************************** + + FileName [cecCorrDyn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Dynamic SRM manager for &scorr.] + + Author [Xiran Zhao] + + Affiliation [University of Chinese Academy of Sciences] + + Date [Ver. 1.0. Started - Jun 2026.] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Cec_DynSrm_t_ +{ + Gia_Man_t * pAig; // host AIG; owned by caller + Cec_IncrMgr_t * pIncr; // active-list manager; owned by caller + Gia_Man_t * pCore; // persistent SRM core without COs + Cbs_Man_t * pCbs; // resident circuit-SAT manager on pCore + int nCoreObjsAtReset; // real post-build pCore size after the last cold (re)build, for compaction (0 until that build finishes) + Vec_Int_t * vSpecLits; // cached core literals, indexed by frame/object + Vec_Int_t * vOutLits; // core literals selected as current SAT outputs + Vec_Int_t * vCopyTouched; // core ANDs copied into the current view + Vec_Int_t * vPiMap; // host obj id -> PI index + Vec_Int_t * vRoMap; // host obj id -> RO index + // Phase-2 measurement (behavior-preserving): per-key stamp used to count the + // union of true-value (no repr substitution) cones of the active pairs. + int * pTrueMark; // size = nFramesTotal * nObjs; 0 = unvisited + int nTrueStamp; // current visit stamp + int nObjs; + int nPis; + int nRegs; + int nFramesTotal; + int nCoreCiNum; + int nBuilds; + int nBuildsActive; + int nCoreResets; + int nCoreCompactions; + int nCoreBuilds; + int nViewBuilds; + int nCacheFullClears; + int nCacheLocalClears; + int nCacheLocalEntries; + int nOutLitsLast; + int nOutLitsMax; + int nCoreObjsLast; + int nCoreObjsMax; + int nViewObjsLast; + int nViewObjsMax; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// Active-pair selection mirrors incremental mode: a pair is active iff an endpoint is +// in the alias-aware TFO (or, in ring mode, the ring edge itself changed). The +// earlier "pending" set that force-re-emitted still-merged SAT pairs has been +// removed: per md/scorr_i_correctness_bug_report.md the alias-aware TFO is the +// real fix, and the retry/pending protection was shown to be both unnecessary +// and incomplete. +static int Cec_DynSrmActiveConst( Cec_DynSrm_t * p, int * pTfoMark, int ObjId ) +{ + (void)p; + return pTfoMark != NULL && pTfoMark[ObjId]; +} + +static int Cec_DynSrmActivePair( Cec_DynSrm_t * p, int * pTfoMark, int fRings, int iPrev, int iObj ) +{ + if ( pTfoMark == NULL ) + return 0; + if ( !fRings ) + return pTfoMark[iPrev] || pTfoMark[iObj]; + return pTfoMark[iPrev] || pTfoMark[iObj] || + Cec_IncrMgrRingEdgeChanged( p->pIncr, iPrev, iObj ); +} + +static int Cec_DynSrmEmitModeAccept( int fActive, Cec_IncrEmitMode_t Mode ) +{ + return Mode == CEC_EMIT_ALL || + (Mode == CEC_EMIT_ACTIVE && fActive) || + (Mode == CEC_EMIT_SKIPPED && !fActive); +} + +static int Cec_DynSrmCacheIndex( Cec_DynSrm_t * p, int f, int ObjId ) +{ + assert( f >= 0 && f < p->nFramesTotal ); + assert( ObjId >= 0 && ObjId < p->nObjs ); + return f * p->nObjs + ObjId; +} + +static int Cec_DynSrmCacheRead( Cec_DynSrm_t * p, int f, Gia_Obj_t * pObj ) +{ + return Vec_IntEntry( p->vSpecLits, Cec_DynSrmCacheIndex(p, f, Gia_ObjId(p->pAig, pObj)) ); +} + +static void Cec_DynSrmCacheWrite( Cec_DynSrm_t * p, int f, Gia_Obj_t * pObj, int Lit ) +{ + Vec_IntWriteEntry( p->vSpecLits, Cec_DynSrmCacheIndex(p, f, Gia_ObjId(p->pAig, pObj)), Lit ); +} + +static int Cec_DynSrmHostPiLit( Cec_DynSrm_t * p, int f, Gia_Obj_t * pObj ) +{ + int ObjId = Gia_ObjId( p->pAig, pObj ); + int iPi = Vec_IntEntry( p->vPiMap, ObjId ); + assert( iPi >= 0 && iPi < p->nPis ); + assert( f >= 0 && f < p->nFramesTotal ); + return Gia_ManCiLit( p->pCore, p->nRegs + f * p->nPis + iPi ); +} + +static int Cec_DynSrmHostRoLit( Cec_DynSrm_t * p, Gia_Obj_t * pObj ) +{ + int ObjId = Gia_ObjId( p->pAig, pObj ); + int iRo = Vec_IntEntry( p->vRoMap, ObjId ); + assert( iRo >= 0 && iRo < p->nRegs ); + return Gia_ManCiLit( p->pCore, iRo ); +} + +static void Cec_DynSrmResetCore( Cec_DynSrm_t * p ) +{ + if ( p->pCbs ) // stop resident solver before its pCore is freed + Cbs_ManStop( p->pCbs ); + p->pCbs = NULL; + if ( p->pCore ) + Gia_ManStop( p->pCore ); + p->pCore = NULL; + p->nCoreObjsAtReset = 0; + Vec_IntFreeP( &p->vSpecLits ); + Vec_IntFreeP( &p->vOutLits ); + Vec_IntFreeP( &p->vCopyTouched ); + Vec_IntFreeP( &p->vPiMap ); + Vec_IntFreeP( &p->vRoMap ); + ABC_FREE( p->pTrueMark ); + p->nTrueStamp = 0; + p->nObjs = p->nPis = p->nRegs = p->nFramesTotal = p->nCoreCiNum = 0; +} + +// pCore is append-only (strash never frees stale nodes from earlier rounds' +// reductions), so under long refinement it grows unboundedly and the resident +// solver's per-round sync/solve walks an ever-larger graph. At a quiescent +// point (start of a build) cold-rebuild once it exceeds a multiple of its +// post-build size; the rebuilt core re-materializes only the live active cones. +#define CEC_DYN_COMPACT_MULT 4 + +static int Cec_DynSrmShouldCompact( Cec_DynSrm_t * p ) +{ + // 64-bit multiply: nCoreObjsAtReset can reach tens of millions (the growth + // case this guards), so CEC_DYN_COMPACT_MULT * it must not overflow int. + return p->nCoreObjsAtReset > 0 && + Gia_ManObjNum(p->pCore) > (ABC_INT64_T)CEC_DYN_COMPACT_MULT * p->nCoreObjsAtReset; +} + +static void Cec_DynSrmEnsureCore( Cec_DynSrm_t * p, int nFrames, int fScorr ) +{ + Gia_Obj_t * pObj; + int f, i, nFramesTotal = nFrames + fScorr; + int fSameShape = ( p->pCore != NULL && + p->nObjs == Gia_ManObjNum(p->pAig) && + p->nPis == Gia_ManPiNum(p->pAig) && + p->nRegs == Gia_ManRegNum(p->pAig) && + p->nFramesTotal == nFramesTotal ); + if ( fSameShape && !Cec_DynSrmShouldCompact(p) ) + return; + if ( fSameShape ) // reusable shape but bloated: cold-rebuild + p->nCoreCompactions++; + Cec_DynSrmResetCore( p ); + p->nObjs = Gia_ManObjNum( p->pAig ); + p->nPis = Gia_ManPiNum( p->pAig ); + p->nRegs = Gia_ManRegNum( p->pAig ); + p->nFramesTotal = nFramesTotal; + p->vSpecLits = Vec_IntStartFull( p->nFramesTotal * p->nObjs ); + p->vOutLits = Vec_IntAlloc( 1000 ); + p->vCopyTouched = Vec_IntAlloc( 1000 ); + p->vPiMap = Vec_IntStartFull( p->nObjs ); + p->vRoMap = Vec_IntStartFull( p->nObjs ); + p->pTrueMark = ABC_CALLOC( int, p->nFramesTotal * p->nObjs ); + p->nTrueStamp = 0; + p->pCore = Gia_ManStart( Abc_MaxInt( p->nFramesTotal * p->nObjs, 1000 ) ); + p->pCore->pName = Abc_UtilStrsav( p->pAig->pName ); + p->pCore->pSpec = Abc_UtilStrsav( p->pAig->pSpec ); + Gia_ManHashAlloc( p->pCore ); + Gia_ManForEachRo( p->pAig, pObj, i ) + { + Vec_IntWriteEntry( p->vRoMap, Gia_ObjId(p->pAig, pObj), i ); + Gia_ManAppendCi( p->pCore ); + } + Gia_ManForEachPi( p->pAig, pObj, i ) + Vec_IntWriteEntry( p->vPiMap, Gia_ObjId(p->pAig, pObj), i ); + for ( f = 0; f < p->nFramesTotal; f++ ) + Gia_ManForEachPi( p->pAig, pObj, i ) + Gia_ManAppendCi( p->pCore ); + p->nCoreCiNum = Gia_ManCiNum( p->pCore ); + assert( p->nCoreCiNum == p->nRegs + p->nFramesTotal * p->nPis ); + // leave nCoreObjsAtReset == 0 (set by ResetCore): only the CIs exist here, the + // live cones are materialized later in BuildCore, so the real post-build size + // is recorded there. + p->nCoreResets++; +} + +static void Cec_DynSrmInvalidateCache( Cec_DynSrm_t * p, int * pTfoMask ) +{ + int f, i, Counter = 0; + assert( p->vSpecLits != NULL ); + if ( pTfoMask == NULL ) + { + Vec_IntFill( p->vSpecLits, p->nFramesTotal * p->nObjs, -1 ); + p->nCacheFullClears++; + return; + } + for ( i = 0; i < p->nObjs; i++ ) + { + if ( !pTfoMask[i] ) + continue; + for ( f = 0; f < p->nFramesTotal; f++ ) + { + Vec_IntWriteEntry( p->vSpecLits, Cec_DynSrmCacheIndex(p, f, i), -1 ); + Counter++; + } + } + p->nCacheLocalClears++; + p->nCacheLocalEntries += Counter; +} + +static int Cec_DynSrmSpecLit( Cec_DynSrm_t * p, Gia_Obj_t * pObj, int f, int nPrefix ); +static int Cec_DynSrmSpecLitInit( Cec_DynSrm_t * p, Gia_Obj_t * pObj, int f, int nPrefix ); + +static int Cec_DynSrmRealLit( Cec_DynSrm_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) +{ + if ( Gia_ObjIsAnd(pObj) ) + { + int iLit0 = Cec_DynSrmSpecLit( p, Gia_ObjFanin0(pObj), f, nPrefix ); + int iLit1 = Cec_DynSrmSpecLit( p, Gia_ObjFanin1(pObj), f, nPrefix ); + iLit0 = Abc_LitNotCond( iLit0, Gia_ObjFaninC0(pObj) ); + iLit1 = Abc_LitNotCond( iLit1, Gia_ObjFaninC1(pObj) ); + return Gia_ManHashAnd( p->pCore, iLit0, iLit1 ); + } + if ( Gia_ObjIsPi(p->pAig, pObj) ) + return Cec_DynSrmHostPiLit( p, f, pObj ); + if ( f == 0 ) + { + assert( Gia_ObjIsRo(p->pAig, pObj) ); + return Cec_DynSrmSpecLit( p, pObj, f, nPrefix ); + } + assert( Gia_ObjIsRo(p->pAig, pObj) ); + pObj = Gia_ObjRoToRi( p->pAig, pObj ); + { + int iLit = Cec_DynSrmSpecLit( p, Gia_ObjFanin0(pObj), f-1, nPrefix ); + return Abc_LitNotCond( iLit, Gia_ObjFaninC0(pObj) ); + } +} + +static int Cec_DynSrmSpecLit( Cec_DynSrm_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) +{ + Gia_Obj_t * pRepr; + int iLit; + if ( Gia_ObjIsConst0(pObj) ) + return 0; + iLit = Cec_DynSrmCacheRead( p, f, pObj ); + if ( iLit >= 0 ) + return iLit; + if ( Gia_ObjIsPi(p->pAig, pObj) ) + { + iLit = Cec_DynSrmHostPiLit( p, f, pObj ); + Cec_DynSrmCacheWrite( p, f, pObj, iLit ); + return iLit; + } + if ( f >= nPrefix && (pRepr = Gia_ObjReprObj(p->pAig, Gia_ObjId(p->pAig, pObj))) ) + { + iLit = Cec_DynSrmSpecLit( p, pRepr, f, nPrefix ); + iLit = Abc_LitNotCond( iLit, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + Cec_DynSrmCacheWrite( p, f, pObj, iLit ); + return iLit; + } + if ( f == 0 && Gia_ObjIsRo(p->pAig, pObj) ) + { + iLit = Cec_DynSrmHostRoLit( p, pObj ); + Cec_DynSrmCacheWrite( p, f, pObj, iLit ); + return iLit; + } + assert( Gia_ObjIsCand(pObj) ); + iLit = Cec_DynSrmRealLit( p, pObj, f, nPrefix ); + Cec_DynSrmCacheWrite( p, f, pObj, iLit ); + return iLit; +} + +static int Cec_DynSrmRealLitInit( Cec_DynSrm_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) +{ + if ( Gia_ObjIsAnd(pObj) ) + { + int iLit0 = Cec_DynSrmSpecLitInit( p, Gia_ObjFanin0(pObj), f, nPrefix ); + int iLit1 = Cec_DynSrmSpecLitInit( p, Gia_ObjFanin1(pObj), f, nPrefix ); + iLit0 = Abc_LitNotCond( iLit0, Gia_ObjFaninC0(pObj) ); + iLit1 = Abc_LitNotCond( iLit1, Gia_ObjFaninC1(pObj) ); + return Gia_ManHashAnd( p->pCore, iLit0, iLit1 ); + } + if ( Gia_ObjIsPi(p->pAig, pObj) ) + return Cec_DynSrmHostPiLit( p, f, pObj ); + if ( f == 0 ) + { + assert( Gia_ObjIsRo(p->pAig, pObj) ); + return Cec_DynSrmSpecLitInit( p, pObj, f, nPrefix ); + } + assert( Gia_ObjIsRo(p->pAig, pObj) ); + pObj = Gia_ObjRoToRi( p->pAig, pObj ); + { + int iLit = Cec_DynSrmSpecLitInit( p, Gia_ObjFanin0(pObj), f-1, nPrefix ); + return Abc_LitNotCond( iLit, Gia_ObjFaninC0(pObj) ); + } +} + +// BMC/init SRM semantics differ from the inductive SRM in one important way: +// frame-0 ROs are fixed to the all-zero initial state. The core still keeps +// RO CIs first to preserve the CEX-input layout expected by resimulation, but +// these CIs are intentionally unused in init-mode cones. +static int Cec_DynSrmSpecLitInit( Cec_DynSrm_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) +{ + Gia_Obj_t * pRepr; + int iLit; + if ( Gia_ObjIsConst0(pObj) ) + return 0; + iLit = Cec_DynSrmCacheRead( p, f, pObj ); + if ( iLit >= 0 ) + return iLit; + if ( Gia_ObjIsPi(p->pAig, pObj) ) + { + iLit = Cec_DynSrmHostPiLit( p, f, pObj ); + Cec_DynSrmCacheWrite( p, f, pObj, iLit ); + return iLit; + } + if ( f >= nPrefix && (pRepr = Gia_ObjReprObj(p->pAig, Gia_ObjId(p->pAig, pObj))) ) + { + iLit = Cec_DynSrmSpecLitInit( p, pRepr, f, nPrefix ); + iLit = Abc_LitNotCond( iLit, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + Cec_DynSrmCacheWrite( p, f, pObj, iLit ); + return iLit; + } + if ( f == 0 && Gia_ObjIsRo(p->pAig, pObj) ) + { + Cec_DynSrmCacheWrite( p, f, pObj, 0 ); + return 0; + } + assert( Gia_ObjIsCand(pObj) ); + iLit = Cec_DynSrmRealLitInit( p, pObj, f, nPrefix ); + Cec_DynSrmCacheWrite( p, f, pObj, iLit ); + return iLit; +} + +static int Cec_DynSrmCopyLit_rec( Gia_Man_t * pCore, Gia_Man_t * pView, Vec_Int_t * vTouched, int iLit ) +{ + Gia_Obj_t * pObj; + int iObj, iLitCopy, iLit0, iLit1; + if ( iLit < 2 ) + return iLit; + iObj = Abc_Lit2Var( iLit ); + pObj = Gia_ManObj( pCore, iObj ); + if ( Gia_ObjIsCi(pObj) ) + { + assert( Gia_ManCiIdToId(pView, Gia_ObjCioId(pObj)) == iObj ); + return iLit; + } + iLitCopy = Gia_ObjCopyArray( pCore, iObj ); + if ( iLitCopy >= 0 ) + return Abc_LitNotCond( iLitCopy, Abc_LitIsCompl(iLit) ); + assert( Gia_ObjIsAnd(pObj) ); + iLit0 = Cec_DynSrmCopyLit_rec( pCore, pView, vTouched, Gia_ObjFaninLit0p(pCore, pObj) ); + iLit1 = Cec_DynSrmCopyLit_rec( pCore, pView, vTouched, Gia_ObjFaninLit1p(pCore, pObj) ); + iLitCopy = Gia_ManHashAnd( pView, iLit0, iLit1 ); + Gia_ObjSetCopyArray( pCore, iObj, iLitCopy ); + Vec_IntPush( vTouched, iObj ); + return Abc_LitNotCond( iLitCopy, Abc_LitIsCompl(iLit) ); +} + +static Gia_Man_t * Cec_DynSrmBuildView( Cec_DynSrm_t * p ) +{ + Gia_Man_t * pView; + Gia_Obj_t * pObj; + int i, iLit, iLitCopy; + pView = Gia_ManStart( Abc_MaxInt( p->nCoreCiNum + 100 * Vec_IntSize(p->vOutLits) + 100, 1000 ) ); + pView->pName = Abc_UtilStrsav( p->pAig->pName ); + pView->pSpec = Abc_UtilStrsav( p->pAig->pSpec ); + Gia_ManHashAlloc( pView ); + Vec_IntFillExtra( &p->pCore->vCopies, Gia_ManObjNum(p->pCore), -1 ); + Vec_IntClear( p->vCopyTouched ); + Gia_ManForEachCi( p->pCore, pObj, i ) + Gia_ManAppendCi( pView ); + Vec_IntForEachEntry( p->vOutLits, iLit, i ) + { + iLitCopy = Cec_DynSrmCopyLit_rec( p->pCore, pView, p->vCopyTouched, iLit ); + Gia_ManAppendCo( pView, iLitCopy ); + } + Vec_IntForEachEntry( p->vCopyTouched, iLit, i ) + Gia_ObjSetCopyArray( p->pCore, iLit, -1 ); + Vec_IntClear( p->vCopyTouched ); + Gia_ManHashStop( pView ); + p->nViewBuilds++; + p->nViewObjsLast = Gia_ManObjNum( pView ); + p->nViewObjsMax = Abc_MaxInt( p->nViewObjsMax, p->nViewObjsLast ); + return pView; +} + +Cec_DynSrm_t * Cec_DynSrmAlloc( Gia_Man_t * pAig, Cec_IncrMgr_t * pIncr ) +{ + Cec_DynSrm_t * p = ABC_CALLOC( Cec_DynSrm_t, 1 ); + p->pAig = pAig; + p->pIncr = pIncr; + return p; +} + +void Cec_DynSrmFree( Cec_DynSrm_t * p ) +{ + if ( p == NULL ) + return; + Cec_DynSrmResetCore( p ); + ABC_FREE( p ); +} + +void Cec_DynSrmPrintStats( Cec_DynSrm_t * p ) +{ + if ( p == NULL ) + return; + Abc_Print( 1, "DynSRM: builds = %d, active_builds = %d\n", + p->nBuilds, p->nBuildsActive ); + Abc_Print( 1, "DynSRM: core_resets = %d, compactions = %d, core_builds = %d, view_builds = %d, out_lits_last/max = %d/%d, core_objs_last/max = %d/%d, view_objs_last/max = %d/%d\n", + p->nCoreResets, p->nCoreCompactions, p->nCoreBuilds, p->nViewBuilds, + p->nOutLitsLast, p->nOutLitsMax, + p->nCoreObjsLast, p->nCoreObjsMax, + p->nViewObjsLast, p->nViewObjsMax ); + Abc_Print( 1, "DynSRM: cache_full_clears = %d, cache_local_clears = %d, cache_local_entries = %d\n", + p->nCacheFullClears, p->nCacheLocalClears, p->nCacheLocalEntries ); +} + +void Cec_DynSrmCountActivePairs( Cec_DynSrm_t * p, int fRings, int * pTfoMark, + int * pnTotal, int * pnActive ) +{ + Gia_Man_t * pAig = p->pAig; + Gia_Obj_t * pObj, * pRepr; + int i, iPrev, iObj; + *pnTotal = *pnActive = 0; + assert( pAig->pReprs != NULL ); + if ( fRings ) + { + Gia_ManForEachObj1( pAig, pObj, i ) + { + if ( Gia_ObjIsConst( pAig, i ) ) + { + (*pnTotal)++; + (*pnActive) += Cec_DynSrmActiveConst( p, pTfoMark, i ); + } + else if ( Gia_ObjIsHead( pAig, i ) ) + { + iPrev = i; + Gia_ClassForEachObj1( pAig, i, iObj ) + { + (*pnTotal)++; + (*pnActive) += Cec_DynSrmActivePair( p, pTfoMark, 1, iPrev, iObj ); + iPrev = iObj; + } + iObj = i; + { + (*pnTotal)++; + (*pnActive) += Cec_DynSrmActivePair( p, pTfoMark, 1, iPrev, iObj ); + } + } + } + } + else + { + Gia_ManForEachObj1( pAig, pObj, i ) + { + int idR; + pRepr = Gia_ObjReprObj( pAig, Gia_ObjId(pAig,pObj) ); + if ( pRepr == NULL ) + continue; + idR = Gia_ObjId( pAig, pRepr ); + (*pnTotal)++; + (*pnActive) += Cec_DynSrmActivePair( p, pTfoMark, 0, idR, i ); + } + } +} + +// Builds (or extends) the persistent COless pCore and selects this round's +// active-pair root literals into p->vOutLits / *pvOutputs. Shared by the view +// path (Cec_DynSrmBuild) and the persistent path (solve pCore directly). +void Cec_DynSrmBuildCore( Cec_DynSrm_t * p, int nFrames, int fScorr, + Vec_Int_t ** pvOutputs, int fRings, int * pTfoMask, Cec_IncrEmitMode_t Mode ) +{ + Gia_Obj_t * pObj, * pRepr; + int i, iPrev, iObj, iPrevNew, iObjNew, iPrevRaw, iObjRaw; + assert( p != NULL ); + assert( nFrames > 0 ); + assert( Gia_ManRegNum(p->pAig) > 0 ); + assert( p->pAig->pReprs != NULL ); + assert( Mode == CEC_EMIT_ALL || pTfoMask != NULL ); + p->nBuilds++; + if ( Mode == CEC_EMIT_ACTIVE ) + p->nBuildsActive++; + Cec_DynSrmEnsureCore( p, nFrames, fScorr ); + Cec_DynSrmInvalidateCache( p, Mode == CEC_EMIT_SKIPPED ? NULL : pTfoMask ); + Gia_ManSetPhase( p->pAig ); + *pvOutputs = Vec_IntAlloc( 1000 ); + Vec_IntClear( p->vOutLits ); + if ( fRings ) + { + Gia_ManForEachObj1( p->pAig, pObj, i ) + { + if ( Gia_ObjIsConst( p->pAig, i ) ) + { + int fActive = Cec_DynSrmActiveConst( p, pTfoMask, i ); + if ( !Cec_DynSrmEmitModeAccept(fActive, Mode) ) + continue; + iObjRaw = Cec_DynSrmRealLit( p, pObj, nFrames, 0 ); + iObjNew = Abc_LitNotCond( iObjRaw, Gia_ObjPhase(pObj) ); + if ( iObjNew != 0 ) + { + Vec_IntPush( *pvOutputs, 0 ); + Vec_IntPush( *pvOutputs, i ); + Vec_IntPush( p->vOutLits, iObjNew ); + } + } + else if ( Gia_ObjIsHead( p->pAig, i ) ) + { + iPrev = i; + Gia_ClassForEachObj1( p->pAig, i, iObj ) + { + int fActive = Cec_DynSrmActivePair( p, pTfoMask, 1, iPrev, iObj ); + if ( Cec_DynSrmEmitModeAccept(fActive, Mode) ) + { + iPrevRaw = Cec_DynSrmRealLit( p, Gia_ManObj(p->pAig, iPrev), nFrames, 0 ); + iObjRaw = Cec_DynSrmRealLit( p, Gia_ManObj(p->pAig, iObj), nFrames, 0 ); + iPrevNew = Abc_LitNotCond( iPrevRaw, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p->pAig, iPrev)) ); + iObjNew = Abc_LitNotCond( iObjRaw, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p->pAig, iObj)) ); + if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) + { + Vec_IntPush( *pvOutputs, iPrev ); + Vec_IntPush( *pvOutputs, iObj ); + Vec_IntPush( p->vOutLits, Gia_ManHashAnd(p->pCore, iPrevNew, Abc_LitNot(iObjNew)) ); + } + } + iPrev = iObj; + } + iObj = i; + { + int fActive = Cec_DynSrmActivePair( p, pTfoMask, 1, iPrev, iObj ); + if ( Cec_DynSrmEmitModeAccept(fActive, Mode) ) + { + iPrevRaw = Cec_DynSrmRealLit( p, Gia_ManObj(p->pAig, iPrev), nFrames, 0 ); + iObjRaw = Cec_DynSrmRealLit( p, Gia_ManObj(p->pAig, iObj), nFrames, 0 ); + iPrevNew = Abc_LitNotCond( iPrevRaw, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p->pAig, iPrev)) ); + iObjNew = Abc_LitNotCond( iObjRaw, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p->pAig, iObj)) ); + if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) + { + Vec_IntPush( *pvOutputs, iPrev ); + Vec_IntPush( *pvOutputs, iObj ); + Vec_IntPush( p->vOutLits, Gia_ManHashAnd(p->pCore, iPrevNew, Abc_LitNot(iObjNew)) ); + } + } + } + } + } + } + else + { + Gia_ManForEachObj1( p->pAig, pObj, i ) + { + pRepr = Gia_ObjReprObj( p->pAig, Gia_ObjId(p->pAig,pObj) ); + if ( pRepr == NULL ) + continue; + { + int idR = Gia_ObjId(p->pAig, pRepr); + int fActive = Cec_DynSrmActivePair( p, pTfoMask, 0, idR, i ); + if ( !Cec_DynSrmEmitModeAccept(fActive, Mode) ) + continue; + } + iPrevRaw = Gia_ObjIsConst(p->pAig, i)? 0 : Cec_DynSrmRealLit( p, pRepr, nFrames, 0 ); + iObjRaw = Cec_DynSrmRealLit( p, pObj, nFrames, 0 ); + iPrevNew = iPrevRaw; + iObjNew = Abc_LitNotCond( iObjRaw, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + if ( iPrevNew != iObjNew ) + { + Vec_IntPush( *pvOutputs, Gia_ObjId(p->pAig, pRepr) ); + Vec_IntPush( *pvOutputs, Gia_ObjId(p->pAig, pObj) ); + Vec_IntPush( p->vOutLits, Gia_ManHashXor(p->pCore, iPrevNew, iObjNew) ); + } + } + } + p->nCoreBuilds++; + p->nOutLitsLast = Vec_IntSize( p->vOutLits ); + p->nOutLitsMax = Abc_MaxInt( p->nOutLitsMax, p->nOutLitsLast ); + p->nCoreObjsLast = Gia_ManObjNum( p->pCore ); + if ( p->nCoreObjsAtReset == 0 ) // first build after a cold (re)set: record the + p->nCoreObjsAtReset = p->nCoreObjsLast; // real post-build size as the compaction baseline + p->nCoreObjsMax = Abc_MaxInt( p->nCoreObjsMax, p->nCoreObjsLast ); +} + +Gia_Man_t * Cec_DynSrmBuild( Cec_DynSrm_t * p, int nFrames, int fScorr, + Vec_Int_t ** pvOutputs, int fRings, int * pTfoMask, Cec_IncrEmitMode_t Mode ) +{ + Cec_DynSrmBuildCore( p, nFrames, fScorr, pvOutputs, fRings, pTfoMask, Mode ); + return Cec_DynSrmBuildView( p ); +} + +// BMC/init variant of Cec_DynSrmBuildCore. It mirrors +// Gia_ManCorrSpecReduceInit(): ROs at frame 0 are constants, representatives +// are applied only at frames >= nPrefix, and every BMC endpoint frame in +// [nPrefix, nPrefix+nFrames) emits the current (repr,obj) candidates. +void Cec_DynSrmBuildCoreInit( Cec_DynSrm_t * p, int nFrames, int nPrefix, int fScorr, + Vec_Int_t ** pvOutputs, int * pTfoMask, Cec_IncrEmitMode_t Mode ) +{ + Gia_Obj_t * pObj, * pRepr; + int f, i, iPrevNew, iObjNew; + assert( p != NULL ); + assert( (!fScorr && nFrames > 1) || (fScorr && nFrames > 0) || nPrefix ); + assert( Gia_ManRegNum(p->pAig) > 0 ); + assert( p->pAig->pReprs != NULL ); + assert( Mode == CEC_EMIT_ALL || pTfoMask != NULL ); + p->nBuilds++; + if ( Mode == CEC_EMIT_ACTIVE ) + p->nBuildsActive++; + Cec_DynSrmEnsureCore( p, nFrames + nPrefix, fScorr ); + Cec_DynSrmInvalidateCache( p, Mode == CEC_EMIT_SKIPPED ? NULL : pTfoMask ); + Gia_ManSetPhase( p->pAig ); + *pvOutputs = Vec_IntAlloc( 1000 ); + Vec_IntClear( p->vOutLits ); + for ( f = nPrefix; f < nFrames + nPrefix; f++ ) + { + Gia_ManForEachObj1( p->pAig, pObj, i ) + { + pRepr = Gia_ObjReprObj( p->pAig, Gia_ObjId(p->pAig,pObj) ); + if ( pRepr == NULL ) + continue; + { + int idR = Gia_ObjId(p->pAig, pRepr); + int fActive = pTfoMask != NULL && (pTfoMask[i] || pTfoMask[idR]); + if ( !Cec_DynSrmEmitModeAccept(fActive, Mode) ) + continue; + } + iPrevNew = Gia_ObjIsConst(p->pAig, i)? 0 : Cec_DynSrmRealLitInit( p, pRepr, f, nPrefix ); + iObjNew = Cec_DynSrmRealLitInit( p, pObj, f, nPrefix ); + iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + if ( iPrevNew != iObjNew ) + { + Vec_IntPush( *pvOutputs, Gia_ObjId(p->pAig, pRepr) ); + Vec_IntPush( *pvOutputs, Gia_ObjId(p->pAig, pObj) ); + Vec_IntPush( p->vOutLits, Gia_ManHashXor(p->pCore, iPrevNew, iObjNew) ); + } + } + } + p->nCoreBuilds++; + p->nOutLitsLast = Vec_IntSize( p->vOutLits ); + p->nOutLitsMax = Abc_MaxInt( p->nOutLitsMax, p->nOutLitsLast ); + p->nCoreObjsLast = Gia_ManObjNum( p->pCore ); + if ( p->nCoreObjsAtReset == 0 ) + p->nCoreObjsAtReset = p->nCoreObjsLast; + p->nCoreObjsMax = Abc_MaxInt( p->nCoreObjsMax, p->nCoreObjsLast ); +} + +Gia_Man_t * Cec_DynSrmBuildInit( Cec_DynSrm_t * p, int nFrames, int nPrefix, int fScorr, + Vec_Int_t ** pvOutputs, int * pTfoMask, Cec_IncrEmitMode_t Mode ) +{ + Cec_DynSrmBuildCoreInit( p, nFrames, nPrefix, fScorr, pvOutputs, pTfoMask, Mode ); + return Cec_DynSrmBuildView( p ); +} + +// This round's active-pair root literals (used by the main loop for counts). +Vec_Int_t * Cec_DynSrmOutLits( Cec_DynSrm_t * p ) { return p->vOutLits; } + +// Solves this round's root literals on the persistent pCore with the resident +// circuit-SAT manager (allocated lazily; re-created after a core reset/compaction +// since its pAig is freed there). The CI-layout assert guards the CEX CioId -> +// resim-input contract that the discarded view used to enforce in the main loop. +Vec_Int_t * Cec_DynSrmSolve( Cec_DynSrm_t * p, int nConfs, Vec_Str_t ** pvStatus ) +{ + assert( Gia_ManRegNum(p->pCore) == 0 ); + assert( Gia_ManCiNum(p->pCore) == p->nRegs + p->nFramesTotal * p->nPis ); + if ( p->pCbs == NULL ) + p->pCbs = Cbs_ManAlloc( p->pCore ); + Cbs_ManSetConflictNum( p->pCbs, nConfs ); + return Cbs_ManSolveRoots( p->pCbs, p->vOutLits, pvStatus, 0 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END diff --git a/src/proof/cec/cecCorrIncr.c b/src/proof/cec/cecCorrIncr.c new file mode 100644 index 0000000000..8d5a1f2446 --- /dev/null +++ b/src/proof/cec/cecCorrIncr.c @@ -0,0 +1,690 @@ +/**CFile**************************************************************** + + FileName [cecCorrIncr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Incremental active-list / TFO filter for &scorr.] + + Author [Xiran Zhao] + + Affiliation [University of Chinese Academy of Sciences] + + Date [Ver. 1.0. Started - May 2026.] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the incremental active-list manager.] + + Description [The manager owns one snapshot of pReprs/pNexts plus the + TFO bookkeeping arrays. pAig must outlive the manager; the manager + never duplicates the AIG, only references it. If the host AIG does + not yet carry a static fanout, this routine builds it and remembers + to tear it down on Free.] + + SideEffects [Builds static fanout on pAig if not already present.] + + SeeAlso [] + +***********************************************************************/ +Cec_IncrMgr_t * Cec_IncrMgrAlloc( Gia_Man_t * pAig, int nFrames ) +{ + Cec_IncrMgr_t * p = ABC_CALLOC( Cec_IncrMgr_t, 1 ); + p->pAig = pAig; + p->nFrames = nFrames; + p->nObjs = Gia_ManObjNum(pAig); + p->vReprPrev = Vec_IntStartFull( p->nObjs ); + p->vNextPrev = Vec_IntStart( p->nObjs ); + p->vSeeds = Vec_IntAlloc( 64 ); + p->vTfoNodes = Vec_IntAlloc( 1024 ); + p->pTfoMark = ABC_CALLOC( int, p->nObjs ); + p->vAliasHeads = Vec_IntStartFull( p->nObjs ); + p->vAliasNext = Vec_IntStartFull( p->nObjs ); + p->vBfsCur = Vec_IntAlloc( 1024 ); + p->vBfsNext = Vec_IntAlloc( 1024 ); + if ( pAig->vFanout == NULL ) + { + Gia_ManStaticFanoutStart( pAig ); + p->fOwnsFanout = 1; + } + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the incremental manager.] + + Description [Releases all internal vectors and the TFO mark array. + If the manager built the static fanout on Alloc, it is also torn + down here. Safe to call with a NULL pointer.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_IncrMgrFree( Cec_IncrMgr_t * p ) +{ + if ( p == NULL ) return; + if ( p->fOwnsFanout ) + Gia_ManStaticFanoutStop( p->pAig ); + Vec_IntFree( p->vReprPrev ); + Vec_IntFree( p->vNextPrev ); + Vec_IntFree( p->vSeeds ); + Vec_IntFree( p->vTfoNodes ); + Vec_IntFree( p->vAliasHeads ); + Vec_IntFree( p->vAliasNext ); + Vec_IntFree( p->vBfsCur ); + Vec_IntFree( p->vBfsNext ); + ABC_FREE( p->pTfoMark ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Snapshots the current equivalence-class state.] + + Description [Copies the per-node pReprs and pNexts arrays into the + manager so the next iteration can diff against the class state whose + pairs were just emitted into the SRM. Should be called after SRM + construction and before SAT/sim refinement: the snapshot then reflects + exactly the pairs the SAT solver was asked to prove. O(N).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cec_IncrMgrSnapshotClasses( Cec_IncrMgr_t * p ) +{ + Gia_Man_t * pAig = p->pAig; + int i; + assert( pAig->pReprs != NULL ); + for ( i = 0; i < p->nObjs; i++ ) + { + Vec_IntWriteEntry( p->vReprPrev, i, Gia_ObjRepr(pAig, i) ); + Vec_IntWriteEntry( p->vNextPrev, i, pAig->pNexts ? Gia_ObjNext(pAig, i) : 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Computes the seed set for the next TFO BFS.] + + Description [Returns the number of nodes whose representative changed + since the last snapshot and stores them in vSeeds. Does not update + the snapshot. + + pNexts changes are intentionally excluded here: a ring-link rewrite is + an edge-local event that creates a new ring edge to reprove, not a new + fanout cone, so it is handled by Cec_IncrMgrRingEdgeChanged at SRM + emission time.] + + SideEffects [] + + SeeAlso [Cec_IncrMgrComputeTfo Cec_IncrMgrRingEdgeChanged] + +***********************************************************************/ +int Cec_IncrMgrComputeSeeds( Cec_IncrMgr_t * p ) +{ + Gia_Man_t * pAig = p->pAig; + int i, reprNew, reprOld; + Vec_IntClear( p->vSeeds ); + for ( i = 1; i < p->nObjs; i++ ) + { + reprNew = Gia_ObjRepr( pAig, i ); + reprOld = Vec_IntEntry( p->vReprPrev, i ); + if ( reprNew != reprOld ) + Vec_IntPush( p->vSeeds, i ); + } + return Vec_IntSize( p->vSeeds ); +} + +/**Function************************************************************* + + Synopsis [Counts nodes whose ring-list successor changed.] + + Description [Used only for convergence and fallback decisions. These + nodes are NOT TFO seeds, because a pNexts-only change creates a new + ring edge (proved edge-locally by the active SRM builder) rather than + a new fanout cone to re-prove. Returns 0 when pNexts is unallocated, + i.e. when ring mode is off.] + + SideEffects [] + + SeeAlso [Cec_IncrMgrComputeSeeds] + +***********************************************************************/ +int Cec_IncrMgrCountNextChanges( Cec_IncrMgr_t * p ) +{ + Gia_Man_t * pAig = p->pAig; + int i, nChanges = 0; + if ( pAig->pNexts == NULL ) + return 0; + for ( i = 1; i < p->nObjs; i++ ) + nChanges += Gia_ObjNext( pAig, i ) != Vec_IntEntry( p->vNextPrev, i ); + return nChanges; +} + +/**Function************************************************************* + + Synopsis [Detects whether a ring edge is new since the last snapshot.] + + Description [Ring classes store list edges explicitly in pNexts, but + the SRM also proves the implicit closing edge tail -> head. For an + explicit edge, the edge is unchanged iff the predecessor's pNexts slot + still names the same successor. For the closing edge there is no + pNexts slot to compare, so we reconstruct whether the same tail/head + pair already existed in the previous snapshot: the tail must have been + pointing to the head (closing the ring) and the head must still have + been a class root. Returns 1 to mean "must be re-proved". Passing a + NULL manager or a non-ring AIG returns 0 (no edge work needed).] + + SideEffects [] + + SeeAlso [Cec_IncrMgrCountActivePairs] + +***********************************************************************/ +int Cec_IncrMgrRingEdgeChanged( Cec_IncrMgr_t * p, int iPrev, int iObj ) +{ + Gia_Man_t * pAig; + int iNextCur, iNextOld; + if ( p == NULL ) + return 0; + pAig = p->pAig; + if ( pAig->pNexts == NULL ) + return 0; + iNextCur = Gia_ObjNext( pAig, iPrev ); + iNextOld = Vec_IntEntry( p->vNextPrev, iPrev ); + if ( iNextCur == iObj ) + return iNextOld != iObj; + if ( iNextCur > 0 ) + return 1; // conservative: should not happen for callers below + // Closing edge: prove if the previous snapshot did not already contain + // exactly this tail/head pair as a ring's closing edge. + return iNextOld > 0 || + Vec_IntEntry( p->vReprPrev, iPrev ) != iObj || + Vec_IntEntry( p->vReprPrev, iObj ) != GIA_VOID || + Vec_IntEntry( p->vNextPrev, iObj ) <= 0; +} + +/**Function************************************************************* + + Synopsis [Counts total and active candidate pairs before SRM build.] + + Description [Mirrors the PO-emission loops in the active SRM builders + but stops before constructing the unrolled network: it walks every + candidate pair the SRM would emit and tallies how many would survive + the active filter (pTfoMark plus the ring-edge override). The count + is approximate because SRM construction can still simplify a pair + away after the literal it represents collapses; it is used only to + decide whether the active filter saves enough work to be worth the + bookkeeping (the main loop falls back to the full SRM above ~70% + active pairs). When pTfoMark is NULL every pair is counted active.] + + SideEffects [] + + SeeAlso [Gia_ManCorrSpecReduce_Emit] + +***********************************************************************/ +void Cec_IncrMgrCountActivePairs( Cec_IncrMgr_t * p, int fRings, int * pTfoMark, + int * pnTotal, int * pnActive ) +{ + Gia_Man_t * pAig = p->pAig; + Gia_Obj_t * pObj, * pRepr; + int i, iPrev, iObj; + *pnTotal = *pnActive = 0; + assert( pAig->pReprs != NULL ); + if ( fRings ) + { + Gia_ManForEachObj1( pAig, pObj, i ) + { + if ( Gia_ObjIsConst( pAig, i ) ) + { + (*pnTotal)++; + (*pnActive) += pTfoMark == NULL || pTfoMark[i]; + } + else if ( Gia_ObjIsHead( pAig, i ) ) + { + iPrev = i; + Gia_ClassForEachObj1( pAig, i, iObj ) + { + (*pnTotal)++; + (*pnActive) += pTfoMark == NULL || pTfoMark[iPrev] || pTfoMark[iObj] || + Cec_IncrMgrRingEdgeChanged( p, iPrev, iObj ); + iPrev = iObj; + } + iObj = i; // closing edge tail -> head + (*pnTotal)++; + (*pnActive) += pTfoMark == NULL || pTfoMark[iPrev] || pTfoMark[iObj] || + Cec_IncrMgrRingEdgeChanged( p, iPrev, iObj ); + } + } + } + else + { + Gia_ManForEachObj1( pAig, pObj, i ) + { + int idR; + pRepr = Gia_ObjReprObj( pAig, Gia_ObjId(pAig,pObj) ); + if ( pRepr == NULL ) + continue; + idR = Gia_ObjId( pAig, pRepr ); + (*pnTotal)++; + (*pnActive) += pTfoMark == NULL || pTfoMark[i] || pTfoMark[idR]; + } + } +} + +/**Function************************************************************* + + Synopsis [Forward TFO BFS from seeds across nFrames unrollings.] + + Description [Marks pTfoMark[id]=1 for every SRM node reachable from + any seed within nFrames combinational+sequential steps. Besides AIG + fanouts, the walk follows representative-to-member alias edges because + Gia_ManCorrSpecReduce_rec(member) uses repr(member) directly. Missing + these edges can reuse an obsolete UNSAT result when a representative's + reduced value changes through another member's fanout cone. + + Each frame performs a combinational fanout BFS; RI fanouts cross to the + next frame by following Gia_ObjRiToRo to the corresponding register + output. After nFrames cross-frame jumps the search stops, since pairs + deeper than that cannot depend on the seeds within an nFrames-deep SRM. + + RI nodes themselves are intentionally not marked: SRM emission is + keyed on AIG candidate nodes (ANDs and CIs) and never on COs, so + marking RIs would only inflate the active set without enabling any + additional pair. + + Mark clearing is amortised: vTfoNodes records every id touched in + the previous round and is iterated to zero only those entries, so + the routine never sweeps the full N-sized array. Cost per call is + O(|TFO_k| * avg_fanout).] + + SideEffects [] + + SeeAlso [Cec_IncrMgrComputeSeeds] + +***********************************************************************/ +void Cec_IncrMgrComputeTfo( Cec_IncrMgr_t * p ) +{ + Gia_Man_t * pAig = p->pAig; + int * pMark = p->pTfoMark; + int f, i, k, Id, FanId, RoId, ReprId, AliasId; + + Vec_IntForEachEntry( p->vTfoNodes, Id, i ) + pMark[Id] = 0; + Vec_IntClear( p->vTfoNodes ); + Vec_IntClear( p->vBfsCur ); + Vec_IntClear( p->vBfsNext ); + + Vec_IntFill( p->vAliasHeads, p->nObjs, -1 ); + Vec_IntFill( p->vAliasNext, p->nObjs, -1 ); + for ( Id = 1; Id < p->nObjs; Id++ ) + { + ReprId = Gia_ObjRepr( pAig, Id ); + if ( ReprId <= 0 || ReprId == GIA_VOID ) + continue; + Vec_IntWriteEntry( p->vAliasNext, Id, Vec_IntEntry(p->vAliasHeads, ReprId) ); + Vec_IntWriteEntry( p->vAliasHeads, ReprId, Id ); + } + + Vec_IntForEachEntry( p->vSeeds, Id, i ) + { + if ( !pMark[Id] ) + { + pMark[Id] = 1; + Vec_IntPush( p->vTfoNodes, Id ); + Vec_IntPush( p->vBfsCur, Id ); + } + } + + for ( f = 0; f <= p->nFrames; f++ ) + { + int head = 0; + while ( head < Vec_IntSize(p->vBfsCur) ) + { + Gia_Obj_t * pFan; + Id = Vec_IntEntry( p->vBfsCur, head++ ); + for ( AliasId = Vec_IntEntry(p->vAliasHeads, Id); + AliasId >= 0; + AliasId = Vec_IntEntry(p->vAliasNext, AliasId) ) + { + if ( pMark[AliasId] ) + continue; + pMark[AliasId] = 1; + Vec_IntPush( p->vTfoNodes, AliasId ); + Vec_IntPush( p->vBfsCur, AliasId ); + } + int nFan = Gia_ObjFanoutNumId( pAig, Id ); + for ( k = 0; k < nFan; k++ ) + { + FanId = Gia_ObjFanoutId( pAig, Id, k ); + pFan = Gia_ManObj( pAig, FanId ); + if ( Gia_ObjIsRi(pAig, pFan) ) + { + if ( f < p->nFrames ) + { + RoId = Gia_ObjRiToRoId( pAig, FanId ); + if ( !pMark[RoId] ) + { + pMark[RoId] = 1; + Vec_IntPush( p->vTfoNodes, RoId ); + Vec_IntPush( p->vBfsNext, RoId ); + } + } + } + else if ( Gia_ObjIsCo(pFan) ) + { + // PO: not a candidate, skip + } + else + { + if ( !pMark[FanId] ) + { + pMark[FanId] = 1; + Vec_IntPush( p->vTfoNodes, FanId ); + Vec_IntPush( p->vBfsCur, FanId ); + } + } + } + } + Vec_IntClear( p->vBfsCur ); + Vec_IntAppend( p->vBfsCur, p->vBfsNext ); + Vec_IntClear( p->vBfsNext ); + if ( Vec_IntSize(p->vBfsCur) == 0 ) + break; + } +} + +/**Function************************************************************* + + Synopsis [Emission-filtered variant of Gia_ManCorrSpecReduce.] + + Description [Identical to Gia_ManCorrSpecReduce in its SRM topology + and speculative reduction; the only difference is PO emission. + CEC_EMIT_ACTIVE emits pairs selected by the incremental TFO filter. + CEC_EMIT_SKIPPED emits the exact complement for shadow validation. + A new or rewired ring edge is always active and can never be emitted + as skipped because it has no prior UNSAT result to reuse. + + Walking the full ring is required (rather than skipping unmarked + members) so iPrev stays aligned with the live class order; the active + predicate is evaluated only after the edge endpoints are known.] + + SideEffects [] + + SeeAlso [Gia_ManCorrSpecReduce Cec_IncrMgrCountActivePairs] + +***********************************************************************/ +Gia_Man_t * Gia_ManCorrSpecReduce_Emit( Gia_Man_t * p, int nFrames, int fScorr, + Vec_Int_t ** pvOutputs, int fRings, + int * pTfoMark, Cec_IncrMgr_t * pIncr, + Cec_IncrEmitMode_t Mode, Vec_Int_t ** pvOutLits ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pRepr; + Vec_Int_t * vXorLits; + int f, i, iPrev, iObj, iPrevNew, iObjNew, iPrevRaw, iObjRaw; + assert( nFrames > 0 ); + assert( Gia_ManRegNum(p) > 0 ); + assert( p->pReprs != NULL ); + assert( Mode == CEC_EMIT_ALL || pTfoMark != NULL ); + Vec_IntFill( &p->vCopies, (nFrames+fScorr)*Gia_ManObjNum(p), -1 ); + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ObjSetCopyF( p, 0, Gia_ManConst0(p), 0 ); + Gia_ManForEachRo( p, pObj, i ) + Gia_ObjSetCopyF( p, 0, pObj, Gia_ManAppendCi(pNew) ); + Gia_ManForEachRo( p, pObj, i ) + if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + Gia_ObjSetCopyF( p, 0, pObj, Gia_ObjCopyF(p, 0, pRepr) ); + for ( f = 0; f < nFrames+fScorr; f++ ) + { + Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); + Gia_ManForEachPi( p, pObj, i ) + Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); + } + *pvOutputs = Vec_IntAlloc( 1000 ); + if ( pvOutLits ) + *pvOutLits = Vec_IntAlloc( 1000 ); + vXorLits = Vec_IntAlloc( 1000 ); + if ( fRings ) + { + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsConst( p, i ) ) + { + int fActive = pTfoMark != NULL && pTfoMark[i]; + int fEmit = Mode == CEC_EMIT_ALL || + (Mode == CEC_EMIT_ACTIVE && fActive) || + (Mode == CEC_EMIT_SKIPPED && !fActive); + if ( !fEmit ) + continue; + iObjRaw = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 ); + iObjNew = Abc_LitNotCond( iObjRaw, Gia_ObjPhase(pObj) ); + if ( iObjNew != 0 ) + { + Vec_IntPush( *pvOutputs, 0 ); + Vec_IntPush( *pvOutputs, i ); + if ( pvOutLits ) + { + Vec_IntPush( *pvOutLits, 0 ); + Vec_IntPush( *pvOutLits, iObjRaw ); + } + Vec_IntPush( vXorLits, iObjNew ); + } + } + else if ( Gia_ObjIsHead( p, i ) ) + { + // Walk every ring edge so iPrev stays aligned with the class + // order; emit only when an endpoint is in TFO or the edge is + // new/rewired since the last snapshot. + iPrev = i; + Gia_ClassForEachObj1( p, i, iObj ) + { + int fActive = pTfoMark != NULL && + (pTfoMark[iPrev] || pTfoMark[iObj] || + Cec_IncrMgrRingEdgeChanged( pIncr, iPrev, iObj )); + int fEmit = Mode == CEC_EMIT_ALL || + (Mode == CEC_EMIT_ACTIVE && fActive) || + (Mode == CEC_EMIT_SKIPPED && !fActive); + if ( fEmit ) + { + iPrevRaw = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 ); + iObjRaw = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 ); + iPrevNew = Abc_LitNotCond( iPrevRaw, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); + iObjNew = Abc_LitNotCond( iObjRaw, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); + if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) + { + Vec_IntPush( *pvOutputs, iPrev ); + Vec_IntPush( *pvOutputs, iObj ); + if ( pvOutLits ) + { + Vec_IntPush( *pvOutLits, iPrevRaw ); + Vec_IntPush( *pvOutLits, iObjRaw ); + } + Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) ); + } + } + iPrev = iObj; + } + // Closing edge tail -> head + iObj = i; + { + int fActive = pTfoMark != NULL && + (pTfoMark[iPrev] || pTfoMark[iObj] || + Cec_IncrMgrRingEdgeChanged( pIncr, iPrev, iObj )); + int fEmit = Mode == CEC_EMIT_ALL || + (Mode == CEC_EMIT_ACTIVE && fActive) || + (Mode == CEC_EMIT_SKIPPED && !fActive); + if ( fEmit ) + { + iPrevRaw = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 ); + iObjRaw = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 ); + iPrevNew = Abc_LitNotCond( iPrevRaw, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); + iObjNew = Abc_LitNotCond( iObjRaw, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); + if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) + { + Vec_IntPush( *pvOutputs, iPrev ); + Vec_IntPush( *pvOutputs, iObj ); + if ( pvOutLits ) + { + Vec_IntPush( *pvOutLits, iPrevRaw ); + Vec_IntPush( *pvOutLits, iObjRaw ); + } + Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) ); + } + } + } + } + } + } + else + { + Gia_ManForEachObj1( p, pObj, i ) + { + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL ) + continue; + { + int idR = Gia_ObjId(p, pRepr); + int fActive = pTfoMark != NULL && (pTfoMark[i] || pTfoMark[idR]); + int fEmit = Mode == CEC_EMIT_ALL || + (Mode == CEC_EMIT_ACTIVE && fActive) || + (Mode == CEC_EMIT_SKIPPED && !fActive); + if ( !fEmit ) + continue; + } + iPrevRaw = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, nFrames, 0 ); + iObjRaw = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 ); + iPrevNew = iPrevRaw; + iObjNew = Abc_LitNotCond( iObjRaw, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + if ( iPrevNew != iObjNew ) + { + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); + if ( pvOutLits ) + { + Vec_IntPush( *pvOutLits, iPrevRaw ); + Vec_IntPush( *pvOutLits, iObjRaw ); + } + Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); + } + } + } + Vec_IntForEachEntry( vXorLits, iObjNew, i ) + Gia_ManAppendCo( pNew, iObjNew ); + Vec_IntFree( vXorLits ); + Gia_ManHashStop( pNew ); + Vec_IntErase( &p->vCopies ); + pNew = Gia_ManCleanup( pTemp = pNew ); + if ( pvOutLits ) + Gia_ManDupRemapLiterals( *pvOutLits, pTemp ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Active-filter variant of Gia_ManCorrSpecReduceInit (BMC SRM).] + + Description [Mirrors Gia_ManCorrSpecReduceInit but emits a candidate + PO (pRepr, pObj) only when at least one of the two endpoints lies in + pTfoMark. The baseline BMC SRM accepts an fRings flag for symmetry + with the inductive builder but never inspects it -- its topology is + always (head, member) pairs derived from pReprs alone, with no ring + edges to close. Therefore this active variant only needs pReprs- + driven seeds: pNexts changes cannot affect this SRM and there is no + closing edge to reprove. Passing pTfoMark == NULL falls back to the + unfiltered baseline behaviour.] + + SideEffects [] + + SeeAlso [Gia_ManCorrSpecReduceInit] + +***********************************************************************/ +Gia_Man_t * Gia_ManCorrSpecReduceInit_Active( Gia_Man_t * p, int nFrames, int nPrefix, int fScorr, + Vec_Int_t ** pvOutputs, int * pTfoMark ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pRepr; + Vec_Int_t * vXorLits; + int f, i, iPrevNew, iObjNew; + assert( (!fScorr && nFrames > 1) || (fScorr && nFrames > 0) || nPrefix ); + assert( Gia_ManRegNum(p) > 0 ); + assert( p->pReprs != NULL ); + Vec_IntFill( &p->vCopies, (nFrames+nPrefix+fScorr)*Gia_ManObjNum(p), -1 ); + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( (nFrames+nPrefix) * Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRo( p, pObj, i ) + { + Gia_ManAppendCi(pNew); + Gia_ObjSetCopyF( p, 0, pObj, 0 ); + } + for ( f = 0; f < nFrames+nPrefix+fScorr; f++ ) + { + Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); + Gia_ManForEachPi( p, pObj, i ) + Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); + } + *pvOutputs = Vec_IntAlloc( 1000 ); + vXorLits = Vec_IntAlloc( 1000 ); + for ( f = nPrefix; f < nFrames+nPrefix; f++ ) + { + Gia_ManForEachObj1( p, pObj, i ) + { + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL ) + continue; + if ( pTfoMark ) + { + int idR = Gia_ObjId(p, pRepr); + if ( !pTfoMark[i] && !pTfoMark[idR] ) + continue; + } + iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, f, nPrefix ); + iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix ); + iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + if ( iPrevNew != iObjNew ) + { + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); + Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); + Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); + } + } + } + Vec_IntForEachEntry( vXorLits, iObjNew, i ) + Gia_ManAppendCo( pNew, iObjNew ); + Vec_IntFree( vXorLits ); + Gia_ManHashStop( pNew ); + Vec_IntErase( &p->vCopies ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +ABC_NAMESPACE_IMPL_END + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/proof/cec/cecCorrIncrSim.c b/src/proof/cec/cecCorrIncrSim.c new file mode 100644 index 0000000000..8bb92809df --- /dev/null +++ b/src/proof/cec/cecCorrIncrSim.c @@ -0,0 +1,2040 @@ +/**CFile**************************************************************** + + FileName [cecCorrIncrSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Persistent event-driven incremental simulation for &scorr.] + + Description [Keeps packed CI patterns and host-AIG values across CEX batches. + Only changed CI words are propagated through the frame-aware fanout graph. + Classes containing truly changed values are fully regrouped. Structural and + measured-time budgets fall back to the standard full sweep.] + + Author [Xiran Zhao] + + Affiliation [University of Chinese Academy of Sciences] + + Date [Ver. 1.0. Started - Jun 2026.] + +***********************************************************************/ + +#include "cecInt.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Cec_SeedSimKey( Cec_SeedSim_t * p, int frame, int objId ) +{ + return frame * p->nObjs + objId; +} + +static inline unsigned * Cec_SeedSimVal( Cec_SeedSim_t * p, int frame, int objId ) +{ + size_t Key = (size_t)Cec_SeedSimKey( p, frame, objId ); + assert( frame >= 0 && frame < p->nFrames ); + assert( objId >= 0 && objId < p->nObjs ); + return p->pVal + Key * p->nWords; +} + +static inline int Cec_SeedSimPhase( Cec_SeedSim_t * p, int frame, int objId ) +{ + assert( frame >= 0 && frame < p->nFrames ); + assert( objId >= 0 && objId < p->nObjs ); + return Abc_InfoHasBit( p->pPhase + (size_t)frame * p->nPhaseWords, objId ); +} + +static inline void Cec_SeedSimSetPhase( Cec_SeedSim_t * p, + int frame, int objId, int Value ) +{ + unsigned * pWord = p->pPhase + (size_t)frame * p->nPhaseWords + (objId >> 5); + unsigned Bit = 1u << (objId & 31); + *pWord = (*pWord & ~Bit) | (Value ? Bit : 0); +} + +static inline int Cec_SeedSimMark( Cec_SeedSim_t * p, int frame, int objId ) +{ + int Key = Cec_SeedSimKey( p, frame, objId ); + if ( p->pMark[Key] == p->nMarkVersion ) + return 0; + p->pMark[Key] = p->nMarkVersion; + Vec_IntPush( p->vDirtyKeys, Key ); + return 1; +} + +static inline int Cec_SeedSimConeHasKey( Cec_SeedSim_t * p, int Key ) +{ + return !p->fUseCone || Abc_InfoHasBit( p->pCone, Key ); +} + +static inline int Cec_SeedSimConeHas( Cec_SeedSim_t * p, int Frame, int ObjId ) +{ + return Cec_SeedSimConeHasKey( p, Cec_SeedSimKey(p, Frame, ObjId) ); +} + +static void Cec_SeedSimConeMark_rec( Cec_SeedSim_t * p, int Frame, int ObjId ) +{ + Gia_Obj_t * pObj; + int Key; + if ( Frame < 0 || Frame >= p->nFrames || ObjId < 0 || ObjId >= p->nObjs ) + return; + Key = Cec_SeedSimKey( p, Frame, ObjId ); + if ( Abc_InfoHasBit(p->pCone, Key) ) + return; + Abc_InfoSetBit( p->pCone, Key ); + p->nConeKeys++; + Vec_IntPush( p->vConeQueue, Key ); + if ( ObjId == 0 ) + return; + pObj = Gia_ManObj( p->pAig, ObjId ); + if ( Gia_ObjIsPi(p->pAig, pObj) ) + return; + if ( Gia_ObjIsRo(p->pAig, pObj) ) + { + Gia_Obj_t * pRi; + int RiId; + if ( Frame == 0 ) + return; + pRi = Gia_ObjRoToRi( p->pAig, pObj ); + RiId = Gia_ObjId( p->pAig, pRi ); + Cec_SeedSimConeMark_rec( p, Frame - 1, + Gia_ObjFaninId0(pRi, RiId) ); + return; + } + if ( Gia_ObjIsAnd(pObj) ) + { + Cec_SeedSimConeMark_rec( p, Frame, + Gia_ObjFaninId0(pObj, ObjId) ); + Cec_SeedSimConeMark_rec( p, Frame, + Gia_ObjFaninId1(pObj, ObjId) ); + } +} + +static void Cec_SeedSimConeCloseClasses( Cec_SeedSim_t * p ) +{ + int i; + for ( i = 0; i < Vec_IntSize(p->vConeQueue); i++ ) + { + int Key = Vec_IntEntry( p->vConeQueue, i ); + int Frame = Key / p->nObjs; + int ObjId = Key % p->nObjs; + int Root, Member, RootKey; + if ( ObjId == 0 ) + continue; + if ( Gia_ObjIsConst(p->pAig, ObjId) ) + continue; + if ( !Gia_ObjIsClass(p->pAig, ObjId) ) + continue; + Root = Gia_ObjIsHead(p->pAig, ObjId) ? ObjId : + Gia_ObjRepr(p->pAig, ObjId); + // close each (frame, class-root) at most once: members and frames repeat + // in the queue, and re-closing a large class is quadratic + RootKey = Frame * p->nObjs + Root; + if ( p->pConeClose[RootKey] == p->nConeCloseVer ) + continue; + p->pConeClose[RootKey] = p->nConeCloseVer; + Cec_SeedSimConeMark_rec( p, Frame, Root ); + Gia_ClassForEachObj1( p->pAig, Root, Member ) + Cec_SeedSimConeMark_rec( p, Frame, Member ); + } +} + +static void Cec_SeedSimBuildFullClassCone( Cec_SeedSim_t * p ) +{ + Gia_Obj_t * pObj; + int Frame, i; + Gia_ManForEachObj1( p->pAig, pObj, i ) + { + if ( !Gia_ObjIsConst(p->pAig, i) && !Gia_ObjIsClass(p->pAig, i) ) + continue; + for ( Frame = 0; Frame < p->nFrames; Frame++ ) + Cec_SeedSimConeMark_rec( p, Frame, i ); + } + Cec_SeedSimConeCloseClasses( p ); +} + +void Cec_SeedSimBuildClassCone( Cec_SeedSim_t * p, Vec_Int_t * vOutputs ) +{ + int i, Obj0, Obj1; + memset( p->pCone, 0, sizeof(unsigned) * p->nConeWords ); + Vec_IntClear( p->vConeQueue ); + p->nConeKeys = 0; + p->fUseCone = 1; + if ( ++p->nConeCloseVer == 0 ) // fresh "class already closed" stamps + { + memset( p->pConeClose, 0, sizeof(int) * (size_t)p->nFrames * p->nObjs ); + p->nConeCloseVer = 1; + } + if ( vOutputs && Vec_IntSize(vOutputs) > 0 ) + { + Vec_IntForEachEntryDouble( vOutputs, Obj0, Obj1, i ) + { + Cec_SeedSimConeMark_rec( p, p->iSeedFrame, Obj0 ); + Cec_SeedSimConeMark_rec( p, p->iSeedFrame, Obj1 ); + } + Cec_SeedSimConeCloseClasses( p ); + if ( p->nConeKeys > 0 ) + return; + } + Cec_SeedSimBuildFullClassCone( p ); +} + +static int Cec_SeedSimEvalActive( Cec_SeedSim_t * p, int Frame, int ObjId, int nLimit ) +{ + Gia_Man_t * pAig = p->pAig; + Gia_Obj_t * pObj = Gia_ManObj( pAig, ObjId ); + int Key = Cec_SeedSimKey( p, Frame, ObjId ); + unsigned * pRes = Cec_SeedSimVal( p, Frame, ObjId ); + int Phase, w; + if ( p->pEvalMark[Key] == p->nEvalVersion ) + return 1; + if ( ++p->nEvalKeys > nLimit ) + return 0; + p->pEvalMark[Key] = p->nEvalVersion; + Phase = Cec_SeedSimPhase( p, Frame, ObjId ); + pRes[0] = (pRes[0] & ~(unsigned)1) | Phase; + for ( w = 0; w < p->nWords; w++ ) + if ( p->pActiveMask[w] ) + pRes[w] = Phase ? ~(unsigned)0 : 0; + if ( ObjId == 0 ) + return 1; + if ( Gia_ObjIsPi(pAig, pObj) ) + { + int iPi = Gia_ObjCioId( pObj ); + unsigned * pInput = (unsigned *)Vec_PtrEntry( p->vBatchInfo, + p->nRegs + Frame * p->nPis + iPi ); + for ( w = 0; w < p->nWords; w++ ) + if ( p->pActiveMask[w] ) + pRes[w] = (pRes[w] & ~p->pActiveMask[w]) | + (pInput[w] & p->pActiveMask[w]); + return 1; + } + if ( Gia_ObjIsRo(pAig, pObj) ) + { + if ( Frame == 0 ) + { + int iReg = Gia_ObjCioId(pObj) - p->nPis; + unsigned * pInput = (unsigned *)Vec_PtrEntry( p->vBatchInfo, iReg ); + for ( w = 0; w < p->nWords; w++ ) + if ( p->pActiveMask[w] ) + pRes[w] = (pRes[w] & ~p->pActiveMask[w]) | + (pInput[w] & p->pActiveMask[w]); + } + else + { + Gia_Obj_t * pRi = Gia_ObjRoToRi( pAig, pObj ); + int RiId = Gia_ObjId( pAig, pRi ); + int DrvId = Gia_ObjFaninId0( pRi, RiId ); + unsigned * pDrv; + if ( !Cec_SeedSimEvalActive(p, Frame - 1, DrvId, nLimit) ) + return 0; + pDrv = Cec_SeedSimVal( p, Frame - 1, DrvId ); + for ( w = 0; w < p->nWords; w++ ) + { + unsigned Value = Gia_ObjFaninC0(pRi) ? ~pDrv[w] : pDrv[w]; + if ( p->pActiveMask[w] ) + pRes[w] = (pRes[w] & ~p->pActiveMask[w]) | + (Value & p->pActiveMask[w]); + } + } + return 1; + } + if ( Gia_ObjIsAnd(pObj) ) + { + int Fan0 = Gia_ObjFaninId0( pObj, ObjId ); + int Fan1 = Gia_ObjFaninId1( pObj, ObjId ); + unsigned * pVal0, * pVal1; + if ( !Cec_SeedSimEvalActive(p, Frame, Fan0, nLimit) || + !Cec_SeedSimEvalActive(p, Frame, Fan1, nLimit) ) + return 0; + pVal0 = Cec_SeedSimVal( p, Frame, Fan0 ); + pVal1 = Cec_SeedSimVal( p, Frame, Fan1 ); + for ( w = 0; w < p->nWords; w++ ) + { + unsigned Val0 = Gia_ObjFaninC0(pObj) ? ~pVal0[w] : pVal0[w]; + unsigned Val1 = Gia_ObjFaninC1(pObj) ? ~pVal1[w] : pVal1[w]; + unsigned Value = Val0 & Val1; + if ( p->pActiveMask[w] ) + pRes[w] = (pRes[w] & ~p->pActiveMask[w]) | + (Value & p->pActiveMask[w]); + } + return 1; + } + return 0; +} + +Cec_SeedSim_t * Cec_SeedSimAlloc( Gia_Man_t * pAig, int nFrames, int iSeedFrame, int nWords ) +{ + Cec_SeedSim_t * p = ABC_CALLOC( Cec_SeedSim_t, 1 ); + size_t nKeys = (size_t)nFrames * Gia_ManObjNum(pAig); + int w; + assert( iSeedFrame >= 0 && iSeedFrame < nFrames ); + p->pAig = pAig; + p->nFrames = nFrames; + p->iSeedFrame = iSeedFrame; + p->nObjs = Gia_ManObjNum( pAig ); + p->nPis = Gia_ManPiNum( pAig ); + p->nRegs = Gia_ManRegNum( pAig ); + p->nWords = nWords; + p->nPhaseWords = Abc_BitWordNum( p->nObjs ); + p->nEventMaskWords = Abc_BitWordNum( nWords ); + p->nConeWords = Abc_BitWordNum( (int)nKeys ); + p->pVal = ABC_CALLOC( unsigned, nKeys * nWords ); + p->pPhase = ABC_CALLOC( unsigned, (size_t)nFrames * p->nPhaseWords ); + p->pActiveMask = ABC_CALLOC( unsigned, nWords ); + p->pCexMask = ABC_CALLOC( unsigned, nWords ); + p->pFoundMask = ABC_CALLOC( unsigned, nWords ); + p->pDiffMask = ABC_CALLOC( unsigned, nWords ); + p->pTempMask = ABC_CALLOC( unsigned, nWords ); + p->pMark = ABC_CALLOC( int, nKeys ); + p->pSpecMark = ABC_CALLOC( int, nKeys ); + p->pDiagMark = ABC_CALLOC( int, nKeys ); + p->pSplitMark = ABC_CALLOC( int, nKeys ); + p->pProcessMark = ABC_CALLOC( int, nKeys ); + p->pEvalMark = ABC_CALLOC( int, nKeys ); + p->pEventWords = ABC_CALLOC( unsigned, nKeys * p->nEventMaskWords ); + p->pCone = ABC_CALLOC( unsigned, p->nConeWords ); + p->pConeClose = ABC_CALLOC( int, nKeys ); + p->pRootMark = ABC_CALLOC( int, p->nObjs ); + p->pTxnMark = ABC_CALLOC( int, p->nObjs ); + p->pInputVarMark = ABC_CALLOC( int, p->nRegs + p->nPis * p->nFrames ); + p->vDiagPairs = Vec_IntAlloc( 192 ); + p->vSpecKeys = Vec_IntAlloc( 1024 ); + p->vSpecMasks = Vec_IntAlloc( 1024 * nWords ); + p->vDiagKeys = Vec_IntAlloc( 1024 ); + p->vDiagRoots = Vec_IntAlloc( 1024 ); + p->vDiagMasks = Vec_IntAlloc( 1024 * nWords ); + p->vSplitKeys = Vec_IntAlloc( 1024 ); + p->vDirtyKeys = Vec_IntAlloc( 4096 ); + p->vWaveKeys = Vec_IntAlloc( 4096 ); + p->vQueue = Vec_IntAlloc( 4096 ); + p->vDirtyRoots = Vec_IntAlloc( 1024 ); + p->vConstRefined = Vec_IntAlloc( 64 ); + p->vClassAll = Vec_IntAlloc( 64 ); + p->vClassOld = Vec_IntAlloc( 64 ); + p->vClassNew = Vec_IntAlloc( 64 ); + p->vTxnObjs = Vec_IntAlloc( 1024 ); + p->vTxnReprs = Vec_IntAlloc( 1024 ); + p->vTxnNexts = Vec_IntAlloc( 1024 ); + p->vPackTouched = Vec_IntAlloc( 1024 ); + p->vInputUndo = Vec_IntAlloc( 2048 ); + p->vChangedInputs = Vec_IntAlloc( 1024 ); + p->vValueUndo = Vec_IntAlloc( 4096 ); + p->vChangedValues = Vec_IntAlloc( 4096 ); + p->vConeQueue = Vec_IntAlloc( 4096 ); + p->pPhase0 = ABC_ALLOC( unsigned, nWords ); + p->pPhase1 = ABC_ALLOC( unsigned, nWords ); + for ( w = 0; w < nWords; w++ ) + { + p->pPhase0[w] = 0; + p->pPhase1[w] = ~(unsigned)0; + } + if ( pAig->vFanout == NULL ) + { + Gia_ManStaticFanoutStart( pAig ); + p->fOwnsFanout = 1; + } + return p; +} + +void Cec_SeedSimFree( Cec_SeedSim_t * p ) +{ + if ( p == NULL ) + return; + if ( p->fOwnsFanout ) + Gia_ManStaticFanoutStop( p->pAig ); + Vec_IntFreeP( &p->vDiagPairs ); + Vec_IntFreeP( &p->vSpecKeys ); + Vec_IntFreeP( &p->vSpecMasks ); + Vec_IntFreeP( &p->vDiagKeys ); + Vec_IntFreeP( &p->vDiagRoots ); + Vec_IntFreeP( &p->vDiagMasks ); + Vec_IntFreeP( &p->vSplitKeys ); + Vec_IntFreeP( &p->vDirtyKeys ); + Vec_IntFreeP( &p->vWaveKeys ); + Vec_IntFreeP( &p->vQueue ); + Vec_IntFreeP( &p->vDirtyRoots ); + Vec_IntFreeP( &p->vConstRefined ); + Vec_IntFreeP( &p->vClassAll ); + Vec_IntFreeP( &p->vClassOld ); + Vec_IntFreeP( &p->vClassNew ); + Vec_IntFreeP( &p->vTxnObjs ); + Vec_IntFreeP( &p->vTxnReprs ); + Vec_IntFreeP( &p->vTxnNexts ); + Vec_IntFreeP( &p->vPackTouched ); + Vec_IntFreeP( &p->vInputUndo ); + Vec_IntFreeP( &p->vChangedInputs ); + Vec_IntFreeP( &p->vValueUndo ); + Vec_IntFreeP( &p->vChangedValues ); + Vec_IntFreeP( &p->vConeQueue ); + Vec_PtrFreeP( &p->vSimInfo ); + ABC_FREE( p->pVal ); + ABC_FREE( p->pPhase ); + ABC_FREE( p->pActiveMask ); + ABC_FREE( p->pCexMask ); + ABC_FREE( p->pFoundMask ); + ABC_FREE( p->pDiffMask ); + ABC_FREE( p->pTempMask ); + ABC_FREE( p->pMark ); + ABC_FREE( p->pSpecMark ); + ABC_FREE( p->pDiagMark ); + ABC_FREE( p->pSplitMark ); + ABC_FREE( p->pProcessMark ); + ABC_FREE( p->pEvalMark ); + ABC_FREE( p->pEventWords ); + ABC_FREE( p->pCone ); + ABC_FREE( p->pConeClose ); + ABC_FREE( p->pRootMark ); + ABC_FREE( p->pTxnMark ); + ABC_FREE( p->pPackPres ); + ABC_FREE( p->pInputUndoMark ); + ABC_FREE( p->pInputVarMark ); + ABC_FREE( p->pPhase0 ); + ABC_FREE( p->pPhase1 ); + ABC_FREE( p ); +} + +static void Cec_SeedSimReset( Cec_SeedSim_t * p ) +{ + size_t nKeys = (size_t)p->nFrames * p->nObjs; + int i, Key; + Vec_IntForEachEntry( p->vSpecKeys, Key, i ) + p->pSpecMark[Key] = 0; + Vec_IntForEachEntry( p->vDiagKeys, Key, i ) + p->pDiagMark[Key] = 0; + Vec_IntClear( p->vDiagPairs ); + Vec_IntClear( p->vSpecKeys ); + Vec_IntClear( p->vSpecMasks ); + Vec_IntClear( p->vDiagKeys ); + Vec_IntClear( p->vDiagRoots ); + Vec_IntClear( p->vDiagMasks ); + Vec_IntClear( p->vSplitKeys ); + Vec_IntClear( p->vDirtyKeys ); + Vec_IntClear( p->vWaveKeys ); + Vec_IntClear( p->vQueue ); + for ( i = 0; i < p->nWords; i++ ) + p->pActiveMask[i] = ~(unsigned)0; + p->pActiveMask[0] &= ~(unsigned)1; + memset( p->pCexMask, 0, sizeof(unsigned) * p->nWords ); + memset( p->pFoundMask, 0, sizeof(unsigned) * p->nWords ); + p->vBatchInfo = NULL; + p->nSpecKeys = 0; + p->nEvalKeys = 0; + p->nMarkVersion++; + p->nSplitVersion++; + p->nProcessVersion++; + p->nEvalVersion++; + if ( p->nMarkVersion == 0 ) + { + memset( p->pMark, 0, sizeof(int) * nKeys ); + p->nMarkVersion = 1; + } + if ( p->nSplitVersion == 0 ) + { + memset( p->pSplitMark, 0, sizeof(int) * nKeys ); + p->nSplitVersion = 1; + } + if ( p->nProcessVersion == 0 ) + { + memset( p->pProcessMark, 0, sizeof(int) * nKeys ); + p->nProcessVersion = 1; + } + if ( p->nEvalVersion == 0 ) + { + memset( p->pEvalMark, 0, sizeof(int) * nKeys ); + p->nEvalVersion = 1; + } +} + +static int Cec_SeedSimAddDiagKey( Cec_SeedSim_t * p, int Frame, int ObjId ) +{ + int Key, iDiag, Repr, w; + if ( ObjId <= 0 || ObjId >= p->nObjs ) + return ObjId == 0; + Key = Cec_SeedSimKey( p, Frame, ObjId ); + iDiag = p->pDiagMark[Key] - 1; + if ( iDiag < 0 ) + { + Repr = Gia_ObjRepr( p->pAig, ObjId ); + iDiag = Vec_IntSize( p->vDiagKeys ); + p->pDiagMark[Key] = iDiag + 1; + Vec_IntPush( p->vDiagKeys, Key ); + Vec_IntPush( p->vDiagRoots, Repr == 0 ? 0 : + (Gia_ObjIsHead(p->pAig, ObjId) ? ObjId : Repr) ); + for ( w = 0; w < p->nWords; w++ ) + Vec_IntPush( p->vDiagMasks, 0 ); + } + return 1; +} + +static int Cec_SeedSimAddDiagBit( Cec_SeedSim_t * p, int Frame, int ObjId, int iBit ) +{ + int Key, iDiag; + unsigned * pMask; + if ( !Cec_SeedSimAddDiagKey(p, Frame, ObjId) ) + return 0; + if ( ObjId == 0 ) + return 1; + Key = Cec_SeedSimKey( p, Frame, ObjId ); + iDiag = p->pDiagMark[Key] - 1; + assert( iDiag >= 0 ); + pMask = (unsigned *)Vec_IntArray(p->vDiagMasks) + (size_t)iDiag * p->nWords; + Abc_InfoSetBit( pMask, iBit ); + return 1; +} + +static int Cec_SeedSimCollectSpecBit( Cec_SeedSim_t * p, int Frame, int ObjId, int iBit, int nLimit ); + +static int Cec_SeedSimCollectRealBit( Cec_SeedSim_t * p, int Frame, int ObjId, int iBit, int nLimit ) +{ + Gia_Obj_t * pObj; + if ( ObjId < 0 || ObjId >= p->nObjs || Frame < 0 || Frame >= p->nFrames ) + return 0; + if ( ObjId == 0 ) + return 1; + pObj = Gia_ManObj( p->pAig, ObjId ); + if ( Gia_ObjIsAnd(pObj) ) + { + return Cec_SeedSimCollectSpecBit( p, Frame, Gia_ObjFaninId0(pObj, ObjId), iBit, nLimit ) && + Cec_SeedSimCollectSpecBit( p, Frame, Gia_ObjFaninId1(pObj, ObjId), iBit, nLimit ); + } + if ( Gia_ObjIsRo(p->pAig, pObj) && Frame > 0 ) + { + Gia_Obj_t * pRi = Gia_ObjRoToRi( p->pAig, pObj ); + int RiId = Gia_ObjId( p->pAig, pRi ); + return Cec_SeedSimCollectSpecBit( p, Frame - 1, + Gia_ObjFaninId0(pRi, RiId), iBit, nLimit ); + } + return 1; +} + +static int Cec_SeedSimCollectSpecBit( Cec_SeedSim_t * p, int Frame, int ObjId, int iBit, int nLimit ) +{ + int Key, Repr, iSpec, iWord = iBit >> 5, w; + unsigned Bit = (unsigned)1 << (iBit & 31); + unsigned * pMask; + if ( ObjId < 0 || ObjId >= p->nObjs || Frame < 0 || Frame >= p->nFrames ) + return 0; + if ( ObjId == 0 ) + return 1; + Key = Cec_SeedSimKey( p, Frame, ObjId ); + iSpec = p->pSpecMark[Key] - 1; + if ( iSpec < 0 ) + { + if ( ++p->nSpecKeys > nLimit ) + return 0; + iSpec = Vec_IntSize( p->vSpecKeys ); + p->pSpecMark[Key] = iSpec + 1; + Vec_IntPush( p->vSpecKeys, Key ); + for ( w = 0; w < p->nWords; w++ ) + Vec_IntPush( p->vSpecMasks, 0 ); + } + pMask = (unsigned *)Vec_IntArray(p->vSpecMasks) + (size_t)iSpec * p->nWords; + if ( pMask[iWord] & Bit ) + return 1; + pMask[iWord] |= Bit; + Repr = Gia_ObjRepr( p->pAig, ObjId ); + if ( Repr != GIA_VOID ) + { + if ( !Cec_SeedSimAddDiagBit(p, Frame, ObjId, iBit) ) + return 0; + return Repr == 0 || + Cec_SeedSimCollectSpecBit( p, Frame, Repr, iBit, nLimit ); + } + return Cec_SeedSimCollectRealBit( p, Frame, ObjId, iBit, nLimit ); +} + +static int Cec_SeedSimCollectDiagnosis( Cec_SeedSim_t * p, Vec_Int_t * vOutputs, Vec_Int_t * vOutBits, int nLimit ) +{ + int i, Out, iBit; + if ( vOutputs == NULL || vOutBits == NULL ) + return 0; + Vec_IntForEachEntryDouble( vOutBits, Out, iBit, i ) + { + int Obj0, Obj1; + if ( Out < 0 || 2*Out + 1 >= Vec_IntSize(vOutputs) ) + return 0; + Obj0 = Vec_IntEntry( vOutputs, 2*Out ); + Obj1 = Vec_IntEntry( vOutputs, 2*Out + 1 ); + Abc_InfoSetBit( p->pCexMask, iBit ); + Vec_IntPush( p->vDiagPairs, Obj0 ); + Vec_IntPush( p->vDiagPairs, Obj1 ); + Vec_IntPush( p->vDiagPairs, iBit ); + if ( !Cec_SeedSimAddDiagKey(p, p->iSeedFrame, Obj0) || + !Cec_SeedSimAddDiagKey(p, p->iSeedFrame, Obj1) ) + return 0; + if ( !Cec_SeedSimCollectRealBit(p, p->iSeedFrame, Obj0, iBit, nLimit) || + !Cec_SeedSimCollectRealBit(p, p->iSeedFrame, Obj1, iBit, nLimit) ) + return 0; + } + return Vec_IntSize(vOutBits) > 0; +} + +static int Cec_SeedSimCollectShapeSpec( Cec_SeedSim_t * p, int Frame, int ObjId, int nLimit ); + +static int Cec_SeedSimCollectShapeReal( Cec_SeedSim_t * p, int Frame, int ObjId, int nLimit ) +{ + Gia_Obj_t * pObj; + int Key; + if ( ObjId < 0 || ObjId >= p->nObjs || Frame < 0 || Frame >= p->nFrames ) + return 0; + if ( ObjId == 0 ) + return 1; + Key = Cec_SeedSimKey( p, Frame, ObjId ); + if ( p->pProcessMark[Key] == p->nProcessVersion ) + return 1; + p->pProcessMark[Key] = p->nProcessVersion; + Vec_IntPush( p->vDirtyKeys, Key ); + if ( Vec_IntSize(p->vDirtyKeys) > nLimit ) + return 0; + pObj = Gia_ManObj( p->pAig, ObjId ); + if ( Gia_ObjIsAnd(pObj) ) + return Cec_SeedSimCollectShapeSpec( p, Frame, Gia_ObjFaninId0(pObj, ObjId), nLimit ) && + Cec_SeedSimCollectShapeSpec( p, Frame, Gia_ObjFaninId1(pObj, ObjId), nLimit ); + if ( Gia_ObjIsRo(p->pAig, pObj) && Frame > 0 ) + { + Gia_Obj_t * pRi = Gia_ObjRoToRi( p->pAig, pObj ); + int RiId = Gia_ObjId( p->pAig, pRi ); + return Cec_SeedSimCollectShapeSpec( p, Frame - 1, + Gia_ObjFaninId0(pRi, RiId), nLimit ); + } + return 1; +} + +static int Cec_SeedSimCollectShapeSpec( Cec_SeedSim_t * p, int Frame, int ObjId, int nLimit ) +{ + Gia_Obj_t * pObj; + int Repr; + if ( ObjId < 0 || ObjId >= p->nObjs || Frame < 0 || Frame >= p->nFrames ) + return 0; + if ( ObjId == 0 || !Cec_SeedSimMark(p, Frame, ObjId) ) + return 1; + if ( Vec_IntSize(p->vDirtyKeys) > nLimit ) + return 0; + Repr = Gia_ObjRepr( p->pAig, ObjId ); + if ( Repr != GIA_VOID ) + return Repr == 0 || Cec_SeedSimCollectShapeSpec( p, Frame, Repr, nLimit ); + pObj = Gia_ManObj( p->pAig, ObjId ); + if ( Gia_ObjIsAnd(pObj) ) + return Cec_SeedSimCollectShapeSpec( p, Frame, Gia_ObjFaninId0(pObj, ObjId), nLimit ) && + Cec_SeedSimCollectShapeSpec( p, Frame, Gia_ObjFaninId1(pObj, ObjId), nLimit ); + if ( Gia_ObjIsRo(p->pAig, pObj) && Frame > 0 ) + { + Gia_Obj_t * pRi = Gia_ObjRoToRi( p->pAig, pObj ); + int RiId = Gia_ObjId( p->pAig, pRi ); + return Cec_SeedSimCollectShapeSpec( p, Frame - 1, + Gia_ObjFaninId0(pRi, RiId), nLimit ); + } + return 1; +} + +static int Cec_SeedSimDiagnosisShapeSmall( Cec_SeedSim_t * p, + Vec_Int_t * vOutputs, Vec_Int_t * vOutBits, int nLimit ) +{ + int i, Out, iBit; + Vec_IntForEachEntryDouble( vOutBits, Out, iBit, i ) + { + int Obj0, Obj1; + (void)iBit; + if ( Out < 0 || 2*Out + 1 >= Vec_IntSize(vOutputs) ) + return 0; + Obj0 = Vec_IntEntry( vOutputs, 2*Out ); + Obj1 = Vec_IntEntry( vOutputs, 2*Out + 1 ); + if ( !Cec_SeedSimCollectShapeReal(p, p->iSeedFrame, Obj0, nLimit) || + !Cec_SeedSimCollectShapeReal(p, p->iSeedFrame, Obj1, nLimit) ) + return 0; + } + return 1; +} + +static void Cec_SeedSimRestartTfoMarks( Cec_SeedSim_t * p ) +{ + size_t nKeys = (size_t)p->nFrames * p->nObjs; + Vec_IntClear( p->vDirtyKeys ); + Vec_IntClear( p->vQueue ); + p->nMarkVersion++; + p->nProcessVersion++; + if ( p->nMarkVersion == 0 ) + { + memset( p->pMark, 0, sizeof(int) * nKeys ); + p->nMarkVersion = 1; + } + if ( p->nProcessVersion == 0 ) + { + memset( p->pProcessMark, 0, sizeof(int) * nKeys ); + p->nProcessVersion = 1; + } +} + +static void Cec_SeedSimUseCexLanes( Cec_SeedSim_t * p ) +{ + int w; + for ( w = 0; w < p->nWords; w++ ) + p->pActiveMask[w] = p->pCexMask[w] ? ~(unsigned)0 : 0; + p->pActiveMask[0] &= ~(unsigned)1; +} + +static void Cec_SeedSimUsePackedLanes( Cec_SeedSim_t * p ) +{ + int w; + if ( p->nEvalKeys > p->nMaxDirty ) + p->nMaxDirty = p->nEvalKeys; + for ( w = 0; w < p->nWords; w++ ) + p->pActiveMask[w] = ~(unsigned)0; + p->pActiveMask[0] &= ~(unsigned)1; + p->nEvalKeys = 0; + p->nEvalVersion++; + if ( p->nEvalVersion == 0 ) + { + size_t nKeys = (size_t)p->nFrames * p->nObjs; + memset( p->pEvalMark, 0, sizeof(int) * nKeys ); + p->nEvalVersion = 1; + } +} + +static int Cec_SeedSimComputeTfo( Cec_SeedSim_t * p, int nLimit ) +{ + if ( Vec_IntSize(p->vDirtyKeys) > nLimit ) + return 0; + while ( Vec_IntSize(p->vQueue) > 0 ) + { + int Key = Vec_IntPop( p->vQueue ); + int Frame = Key / p->nObjs; + int ObjId = Key % p->nObjs; + int FanId, i; + Gia_ObjForEachFanoutStaticId( p->pAig, ObjId, FanId, i ) + { + Gia_Obj_t * pFan = Gia_ManObj( p->pAig, FanId ); + if ( Gia_ObjIsAnd(pFan) ) + { + if ( Cec_SeedSimMark( p, Frame, FanId ) ) + { + if ( Vec_IntSize(p->vDirtyKeys) > nLimit ) + return 0; + Vec_IntPush( p->vQueue, Cec_SeedSimKey(p, Frame, FanId) ); + } + } + else if ( Gia_ObjIsRi(p->pAig, pFan) && Frame + 1 < p->nFrames ) + { + int RoId = Gia_ObjRiToRoId( p->pAig, FanId ); + if ( Cec_SeedSimMark( p, Frame + 1, RoId ) ) + { + if ( Vec_IntSize(p->vDirtyKeys) > nLimit ) + return 0; + Vec_IntPush( p->vQueue, Cec_SeedSimKey(p, Frame + 1, RoId) ); + } + } + } + } + return 1; +} + +static void Cec_SeedSimStartRootSet( Cec_SeedSim_t * p ) +{ + p->nRootVersion++; + if ( p->nRootVersion == 0 ) + { + memset( p->pRootMark, 0, sizeof(int) * p->nObjs ); + p->nRootVersion = 1; + } + Vec_IntClear( p->vDirtyRoots ); + Vec_IntClear( p->vConstRefined ); +} + +static void Cec_SeedSimAddRoot( Cec_SeedSim_t * p, int ObjId ) +{ + Gia_Man_t * pAig = p->pAig; + int iRoot; + if ( Gia_ObjIsConst(pAig, ObjId) ) + { + iRoot = ObjId; + if ( p->pRootMark[iRoot] != p->nRootVersion ) + { + p->pRootMark[iRoot] = p->nRootVersion; + Vec_IntPush( p->vConstRefined, iRoot ); + } + } + else if ( Gia_ObjIsClass(pAig, ObjId) ) + { + iRoot = Gia_ObjIsHead(pAig, ObjId) ? ObjId : Gia_ObjRepr(pAig, ObjId); + if ( p->pRootMark[iRoot] != p->nRootVersion ) + { + p->pRootMark[iRoot] = p->nRootVersion; + Vec_IntPush( p->vDirtyRoots, iRoot ); + } + } + else + return; +} + +static int Cec_SeedSimCollectEvalShape( Cec_SeedSim_t * p, + int Frame, int ObjId, int nLimit ) +{ + Gia_Obj_t * pObj; + int Key; + if ( ObjId < 0 || ObjId >= p->nObjs || Frame < 0 || Frame >= p->nFrames ) + return 0; + Key = Cec_SeedSimKey( p, Frame, ObjId ); + if ( p->pProcessMark[Key] == p->nProcessVersion ) + return 1; + p->pProcessMark[Key] = p->nProcessVersion; + Vec_IntPush( p->vDirtyKeys, Key ); + if ( Vec_IntSize(p->vDirtyKeys) > nLimit ) + return 0; + if ( ObjId == 0 ) + return 1; + pObj = Gia_ManObj( p->pAig, ObjId ); + if ( Gia_ObjIsAnd(pObj) ) + return Cec_SeedSimCollectEvalShape( p, Frame, + Gia_ObjFaninId0(pObj, ObjId), nLimit ) && + Cec_SeedSimCollectEvalShape( p, Frame, + Gia_ObjFaninId1(pObj, ObjId), nLimit ); + if ( Gia_ObjIsRo(p->pAig, pObj) && Frame > 0 ) + { + Gia_Obj_t * pRi = Gia_ObjRoToRi( p->pAig, pObj ); + int RiId = Gia_ObjId( p->pAig, pRi ); + return Cec_SeedSimCollectEvalShape( p, Frame - 1, + Gia_ObjFaninId0(pRi, RiId), nLimit ); + } + return 1; +} + +static int Cec_SeedSimDiagnosisEvalShapeSmall( Cec_SeedSim_t * p, + Vec_Int_t * vKeys, int nLimit ) +{ + int iLo = 0; + Vec_IntSort( vKeys, 0 ); + while ( iLo < Vec_IntSize(vKeys) ) + { + int Frame = Vec_IntEntry(vKeys, iLo) / p->nObjs; + int iHi = iLo, i, Key, ObjId, Ent; + while ( iHi < Vec_IntSize(vKeys) && + Vec_IntEntry(vKeys, iHi) / p->nObjs == Frame ) + iHi++; + Cec_SeedSimStartRootSet( p ); + for ( i = iLo; i < iHi; i++ ) + { + Key = Vec_IntEntry( vKeys, i ); + ObjId = Key % p->nObjs; + if ( Gia_ObjIsConst(p->pAig, ObjId) || + Gia_ObjIsClass(p->pAig, ObjId) ) + Cec_SeedSimAddRoot( p, ObjId ); + else if ( !Cec_SeedSimCollectEvalShape(p, Frame, ObjId, nLimit) ) + return 0; + } + Vec_IntForEachEntry( p->vDirtyRoots, Ent, i ) + { + int Member; + if ( !Cec_SeedSimCollectEvalShape(p, Frame, Ent, nLimit) ) + return 0; + Gia_ClassForEachObj1( p->pAig, Ent, Member ) + if ( !Cec_SeedSimCollectEvalShape(p, Frame, Member, nLimit) ) + return 0; + } + Vec_IntForEachEntry( p->vConstRefined, Ent, i ) + if ( !Cec_SeedSimCollectEvalShape(p, Frame, Ent, nLimit) ) + return 0; + iLo = iHi; + } + return 1; +} + +static void Cec_SeedSimDiffMask( Cec_SeedSim_t * p, unsigned * pValue0, + unsigned * pValue1, unsigned * pMask, unsigned * pDiff ) +{ + int fCompl = (pValue0[0] & 1) != (pValue1[0] & 1); + int w; + for ( w = 0; w < p->nWords; w++ ) + pDiff[w] = (pValue0[w] ^ (fCompl ? ~pValue1[w] : pValue1[w])) & pMask[w]; +} + +static int Cec_SeedSimMaskIsZero( unsigned * pMask, int nWords ) +{ + int w; + for ( w = 0; w < nWords; w++ ) + if ( pMask[w] ) + return 0; + return 1; +} + +static inline unsigned Cec_SeedSimRefineMaskWord( Cec_SeedSim_t * p, int w ) +{ + return p->pRefineMask[w] | (w == 0); +} + +static int Cec_SeedSimCompareRefine( Cec_SeedSim_t * p, + unsigned * pValue0, unsigned * pValue1 ) +{ + int fCompl = (pValue0[0] & 1) != (pValue1[0] & 1); + int w; + if ( fCompl ) + { + for ( w = 0; w < p->nWords; w++ ) + if ( (pValue0[w] ^ ~pValue1[w]) & Cec_SeedSimRefineMaskWord(p, w) ) + return 0; + } + else + { + for ( w = 0; w < p->nWords; w++ ) + if ( (pValue0[w] ^ pValue1[w]) & Cec_SeedSimRefineMaskWord(p, w) ) + return 0; + } + return 1; +} + +static int Cec_SeedSimHashRefine( Cec_SeedSim_t * p, + unsigned * pValue, int nTableSize ) +{ + static int s_Primes[16] = { + 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, + 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 + }; + unsigned uHash = 0; + int w; + if ( pValue[0] & 1 ) + for ( w = 0; w < p->nWords; w++ ) + uHash ^= (~pValue[w] & Cec_SeedSimRefineMaskWord(p, w)) * + s_Primes[w & 0xf]; + else + for ( w = 0; w < p->nWords; w++ ) + uHash ^= (pValue[w] & Cec_SeedSimRefineMaskWord(p, w)) * + s_Primes[w & 0xf]; + return (int)(uHash % nTableSize); +} + +static int Cec_SeedSimCurrentRoot( Cec_SeedSim_t * p, int ObjId ) +{ + if ( ObjId == 0 || Gia_ObjIsConst(p->pAig, ObjId) ) + return 0; + if ( Gia_ObjIsHead(p->pAig, ObjId) ) + return ObjId; + if ( Gia_ObjIsClass(p->pAig, ObjId) ) + return Gia_ObjRepr(p->pAig, ObjId); + return ObjId; +} + +static void Cec_SeedSimCheckFailedPairs( Cec_SeedSim_t * p, int Frame ) +{ + int i; + assert( Frame == p->iSeedFrame ); + for ( i = 0; i < Vec_IntSize(p->vDiagPairs); i += 3 ) + { + int Obj0 = Vec_IntEntry( p->vDiagPairs, i ); + int Obj1 = Vec_IntEntry( p->vDiagPairs, i + 1 ); + int iBit = Vec_IntEntry( p->vDiagPairs, i + 2 ); + int iWord = iBit >> 5; + unsigned Bit = (unsigned)1 << (iBit & 31); + unsigned * pValue0, * pValue1; + if ( Cec_SeedSimCurrentRoot(p, Obj0) != Cec_SeedSimCurrentRoot(p, Obj1) ) + { + p->pFoundMask[iWord] |= Bit; + continue; + } + pValue0 = Obj0 == 0 ? p->pPhase0 : Cec_SeedSimVal( p, Frame, Obj0 ); + pValue1 = Obj1 == 0 ? p->pPhase0 : Cec_SeedSimVal( p, Frame, Obj1 ); + Cec_SeedSimDiffMask( p, pValue0, pValue1, p->pActiveMask, p->pDiffMask ); + p->pFoundMask[iWord] |= p->pDiffMask[iWord] & Bit; + } +} + +static void Cec_SeedSimAddSplitKey( Cec_SeedSim_t * p, int Frame, int ObjId ) +{ + int Key = Cec_SeedSimKey( p, Frame, ObjId ); + if ( p->pSplitMark[Key] == p->nSplitVersion ) + return; + p->pSplitMark[Key] = p->nSplitVersion; + Vec_IntPush( p->vSplitKeys, Key ); +} + +static int Cec_SeedSimPrepareFrame( Cec_SeedSim_t * p, Vec_Int_t * vKeys, + int Frame, int iLo, int iHi, int nLimit, int fDiagnosis ) +{ + Gia_Man_t * pAig = p->pAig; + int i, Key, Ent; + Cec_SeedSimStartRootSet( p ); + for ( i = iLo; i < iHi; i++ ) + { + int ObjId; + Key = Vec_IntEntry( vKeys, i ); + ObjId = Key % p->nObjs; + if ( fDiagnosis ) + { + int iDiag = p->pDiagMark[Key] - 1; + unsigned * pMask; + int RootOld; + assert( iDiag >= 0 ); + pMask = (unsigned *)Vec_IntArray(p->vDiagMasks) + (size_t)iDiag * p->nWords; + RootOld = Vec_IntEntry( p->vDiagRoots, iDiag ); + int RootNew = Gia_ObjIsConst(pAig, ObjId) ? 0 : + (Gia_ObjIsHead(pAig, ObjId) ? ObjId : + (Gia_ObjIsClass(pAig, ObjId) ? Gia_ObjRepr(pAig, ObjId) : GIA_VOID)); + // Failed endpoints are diagnosis keys as well. An endpoint + // outside an equivalence class has no member-to-root assumption. + if ( RootOld == GIA_VOID ) + { + if ( !Cec_SeedSimEvalActive(p, Frame, ObjId, nLimit) ) + return 0; + continue; + } + if ( RootNew != RootOld ) + { + int w; + for ( w = 0; w < p->nWords; w++ ) + p->pFoundMask[w] |= pMask[w]; + continue; + } + } + Cec_SeedSimAddRoot( p, ObjId ); + } + Vec_IntForEachEntry( p->vDirtyRoots, Ent, i ) + { + int Member; + if ( !Cec_SeedSimEvalActive(p, Frame, Ent, nLimit) ) + return 0; + Gia_ClassForEachObj1( pAig, Ent, Member ) + { + if ( !Cec_SeedSimEvalActive(p, Frame, Member, nLimit) ) + return 0; + } + } + Vec_IntForEachEntry( p->vConstRefined, Ent, i ) + if ( !Cec_SeedSimEvalActive(p, Frame, Ent, nLimit) ) + return 0; + if ( fDiagnosis ) + { + for ( i = iLo; i < iHi; i++ ) + { + unsigned * pMask, * pValue0, * pValue1; + int ObjId, RootOld, RootNew, iDiag, w; + Key = Vec_IntEntry( vKeys, i ); + ObjId = Key % p->nObjs; + iDiag = p->pDiagMark[Key] - 1; + assert( iDiag >= 0 ); + RootOld = Vec_IntEntry( p->vDiagRoots, iDiag ); + RootNew = Gia_ObjIsConst(pAig, ObjId) ? 0 : + (Gia_ObjIsHead(pAig, ObjId) ? ObjId : + (Gia_ObjIsClass(pAig, ObjId) ? Gia_ObjRepr(pAig, ObjId) : GIA_VOID)); + pMask = (unsigned *)Vec_IntArray(p->vDiagMasks) + (size_t)iDiag * p->nWords; + if ( RootOld == GIA_VOID ) + continue; + if ( RootNew != RootOld ) + { + for ( w = 0; w < p->nWords; w++ ) + p->pFoundMask[w] |= pMask[w]; + continue; + } + if ( ObjId == RootOld ) + continue; + pValue0 = Cec_SeedSimVal( p, Frame, ObjId ); + pValue1 = RootOld == 0 ? + (Gia_ObjPhase(Gia_ManObj(pAig, ObjId)) ? p->pPhase1 : p->pPhase0) : + Cec_SeedSimVal( p, Frame, RootOld ); + Cec_SeedSimDiffMask( p, pValue0, pValue1, pMask, p->pDiffMask ); + for ( w = 0; w < p->nWords; w++ ) + p->pFoundMask[w] |= p->pDiffMask[w]; + } + if ( Frame == p->iSeedFrame ) + Cec_SeedSimCheckFailedPairs( p, Frame ); + } + return 1; +} + +static void Cec_SeedSimTxnBegin( Cec_SeedSim_t * p ) +{ + assert( !p->fTxnActive ); + assert( p->pAig->pReprs != NULL && p->pAig->pNexts != NULL ); + Vec_IntClear( p->vTxnObjs ); + Vec_IntClear( p->vTxnReprs ); + Vec_IntClear( p->vTxnNexts ); + p->nTxnVersion++; + if ( p->nTxnVersion == 0 ) + { + memset( p->pTxnMark, 0, sizeof(int) * p->nObjs ); + p->nTxnVersion = 1; + } + p->fTxnActive = 1; +} + +static void Cec_SeedSimTxnSaveObj( Cec_SeedSim_t * p, int ObjId ) +{ + assert( ObjId >= 0 && ObjId < p->nObjs ); + if ( !p->fTxnActive || p->pTxnMark[ObjId] == p->nTxnVersion ) + return; + p->pTxnMark[ObjId] = p->nTxnVersion; + Vec_IntPush( p->vTxnObjs, ObjId ); + Vec_IntPush( p->vTxnReprs, Gia_ObjRepr(p->pAig, ObjId) ); + Vec_IntPush( p->vTxnNexts, Gia_ObjNext(p->pAig, ObjId) ); +} + +static void Cec_SeedSimTxnSaveVec( Cec_SeedSim_t * p, Vec_Int_t * vObjs ) +{ + int i, ObjId; + Vec_IntForEachEntry( vObjs, ObjId, i ) + Cec_SeedSimTxnSaveObj( p, ObjId ); +} + +static void Cec_SeedSimTxnCommit( Cec_SeedSim_t * p ) +{ + assert( p->fTxnActive ); + p->fTxnActive = 0; + Vec_IntClear( p->vTxnObjs ); + Vec_IntClear( p->vTxnReprs ); + Vec_IntClear( p->vTxnNexts ); +} + +static void Cec_SeedSimTxnRollback( Cec_SeedSim_t * p ) +{ + int i, ObjId, nChanged = 0; + assert( p->fTxnActive ); + assert( Vec_IntSize(p->vTxnObjs) == Vec_IntSize(p->vTxnReprs) ); + assert( Vec_IntSize(p->vTxnObjs) == Vec_IntSize(p->vTxnNexts) ); + for ( i = Vec_IntSize(p->vTxnObjs) - 1; i >= 0; i-- ) + { + ObjId = Vec_IntEntry( p->vTxnObjs, i ); + if ( Gia_ObjRepr(p->pAig, ObjId) != Vec_IntEntry(p->vTxnReprs, i) || + Gia_ObjNext(p->pAig, ObjId) != Vec_IntEntry(p->vTxnNexts, i) ) + nChanged++; + Gia_ObjSetRepr( p->pAig, ObjId, Vec_IntEntry(p->vTxnReprs, i) ); + Gia_ObjSetNext( p->pAig, ObjId, Vec_IntEntry(p->vTxnNexts, i) ); + } + p->fTxnActive = 0; + p->nBatchRollback++; + p->nRollbackObjs += nChanged; + Vec_IntClear( p->vTxnObjs ); + Vec_IntClear( p->vTxnReprs ); + Vec_IntClear( p->vTxnNexts ); +} + +static int Cec_SeedSimRefineClass_rec( Cec_SeedSim_t * p, int Frame, int iRoot ) +{ + unsigned * pSim0; + int Ent, Count = 0; + Vec_IntClear( p->vClassOld ); + Vec_IntClear( p->vClassNew ); + Vec_IntPush( p->vClassOld, iRoot ); + pSim0 = Cec_SeedSimVal( p, Frame, iRoot ); + Gia_ClassForEachObj1( p->pAig, iRoot, Ent ) + { + unsigned * pSim1 = Cec_SeedSimVal( p, Frame, Ent ); + if ( Cec_SeedSimCompareRefine(p, pSim0, pSim1) ) + Vec_IntPush( p->vClassOld, Ent ); + else + Vec_IntPush( p->vClassNew, Ent ); + } + if ( Vec_IntSize(p->vClassNew) == 0 ) + return 0; + Cec_SeedSimTxnSaveVec( p, p->vClassOld ); + Cec_SeedSimTxnSaveVec( p, p->vClassNew ); + Cec_ManSimClassCreate( p->pAig, p->vClassOld ); + Cec_ManSimClassCreate( p->pAig, p->vClassNew ); + if ( Vec_IntSize(p->vClassNew) > 1 ) + Count += Cec_SeedSimRefineClass_rec( p, Frame, Vec_IntEntry(p->vClassNew, 0) ); + return Count + 1; +} + +static int Cec_SeedSimRefineClass( Cec_SeedSim_t * p, int Frame, int iRoot ) +{ + unsigned * pRoot = Cec_SeedSimVal( p, Frame, iRoot ); + unsigned * pDiff = p->pDiffMask; + unsigned * pTemp = p->pTempMask; + int Ent, i, w, Count; + memset( pDiff, 0, sizeof(unsigned) * p->nWords ); + Vec_IntClear( p->vClassAll ); + Gia_ClassForEachObj( p->pAig, iRoot, Ent ) + { + Vec_IntPush( p->vClassAll, Ent ); + if ( Ent == iRoot ) + continue; + Cec_SeedSimDiffMask( p, pRoot, Cec_SeedSimVal(p, Frame, Ent), + p->pRefineMask, pTemp ); + for ( w = 0; w < p->nWords; w++ ) + pDiff[w] |= pTemp[w]; + } + if ( Cec_SeedSimMaskIsZero(pDiff, p->nWords) ) + return 0; + Count = Cec_SeedSimRefineClass_rec( p, Frame, iRoot ); + assert( Count > 0 ); + Vec_IntForEachEntry( p->vClassAll, Ent, i ) + Cec_SeedSimAddSplitKey( p, Frame, Ent ); + return Count; +} + +static void Cec_SeedSimProcessRefinedConstants( Cec_SeedSim_t * p, + Cec_ManSim_t * pSim, int Frame ) +{ + Gia_Man_t * pAig = p->pAig; + int * pTable; + int i, k, Key, iPrev, nTableSize; + if ( Vec_IntSize(p->vConstRefined) == 0 ) + return; + Vec_IntForEachEntry( p->vConstRefined, i, k ) + { + unsigned * pValue = Cec_SeedSimVal( p, Frame, i ); + unsigned * pPhase = Gia_ObjPhase(Gia_ManObj(pAig, i)) ? p->pPhase1 : p->pPhase0; + unsigned * pDiff = p->pDiffMask; + Cec_SeedSimDiffMask( p, pValue, pPhase, p->pRefineMask, pDiff ); + if ( Cec_SeedSimMaskIsZero(pDiff, p->nWords) ) + { + Vec_IntDrop( p->vConstRefined, k-- ); + continue; + } + Cec_SeedSimAddSplitKey( p, Frame, i ); + } + if ( Vec_IntSize(p->vConstRefined) == 0 ) + return; + Cec_SeedSimTxnSaveVec( p, p->vConstRefined ); + if ( pSim->pPars->fConstCorr ) + { + Vec_IntForEachEntry( p->vConstRefined, i, k ) + Gia_ObjSetRepr( pAig, i, GIA_VOID ); + return; + } + nTableSize = Abc_PrimeCudd( 100 + Vec_IntSize(p->vConstRefined) / 3 ); + pTable = ABC_CALLOC( int, nTableSize ); + Vec_IntForEachEntry( p->vConstRefined, i, k ) + { + assert( Gia_ObjRepr(pAig, i) == 0 ); + assert( Gia_ObjNext(pAig, i) == 0 ); + Key = Cec_SeedSimHashRefine( p, Cec_SeedSimVal(p, Frame, i), nTableSize ); + iPrev = pTable[Key]; + if ( iPrev == 0 ) + Gia_ObjSetRepr( pAig, i, GIA_VOID ); + else + { + assert( iPrev < i ); + Gia_ObjSetNext( pAig, iPrev, i ); + Gia_ObjSetRepr( pAig, i, Gia_ObjRepr(pAig, iPrev) ); + if ( Gia_ObjRepr(pAig, i) == GIA_VOID ) + Gia_ObjSetRepr( pAig, i, iPrev ); + } + pTable[Key] = i; + } + Vec_IntForEachEntry( p->vConstRefined, i, k ) + if ( Gia_ObjIsHead(pAig, i) ) + Cec_SeedSimRefineClass_rec( p, Frame, i ); + ABC_FREE( pTable ); +} + +static void Cec_SeedSimRefineFrame( Cec_SeedSim_t * p, Cec_ManSim_t * pSim, + int Frame ) +{ + int i, Ent; + Vec_IntForEachEntry( p->vDirtyRoots, Ent, i ) + if ( Gia_ObjIsHead(p->pAig, Ent) ) + Cec_SeedSimRefineClass( p, Frame, Ent ); + Cec_SeedSimProcessRefinedConstants( p, pSim, Frame ); +} + +static int Cec_SeedSimProcessKeys( Cec_SeedSim_t * p, Cec_ManSim_t * pSim, + Vec_Int_t * vKeys, int nLimit, int fDiagnosis ) +{ + int iLo = 0; + p->pRefineMask = p->pActiveMask; + Vec_IntSort( vKeys, 0 ); + while ( iLo < Vec_IntSize(vKeys) ) + { + int Frame = Vec_IntEntry(vKeys, iLo) / p->nObjs; + int iHi = iLo; + while ( iHi < Vec_IntSize(vKeys) && + Vec_IntEntry(vKeys, iHi) / p->nObjs == Frame ) + iHi++; + if ( !Cec_SeedSimPrepareFrame(p, vKeys, Frame, iLo, iHi, nLimit, fDiagnosis) ) + return 0; + Cec_SeedSimRefineFrame( p, pSim, Frame ); + iLo = iHi; + } + return 1; +} + +static int Cec_SeedSimDiagnosisMissing( Cec_SeedSim_t * p ) +{ + int Count = 0, w; + for ( w = 0; w < p->nWords; w++ ) + { + unsigned Bits = p->pCexMask[w] & ~p->pFoundMask[w]; + while ( Bits ) + { + Bits &= Bits - 1; + Count++; + } + } + return Count; +} + +static void Cec_SeedSimRecordBatch( Cec_SeedSim_t * p, int nCex ) +{ + p->nBatchCex += nCex; + if ( nCex > p->nBatchCexMax ) + p->nBatchCexMax = nCex; +} + +static void Cec_SeedSimBuildPersistentValues( Cec_SeedSim_t * p ) +{ + Gia_Obj_t * pObj; + int Frame, i, w; + for ( Frame = 0; Frame < p->nFrames; Frame++ ) + { + memset( Cec_SeedSimVal(p, Frame, 0), 0, sizeof(unsigned) * p->nWords ); + for ( i = 0; i < p->nPis; i++ ) + { + int ObjId = Gia_ObjId( p->pAig, Gia_ManPi(p->pAig, i) ); + unsigned * pDst = Cec_SeedSimVal( p, Frame, ObjId ); + unsigned * pSrc = (unsigned *)Vec_PtrEntry( + p->vSimInfo, p->nRegs + Frame * p->nPis + i ); + memcpy( pDst, pSrc, sizeof(unsigned) * p->nWords ); + } + for ( i = 0; i < p->nRegs; i++ ) + { + int ObjId = Gia_ObjId( p->pAig, Gia_ManRo(p->pAig, i) ); + unsigned * pDst = Cec_SeedSimVal( p, Frame, ObjId ); + if ( Frame == 0 ) + { + unsigned * pSrc = (unsigned *)Vec_PtrEntry( p->vSimInfo, i ); + memcpy( pDst, pSrc, sizeof(unsigned) * p->nWords ); + } + else + { + Gia_Obj_t * pRi = Gia_ObjRoToRi( p->pAig, Gia_ManRo(p->pAig, i) ); + int RiId = Gia_ObjId( p->pAig, pRi ); + unsigned * pSrc = Cec_SeedSimVal( + p, Frame - 1, Gia_ObjFaninId0(pRi, RiId) ); + if ( Gia_ObjFaninC0(pRi) ) + for ( w = 0; w < p->nWords; w++ ) + pDst[w] = ~pSrc[w]; + else + memcpy( pDst, pSrc, sizeof(unsigned) * p->nWords ); + } + } + Gia_ManForEachAnd( p->pAig, pObj, i ) + { + unsigned * pDst = Cec_SeedSimVal( p, Frame, i ); + unsigned * pVal0 = Cec_SeedSimVal( + p, Frame, Gia_ObjFaninId0(pObj, i) ); + unsigned * pVal1 = Cec_SeedSimVal( + p, Frame, Gia_ObjFaninId1(pObj, i) ); + for ( w = 0; w < p->nWords; w++ ) + { + unsigned Val0 = Gia_ObjFaninC0(pObj) ? ~pVal0[w] : pVal0[w]; + unsigned Val1 = Gia_ObjFaninC1(pObj) ? ~pVal1[w] : pVal1[w]; + pDst[w] = Val0 & Val1; + } + } + } +} + +void Cec_SeedSimEnsurePersistent( Cec_SeedSim_t * p, Cec_ManSim_t * pSim ) +{ + int nInputs = p->nRegs + p->nPis * p->nFrames; + size_t nInputWords = (size_t)nInputs * p->nWords; + int i, w; + if ( p->vSimInfo == NULL ) + { + p->vSimInfo = Vec_PtrAllocSimInfo( nInputs, p->nWords ); + p->pPackPres = ABC_CALLOC( unsigned, nInputWords ); + p->pInputUndoMark = ABC_CALLOC( int, nInputWords ); + } + if ( p->fInitialized ) + return; + for ( i = 0; i < nInputs; i++ ) + { + unsigned * pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, i ); + for ( w = 0; w < p->nWords; w++ ) + pInfo[w] = i < p->nRegs ? 0 : Gia_ManRandom( 0 ); + pInfo[0] &= ~(unsigned)1; + } + // The baseline full sweep makes every current class consistent with the + // persistent patterns. It is paid once; later fallbacks are rolled back + // to this evolving persistent state without copying the dense value cache. + Cec_ManSeqResimulateSeed( pSim, p->vSimInfo, p ); + Cec_SeedSimBuildPersistentValues( p ); + p->fInitialized = 1; +} + +static void Cec_SeedSimStartInputTxn( Cec_SeedSim_t * p ) +{ + size_t nInputWords = (size_t)Vec_PtrSize(p->vSimInfo) * p->nWords; + Vec_IntClear( p->vInputUndo ); + Vec_IntClear( p->vChangedInputs ); + p->nInputUndoVersion++; + p->nInputVarVersion++; + if ( p->nInputUndoVersion == 0 ) + { + memset( p->pInputUndoMark, 0, sizeof(int) * nInputWords ); + p->nInputUndoVersion = 1; + } + if ( p->nInputVarVersion == 0 ) + { + memset( p->pInputVarMark, 0, + sizeof(int) * Vec_PtrSize(p->vSimInfo) ); + p->nInputVarVersion = 1; + } +} + +static void Cec_SeedSimSetInputWord( Cec_SeedSim_t * p, + int iVar, int w, unsigned Value ) +{ + int Flat = iVar * p->nWords + w; + unsigned * pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, iVar ); + if ( pInfo[w] == Value ) + return; + if ( p->pInputUndoMark[Flat] != p->nInputUndoVersion ) + { + p->pInputUndoMark[Flat] = p->nInputUndoVersion; + Vec_IntPush( p->vInputUndo, Flat ); + Vec_IntPush( p->vInputUndo, (int)pInfo[w] ); + } + if ( p->pInputVarMark[iVar] != p->nInputVarVersion ) + { + p->pInputVarMark[iVar] = p->nInputVarVersion; + Vec_IntPush( p->vChangedInputs, iVar ); + } + pInfo[w] = Value; +} + +static int Cec_SeedSimPackTry( Cec_SeedSim_t * p, + int iBit, int * pLits, int nLits ) +{ + int i, iVar, w = iBit >> 5; + unsigned Bit = (unsigned)1 << (iBit & 31); + for ( i = 0; i < nLits; i++ ) + { + unsigned * pInfo, * pPres; + iVar = Abc_Lit2Var( pLits[i] ); + pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, iVar ); + pPres = p->pPackPres + (size_t)iVar * p->nWords; + if ( (pPres[w] & Bit) && + ((pInfo[w] & Bit) != (Abc_LitIsCompl(pLits[i]) ? 0 : Bit)) ) + return 0; + } + for ( i = 0; i < nLits; i++ ) + { + unsigned * pInfo, * pPres; + unsigned Value; + int Flat; + iVar = Abc_Lit2Var( pLits[i] ); + pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, iVar ); + pPres = p->pPackPres + (size_t)iVar * p->nWords; + Flat = iVar * p->nWords + w; + if ( pPres[w] == 0 ) + Vec_IntPush( p->vPackTouched, Flat ); + pPres[w] |= Bit; + Value = Abc_LitIsCompl(pLits[i]) ? pInfo[w] & ~Bit : pInfo[w] | Bit; + Cec_SeedSimSetInputWord( p, iVar, w, Value ); + } + return 1; +} + +int Cec_SeedSimLoadPersistentBatch( Cec_SeedSim_t * p, Vec_Int_t * vCexStore, + int iStart, Vec_Int_t * vPairs, Vec_Int_t * vOutBits ) +{ + Vec_Int_t * vPat = Vec_IntAlloc( 100 ); + int nBits = 32 * p->nWords; + int i, k, nSize, Out, Flat; + Cec_SeedSimStartInputTxn( p ); + Vec_IntClear( p->vPackTouched ); + Vec_IntClear( vOutBits ); + while ( iStart < Vec_IntSize(vCexStore) ) + { + Out = Vec_IntEntry( vCexStore, iStart++ ); + nSize = Vec_IntEntry( vCexStore, iStart++ ); + if ( nSize <= 0 ) + continue; + Vec_IntClear( vPat ); + for ( k = 0; k < nSize; k++ ) + Vec_IntPush( vPat, Vec_IntEntry(vCexStore, iStart++) ); + for ( k = 1; k < nBits; k++ ) + if ( Cec_SeedSimPackTry( + p, k, Vec_IntArray(vPat), Vec_IntSize(vPat)) ) + break; + if ( k < nBits ) + { + Vec_IntPush( vOutBits, Out ); + Vec_IntPush( vOutBits, k ); + } + if ( k == nBits - 1 ) + break; + } + Vec_IntForEachEntry( p->vPackTouched, Flat, i ) + p->pPackPres[Flat] = 0; + Vec_IntClear( p->vPackTouched ); + Vec_IntForEachEntryDouble( vPairs, k, Out, i ) + { + unsigned * pSrc = (unsigned *)Vec_PtrEntry( p->vSimInfo, k ); + for ( nSize = 0; nSize < p->nWords; nSize++ ) + Cec_SeedSimSetInputWord( p, Out, nSize, pSrc[nSize] ); + } + Vec_IntFree( vPat ); + return iStart; +} + +void Cec_SeedSimRestorePersistentInputs( Cec_SeedSim_t * p ) +{ + int i, Flat; + for ( i = Vec_IntSize(p->vInputUndo) - 2; i >= 0; i -= 2 ) + { + Flat = Vec_IntEntry( p->vInputUndo, i ); + ((unsigned *)Vec_PtrEntry( + p->vSimInfo, Flat / p->nWords))[Flat % p->nWords] = + (unsigned)Vec_IntEntry( p->vInputUndo, i + 1 ); + } + Vec_IntClear( p->vInputUndo ); + Vec_IntClear( p->vChangedInputs ); +} + +static void Cec_SeedSimCommitPersistentInputs( Cec_SeedSim_t * p ) +{ + Vec_IntClear( p->vInputUndo ); + Vec_IntClear( p->vChangedInputs ); +} + +static void Cec_SeedSimEventHeapPushWord( Cec_SeedSim_t * p, int Key, int w ) +{ + unsigned * pWords = p->pEventWords + (size_t)Key * p->nEventMaskWords; + int i, Parent, fNew = 0; + if ( p->pMark[Key] != p->nMarkVersion ) + { + p->pMark[Key] = p->nMarkVersion; + memset( pWords, 0, sizeof(unsigned) * p->nEventMaskWords ); + Vec_IntPush( p->vQueue, Key ); + fNew = 1; + } + else if ( Abc_InfoHasBit(pWords, w) ) + return; + Abc_InfoSetBit( pWords, w ); + if ( !fNew ) + return; + for ( i = Vec_IntSize(p->vQueue) - 1; i > 0; i = Parent ) + { + Parent = (i - 1) >> 1; + if ( Vec_IntEntry(p->vQueue, Parent) <= Key ) + break; + Vec_IntWriteEntry( p->vQueue, i, + Vec_IntEntry(p->vQueue, Parent) ); + } + Vec_IntWriteEntry( p->vQueue, i, Key ); +} + +static int Cec_SeedSimEventHeapPop( Cec_SeedSim_t * p ) +{ + int Result = Vec_IntEntry( p->vQueue, 0 ); + int Last = Vec_IntPop( p->vQueue ); + int Size = Vec_IntSize( p->vQueue ); + int i = 0; + if ( Size == 0 ) + return Result; + while ( 2 * i + 1 < Size ) + { + int Child = 2 * i + 1; + if ( Child + 1 < Size && + Vec_IntEntry(p->vQueue, Child + 1) < + Vec_IntEntry(p->vQueue, Child) ) + Child++; + if ( Vec_IntEntry(p->vQueue, Child) >= Last ) + break; + Vec_IntWriteEntry( p->vQueue, i, + Vec_IntEntry(p->vQueue, Child) ); + i = Child; + } + Vec_IntWriteEntry( p->vQueue, i, Last ); + return Result; +} + +static void Cec_SeedSimEventRecordWord( Cec_SeedSim_t * p, + int Key, int w, unsigned OldValue ) +{ + Vec_IntPush( p->vValueUndo, Key ); + Vec_IntPush( p->vValueUndo, w ); + Vec_IntPush( p->vValueUndo, (int)OldValue ); +} + +static void Cec_SeedSimEventRecordChanged( Cec_SeedSim_t * p, int Key ) +{ + if ( p->pProcessMark[Key] == p->nProcessVersion ) + return; + p->pProcessMark[Key] = p->nProcessVersion; + Vec_IntPush( p->vChangedValues, Key ); +} + +static int Cec_SeedSimEventQueueFanouts( Cec_SeedSim_t * p, + int Frame, int ObjId, int w, int nEdgeLimit ) +{ + int FanId, i; + Gia_ObjForEachFanoutStaticId( p->pAig, ObjId, FanId, i ) + { + Gia_Obj_t * pFan = Gia_ManObj( p->pAig, FanId ); + if ( ++p->nEventEdges > nEdgeLimit ) + return 0; + if ( Gia_ObjIsAnd(pFan) ) + { + int FanKey = Cec_SeedSimKey(p, Frame, FanId); + if ( Cec_SeedSimConeHasKey(p, FanKey) ) + Cec_SeedSimEventHeapPushWord( p, FanKey, w ); + } + else if ( Gia_ObjIsRi(p->pAig, pFan) && + Frame + 1 < p->nFrames ) + { + int RoKey = Cec_SeedSimKey( + p, Frame + 1, Gia_ObjRiToRoId(p->pAig, FanId)); + if ( Cec_SeedSimConeHasKey(p, RoKey) ) + Cec_SeedSimEventHeapPushWord( p, RoKey, w ); + } + } + return 1; +} + +static int Cec_SeedSimEventUpdateInput( Cec_SeedSim_t * p, + int iVar, int nEdgeLimit ) +{ + int Frame, ObjId, w, Key, fChanged = 0; + unsigned * pInput; + if ( iVar < p->nRegs ) + { + Frame = 0; + ObjId = Gia_ObjId( p->pAig, Gia_ManRo(p->pAig, iVar) ); + } + else + { + int iPi = (iVar - p->nRegs) % p->nPis; + Frame = (iVar - p->nRegs) / p->nPis; + ObjId = Gia_ObjId( p->pAig, Gia_ManPi(p->pAig, iPi) ); + } + Key = Cec_SeedSimKey( p, Frame, ObjId ); + if ( !Cec_SeedSimConeHasKey(p, Key) ) + return 1; + pInput = (unsigned *)Vec_PtrEntry( p->vSimInfo, iVar ); + for ( w = 0; w < p->nWords; w++ ) + { + unsigned * pValue = Cec_SeedSimVal( p, Frame, ObjId ); + if ( pValue[w] == pInput[w] ) + continue; + Cec_SeedSimEventRecordWord( + p, Key, w, pValue[w] ); + pValue[w] = pInput[w]; + fChanged = 1; + if ( !Cec_SeedSimEventQueueFanouts( + p, Frame, ObjId, w, nEdgeLimit) ) + return 0; + } + if ( !fChanged ) + return 1; + Cec_SeedSimEventRecordChanged( p, Key ); + return 1; +} + +static int Cec_SeedSimEventUpdateNode( Cec_SeedSim_t * p, + int Key, int nNodeLimit, int nEdgeLimit ) +{ + int Frame = Key / p->nObjs; + int ObjId = Key % p->nObjs; + Gia_Obj_t * pObj = Gia_ManObj( p->pAig, ObjId ); + unsigned * pDst = Cec_SeedSimVal( p, Frame, ObjId ); + unsigned * pVal0, * pVal1 = NULL; + unsigned * pWords = p->pEventWords + (size_t)Key * p->nEventMaskWords; + int m, w, fChanged = 0; + if ( Gia_ObjIsRo(p->pAig, pObj) ) + { + Gia_Obj_t * pRi; + int RiId; + assert( Frame > 0 ); + pRi = Gia_ObjRoToRi( p->pAig, pObj ); + RiId = Gia_ObjId( p->pAig, pRi ); + pVal0 = Cec_SeedSimVal( + p, Frame - 1, Gia_ObjFaninId0(pRi, RiId) ); + for ( m = 0; m < p->nEventMaskWords; m++ ) + { + unsigned Bits = pWords[m]; + while ( Bits ) + { + w = 32 * m + Gia_WordFindFirstBit( Bits ); + Bits &= Bits - 1; + if ( w >= p->nWords ) + continue; + if ( ++p->nEventPops > nNodeLimit ) + return 0; + { + unsigned Value = Gia_ObjFaninC0(pRi) ? ~pVal0[w] : pVal0[w]; + if ( pDst[w] == Value ) + continue; + Cec_SeedSimEventRecordWord( p, Key, w, pDst[w] ); + pDst[w] = Value; + fChanged = 1; + if ( !Cec_SeedSimEventQueueFanouts( + p, Frame, ObjId, w, nEdgeLimit) ) + return 0; + } + } + } + } + else + { + assert( Gia_ObjIsAnd(pObj) ); + pVal0 = Cec_SeedSimVal( + p, Frame, Gia_ObjFaninId0(pObj, ObjId) ); + pVal1 = Cec_SeedSimVal( + p, Frame, Gia_ObjFaninId1(pObj, ObjId) ); + for ( m = 0; m < p->nEventMaskWords; m++ ) + { + unsigned Bits = pWords[m]; + while ( Bits ) + { + w = 32 * m + Gia_WordFindFirstBit( Bits ); + Bits &= Bits - 1; + if ( w >= p->nWords ) + continue; + if ( ++p->nEventPops > nNodeLimit ) + return 0; + { + unsigned Val0 = Gia_ObjFaninC0(pObj) ? ~pVal0[w] : pVal0[w]; + unsigned Val1 = Gia_ObjFaninC1(pObj) ? ~pVal1[w] : pVal1[w]; + unsigned Value = Val0 & Val1; + if ( pDst[w] == Value ) + continue; + Cec_SeedSimEventRecordWord( p, Key, w, pDst[w] ); + pDst[w] = Value; + fChanged = 1; + if ( !Cec_SeedSimEventQueueFanouts( + p, Frame, ObjId, w, nEdgeLimit) ) + return 0; + } + } + } + } + if ( !fChanged ) + return 1; + Cec_SeedSimEventRecordChanged( p, Key ); + return 1; +} + +static void Cec_SeedSimEventRollbackValues( Cec_SeedSim_t * p ) +{ + int i, Key, w; + for ( i = Vec_IntSize(p->vValueUndo) - 3; i >= 0; i -= 3 ) + { + Key = Vec_IntEntry( p->vValueUndo, i ); + w = Vec_IntEntry( p->vValueUndo, i + 1 ); + Cec_SeedSimVal( + p, Key / p->nObjs, Key % p->nObjs)[w] = + (unsigned)Vec_IntEntry( p->vValueUndo, i + 2 ); + } + Vec_IntClear( p->vValueUndo ); + Vec_IntClear( p->vChangedValues ); +} + +static void Cec_SeedSimEventRefine( Cec_SeedSim_t * p, Cec_ManSim_t * pSim ) +{ + int iLo = 0; + p->pRefineMask = p->pActiveMask; + // Baseline classes are value-consistent. If a pair becomes different, + // at least one member changed, so regrouping these roots is complete. + Vec_IntSort( p->vChangedValues, 0 ); + while ( iLo < Vec_IntSize(p->vChangedValues) ) + { + int Frame = Vec_IntEntry(p->vChangedValues, iLo) / p->nObjs; + int iHi = iLo, i, Key, ObjId; + while ( iHi < Vec_IntSize(p->vChangedValues) && + Vec_IntEntry(p->vChangedValues, iHi) / p->nObjs == Frame ) + iHi++; + Cec_SeedSimStartRootSet( p ); + for ( i = iLo; i < iHi; i++ ) + { + Key = Vec_IntEntry( p->vChangedValues, i ); + ObjId = Key % p->nObjs; + if ( Gia_ObjIsConst(p->pAig, ObjId) || + Gia_ObjIsClass(p->pAig, ObjId) ) + Cec_SeedSimAddRoot( p, ObjId ); + } + Cec_SeedSimRefineFrame( p, pSim, Frame ); + iLo = iHi; + } +} + +static void Cec_SeedSimQueueInitialSplits( Cec_SeedSim_t * p, int nInitialSplits ) +{ + int i, Key; + for ( i = 0; i < nInitialSplits; i++ ) + { + Key = Vec_IntEntry( p->vSplitKeys, i ); + int Frame = Key / p->nObjs; + int ObjId = Key % p->nObjs; + if ( Cec_SeedSimMark(p, Frame, ObjId) ) + Vec_IntPush( p->vQueue, Key ); + } +} + +static void Cec_SeedSimCollectWave( Cec_SeedSim_t * p ) +{ + int i, Key; + Vec_IntClear( p->vWaveKeys ); + Vec_IntForEachEntry( p->vDirtyKeys, Key, i ) + { + if ( p->pProcessMark[Key] == p->nProcessVersion ) + continue; + p->pProcessMark[Key] = p->nProcessVersion; + Vec_IntPush( p->vWaveKeys, Key ); + } +} + +static int Cec_SeedSimTryBatchLegacy( Cec_SeedSim_t * p, Cec_ManSim_t * pSim, + Vec_Ptr_t * vSimInfo, Vec_Int_t * vOutputs, Vec_Int_t * vOutBits, int nFrames ) +{ + ABC_INT64_T nKeys = (ABC_INT64_T)p->nFrames * p->nObjs; + int nLimit = (int)(nKeys * CEC_SEEDSIM_HARD_FRAC_NUM / CEC_SEEDSIM_HARD_FRAC_DEN); + int nDiagLimit = (int)(nKeys * CEC_SEEDSIM_DIAG_FRAC_NUM / CEC_SEEDSIM_DIAG_FRAC_DEN); + int nTfoLimit = (int)(nKeys * CEC_SEEDSIM_TFO_FRAC_NUM / CEC_SEEDSIM_TFO_FRAC_DEN); + int nBatchCex = Vec_IntSize(vOutBits) / 2; + int nPackedLanes = 32 * p->nWords - 1; + int nInitialSplits, nDirty; + assert( nFrames == p->nFrames ); + assert( Vec_PtrSize(vSimInfo) == p->nRegs + p->nPis * p->nFrames ); + assert( Vec_PtrReadWordsSimInfo(vSimInfo) == p->nWords ); + Cec_SeedSimRecordBatch( p, nBatchCex ); + if ( !p->fInitialized ) + { + p->nFallbackPre++; + p->nBatchFull++; + return CEC_SEEDSIM_RESULT_FULL; + } + if ( nBatchCex > CEC_SEEDSIM_CEX_LANE_FACTOR * nPackedLanes ) + { + p->nFallbackCex++; + p->nBatchFull++; + return CEC_SEEDSIM_RESULT_FULL_WIDE; + } + Cec_SeedSimReset( p ); + p->vBatchInfo = vSimInfo; + if ( !Cec_SeedSimDiagnosisShapeSmall(p, vOutputs, vOutBits, nDiagLimit) ) + { + nDirty = Vec_IntSize( p->vDirtyKeys ); + if ( nDirty > p->nMaxDirty ) + p->nMaxDirty = nDirty; + p->vBatchInfo = NULL; + p->nFallbackPre++; + p->nBatchFull++; + return CEC_SEEDSIM_RESULT_FULL_WIDE; + } + Cec_SeedSimRestartTfoMarks( p ); + if ( !Cec_SeedSimCollectDiagnosis(p, vOutputs, vOutBits, nLimit) || + Vec_IntSize(p->vDiagKeys) > nLimit ) + { + nDirty = Abc_MaxInt( p->nSpecKeys, p->nEvalKeys ); + if ( nDirty > p->nMaxDirty ) + p->nMaxDirty = nDirty; + p->vBatchInfo = NULL; + p->nFallbackPre++; + p->nBatchFull++; + return CEC_SEEDSIM_RESULT_FULL_WIDE; + } + if ( !Cec_SeedSimDiagnosisEvalShapeSmall(p, p->vDiagKeys, nDiagLimit) ) + { + nDirty = Vec_IntSize( p->vDirtyKeys ); + if ( nDirty > p->nMaxDirty ) + p->nMaxDirty = nDirty; + p->vBatchInfo = NULL; + p->nFallbackPre++; + p->nBatchFull++; + return CEC_SEEDSIM_RESULT_FULL_WIDE; + } + Cec_SeedSimRestartTfoMarks( p ); + Cec_SeedSimUseCexLanes( p ); + Cec_SeedSimTxnBegin( p ); + if ( !Cec_SeedSimProcessKeys(p, pSim, p->vDiagKeys, nLimit, 1) ) + { + nDirty = Abc_MaxInt( p->nSpecKeys, p->nEvalKeys ); + if ( nDirty > p->nMaxDirty ) + p->nMaxDirty = nDirty; + Cec_SeedSimTxnRollback( p ); + p->vBatchInfo = NULL; + p->nFallbackProcess++; + p->nBatchFull++; + return CEC_SEEDSIM_RESULT_FULL; + } + { + int nMissing; + nMissing = Cec_SeedSimDiagnosisMissing( p ); + if ( nMissing ) + { + nDirty = Abc_MaxInt( p->nSpecKeys, p->nEvalKeys ); + if ( nDirty > p->nMaxDirty ) + p->nMaxDirty = nDirty; + Cec_SeedSimTxnRollback( p ); + p->vBatchInfo = NULL; + p->nCoverageMiss += nMissing; + p->nFallbackCoverage++; + p->nBatchFull++; + return CEC_SEEDSIM_RESULT_FULL; + } + } + Cec_SeedSimTxnCommit( p ); + Cec_SeedSimUsePackedLanes( p ); + nInitialSplits = Vec_IntSize( p->vSplitKeys ); + Cec_SeedSimQueueInitialSplits( p, nInitialSplits ); + if ( !Cec_SeedSimComputeTfo(p, nTfoLimit) ) + { + nDirty = Vec_IntSize( p->vDirtyKeys ); + if ( nDirty > p->nMaxDirty ) + p->nMaxDirty = nDirty; + p->vBatchInfo = NULL; + p->nBatchTrunc++; + p->nTruncCone++; + p->nBatchLocal++; + return CEC_SEEDSIM_RESULT_LOCAL; + } + Cec_SeedSimCollectWave( p ); + if ( Vec_IntSize(p->vWaveKeys) && + !Cec_SeedSimProcessKeys(p, pSim, p->vWaveKeys, nTfoLimit, 0) ) + { + p->nDeferredSplits += Vec_IntSize(p->vSplitKeys) - nInitialSplits; + if ( p->nEvalKeys > p->nMaxDirty ) + p->nMaxDirty = p->nEvalKeys; + p->vBatchInfo = NULL; + p->nBatchTrunc++; + p->nTruncEval++; + p->nBatchLocal++; + return CEC_SEEDSIM_RESULT_LOCAL; + } + p->nDeferredSplits += Vec_IntSize(p->vSplitKeys) - nInitialSplits; + nDirty = Abc_MaxInt( p->nSpecKeys, Vec_IntSize(p->vDirtyKeys) ); + nDirty = Abc_MaxInt( nDirty, p->nEvalKeys ); + if ( nDirty > p->nMaxDirty ) + p->nMaxDirty = nDirty; + p->vBatchInfo = NULL; + p->nBatchLocal++; + return CEC_SEEDSIM_RESULT_LOCAL; +} + +int Cec_SeedSimTryBatch( Cec_SeedSim_t * p, Cec_ManSim_t * pSim, + Vec_Ptr_t * vSimInfo, Vec_Int_t * vOutputs, Vec_Int_t * vOutBits, int nFrames ) +{ + ABC_INT64_T nKeys = (ABC_INT64_T)p->nFrames * p->nObjs; + ABC_INT64_T nWordKeys = nKeys * p->nWords; + ABC_INT64_T nNodeLimit64 = nWordKeys * + CEC_EVENT_NODE_WORD_FRAC_NUM / CEC_EVENT_NODE_WORD_FRAC_DEN; + ABC_INT64_T nEdgeLimit64 = nWordKeys * + CEC_EVENT_EDGE_WORD_FRAC_NUM / CEC_EVENT_EDGE_WORD_FRAC_DEN; + int nNodeLimit = nNodeLimit64 > 0x7fffffff ? 0x7fffffff : (int)nNodeLimit64; + int nEdgeLimit = nEdgeLimit64 > 0x7fffffff ? 0x7fffffff : (int)nEdgeLimit64; + int nInputVars = Vec_IntSize( p->vChangedInputs ); + int nInputWords = Vec_IntSize( p->vInputUndo ) / 2; + int nTotalInputs = p->nRegs + p->nPis * p->nFrames; + int i, iVar, Key; + int Status = CEC_SEEDSIM_RESULT_LOCAL; + assert( nFrames == p->nFrames ); + assert( vSimInfo == p->vSimInfo ); + Cec_SeedSimRecordBatch( p, Vec_IntSize(vOutBits) / 2 ); + p->nEventInputVarsMax = Abc_MaxInt( p->nEventInputVarsMax, nInputVars ); + p->nEventInputWordsMax = Abc_MaxInt( p->nEventInputWordsMax, nInputWords ); + if ( (ABC_INT64_T)nInputVars * CEC_EVENT_INPUT_FRAC_DEN > + (ABC_INT64_T)nTotalInputs * CEC_EVENT_INPUT_FRAC_NUM ) + { + p->nFallbackCex++; + p->nBatchFull++; + return CEC_SEEDSIM_RESULT_FULL_WIDE; + } + (void)vOutputs; + Cec_SeedSimReset( p ); + Vec_IntClear( p->vValueUndo ); + Vec_IntClear( p->vChangedValues ); + p->nEventPops = p->nEventEdges = 0; + + Vec_IntForEachEntry( p->vChangedInputs, iVar, i ) + if ( !Cec_SeedSimEventUpdateInput(p, iVar, nEdgeLimit) ) + { + Status = CEC_SEEDSIM_RESULT_FULL_WIDE; + break; + } + while ( Status == CEC_SEEDSIM_RESULT_LOCAL && + Vec_IntSize(p->vQueue) > 0 ) + { + Key = Cec_SeedSimEventHeapPop( p ); + if ( !Cec_SeedSimEventUpdateNode( + p, Key, nNodeLimit, nEdgeLimit) ) + { + Status = CEC_SEEDSIM_RESULT_FULL_WIDE; + break; + } + } + p->nEventPopsMax = Abc_MaxInt( p->nEventPopsMax, p->nEventPops ); + p->nEventEdgesMax = Abc_MaxInt( p->nEventEdgesMax, p->nEventEdges ); + p->nMaxDirty = Abc_MaxInt( + p->nMaxDirty, Vec_IntSize(p->vChangedValues) ); + if ( Status != CEC_SEEDSIM_RESULT_LOCAL ) + { + Cec_SeedSimEventRollbackValues( p ); + p->nEventFallback++; + p->nEventFallbackWork++; + p->nFallbackPre++; + p->nBatchFull++; + return Status; + } + Cec_SeedSimTxnBegin( p ); + Cec_SeedSimEventRefine( p, pSim ); + Cec_SeedSimTxnCommit( p ); + Vec_IntClear( p->vValueUndo ); + Vec_IntClear( p->vChangedValues ); + Cec_SeedSimCommitPersistentInputs( p ); + p->nEventLocal++; + p->nBatchLocal++; + return CEC_SEEDSIM_RESULT_LOCAL; +} + +void Cec_SeedSimSaveFrameInputs( Cec_SeedSim_t * p, Vec_Ptr_t * vInfoCis, int Frame ) +{ + Gia_Obj_t * pObj; + int i; + assert( Frame >= 0 && Frame < p->nFrames ); + assert( Vec_PtrSize(vInfoCis) == p->nPis + p->nRegs ); + assert( Vec_PtrReadWordsSimInfo(vInfoCis) == p->nWords ); + Cec_SeedSimSetPhase( p, Frame, 0, 0 ); + Gia_ManForEachCi( p->pAig, pObj, i ) + Cec_SeedSimSetPhase( p, Frame, Gia_ObjId(p->pAig, pObj), 0 ); +} + +void Cec_SeedSimSaveFrameOutputs( Cec_SeedSim_t * p, Vec_Ptr_t * vInfoCos, int Frame ) +{ + Gia_Obj_t * pObj; + int i; + assert( Frame >= 0 && Frame < p->nFrames ); + assert( Vec_PtrSize(vInfoCos) == Gia_ManCoNum(p->pAig) ); + assert( Vec_PtrReadWordsSimInfo(vInfoCos) == p->nWords ); + Gia_ManForEachCo( p->pAig, pObj, i ) + Cec_SeedSimSetPhase( p, Frame, Gia_ObjId(p->pAig, pObj), + ((unsigned *)Vec_PtrEntry(vInfoCos, i))[0] & 1 ); +} + +void Cec_SeedSimFinishFull( Cec_SeedSim_t * p ) +{ + p->fInitialized = 1; +} + +void Cec_SeedSimBeginCall( Cec_SeedSim_t * p ) +{ + assert( !p->fTxnActive ); + p->nBatchLocal = p->nBatchFull = p->nBatchTrunc = p->nMaxDirty = 0; + p->nBatchRollback = p->nRollbackObjs = p->nCoverageMiss = 0; + p->nFallbackPre = p->nFallbackProcess = p->nFallbackCoverage = 0; + p->nFallbackCex = p->nFallbackBypass = 0; + p->nTruncCone = p->nTruncEval = 0; + p->nBatchCex = p->nBatchCexMax = p->nDeferredSplits = 0; + p->nEventLocal = p->nEventFallback = 0; + p->nEventPopsMax = p->nEventEdgesMax = 0; + p->nEventInputVarsMax = p->nEventInputWordsMax = 0; + p->nEventFallbackWork = 0; +} + +void Cec_SeedSimBypassBatch( Cec_SeedSim_t * p, int nCex ) +{ + Cec_SeedSimRecordBatch( p, nCex ); + p->nFallbackBypass++; + p->nBatchFull++; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END diff --git a/src/proof/cec/cecInt.h b/src/proof/cec/cecInt.h index f78e5f25ff..f2f608fa83 100644 --- a/src/proof/cec/cecInt.h +++ b/src/proof/cec/cecInt.h @@ -149,7 +149,7 @@ struct Cec_ManFra_t_ { // parameters Gia_Man_t * pAig; // the AIG to be used for simulation - Cec_ParFra_t * pPars; // SAT sweeping parameters + Cec_ParFra_t * pPars; // SAT sweeping parameters // simulation patterns Vec_Int_t * vXorNodes; // nodes used in speculative reduction int nAllProved; // total number of proved nodes @@ -165,6 +165,192 @@ struct Cec_ManFra_t_ abctime timeTotal; // total runtime }; +// incremental active-list manager for &scorr -i +typedef struct Cec_IncrMgr_t_ Cec_IncrMgr_t; +struct Cec_IncrMgr_t_ +{ + Gia_Man_t * pAig; // host AIG (immutable across iterations) + int nFrames; // unrolling depth used by the SRM builder + int nObjs; // cached Gia_ManObjNum(pAig) + Vec_Int_t * vReprPrev; // snapshot of pReprs from previous round + Vec_Int_t * vNextPrev; // snapshot of pNexts from previous round + Vec_Int_t * vSeeds; // repr-change TFO seeds + Vec_Int_t * vTfoNodes; // ids currently in TFO (for fast clearing) + int * pTfoMark; // dense mark array, size = nObjs + Vec_Int_t * vAliasHeads; // repr -> first member using it in the SRM + Vec_Int_t * vAliasNext; // next member with the same representative + Vec_Int_t * vBfsCur; // BFS frontier for current frame + Vec_Int_t * vBfsNext; // BFS frontier carried to next frame + int fOwnsFanout; // 1 if we built static fanout (must free) +}; + +typedef enum Cec_IncrEmitMode_t_ +{ + CEC_EMIT_ALL, + CEC_EMIT_ACTIVE, + CEC_EMIT_SKIPPED +} Cec_IncrEmitMode_t; + +// Persistent event-driven simulation manager for &scorr incremental mode. +// Packed input patterns and host-AIG values survive across CEX batches. A +// batch records only the input words it changes; real value deltas propagate +// through the frame-aware fanout graph and dirty classes are fully regrouped. +// +// Keying uses key = frame*nObjs + objId. pVal layout: +// pVal[(frame * nObjs + objId) * nWords + w] +typedef struct Cec_SeedSim_t_ Cec_SeedSim_t; +struct Cec_SeedSim_t_ +{ + Gia_Man_t * pAig; // host AIG (immutable across iterations) + int nFrames; // total unrolling depth used by resim + int iSeedFrame; // frame where SAT proved the endpoint pair + int nObjs; // cached Gia_ManObjNum(pAig) + int nPis; // cached Gia_ManPiNum(pAig) + int nRegs; // cached Gia_ManRegNum(pAig) + int nWords; // sim words per key (= pSim->pPars->nWords) + int nPhaseWords; // bitset words per frame for persistent phase anchors + int fInitialized; // persistent inputs/values have a refined baseline + // Dense persistent value storage. + unsigned * pVal; // size = (size_t)nFrames * nObjs * nWords + unsigned * pPhase; // size = (size_t)nFrames * nPhaseWords + unsigned * pActiveMask; // all packed simulation lanes except phase bit 0 + unsigned * pCexMask; // packed real-CEX lanes used for diagnosis coverage + unsigned * pRefineMask; // non-owning mask selected for current regrouping phase + unsigned * pFoundMask; // CEX lanes explained by a real host-AIG split + unsigned * pDiffMask; // nWords scratch for signature differences + unsigned * pTempMask; // nWords scratch + // Dense per-key state. + int * pMark; // split-TFO visited stamp, size = nFrames * nObjs + int * pSpecMark; // sparse speculative-mask record index plus one + int * pDiagMark; // sparse diagnosis record index plus one + int * pSplitMark; // real-split worklist stamp + int * pProcessMark; // split-TFO key already refined stamp + int * pEvalMark; // current-input value version stamp + int nMarkVersion; + int nSplitVersion; + int nProcessVersion; + int nEvalVersion; + int nSpecKeys; // unrolled keys visited by speculative diagnosis + int nEvalKeys; // keys evaluated from current inputs this batch + Vec_Int_t * vDiagPairs; // failed host pairs as triples (obj0, obj1, bit) + Vec_Int_t * vSpecKeys; // sparse speculative-TFI keys + Vec_Int_t * vSpecMasks; // flat [spec record][word] lane masks + Vec_Int_t * vDiagKeys; // sparse speculative assumptions/failed endpoints + Vec_Int_t * vDiagRoots; // original class root for each diagnosis record + Vec_Int_t * vDiagMasks; // flat [diagnosis record][word] lane masks + Vec_Int_t * vSplitKeys; // nodes in classes actually split by current CEX + Vec_Int_t * vDirtyKeys; // keys reached by split-driven TFO + Vec_Int_t * vWaveKeys; // newly reached TFO keys awaiting refinement + Vec_Int_t * vQueue; // split-TFO BFS frontier + Vec_Ptr_t * vSimInfo; // reusable full-simulation CI storage + Vec_Ptr_t * vBatchInfo; // non-owning current packed CEX input vectors + // Persistent CEX packing and event propagation. + unsigned * pPackPres; // sparse-cleared assignment-presence words + int * pInputUndoMark; // input word already journaled this batch + int * pInputVarMark; // input vector already queued this batch + int nInputUndoVersion; + int nInputVarVersion; + Vec_Int_t * vPackTouched; // flat input words to clear after packing + Vec_Int_t * vInputUndo; // pairs (flat input word, old value) + Vec_Int_t * vChangedInputs; // input vector indices changed by this batch + Vec_Int_t * vValueUndo; // triples (key, word, old value) + Vec_Int_t * vChangedValues; // keys whose persistent value really changed + unsigned * pEventWords; // sparse queued-word masks, indexed by key + int nEventMaskWords; // words needed to represent nWords bits + int nEventPops; // evaluated node-word operations + int nEventEdges; // traversed fanout word-edges + // Frame-aware class-cone filter. When enabled, event propagation only + // visits keys in the true TFI of current class/constant candidates. + unsigned * pCone; // bitset indexed by key = frame*nObjs+objId + int nConeWords; // bitset words for pCone + int nConeKeys; // marked keys in the current cone + int fUseCone; // 1 after pCone was built for this resim call + Vec_Int_t * vConeQueue; // newly marked keys used to class-close pCone + int * pConeClose; // (frame,root) stamp: class already closed this build + int nConeCloseVer; // version for pConeClose + int nFallbackStreak; // persists across resimulation calls + int nFallbackCooldown; // batches bypassed before next event probe + // Class-refinement scratch. + int * pRootMark; // per-objId "root already queued" stamp + int nRootVersion; + Vec_Int_t * vDirtyRoots; + Vec_Int_t * vConstRefined; + Vec_Int_t * vClassAll; + Vec_Int_t * vClassOld; + Vec_Int_t * vClassNew; + // Sparse undo journal for diagnosis-time class refinement. + int * pTxnMark; // object already saved in the current transaction + int nTxnVersion; + int fTxnActive; + Vec_Int_t * vTxnObjs; + Vec_Int_t * vTxnReprs; + Vec_Int_t * vTxnNexts; + unsigned * pPhase0; // nWords of 0 (phase-0 vector, used by refine) + unsigned * pPhase1; // nWords of ~0 (phase-1 vector) + int fOwnsFanout; // 1 if we built static fanout (must free) + // Profile counters (reset per resim call) + int nBatchLocal; // rounds handled by local TFO sim + int nBatchFull; // rounds that fell back to full sweep + int nBatchTrunc; // local rounds that stopped optional TFO expansion + int nBatchRollback; // diagnosis transactions rolled back before full sweep + int nRollbackObjs; // class entries restored by transaction rollback + int nCoverageMiss; // packed CEX lanes unexplained by local diagnosis + int nFallbackPre; // fallback before diagnosis mutates classes + int nFallbackProcess; // fallback because diagnosis evaluation exceeded budget + int nFallbackCoverage; // fallback because diagnosis did not explain all CEX lanes + int nFallbackCex; // cheap rejection of oversized packed CEX batches + int nFallbackBypass; // batches sent directly to full after repeated fallback + int nTruncCone; // local TFO stopped while growing the structural cone + int nTruncEval; // local TFO stopped while evaluating/refining the cone + int nBatchCex; // total real CEX records across packed batches + int nBatchCexMax; // largest real-CEX count in one packed batch + int nDeferredSplits; // TFO-created splits not re-enqueued in fixed-frontier mode + int nMaxDirty; // largest TFO/evaluated closure across this call + int nEventLocal; // batches completed by value-delta propagation + int nEventFallback; // batches whose event budget was exceeded + int nEventPopsMax; // largest number of evaluated event nodes + int nEventEdgesMax; // largest number of traversed fanout edges + int nEventInputVarsMax; // largest changed-CI count in one batch + int nEventInputWordsMax; // largest changed-CI-word count in one batch + int nEventFallbackWork; // structural word-operation budget exceeded +}; + +// Dynamic SRM construction manager for &scorr incremental mode. It keeps the +// speculative SRM core used by SAT. +typedef struct Cec_DynSrm_t_ Cec_DynSrm_t; + +// Recursive diagnosis has a much higher constant factor than a linear sweep. +// Reject wide speculative and complete-class evaluation cones before mutation. +#define CEC_SEEDSIM_DIAG_FRAC_NUM 1 +#define CEC_SEEDSIM_DIAG_FRAC_DEN 20 +// Detailed lane-aware diagnosis is required for correctness, but should still +// fall back before recursive work approaches the cost of a full linear sweep. +#define CEC_SEEDSIM_HARD_FRAC_NUM 1 +#define CEC_SEEDSIM_HARD_FRAC_DEN 10 +// Split-driven TFO refinement is optional. Stop it without a full fallback +// when its structural or demand-evaluation closure exceeds this budget. +#define CEC_SEEDSIM_TFO_FRAC_NUM 1 +#define CEC_SEEDSIM_TFO_FRAC_DEN 20 +// Diagnosis cost grows with the number of CEX records, even when many records +// share the same packed bit lane. Reject unusually dense batches cheaply. +#define CEC_SEEDSIM_CEX_LANE_FACTOR 8 +// Consecutive wide cones use bounded exponential backoff. A successful local +// batch clears both the streak and cooldown immediately. +#define CEC_SEEDSIM_MAX_FALLBACK_BACKOFF 7 +#define CEC_EVENT_NODE_WORD_FRAC_NUM 1 +#define CEC_EVENT_NODE_WORD_FRAC_DEN 10 +#define CEC_EVENT_EDGE_WORD_FRAC_NUM 1 +#define CEC_EVENT_EDGE_WORD_FRAC_DEN 5 +// Up-front density gate for the event path. When a batch's changed-CI seed +// exceeds this fraction of all unrolled inputs, its dirty closure approaches a +// full sweep and bit-parallel full resim wins; reject the batch before doing +// any propagation work that a mid-flight budget abort would otherwise discard. +#define CEC_EVENT_INPUT_FRAC_NUM 1 +#define CEC_EVENT_INPUT_FRAC_DEN 8 +#define CEC_SEEDSIM_RESULT_FULL 0 +#define CEC_SEEDSIM_RESULT_LOCAL 1 +#define CEC_SEEDSIM_RESULT_FULL_WIDE -1 + //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -175,11 +361,58 @@ struct Cec_ManFra_t_ /*=== cecCorr.c ============================================================*/ extern void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, abctime Time ); +extern void Cec_ManStartSimInfo( Vec_Ptr_t * vInfo, int nFlops ); +extern Vec_Int_t * Gia_ManCorrCreateRemapping( Gia_Man_t * p ); +extern void Gia_ManCorrPerformRemapping( Vec_Int_t * vPairs, Vec_Ptr_t * vInfo ); +extern int Cec_ManLoadCounterExamples( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart ); +extern int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ); +extern void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ); +extern Gia_Man_t * Gia_ManCorrSpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings ); +/*=== cecCorrIncr.c ============================================================*/ +extern Cec_IncrMgr_t * Cec_IncrMgrAlloc( Gia_Man_t * pAig, int nFrames ); +extern void Cec_IncrMgrFree( Cec_IncrMgr_t * p ); +extern void Cec_IncrMgrSnapshotClasses( Cec_IncrMgr_t * p ); +extern int Cec_IncrMgrComputeSeeds( Cec_IncrMgr_t * p ); +extern int Cec_IncrMgrCountNextChanges( Cec_IncrMgr_t * p ); +extern int Cec_IncrMgrRingEdgeChanged( Cec_IncrMgr_t * p, int iPrev, int iObj ); +extern void Cec_IncrMgrCountActivePairs( Cec_IncrMgr_t * p, int fRings, int * pTfoMark, int * pnTotal, int * pnActive ); +extern void Cec_IncrMgrComputeTfo( Cec_IncrMgr_t * p ); +extern Gia_Man_t * Gia_ManCorrSpecReduce_Emit( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings, int * pTfoMark, Cec_IncrMgr_t * pIncr, Cec_IncrEmitMode_t Mode, Vec_Int_t ** pvOutLits ); +extern Gia_Man_t * Gia_ManCorrSpecReduceInit_Active( Gia_Man_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int * pTfoMark ); +/*=== cecCorrDyn.c ============================================================*/ +extern Cec_DynSrm_t * Cec_DynSrmAlloc( Gia_Man_t * pAig, Cec_IncrMgr_t * pIncr ); +extern void Cec_DynSrmFree( Cec_DynSrm_t * p ); +extern void Cec_DynSrmPrintStats( Cec_DynSrm_t * p ); +extern void Cec_DynSrmCountActivePairs( Cec_DynSrm_t * p, int fRings, int * pTfoMark, int * pnTotal, int * pnActive ); +extern Gia_Man_t * Cec_DynSrmBuild( Cec_DynSrm_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings, int * pTfoMask, Cec_IncrEmitMode_t Mode ); +extern void Cec_DynSrmBuildCore( Cec_DynSrm_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings, int * pTfoMask, Cec_IncrEmitMode_t Mode ); +extern Gia_Man_t * Cec_DynSrmBuildInit( Cec_DynSrm_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int * pTfoMask, Cec_IncrEmitMode_t Mode ); +extern void Cec_DynSrmBuildCoreInit( Cec_DynSrm_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int * pTfoMask, Cec_IncrEmitMode_t Mode ); +extern Vec_Int_t * Cec_DynSrmOutLits( Cec_DynSrm_t * p ); +extern Vec_Int_t * Cec_DynSrmSolve( Cec_DynSrm_t * p, int nConfs, Vec_Str_t ** pvStatus ); +/*=== cecCorrIncrSim.c ============================================================*/ +extern Cec_SeedSim_t * Cec_SeedSimAlloc( Gia_Man_t * pAig, int nFrames, int iSeedFrame, int nWords ); +extern void Cec_SeedSimFree( Cec_SeedSim_t * p ); +extern int Cec_SeedSimTryBatch( Cec_SeedSim_t * p, Cec_ManSim_t * pSim, Vec_Ptr_t * vSimInfo, Vec_Int_t * vOutputs, Vec_Int_t * vOutBits, int nFrames ); +extern void Cec_SeedSimSaveFrameInputs( Cec_SeedSim_t * p, Vec_Ptr_t * vInfoCis, int Frame ); +extern void Cec_SeedSimSaveFrameOutputs( Cec_SeedSim_t * p, Vec_Ptr_t * vInfoCos, int Frame ); +extern void Cec_SeedSimFinishFull( Cec_SeedSim_t * p ); +extern void Cec_SeedSimBeginCall( Cec_SeedSim_t * p ); +extern void Cec_SeedSimBypassBatch( Cec_SeedSim_t * p, int nCex ); +extern void Cec_SeedSimEnsurePersistent( Cec_SeedSim_t * p, Cec_ManSim_t * pSim ); +extern void Cec_SeedSimBuildClassCone( Cec_SeedSim_t * p, Vec_Int_t * vOutputs ); +extern int Cec_SeedSimLoadPersistentBatch( Cec_SeedSim_t * p, Vec_Int_t * vCexStore, int iStart, Vec_Int_t * vPairs, Vec_Int_t * vOutBits ); +extern void Cec_SeedSimRestorePersistentInputs( Cec_SeedSim_t * p ); /*=== cecClass.c ============================================================*/ extern int Cec_ManSimClassRemoveOne( Cec_ManSim_t * p, int i ); +extern void Cec_ManSimClassCreate( Gia_Man_t * p, Vec_Int_t * vClass ); +extern int Cec_ManSimCompareEqual( unsigned * p0, unsigned * p1, int nWords ); +extern int Cec_ManSimHashKey( unsigned * pSim, int nWords, int nTableSize ); extern int Cec_ManSimClassesPrepare( Cec_ManSim_t * p, int LevelMax ); extern int Cec_ManSimClassesRefine( Cec_ManSim_t * p ); extern int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos ); +extern int Cec_ManSimSimulateRoundSavePhase( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos, unsigned * pSave ); +extern int Cec_ManSimRefineMappedFrame( Cec_ManSim_t * p, unsigned * pValues, Vec_Int_t * vLits, int iBase, int nWords ); /*=== cecIso.c ============================================================*/ extern int * Cec_ManDetectIsomorphism( Gia_Man_t * p ); /*=== cecMan.c ============================================================*/ @@ -200,6 +433,7 @@ extern Vec_Ptr_t * Cec_ManPatCollectPatterns( Cec_ManPat_t * pMan, int extern Vec_Ptr_t * Cec_ManPatPackPatterns( Vec_Int_t * vCexStore, int nInputs, int nRegs, int nWordsInit ); /*=== cecSeq.c ============================================================*/ extern int Cec_ManSeqResimulate( Cec_ManSim_t * p, Vec_Ptr_t * vInfo ); +extern int Cec_ManSeqResimulateSeed( Cec_ManSim_t * p, Vec_Ptr_t * vInfo, Cec_SeedSim_t * pSeed ); extern int Cec_ManSeqResimulateInfo( Gia_Man_t * pAig, Vec_Ptr_t * vSimInfo, Abc_Cex_t * pBestState, int fCheckMiter ); extern void Cec_ManSeqDeriveInfoInitRandom( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex ); extern int Cec_ManCountNonConstOutputs( Gia_Man_t * pAig ); @@ -210,6 +444,7 @@ extern void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pA extern void Cec_ManSatSolveCSat( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars ); extern Vec_Str_t * Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats ); extern Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus ); +extern Vec_Int_t * Cec_ManSatSolveMiterOutVals( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus, Vec_Int_t * vOutLits, Vec_Int_t ** pvOutVals ); extern int Cec_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * pObj ); extern int Cec_ManSatCheckNodeTwo( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ); extern void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ); diff --git a/src/proof/cec/cecProve.c b/src/proof/cec/cecProve.c index cf8dfa7ed2..94eafa479e 100644 --- a/src/proof/cec/cecProve.c +++ b/src/proof/cec/cecProve.c @@ -19,6 +19,9 @@ ***********************************************************************/ #include +#include +#include +#include #include "aig/gia/gia.h" #include "aig/gia/giaAig.h" @@ -52,14 +55,25 @@ extern int Bmcg_ManPerform( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ); typedef struct Par_Share_t_ Par_Share_t; typedef struct Par_ThData_t_ Par_ThData_t; +typedef struct Wlc_Ntk_t_ Wlc_Ntk_t; +struct Cec_ScorrStop_t_; +struct Cec_SproveTrace_t_; static int Cec_SProveCallback( void * pUser, int fSolved, unsigned Result ); +static Gia_Man_t * Cec_GiaScorrOld( Gia_Man_t * p, int nTimeOut, Par_Share_t * pShare, struct Cec_ScorrStop_t_ * pStopOut ); +static Gia_Man_t * Cec_GiaScorrNew( Gia_Man_t * p, int nTimeOut, Par_Share_t * pShare, struct Cec_ScorrStop_t_ * pStopOut ); +#ifdef ABC_USE_PTHREADS +static void Cec_GiaInitThreads( Par_ThData_t * ThData, int nWorkers, Gia_Man_t * p, int nTimeOut, int nTimeOutU, Wlc_Ntk_t * pWlc, const char * pUfarArgs, int fVerbose, pthread_t * WorkerThread, Par_Share_t * pShare, int * pEngines, int StageId, int NetId, struct Cec_SproveTrace_t_ * pTrace ); +static void Cec_GiaStopThreads( Par_ThData_t * ThData, pthread_t * WorkerThread, int nWorkers ); +#endif +static int Cec_GiaWaitThreads( Par_ThData_t * ThData, int nWorkers, Gia_Man_t * p, int RetValue, int * pRetEngine ); -typedef struct Wlc_Ntk_t_ Wlc_Ntk_t; -extern int Ufar_ProveWithTimeout( Wlc_Ntk_t * pNtk, int nTimeOut, int fVerbose, int (*pFuncStop)(int), int RunId ); +extern int Ufar_ProveWithTimeout( Wlc_Ntk_t * pNtk, int nTimeOut, int fVerbose, int (*pFuncStop)(int), int RunId, const char * pArgs ); #ifndef ABC_USE_PTHREADS -int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fUseUif, Wlc_Ntk_t * pWlc, int fVerbose, int fVeryVerbose, int fSilent ) { return -1; } +int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fUseUif, Wlc_Ntk_t * pWlc, int fVerbose, int fVeryVerbose, int fSilent, char * pReplayFile, char * pUfarArgs ) { return -1; } +int Cec_GiaReplayReadParams( char * pFileName, int * pnProcs, int * pnTimeOut, int * pnTimeOut2, int * pnTimeOut3, int * pfUseUif ) { return 0; } +int Cec_GiaReplayTest( Gia_Man_t * p, Wlc_Ntk_t * pWlc, char * pFileName, int fVerbose, int fVeryVerbose, int fSilent ) { return -1; } #else // pthreads are used @@ -68,6 +82,13 @@ int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, in #define PAR_ENGINE_SCORR1 7 #define PAR_ENGINE_SCORR2 8 #define PAR_ENGINE_GLA 9 +#define SPROVE_STAGE_MAX 4 +#define SPROVE_NET_ORIG 0 +#define SPROVE_NET_SCNEW 1 +#define SPROVE_NET_SCOLD 2 +typedef struct Cec_SproveTrace_t_ Cec_SproveTrace_t; +typedef struct Cec_SproveStage_t_ Cec_SproveStage_t; +typedef struct Cec_SprovePlan_t_ Cec_SprovePlan_t; struct Par_Share_t_ { volatile int fSolved; @@ -85,7 +106,13 @@ typedef struct Par_ThData_t_ int fVerbose; int nTimeOutU; Wlc_Ntk_t * pWlc; + const char * pUfarArgs; + int WorkerId; + int StageId; + int NetId; + int StopReason; Par_Share_t * pShare; + Cec_SproveTrace_t * pTrace; pthread_mutex_t Mutex; pthread_cond_t Cond; } Par_ThData_t; @@ -93,7 +120,47 @@ typedef struct Cec_ScorrStop_t_ { Par_Share_t * pShare; abctime TimeToStop; + int fStoppedByCallback; + int fStoppedByTimeout; } Cec_ScorrStop_t; +struct Cec_SproveTrace_t_ +{ + FILE * pFile; + int fActive; + abctime clkStart; + pthread_mutex_t Mutex; +}; +struct Cec_SproveStage_t_ +{ + int Id; + int fGuardUnsolved; + int GuardExistsNet; + int GuardAndLimitNet; + int GuardAndLimit; + int fHasRound; + int RoundNet; + int RoundTimeout; + int nRoundEngines; + int RoundEngines[PAR_THR_MAX]; + int fHasReduce; + int ReduceType; + int ReduceNetIn; + int ReduceNetOut; + int ReduceTimeout; +}; +struct Cec_SprovePlan_t_ +{ + int nProcs; + int nTimeOut; + int nTimeOut2; + int nTimeOut3; + int fUseUif; + int fPersistentUif; + int nTimeOutUif; + char * pUfarArgs; + int nStages; + Cec_SproveStage_t Stages[SPROVE_STAGE_MAX]; +}; static volatile Par_Share_t * g_pUfarShare = NULL; static volatile Par_Share_t * g_pGlaShare = NULL; static inline const char * Cec_SolveEngineName( int iEngine ) @@ -146,9 +213,15 @@ static int Cec_ScorrStop( void * pUser ) if ( p == NULL ) return 0; if ( p->pShare && p->pShare->fSolved ) + { + p->fStoppedByCallback = 1; return 1; + } if ( p->TimeToStop && Abc_Clock() >= p->TimeToStop ) + { + p->fStoppedByTimeout = 1; return 1; + } return 0; } static int Cec_SProveCallback( void * pUser, int fSolved, unsigned Result ) @@ -170,6 +243,653 @@ static int Cec_SProveCallback( void * pUser, int fSolved, unsigned Result ) return pShare->fSolved != 0; } +static inline const char * Cec_SproveNetName( int NetId ) +{ + if ( NetId == SPROVE_NET_ORIG ) + return "orig"; + if ( NetId == SPROVE_NET_SCNEW ) + return "scnew"; + if ( NetId == SPROVE_NET_SCOLD ) + return "scold"; + return "unknown"; +} +static inline int Cec_SproveNetId( const char * pName ) +{ + if ( !strcmp(pName, "orig") ) + return SPROVE_NET_ORIG; + if ( !strcmp(pName, "scnew") ) + return SPROVE_NET_SCNEW; + if ( !strcmp(pName, "scold") ) + return SPROVE_NET_SCOLD; + return -1; +} +static inline const char * Cec_SproveStopName( int StopReason ) +{ + if ( StopReason == 1 ) + return "self"; + if ( StopReason == 2 ) + return "callback"; + if ( StopReason == 3 ) + return "timeout"; + if ( StopReason == 4 ) + return "skip"; + return "unknown"; +} +static inline const char * Cec_SproveResultName( int RetValue ) +{ + if ( RetValue == 0 ) + return "sat"; + if ( RetValue == 1 ) + return "unsat"; + return "undecided"; +} +static inline unsigned long long Cec_SproveClockToMs( abctime Time ) +{ + return (unsigned long long)(1000.0 * (double)Time / (double)CLOCKS_PER_SEC); +} +static int Cec_SproveFindValue( char * pLine, const char * pKey, char * pValue, int nValueSize ) +{ + char * pBeg = strstr( pLine, pKey ); + int i = 0; + if ( pBeg == NULL ) + return 0; + pBeg += strlen(pKey); + while ( *pBeg && *pBeg != ' ' && *pBeg != '\t' && *pBeg != '\r' && *pBeg != '\n' ) + { + if ( i < nValueSize - 1 ) + pValue[i++] = *pBeg; + pBeg++; + } + pValue[i] = 0; + return i > 0; +} +static int Cec_SproveParseEngineName( const char * pName ) +{ + int i; + for ( i = 0; i <= PAR_ENGINE_GLA; i++ ) + if ( !strcmp(pName, Cec_SolveEngineName(i)) ) + return i; + return -1; +} +static int Cec_SprovePlanTimeoutTotal( Cec_SprovePlan_t * pPlan ) +{ + int i, Total = 0; + for ( i = 0; i < pPlan->nStages; i++ ) + { + Cec_SproveStage_t * pStage = &pPlan->Stages[i]; + int RoundTime = pStage->fHasRound ? pStage->RoundTimeout : 0; + int ReduceTime = pStage->fHasReduce ? pStage->ReduceTimeout : 0; + Total += Abc_MaxInt( RoundTime, ReduceTime ); + } + return Total; +} +static void Cec_SproveDeriveEngineList( int nProcs, int fUseUif, int fPersistentUif, int * pEngines, int * pnEngines ) +{ + int i, nEngines = nProcs + ((fUseUif && !fPersistentUif) ? 1 : 0); + assert( nEngines >= 1 && nEngines <= PAR_THR_MAX ); + if ( fUseUif && nProcs == 6 ) + { + if ( fPersistentUif ) + { + int UifEngines[6] = { 0, 1, 2, 3, 4, PAR_ENGINE_GLA }; + memcpy( pEngines, UifEngines, sizeof(UifEngines) ); + *pnEngines = 6; + } + else + { + int UifEngines[7] = { 0, 1, 2, 3, 4, PAR_ENGINE_GLA, PAR_ENGINE_UFAR }; + memcpy( pEngines, UifEngines, sizeof(UifEngines) ); + *pnEngines = 7; + } + return; + } + for ( i = 0; i < nEngines; i++ ) + { + if ( fUseUif && !fPersistentUif && i == nEngines - 1 ) + pEngines[i] = PAR_ENGINE_UFAR; + else if ( !fUseUif && nEngines == 6 && i == 5 ) + pEngines[i] = PAR_ENGINE_GLA; + else + pEngines[i] = i; + } + *pnEngines = nEngines; +} +static void Cec_SproveTrimLineEnd( char * pLine ) +{ + int nSize = strlen( pLine ); + while ( nSize > 0 && (pLine[nSize - 1] == '\n' || pLine[nSize - 1] == '\r') ) + pLine[--nSize] = 0; +} +static void Cec_SprovePlanSetUfarArgs( Cec_SprovePlan_t * pPlan, const char * pUfarArgs ) +{ + ABC_FREE( pPlan->pUfarArgs ); + pPlan->pUfarArgs = NULL; + if ( pUfarArgs && pUfarArgs[0] ) + pPlan->pUfarArgs = Abc_UtilStrsav( (char *)pUfarArgs ); +} +static void Cec_SprovePlanFree( Cec_SprovePlan_t * pPlan ) +{ + ABC_FREE( pPlan->pUfarArgs ); + pPlan->pUfarArgs = NULL; +} +static void Cec_SprovePlanDefault( Cec_SprovePlan_t * pPlan, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fUseUif, const char * pUfarArgs ) +{ + int nEngines; + memset( pPlan, 0, sizeof(Cec_SprovePlan_t) ); + { + int i; + for ( i = 0; i < SPROVE_STAGE_MAX; i++ ) + pPlan->Stages[i].GuardExistsNet = pPlan->Stages[i].GuardAndLimitNet = -1; + } + pPlan->nProcs = nProcs; + pPlan->nTimeOut = nTimeOut; + pPlan->nTimeOut2 = nTimeOut2; + pPlan->nTimeOut3 = nTimeOut3; + pPlan->fUseUif = fUseUif; + pPlan->fPersistentUif = fUseUif ? 1 : 0; + Cec_SprovePlanSetUfarArgs( pPlan, pUfarArgs ); + pPlan->nStages = 4; + Cec_SproveDeriveEngineList( nProcs, fUseUif, pPlan->fPersistentUif, pPlan->Stages[0].RoundEngines, &nEngines ); + + pPlan->Stages[0].Id = 1; + pPlan->Stages[0].fHasRound = 1; + pPlan->Stages[0].RoundNet = SPROVE_NET_ORIG; + pPlan->Stages[0].RoundTimeout = nTimeOut; + pPlan->Stages[0].nRoundEngines = nEngines; + pPlan->Stages[0].fHasReduce = 1; + pPlan->Stages[0].ReduceType = PAR_ENGINE_SCORR1; + pPlan->Stages[0].ReduceNetIn = SPROVE_NET_ORIG; + pPlan->Stages[0].ReduceNetOut = SPROVE_NET_SCNEW; + pPlan->Stages[0].ReduceTimeout = nTimeOut; + + pPlan->Stages[1].Id = 2; + pPlan->Stages[1].fGuardUnsolved = 1; + pPlan->Stages[1].fHasRound = 1; + pPlan->Stages[1].RoundNet = SPROVE_NET_SCNEW; + pPlan->Stages[1].RoundTimeout = nTimeOut2; + pPlan->Stages[1].nRoundEngines = nEngines; + memcpy( pPlan->Stages[1].RoundEngines, pPlan->Stages[0].RoundEngines, sizeof(int) * nEngines ); + + pPlan->Stages[2].Id = 3; + pPlan->Stages[2].fGuardUnsolved = 1; + pPlan->Stages[2].GuardAndLimitNet = SPROVE_NET_SCNEW; + pPlan->Stages[2].GuardAndLimit = 100000; + pPlan->Stages[2].fHasReduce = 1; + pPlan->Stages[2].ReduceType = PAR_ENGINE_SCORR2; + pPlan->Stages[2].ReduceNetIn = SPROVE_NET_SCNEW; + pPlan->Stages[2].ReduceNetOut = SPROVE_NET_SCOLD; + pPlan->Stages[2].ReduceTimeout = nTimeOut3; + + pPlan->Stages[3].Id = 4; + pPlan->Stages[3].fGuardUnsolved = 1; + pPlan->Stages[3].GuardExistsNet = SPROVE_NET_SCOLD; + pPlan->Stages[3].fHasRound = 1; + pPlan->Stages[3].RoundNet = SPROVE_NET_SCOLD; + pPlan->Stages[3].RoundTimeout = nTimeOut3; + pPlan->Stages[3].nRoundEngines = nEngines; + memcpy( pPlan->Stages[3].RoundEngines, pPlan->Stages[0].RoundEngines, sizeof(int) * nEngines ); + pPlan->nTimeOutUif = pPlan->fPersistentUif ? Cec_SprovePlanTimeoutTotal( pPlan ) : 0; +} +static void Cec_SproveTraceWrite( Cec_SproveTrace_t * pTrace, const char * pFormat, ... ) +{ + va_list args; + if ( pTrace == NULL || !pTrace->fActive || pTrace->pFile == NULL ) + return; + pthread_mutex_lock( &pTrace->Mutex ); + va_start( args, pFormat ); + vfprintf( pTrace->pFile, pFormat, args ); + va_end( args ); + fputc( '\n', pTrace->pFile ); + fflush( pTrace->pFile ); + pthread_mutex_unlock( &pTrace->Mutex ); +} +static abctime Cec_SproveTraceTime( Cec_SproveTrace_t * pTrace ) +{ + return pTrace ? Abc_Clock() - pTrace->clkStart : 0; +} +static void Cec_SproveTraceOpen( Cec_SproveTrace_t * pTrace, Gia_Man_t * p, Cec_SprovePlan_t * pPlan, char * pReplayFile ) +{ + int i, k; + char * pProbName = p->pSpec ? p->pSpec : Gia_ManName(p); + memset( pTrace, 0, sizeof(Cec_SproveTrace_t) ); + if ( pReplayFile == NULL ) + return; + pTrace->pFile = fopen( pReplayFile, "wb" ); + if ( pTrace->pFile == NULL ) + return; + pTrace->fActive = 1; + pTrace->clkStart = Abc_Clock(); + pthread_mutex_init( &pTrace->Mutex, NULL ); + Cec_SproveTraceWrite( pTrace, "SPROVE_REPLAY 1" ); + Cec_SproveTraceWrite( pTrace, "CASE %s", pProbName ? pProbName : "(none)" ); + Cec_SproveTraceWrite( pTrace, "PARAMS P=%d T=%d U=%d W=%d UIF=%d", pPlan->nProcs, pPlan->nTimeOut, pPlan->nTimeOut2, pPlan->nTimeOut3, pPlan->fUseUif ); + if ( pPlan->fUseUif ) + Cec_SproveTraceWrite( pTrace, "UFAR mode=%s timeout=%d", pPlan->fPersistentUif ? "persistent" : "round", pPlan->nTimeOutUif ); + if ( pPlan->pUfarArgs && pPlan->pUfarArgs[0] ) + Cec_SproveTraceWrite( pTrace, "UFAR_ARGS %s", pPlan->pUfarArgs ); + Cec_SproveTraceWrite( pTrace, "" ); + Cec_SproveTraceWrite( pTrace, "PLAN_BEGIN" ); + for ( i = 0; i < pPlan->nStages; i++ ) + { + Cec_SproveStage_t * pStage = &pPlan->Stages[i]; + char Buffer[256]; + Buffer[0] = 0; + if ( pStage->fGuardUnsolved ) + strcat( Buffer, "unsolved" ); + if ( pStage->GuardExistsNet >= 0 ) + sprintf( Buffer + strlen(Buffer), "%sexists(%s)", Buffer[0] ? "," : "", Cec_SproveNetName(pStage->GuardExistsNet) ); + if ( pStage->GuardAndLimitNet >= 0 ) + sprintf( Buffer + strlen(Buffer), "%sand_lt(%s,%d)", Buffer[0] ? "," : "", Cec_SproveNetName(pStage->GuardAndLimitNet), pStage->GuardAndLimit ); + if ( !Buffer[0] ) + strcpy( Buffer, "none" ); + if ( pStage->fHasRound ) + { + char EngBuf[128]; + EngBuf[0] = 0; + for ( k = 0; k < pStage->nRoundEngines; k++ ) + { + if ( k > 0 ) + strcat( EngBuf, "," ); + strcat( EngBuf, Cec_SolveEngineName(pStage->RoundEngines[k]) ); + } + Cec_SproveTraceWrite( pTrace, "ROUND stage=%d guard=%s net=%s timeout=%d engines=%s", pStage->Id, Buffer, Cec_SproveNetName(pStage->RoundNet), pStage->RoundTimeout, EngBuf ); + } + if ( pStage->fHasReduce ) + Cec_SproveTraceWrite( pTrace, "REDUCE stage=%d guard=%s name=%s in=%s out=%s timeout=%d stop=callback_or_timeout", pStage->Id, Buffer, Cec_SolveEngineName(pStage->ReduceType), Cec_SproveNetName(pStage->ReduceNetIn), Cec_SproveNetName(pStage->ReduceNetOut), pStage->ReduceTimeout ); + } + Cec_SproveTraceWrite( pTrace, "PLAN_END" ); + Cec_SproveTraceWrite( pTrace, "" ); + Cec_SproveTraceWrite( pTrace, "OBSERVED_BEGIN" ); + Cec_SproveTraceWrite( pTrace, "CHECKPOINT net=orig regs=%d ands=%d pos=%d", Gia_ManRegNum(p), Gia_ManAndNum(p), Gia_ManPoNum(p) ); +} +static void Cec_SproveTraceClose( Cec_SproveTrace_t * pTrace ) +{ + if ( pTrace == NULL || !pTrace->fActive ) + return; + Cec_SproveTraceWrite( pTrace, "OBSERVED_END" ); + pthread_mutex_destroy( &pTrace->Mutex ); + fclose( pTrace->pFile ); + pTrace->pFile = NULL; + pTrace->fActive = 0; +} +static int Cec_SproveReplayReadParamsInt( char * pFileName, Cec_SprovePlan_t * pPlan ) +{ + char Buffer[1024], Value[256]; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + return 0; + memset( pPlan, 0, sizeof(Cec_SprovePlan_t) ); + { + int i; + for ( i = 0; i < SPROVE_STAGE_MAX; i++ ) + pPlan->Stages[i].GuardExistsNet = pPlan->Stages[i].GuardAndLimitNet = -1; + } + while ( fgets( Buffer, sizeof(Buffer), pFile ) != NULL ) + { + if ( strncmp(Buffer, "PARAMS ", 7) == 0 ) + { + if ( !Cec_SproveFindValue(Buffer, "P=", Value, sizeof(Value)) ) break; + pPlan->nProcs = atoi(Value); + if ( !Cec_SproveFindValue(Buffer, "T=", Value, sizeof(Value)) ) break; + pPlan->nTimeOut = atoi(Value); + if ( !Cec_SproveFindValue(Buffer, "U=", Value, sizeof(Value)) ) break; + pPlan->nTimeOut2 = atoi(Value); + if ( !Cec_SproveFindValue(Buffer, "W=", Value, sizeof(Value)) ) break; + pPlan->nTimeOut3 = atoi(Value); + if ( !Cec_SproveFindValue(Buffer, "UIF=", Value, sizeof(Value)) ) break; + pPlan->fUseUif = atoi(Value); + } + else if ( strncmp(Buffer, "UFAR_ARGS ", 10) == 0 ) + { + Cec_SproveTrimLineEnd( Buffer ); + Cec_SprovePlanSetUfarArgs( pPlan, Buffer + 10 ); + } + else if ( strncmp(Buffer, "UFAR ", 5) == 0 ) + { + if ( Cec_SproveFindValue(Buffer, "mode=", Value, sizeof(Value)) ) + pPlan->fPersistentUif = !strcmp(Value, "persistent"); + if ( Cec_SproveFindValue(Buffer, "timeout=", Value, sizeof(Value)) ) + pPlan->nTimeOutUif = atoi(Value); + } + else if ( pPlan->nProcs > 0 && (strncmp(Buffer, "PLAN_BEGIN", 10) == 0 || strncmp(Buffer, "OBSERVED_BEGIN", 14) == 0) ) + { + if ( pPlan->fUseUif && pPlan->nTimeOutUif == 0 ) + pPlan->nTimeOutUif = pPlan->fPersistentUif ? (pPlan->nTimeOut + pPlan->nTimeOut2 + 2 * pPlan->nTimeOut3) : 0; + fclose( pFile ); + return 1; + } + } + fclose( pFile ); + return pPlan->nProcs > 0; +} +static int Cec_SproveReplayReadPlan( char * pFileName, Cec_SprovePlan_t * pPlan ) +{ + char Buffer[1024], Value[256], Guard[256], Engines[256]; + FILE * pFile; + int fInPlan = 0; + if ( !Cec_SproveReplayReadParamsInt( pFileName, pPlan ) ) + return 0; + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + return 0; + while ( fgets( Buffer, sizeof(Buffer), pFile ) != NULL ) + { + Cec_SproveStage_t * pStage; + int StageId; + if ( strncmp(Buffer, "PLAN_BEGIN", 10) == 0 ) + { + fInPlan = 1; + continue; + } + if ( strncmp(Buffer, "PLAN_END", 8) == 0 || strncmp(Buffer, "OBSERVED_BEGIN", 14) == 0 ) + break; + if ( !fInPlan ) + continue; + if ( strncmp(Buffer, "ROUND ", 6) == 0 ) + { + char * pTok; + int nEngines = 0; + if ( !Cec_SproveFindValue(Buffer, "stage=", Value, sizeof(Value)) ) + continue; + StageId = atoi(Value); + if ( StageId < 1 || StageId > SPROVE_STAGE_MAX ) + continue; + pStage = &pPlan->Stages[StageId - 1]; + if ( StageId > pPlan->nStages ) + pPlan->nStages = StageId; + memset( Guard, 0, sizeof(Guard) ); + Cec_SproveFindValue(Buffer, "guard=", Guard, sizeof(Guard)); + pStage->Id = StageId; + pStage->fGuardUnsolved = strstr( Guard, "unsolved" ) != NULL; + if ( strstr(Guard, "exists(") ) + { + sscanf( strstr(Guard, "exists("), "exists(%255[^)])", Value ); + pStage->GuardExistsNet = Cec_SproveNetId( Value ); + } + if ( strstr(Guard, "and_lt(") ) + { + sscanf( strstr(Guard, "and_lt("), "and_lt(%255[^,],%d)", Value, &pStage->GuardAndLimit ); + pStage->GuardAndLimitNet = Cec_SproveNetId( Value ); + } + if ( Cec_SproveFindValue(Buffer, "net=", Value, sizeof(Value)) ) + pStage->RoundNet = Cec_SproveNetId( Value ); + if ( Cec_SproveFindValue(Buffer, "timeout=", Value, sizeof(Value)) ) + pStage->RoundTimeout = atoi(Value); + if ( Cec_SproveFindValue(Buffer, "engines=", Engines, sizeof(Engines)) ) + { + pTok = strtok( Engines, "," ); + while ( pTok && nEngines < PAR_THR_MAX ) + { + pStage->RoundEngines[nEngines++] = Cec_SproveParseEngineName( pTok ); + pTok = strtok( NULL, "," ); + } + } + pStage->fHasRound = 1; + pStage->nRoundEngines = nEngines; + } + else if ( strncmp(Buffer, "REDUCE ", 7) == 0 ) + { + if ( !Cec_SproveFindValue(Buffer, "stage=", Value, sizeof(Value)) ) + continue; + StageId = atoi(Value); + if ( StageId < 1 || StageId > SPROVE_STAGE_MAX ) + continue; + pStage = &pPlan->Stages[StageId - 1]; + if ( StageId > pPlan->nStages ) + pPlan->nStages = StageId; + memset( Guard, 0, sizeof(Guard) ); + Cec_SproveFindValue(Buffer, "guard=", Guard, sizeof(Guard)); + pStage->Id = StageId; + pStage->fGuardUnsolved = strstr( Guard, "unsolved" ) != NULL; + if ( strstr(Guard, "exists(") ) + { + sscanf( strstr(Guard, "exists("), "exists(%255[^)])", Value ); + pStage->GuardExistsNet = Cec_SproveNetId( Value ); + } + if ( strstr(Guard, "and_lt(") ) + { + sscanf( strstr(Guard, "and_lt("), "and_lt(%255[^,],%d)", Value, &pStage->GuardAndLimit ); + pStage->GuardAndLimitNet = Cec_SproveNetId( Value ); + } + if ( Cec_SproveFindValue(Buffer, "name=", Value, sizeof(Value)) ) + pStage->ReduceType = Cec_SproveParseEngineName( Value ); + if ( Cec_SproveFindValue(Buffer, "in=", Value, sizeof(Value)) ) + pStage->ReduceNetIn = Cec_SproveNetId( Value ); + if ( Cec_SproveFindValue(Buffer, "out=", Value, sizeof(Value)) ) + pStage->ReduceNetOut = Cec_SproveNetId( Value ); + if ( Cec_SproveFindValue(Buffer, "timeout=", Value, sizeof(Value)) ) + pStage->ReduceTimeout = atoi(Value); + pStage->fHasReduce = 1; + } + } + fclose( pFile ); + return pPlan->nStages > 0; +} +static Gia_Man_t * Cec_SproveGetNet( int NetId, Gia_Man_t * pOrig, Gia_Man_t * pScorr, Gia_Man_t * pScorr2 ) +{ + if ( NetId == SPROVE_NET_ORIG ) + return pOrig; + if ( NetId == SPROVE_NET_SCNEW ) + return pScorr; + if ( NetId == SPROVE_NET_SCOLD ) + return pScorr2; + return NULL; +} +static void Cec_SproveSetNet( int NetId, Gia_Man_t ** ppScorr, Gia_Man_t ** ppScorr2, Gia_Man_t * pNet ) +{ + if ( NetId == SPROVE_NET_SCNEW ) + { + Gia_ManStopP( ppScorr ); + *ppScorr = pNet; + } + else if ( NetId == SPROVE_NET_SCOLD ) + { + Gia_ManStopP( ppScorr2 ); + *ppScorr2 = pNet; + } + else + Gia_ManStop( pNet ); +} +static int Cec_SproveCheckGuard( Cec_SproveStage_t * pStage, int RetValue, Gia_Man_t * pOrig, Gia_Man_t * pScorr, Gia_Man_t * pScorr2 ) +{ + Gia_Man_t * pNet; + if ( pStage->fGuardUnsolved && RetValue != -1 ) + return 0; + if ( pStage->GuardExistsNet >= 0 && Cec_SproveGetNet( pStage->GuardExistsNet, pOrig, pScorr, pScorr2 ) == NULL ) + return 0; + if ( pStage->GuardAndLimitNet >= 0 ) + { + pNet = Cec_SproveGetNet( pStage->GuardAndLimitNet, pOrig, pScorr, pScorr2 ); + if ( pNet == NULL || Gia_ManAndNum(pNet) >= pStage->GuardAndLimit ) + return 0; + } + return 1; +} +static void Cec_SproveTraceCheckpoint( Cec_SproveTrace_t * pTrace, int NetId, Gia_Man_t * pNet ) +{ + if ( pTrace == NULL || !pTrace->fActive || pNet == NULL ) + return; + Cec_SproveTraceWrite( pTrace, "CHECKPOINT net=%s regs=%d ands=%d pos=%d", Cec_SproveNetName(NetId), Gia_ManRegNum(pNet), Gia_ManAndNum(pNet), Gia_ManPoNum(pNet) ); +} +static Gia_Man_t * Cec_SproveRunReduce( Gia_Man_t * pInput, Cec_SproveStage_t * pStage, Par_Share_t * pShare, Cec_SproveTrace_t * pTrace, abctime * pClkUsed, int * pRetValue, int * pRetEngine ) +{ + Cec_ScorrStop_t Stop; + abctime clk = Abc_Clock(); + Gia_Man_t * pOutput = NULL; + int StopReason = 1; + memset( &Stop, 0, sizeof(Stop) ); + if ( pTrace && pTrace->fActive ) + Cec_SproveTraceWrite( pTrace, "START kind=reduce stage=%d name=%s in=%s out=%s timeout=%d t=%llu", + pStage->Id, Cec_SolveEngineName(pStage->ReduceType), Cec_SproveNetName(pStage->ReduceNetIn), Cec_SproveNetName(pStage->ReduceNetOut), pStage->ReduceTimeout, + Cec_SproveClockToMs( Cec_SproveTraceTime(pTrace) ) ); + if ( pStage->ReduceType == PAR_ENGINE_SCORR1 ) + pOutput = Cec_GiaScorrNew( pInput, pStage->ReduceTimeout, pShare, &Stop ); + else if ( pStage->ReduceType == PAR_ENGINE_SCORR2 ) + pOutput = Cec_GiaScorrOld( pInput, pStage->ReduceTimeout, pShare, &Stop ); + else + assert( 0 ); + if ( Gia_ManAndNum(pOutput) == 0 ) + { + pShare->fSolved = 1; + pShare->Result = 1; + pShare->iEngine = pStage->ReduceType; + *pRetValue = 1; + *pRetEngine = pStage->ReduceType; + } + if ( Stop.fStoppedByCallback ) + StopReason = 2; + else if ( Stop.fStoppedByTimeout ) + StopReason = 3; + if ( pClkUsed ) + *pClkUsed = Abc_Clock() - clk; + if ( pTrace && pTrace->fActive ) + { + Cec_SproveTraceWrite( pTrace, "STOP kind=reduce stage=%d name=%s in=%s out=%s result=%s stop=%s t=%llu elapsed=%llu", + pStage->Id, Cec_SolveEngineName(pStage->ReduceType), Cec_SproveNetName(pStage->ReduceNetIn), Cec_SproveNetName(pStage->ReduceNetOut), + *pRetEngine == pStage->ReduceType ? Cec_SproveResultName(*pRetValue) : "undecided", + Cec_SproveStopName(StopReason), Cec_SproveClockToMs( Cec_SproveTraceTime(pTrace) ), Cec_SproveClockToMs( Abc_Clock() - clk ) ); + Cec_SproveTraceCheckpoint( pTrace, pStage->ReduceNetOut, pOutput ); + } + return pOutput; +} +static void Cec_SproveTakeSharedResult( Par_Share_t * pShare, int * pRetValue, int * pRetEngine ) +{ + if ( pShare == NULL || pRetValue == NULL || pRetEngine == NULL ) + return; + if ( *pRetValue == -1 && pShare->fSolved ) + { + *pRetValue = (int)pShare->Result; + *pRetEngine = pShare->iEngine; + } +} +static int Cec_SproveExecutePlan( Gia_Man_t * p, Cec_SprovePlan_t * pPlan, Wlc_Ntk_t * pWlc, int fVerbose, int fVeryVerbose, int fSilent, char * pReplayFile ) +{ + abctime clkTotal = Abc_Clock(), clkStage = 0; + Par_ThData_t ThData[PAR_THR_MAX]; + pthread_t WorkerThread[PAR_THR_MAX]; + Par_ThData_t UifData[1]; + pthread_t UifThread[1]; + Par_Share_t Share; + Cec_SproveTrace_t Trace; + Gia_Man_t * pScorr = NULL, * pScorr2 = NULL; + int UifEngines[1] = { PAR_ENGINE_UFAR }; + int i, RetValue = -1, RetEngine = -1, fThreadsStarted = 0, fUifStarted = 0; + (void)fVeryVerbose; + memset( &Share, 0, sizeof(Par_Share_t) ); + memset( &Trace, 0, sizeof(Cec_SproveTrace_t) ); + memset( ThData, 0, sizeof(ThData) ); + memset( WorkerThread, 0, sizeof(WorkerThread) ); + memset( UifData, 0, sizeof(UifData) ); + memset( UifThread, 0, sizeof(UifThread) ); + 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", pPlan->nProcs, pPlan->nTimeOut, fVerbose ); + fflush( stdout ); + Cec_SproveTraceOpen( &Trace, p, pPlan, pReplayFile ); + if ( pPlan->fUseUif && pPlan->fPersistentUif && pWlc != NULL ) + { + Cec_SproveTraceWrite( &Trace, "START kind=ufar mode=persistent timeout=%d t=%llu", + pPlan->nTimeOutUif, Cec_SproveClockToMs( Cec_SproveTraceTime(&Trace) ) ); + Cec_GiaInitThreads( UifData, 1, p, pPlan->nTimeOutUif, pPlan->nTimeOutUif, pWlc, pPlan->pUfarArgs, fVerbose, + UifThread, &Share, UifEngines, 0, SPROVE_NET_ORIG, &Trace ); + fUifStarted = 1; + } + for ( i = 0; i < pPlan->nStages; i++ ) + { + Cec_SproveStage_t * pStage = &pPlan->Stages[i]; + Gia_Man_t * pRoundNet = NULL, * pReduceNet = NULL, * pReduceOut = NULL; + Cec_SproveTakeSharedResult( &Share, &RetValue, &RetEngine ); + if ( !Cec_SproveCheckGuard( pStage, RetValue, p, pScorr, pScorr2 ) ) + { + Cec_SproveTraceWrite( &Trace, "SKIP stage=%d reason=guard", pStage->Id ); + continue; + } + if ( pStage->fHasRound ) + { + pRoundNet = Cec_SproveGetNet( pStage->RoundNet, p, pScorr, pScorr2 ); + if ( pRoundNet == NULL ) + { + Cec_SproveTraceWrite( &Trace, "SKIP stage=%d reason=missing_round_net", pStage->Id ); + continue; + } + Cec_SproveTraceWrite( &Trace, "START kind=round stage=%d net=%s timeout=%d t=%llu", + pStage->Id, Cec_SproveNetName(pStage->RoundNet), pStage->RoundTimeout, Cec_SproveClockToMs( Cec_SproveTraceTime(&Trace) ) ); + Cec_GiaInitThreads( ThData, pStage->nRoundEngines, pRoundNet, pStage->RoundTimeout, pStage->RoundTimeout, pWlc, pPlan->pUfarArgs, fVerbose, + fThreadsStarted ? NULL : WorkerThread, &Share, pStage->RoundEngines, pStage->Id, pStage->RoundNet, &Trace ); + fThreadsStarted = 1; + } + if ( pStage->fHasReduce ) + { + pReduceNet = Cec_SproveGetNet( pStage->ReduceNetIn, p, pScorr, pScorr2 ); + if ( pReduceNet == NULL ) + Cec_SproveTraceWrite( &Trace, "SKIP stage=%d reason=missing_reduce_net", pStage->Id ); + else + { + pReduceOut = Cec_SproveRunReduce( pReduceNet, pStage, &Share, &Trace, &clkStage, &RetValue, &RetEngine ); + Cec_SproveSetNet( pStage->ReduceNetOut, &pScorr, &pScorr2, pReduceOut ); + Cec_SproveTakeSharedResult( &Share, &RetValue, &RetEngine ); + } + } + if ( pStage->fHasRound ) + { + RetValue = Cec_GiaWaitThreads( ThData, pStage->nRoundEngines, p, RetValue, &RetEngine ); + Cec_SproveTakeSharedResult( &Share, &RetValue, &RetEngine ); + Cec_SproveTraceWrite( &Trace, "STOP kind=round stage=%d net=%s result=%s winner=%s t=%llu", + pStage->Id, Cec_SproveNetName(pStage->RoundNet), Cec_SproveResultName(RetValue), + RetEngine >= 0 ? Cec_SolveEngineName(RetEngine) : "none", Cec_SproveClockToMs( Cec_SproveTraceTime(&Trace) ) ); + } + if ( pStage->fHasReduce && RetValue == -1 && !fSilent && fVerbose ) + { + Gia_Man_t * pAfter = Cec_SproveGetNet( pStage->ReduceNetOut, p, pScorr, pScorr2 ); + if ( pAfter ) + { + printf( "Reduced the miter from %d to %d nodes. ", + Gia_ManAndNum(Cec_SproveGetNet(pStage->ReduceNetIn, p, pScorr, pScorr2)), Gia_ManAndNum(pAfter) ); + Abc_PrintTime( 1, "Time", clkStage ); + } + } + } + if ( fUifStarted ) + { + RetValue = Cec_GiaWaitThreads( UifData, 1, p, RetValue, &RetEngine ); + Cec_SproveTakeSharedResult( &Share, &RetValue, &RetEngine ); + Cec_SproveTraceWrite( &Trace, "STOP kind=ufar mode=persistent result=%s winner=%s t=%llu", + Cec_SproveResultName(RetValue), RetEngine == PAR_ENGINE_UFAR ? "ufar" : "other", + Cec_SproveClockToMs( Cec_SproveTraceTime(&Trace) ) ); + } + if ( fThreadsStarted ) + Cec_GiaStopThreads( ThData, WorkerThread, pPlan->Stages[0].nRoundEngines ); + if ( fUifStarted ) + Cec_GiaStopThreads( UifData, UifThread, 1 ); + Gia_ManStopP( &pScorr2 ); + Gia_ManStopP( &pScorr ); + if ( !fSilent ) + { + char * pProbName = p->pSpec ? p->pSpec : Gia_ManName(p); + if ( RetValue != -1 && RetEngine < 0 ) + RetEngine = PAR_ENGINE_SCORR1; + printf( "Problem \"%s\" is ", pProbName ? pProbName : "(none)" ); + if ( RetValue == 0 ) + printf( "SATISFIABLE (solved by %s).", Cec_SolveEngineName(RetEngine) ); + else if ( RetValue == 1 ) + printf( "UNSATISFIABLE (solved by %s).", Cec_SolveEngineName(RetEngine) ); + else if ( RetValue == -1 ) + printf( "UNDECIDED." ); + else assert( 0 ); + printf( " " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); + fflush( stdout ); + } + Cec_SproveTraceWrite( &Trace, "FINAL result=%s winner=%s total=%llu", + Cec_SproveResultName(RetValue), RetEngine >= 0 ? Cec_SolveEngineName(RetEngine) : "none", + Cec_SproveClockToMs( Abc_Clock() - clkTotal ) ); + Cec_SproveTraceClose( &Trace ); + return RetValue; +} + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -189,10 +909,18 @@ int Cec_GiaProveOne( Gia_Man_t * p, int iEngine, int nTimeOut, int fVerbose, Par { abctime clk = Abc_Clock(); int RetValue = -1; + if ( pThData && pThData->pTrace ) + Cec_SproveTraceWrite( pThData->pTrace, "START kind=engine stage=%d net=%s engine=%s worker=%d timeout=%d t=%llu", + pThData->StageId, Cec_SproveNetName(pThData->NetId), Cec_SolveEngineName(iEngine), pThData->WorkerId, nTimeOut, + Cec_SproveClockToMs( Cec_SproveTraceTime(pThData->pTrace) ) ); if ( iEngine != PAR_ENGINE_UFAR && iEngine != PAR_ENGINE_GLA && Gia_ManRegNum(p) == 0 ) { if ( fVerbose ) printf( "Engine %d (%-5s) skipped because the current miter is combinational.\n", iEngine, Cec_SolveEngineName(iEngine) ); + if ( pThData && pThData->pTrace ) + Cec_SproveTraceWrite( pThData->pTrace, "STOP kind=engine stage=%d net=%s engine=%s worker=%d result=undecided stop=skip t=%llu", + pThData->StageId, Cec_SproveNetName(pThData->NetId), Cec_SolveEngineName(iEngine), pThData->WorkerId, + Cec_SproveClockToMs( Cec_SproveTraceTime(pThData->pTrace) ) ); return -1; } //abctime clkStop = nTimeOut * CLOCKS_PER_SEC + Abc_Clock(); @@ -302,7 +1030,7 @@ int Cec_GiaProveOne( Gia_Man_t * p, int iEngine, int nTimeOut, int fVerbose, Par if ( pThData && pThData->pWlc ) { g_pUfarShare = pThData->pShare; - RetValue = Ufar_ProveWithTimeout( pThData->pWlc, pThData->nTimeOutU, fVerbose, Cec_SProveStopUfar, 0 ); + RetValue = Ufar_ProveWithTimeout( pThData->pWlc, pThData->nTimeOutU, fVerbose, Cec_SProveStopUfar, 0, pThData->pUfarArgs ); g_pUfarShare = NULL; } } @@ -326,19 +1054,39 @@ int Cec_GiaProveOne( Gia_Man_t * p, int iEngine, int nTimeOut, int fVerbose, Par //while ( Abc_Clock() < clkStop ); if ( pThData && pThData->pShare && RetValue != -1 ) Cec_SProveCallback( (void *)pThData, 1, (unsigned)RetValue ); + if ( pThData ) + { + if ( RetValue != -1 ) + pThData->StopReason = 1; + else if ( pThData->pShare && pThData->pShare->fSolved ) + pThData->StopReason = 2; + else + pThData->StopReason = 3; + } + if ( pThData && pThData->pTrace ) + Cec_SproveTraceWrite( pThData->pTrace, "STOP kind=engine stage=%d net=%s engine=%s worker=%d result=%s stop=%s t=%llu elapsed=%llu", + pThData->StageId, Cec_SproveNetName(pThData->NetId), Cec_SolveEngineName(iEngine), pThData->WorkerId, + Cec_SproveResultName(RetValue), Cec_SproveStopName(pThData->StopReason), + Cec_SproveClockToMs( Cec_SproveTraceTime(pThData->pTrace) ), + Cec_SproveClockToMs( Abc_Clock() - clk ) ); if ( fVerbose ) { printf( "Engine %d (%-5s) finished and %ssolved the problem. ", iEngine, Cec_SolveEngineName(iEngine), RetValue != -1 ? " " : "not " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } return RetValue; } -Gia_Man_t * Cec_GiaScorrOld( Gia_Man_t * p, int nTimeOut, Par_Share_t * pShare ) +Gia_Man_t * Cec_GiaScorrOld( Gia_Man_t * p, int nTimeOut, Par_Share_t * pShare, Cec_ScorrStop_t * pStopOut ) { Cec_ScorrStop_t Stop; + memset( &Stop, 0, sizeof(Stop) ); Stop.pShare = pShare; Stop.TimeToStop = nTimeOut > 0 ? (abctime)(Abc_Clock() + (abctime)nTimeOut * CLOCKS_PER_SEC) : 0; if ( Gia_ManRegNum(p) == 0 ) + { + if ( pStopOut ) + *pStopOut = Stop; return Gia_ManDup( p ); + } Ssw_Pars_t Pars, * pPars = &Pars; Ssw_ManSetDefaultParams( pPars ); pPars->pFunc = (void *)Cec_ScorrStop; @@ -348,15 +1096,22 @@ Gia_Man_t * Cec_GiaScorrOld( Gia_Man_t * p, int nTimeOut, Par_Share_t * pShare ) Gia_Man_t * pGia2 = Gia_ManFromAigSimple( pAig2 ); Aig_ManStop( pAig2 ); Aig_ManStop( pAig ); + if ( pStopOut ) + *pStopOut = Stop; return pGia2; } -Gia_Man_t * Cec_GiaScorrNew( Gia_Man_t * p, int nTimeOut, Par_Share_t * pShare ) +Gia_Man_t * Cec_GiaScorrNew( Gia_Man_t * p, int nTimeOut, Par_Share_t * pShare, Cec_ScorrStop_t * pStopOut ) { Cec_ScorrStop_t Stop; + memset( &Stop, 0, sizeof(Stop) ); Stop.pShare = pShare; Stop.TimeToStop = nTimeOut > 0 ? (abctime)(Abc_Clock() + (abctime)nTimeOut * CLOCKS_PER_SEC) : 0; if ( Gia_ManRegNum(p) == 0 ) + { + if ( pStopOut ) + *pStopOut = Stop; return Gia_ManDup( p ); + } Cec_ParCor_t Pars, * pPars = &Pars; Cec_ManCorSetDefaultParams( pPars ); pPars->nBTLimit = 100; @@ -365,7 +1120,10 @@ Gia_Man_t * Cec_GiaScorrNew( Gia_Man_t * p, int nTimeOut, Par_Share_t * pShare ) pPars->fUseCSat = 1; pPars->pFunc = (void *)Cec_ScorrStop; pPars->pData = (void *)&Stop; - return Cec_ManLSCorrespondence( p, pPars ); + p = Cec_ManLSCorrespondence( p, pPars ); + if ( pStopOut ) + *pStopOut = Stop; + return p; } /**Function************************************************************* @@ -424,7 +1182,7 @@ static void Cec_GiaStartThreads( Par_ThData_t * ThData, int nWorkers ) assert( status == 0 ); } } -static void Cec_GiaInitThreads( Par_ThData_t * ThData, int nWorkers, Gia_Man_t * p, int nTimeOut, int nTimeOutU, Wlc_Ntk_t * pWlc, int fUseUif, int fVerbose, pthread_t * WorkerThread, Par_Share_t * pShare ) +static void Cec_GiaInitThreads( Par_ThData_t * ThData, int nWorkers, Gia_Man_t * p, int nTimeOut, int nTimeOutU, Wlc_Ntk_t * pWlc, const char * pUfarArgs, int fVerbose, pthread_t * WorkerThread, Par_Share_t * pShare, int * pEngines, int StageId, int NetId, Cec_SproveTrace_t * pTrace ) { int i, status; assert( nWorkers <= PAR_THR_MAX ); @@ -434,12 +1192,7 @@ static void Cec_GiaInitThreads( Par_ThData_t * ThData, int nWorkers, Gia_Man_t * { ThData[i].p = Gia_ManDup( p ); Cec_CopyGiaName( p, ThData[i].p ); - if ( fUseUif && i == nWorkers - 1 ) - ThData[i].iEngine = PAR_ENGINE_UFAR; - else if ( !fUseUif && nWorkers == 6 && i == 5 ) - ThData[i].iEngine = PAR_ENGINE_GLA; - else - ThData[i].iEngine = i; + ThData[i].iEngine = pEngines[i]; ThData[i].fWorking = 0; ThData[i].fStop = 0; ThData[i].nTimeOut = nTimeOut; @@ -447,7 +1200,13 @@ static void Cec_GiaInitThreads( Par_ThData_t * ThData, int nWorkers, Gia_Man_t * ThData[i].fVerbose = fVerbose; ThData[i].nTimeOutU= nTimeOutU; ThData[i].pWlc = pWlc; + ThData[i].pUfarArgs= pUfarArgs; + ThData[i].WorkerId = i; + ThData[i].StageId = StageId; + ThData[i].NetId = NetId; + ThData[i].StopReason = 0; ThData[i].pShare = pShare; + ThData[i].pTrace = pTrace; status = pthread_mutex_init( &ThData[i].Mutex, NULL ); assert( status == 0 ); status = pthread_cond_init( &ThData[i].Cond, NULL ); @@ -463,18 +1222,19 @@ static void Cec_GiaInitThreads( Par_ThData_t * ThData, int nWorkers, Gia_Man_t * Gia_ManStopP( &ThData[i].p ); ThData[i].p = Gia_ManDup( p ); Cec_CopyGiaName( p, ThData[i].p ); - if ( fUseUif && i == nWorkers - 1 ) - ThData[i].iEngine = PAR_ENGINE_UFAR; - else if ( !fUseUif && nWorkers == 6 && i == 5 ) - ThData[i].iEngine = PAR_ENGINE_GLA; - else - ThData[i].iEngine = i; + ThData[i].iEngine = pEngines[i]; ThData[i].nTimeOut = nTimeOut; ThData[i].Result = -1; ThData[i].fVerbose = fVerbose; ThData[i].nTimeOutU= nTimeOutU; ThData[i].pWlc = pWlc; + ThData[i].pUfarArgs= pUfarArgs; + ThData[i].WorkerId = i; + ThData[i].StageId = StageId; + ThData[i].NetId = NetId; + ThData[i].StopReason = 0; ThData[i].pShare = pShare; + ThData[i].pTrace = pTrace; status = pthread_mutex_unlock( &ThData[i].Mutex ); assert( status == 0 ); } @@ -527,98 +1287,43 @@ static int Cec_GiaWaitThreads( Par_ThData_t * ThData, int nWorkers, Gia_Man_t * return RetValue; } -int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fUseUif, Wlc_Ntk_t * pWlc, int fVerbose, int fVeryVerbose, int fSilent ) +int Cec_GiaReplayReadParams( char * pFileName, int * pnProcs, int * pnTimeOut, int * pnTimeOut2, int * pnTimeOut3, int * pfUseUif ) { - abctime clkScorr = 0, clkTotal = Abc_Clock(); - Par_ThData_t ThData[PAR_THR_MAX]; - pthread_t WorkerThread[PAR_THR_MAX]; - Par_Share_t Share; - int nWorkers = nProcs + (fUseUif ? 1 : 0), RetValue = -1, RetEngine = -1; - memset( &Share, 0, sizeof(Par_Share_t) ); - memset( ThData, 0, sizeof(ThData) ); - memset( WorkerThread, 0, sizeof(WorkerThread) ); - 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 ); - + Cec_SprovePlan_t Plan; + if ( !Cec_SproveReplayReadParamsInt( pFileName, &Plan ) ) + return 0; + if ( pnProcs ) + *pnProcs = Plan.nProcs; + if ( pnTimeOut ) + *pnTimeOut = Plan.nTimeOut; + if ( pnTimeOut2 ) + *pnTimeOut2 = Plan.nTimeOut2; + if ( pnTimeOut3 ) + *pnTimeOut3 = Plan.nTimeOut3; + if ( pfUseUif ) + *pfUseUif = Plan.fUseUif; + Cec_SprovePlanFree( &Plan ); + return 1; +} +int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, int nTimeOut3, int fUseUif, Wlc_Ntk_t * pWlc, int fVerbose, int fVeryVerbose, int fSilent, char * pReplayFile, char * pUfarArgs ) +{ + Cec_SprovePlan_t Plan; + int RetValue; + Cec_SprovePlanDefault( &Plan, nProcs, nTimeOut, nTimeOut2, nTimeOut3, fUseUif, pUfarArgs ); assert( nProcs >= 1 && nProcs <= 6 ); - assert( nWorkers <= PAR_THR_MAX ); - Cec_GiaInitThreads( ThData, nWorkers, p, nTimeOut, nTimeOut3, pWlc, fUseUif, fVerbose, WorkerThread, &Share ); - - // meanwhile, perform scorr - Gia_Man_t * pScorr = Cec_GiaScorrNew( p, nTimeOut, &Share ); - clkScorr = Abc_Clock() - clkTotal; - if ( Gia_ManAndNum(pScorr) == 0 ) - { - Share.fSolved = 1; - Share.Result = 1; - Share.iEngine = PAR_ENGINE_SCORR1; - RetValue = 1, RetEngine = PAR_ENGINE_SCORR1; - } - - RetValue = Cec_GiaWaitThreads( ThData, nWorkers, 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, nWorkers, pScorr, nTimeOut2, nTimeOut3, pWlc, fUseUif, fVerbose, NULL, &Share ); - - RetValue = Cec_GiaWaitThreads( ThData, nWorkers, p, RetValue, &RetEngine ); - if ( RetValue == -1 && Gia_ManAndNum(pScorr) < 100000 ) - { - // Run this reduction only when round-2 did not decide the problem. - Gia_Man_t * pScorr2 = Cec_GiaScorrOld( pScorr, nTimeOut3, &Share ); - clkScorr2 = Abc_Clock() - clkStart; - if ( Gia_ManAndNum(pScorr2) == 0 ) - { - Share.fSolved = 1; - Share.Result = 1; - Share.iEngine = PAR_ENGINE_SCORR2; - RetValue = 1, RetEngine = PAR_ENGINE_SCORR2; - } - - 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, nWorkers, pScorr2, nTimeOut3, nTimeOut3, pWlc, fUseUif, fVerbose, NULL, &Share ); - - RetValue = Cec_GiaWaitThreads( ThData, nWorkers, p, RetValue, &RetEngine ); - // do something else - } - Gia_ManStop( pScorr2 ); - } - } - Gia_ManStop( pScorr ); - - // stop threads - Cec_GiaStopThreads( ThData, WorkerThread, nWorkers ); - if ( !fSilent ) - { - char * pProbName = p->pSpec ? p->pSpec : Gia_ManName(p); - if ( RetValue != -1 && RetEngine < 0 ) - RetEngine = PAR_ENGINE_SCORR1; - printf( "Problem \"%s\" is ", pProbName ? pProbName : "(none)" ); - if ( RetValue == 0 ) - printf( "SATISFIABLE (solved by %s).", Cec_SolveEngineName(RetEngine) ); - else if ( RetValue == 1 ) - printf( "UNSATISFIABLE (solved by %s).", Cec_SolveEngineName(RetEngine) ); - else if ( RetValue == -1 ) - printf( "UNDECIDED." ); - else assert( 0 ); - printf( " " ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); - fflush( stdout ); - } + assert( nProcs + (fUseUif ? 1 : 0) <= PAR_THR_MAX ); + RetValue = Cec_SproveExecutePlan( p, &Plan, pWlc, fVerbose, fVeryVerbose, fSilent, pReplayFile ); + Cec_SprovePlanFree( &Plan ); + return RetValue; +} +int Cec_GiaReplayTest( Gia_Man_t * p, Wlc_Ntk_t * pWlc, char * pFileName, int fVerbose, int fVeryVerbose, int fSilent ) +{ + Cec_SprovePlan_t Plan; + int RetValue; + if ( !Cec_SproveReplayReadPlan( pFileName, &Plan ) ) + return -1; + RetValue = Cec_SproveExecutePlan( p, &Plan, pWlc, fVerbose, fVeryVerbose, fSilent, NULL ); + Cec_SprovePlanFree( &Plan ); return RetValue; } diff --git a/src/proof/cec/cecSeq.c b/src/proof/cec/cecSeq.c index 81420e032e..629941b74e 100644 --- a/src/proof/cec/cecSeq.c +++ b/src/proof/cec/cecSeq.c @@ -170,6 +170,53 @@ int Cec_ManSeqResimulate( Cec_ManSim_t * p, Vec_Ptr_t * vInfo ) return 0; } +int Cec_ManSeqResimulateSeed( Cec_ManSim_t * p, Vec_Ptr_t * vInfo, Cec_SeedSim_t * pSeed ) +{ + unsigned * pInfo0, * pInfo1; + int f, i, k, w, RetValue; + assert( pSeed != NULL ); + assert( pSeed->pAig == p->pAig ); + assert( pSeed->nFrames == p->pPars->nFrames ); + assert( pSeed->nWords == p->nWords ); + assert( Vec_PtrSize(vInfo) == Gia_ManRegNum(p->pAig) + Gia_ManPiNum(p->pAig) * p->pPars->nFrames ); + for ( k = 0; k < Gia_ManRegNum(p->pAig); k++ ) + { + pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, k ); + pInfo1 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, Gia_ManPoNum(p->pAig) + k ); + for ( w = 0; w < p->nWords; w++ ) + pInfo1[w] = pInfo0[w]; + } + for ( f = 0; f < p->pPars->nFrames; f++ ) + { + unsigned * pSave = pSeed->pPhase + (size_t)f * pSeed->nPhaseWords; + for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) + { + pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, k++ ); + pInfo1 = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, i ); + for ( w = 0; w < p->nWords; w++ ) + pInfo1[w] = pInfo0[w]; + } + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + { + pInfo0 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, Gia_ManPoNum(p->pAig) + i ); + pInfo1 = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, Gia_ManPiNum(p->pAig) + i ); + for ( w = 0; w < p->nWords; w++ ) + pInfo1[w] = pInfo0[w]; + } + Cec_SeedSimSaveFrameInputs( pSeed, p->vCiSimInfo, f ); + RetValue = Cec_ManSimSimulateRoundSavePhase( p, p->vCiSimInfo, p->vCoSimInfo, pSave ); + Cec_SeedSimSaveFrameOutputs( pSeed, p->vCoSimInfo, f ); + if ( RetValue ) + { + pSeed->fInitialized = 0; + return 1; + } + } + assert( k == Vec_PtrSize(vInfo) ); + Cec_SeedSimFinishFull( pSeed ); + return 0; +} + /**Function************************************************************* Synopsis [Resimulates information to refine equivalence classes.] diff --git a/src/proof/cec/cecSolve.c b/src/proof/cec/cecSolve.c index f8342859ab..a3518e76b7 100644 --- a/src/proof/cec/cecSolve.c +++ b/src/proof/cec/cecSolve.c @@ -1055,6 +1055,32 @@ void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 Cec_ManSatSolveMiter_rec( p, p->pAig, Gia_Regular(pObj2) ); } +static int Cec_ManSatLitValue( Cec_ManSat_t * p, int iLit ) +{ + Gia_Obj_t * pObj; + if ( iLit < 0 ) + return -1; + if ( Abc_Lit2Var(iLit) == 0 ) + return Abc_LitIsCompl(iLit); + pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(iLit) ); + if ( Cec_ObjSatNum(p, pObj) == 0 ) + return -1; + return Cec_ObjSatVarValue( p, pObj ) ^ Abc_LitIsCompl(iLit); +} + +static void Cec_ManSatSaveOutVals( Cec_ManSat_t * p, Vec_Int_t * vOutLits, Vec_Int_t * vOutVals, int Out ) +{ + int Val0, Val1; + if ( vOutLits == NULL || vOutVals == NULL ) + return; + if ( 2*Out + 1 >= Vec_IntSize(vOutLits) ) + return; + Val0 = Cec_ManSatLitValue( p, Vec_IntEntry(vOutLits, 2*Out) ); + Val1 = Cec_ManSatLitValue( p, Vec_IntEntry(vOutLits, 2*Out + 1) ); + Vec_IntWriteEntry( vOutVals, 2*Out, Val0 ); + Vec_IntWriteEntry( vOutVals, 2*Out + 1, Val1 ); +} + /**Function************************************************************* Synopsis [Performs one round of solving for the POs of the AIG.] @@ -1067,10 +1093,11 @@ void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 SeeAlso [] ***********************************************************************/ -Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus ) +Vec_Int_t * Cec_ManSatSolveMiterOutVals( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus, Vec_Int_t * vOutLits, Vec_Int_t ** pvOutVals ) { Bar_Progress_t * pProgress = NULL; Vec_Int_t * vCexStore; + Vec_Int_t * vOutVals = NULL; Vec_Str_t * vStatus; Cec_ManSat_t * p; Gia_Obj_t * pObj; @@ -1083,6 +1110,12 @@ Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_St // create resulting data-structures vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); vCexStore = Vec_IntAlloc( 10000 ); + if ( pvOutVals ) + { + *pvOutVals = NULL; + if ( vOutLits ) + vOutVals = Vec_IntStartFull( 2 * Gia_ManPoNum(pAig) ); + } // perform solving p = Cec_ManSatCreate( pAig, pPars ); pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) ); @@ -1115,6 +1148,7 @@ Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_St if ( status == 1 ) continue; assert( status == 0 ); + Cec_ManSatSaveOutVals( p, vOutLits, vOutVals, i ); // save the pattern // Gia_ManIncrementTravId( pAig ); // Cec_ManSatSolveMiter_rec( p, pAig, Gia_ObjFanin0(pObj) ); @@ -1128,9 +1162,18 @@ Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_St // Cec_ManSatPrintStats( p ); Cec_ManSatStop( p ); *pvStatus = vStatus; + if ( pvOutVals ) + *pvOutVals = vOutVals; + else + Vec_IntFreeP( &vOutVals ); return vCexStore; } +Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus ) +{ + return Cec_ManSatSolveMiterOutVals( pAig, pPars, pvStatus, NULL, NULL ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/proof/cec/module.make b/src/proof/cec/module.make index ed8deba98d..a009e3b714 100644 --- a/src/proof/cec/module.make +++ b/src/proof/cec/module.make @@ -3,6 +3,9 @@ SRC += src/proof/cec/cecCec.c \ src/proof/cec/cecClass.c \ src/proof/cec/cecCore.c \ src/proof/cec/cecCorr.c \ + src/proof/cec/cecCorrDyn.c \ + src/proof/cec/cecCorrIncr.c \ + src/proof/cec/cecCorrIncrSim.c \ src/proof/cec/cecIso.c \ src/proof/cec/cecMan.c \ src/proof/cec/cecPat.c \ diff --git a/src/proof/ssw/sswConstr.c b/src/proof/ssw/sswConstr.c index d8be282fad..953ef2cfac 100644 --- a/src/proof/ssw/sswConstr.c +++ b/src/proof/ssw/sswConstr.c @@ -501,6 +501,7 @@ int Ssw_ManSweepBmcConstr( Ssw_Man_t * p ) int i, f, iLits; abctime clk; clk = Abc_Clock(); + abctime timeSatBmc = p->timeSat, timeSimSatBmc = p->timeSimSat; // start initialized timeframes p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); @@ -568,7 +569,7 @@ clk = Abc_Clock(); // cleanup // Ssw_ClassesCheck( p->ppClasses ); -p->timeBmc += Abc_Clock() - clk; +p->timeBmc += (Abc_Clock() - clk) - (p->timeSat - timeSatBmc) - (p->timeSimSat - timeSimSatBmc); return p->fRefined; } diff --git a/src/proof/ssw/sswSweep.c b/src/proof/ssw/sswSweep.c index ead977af33..092cb1232c 100644 --- a/src/proof/ssw/sswSweep.c +++ b/src/proof/ssw/sswSweep.c @@ -276,6 +276,7 @@ int Ssw_ManSweepBmc( Ssw_Man_t * p ) int i, f; abctime clk; clk = Abc_Clock(); + abctime timeSatBmc = p->timeSat, timeSimSatBmc = p->timeSimSat; // start initialized timeframes p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); @@ -329,7 +330,7 @@ clk = Abc_Clock(); // cleanup // Ssw_ClassesCheck( p->ppClasses ); -p->timeBmc += Abc_Clock() - clk; +p->timeBmc += (Abc_Clock() - clk) - (p->timeSat - timeSatBmc) - (p->timeSimSat - timeSimSatBmc); return p->fRefined; } diff --git a/src/sat/bmc/bmc.h b/src/sat/bmc/bmc.h index 1e6d51a243..83ddc810a7 100644 --- a/src/sat/bmc/bmc.h +++ b/src/sat/bmc/bmc.h @@ -82,6 +82,8 @@ struct Bmc_EsPar_t_ char * pSymStr; char * pPermStr; char * pGuide; + int * pPermFans; + int * pSolFans; Vec_Wrd_t* vTruths; }; @@ -134,6 +136,7 @@ struct Saig_ParBmc_t_ int fNoRestarts; // disables periodic restarts int fUseSatoko; // enables using Satoko int fUseGlucose; // enables using Glucose 3.0 + int fUseCadical; // enables using CaDiCaL int nLearnedStart; // starting learned clause limit int nLearnedDelta; // delta of learned clause limit int nLearnedPerce; // ratio of learned clause limit diff --git a/src/sat/bmc/bmcBmc3.c b/src/sat/bmc/bmcBmc3.c index 7e0a6cfdcd..a6d5bc5945 100644 --- a/src/sat/bmc/bmcBmc3.c +++ b/src/sat/bmc/bmcBmc3.c @@ -23,12 +23,21 @@ #include "sat/bsat/satStore.h" #include "sat/satoko/satoko.h" #include "sat/glucose/AbcGlucose.h" +#include "sat/cadical/cadicalSolver.h" +#include "sat/cadical/ccadical.h" #include "misc/vec/vecHsh.h" #include "misc/vec/vecWec.h" #include "bmc.h" ABC_NAMESPACE_IMPL_START +static inline void Bmc3_CadicalSetRuntimeLimit( cadical_solver * pSat4, abctime nSeconds ) +{ + if ( pSat4 == NULL || nSeconds <= 0 ) + return; + ccadical_limit( (CCaDiCaL *)pSat4->p, "seconds", nSeconds ); +} + //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// @@ -64,6 +73,7 @@ struct Gia_ManBmc_t_ sat_solver * pSat; // SAT solver satoko_t * pSat2; // SAT solver bmcg_sat_solver * pSat3; // SAT solver + cadical_solver * pSat4; // SAT solver int nSatVars; // SAT variables int nObjNums; // SAT objects int nWordNum; // unsigned words for ternary simulation @@ -718,7 +728,7 @@ Vec_Int_t * Saig_ManBmcComputeMappingRefs( Aig_Man_t * p, Vec_Int_t * vMap ) SeeAlso [] ***********************************************************************/ -Gia_ManBmc_t * Saig_Bmc3ManStart( Aig_Man_t * pAig, int nTimeOutOne, int nConfLimit, int fUseSatoko, int fUseGlucose ) +Gia_ManBmc_t * Saig_Bmc3ManStart( Aig_Man_t * pAig, int nTimeOutOne, int nConfLimit, int fUseSatoko, int fUseGlucose, int fUseCadical ) { Gia_ManBmc_t * p; Aig_Obj_t * pObj; @@ -763,6 +773,11 @@ Gia_ManBmc_t * Saig_Bmc3ManStart( Aig_Man_t * pAig, int nTimeOutOne, int nConfLi for ( i = 0; i < 1000; i++ ) bmcg_sat_solver_addvar( p->pSat3 ); } + else if ( fUseCadical ) + { + p->pSat4 = cadical_solver_new(); + cadical_solver_setnvars(p->pSat4, 1000); + } else { p->pSat = sat_solver_new(); @@ -806,9 +821,9 @@ void Saig_Bmc3ManStop( Gia_ManBmc_t * p ) p->pSat ? p->pSat->nLearntDelta : 0, p->pSat ? p->pSat->nLearntRatio : 0, p->pSat ? p->pSat->nDBreduces : 0, - p->pSat ? sat_solver_nvars(p->pSat) : p->pSat3 ? bmcg_sat_solver_varnum(p->pSat3) : satoko_varnum(p->pSat2), + p->pSat ? sat_solver_nvars(p->pSat) : p->pSat4 ? cadical_solver_nvars(p->pSat4) : p->pSat3 ? bmcg_sat_solver_varnum(p->pSat3) : satoko_varnum(p->pSat2), nUsedVars, - 100.0*nUsedVars/(p->pSat ? sat_solver_nvars(p->pSat) : p->pSat3 ? bmcg_sat_solver_varnum(p->pSat3) : satoko_varnum(p->pSat2)) ); + 100.0*nUsedVars/(p->pSat ? sat_solver_nvars(p->pSat) : p->pSat4 ? cadical_solver_nvars(p->pSat4) : p->pSat3 ? bmcg_sat_solver_varnum(p->pSat3) : satoko_varnum(p->pSat2)) ); Abc_Print( 1, "Buffs = %d. Dups = %d. Hash hits = %d. Hash misses = %d. UniProps = %d.\n", p->nBufNum, p->nDupNum, p->nHashHit, p->nHashMiss, p->nUniProps ); } @@ -830,6 +845,7 @@ void Saig_Bmc3ManStop( Gia_ManBmc_t * p ) if ( p->pSat ) sat_solver_delete( p->pSat ); if ( p->pSat2 ) satoko_destroy( p->pSat2 ); if ( p->pSat3 ) bmcg_sat_solver_stop( p->pSat3 ); + if ( p->pSat4 ) cadical_solver_delete( p->pSat4 ); ABC_FREE( p->pTime4Outs ); Vec_IntFree( p->vData ); Hsh_IntManStop( p->vHash ); @@ -1029,6 +1045,11 @@ static inline void Saig_ManBmcAddClauses( Gia_ManBmc_t * p, int uTruth, int Lits if ( !bmcg_sat_solver_addclause( p->pSat3, ClaLits, nClaLits ) ) assert( 0 ); } + else if ( p->pSat4 ) + { + if ( !cadical_solver_addclause( p->pSat4, ClaLits, ClaLits+nClaLits ) ) + assert( 0 ); + } else { if ( !sat_solver_addclause( p->pSat, ClaLits, ClaLits+nClaLits ) ) @@ -1287,6 +1308,11 @@ int Saig_ManBmcCreateCnf( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame ) for ( i = bmcg_sat_solver_varnum(p->pSat3); i < p->nSatVars; i++ ) bmcg_sat_solver_addvar( p->pSat3 ); } + else if ( p->pSat4 ) + { + for ( i = cadical_solver_nvars(p->pSat4); i < p->nSatVars; i++ ) + cadical_solver_addvar( p->pSat4 ); + } else sat_solver_setnvars( p->pSat, p->nSatVars ); return Lit; @@ -1411,6 +1437,11 @@ Abc_Cex_t * Saig_ManGenerateCex( Gia_ManBmc_t * p, int f, int i ) if ( iLit != ~0 && bmcg_sat_solver_read_cex_varvalue(p->pSat3, lit_var(iLit)) ) Abc_InfoSetBit( pCex->pData, iBit + k ); } + else if ( p->pSat4) + { + if ( iLit != ~0 && cadical_solver_get_var_value(p->pSat4, lit_var(iLit)) ) + Abc_InfoSetBit( pCex->pData, iBit + k ); + } else { if ( iLit != ~0 && sat_solver_var_value(p->pSat, lit_var(iLit)) ) @@ -1445,6 +1476,10 @@ int Saig_ManCallSolver( Gia_ManBmc_t * p, int Lit ) bmcg_sat_solver_set_conflict_budget( p->pSat3, p->pPars->nConfLimit ); return bmcg_sat_solver_solve( p->pSat3, &Lit, 1 ); } + else if ( p->pSat4 ) + { + return cadical_solver_solve( p->pSat4, &Lit, &Lit + 1, (ABC_INT64_T)p->pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + } else return sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)p->pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); } @@ -1482,7 +1517,7 @@ int Saig_ManBmcScalable( Aig_Man_t * pAig, Saig_ParBmc_t * pPars ) nTimeToStopNG = pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0; nTimeToStop = Saig_ManBmcTimeToStop( pPars, nTimeToStopNG ); // create BMC manager - p = Saig_Bmc3ManStart( pAig, pPars->nTimeOutOne, pPars->nConfLimit, pPars->fUseSatoko, pPars->fUseGlucose ); + p = Saig_Bmc3ManStart( pAig, pPars->nTimeOutOne, pPars->nConfLimit, pPars->fUseSatoko, pPars->fUseGlucose, pPars->fUseCadical ); p->pPars = pPars; if ( p->pSat ) { @@ -1498,6 +1533,10 @@ int Saig_ManBmcScalable( Aig_Man_t * pAig, Saig_ParBmc_t * pPars ) { // satoko_set_runid(p->pSat3, p->pPars->RunId); // satoko_set_stop_func(p->pSat3, p->pPars->pFuncStop); + } + else if ( p->pSat4 ) + { + } else { @@ -1522,6 +1561,8 @@ int Saig_ManBmcScalable( Aig_Man_t * pAig, Saig_ParBmc_t * pPars ) satoko_set_runtime_limit( p->pSat2, nTimeToStop ); else if ( p->pSat3 ) bmcg_sat_solver_set_runtime_limit( p->pSat3, nTimeToStop ); + else if ( p-> pSat4 ) + Bmc3_CadicalSetRuntimeLimit( p->pSat4, nTimeToStop ); else sat_solver_set_runtime_limit( p->pSat, nTimeToStop ); } @@ -1659,6 +1700,8 @@ clkOther += Abc_Clock() - clk2; satoko_set_runtime_limit( p->pSat2, p->pTime4Outs[i] + Abc_Clock() ); else if ( p->pSat3 ) bmcg_sat_solver_set_runtime_limit( p->pSat3, p->pTime4Outs[i] + Abc_Clock() ); + else if ( p-> pSat4 ) + Bmc3_CadicalSetRuntimeLimit( p->pSat4, p->pTime4Outs[i] + Abc_Clock() ); else sat_solver_set_runtime_limit( p->pSat, p->pTime4Outs[i] + Abc_Clock() ); } @@ -1690,6 +1733,8 @@ nTimeUnsat += clkSatRun; status = satoko_add_clause( p->pSat2, &Lit, 1 ); else if ( p->pSat3 ) status = bmcg_sat_solver_addclause( p->pSat3, &Lit, 1 ); + else if ( p->pSat4 ) + status = cadical_solver_addclause( p->pSat4, &Lit, &Lit + 1 ); else status = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); assert( status ); @@ -1721,12 +1766,12 @@ nTimeSat += clkSatRun; { Abc_Print( 1, "%4d %s : ", f, fUnfinished ? "-" : "+" ); Abc_Print( 1, "Var =%8.0f. ", (double)p->nSatVars ); - Abc_Print( 1, "Cla =%9.0f. ", (double)(p->pSat ? p->pSat->stats.clauses : p->pSat3 ? bmcg_sat_solver_clausenum(p->pSat3) : satoko_clausenum(p->pSat2)) ); - Abc_Print( 1, "Conf =%7.0f. ", (double)(p->pSat ? p->pSat->stats.conflicts : p->pSat3 ? bmcg_sat_solver_conflictnum(p->pSat3) : satoko_conflictnum(p->pSat2)) ); + Abc_Print( 1, "Cla =%9.0f. ", (double)(p->pSat ? p->pSat->stats.clauses : p->pSat4 ? cadical_solver_nclauses(p->pSat4) : p->pSat3 ? bmcg_sat_solver_clausenum(p->pSat3) : satoko_clausenum(p->pSat2)) ); + Abc_Print( 1, "Conf =%7.0f. ", (double)(p->pSat ? p->pSat->stats.conflicts : p->pSat4 ? cadical_solver_nconflicts(p->pSat4) : p->pSat3 ? bmcg_sat_solver_conflictnum(p->pSat3) : satoko_conflictnum(p->pSat2)) ); // Abc_Print( 1, "Imp =%10.0f. ", (double)p->pSat->stats.propagations ); // Abc_Print( 1, "Uni =%7.0f. ",(double)(p->pSat ? sat_solver_count_assigned(p->pSat) : 0) ); // ABC_PRT( "Time", Abc_Clock() - clk ); - Abc_Print( 1, "Learn =%7.0f. ", (double)(p->pSat ? p->pSat->stats.learnts : p->pSat3 ? bmcg_sat_solver_learntnum(p->pSat3) : satoko_learntnum(p->pSat2)) ); + Abc_Print( 1, "Learn =%7.0f. ", (double)(p->pSat ? p->pSat->stats.learnts : p->pSat4 ? cadical_solver_nlearned(p->pSat4) : p->pSat3 ? bmcg_sat_solver_learntnum(p->pSat3) : satoko_learntnum(p->pSat2)) ); Abc_Print( 1, "%4.0f MB", 4.25*(f+1)*p->nObjNums /(1<<20) ); Abc_Print( 1, "%4.0f MB", 1.0*(p->pSat ? sat_solver_memory(p->pSat) : 0)/(1<<20) ); Abc_Print( 1, "%9.2f sec ", (float)(Abc_Clock() - clkTotal)/(float)(CLOCKS_PER_SEC) ); @@ -1773,6 +1818,8 @@ nTimeSat += clkSatRun; satoko_set_runtime_limit( p->pSat2, nTimeToStop ); else if ( p->pSat3 ) bmcg_sat_solver_set_runtime_limit( p->pSat3, nTimeToStop ); + else if ( p->pSat4 ) + Bmc3_CadicalSetRuntimeLimit ( p->pSat4, nTimeToStop ); else sat_solver_set_runtime_limit( p->pSat, nTimeToStop ); } @@ -1798,6 +1845,11 @@ nTimeSat += clkSatRun; if ( bmcg_sat_solver_read_cex_varvalue(p->pSat3, lit_var(Lit)) == Abc_LitIsCompl(Lit) ) continue; } + else if (p->pSat4) + { + if ( cadical_solver_get_var_value(p->pSat4, lit_var(Lit)) == Abc_LitIsCompl(Lit) ) + continue; + } else { if ( sat_solver_var_value(p->pSat, lit_var(Lit)) == Abc_LitIsCompl(Lit) ) @@ -1841,7 +1893,7 @@ nTimeUndec += clkSatRun; } if ( pPars->fVerbose ) { - if ( fFirst == 1 && f > 0 && (p->pSat ? p->pSat->stats.conflicts : p->pSat3 ? bmcg_sat_solver_conflictnum(p->pSat3) : satoko_conflictnum(p->pSat2)) > 1 ) + if ( fFirst == 1 && f > 0 && (p->pSat ? p->pSat->stats.conflicts : p->pSat4 ? cadical_solver_nconflicts(p->pSat4) : p->pSat3 ? bmcg_sat_solver_conflictnum(p->pSat3) : satoko_conflictnum(p->pSat2)) > 1 ) { fFirst = 0; // Abc_Print( 1, "Outputs of frames up to %d are trivially UNSAT.\n", f ); @@ -1849,11 +1901,11 @@ nTimeUndec += clkSatRun; Abc_Print( 1, "%4d %s : ", f, fUnfinished ? "-" : "+" ); Abc_Print( 1, "Var =%8.0f. ", (double)p->nSatVars ); // Abc_Print( 1, "Used =%8.0f. ", (double)sat_solver_count_usedvars(p->pSat) ); - Abc_Print( 1, "Cla =%9.0f. ", (double)(p->pSat ? p->pSat->stats.clauses : p->pSat3 ? bmcg_sat_solver_clausenum(p->pSat3) : satoko_clausenum(p->pSat2)) ); - Abc_Print( 1, "Conf =%7.0f. ",(double)(p->pSat ? p->pSat->stats.conflicts : p->pSat3 ? bmcg_sat_solver_conflictnum(p->pSat3) : satoko_conflictnum(p->pSat2)) ); + Abc_Print( 1, "Cla =%9.0f. ", (double)(p->pSat ? p->pSat->stats.clauses : p->pSat4 ? cadical_solver_nclauses(p->pSat4) : p->pSat3 ? bmcg_sat_solver_clausenum(p->pSat3) : satoko_clausenum(p->pSat2)) ); + Abc_Print( 1, "Conf =%7.0f. ",(double)(p->pSat ? p->pSat->stats.conflicts : p->pSat4 ? cadical_solver_nconflicts(p->pSat4) : p->pSat3 ? bmcg_sat_solver_conflictnum(p->pSat3) : satoko_conflictnum(p->pSat2)) ); // Abc_Print( 1, "Imp =%10.0f. ", (double)p->pSat->stats.propagations ); // Abc_Print( 1, "Uni =%7.0f. ", (double)(p->pSat ? sat_solver_count_assigned(p->pSat) : 0) ); - Abc_Print( 1, "Learn =%7.0f. ", (double)(p->pSat ? p->pSat->stats.learnts : p->pSat3 ? bmcg_sat_solver_learntnum(p->pSat3) : satoko_learntnum(p->pSat2)) ); + Abc_Print( 1, "Learn =%7.0f. ", (double)(p->pSat ? p->pSat->stats.learnts : p->pSat4 ? cadical_solver_nlearned(p->pSat4) : p->pSat3 ? bmcg_sat_solver_learntnum(p->pSat3) : satoko_learntnum(p->pSat2)) ); if ( pPars->fSolveAll ) Abc_Print( 1, "CEX =%5d. ", pPars->nFailOuts ); if ( pPars->nTimeOutOne ) diff --git a/src/sat/bmc/bmcBmcG.c b/src/sat/bmc/bmcBmcG.c index af2da1e2e4..78321badb5 100644 --- a/src/sat/bmc/bmcBmcG.c +++ b/src/sat/bmc/bmcBmcG.c @@ -362,6 +362,8 @@ int Bmcg_ManPerformOne( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ) Abc_CexFreeP( &pGia->pCexSeq ); for ( f = 0; !pPars->nFramesMax || f < pPars->nFramesMax; f += pPars->nFramesAdd ) { + if ( pPars->pFuncProgress && pPars->pFuncProgress( pPars->pProgress, 0, 0 ) ) + break; Cnf_Dat_t * pCnf = Bmcg_ManAddNewCnf( p, f, pPars->nFramesAdd ); if ( pCnf == NULL ) { @@ -378,15 +380,21 @@ int Bmcg_ManPerformOne( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ) assert( Gia_ManPoNum(p->pFrames) == (f + pPars->nFramesAdd) * Gia_ManPoNum(pGia) ); for ( k = 0; k < pPars->nFramesAdd; k++ ) { + if ( pPars->pFuncProgress && pPars->pFuncProgress( pPars->pProgress, 0, 0 ) ) + break; for ( i = 0; i < Gia_ManPoNum(pGia); i++ ) { abctime clk = Abc_Clock(); int iObj = Gia_ObjId( p->pFrames, Gia_ManCo(p->pFrames, (f+k) * Gia_ManPoNum(pGia) + i) ); int iLit = Abc_Var2Lit( Vec_IntEntry(&p->vFr2Sat, iObj), 0 ); + if ( pPars->pFuncProgress && pPars->pFuncProgress( pPars->pProgress, 0, 0 ) ) + break; if ( pPars->nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= pPars->nTimeOut ) break; status = bmcg_sat_solver_solve( p->pSats[0], &iLit, 1 ); p->timeSat += Abc_Clock() - clk; + if ( pPars->pFuncProgress && pPars->pFuncProgress( pPars->pProgress, 0, 0 ) ) + break; if ( status == -1 ) // unsat { if ( i == Gia_ManPoNum(pGia)-1 ) diff --git a/src/sat/bmc/bmcMaj.c b/src/sat/bmc/bmcMaj.c index e342ff350a..b5831e7ff3 100644 --- a/src/sat/bmc/bmcMaj.c +++ b/src/sat/bmc/bmcMaj.c @@ -488,7 +488,8 @@ int Exa_ManMarkup( Exa_Man_t * p ) } } } - printf( "The number of parameter variables = %d.\n", p->iVar ); + if ( !p->pPars->fSilent ) + printf( "The number of parameter variables = %d.\n", p->iVar ); return p->iVar; // printout for ( i = p->nVars; i < p->nObjs; i++ ) @@ -569,6 +570,18 @@ static inline int Exa_ManFindFanin( Exa_Man_t * p, int i, int k ) assert( Count == 1 ); return iVar; } +static inline char * Exa_ManObjName( Exa_Man_t * p, int iObj, char * pBuffer ) +{ + if ( iObj < 0 ) + sprintf( pBuffer, "*" ); + else if ( iObj < p->nVars ) + sprintf( pBuffer, "%c", 'a' + iObj ); + else if ( iObj - p->nVars < 26 ) + sprintf( pBuffer, "%c", 'A' + iObj - p->nVars ); + else + sprintf( pBuffer, "N%d", iObj - p->nVars ); + return pBuffer; +} static inline int Exa_ManEval( Exa_Man_t * p ) { static int Flag = 0; @@ -637,20 +650,18 @@ void Exa_ManDumpBlif( Exa_Man_t * p, int fCompl ) int Val1 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart); int Val2 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+1); int Val3 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+2); + char Name[16]; fprintf( pFile, ".names" ); for ( k = 1; k >= 0; k-- ) { iVar = Exa_ManFindFanin( p, i, k ); - if ( iVar >= 0 && iVar < p->nVars ) - fprintf( pFile, " %c", 'a'+iVar ); - else - fprintf( pFile, " %02d", iVar ); + fprintf( pFile, " %s", Exa_ManObjName(p, iVar, Name) ); } if ( i == p->nObjs - 1 ) fprintf( pFile, " F\n" ); else - fprintf( pFile, " %02d\n", i ); + fprintf( pFile, " %s\n", Exa_ManObjName(p, i, Name) ); if ( i == p->nObjs - 1 && fCompl ) fprintf( pFile, "00 1\n" ); if ( (i == p->nObjs - 1 && fCompl) ^ Val1 ) @@ -668,6 +679,7 @@ void Exa_ManDumpBlif( Exa_Man_t * p, int fCompl ) void Exa_ManPrintSolution( Exa_Man_t * p, int fCompl ) { int i, k, iVar; + char Name[16]; printf( "Realization of given %d-input function using %d two-input gates:\n", p->nVars, p->nNodes ); // for ( i = p->nVars + 2; i < p->nObjs; i++ ) for ( i = p->nObjs - 1; i >= p->nVars; i-- ) @@ -677,20 +689,107 @@ void Exa_ManPrintSolution( Exa_Man_t * p, int fCompl ) int Val2 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+1); int Val3 = bmcg_sat_solver_read_cex_varvalue(p->pSat, iVarStart+2); if ( i == p->nObjs - 1 && fCompl ) - printf( "%02d = 4\'b%d%d%d1(", i, !Val3, !Val2, !Val1 ); + printf( "%s = 4\'b%d%d%d1(", Exa_ManObjName(p, i, Name), !Val3, !Val2, !Val1 ); else - printf( "%02d = 4\'b%d%d%d0(", i, Val3, Val2, Val1 ); + printf( "%s = 4\'b%d%d%d0(", Exa_ManObjName(p, i, Name), Val3, Val2, Val1 ); for ( k = 1; k >= 0; k-- ) { iVar = Exa_ManFindFanin( p, i, k ); - if ( iVar >= 0 && iVar < p->nVars ) - printf( " %c", 'a'+iVar ); - else - printf( " %02d", iVar ); + printf( " %s", Exa_ManObjName(p, iVar, Name) ); } printf( " )\n" ); } } +static inline int Exa_ManPermFanin( Exa_Man_t * p, int i, int k ) +{ + char * pPermStr = p->pPars->pPermStr; + int iTarget = 2 * (i - p->nVars) + (k ? 0 : 1); + int nSeen = 0; + char * pToken; + if ( p->pPars->pPermFans ) + return p->pPars->pPermFans[iTarget]; + assert( pPermStr != NULL ); + for ( pToken = pPermStr; *pToken; ) + { + int iObj = -2; + if ( *pToken == '_' ) + { + pToken++; + continue; + } + if ( *pToken == '*' ) + { + iObj = -1; + pToken++; + } + else if ( *pToken >= 'a' && *pToken < 'a' + p->nVars ) + iObj = *pToken++ - 'a'; + else if ( *pToken >= 'A' && *pToken <= 'Z' ) + iObj = p->nVars + (*pToken++ - 'A'); + else if ( *pToken == 'N' ) + { + char * pNext = pToken + 1; + int Num = 0; + assert( *pNext >= '0' && *pNext <= '9' ); + while ( *pNext >= '0' && *pNext <= '9' ) + Num = 10 * Num + *pNext++ - '0'; + iObj = p->nVars + Num; + pToken = pNext; + } + else + assert( 0 ); + if ( nSeen++ == iTarget ) + return iObj; + } + assert( 0 ); + return -1; +} +static void Exa_ManPrintPermFanin( Exa_Man_t * p, int iFanin ) +{ + char Name[16]; + printf( "%s ", Exa_ManObjName(p, iFanin, Name) ); +} +static void Exa_ManPrintFixedPerm( Exa_Man_t * p ) +{ + int i, k; + char Name[16]; + if ( (p->pPars->pPermStr == NULL && p->pPars->pPermFans == NULL) || p->pPars->fSilent ) + return; + printf( "Using fixed input assignment provided by the user %s:\n", p->pPars->pPermStr ? p->pPars->pPermStr : "" ); + for ( i = p->nObjs - 1; i >= p->nVars; i-- ) + { + printf( "%s : ", Exa_ManObjName(p, i, Name) ); + for ( k = 1; k >= 0; k-- ) + Exa_ManPrintPermFanin( p, Exa_ManPermFanin(p, i, k) ); + printf( "\n" ); + } +} +static void Exa_ManPrintPerm( Exa_Man_t * p ) +{ + int i, k, iVar; + char Name[16]; + printf( "The variable permutation is \"" ); + for ( i = p->nVars; i < p->nObjs; i++ ) + { + if ( i > p->nVars ) + printf( "_" ); + for ( k = 1; k >= 0; k-- ) + { + iVar = Exa_ManFindFanin( p, i, k ); + printf( "%s", Exa_ManObjName(p, iVar, Name) ); + } + } + printf( "\".\n" ); +} +static void Exa_ManSaveSolution( Exa_Man_t * p ) +{ + int i, k, Pos = 0; + ABC_FREE( p->pPars->pSolFans ); + p->pPars->pSolFans = ABC_ALLOC( int, 2 * p->nNodes ); + for ( i = p->nVars; i < p->nObjs; i++ ) + for ( k = 1; k >= 0; k-- ) + p->pPars->pSolFans[Pos++] = Exa_ManFindFanin( p, i, k ); +} /**Function************************************************************* @@ -716,6 +815,39 @@ static inline int Exa_ManAddClause( Exa_Man_t * p, int * pLits, int nLits ) } return bmcg_sat_solver_addclause( p->pSat, pLits, nLits ); } +static int Exa_ManAddPermConstr( Exa_Man_t * p ) +{ + int i, k, iVar, Lit; + char Name0[16], Name1[16]; + if ( p->pPars->pPermStr == NULL && p->pPars->pPermFans == NULL ) + return 1; + Exa_ManPrintFixedPerm( p ); + for ( i = p->nVars; i < p->nObjs; i++ ) + { + for ( k = 0; k < 2; k++ ) + { + iVar = Exa_ManPermFanin( p, i, k ); + if ( iVar == -1 ) + continue; + if ( iVar < 0 || iVar >= p->nVars || p->VarMarks[i][k][iVar] == 0 ) + { + if ( iVar >= p->nVars && iVar < i && p->VarMarks[i][k][iVar] ) + { + Lit = Abc_Var2Lit( p->VarMarks[i][k][iVar], 0 ); + if ( !Exa_ManAddClause( p, &Lit, 1 ) ) + return 0; + continue; + } + printf( "Cannot force node %s fanin %d to object %s because this connection is not available.\n", Exa_ManObjName(p, i, Name0), k, Exa_ManObjName(p, iVar, Name1) ); + return 0; + } + Lit = Abc_Var2Lit( p->VarMarks[i][k][iVar], 0 ); + if ( !Exa_ManAddClause( p, &Lit, 1 ) ) + return 0; + } + } + return 1; +} int Exa_ManAddCnfAdd( Exa_Man_t * p, int * pnAdded ) { int pLits[MAJ_NOBJS], pLits2[2], i, j, k, n, m; @@ -794,6 +926,8 @@ int Exa_ManAddCnfStart( Exa_Man_t * p, int fOnlyAnd ) assert( n == p->nVars + p->nNodes ); Vec_IntFreeP( &vRes ); } + if ( !Exa_ManAddPermConstr(p) ) + return 0; // input constraints for ( i = p->nVars; i < p->nObjs; i++ ) { @@ -946,9 +1080,10 @@ int Exa_ManAddCnf( Exa_Man_t * p, int iMint ) p->iVar += 3*p->nNodes; return 1; } -void Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ) +int Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ) { int i, status, iMint = 1; + int fFound = 0; abctime clkTotal = Abc_Clock(); Exa_Man_t * p; int fCompl = 0; word pTruth[64]; Abc_TtReadHex( pTruth, pPars->pTtStr ); @@ -956,8 +1091,13 @@ void Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ) p = Exa_ManAlloc( pPars, pTruth ); if ( pTruth[0] & 1 ) { fCompl = 1; Abc_TtNot( pTruth, p->nWords ); } status = Exa_ManAddCnfStart( p, pPars->fOnlyAnd ); - assert( status ); - printf( "Running exact synthesis for %d-input function with %d two-input gates...\n", p->nVars, p->nNodes ); + if ( !status ) + { + Exa_ManFree( p ); + return 0; + } + if ( !pPars->fSilent ) + printf( "Running exact synthesis for %d-input function with %d two-input gates...\n", p->nVars, p->nNodes ); for ( i = 0; iMint != -1; i++ ) { abctime clk = Abc_Clock(); @@ -978,23 +1118,33 @@ void Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ) } if ( status == GLUCOSE_UNSAT ) { - printf( "The problem has no solution.\n" ); + if ( !pPars->fSilent ) + printf( "The problem has no solution.\n" ); break; } if ( status == GLUCOSE_UNDEC ) { - printf( "The solver timed out after %d sec.\n", pPars->RuntimeLim ); + if ( !pPars->fSilent ) + printf( "The solver timed out after %d sec.\n", pPars->RuntimeLim ); break; } iMint = Exa_ManEval( p ); } if ( iMint == -1 ) { - Exa_ManPrintSolution( p, fCompl ); - Exa_ManDumpBlif( p, fCompl ); + Exa_ManSaveSolution( p ); + if ( !pPars->fSilent ) + { + Exa_ManPrintSolution( p, fCompl ); + Exa_ManPrintPerm( p ); + Exa_ManDumpBlif( p, fCompl ); + } + fFound = 1; } Exa_ManFree( p ); - Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); + if ( !pPars->fSilent ) + Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); + return fFound; } diff --git a/src/sat/bmc/bmcMaj2.c b/src/sat/bmc/bmcMaj2.c index 761795d967..23ccb72176 100644 --- a/src/sat/bmc/bmcMaj2.c +++ b/src/sat/bmc/bmcMaj2.c @@ -577,7 +577,8 @@ static int Exa_ManMarkup( Exa_Man_t * p ) } } } - printf( "The number of parameter variables = %d.\n", p->iVar ); + if ( !p->pPars->fSilent ) + printf( "The number of parameter variables = %d.\n", p->iVar ); return p->iVar; // printout for ( i = p->nVars; i < p->nObjs; i++ ) @@ -640,6 +641,18 @@ static inline int Exa_ManFindFanin( Exa_Man_t * p, int i, int k ) assert( Count == 1 ); return iVar; } +static inline char * Exa_ManObjName( Exa_Man_t * p, int iObj, char * pBuffer ) +{ + if ( iObj < 0 ) + sprintf( pBuffer, "*" ); + else if ( iObj < p->nVars ) + sprintf( pBuffer, "%c", 'a' + iObj ); + else if ( iObj - p->nVars < 26 ) + sprintf( pBuffer, "%c", 'A' + iObj - p->nVars ); + else + sprintf( pBuffer, "N%d", iObj - p->nVars ); + return pBuffer; +} static inline int Exa_ManEval( Exa_Man_t * p ) { static int Flag = 0; @@ -681,6 +694,7 @@ static inline int Exa_ManEval( Exa_Man_t * p ) static void Exa_ManPrintSolution( Exa_Man_t * p, int fCompl ) { int i, k, iVar; + char Name[16]; printf( "Realization of given %d-input function using %d two-input gates:\n", p->nVars, p->nNodes ); // for ( i = p->nVars + 2; i < p->nObjs; i++ ) for ( i = p->nObjs - 1; i >= p->nVars; i-- ) @@ -690,20 +704,140 @@ static void Exa_ManPrintSolution( Exa_Man_t * p, int fCompl ) int Val2 = sat_solver_var_value(p->pSat, iVarStart+1); int Val3 = sat_solver_var_value(p->pSat, iVarStart+2); if ( i == p->nObjs - 1 && fCompl ) - printf( "%02d = 4\'b%d%d%d1(", i, !Val3, !Val2, !Val1 ); + printf( "%s = 4\'b%d%d%d1(", Exa_ManObjName(p, i, Name), !Val3, !Val2, !Val1 ); else - printf( "%02d = 4\'b%d%d%d0(", i, Val3, Val2, Val1 ); + printf( "%s = 4\'b%d%d%d0(", Exa_ManObjName(p, i, Name), Val3, Val2, Val1 ); for ( k = 1; k >= 0; k-- ) { iVar = Exa_ManFindFanin( p, i, k ); - if ( iVar >= 0 && iVar < p->nVars ) - printf( " %c", 'a'+iVar ); - else - printf( " %02d", iVar ); + printf( " %s", Exa_ManObjName(p, iVar, Name) ); } printf( " )\n" ); } } +static inline int Exa_ManPermFanin( Exa_Man_t * p, int i, int k ) +{ + char * pPermStr = p->pPars->pPermStr; + int iTarget = 2 * (i - p->nVars) + (k ? 0 : 1); + int nSeen = 0; + char * pToken; + if ( p->pPars->pPermFans ) + return p->pPars->pPermFans[iTarget]; + assert( pPermStr != NULL ); + for ( pToken = pPermStr; *pToken; ) + { + int iObj = -2; + if ( *pToken == '_' ) + { + pToken++; + continue; + } + if ( *pToken == '*' ) + { + iObj = -1; + pToken++; + } + else if ( *pToken >= 'a' && *pToken < 'a' + p->nVars ) + iObj = *pToken++ - 'a'; + else if ( *pToken >= 'A' && *pToken <= 'Z' ) + iObj = p->nVars + (*pToken++ - 'A'); + else if ( *pToken == 'N' ) + { + char * pNext = pToken + 1; + int Num = 0; + assert( *pNext >= '0' && *pNext <= '9' ); + while ( *pNext >= '0' && *pNext <= '9' ) + Num = 10 * Num + *pNext++ - '0'; + iObj = p->nVars + Num; + pToken = pNext; + } + else + assert( 0 ); + if ( nSeen++ == iTarget ) + return iObj; + } + assert( 0 ); + return -1; +} +static void Exa_ManPrintPermFanin( Exa_Man_t * p, int iFanin ) +{ + char Name[16]; + printf( "%s ", Exa_ManObjName(p, iFanin, Name) ); +} +static void Exa_ManPrintFixedPerm( Exa_Man_t * p ) +{ + int i, k; + char Name[16]; + if ( (p->pPars->pPermStr == NULL && p->pPars->pPermFans == NULL) || p->pPars->fSilent ) + return; + printf( "Using fixed input assignment provided by the user %s:\n", p->pPars->pPermStr ? p->pPars->pPermStr : "" ); + for ( i = p->nObjs - 1; i >= p->nVars; i-- ) + { + printf( "%s : ", Exa_ManObjName(p, i, Name) ); + for ( k = 1; k >= 0; k-- ) + Exa_ManPrintPermFanin( p, Exa_ManPermFanin(p, i, k) ); + printf( "\n" ); + } +} +static void Exa_ManPrintPerm( Exa_Man_t * p ) +{ + int i, k, iVar; + char Name[16]; + printf( "The variable permutation is \"" ); + for ( i = p->nVars; i < p->nObjs; i++ ) + { + if ( i > p->nVars ) + printf( "_" ); + for ( k = 1; k >= 0; k-- ) + { + iVar = Exa_ManFindFanin( p, i, k ); + printf( "%s", Exa_ManObjName(p, iVar, Name) ); + } + } + printf( "\".\n" ); +} +static void Exa_ManSaveSolution( Exa_Man_t * p ) +{ + int i, k, Pos = 0; + ABC_FREE( p->pPars->pSolFans ); + p->pPars->pSolFans = ABC_ALLOC( int, 2 * p->nNodes ); + for ( i = p->nVars; i < p->nObjs; i++ ) + for ( k = 1; k >= 0; k-- ) + p->pPars->pSolFans[Pos++] = Exa_ManFindFanin( p, i, k ); +} +static int Exa_ManAddPermConstr( Exa_Man_t * p ) +{ + int i, k, iVar, Lit; + char Name0[16], Name1[16]; + if ( p->pPars->pPermStr == NULL && p->pPars->pPermFans == NULL ) + return 1; + Exa_ManPrintFixedPerm( p ); + for ( i = p->nVars; i < p->nObjs; i++ ) + { + for ( k = 0; k < 2; k++ ) + { + iVar = Exa_ManPermFanin( p, i, k ); + if ( iVar == -1 ) + continue; + if ( iVar < 0 || iVar >= p->nVars || p->VarMarks[i][k][iVar] == 0 ) + { + if ( iVar >= p->nVars && iVar < i && p->VarMarks[i][k][iVar] ) + { + Lit = Abc_Var2Lit( p->VarMarks[i][k][iVar], 0 ); + if ( !sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ) ) + return 0; + continue; + } + printf( "Cannot force node %s fanin %d to object %s because this connection is not available.\n", Exa_ManObjName(p, i, Name0), k, Exa_ManObjName(p, iVar, Name1) ); + return 0; + } + Lit = Abc_Var2Lit( p->VarMarks[i][k][iVar], 0 ); + if ( !sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ) ) + return 0; + } + } + return 1; +} /**Function************************************************************* @@ -720,6 +854,8 @@ static void Exa_ManPrintSolution( Exa_Man_t * p, int fCompl ) static int Exa_ManAddCnfStart( Exa_Man_t * p, int fOnlyAnd ) { int pLits[MAJ_NOBJS], pLits2[2], i, j, k, n, m; + if ( !Exa_ManAddPermConstr(p) ) + return 0; // input constraints for ( i = p->nVars; i < p->nObjs; i++ ) { @@ -849,9 +985,10 @@ static int Exa_ManAddCnf( Exa_Man_t * p, int iMint ) p->iVar += 3*p->nNodes; return 1; } -void Exa_ManExactSynthesis2( Bmc_EsPar_t * pPars ) +int Exa_ManExactSynthesis2( Bmc_EsPar_t * pPars ) { int i, status, iMint = 1; + int fFound = 0; abctime clkTotal = Abc_Clock(); Exa_Man_t * p; int fCompl = 0; word pTruth[64]; Abc_TtReadHex( pTruth, pPars->pTtStr ); @@ -859,8 +996,13 @@ void Exa_ManExactSynthesis2( Bmc_EsPar_t * pPars ) p = Exa_ManAlloc( pPars, pTruth ); if ( pTruth[0] & 1 ) { fCompl = 1; Abc_TtNot( pTruth, p->nWords ); } status = Exa_ManAddCnfStart( p, pPars->fOnlyAnd ); - assert( status ); - printf( "Running exact synthesis for %d-input function with %d two-input gates...\n", p->nVars, p->nNodes ); + if ( !status ) + { + Exa_ManFree( p ); + return 0; + } + if ( !pPars->fSilent ) + printf( "Running exact synthesis for %d-input function with %d two-input gates...\n", p->nVars, p->nNodes ); for ( i = 0; iMint != -1; i++ ) { abctime clk = Abc_Clock(); @@ -878,15 +1020,26 @@ void Exa_ManExactSynthesis2( Bmc_EsPar_t * pPars ) } if ( status == l_False ) { - printf( "The problem has no solution.\n" ); + if ( !pPars->fSilent ) + printf( "The problem has no solution.\n" ); break; } iMint = Exa_ManEval( p ); } if ( iMint == -1 ) - Exa_ManPrintSolution( p, fCompl ); + { + Exa_ManSaveSolution( p ); + if ( !pPars->fSilent ) + { + Exa_ManPrintSolution( p, fCompl ); + Exa_ManPrintPerm( p ); + } + fFound = 1; + } Exa_ManFree( p ); - Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); + if ( !pPars->fSilent ) + Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); + return fFound; } diff --git a/src/sat/cadical/cadical.hpp b/src/sat/cadical/cadical.hpp index 7ceedcec48..4ef09e0c45 100644 --- a/src/sat/cadical/cadical.hpp +++ b/src/sat/cadical/cadical.hpp @@ -1058,6 +1058,7 @@ class Solver { // Extra APIs int clauses (); int conflicts (); + int learned (); private: //==== start of state ==================================================== diff --git a/src/sat/cadical/cadicalSolver.c b/src/sat/cadical/cadicalSolver.c index f27fe19f91..30cd6c68c1 100644 --- a/src/sat/cadical/cadicalSolver.c +++ b/src/sat/cadical/cadicalSolver.c @@ -297,6 +297,21 @@ int cadical_solver_nconflicts(cadical_solver* s) { return ccadical_conflicts((CCaDiCaL*)s->p); } +/**Function************************************************************* + + Synopsis [get number of learned clauses] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int cadical_solver_nlearned(cadical_solver* s) { + return ccadical_learned((CCaDiCaL*)s->p); +} + /**Function************************************************************* diff --git a/src/sat/cadical/cadicalSolver.h b/src/sat/cadical/cadicalSolver.h index 2aec06c2ab..9e6394ff5b 100644 --- a/src/sat/cadical/cadicalSolver.h +++ b/src/sat/cadical/cadicalSolver.h @@ -67,6 +67,7 @@ extern void cadical_solver_setnvars(cadical_solver* s,int n); extern int cadical_solver_get_var_value(cadical_solver* s, int v); extern int cadical_solver_nclauses(cadical_solver* s); extern int cadical_solver_nconflicts(cadical_solver* s); +extern int cadical_solver_nlearned(cadical_solver* s); extern Vec_Int_t * cadical_solve_cnf( Cnf_Dat_t * pCnf, char * pArgs, int nConfs, int nTimeLimit, int fSat, int fUnsat, int fPrintCex, int fVerbose ); ABC_NAMESPACE_HEADER_END diff --git a/src/sat/cadical/cadical_ccadical.cpp b/src/sat/cadical/cadical_ccadical.cpp index 3b61a0373d..a929a4743c 100644 --- a/src/sat/cadical/cadical_ccadical.cpp +++ b/src/sat/cadical/cadical_ccadical.cpp @@ -228,4 +228,8 @@ int ccadical_conflicts(CCaDiCaL *ptr) { return ((Wrapper *) ptr)->solver->conflicts (); } +int ccadical_learned(CCaDiCaL *ptr) { + return ((Wrapper *) ptr)->solver->learned (); +} + ABC_NAMESPACE_IMPL_END diff --git a/src/sat/cadical/cadical_file.cpp b/src/sat/cadical/cadical_file.cpp index d48193e93c..c4225dbeb0 100644 --- a/src/sat/cadical/cadical_file.cpp +++ b/src/sat/cadical/cadical_file.cpp @@ -41,7 +41,7 @@ extern "C" { #endif -#if defined(__APPLE__) || defined(__MACH__) +#if defined(__APPLE__) && defined(__MACH__) extern "C" { #include @@ -293,7 +293,7 @@ FILE *File::read_pipe (Internal *internal, const char *fmt, const int *sig, #if !defined(_WIN32) && !defined(__wasm) -#if defined(__APPLE__) || defined(__MACH__) +#if defined(__APPLE__) && defined(__MACH__) static std::mutex compressed_file_writing_mutex; #endif @@ -312,7 +312,7 @@ FILE *File::write_pipe (Internal *internal, const char *command, char *absolute_command_path = find_program (argv[0]); int pipe_fds[2], out; FILE *res = 0; -#if defined(__APPLE__) || defined(__MACH__) +#if defined(__APPLE__) && defined(__MACH__) compressed_file_writing_mutex.lock (); #endif if (!absolute_command_path) @@ -369,7 +369,7 @@ FILE *File::write_pipe (Internal *internal, const char *command, #ifdef CADICAL_QUIET (void) internal; #endif -#if defined(__APPLE__) || defined(__MACH__) +#if defined(__APPLE__) && defined(__MACH__) if (!res) compressed_file_writing_mutex.unlock (); #endif @@ -475,7 +475,7 @@ void File::close (bool print) { MSG ("closing output pipe to write '%s'", name ()); fclose (file); waitpid (child_pid, 0, 0); -#if defined(__APPLE__) || defined(__MACH__) +#if defined(__APPLE__) && defined(__MACH__) compressed_file_writing_mutex.unlock (); #endif } diff --git a/src/sat/cadical/cadical_solver.cpp b/src/sat/cadical/cadical_solver.cpp index 7dd03e8be3..0efeddaa89 100644 --- a/src/sat/cadical/cadical_solver.cpp +++ b/src/sat/cadical/cadical_solver.cpp @@ -1853,6 +1853,10 @@ int Solver::conflicts () { return internal->stats.conflicts; } +int Solver::learned () { + return internal->stats.learned.clauses; +} + } // namespace CaDiCaL ABC_NAMESPACE_IMPL_END diff --git a/src/sat/cadical/ccadical.h b/src/sat/cadical/ccadical.h index ef442e7a38..b4401305cd 100644 --- a/src/sat/cadical/ccadical.h +++ b/src/sat/cadical/ccadical.h @@ -63,6 +63,7 @@ void ccadical_resize(CCaDiCaL *, int min_max_var); int ccadical_is_inconsistent(CCaDiCaL *); int ccadical_clauses(CCaDiCaL *); int ccadical_conflicts(CCaDiCaL *); +int ccadical_learned(CCaDiCaL *); /*------------------------------------------------------------------------*/ diff --git a/src/sat/cnf/cnfMan.c b/src/sat/cnf/cnfMan.c index 16a4cf2195..cfcc437f16 100644 --- a/src/sat/cnf/cnfMan.c +++ b/src/sat/cnf/cnfMan.c @@ -9,7 +9,7 @@ Synopsis [] Author [Alan Mishchenko] - + Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] @@ -25,13 +25,47 @@ ABC_NAMESPACE_IMPL_START - //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static inline int Cnf_Lit2Var( int Lit ) { return (Lit & 1)? -(Lit >> 1)-1 : (Lit >> 1)+1; } -static inline int Cnf_Lit2Var2( int Lit ) { return (Lit & 1)? -(Lit >> 1) : (Lit >> 1); } +static inline int Cnf_Lit2Var(int Lit) { return (Lit & 1) ? -(Lit >> 1) - 1 : (Lit >> 1) + 1; } +static inline int Cnf_Lit2Var2(int Lit) { return (Lit & 1) ? -(Lit >> 1) : (Lit >> 1); } + +// Emits unit clauses for DIMACS variables that are declared in the header +// but never referenced in any clause. After strash, a primary input that +// is wired directly to a primary output has no fanout into any AND node, +// so the Tseitin encoder leaves the corresponding DIMACS variable without +// any connecting clause. Such a dangling variable silently doubles the +// model count of the output formula, breaking #SAT and uniform sampling. +// Forcing each unreferenced declared variable to a fixed polarity restores +// the original number of satisfying assignments without affecting the set +// of assignments over live variables. Pass pFile == NULL to only count. +static int Cnf_DataWriteDanglingUnitClauses(FILE *pFile, Cnf_Dat_t *p) +{ + char *pUsed; + int *pLit, *pStop; + int i, v, iVar, nExtra = 0; + if (p->nVars <= 0) + return 0; + pUsed = ABC_CALLOC(char, p->nVars + 1); + for (i = 0; i < p->nClauses; i++) + for (pLit = p->pClauses[i], pStop = p->pClauses[i + 1]; pLit < pStop; pLit++) + { + iVar = (*pLit >> 1) + 1; + if (iVar >= 1 && iVar <= p->nVars) + pUsed[iVar] = 1; + } + for (v = 1; v <= p->nVars; v++) + if (!pUsed[v]) + { + if (pFile) + fprintf(pFile, "-%d 0\n", v); + nExtra++; + } + ABC_FREE(pUsed); + return nExtra; +} //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -42,29 +76,29 @@ static inline int Cnf_Lit2Var2( int Lit ) { return (Lit & 1)? -(Lit >> 1) Synopsis [Starts the fraiging manager.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -Cnf_Man_t * Cnf_ManStart() +Cnf_Man_t *Cnf_ManStart() { - Cnf_Man_t * p; + Cnf_Man_t *p; int i; // allocate the manager - p = ABC_ALLOC( Cnf_Man_t, 1 ); - memset( p, 0, sizeof(Cnf_Man_t) ); + p = ABC_ALLOC(Cnf_Man_t, 1); + memset(p, 0, sizeof(Cnf_Man_t)); // derive internal data structures - Cnf_ReadMsops( &p->pSopSizes, &p->pSops ); + Cnf_ReadMsops(&p->pSopSizes, &p->pSops); // allocate memory manager for cuts p->pMemCuts = Aig_MmFlexStart(); p->nMergeLimit = 10; // allocate temporary truth tables - p->pTruths[0] = ABC_ALLOC( unsigned, 4 * Abc_TruthWordNum(p->nMergeLimit) ); - for ( i = 1; i < 4; i++ ) - p->pTruths[i] = p->pTruths[i-1] + Abc_TruthWordNum(p->nMergeLimit); - p->vMemory = Vec_IntAlloc( 1 << 18 ); + p->pTruths[0] = ABC_ALLOC(unsigned, 4 * Abc_TruthWordNum(p->nMergeLimit)); + for (i = 1; i < 4; i++) + p->pTruths[i] = p->pTruths[i - 1] + Abc_TruthWordNum(p->nMergeLimit); + p->vMemory = Vec_IntAlloc(1 << 18); return p; } @@ -73,21 +107,21 @@ Cnf_Man_t * Cnf_ManStart() Synopsis [Stops the fraiging manager.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -void Cnf_ManStop( Cnf_Man_t * p ) +void Cnf_ManStop(Cnf_Man_t *p) { - Vec_IntFree( p->vMemory ); - ABC_FREE( p->pTruths[0] ); - Aig_MmFlexStop( p->pMemCuts, 0 ); - ABC_FREE( p->pSopSizes ); - ABC_FREE( p->pSops[1] ); - ABC_FREE( p->pSops ); - ABC_FREE( p ); + Vec_IntFree(p->vMemory); + ABC_FREE(p->pTruths[0]); + Aig_MmFlexStop(p->pMemCuts, 0); + ABC_FREE(p->pSopSizes); + ABC_FREE(p->pSops[1]); + ABC_FREE(p->pSops); + ABC_FREE(p); } /**Function************************************************************* @@ -95,18 +129,19 @@ void Cnf_ManStop( Cnf_Man_t * p ) Synopsis [Returns the array of CI IDs.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -Vec_Int_t * Cnf_DataCollectPiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p ) +Vec_Int_t *Cnf_DataCollectPiSatNums(Cnf_Dat_t *pCnf, Aig_Man_t *p) { - Aig_Obj_t * pObj; int i; - Vec_Int_t * vCiIds = Vec_IntAlloc( Aig_ManCiNum(p) ); - Aig_ManForEachCi( p, pObj, i ) - Vec_IntPush( vCiIds, pCnf->pVarNums[pObj->Id] ); + Aig_Obj_t *pObj; + int i; + Vec_Int_t *vCiIds = Vec_IntAlloc(Aig_ManCiNum(p)); + Aig_ManForEachCi(p, pObj, i) + Vec_IntPush(vCiIds, pCnf->pVarNums[pObj->Id]); return vCiIds; } @@ -115,25 +150,25 @@ Vec_Int_t * Cnf_DataCollectPiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p ) Synopsis [Allocates the new CNF.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -Cnf_Dat_t * Cnf_DataAlloc( Aig_Man_t * pAig, int nVars, int nClauses, int nLiterals ) +Cnf_Dat_t *Cnf_DataAlloc(Aig_Man_t *pAig, int nVars, int nClauses, int nLiterals) { - Cnf_Dat_t * pCnf; - pCnf = ABC_CALLOC( Cnf_Dat_t, 1 ); + Cnf_Dat_t *pCnf; + pCnf = ABC_CALLOC(Cnf_Dat_t, 1); pCnf->pMan = pAig; pCnf->nVars = nVars; pCnf->nClauses = nClauses; pCnf->nLiterals = nLiterals; - pCnf->pClauses = ABC_ALLOC( int *, nClauses + 1 ); - pCnf->pClauses[0] = ABC_ALLOC( int, nLiterals ); + pCnf->pClauses = ABC_ALLOC(int *, nClauses + 1); + pCnf->pClauses[0] = ABC_ALLOC(int, nLiterals); pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; - if ( pCnf->pVarNums ) - pCnf->pVarNums = ABC_FALLOC( int, Aig_ManObjNumMax(pAig) ); + if (pCnf->pVarNums) + pCnf->pVarNums = ABC_FALLOC(int, Aig_ManObjNumMax(pAig)); return pCnf; } @@ -142,54 +177,55 @@ Cnf_Dat_t * Cnf_DataAlloc( Aig_Man_t * pAig, int nVars, int nClauses, int nLiter Synopsis [Allocates the new CNF.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -Cnf_Dat_t * Cnf_DataDup( Cnf_Dat_t * p ) +Cnf_Dat_t *Cnf_DataDup(Cnf_Dat_t *p) { - Cnf_Dat_t * pCnf; + Cnf_Dat_t *pCnf; int i; - pCnf = Cnf_DataAlloc( p->pMan, p->nVars, p->nClauses, p->nLiterals ); - memcpy( pCnf->pClauses[0], p->pClauses[0], sizeof(int) * p->nLiterals ); - if ( p->pVarNums ) - memcpy( pCnf->pVarNums, p->pVarNums, sizeof(int) * Aig_ManObjNumMax(p->pMan) ); - for ( i = 1; i < p->nClauses; i++ ) + pCnf = Cnf_DataAlloc(p->pMan, p->nVars, p->nClauses, p->nLiterals); + memcpy(pCnf->pClauses[0], p->pClauses[0], sizeof(int) * p->nLiterals); + if (p->pVarNums) + memcpy(pCnf->pVarNums, p->pVarNums, sizeof(int) * Aig_ManObjNumMax(p->pMan)); + for (i = 1; i < p->nClauses; i++) pCnf->pClauses[i] = pCnf->pClauses[0] + (p->pClauses[i] - p->pClauses[0]); return pCnf; } -Cnf_Dat_t * Cnf_DataDupCof( Cnf_Dat_t * p, int Lit ) +Cnf_Dat_t *Cnf_DataDupCof(Cnf_Dat_t *p, int Lit) { - Cnf_Dat_t * pCnf; + Cnf_Dat_t *pCnf; int i; - pCnf = Cnf_DataAlloc( p->pMan, p->nVars, p->nClauses+1, p->nLiterals+1 ); - memcpy( pCnf->pClauses[0], p->pClauses[0], sizeof(int) * p->nLiterals ); - if ( pCnf->pVarNums ) - memcpy( pCnf->pVarNums, p->pVarNums, sizeof(int) * Aig_ManObjNumMax(p->pMan) ); - for ( i = 1; i < p->nClauses; i++ ) + pCnf = Cnf_DataAlloc(p->pMan, p->nVars, p->nClauses + 1, p->nLiterals + 1); + memcpy(pCnf->pClauses[0], p->pClauses[0], sizeof(int) * p->nLiterals); + if (pCnf->pVarNums) + memcpy(pCnf->pVarNums, p->pVarNums, sizeof(int) * Aig_ManObjNumMax(p->pMan)); + for (i = 1; i < p->nClauses; i++) pCnf->pClauses[i] = pCnf->pClauses[0] + (p->pClauses[i] - p->pClauses[0]); pCnf->pClauses[p->nClauses] = pCnf->pClauses[0] + p->nLiterals; pCnf->pClauses[p->nClauses][0] = Lit; - assert( pCnf->pClauses[p->nClauses+1] == pCnf->pClauses[0] + p->nLiterals+1 ); + assert(pCnf->pClauses[p->nClauses + 1] == pCnf->pClauses[0] + p->nLiterals + 1); return pCnf; } -Cnf_Dat_t * Cnf_DataDupCofArray( Cnf_Dat_t * p, Vec_Int_t * vLits ) +Cnf_Dat_t *Cnf_DataDupCofArray(Cnf_Dat_t *p, Vec_Int_t *vLits) { - Cnf_Dat_t * pCnf; + Cnf_Dat_t *pCnf; int i, iLit; - pCnf = Cnf_DataAlloc( p->pMan, p->nVars, p->nClauses+Vec_IntSize(vLits), p->nLiterals+Vec_IntSize(vLits) ); - memcpy( pCnf->pClauses[0], p->pClauses[0], sizeof(int) * p->nLiterals ); - if ( pCnf->pVarNums ) - memcpy( pCnf->pVarNums, p->pVarNums, sizeof(int) * Aig_ManObjNumMax(p->pMan) ); - for ( i = 1; i < p->nClauses; i++ ) + pCnf = Cnf_DataAlloc(p->pMan, p->nVars, p->nClauses + Vec_IntSize(vLits), p->nLiterals + Vec_IntSize(vLits)); + memcpy(pCnf->pClauses[0], p->pClauses[0], sizeof(int) * p->nLiterals); + if (pCnf->pVarNums) + memcpy(pCnf->pVarNums, p->pVarNums, sizeof(int) * Aig_ManObjNumMax(p->pMan)); + for (i = 1; i < p->nClauses; i++) pCnf->pClauses[i] = pCnf->pClauses[0] + (p->pClauses[i] - p->pClauses[0]); - Vec_IntForEachEntry( vLits, iLit, i ) { - pCnf->pClauses[p->nClauses+i] = pCnf->pClauses[0] + p->nLiterals+i; - pCnf->pClauses[p->nClauses+i][0] = iLit; + Vec_IntForEachEntry(vLits, iLit, i) + { + pCnf->pClauses[p->nClauses + i] = pCnf->pClauses[0] + p->nLiterals + i; + pCnf->pClauses[p->nClauses + i][0] = iLit; } - assert( pCnf->pClauses[p->nClauses+Vec_IntSize(vLits)] == pCnf->pClauses[0] + p->nLiterals+Vec_IntSize(vLits) ); + assert(pCnf->pClauses[p->nClauses + Vec_IntSize(vLits)] == pCnf->pClauses[0] + p->nLiterals + Vec_IntSize(vLits)); return pCnf; } @@ -198,24 +234,24 @@ Cnf_Dat_t * Cnf_DataDupCofArray( Cnf_Dat_t * p, Vec_Int_t * vLits ) Synopsis [] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -void Cnf_DataFree( Cnf_Dat_t * p ) +void Cnf_DataFree(Cnf_Dat_t *p) { - if ( p == NULL ) + if (p == NULL) return; - Vec_IntFreeP( &p->vMapping ); - ABC_FREE( p->pClaPols ); - ABC_FREE( p->pObj2Clause ); - ABC_FREE( p->pObj2Count ); - ABC_FREE( p->pClauses[0] ); - ABC_FREE( p->pClauses ); - ABC_FREE( p->pVarNums ); - ABC_FREE( p ); + Vec_IntFreeP(&p->vMapping); + ABC_FREE(p->pClaPols); + ABC_FREE(p->pObj2Clause); + ABC_FREE(p->pObj2Count); + ABC_FREE(p->pClauses[0]); + ABC_FREE(p->pClauses); + ABC_FREE(p->pVarNums); + ABC_FREE(p); } /**Function************************************************************* @@ -223,40 +259,39 @@ void Cnf_DataFree( Cnf_Dat_t * p ) Synopsis [] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -void Cnf_DataLift( Cnf_Dat_t * p, int nVarsPlus ) +void Cnf_DataLift(Cnf_Dat_t *p, int nVarsPlus) { - Aig_Obj_t * pObj; + Aig_Obj_t *pObj; int v; - if ( p->pMan ) + if (p->pMan) { - Aig_ManForEachObj( p->pMan, pObj, v ) - if ( p->pVarNums[pObj->Id] >= 0 ) - p->pVarNums[pObj->Id] += nVarsPlus; + Aig_ManForEachObj(p->pMan, pObj, v) if (p->pVarNums[pObj->Id] >= 0) + p->pVarNums[pObj->Id] += nVarsPlus; } - for ( v = 0; v < p->nLiterals; v++ ) - p->pClauses[0][v] += 2*nVarsPlus; + for (v = 0; v < p->nLiterals; v++) + p->pClauses[0][v] += 2 * nVarsPlus; } -void Cnf_DataCollectFlipLits( Cnf_Dat_t * p, int iFlipVar, Vec_Int_t * vFlips ) +void Cnf_DataCollectFlipLits(Cnf_Dat_t *p, int iFlipVar, Vec_Int_t *vFlips) { int v; - assert( p->pMan == NULL ); - Vec_IntClear( vFlips ); - for ( v = 0; v < p->nLiterals; v++ ) - if ( Abc_Lit2Var(p->pClauses[0][v]) == iFlipVar ) - Vec_IntPush( vFlips, v ); + assert(p->pMan == NULL); + Vec_IntClear(vFlips); + for (v = 0; v < p->nLiterals; v++) + if (Abc_Lit2Var(p->pClauses[0][v]) == iFlipVar) + Vec_IntPush(vFlips, v); } -void Cnf_DataLiftAndFlipLits( Cnf_Dat_t * p, int nVarsPlus, Vec_Int_t * vLits ) +void Cnf_DataLiftAndFlipLits(Cnf_Dat_t *p, int nVarsPlus, Vec_Int_t *vLits) { int i, iLit; - assert( p->pMan == NULL ); - Vec_IntForEachEntry( vLits, iLit, i ) - p->pClauses[0][iLit] = Abc_LitNot(p->pClauses[0][iLit]) + 2*nVarsPlus; + assert(p->pMan == NULL); + Vec_IntForEachEntry(vLits, iLit, i) + p->pClauses[0][iLit] = Abc_LitNot(p->pClauses[0][iLit]) + 2 * nVarsPlus; } /**Function************************************************************* @@ -264,24 +299,24 @@ void Cnf_DataLiftAndFlipLits( Cnf_Dat_t * p, int nVarsPlus, Vec_Int_t * vLits ) Synopsis [] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -void Cnf_DataPrint( Cnf_Dat_t * p, int fReadable ) +void Cnf_DataPrint(Cnf_Dat_t *p, int fReadable) { - FILE * pFile = stdout; - int * pLit, * pStop, i; - fprintf( pFile, "p cnf %d %d\n", p->nVars, p->nClauses ); - for ( i = 0; i < p->nClauses; i++ ) + FILE *pFile = stdout; + int *pLit, *pStop, i; + fprintf(pFile, "p cnf %d %d\n", p->nVars, p->nClauses); + for (i = 0; i < p->nClauses; i++) { - for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ ) - fprintf( pFile, "%s%d ", Abc_LitIsCompl(*pLit) ? "-":"", fReadable? Abc_Lit2Var(*pLit) : Abc_Lit2Var(*pLit)+1 ); - fprintf( pFile, "\n" ); + for (pLit = p->pClauses[i], pStop = p->pClauses[i + 1]; pLit < pStop; pLit++) + fprintf(pFile, "%s%d ", Abc_LitIsCompl(*pLit) ? "-" : "", fReadable ? Abc_Lit2Var(*pLit) : Abc_Lit2Var(*pLit) + 1); + fprintf(pFile, "\n"); } - fprintf( pFile, "\n" ); + fprintf(pFile, "\n"); } /**Function************************************************************* @@ -289,88 +324,88 @@ void Cnf_DataPrint( Cnf_Dat_t * p, int fReadable ) Synopsis [Writes CNF into a file.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -void Cnf_DataWriteIntoFileGz( Cnf_Dat_t * p, char * pFileName, int fReadable, Vec_Int_t * vForAlls, Vec_Int_t * vExists ) +void Cnf_DataWriteIntoFileGz(Cnf_Dat_t *p, char *pFileName, int fReadable, Vec_Int_t *vForAlls, Vec_Int_t *vExists) { gzFile pFile; - int * pLit, * pStop, i, VarId; - pFile = gzopen( pFileName, "wb" ); - if ( pFile == NULL ) + int *pLit, *pStop, i, VarId; + pFile = gzopen(pFileName, "wb"); + if (pFile == NULL) { - printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" ); + printf("Cnf_WriteIntoFile(): Output file cannot be opened.\n"); return; } - gzprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" ); - gzprintf( pFile, "p cnf %d %d\n", p->nVars, p->nClauses ); - if ( vForAlls ) + gzprintf(pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n"); + gzprintf(pFile, "p cnf %d %d\n", p->nVars, p->nClauses); + if (vForAlls) { - gzprintf( pFile, "a " ); - Vec_IntForEachEntry( vForAlls, VarId, i ) - gzprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); - gzprintf( pFile, "0\n" ); + gzprintf(pFile, "a "); + Vec_IntForEachEntry(vForAlls, VarId, i) + gzprintf(pFile, "%d ", fReadable ? VarId : VarId + 1); + gzprintf(pFile, "0\n"); } - if ( vExists ) + if (vExists) { - gzprintf( pFile, "e " ); - Vec_IntForEachEntry( vExists, VarId, i ) - gzprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); - gzprintf( pFile, "0\n" ); + gzprintf(pFile, "e "); + Vec_IntForEachEntry(vExists, VarId, i) + gzprintf(pFile, "%d ", fReadable ? VarId : VarId + 1); + gzprintf(pFile, "0\n"); } - for ( i = 0; i < p->nClauses; i++ ) + for (i = 0; i < p->nClauses; i++) { - for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ ) - gzprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) ); - gzprintf( pFile, "0\n" ); + for (pLit = p->pClauses[i], pStop = p->pClauses[i + 1]; pLit < pStop; pLit++) + gzprintf(pFile, "%d ", fReadable ? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit)); + gzprintf(pFile, "0\n"); } - gzprintf( pFile, "\n" ); - gzclose( pFile ); + gzprintf(pFile, "\n"); + gzclose(pFile); } -void Cnf_DataWriteIntoFileInvGz( Cnf_Dat_t * p, char * pFileName, int fReadable, Vec_Int_t * vExists1, Vec_Int_t * vForAlls, Vec_Int_t * vExists2 ) +void Cnf_DataWriteIntoFileInvGz(Cnf_Dat_t *p, char *pFileName, int fReadable, Vec_Int_t *vExists1, Vec_Int_t *vForAlls, Vec_Int_t *vExists2) { gzFile pFile; - int * pLit, * pStop, i, VarId; - pFile = gzopen( pFileName, "wb" ); - if ( pFile == NULL ) + int *pLit, *pStop, i, VarId; + pFile = gzopen(pFileName, "wb"); + if (pFile == NULL) { - printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" ); + printf("Cnf_WriteIntoFile(): Output file cannot be opened.\n"); return; } - gzprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" ); - gzprintf( pFile, "p cnf %d %d\n", p->nVars, p->nClauses ); - if ( vExists1 ) + gzprintf(pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n"); + gzprintf(pFile, "p cnf %d %d\n", p->nVars, p->nClauses); + if (vExists1) { - gzprintf( pFile, "e " ); - Vec_IntForEachEntry( vExists1, VarId, i ) - gzprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); - gzprintf( pFile, "0\n" ); + gzprintf(pFile, "e "); + Vec_IntForEachEntry(vExists1, VarId, i) + gzprintf(pFile, "%d ", fReadable ? VarId : VarId + 1); + gzprintf(pFile, "0\n"); } - if ( vForAlls ) + if (vForAlls) { - gzprintf( pFile, "a " ); - Vec_IntForEachEntry( vForAlls, VarId, i ) - gzprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); - gzprintf( pFile, "0\n" ); + gzprintf(pFile, "a "); + Vec_IntForEachEntry(vForAlls, VarId, i) + gzprintf(pFile, "%d ", fReadable ? VarId : VarId + 1); + gzprintf(pFile, "0\n"); } - if ( vExists2 ) + if (vExists2) { - gzprintf( pFile, "e " ); - Vec_IntForEachEntry( vExists2, VarId, i ) - gzprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); - gzprintf( pFile, "0\n" ); + gzprintf(pFile, "e "); + Vec_IntForEachEntry(vExists2, VarId, i) + gzprintf(pFile, "%d ", fReadable ? VarId : VarId + 1); + gzprintf(pFile, "0\n"); } - for ( i = 0; i < p->nClauses; i++ ) + for (i = 0; i < p->nClauses; i++) { - for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ ) - gzprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) ); - gzprintf( pFile, "0\n" ); + for (pLit = p->pClauses[i], pStop = p->pClauses[i + 1]; pLit < pStop; pLit++) + gzprintf(pFile, "%d ", fReadable ? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit)); + gzprintf(pFile, "0\n"); } - gzprintf( pFile, "\n" ); - gzclose( pFile ); + gzprintf(pFile, "\n"); + gzclose(pFile); } /**Function************************************************************* @@ -378,98 +413,101 @@ void Cnf_DataWriteIntoFileInvGz( Cnf_Dat_t * p, char * pFileName, int fReadable, Synopsis [Writes CNF into a file.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable, Vec_Int_t * vForAlls, Vec_Int_t * vExists ) +void Cnf_DataWriteIntoFile(Cnf_Dat_t *p, char *pFileName, int fReadable, Vec_Int_t *vForAlls, Vec_Int_t *vExists) { - FILE * pFile; - int * pLit, * pStop, i, VarId; - if ( !strncmp(pFileName+strlen(pFileName)-3,".gz",3) ) + FILE *pFile; + int *pLit, *pStop, i, VarId, nExtra; + if (!strncmp(pFileName + strlen(pFileName) - 3, ".gz", 3)) { - Cnf_DataWriteIntoFileGz( p, pFileName, fReadable, vForAlls, vExists ); + Cnf_DataWriteIntoFileGz(p, pFileName, fReadable, vForAlls, vExists); return; } - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) + pFile = fopen(pFileName, "w"); + if (pFile == NULL) { - printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" ); + printf("Cnf_WriteIntoFile(): Output file cannot be opened.\n"); return; } - fprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" ); - fprintf( pFile, "p cnf %d %d\n", p->nVars, p->nClauses ); - if ( vForAlls ) + nExtra = Cnf_DataWriteDanglingUnitClauses(NULL, p); + fprintf(pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n"); + fprintf(pFile, "p cnf %d %d\n", p->nVars, p->nClauses + nExtra); + if (vForAlls) { - fprintf( pFile, "a " ); - Vec_IntForEachEntry( vForAlls, VarId, i ) - fprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); - fprintf( pFile, "0\n" ); + fprintf(pFile, "a "); + Vec_IntForEachEntry(vForAlls, VarId, i) + fprintf(pFile, "%d ", fReadable ? VarId : VarId + 1); + fprintf(pFile, "0\n"); } - if ( vExists ) + if (vExists) { - fprintf( pFile, "e " ); - Vec_IntForEachEntry( vExists, VarId, i ) - fprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); - fprintf( pFile, "0\n" ); + fprintf(pFile, "e "); + Vec_IntForEachEntry(vExists, VarId, i) + fprintf(pFile, "%d ", fReadable ? VarId : VarId + 1); + fprintf(pFile, "0\n"); } - for ( i = 0; i < p->nClauses; i++ ) + for (i = 0; i < p->nClauses; i++) { - for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ ) - fprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) ); - fprintf( pFile, "0\n" ); + for (pLit = p->pClauses[i], pStop = p->pClauses[i + 1]; pLit < pStop; pLit++) + fprintf(pFile, "%d ", fReadable ? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit)); + fprintf(pFile, "0\n"); } - fprintf( pFile, "\n" ); - fclose( pFile ); + if (nExtra) + Cnf_DataWriteDanglingUnitClauses(pFile, p); + fprintf(pFile, "\n"); + fclose(pFile); } -void Cnf_DataWriteIntoFileInv( Cnf_Dat_t * p, char * pFileName, int fReadable, Vec_Int_t * vExists1, Vec_Int_t * vForAlls, Vec_Int_t * vExists2 ) +void Cnf_DataWriteIntoFileInv(Cnf_Dat_t *p, char *pFileName, int fReadable, Vec_Int_t *vExists1, Vec_Int_t *vForAlls, Vec_Int_t *vExists2) { - FILE * pFile; - int * pLit, * pStop, i, VarId; - if ( !strncmp(pFileName+strlen(pFileName)-3,".gz",3) ) + FILE *pFile; + int *pLit, *pStop, i, VarId; + if (!strncmp(pFileName + strlen(pFileName) - 3, ".gz", 3)) { - Cnf_DataWriteIntoFileInvGz( p, pFileName, fReadable, vExists1, vForAlls, vExists2 ); + Cnf_DataWriteIntoFileInvGz(p, pFileName, fReadable, vExists1, vForAlls, vExists2); return; } - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) + pFile = fopen(pFileName, "w"); + if (pFile == NULL) { - printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" ); + printf("Cnf_WriteIntoFile(): Output file cannot be opened.\n"); return; } - fprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" ); - fprintf( pFile, "p cnf %d %d\n", p->nVars, p->nClauses ); - if ( vExists1 ) + fprintf(pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n"); + fprintf(pFile, "p cnf %d %d\n", p->nVars, p->nClauses); + if (vExists1) { - fprintf( pFile, "e " ); - Vec_IntForEachEntry( vExists1, VarId, i ) - fprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); - fprintf( pFile, "0\n" ); + fprintf(pFile, "e "); + Vec_IntForEachEntry(vExists1, VarId, i) + fprintf(pFile, "%d ", fReadable ? VarId : VarId + 1); + fprintf(pFile, "0\n"); } - if ( vForAlls ) + if (vForAlls) { - fprintf( pFile, "a " ); - Vec_IntForEachEntry( vForAlls, VarId, i ) - fprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); - fprintf( pFile, "0\n" ); + fprintf(pFile, "a "); + Vec_IntForEachEntry(vForAlls, VarId, i) + fprintf(pFile, "%d ", fReadable ? VarId : VarId + 1); + fprintf(pFile, "0\n"); } - if ( vExists2 ) + if (vExists2) { - fprintf( pFile, "e " ); - Vec_IntForEachEntry( vExists2, VarId, i ) - fprintf( pFile, "%d ", fReadable? VarId : VarId+1 ); - fprintf( pFile, "0\n" ); + fprintf(pFile, "e "); + Vec_IntForEachEntry(vExists2, VarId, i) + fprintf(pFile, "%d ", fReadable ? VarId : VarId + 1); + fprintf(pFile, "0\n"); } - for ( i = 0; i < p->nClauses; i++ ) + for (i = 0; i < p->nClauses; i++) { - for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ ) - fprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) ); - fprintf( pFile, "0\n" ); + for (pLit = p->pClauses[i], pStop = p->pClauses[i + 1]; pLit < pStop; pLit++) + fprintf(pFile, "%d ", fReadable ? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit)); + fprintf(pFile, "0\n"); } - fprintf( pFile, "\n" ); - fclose( pFile ); + fprintf(pFile, "\n"); + fclose(pFile); } /**Function************************************************************* @@ -477,89 +515,89 @@ void Cnf_DataWriteIntoFileInv( Cnf_Dat_t * p, char * pFileName, int fReadable, V Synopsis [Writes CNF into a file.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -void * Cnf_DataWriteIntoSolverInt( void * pSolver, Cnf_Dat_t * p, int nFrames, int fInit ) +void *Cnf_DataWriteIntoSolverInt(void *pSolver, Cnf_Dat_t *p, int nFrames, int fInit) { - sat_solver * pSat = (sat_solver *)pSolver; + sat_solver *pSat = (sat_solver *)pSolver; int i, f, status; - assert( nFrames > 0 ); - assert( pSat ); -// pSat = sat_solver_new(); - sat_solver_setnvars( pSat, p->nVars * nFrames ); - for ( i = 0; i < p->nClauses; i++ ) + assert(nFrames > 0); + assert(pSat); + // pSat = sat_solver_new(); + sat_solver_setnvars(pSat, p->nVars * nFrames); + for (i = 0; i < p->nClauses; i++) { - if ( !sat_solver_addclause( pSat, p->pClauses[i], p->pClauses[i+1] ) ) + if (!sat_solver_addclause(pSat, p->pClauses[i], p->pClauses[i + 1])) { - sat_solver_delete( pSat ); + sat_solver_delete(pSat); return NULL; } } - if ( nFrames > 1 ) + if (nFrames > 1) { - Aig_Obj_t * pObjLo, * pObjLi; - int nLitsAll, * pLits, Lits[2]; + Aig_Obj_t *pObjLo, *pObjLi; + int nLitsAll, *pLits, Lits[2]; nLitsAll = 2 * p->nVars; pLits = p->pClauses[0]; - for ( f = 1; f < nFrames; f++ ) + for (f = 1; f < nFrames; f++) { // add equality of register inputs/outputs for different timeframes - Aig_ManForEachLiLoSeq( p->pMan, pObjLi, pObjLo, i ) + Aig_ManForEachLiLoSeq(p->pMan, pObjLi, pObjLo, i) { - Lits[0] = (f-1)*nLitsAll + toLitCond( p->pVarNums[pObjLi->Id], 0 ); - Lits[1] = f *nLitsAll + toLitCond( p->pVarNums[pObjLo->Id], 1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + Lits[0] = (f - 1) * nLitsAll + toLitCond(p->pVarNums[pObjLi->Id], 0); + Lits[1] = f * nLitsAll + toLitCond(p->pVarNums[pObjLo->Id], 1); + if (!sat_solver_addclause(pSat, Lits, Lits + 2)) { - sat_solver_delete( pSat ); + sat_solver_delete(pSat); return NULL; } Lits[0]++; Lits[1]--; - if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + if (!sat_solver_addclause(pSat, Lits, Lits + 2)) { - sat_solver_delete( pSat ); + sat_solver_delete(pSat); return NULL; } } // add clauses for the next timeframe - for ( i = 0; i < p->nLiterals; i++ ) + for (i = 0; i < p->nLiterals; i++) pLits[i] += nLitsAll; - for ( i = 0; i < p->nClauses; i++ ) + for (i = 0; i < p->nClauses; i++) { - if ( !sat_solver_addclause( pSat, p->pClauses[i], p->pClauses[i+1] ) ) + if (!sat_solver_addclause(pSat, p->pClauses[i], p->pClauses[i + 1])) { - sat_solver_delete( pSat ); + sat_solver_delete(pSat); return NULL; } } } // return literals to their original state - nLitsAll = (f-1) * nLitsAll; - for ( i = 0; i < p->nLiterals; i++ ) + nLitsAll = (f - 1) * nLitsAll; + for (i = 0; i < p->nLiterals; i++) pLits[i] -= nLitsAll; } - if ( fInit ) + if (fInit) { - Aig_Obj_t * pObjLo; + Aig_Obj_t *pObjLo; int Lits[1]; - Aig_ManForEachLoSeq( p->pMan, pObjLo, i ) + Aig_ManForEachLoSeq(p->pMan, pObjLo, i) { - Lits[0] = toLitCond( p->pVarNums[pObjLo->Id], 1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 1 ) ) + Lits[0] = toLitCond(p->pVarNums[pObjLo->Id], 1); + if (!sat_solver_addclause(pSat, Lits, Lits + 1)) { - sat_solver_delete( pSat ); + sat_solver_delete(pSat); return NULL; } } } status = sat_solver_simplify(pSat); - if ( status == 0 ) + if (status == 0) { - sat_solver_delete( pSat ); + sat_solver_delete(pSat); return NULL; } return pSat; @@ -570,15 +608,15 @@ void * Cnf_DataWriteIntoSolverInt( void * pSolver, Cnf_Dat_t * p, int nFrames, i Synopsis [Writes CNF into a file.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit ) +void *Cnf_DataWriteIntoSolver(Cnf_Dat_t *p, int nFrames, int fInit) { - return Cnf_DataWriteIntoSolverInt( sat_solver_new(), p, nFrames, fInit ); + return Cnf_DataWriteIntoSolverInt(sat_solver_new(), p, nFrames, fInit); } /**Function************************************************************* @@ -586,88 +624,88 @@ void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit ) Synopsis [Writes CNF into a file.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -void * Cnf_DataWriteIntoSolver2( Cnf_Dat_t * p, int nFrames, int fInit ) +void *Cnf_DataWriteIntoSolver2(Cnf_Dat_t *p, int nFrames, int fInit) { - sat_solver2 * pSat; + sat_solver2 *pSat; int i, f, status; - assert( nFrames > 0 ); + assert(nFrames > 0); pSat = sat_solver2_new(); - sat_solver2_setnvars( pSat, p->nVars * nFrames ); - for ( i = 0; i < p->nClauses; i++ ) + sat_solver2_setnvars(pSat, p->nVars * nFrames); + for (i = 0; i < p->nClauses; i++) { - if ( !sat_solver2_addclause( pSat, p->pClauses[i], p->pClauses[i+1], 0 ) ) + if (!sat_solver2_addclause(pSat, p->pClauses[i], p->pClauses[i + 1], 0)) { - sat_solver2_delete( pSat ); + sat_solver2_delete(pSat); return NULL; } } - if ( nFrames > 1 ) + if (nFrames > 1) { - Aig_Obj_t * pObjLo, * pObjLi; - int nLitsAll, * pLits, Lits[2]; + Aig_Obj_t *pObjLo, *pObjLi; + int nLitsAll, *pLits, Lits[2]; nLitsAll = 2 * p->nVars; pLits = p->pClauses[0]; - for ( f = 1; f < nFrames; f++ ) + for (f = 1; f < nFrames; f++) { // add equality of register inputs/outputs for different timeframes - Aig_ManForEachLiLoSeq( p->pMan, pObjLi, pObjLo, i ) + Aig_ManForEachLiLoSeq(p->pMan, pObjLi, pObjLo, i) { - Lits[0] = (f-1)*nLitsAll + toLitCond( p->pVarNums[pObjLi->Id], 0 ); - Lits[1] = f *nLitsAll + toLitCond( p->pVarNums[pObjLo->Id], 1 ); - if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) ) + Lits[0] = (f - 1) * nLitsAll + toLitCond(p->pVarNums[pObjLi->Id], 0); + Lits[1] = f * nLitsAll + toLitCond(p->pVarNums[pObjLo->Id], 1); + if (!sat_solver2_addclause(pSat, Lits, Lits + 2, 0)) { - sat_solver2_delete( pSat ); + sat_solver2_delete(pSat); return NULL; } Lits[0]++; Lits[1]--; - if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) ) + if (!sat_solver2_addclause(pSat, Lits, Lits + 2, 0)) { - sat_solver2_delete( pSat ); + sat_solver2_delete(pSat); return NULL; } } // add clauses for the next timeframe - for ( i = 0; i < p->nLiterals; i++ ) + for (i = 0; i < p->nLiterals; i++) pLits[i] += nLitsAll; - for ( i = 0; i < p->nClauses; i++ ) + for (i = 0; i < p->nClauses; i++) { - if ( !sat_solver2_addclause( pSat, p->pClauses[i], p->pClauses[i+1], 0 ) ) + if (!sat_solver2_addclause(pSat, p->pClauses[i], p->pClauses[i + 1], 0)) { - sat_solver2_delete( pSat ); + sat_solver2_delete(pSat); return NULL; } } } // return literals to their original state - nLitsAll = (f-1) * nLitsAll; - for ( i = 0; i < p->nLiterals; i++ ) + nLitsAll = (f - 1) * nLitsAll; + for (i = 0; i < p->nLiterals; i++) pLits[i] -= nLitsAll; } - if ( fInit ) + if (fInit) { - Aig_Obj_t * pObjLo; + Aig_Obj_t *pObjLo; int Lits[1]; - Aig_ManForEachLoSeq( p->pMan, pObjLo, i ) + Aig_ManForEachLoSeq(p->pMan, pObjLo, i) { - Lits[0] = toLitCond( p->pVarNums[pObjLo->Id], 1 ); - if ( !sat_solver2_addclause( pSat, Lits, Lits + 1, 0 ) ) + Lits[0] = toLitCond(p->pVarNums[pObjLo->Id], 1); + if (!sat_solver2_addclause(pSat, Lits, Lits + 1, 0)) { - sat_solver2_delete( pSat ); + sat_solver2_delete(pSat); return NULL; } } } status = sat_solver2_simplify(pSat); - if ( status == 0 ) + if (status == 0) { - sat_solver2_delete( pSat ); + sat_solver2_delete(pSat); return NULL; } return pSat; @@ -678,26 +716,26 @@ void * Cnf_DataWriteIntoSolver2( Cnf_Dat_t * p, int nFrames, int fInit ) Synopsis [Adds the OR-clause.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -int Cnf_DataWriteOrClause( void * p, Cnf_Dat_t * pCnf ) +int Cnf_DataWriteOrClause(void *p, Cnf_Dat_t *pCnf) { - sat_solver * pSat = (sat_solver *)p; - Aig_Obj_t * pObj; - int i, * pLits; - pLits = ABC_ALLOC( int, Aig_ManCoNum(pCnf->pMan) ); - Aig_ManForEachCo( pCnf->pMan, pObj, i ) - pLits[i] = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); - if ( !sat_solver_addclause( pSat, pLits, pLits + Aig_ManCoNum(pCnf->pMan) ) ) - { - ABC_FREE( pLits ); + sat_solver *pSat = (sat_solver *)p; + Aig_Obj_t *pObj; + int i, *pLits; + pLits = ABC_ALLOC(int, Aig_ManCoNum(pCnf->pMan)); + Aig_ManForEachCo(pCnf->pMan, pObj, i) + pLits[i] = toLitCond(pCnf->pVarNums[pObj->Id], 0); + if (!sat_solver_addclause(pSat, pLits, pLits + Aig_ManCoNum(pCnf->pMan))) + { + ABC_FREE(pLits); return 0; } - ABC_FREE( pLits ); + ABC_FREE(pLits); return 1; } @@ -706,26 +744,26 @@ int Cnf_DataWriteOrClause( void * p, Cnf_Dat_t * pCnf ) Synopsis [Adds the OR-clause.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -int Cnf_DataWriteOrClause2( void * p, Cnf_Dat_t * pCnf ) +int Cnf_DataWriteOrClause2(void *p, Cnf_Dat_t *pCnf) { - sat_solver2 * pSat = (sat_solver2 *)p; - Aig_Obj_t * pObj; - int i, * pLits; - pLits = ABC_ALLOC( int, Aig_ManCoNum(pCnf->pMan) ); - Aig_ManForEachCo( pCnf->pMan, pObj, i ) - pLits[i] = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); - if ( !sat_solver2_addclause( pSat, pLits, pLits + Aig_ManCoNum(pCnf->pMan), 0 ) ) - { - ABC_FREE( pLits ); + sat_solver2 *pSat = (sat_solver2 *)p; + Aig_Obj_t *pObj; + int i, *pLits; + pLits = ABC_ALLOC(int, Aig_ManCoNum(pCnf->pMan)); + Aig_ManForEachCo(pCnf->pMan, pObj, i) + pLits[i] = toLitCond(pCnf->pVarNums[pObj->Id], 0); + if (!sat_solver2_addclause(pSat, pLits, pLits + Aig_ManCoNum(pCnf->pMan), 0)) + { + ABC_FREE(pLits); return 0; } - ABC_FREE( pLits ); + ABC_FREE(pLits); return 1; } @@ -734,21 +772,21 @@ int Cnf_DataWriteOrClause2( void * p, Cnf_Dat_t * pCnf ) Synopsis [Adds the OR-clause.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -int Cnf_DataWriteAndClauses( void * p, Cnf_Dat_t * pCnf ) +int Cnf_DataWriteAndClauses(void *p, Cnf_Dat_t *pCnf) { - sat_solver * pSat = (sat_solver *)p; - Aig_Obj_t * pObj; + sat_solver *pSat = (sat_solver *)p; + Aig_Obj_t *pObj; int i, Lit; - Aig_ManForEachCo( pCnf->pMan, pObj, i ) + Aig_ManForEachCo(pCnf->pMan, pObj, i) { - Lit = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); - if ( !sat_solver_addclause( pSat, &Lit, &Lit+1 ) ) + Lit = toLitCond(pCnf->pVarNums[pObj->Id], 0); + if (!sat_solver_addclause(pSat, &Lit, &Lit + 1)) return 0; } return 1; @@ -759,35 +797,35 @@ int Cnf_DataWriteAndClauses( void * p, Cnf_Dat_t * pCnf ) Synopsis [Transforms polarity of the internal veriables.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -void Cnf_DataTranformPolarity( Cnf_Dat_t * pCnf, int fTransformPos ) +void Cnf_DataTranformPolarity(Cnf_Dat_t *pCnf, int fTransformPos) { - Aig_Obj_t * pObj; - int * pVarToPol; + Aig_Obj_t *pObj; + int *pVarToPol; int i, iVar; // create map from the variable number to its polarity - pVarToPol = ABC_CALLOC( int, pCnf->nVars ); - Aig_ManForEachObj( pCnf->pMan, pObj, i ) + pVarToPol = ABC_CALLOC(int, pCnf->nVars); + Aig_ManForEachObj(pCnf->pMan, pObj, i) { - if ( !fTransformPos && Aig_ObjIsCo(pObj) ) + if (!fTransformPos && Aig_ObjIsCo(pObj)) continue; - if ( pCnf->pVarNums[pObj->Id] >= 0 ) - pVarToPol[ pCnf->pVarNums[pObj->Id] ] = pObj->fPhase; + if (pCnf->pVarNums[pObj->Id] >= 0) + pVarToPol[pCnf->pVarNums[pObj->Id]] = pObj->fPhase; } // transform literals - for ( i = 0; i < pCnf->nLiterals; i++ ) + for (i = 0; i < pCnf->nLiterals; i++) { iVar = lit_var(pCnf->pClauses[0][i]); - assert( iVar < pCnf->nVars ); - if ( pVarToPol[iVar] ) - pCnf->pClauses[0][i] = lit_neg( pCnf->pClauses[0][i] ); + assert(iVar < pCnf->nVars); + if (pVarToPol[iVar]) + pCnf->pClauses[0][i] = lit_neg(pCnf->pClauses[0][i]); } - ABC_FREE( pVarToPol ); + ABC_FREE(pVarToPol); } /**Function************************************************************* @@ -795,39 +833,39 @@ void Cnf_DataTranformPolarity( Cnf_Dat_t * pCnf, int fTransformPos ) Synopsis [Adds constraints for the two-input AND-gate.] Description [] - + SideEffects [] SeeAlso [] ***********************************************************************/ -int Cnf_DataAddXorClause( void * pSat, int iVarA, int iVarB, int iVarC ) +int Cnf_DataAddXorClause(void *pSat, int iVarA, int iVarB, int iVarC) { lit Lits[3]; - assert( iVarA > 0 && iVarB > 0 && iVarC > 0 ); + assert(iVarA > 0 && iVarB > 0 && iVarC > 0); - Lits[0] = toLitCond( iVarA, 1 ); - Lits[1] = toLitCond( iVarB, 1 ); - Lits[2] = toLitCond( iVarC, 1 ); - if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) ) + Lits[0] = toLitCond(iVarA, 1); + Lits[1] = toLitCond(iVarB, 1); + Lits[2] = toLitCond(iVarC, 1); + if (!sat_solver_addclause((sat_solver *)pSat, Lits, Lits + 3)) return 0; - Lits[0] = toLitCond( iVarA, 1 ); - Lits[1] = toLitCond( iVarB, 0 ); - Lits[2] = toLitCond( iVarC, 0 ); - if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) ) + Lits[0] = toLitCond(iVarA, 1); + Lits[1] = toLitCond(iVarB, 0); + Lits[2] = toLitCond(iVarC, 0); + if (!sat_solver_addclause((sat_solver *)pSat, Lits, Lits + 3)) return 0; - Lits[0] = toLitCond( iVarA, 0 ); - Lits[1] = toLitCond( iVarB, 1 ); - Lits[2] = toLitCond( iVarC, 0 ); - if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) ) + Lits[0] = toLitCond(iVarA, 0); + Lits[1] = toLitCond(iVarB, 1); + Lits[2] = toLitCond(iVarC, 0); + if (!sat_solver_addclause((sat_solver *)pSat, Lits, Lits + 3)) return 0; - Lits[0] = toLitCond( iVarA, 0 ); - Lits[1] = toLitCond( iVarB, 0 ); - Lits[2] = toLitCond( iVarC, 1 ); - if ( !sat_solver_addclause( (sat_solver *)pSat, Lits, Lits + 3 ) ) + Lits[0] = toLitCond(iVarA, 0); + Lits[1] = toLitCond(iVarB, 0); + Lits[2] = toLitCond(iVarC, 1); + if (!sat_solver_addclause((sat_solver *)pSat, Lits, Lits + 3)) return 0; return 1; @@ -837,6 +875,4 @@ int Cnf_DataAddXorClause( void * pSat, int iVarA, int iVarB, int iVarC ) /// END OF FILE /// //////////////////////////////////////////////////////////////////////// - ABC_NAMESPACE_IMPL_END - diff --git a/src/sat/glucose/AbcGlucose.cpp b/src/sat/glucose/AbcGlucose.cpp index d6f4c454dc..3df050cbc8 100644 --- a/src/sat/glucose/AbcGlucose.cpp +++ b/src/sat/glucose/AbcGlucose.cpp @@ -878,6 +878,9 @@ Vec_Int_t * Glucose_SolverFromAig( Gia_Man_t * p, SimpSolver& s ) abctime clk = Abc_Clock(); vec * lits = &s.user_lits; Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8 /*nLutSize*/, 0 /*fCnfObjIds*/, 1/*fAddOrCla*/, 0, 0/*verbose*/ ); + // CNF variable IDs are 1-based and may include unused variables. + // Create the full range so model[] can be indexed by pVarNums directly. + s.addVar( pCnf->nVars - 1 ); for ( int i = 0; i < pCnf->nClauses; i++ ) { lits->clear(); diff --git a/src/sat/glucose2/AbcGlucose2.cpp b/src/sat/glucose2/AbcGlucose2.cpp index 6201779cb1..2d7d1c3f58 100644 --- a/src/sat/glucose2/AbcGlucose2.cpp +++ b/src/sat/glucose2/AbcGlucose2.cpp @@ -896,6 +896,9 @@ Vec_Int_t * Glucose_SolverFromAig( Gia_Man_t * p, SimpSolver& s ) abctime clk = Abc_Clock(); vec * lits = &s.user_lits; Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8 /*nLutSize*/, 0 /*fCnfObjIds*/, 1/*fAddOrCla*/, 0, 0/*verbose*/ ); + // CNF variable IDs are 1-based and may include unused variables. + // Create the full range so model[] can be indexed by pVarNums directly. + s.addVar( pCnf->nVars - 1 ); for ( int i = 0; i < pCnf->nClauses; i++ ) { lits->clear(); diff --git a/src/sat/kissat/colors.c b/src/sat/kissat/colors.c index c6141b7491..7c41fba617 100644 --- a/src/sat/kissat/colors.c +++ b/src/sat/kissat/colors.c @@ -1,6 +1,7 @@ #include "colors.h" #if defined(WIN32) && !defined(__MINGW32__) +#include #define isatty _isatty #else #include diff --git a/src/sat/kissat/file.c b/src/sat/kissat/file.c index e4486783d2..c0d14c6cc2 100644 --- a/src/sat/kissat/file.c +++ b/src/sat/kissat/file.c @@ -9,10 +9,12 @@ #include #ifdef WIN32 +#include #define unlink _unlink #define access _access #define R_OK 4 #define W_OK 2 +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #else #include #endif diff --git a/test/gia/CMakeLists.txt b/test/gia/CMakeLists.txt index e4dffd475e..9ae8a41ca1 100644 --- a/test/gia/CMakeLists.txt +++ b/test/gia/CMakeLists.txt @@ -7,4 +7,15 @@ target_link_libraries(gia_test gtest_discover_tests(gia_test WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_executable(origins_test origins_test.cc) + +target_link_libraries(origins_test + gtest_main + libabc +) + +gtest_discover_tests(origins_test + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) \ No newline at end of file diff --git a/test/gia/origins_test.cc b/test/gia/origins_test.cc new file mode 100644 index 0000000000..92a49f0486 --- /dev/null +++ b/test/gia/origins_test.cc @@ -0,0 +1,283 @@ +// Regression tests for per-object origin tracking (vOrigins). +// +// Covers the core infrastructure (set/get/add/dedup/inline->overflow +// promotion/union/cap), propagation through Gia_ManDup, the AIGER "y" +// extension write/read round-trip, and preservation through the &nf +// standard-cell mapper (which maps in place and is therefore expected to +// preserve origins without dedicated propagation code). + +#include "gtest/gtest.h" + +#include "aig/gia/gia.h" +#include "base/main/main.h" +#include "base/cmd/cmd.h" + +#include +#include + +ABC_NAMESPACE_IMPL_START + +// -------------------------------------------------------------------------- +// helpers +// -------------------------------------------------------------------------- + +// Build a 2-input single-AND combinational AIG: o = a & b. +static Gia_Man_t* BuildSmallAig() { + Gia_Man_t* p = Gia_ManStart(100); + int a = Gia_ManAppendCi(p); + int b = Gia_ManAppendCi(p); + int g = Gia_ManAppendAnd(p, a, b); + Gia_ManAppendCo(p, g); + return p; +} + +// Build o = (a & b) | (c & d), expressed with ANDs and inverters so the +// mapper has something non-trivial to do. +static Gia_Man_t* BuildOrOfAnds() { + Gia_Man_t* p = Gia_ManStart(100); + int a = Gia_ManAppendCi(p); + int b = Gia_ManAppendCi(p); + int c = Gia_ManAppendCi(p); + int d = Gia_ManAppendCi(p); + int ab = Gia_ManAppendAnd(p, a, b); + int cd = Gia_ManAppendAnd(p, c, d); + int nand = Gia_ManAppendAnd(p, Abc_LitNot(ab), Abc_LitNot(cd)); // ~ab & ~cd + Gia_ManAppendCo(p, Abc_LitNot(nand)); // ab | cd + return p; +} + +static int FirstAndId(Gia_Man_t* p) { + Gia_Obj_t* pObj; + int i; + Gia_ManForEachAnd(p, pObj, i) return i; + return -1; +} + +static int CountTotalOrigins(Gia_Man_t* p) { + Gia_Obj_t* pObj; + int i, total = 0; + if (!p->vOrigins) return 0; + Gia_ManForEachObj(p, pObj, i) total += Gia_ObjOriginsNum(p, i); + return total; +} + +// Allocate origins and seed every AND node with its own id (the "identity" +// mapping Yosys writes via the XAIGER "y" extension). +static void SeedIdentityOrigins(Gia_Man_t* p) { + Gia_Obj_t* pObj; + int i; + p->vOrigins = Gia_ManOriginsAlloc(Gia_ManObjNum(p)); + Gia_ManForEachAnd(p, pObj, i) Gia_ObjSetOrigin(p, i, i); +} + +// -------------------------------------------------------------------------- +// core infrastructure +// -------------------------------------------------------------------------- + +TEST(OriginsTest, SetAndGetSingleOrigin) { + Gia_Man_t* p = BuildSmallAig(); + p->vOrigins = Gia_ManOriginsAlloc(Gia_ManObjNum(p)); + int g = FirstAndId(p); + Gia_ObjSetOrigin(p, g, 42); + EXPECT_EQ(Gia_ObjOriginsNum(p, g), 1); + EXPECT_EQ(Gia_ObjOriginsGet(p, g, 0), 42); + Gia_ManStop(p); +} + +TEST(OriginsTest, AddDeduplicates) { + Gia_Man_t* p = BuildSmallAig(); + p->vOrigins = Gia_ManOriginsAlloc(Gia_ManObjNum(p)); + int g = FirstAndId(p); + Gia_ObjAddOrigin(p, g, 7); + Gia_ObjAddOrigin(p, g, 7); // duplicate: ignored + EXPECT_EQ(Gia_ObjOriginsNum(p, g), 1); + Gia_ObjAddOrigin(p, g, 9); + EXPECT_EQ(Gia_ObjOriginsNum(p, g), 2); + Gia_ManStop(p); +} + +TEST(OriginsTest, InlineToOverflowPromotion) { + Gia_Man_t* p = BuildSmallAig(); + p->vOrigins = Gia_ManOriginsAlloc(Gia_ManObjNum(p)); + int g = FirstAndId(p); + const int N = GIA_ORIGINS_INLINE + 3; // force promotion past the inline buffer + for (int k = 0; k < N; k++) Gia_ObjAddOrigin(p, g, 100 + k); + EXPECT_EQ(Gia_ObjOriginsNum(p, g), N); + std::set got; + for (int k = 0; k < N; k++) got.insert(Gia_ObjOriginsGet(p, g, k)); + for (int k = 0; k < N; k++) EXPECT_TRUE(got.count(100 + k)) << "missing origin " << (100 + k); + Gia_ManStop(p); +} + +TEST(OriginsTest, UnionAcrossManagers) { + Gia_Man_t* src = BuildSmallAig(); + src->vOrigins = Gia_ManOriginsAlloc(Gia_ManObjNum(src)); + int sg = FirstAndId(src); + Gia_ObjAddOrigin(src, sg, 11); + Gia_ObjAddOrigin(src, sg, 22); + + Gia_Man_t* dst = BuildSmallAig(); + dst->vOrigins = Gia_ManOriginsAlloc(Gia_ManObjNum(dst)); + int dg = FirstAndId(dst); + Gia_ObjAddOrigin(dst, dg, 11); // overlaps with src + + Gia_ObjUnionOrigins(dst, dg, src, sg); + EXPECT_EQ(Gia_ObjOriginsNum(dst, dg), 2); // {11, 22} deduplicated + + Gia_ManStop(src); + Gia_ManStop(dst); +} + +TEST(OriginsTest, NOriginsMaxCapsAccumulation) { + Gia_Man_t* p = BuildSmallAig(); + p->vOrigins = Gia_ManOriginsAlloc(Gia_ManObjNum(p)); + p->nOriginsMax = 10; + int g = FirstAndId(p); + for (int k = 0; k < 50; k++) Gia_ObjAddOrigin(p, g, 1000 + k); + EXPECT_EQ(Gia_ObjOriginsNum(p, g), 10); // capped once in overflow mode + Gia_ManStop(p); +} + +// -------------------------------------------------------------------------- +// propagation +// -------------------------------------------------------------------------- + +TEST(OriginsTest, GiaManDupPreservesOrigins) { + Gia_Man_t* p = BuildSmallAig(); + p->vOrigins = Gia_ManOriginsAlloc(Gia_ManObjNum(p)); + int g = FirstAndId(p); + Gia_ObjAddOrigin(p, g, 55); + + Gia_Man_t* dup = Gia_ManDup(p); + ASSERT_TRUE(dup->vOrigins != nullptr); + EXPECT_EQ(CountTotalOrigins(dup), 1); + int dg = FirstAndId(dup); + ASSERT_GE(dg, 0); + EXPECT_EQ(Gia_ObjOriginsNum(dup, dg), 1); + EXPECT_EQ(Gia_ObjOriginsGet(dup, dg, 0), 55); + + Gia_ManStop(p); + Gia_ManStop(dup); +} + +TEST(OriginsTest, AigerWriteReadRoundTripPreservesOrigins) { + Gia_Man_t* p = BuildSmallAig(); + p->vOrigins = Gia_ManOriginsAlloc(Gia_ManObjNum(p)); + int g = FirstAndId(p); + Gia_ObjAddOrigin(p, g, 77); + + const char* fname = "test_origins_roundtrip.aig"; + Gia_AigerWrite(p, (char*)fname, 0, 0, 0); // "y" extension emitted unconditionally + Gia_Man_t* q = Gia_AigerRead((char*)fname, 0, 0, 0); + remove(fname); + + ASSERT_TRUE(q != nullptr); + ASSERT_TRUE(q->vOrigins != nullptr); + EXPECT_EQ(CountTotalOrigins(q), 1); + + Gia_ManStop(p); + Gia_ManStop(q); +} + +// -------------------------------------------------------------------------- +// engine: &nf standard-cell mapping +// +// &nf maps in place (Nf_ManDeriveMapping returns p->pGia without renumbering), +// so origins on the AIG nodes must survive standard-cell mapping unchanged. +// -------------------------------------------------------------------------- + +TEST(OriginsTest, NfMappingPreservesOrigins) { + // Seed a design with origins and write it to AIGER (carries the "y" ext). + Gia_Man_t* p = BuildOrOfAnds(); + SeedIdentityOrigins(p); + const int seeded = CountTotalOrigins(p); + ASSERT_GT(seeded, 0); + const char* aig = "test_origins_nf_in.aig"; + Gia_AigerWrite(p, (char*)aig, 0, 0, 0); + Gia_ManStop(p); + + Abc_Start(); + Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame(); + + ASSERT_EQ(Cmd_CommandExecute(pAbc, "read_genlib test_origins.genlib"), 0); + char cmd[256]; + snprintf(cmd, sizeof(cmd), "&read %s", aig); + ASSERT_EQ(Cmd_CommandExecute(pAbc, cmd), 0); + + Gia_Man_t* before = Abc_FrameReadGia(pAbc); + ASSERT_TRUE(before != nullptr); + ASSERT_GT(CountTotalOrigins(before), 0); // origins read back from "y" + + ASSERT_EQ(Cmd_CommandExecute(pAbc, "&nf"), 0); + + Gia_Man_t* after = Abc_FrameReadGia(pAbc); + ASSERT_TRUE(after != nullptr); + ASSERT_TRUE(after->vOrigins != nullptr); + EXPECT_GT(CountTotalOrigins(after), 0); // preserved through &nf std-cell mapping + + remove(aig); + Abc_Stop(); +} + +// Regression: writing a cell-mapped GIA emits an "M" (cell-mapping) section +// followed by the "y" origin section. The AIGER reader must SKIP the unknown +// "M" section rather than bail out of the extension loop, otherwise the "y" +// origins (written after "M") are silently lost on read-back. +TEST(OriginsTest, MappedAigerRoundTripPreservesOrigins) { + Gia_Man_t* p = BuildOrOfAnds(); + SeedIdentityOrigins(p); + const char* in = "test_origins_mapped_in.aig"; + Gia_AigerWrite(p, (char*)in, 0, 0, 0); + Gia_ManStop(p); + + Abc_Start(); + Abc_Frame_t* pAbc = Abc_FrameGetGlobalFrame(); + ASSERT_EQ(Cmd_CommandExecute(pAbc, "read_genlib test_origins.genlib"), 0); + char cmd[256]; + snprintf(cmd, sizeof(cmd), "&read %s", in); + ASSERT_EQ(Cmd_CommandExecute(pAbc, cmd), 0); + ASSERT_EQ(Cmd_CommandExecute(pAbc, "&nf"), 0); // creates cell mapping + ASSERT_EQ(Cmd_CommandExecute(pAbc, "&write test_origins_mapped_out.aig"), 0); // emits "M" then "y" + ASSERT_EQ(Cmd_CommandExecute(pAbc, "&read test_origins_mapped_out.aig"), 0); // must skip "M" to reach "y" + + Gia_Man_t* after = Abc_FrameReadGia(pAbc); + ASSERT_TRUE(after != nullptr); + ASSERT_TRUE(after->vOrigins != nullptr); // would be NULL without the "M"-skip fix + EXPECT_GT(CountTotalOrigins(after), 0); + + remove(in); + remove("test_origins_mapped_out.aig"); + Abc_Stop(); +} + +// Balancing rebuilds the AIG, creating new internal nodes with no 1:1 origin +// correspondence. Gia_ManOriginsDupFill must cover them bottom-up so no node +// (and thus no cell later mapped from it) loses provenance. A left-deep AND +// chain is restructured into a shallow tree, forcing fresh nodes. +TEST(OriginsTest, AreaBalancePreservesOriginCoverage) { + Gia_Man_t* p = Gia_ManStart(100); + int ci[8], i; + for (i = 0; i < 8; i++) ci[i] = Gia_ManAppendCi(p); + int lit = ci[0]; + for (i = 1; i < 8; i++) lit = Gia_ManAppendAnd(p, lit, ci[i]); + Gia_ManAppendCo(p, lit); + // Seed identity origins on every object (CIs included) as the XAIGER "y" + // extension does — the fill propagates CI origins up into new leaf nodes. + Gia_Obj_t* pSeed; + p->vOrigins = Gia_ManOriginsAlloc(Gia_ManObjNum(p)); + Gia_ManForEachObj(p, pSeed, i) + if (i > 0) Gia_ObjSetOrigin(p, i, i); + + Gia_Man_t* pNew = Gia_ManAreaBalance(p, 1, 1000, 0, 0); + ASSERT_TRUE(pNew->vOrigins != nullptr); + Gia_Obj_t* pObj; + int uncovered = 0; + Gia_ManForEachAnd(pNew, pObj, i) + if (Gia_ObjOriginsNum(pNew, i) == 0) uncovered++; + EXPECT_EQ(uncovered, 0) << "balanced AIG has AND nodes with no origin"; + + Gia_ManStop(p); + Gia_ManStop(pNew); +} + +ABC_NAMESPACE_IMPL_END diff --git a/test/gia/test_origins.genlib b/test/gia/test_origins.genlib new file mode 100644 index 0000000000..89815dbdbb --- /dev/null +++ b/test/gia/test_origins.genlib @@ -0,0 +1,8 @@ +GATE zero 0 O=CONST0; +GATE one 0 O=CONST1; +GATE buf 1 O=a; PIN * NONINV 1 999 1.0 0.0 1.0 0.0 +GATE inv 1 O=!a; PIN * INV 1 999 1.0 0.0 1.0 0.0 +GATE and2 3 O=a*b; PIN * NONINV 1 999 1.0 0.0 1.0 0.0 +GATE or2 3 O=a+b; PIN * NONINV 1 999 1.0 0.0 1.0 0.0 +GATE nand2 2 O=!(a*b); PIN * INV 1 999 1.0 0.0 1.0 0.0 +GATE nor2 2 O=!(a+b); PIN * INV 1 999 1.0 0.0 1.0 0.0 diff --git a/test/write_cnf_dangling.sh b/test/write_cnf_dangling.sh new file mode 100755 index 0000000000..bbb80b7dc9 --- /dev/null +++ b/test/write_cnf_dangling.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# Regression test for berkeley-abc/abc#479 +# +# After "strash", a primary input wired directly to a primary output becomes +# a dangling PI: it shows up in the DIMACS header's variable count but the +# Tseitin encoder emits no clause mentioning it. Such a free variable +# silently doubles the model count of the written formula, breaking #SAT +# and uniform sampling. +# +# The fix in Cnf_DataWriteIntoFile() detects DIMACS variables that are +# declared in the header but unreferenced in any clause, and emits a unit +# clause pinning each of them to false. The two cases below exercise that +# behaviour against the abc binary. + +set -eu + +ABC=${ABC:-./abc} +TMP=$(mktemp -d) +trap 'rm -rf "$TMP"' EXIT + +fail() { echo "FAIL: $1" >&2; exit 1; } + +run_case() { + local name=$1 input=$2 + local in="$TMP/$name.in.cnf" out="$TMP/$name.out.cnf" + printf '%s' "$input" > "$in" + "$ABC" -q "read_cnf $in; strash; write_cnf $out" > /dev/null + + # Extract declared variable count from the header. + local header + header=$(grep -m1 '^p cnf ' "$out") + local nVars + nVars=$(echo "$header" | awk '{print $3}') + + # Every variable 1..nVars must appear (positive or negated) in some clause. + local v + for v in $(seq 1 "$nVars"); do + if ! grep -Eq "(^|[ \t-])$v( |$)" "$out"; then + cat "$out" >&2 + fail "$name: variable $v declared in header but never used in any clause" + fi + done + echo "PASS: $name ($header)" +} + +# Case 1: original reproducer from issue #479 -- a single PI wired directly +# to a single PO. Before the fix, the output was "p cnf 3 2" with clauses +# "-3 0" and "2 0", leaving variable 1 unconstrained. +run_case "pi_to_po_direct" "p cnf 1 1 +1 0 +" + +# Case 2: two independent PIs, each a direct wire to its own PO. Both PIs +# end up dangling after strash. +run_case "two_pis_two_pos" "p cnf 2 2 +1 0 +2 0 +" + +echo "All regression tests passed."