From b5f4afa73b4190f6c781ba55befd072503f8b658 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 26 Jul 2024 09:10:39 -0700 Subject: [PATCH] Duplicating AIG after synthesis. --- src/aig/gia/giaUtil.c | 121 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/src/aig/gia/giaUtil.c b/src/aig/gia/giaUtil.c index d3a3cb0b5e..2a29ea4314 100644 --- a/src/aig/gia/giaUtil.c +++ b/src/aig/gia/giaUtil.c @@ -3341,6 +3341,127 @@ Gia_Man_t * Gia_ManGenMux( int nIns, char * pNums ) return p; } +/**Function************************************************************* + + Synopsis [Returns 1 if this window has a topo error (forward path from an output to an input).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManWindowCheckTopoError_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + return 1; // there is an error + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; // there is no error; visited this node before + Gia_ObjSetTravIdPrevious(p, pObj); + if ( Gia_ManWindowCheckTopoError_rec(p, Gia_ObjFanin0(pObj)) || Gia_ManWindowCheckTopoError_rec(p, Gia_ObjFanin1(pObj)) ) + return 1; + Gia_ObjSetTravIdCurrent(p, pObj); + return 0; +} +int Gia_ManWindowCheckTopoError( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i, fError = 0; + // outputs should be internal nodes + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + assert(Gia_ObjIsAnd(pObj)); + // mark outputs + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + Gia_ObjSetTravIdCurrent(p, pObj); + // start from inputs and make sure we do not reach any of the outputs + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + fError |= Gia_ManWindowCheckTopoError_rec(p, pObj); + return fError; +} + +/**Function************************************************************* + + Synopsis [Updates the AIG after multiple windows have been optimized.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDupInsertWindows_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vMap, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins ) +{ + if ( ~pObj->Value ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + if ( Vec_IntEntry(vMap, Gia_ObjId(p, pObj)) == -1 ) // this is a regular node + { + Gia_ManDupInsertWindows_rec( pNew, p, Gia_ObjFanin0(pObj), vMap, vvIns, vvOuts, vWins ); + Gia_ManDupInsertWindows_rec( pNew, p, Gia_ObjFanin1(pObj), vMap, vvIns, vvOuts, vWins ); + return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + // this node is an output of a window + int iWin = Vec_IntEntry(vMap, Gia_ObjId(p, pObj)); + Vec_Int_t * vIns = (Vec_Int_t *)Vec_PtrEntry(vvIns, iWin); + Vec_Int_t * vOuts = (Vec_Int_t *)Vec_PtrEntry(vvOuts, iWin); + Gia_Man_t * pWin = (Gia_Man_t *)Vec_PtrEntry(vWins, iWin); + // build transinvite fanins of window inputs + Gia_Obj_t * pNode; int i; + Gia_ManConst0(pWin)->Value = 0; + Gia_ManForEachObjVec( vIns, p, pNode, i ) + Gia_ManPi(pWin, i)->Value = Gia_ManDupInsertWindows_rec( pNew, p, pNode, vMap, vvIns, vvOuts, vWins ); + // add window nodes + Gia_ManForEachAnd( pWin, pNode, i ) + pNode->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pNode), Gia_ObjFanin1Copy(pNode) ); + // transfer to window outputs + Gia_ManForEachObjVec( vOuts, p, pNode, i ) + pNode->Value = Gia_ObjFanin0Copy(Gia_ManPo(pWin, i)); + assert( ~pObj->Value ); + return pObj->Value; +} +Gia_Man_t * Gia_ManDupInsertWindows( Gia_Man_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins ) +{ + // check consistency of input data + Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, k, iNode; + Vec_PtrForEachEntry( Gia_Man_t *, vWins, pTemp, i ) { + Vec_Int_t * vIns = (Vec_Int_t *)Vec_PtrEntry(vvIns, i); + Vec_Int_t * vOuts = (Vec_Int_t *)Vec_PtrEntry(vvOuts, i); + assert( Vec_IntSize(vIns) == Gia_ManPiNum(pTemp) ); + assert( Vec_IntSize(vOuts) == Gia_ManPoNum(pTemp) ); + assert( !Gia_ManWindowCheckTopoError(p, vIns, vOuts) ); + } + // create mapping of window outputs into window IDs + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ), * vOuts; + Vec_PtrForEachEntry( Vec_Int_t *, vvOuts, vOuts, i ) + Vec_IntForEachEntry( vOuts, iNode, k ) + Vec_IntWriteEntry( vMap, iNode, i ); + // create the resulting AIG by performing DFS from the POs of the original AIG + // it goes recursively through original nodes and windows until it reaches the PIs of the original AIG + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupInsertWindows_rec( pNew, p, Gia_ObjFanin0(pObj), vMap, vvIns, vvOuts, vWins ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + // cleanup and return + Vec_IntFree( vMap ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManPrint( pNew ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// ////////////////////////////////////////////////////////////////////////