From 9e02a87c1d9bd4a72d479f2d5e7918bd6b05c584 Mon Sep 17 00:00:00 2001 From: Min Hsu Date: Tue, 19 May 2026 14:17:09 -0700 Subject: [PATCH 01/15] misc: Prevent Vec_IntRemove from loading nSize in every iteration This seemly benign loop ``` for ( i++; i < p->nSize; i++ ) p->pArray[i-1] = p->pArray[i]; ``` will actually load `p->nSize` in every loop iteration (rather than memorizing the value) due to some unfortunate pointer aliasing properties in C/C++. As Vec_IntRemove is quite ubiquitous, this extra memory load actually causes visible performance impact and prevents further optimizations on the loop. This patch fixes this by factoring `p->nSize` out of the loop. --- src/misc/vec/vecInt.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/misc/vec/vecInt.h b/src/misc/vec/vecInt.h index e32a2dd18..9a73cde83 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; From 7b0a6cbb588463bc31f3c191e139d8fae546245d Mon Sep 17 00:00:00 2001 From: JingrenWang Date: Mon, 1 Jun 2026 16:23:38 +0800 Subject: [PATCH 02/15] Feat(rd_inv): Simple inv redis framework. Signed-off-by: JingrenWang --- abclib.dsp | 4 + src/base/abc/abc.h | 4 + src/base/abc/abcDfs.c | 96 ++++ src/base/abci/abc.c | 55 ++- src/base/abci/abcRmInverters.c | 853 +++++++++++++++++++++++++++++++++ src/base/abci/module.make | 1 + 6 files changed, 1012 insertions(+), 1 deletion(-) create mode 100644 src/base/abci/abcRmInverters.c diff --git a/abclib.dsp b/abclib.dsp index 2f16e849e..4aa3a34ce 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 diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h index 0b0376c47..e49080823 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 68c005a5e..d95c8ad02 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/abci/abc.c b/src/base/abci/abc.c index 44ceacc88..a00315e3b 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -149,6 +149,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 ); @@ -1008,6 +1009,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 ); @@ -7995,7 +7997,58 @@ usage: 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 [] diff --git a/src/base/abci/abcRmInverters.c b/src/base/abci/abcRmInverters.c new file mode 100644 index 000000000..2d25d9423 --- /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 fe063a42a..5891071dd 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 \ From 8149daf921f09956467e8da22efd8a9208ebfebb Mon Sep 17 00:00:00 2001 From: longfei Date: Sat, 6 Jun 2026 20:31:57 +0800 Subject: [PATCH 03/15] giaSatLut: fix &satlut expanding LUT size from K=5 to K=6 Sbl_CutIsFeasible only checked LutSize <= 4 before the final return Count <= 6, allowing 6-input cuts when LutSize=5. Add the missing LutSize <= 5 check after the 5th bit-strip. --- src/aig/gia/giaSatLut.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/aig/gia/giaSatLut.c b/src/aig/gia/giaSatLut.c index 679c9e58b..31e0972f8 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; } From b73fcb78ed766b4fefe02dfbcc03030ecc7f58fd Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 8 Jun 2026 16:11:31 +0200 Subject: [PATCH 04/15] Add missing includes for windows --- src/base/main/mainUtils.c | 1 + src/sat/kissat/colors.c | 1 + src/sat/kissat/file.c | 2 ++ 3 files changed, 4 insertions(+) diff --git a/src/base/main/mainUtils.c b/src/base/main/mainUtils.c index 5db012cfe..018914f9c 100644 --- a/src/base/main/mainUtils.c +++ b/src/base/main/mainUtils.c @@ -20,6 +20,7 @@ #ifdef WIN32 #include +#include #else #include #endif diff --git a/src/sat/kissat/colors.c b/src/sat/kissat/colors.c index c6141b749..7c41fba61 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 e4486783d..c0d14c6cc 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 From d3d218eee2b2c78a624f4e6c4e166d8930603397 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 8 Jun 2026 16:11:48 +0200 Subject: [PATCH 05/15] Cleanup --- src/base/abci/abcNpn.c | 9 --------- src/opt/dau/dau.h | 1 + src/opt/dau/dauNpn.c | 1 - 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/base/abci/abcNpn.c b/src/base/abci/abcNpn.c index 92b47c177..ab8a7a685 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/opt/dau/dau.h b/src/opt/dau/dau.h index 82e9b83b2..37d24aa5a 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/dauNpn.c b/src/opt/dau/dauNpn.c index f4a4bb531..be9aae3ef 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 ); From 1e130338f049899938b37fba43efd506d687773e Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 9 Jun 2026 08:20:13 +0200 Subject: [PATCH 06/15] Make sure we detect these errors in future --- .github/scripts/abcexe.vcxproj | 1 + .github/scripts/abclib.vcxproj.template | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/scripts/abcexe.vcxproj b/.github/scripts/abcexe.vcxproj index 817e0809e..950021017 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 77498528d..9b21d325f 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 From a4b79128953e3d1b214dd352b7c47797187a3405 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 16 Jun 2026 04:52:40 -0700 Subject: [PATCH 07/15] Adding API to compute switching activity --- src/map/scl/sclSize.h | 1 + src/map/scl/sclUtil.c | 76 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/src/map/scl/sclSize.h b/src/map/scl/sclSize.h index acb66bb9c..6164b4e02 100644 --- a/src/map/scl/sclSize.h +++ b/src/map/scl/sclSize.h @@ -645,6 +645,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/sclUtil.c b/src/map/scl/sclUtil.c index 331dedb5c..8d56148f2 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 @@ -275,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 [] From e00a2fe8349dbe068cf37b83b1296264bc9ec277 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 16 Jun 2026 05:05:05 -0700 Subject: [PATCH 08/15] Adding support power info exraction from Liberty --- src/map/scl/sclLib.h | 6 ++- src/map/scl/sclLibScl.c | 18 +++++++- src/map/scl/sclLiberty.c | 96 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 110 insertions(+), 10 deletions(-) diff --git a/src/map/scl/sclLib.h b/src/map/scl/sclLib.h index eb2d7920d..1dd86cc3d 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 9 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_ @@ -407,6 +409,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 ); diff --git a/src/map/scl/sclLibScl.c b/src/map/scl/sclLibScl.c index 18a4b8a57..cdd8fb29e 100644 --- a/src/map/scl/sclLibScl.c +++ b/src/map/scl/sclLibScl.c @@ -392,6 +392,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 +556,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 ); @@ -831,6 +835,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 +904,3 @@ SC_Lib * Abc_SclMergeLibraries( SC_Lib * pLib1, SC_Lib * pLib2, int fUsePrefix ) ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclLiberty.c b/src/map/scl/sclLiberty.c index 06d40c84b..4171aa5fc 100644 --- a/src/map/scl/sclLiberty.c +++ b/src/map/scl/sclLiberty.c @@ -1116,6 +1116,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 +1224,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 +1318,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 +1528,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 +1547,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 +1555,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 ) @@ -1668,6 +1740,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 +1762,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 +1774,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 +1818,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 +1915,3 @@ void Scl_LibertyTest() ABC_NAMESPACE_IMPL_END - From 2d835aabf0cb0530aeb33aa8e8f2744945b26d2e Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 16 Jun 2026 07:46:55 -0700 Subject: [PATCH 09/15] Adding command "power" to eval static/dynamic power --- src/map/scl/scl.c | 105 ++++++++++++++++++++++++++++++++++++++- src/map/scl/sclLib.h | 70 ++++++++++++++++++++++++-- src/map/scl/sclLibScl.c | 4 ++ src/map/scl/sclLibUtil.c | 11 +++- src/map/scl/sclLiberty.c | 14 ++++++ src/map/scl/sclSize.c | 87 +++++++++++++++++++++++++++++++- src/map/scl/sclSize.h | 1 + 7 files changed, 285 insertions(+), 7 deletions(-) diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index b012435f5..f023680e2 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 @@ usage: 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 @@ usage: ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclLib.h b/src/map/scl/sclLib.h index 1dd86cc3d..fd2f5bb49 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 9 +#define ABC_SCL_CUR_VERSION 10 typedef enum { @@ -232,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 @@ -353,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; } @@ -496,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); @@ -516,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) ); @@ -666,8 +725,11 @@ static inline SC_Timing * Scl_CellPinOutTime( SC_Cell * pCell, int iOut, int iPi SC_Timings * pRTime; assert( iOut >= 0 && iOut < pCell->n_outputs ); assert( iPin >= 0 && iPin < pCell->n_inputs ); + if ( pCell->n_inputs + iOut >= Vec_PtrSize(&pCell->vPins) ) + return NULL; pPin = SC_CellPin( pCell, pCell->n_inputs + iOut ); - assert( Vec_PtrSize(&pPin->vRTimings) == pCell->n_inputs ); + if ( iPin >= Vec_PtrSize(&pPin->vRTimings) ) + return NULL; pRTime = (SC_Timings *)Vec_PtrEntry( &pPin->vRTimings, iPin ); if ( Vec_PtrSize(&pRTime->vTimings) == 0 ) return NULL; diff --git a/src/map/scl/sclLibScl.c b/src/map/scl/sclLibScl.c index cdd8fb29e..42dd6b78e 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-- ) @@ -594,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) ); @@ -735,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" ); diff --git a/src/map/scl/sclLibUtil.c b/src/map/scl/sclLibUtil.c index 4115143c3..e132b7341 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 4171aa5fc..98d5e2ab3 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; @@ -1606,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 ); diff --git a/src/map/scl/sclSize.c b/src/map/scl/sclSize.c index 8d3a2dd5a..a2ba65ee9 100644 --- a/src/map/scl/sclSize.c +++ b/src/map/scl/sclSize.c @@ -759,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************************************************************* @@ -972,4 +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 6164b4e02..8466469c4 100644 --- a/src/map/scl/sclSize.h +++ b/src/map/scl/sclSize.h @@ -634,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 ); From 61e74a103316421888004794e9e74dcac9d94dd2 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 16 Jun 2026 07:52:19 -0700 Subject: [PATCH 10/15] Update high-effort synthesis. --- src/aig/gia/giaDeep.c | 303 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 301 insertions(+), 2 deletions(-) diff --git a/src/aig/gia/giaDeep.c b/src/aig/gia/giaDeep.c index 9d2a2c875..9c506eab5 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 - From 334ae5d1b78d3820fbd59646353a954a4e2b3112 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 16 Jun 2026 07:53:07 -0700 Subject: [PATCH 11/15] Update .gitingore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7236839d3..e2e5e555c 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 From cfd526afd0a4d5d9375a26853179cea5b788022a Mon Sep 17 00:00:00 2001 From: Mahesh Madhav Date: Tue, 16 Jun 2026 15:33:12 +0000 Subject: [PATCH 12/15] Fix strict aliasing violations The cast to char** is a violation of strict aliasing rules. Compilers may generate incorrect code due to this issue. Using memcpy to avoid the issue. Not expecting perf difference. --- src/aig/hop/hop.h | 6 +++--- src/aig/hop/hopMem.c | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/aig/hop/hop.h b/src/aig/hop/hop.h index 6b8085cc5..5fc022a69 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 79de38048..e6142e95e 100644 --- a/src/aig/hop/hopMem.c +++ b/src/aig/hop/hopMem.c @@ -88,14 +88,16 @@ void Hop_ManStopMemory( Hop_Man_t * p ) ***********************************************************************/ void Hop_ManAddMemory( Hop_Man_t * p ) { - char * pMemory; + Hop_Obj_t * pMemory; + char *PMemAlign = 0; 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 pMemory = pMemory + 64 - (((int)(ABC_PTRUINT_T)pMemory) & 63); @@ -105,10 +107,12 @@ void Hop_ManAddMemory( Hop_Man_t * p ) p->pListFree = (Hop_Obj_t *)pMemory; for ( i = 1; i <= IVY_PAGE_MASK; i++ ) { - *((char **)pMemory) = pMemory + sizeof(Hop_Obj_t); - pMemory += sizeof(Hop_Obj_t); + Hop_Obj_t *NextPtr = pMemory + 1; + memcpy(pMemory, &NextPtr, sizeof(Hop_Obj_t *)); + pMemory += 1; } - *((char **)pMemory) = NULL; + Hop_Obj_t *NullPtr = NULL; + memcpy(pMemory, &NullPtr, sizeof(Hop_Obj_t *)); } //////////////////////////////////////////////////////////////////////// From 70a92ee63fa6194f75c272636000ba149b89de72 Mon Sep 17 00:00:00 2001 From: Franz Reichl Date: Thu, 18 Jun 2026 14:06:04 +0200 Subject: [PATCH 13/15] Fix issue with constant replacements --- src/base/abci/abc.c | 4 ++-- src/opt/eslim/delayEngine.cpp | 12 +++++++----- src/opt/eslim/windowMan.tpp | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index eee4432b1..8d95d60b4 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -61033,7 +61033,7 @@ int Abc_CommandAbc9eSLIM( Abc_Frame_t * pAbc, int argc, char ** argv ) { } params.synthesis_approach = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( params.synthesis_approach < 0 || params.synthesis_approach > 2) + if ( params.synthesis_approach < 0 || params.synthesis_approach > 3) goto usage; break; case 'I': @@ -61249,7 +61249,7 @@ int Abc_CommandAbc9elSLIM( Abc_Frame_t * pAbc, int argc, char ** argv ) { } params.synthesis_approach = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( params.synthesis_approach < 0 || params.synthesis_approach > 2) + if ( params.synthesis_approach < 0 || params.synthesis_approach > 3) goto usage; break; case 'I': diff --git a/src/opt/eslim/delayEngine.cpp b/src/opt/eslim/delayEngine.cpp index 0604a242a..5e92566cf 100644 --- a/src/opt/eslim/delayEngine.cpp +++ b/src/opt/eslim/delayEngine.cpp @@ -83,11 +83,13 @@ namespace eSLIM { } int replacement_size = synth.getSizeFromActivationVars(last_model); int replacement_delay = synth.getDelayFromDelayVariables(last_model); - assert (replacement_delay > 0); - std::vector model = synth.reduceDelay(replacement_size, replacement_delay - 1); - if (model.size() > 0) { - replacement_size = synth.getSizeFromActivationVars(model); - std::swap(last_model, 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); } diff --git a/src/opt/eslim/windowMan.tpp b/src/opt/eslim/windowMan.tpp index d09b264ab..c540988a3 100644 --- a/src/opt/eslim/windowMan.tpp +++ b/src/opt/eslim/windowMan.tpp @@ -126,7 +126,7 @@ namespace eSLIM { 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]) + eSLIM_Man::applyeSLIM(windows[wid], cfg, wlogs[wid]); #endif } From 7d253d7cb2431a2d814c0b8b7d175751a345dfe1 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 22 Jun 2026 19:35:32 -0700 Subject: [PATCH 14/15] Do not support extension "e" (equiv classes of nodes). --- src/aig/gia/giaAiger.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/aig/gia/giaAiger.c b/src/aig/gia/giaAiger.c index c17783832..e5c45df3b 100644 --- a/src/aig/gia/giaAiger.c +++ b/src/aig/gia/giaAiger.c @@ -685,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' ) { @@ -1582,15 +1582,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 ) { From 2eb8f38cd1a4f58caf152ccddbd76a5e885c8c5b Mon Sep 17 00:00:00 2001 From: Mahesh Madhav Date: Wed, 24 Jun 2026 14:35:55 -0400 Subject: [PATCH 15/15] Fix build errors and spacing --- src/aig/hop/hopMem.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/aig/hop/hopMem.c b/src/aig/hop/hopMem.c index e6142e95e..50932971c 100644 --- a/src/aig/hop/hopMem.c +++ b/src/aig/hop/hopMem.c @@ -88,31 +88,32 @@ void Hop_ManStopMemory( Hop_Man_t * p ) ***********************************************************************/ void Hop_ManAddMemory( Hop_Man_t * p ) { - Hop_Obj_t * pMemory; - char *PMemAlign = 0; + 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 pMemory = pMemory + 64 - (((int)(ABC_PTRUINT_T)pMemory) & 63); // 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++ ) { - Hop_Obj_t *NextPtr = pMemory + 1; - memcpy(pMemory, &NextPtr, sizeof(Hop_Obj_t *)); - pMemory += 1; + pNext = pEntry + 1; + memcpy( pEntry, &pNext, sizeof(Hop_Obj_t *) ); + pEntry++; } - Hop_Obj_t *NullPtr = NULL; - memcpy(pMemory, &NullPtr, sizeof(Hop_Obj_t *)); + pNext = NULL; + memcpy( pEntry, &pNext, sizeof(Hop_Obj_t *) ); } ////////////////////////////////////////////////////////////////////////