From f3157272ae94a067f8a41b92b890061c77e7a91a Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 8 May 2026 16:03:24 -0700 Subject: [PATCH] Initial support of multi-output gates in sizing. --- src/base/abc/abcNtk.c | 82 ++++++++++++++++++++++++++++++++++++++++- src/map/scl/sclDnsize.c | 3 +- src/map/scl/sclSize.h | 63 +++++++++++++++++++++++++++++++ src/map/scl/sclUpsize.c | 7 ++-- src/map/scl/sclUtil.c | 5 ++- 5 files changed, 151 insertions(+), 9 deletions(-) diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c index 9d6c4f0ea..047cbf521 100644 --- a/src/base/abc/abcNtk.c +++ b/src/base/abc/abcNtk.c @@ -39,6 +39,86 @@ ABC_NAMESPACE_IMPL_START /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +static int Abc_NtkDupDfsSameFanins( Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 ) +{ + Abc_Obj_t * pFanin0, * pFanin1; + int i; + if ( pObj0 == NULL || pObj1 == NULL || Abc_ObjFaninNum(pObj0) != Abc_ObjFaninNum(pObj1) ) + return 0; + Abc_ObjForEachFanin( pObj0, pFanin0, i ) + { + pFanin1 = Abc_ObjFanin( pObj1, i ); + if ( pFanin0 != pFanin1 ) + return 0; + } + return 1; +} +static Abc_Obj_t * Abc_NtkDupDfsFindTwin( Vec_Ptr_t * vNodes, Vec_Int_t * vSeen, Abc_Obj_t * pObj ) +{ + Mio_Gate_t * pGate = (Mio_Gate_t *)pObj->pData; + Abc_Obj_t * pObj2; + int i; + if ( pGate == NULL || Mio_GateReadTwin(pGate) == NULL ) + return NULL; + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj2, i ) + { + if ( pObj2 == pObj || Vec_IntEntry(vSeen, Abc_ObjId(pObj2)) ) + continue; + if ( (Mio_Gate_t *)pObj2->pData != Mio_GateReadTwin(pGate) ) + continue; + if ( Abc_NtkDupDfsSameFanins(pObj, pObj2) ) + return pObj2; + } + return NULL; +} +static Vec_Ptr_t * Abc_NtkDupDfsOrderTwinNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ) +{ + Vec_Int_t * vSeen; + Vec_Ptr_t * vRes; + Abc_Obj_t * pObj, * pTwin; + Mio_Gate_t * pGate, * pGateBase; + int i; + if ( !Abc_NtkHasMapping(pNtk) || pNtk->pManFunc == NULL ) + return vNodes; + vSeen = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + vRes = Vec_PtrAlloc( Vec_PtrSize(vNodes) ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + if ( Vec_IntEntry(vSeen, Abc_ObjId(pObj)) ) + continue; + pGate = (Mio_Gate_t *)pObj->pData; + if ( pGate == NULL || Mio_GateReadTwin(pGate) == NULL ) + { + Vec_PtrPush( vRes, pObj ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pObj), 1 ); + continue; + } + pTwin = Abc_NtkDupDfsFindTwin( vNodes, vSeen, pObj ); + if ( pTwin == NULL ) + { + Vec_PtrPush( vRes, pObj ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pObj), 1 ); + continue; + } + pGateBase = Mio_LibraryReadGateByName( (Mio_Library_t *)pNtk->pManFunc, Mio_GateReadName(pGate), NULL ); + if ( pGateBase == (Mio_Gate_t *)pTwin->pData ) + { + Vec_PtrPush( vRes, pTwin ); + Vec_PtrPush( vRes, pObj ); + } + else + { + Vec_PtrPush( vRes, pObj ); + Vec_PtrPush( vRes, pTwin ); + } + Vec_IntWriteEntry( vSeen, Abc_ObjId(pObj), 1 ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pTwin), 1 ); + } + Vec_IntFree( vSeen ); + Vec_PtrFree( vNodes ); + return vRes; +} + /**Function************************************************************* Synopsis [Creates a new Ntk.] @@ -548,6 +628,7 @@ Abc_Ntk_t * Abc_NtkDupDfs( Abc_Ntk_t * pNtk ) pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); // copy the internal nodes vNodes = Abc_NtkDfs( pNtk, 0 ); + vNodes = Abc_NtkDupDfsOrderTwinNodes( pNtk, vNodes ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 0 ); Vec_PtrFree( vNodes ); @@ -2621,4 +2702,3 @@ Abc_Ntk_t * Abc_NtkCreateFromGias( char * pName, Vec_Ptr_t * vGias, Gia_Man_t * ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclDnsize.c b/src/map/scl/sclDnsize.c index 35f2c8247..20ffebb6f 100644 --- a/src/map/scl/sclDnsize.c +++ b/src/map/scl/sclDnsize.c @@ -149,7 +149,7 @@ p->timeSize += Abc_Clock() - clk; { pCellNew = SC_LibCell( p->pLib, gateBest ); Abc_SclObjSetCell( pObj, pCellNew ); - p->SumArea += pCellNew->area - pCellOld->area; + p->SumArea += Abc_SclObjAreaDelta( pObj, pCellOld, pCellNew ); // printf( "%f %f -> %f\n", pCellNew->area - pCellOld->area, p->SumArea - (pCellNew->area - pCellOld->area), p->SumArea ); // printf( "%6d %20s -> %20s %f -> %f\n", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName, pCellOld->area, pCellNew->area ); // mark used nodes with the current trav ID @@ -376,4 +376,3 @@ void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclSize.h b/src/map/scl/sclSize.h index 133ae6647..acb66bb9c 100644 --- a/src/map/scl/sclSize.h +++ b/src/map/scl/sclSize.h @@ -27,6 +27,7 @@ //////////////////////////////////////////////////////////////////////// #include "base/abc/abc.h" +#include "map/mio/mio.h" #include "misc/vec/vecQue.h" #include "misc/vec/vecWec.h" #include "sclLib.h" @@ -130,6 +131,64 @@ static inline float Abc_SclObjInDrive( SC_Man * p, Abc_Obj_t * pObj ) static inline void Abc_SclObjSetInDrive( SC_Man * p, Abc_Obj_t * pObj, float c){ Vec_FltWriteEntry( p->vInDrive, pObj->iData, c ); } static inline void Abc_SclManSetFaninCallBack( SC_Man * p, void * pCallBack ) { p->pFuncFanin = (float (*)(void *, Abc_Obj_t *, Abc_Obj_t *, int, int))pCallBack; } +static inline int Abc_SclObjsHaveSameFanins( Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 ) +{ + Abc_Obj_t * pFanin0, * pFanin1; + int i; + if ( pObj0 == NULL || pObj1 == NULL || Abc_ObjFaninNum(pObj0) != Abc_ObjFaninNum(pObj1) ) + return 0; + Abc_ObjForEachFanin( pObj0, pFanin0, i ) + { + pFanin1 = Abc_ObjFanin( pObj1, i ); + if ( pFanin0 != pFanin1 ) + return 0; + } + return 1; +} +static inline int Abc_SclObjIsMogOutput( Abc_Obj_t * pObj ) +{ + Mio_Gate_t * pGate; + if ( pObj == NULL || !Abc_ObjIsNode(pObj) ) + return 0; + pGate = (Mio_Gate_t *)pObj->pData; + return pGate != NULL && Mio_GateReadTwin(pGate) != NULL; +} +static inline int Abc_SclObjIsSecondTwin( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pPrev; + Mio_Gate_t * pGate; + if ( !Abc_SclObjIsMogOutput(pObj) || Abc_ObjId(pObj) == 0 ) + return 0; + pPrev = Abc_NtkObj( pObj->pNtk, Abc_ObjId(pObj) - 1 ); + if ( pPrev == NULL || !Abc_ObjIsNode(pPrev) ) + return 0; + pGate = (Mio_Gate_t *)pObj->pData; + if ( Mio_GateReadTwin(pGate) != (Mio_Gate_t *)pPrev->pData ) + return 0; + return Abc_SclObjsHaveSameFanins( pObj, pPrev ); +} +static inline Abc_Obj_t * Abc_SclObjTwin( Abc_Obj_t * pObj ) +{ + if ( Abc_SclObjIsSecondTwin(pObj) ) + return Abc_NtkObj( pObj->pNtk, Abc_ObjId(pObj) - 1 ); + return Abc_NtkFetchTwinNode( pObj ); +} +static inline int Abc_SclObjTwinFaninsMatch( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pTwin = Abc_SclObjTwin( pObj ); + return pTwin != NULL && Abc_SclObjsHaveSameFanins( pObj, pTwin ); +} +static inline int Abc_SclObjIsCanonicalMog( Abc_Obj_t * pObj ) +{ + return Abc_SclObjIsMogOutput(pObj) && !Abc_SclObjIsSecondTwin(pObj); +} +static inline float Abc_SclObjAreaDelta( Abc_Obj_t * pObj, SC_Cell * pCellOld, SC_Cell * pCellNew ) +{ + if ( Abc_SclObjIsSecondTwin(pObj) ) + return 0.0; + return pCellNew->area - pCellOld->area; +} + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -450,7 +509,11 @@ static inline float Abc_SclGetTotalArea( Abc_Ntk_t * pNtk ) Abc_Obj_t * pObj; int i; Abc_NtkForEachNodeNotBarBuf1( pNtk, pObj, i ) + { + if ( Abc_SclObjIsSecondTwin(pObj) ) + continue; Area += Abc_SclObjCell(pObj)->area; + } return Area; } static inline float Abc_SclGetMaxDelay( SC_Man * p ) diff --git a/src/map/scl/sclUpsize.c b/src/map/scl/sclUpsize.c index 822278a33..fbc3290af 100644 --- a/src/map/scl/sclUpsize.c +++ b/src/map/scl/sclUpsize.c @@ -489,7 +489,7 @@ int Abc_SclFindBypasses( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notc // update cell pCellOld = Abc_SclObjCell( pFanin ); pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(p->vNode2Gate, iNode) ); - p->SumArea += pCellNew->area - pCellOld->area; + p->SumArea += Abc_SclObjAreaDelta( pFanin, pCellOld, pCellNew ); Abc_SclObjSetCell( pFanin, pCellNew ); Abc_SclUpdateLoad( p, pFanin, pCellOld, pCellNew ); // record the update @@ -646,7 +646,7 @@ int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notch //printf( "gain is %f\n", Vec_FltEntry(p->vNode2Gain, Abc_ObjId(pObj)) ); // update gate Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); - p->SumArea += pCellNew->area - pCellOld->area; + p->SumArea += Abc_SclObjAreaDelta( pObj, pCellOld, pCellNew ); Abc_SclObjSetCell( pObj, pCellNew ); // record the update Vec_IntPush( p->vUpdates, Abc_ObjId(pObj) ); @@ -686,7 +686,7 @@ return Limit; // if ( pCellOld->Order > 0 ) // printf( "%.2f %d -> %d(%d) ", Vec_FltEntry(p->vNode2Gain, iNode), pCellOld->Order, pCellNew->Order, pCellNew->nGates ); // update gate - p->SumArea += pCellNew->area - pCellOld->area; + p->SumArea += Abc_SclObjAreaDelta( pObj, pCellOld, pCellNew ); Abc_SclObjSetCell( pObj, pCellNew ); Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); // record the update @@ -1043,4 +1043,3 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars, ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclUtil.c b/src/map/scl/sclUtil.c index 0deb0f0fd..331dedb5c 100644 --- a/src/map/scl/sclUtil.c +++ b/src/map/scl/sclUtil.c @@ -75,9 +75,11 @@ void Abc_SclSclGates2MioGates( SC_Lib * pLib, Abc_Ntk_t * p ) assert( p->vGates != NULL ); Abc_NtkForEachNodeNotBarBuf1( p, pObj, i ) { + Mio_Gate_t * pGateOld = (Mio_Gate_t *)pObj->pData; + char * pOutName = Abc_SclObjIsMogOutput(pObj) ? Mio_GateReadOutName(pGateOld) : NULL; pCell = Abc_SclObjCell(pObj); assert( pCell->n_inputs == Abc_ObjFaninNum(pObj) ); - pObj->pData = Mio_LibraryReadGateByName( (Mio_Library_t *)p->pManFunc, pCell->pName, NULL ); + pObj->pData = Mio_LibraryReadGateByName( (Mio_Library_t *)p->pManFunc, pCell->pName, pOutName ); Counter += (pObj->pData == NULL); assert( pObj->fMarkA == 0 && pObj->fMarkB == 0 ); CounterAll++; @@ -317,4 +319,3 @@ void Abc_SclInsertBarBufs( Abc_Ntk_t * pNtk, Vec_Int_t * vBufs ) ABC_NAMESPACE_IMPL_END -