/**CFile**************************************************************** FileName [ivyCutTrav.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyCutTrav.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ); static void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ); static void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, int nLeaves, int nWords, Vec_Int_t * vStore ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes cuts for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Store_t * Ivy_NodeFindCutsTravAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront, Vec_Int_t * vStore, Vec_Vec_t * vBitCuts ) { static Ivy_Store_t CutStore, * pCutStore = &CutStore; Vec_Ptr_t * vCuts, * vCuts0, * vCuts1; unsigned * pBitCut; Ivy_Obj_t * pLeaf; Ivy_Cut_t * pCut; int i, k, nWords, nNodes; assert( nLeaves <= IVY_CUT_INPUT ); // find the given number of nodes in the TFI Ivy_NodeComputeVolume( pObj, nNodeLimit - 1, vNodes, vFront ); nNodes = Vec_PtrSize(vNodes); // assert( nNodes <= nNodeLimit ); // make sure vBitCuts has enough room Vec_VecExpand( vBitCuts, nNodes-1 ); Vec_VecClear( vBitCuts ); // prepare the memory manager Vec_IntClear( vStore ); Vec_IntGrow( vStore, 64000 ); // set elementary cuts for the leaves nWords = Extra_BitWordNum( nNodes ); Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pLeaf, i ) { assert( Ivy_ObjTravId(pLeaf) < nNodes ); // get the new bitcut pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); // set it as the cut of this leaf Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); } // compute the cuts for each node Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pLeaf, i ) { // skip the leaves vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pLeaf) ); if ( Vec_PtrSize(vCuts) > 0 ) continue; // add elementary cut pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); // set it as the cut of this leaf Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); // get the fanin cuts vCuts0 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin0(pLeaf) ) ); vCuts1 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin1(pLeaf) ) ); assert( Vec_PtrSize(vCuts0) > 0 ); assert( Vec_PtrSize(vCuts1) > 0 ); // merge the cuts Ivy_NodeFindCutsMerge( vCuts0, vCuts1, vCuts, nLeaves, nWords, vStore ); } // start the structure pCutStore->nCuts = 0; pCutStore->nCutsMax = IVY_CUT_LIMIT; // collect the cuts of the root node vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pObj) ); Vec_PtrForEachEntry( unsigned *, vCuts, pBitCut, i ) { pCut = pCutStore->pCuts + pCutStore->nCuts++; pCut->nSize = 0; pCut->nSizeMax = nLeaves; pCut->uHash = 0; for ( k = 0; k < nNodes; k++ ) if ( Extra_TruthHasBit(pBitCut, k) ) pCut->pArray[ pCut->nSize++ ] = Ivy_ObjId( (Ivy_Obj_t *)Vec_PtrEntry(vNodes, k) ); assert( pCut->nSize <= nLeaves ); if ( pCutStore->nCuts == pCutStore->nCutsMax ) break; } // clean the travIds Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pLeaf, i ) pLeaf->TravId = 0; return pCutStore; } /**Function************************************************************* Synopsis [Creates elementary bit-cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ) { unsigned * pBitCut; pBitCut = Vec_IntFetch( vStore, nWords ); memset( pBitCut, 0, 4 * nWords ); Extra_TruthSetBit( pBitCut, NodeId ); return pBitCut; } /**Function************************************************************* Synopsis [Compares the node by level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_CompareNodesByLevel( Ivy_Obj_t ** ppObj1, Ivy_Obj_t ** ppObj2 ) { Ivy_Obj_t * pObj1 = *ppObj1; Ivy_Obj_t * pObj2 = *ppObj2; if ( pObj1->Level < pObj2->Level ) return -1; if ( pObj1->Level > pObj2->Level ) return 1; return 0; } /**Function************************************************************* Synopsis [Mark all nodes up to the given depth.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeComputeVolumeTrav1_rec( Ivy_Obj_t * pObj, int Depth ) { if ( Ivy_ObjIsCi(pObj) || Depth == 0 ) return; Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin0(pObj), Depth - 1 ); Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin1(pObj), Depth - 1 ); pObj->fMarkA = 1; } /**Function************************************************************* Synopsis [Collect the marked nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeComputeVolumeTrav2_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( !pObj->fMarkA ) return; Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin0(pObj), vNodes ); Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin1(pObj), vNodes ); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) { Ivy_Obj_t * pTemp, * pFanin; int i, nNodes; // mark nodes up to the given depth Ivy_NodeComputeVolumeTrav1_rec( pObj, 6 ); // collect the marked nodes Vec_PtrClear( vFront ); Ivy_NodeComputeVolumeTrav2_rec( pObj, vFront ); // find the fanins that are not marked Vec_PtrClear( vNodes ); Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) { pFanin = Ivy_ObjFanin0(pTemp); if ( !pFanin->fMarkA ) { pFanin->fMarkA = 1; Vec_PtrPush( vNodes, pFanin ); } pFanin = Ivy_ObjFanin1(pTemp); if ( !pFanin->fMarkA ) { pFanin->fMarkA = 1; Vec_PtrPush( vNodes, pFanin ); } } // remember the number of nodes in the frontier nNodes = Vec_PtrSize( vNodes ); // add the remaining nodes Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) Vec_PtrPush( vNodes, pTemp ); // unmark the nodes Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pTemp, i ) { pTemp->fMarkA = 0; pTemp->TravId = i; } // collect the frontier nodes Vec_PtrClear( vFront ); Vec_PtrForEachEntryStop( Ivy_Obj_t *, vNodes, pTemp, i, nNodes ) Vec_PtrPush( vFront, pTemp ); // printf( "%d ", Vec_PtrSize(vNodes) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeComputeVolume2( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) { Ivy_Obj_t * pLeaf, * pPivot, * pFanin; int LevelMax, i; assert( Ivy_ObjIsNode(pObj) ); // clear arrays Vec_PtrClear( vNodes ); Vec_PtrClear( vFront ); // add the root pObj->fMarkA = 1; Vec_PtrPush( vNodes, pObj ); Vec_PtrPush( vFront, pObj ); // expand node with maximum level LevelMax = pObj->Level; do { // get the node to expand pPivot = NULL; Vec_PtrForEachEntryReverse( Ivy_Obj_t *, vFront, pLeaf, i ) { if ( (int)pLeaf->Level == LevelMax ) { pPivot = pLeaf; break; } } // decrease level if we did not find the node if ( pPivot == NULL ) { if ( --LevelMax == 0 ) break; continue; } // the node to expand is found // remove it from frontier Vec_PtrRemove( vFront, pPivot ); // add fanins pFanin = Ivy_ObjFanin0(pPivot); if ( !pFanin->fMarkA ) { pFanin->fMarkA = 1; Vec_PtrPush( vNodes, pFanin ); Vec_PtrPush( vFront, pFanin ); } pFanin = Ivy_ObjFanin1(pPivot); if ( pFanin && !pFanin->fMarkA ) { pFanin->fMarkA = 1; Vec_PtrPush( vNodes, pFanin ); Vec_PtrPush( vFront, pFanin ); } // quit if we collected enough nodes } while ( Vec_PtrSize(vNodes) < nNodeLimit ); // sort nodes by level Vec_PtrSort( vNodes, (int (*)(void))Ivy_CompareNodesByLevel ); // make sure the nodes are ordered in the increasing number of levels pFanin = (Ivy_Obj_t *)Vec_PtrEntry( vNodes, 0 ); pPivot = (Ivy_Obj_t *)Vec_PtrEntryLast( vNodes ); assert( pFanin->Level <= pPivot->Level ); // clean the marks and remember node numbers in the TravId Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pFanin, i ) { pFanin->fMarkA = 0; pFanin->TravId = i; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Extra_TruthOrWords( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nWords ) { int w; for ( w = nWords-1; w >= 0; w-- ) pOut[w] = pIn0[w] | pIn1[w]; } static inline int Extra_TruthIsImplyWords( unsigned * pIn1, unsigned * pIn2, int nWords ) { int w; for ( w = nWords-1; w >= 0; w-- ) if ( pIn1[w] & ~pIn2[w] ) return 0; return 1; } /**Function************************************************************* Synopsis [Merges two sets of bit-cuts at a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, int nLeaves, int nWords, Vec_Int_t * vStore ) { unsigned * pBitCut, * pBitCut0, * pBitCut1, * pBitCutTest; int i, k, c, w, Counter; // iterate through the cut pairs Vec_PtrForEachEntry( unsigned *, vCuts0, pBitCut0, i ) Vec_PtrForEachEntry( unsigned *, vCuts1, pBitCut1, k ) { // skip infeasible cuts Counter = 0; for ( w = 0; w < nWords; w++ ) { Counter += Extra_WordCountOnes( pBitCut0[w] | pBitCut1[w] ); if ( Counter > nLeaves ) break; } if ( Counter > nLeaves ) continue; // the new cut is feasible - create it pBitCutTest = Vec_IntFetch( vStore, nWords ); Extra_TruthOrWords( pBitCutTest, pBitCut0, pBitCut1, nWords ); // filter contained cuts; try to find containing cut w = 0; Vec_PtrForEachEntry( unsigned *, vCuts, pBitCut, c ) { if ( Extra_TruthIsImplyWords( pBitCut, pBitCutTest, nWords ) ) break; if ( Extra_TruthIsImplyWords( pBitCutTest, pBitCut, nWords ) ) continue; Vec_PtrWriteEntry( vCuts, w++, pBitCut ); } if ( c != Vec_PtrSize(vCuts) ) continue; Vec_PtrShrink( vCuts, w ); // add the cut Vec_PtrPush( vCuts, pBitCutTest ); } } /**Function************************************************************* Synopsis [Compute the set of all cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManTestCutsTravAll( Ivy_Man_t * p ) { Ivy_Store_t * pStore; Ivy_Obj_t * pObj; Vec_Ptr_t * vNodes, * vFront; Vec_Int_t * vStore; Vec_Vec_t * vBitCuts; int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; abctime clk = Abc_Clock(); vNodes = Vec_PtrAlloc( 100 ); vFront = Vec_PtrAlloc( 100 ); vStore = Vec_IntAlloc( 100 ); vBitCuts = Vec_VecAlloc( 100 ); nNodeTotal = nNodeOver = 0; nCutsTotal = -Ivy_ManNodeNum(p); Ivy_ManForEachObj( p, pObj, i ) { if ( !Ivy_ObjIsNode(pObj) ) continue; pStore = Ivy_NodeFindCutsTravAll( p, pObj, 4, 60, vNodes, vFront, vStore, vBitCuts ); nCutsCut = pStore->nCuts; nCutsTotal += nCutsCut; nNodeOver += (nCutsCut == IVY_CUT_LIMIT); nNodeTotal++; } printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); ABC_PRT( "Time", Abc_Clock() - clk ); Vec_PtrFree( vNodes ); Vec_PtrFree( vFront ); Vec_IntFree( vStore ); Vec_VecFree( vBitCuts ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END