/**CFile**************************************************************** FileName [cutNode.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [K-feasible cut computation package.] Synopsis [Procedures to compute cuts for a node.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cutInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ); static int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns 1 if pDom is contained in pCut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cut_CutCheckDominance( Cut_Cut_t * pDom, Cut_Cut_t * pCut ) { int i, k; for ( i = 0; i < (int)pDom->nLeaves; i++ ) { for ( k = 0; k < (int)pCut->nLeaves; k++ ) if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) break; if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut return 0; } // every node in pDom is contained in pCut return 1; } /**Function************************************************************* Synopsis [Filters cuts using dominance.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList ) { Cut_Cut_t * pListR, ** ppListR = &pListR; Cut_Cut_t * pCut, * pCut2, * pDom, * pPrev; // save the first cut *ppListR = pList, ppListR = &pList->pNext; // try to filter out other cuts pPrev = pList; Cut_ListForEachCutSafe( pList->pNext, pCut, pCut2 ) { assert( pCut->nLeaves > 1 ); // go through all the previous cuts up to pCut Cut_ListForEachCutStop( pList->pNext, pDom, pCut ) { if ( pDom->nLeaves > pCut->nLeaves ) continue; if ( (pDom->uSign & pCut->uSign) != pDom->uSign ) continue; if ( Cut_CutCheckDominance( pDom, pCut ) ) break; } if ( pDom != pCut ) // pDom is contained in pCut - recycle pCut { // make sure cuts are connected after removing pPrev->pNext = pCut->pNext; // recycle the cut Cut_CutRecycle( p, pCut ); } else // pDom is NOT contained in pCut - save pCut { *ppListR = pCut, ppListR = &pCut->pNext; pPrev = pCut; } } *ppListR = NULL; } /**Function************************************************************* Synopsis [Checks equality of one cut.] Description [Returns 1 if the cut is removed.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cut_CutFilterOneEqual( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut ) { Cut_Cut_t * pTemp; Cut_ListForEachCut( pSuperList->pHead[pCut->nLeaves], pTemp ) { // skip the non-contained cuts if ( pCut->uSign != pTemp->uSign ) continue; // check containment seriously if ( Cut_CutCheckDominance( pTemp, pCut ) ) { p->nCutsFilter++; Cut_CutRecycle( p, pCut ); return 1; } } return 0; } /**Function************************************************************* Synopsis [Checks containment for one cut.] Description [Returns 1 if the cut is removed.] SideEffects [May remove other cuts in the set.] SeeAlso [] ***********************************************************************/ static inline int Cut_CutFilterOne( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut ) { Cut_Cut_t * pTemp, * pTemp2, ** ppTail; int a; // check if this cut is filtered out by smaller cuts for ( a = 2; a <= (int)pCut->nLeaves; a++ ) { Cut_ListForEachCut( pSuperList->pHead[a], pTemp ) { // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) continue; // check containment seriously if ( Cut_CutCheckDominance( pTemp, pCut ) ) { p->nCutsFilter++; Cut_CutRecycle( p, pCut ); return 1; } } } // filter out other cuts using this one for ( a = pCut->nLeaves + 1; a <= (int)pCut->nVarsMax; a++ ) { ppTail = pSuperList->pHead + a; Cut_ListForEachCutSafe( pSuperList->pHead[a], pTemp, pTemp2 ) { // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) { ppTail = &pTemp->pNext; continue; } // check containment seriously if ( Cut_CutCheckDominance( pCut, pTemp ) ) { p->nCutsFilter++; p->nNodeCuts--; // move the head if ( pSuperList->pHead[a] == pTemp ) pSuperList->pHead[a] = pTemp->pNext; // move the tail if ( pSuperList->ppTail[a] == &pTemp->pNext ) pSuperList->ppTail[a] = ppTail; // skip the given cut in the list *ppTail = pTemp->pNext; // recycle pTemp Cut_CutRecycle( p, pTemp ); } else ppTail = &pTemp->pNext; } assert( ppTail == pSuperList->ppTail[a] ); assert( *ppTail == NULL ); } return 0; } /**Function************************************************************* Synopsis [Checks if the cut is local and can be removed.] Description [Returns 1 if the cut is removed.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cut_CutFilterGlobal( Cut_Man_t * p, Cut_Cut_t * pCut ) { int a; if ( pCut->nLeaves == 1 ) return 0; for ( a = 0; a < (int)pCut->nLeaves; a++ ) if ( Vec_IntEntry( p->vNodeAttrs, pCut->pLeaves[a] ) ) // global return 0; // there is no global nodes, the cut should be removed p->nCutsFilter++; Cut_CutRecycle( p, pCut ); return 1; } /**Function************************************************************* Synopsis [Checks containment for one cut.] Description [Returns 1 if the cut is removed.] SideEffects [May remove other cuts in the set.] SeeAlso [] ***********************************************************************/ static inline int Cut_CutFilterOld( Cut_Man_t * p, Cut_Cut_t * pList, Cut_Cut_t * pCut ) { Cut_Cut_t * pPrev, * pTemp, * pTemp2, ** ppTail; // check if this cut is filtered out by smaller cuts pPrev = NULL; Cut_ListForEachCut( pList, pTemp ) { if ( pTemp->nLeaves > pCut->nLeaves ) break; pPrev = pTemp; // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) continue; // check containment seriously if ( Cut_CutCheckDominance( pTemp, pCut ) ) { p->nCutsFilter++; Cut_CutRecycle( p, pCut ); return 1; } } assert( pPrev->pNext == pTemp ); // filter out other cuts using this one ppTail = &pPrev->pNext; Cut_ListForEachCutSafe( pTemp, pTemp, pTemp2 ) { // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) { ppTail = &pTemp->pNext; continue; } // check containment seriously if ( Cut_CutCheckDominance( pCut, pTemp ) ) { p->nCutsFilter++; p->nNodeCuts--; // skip the given cut in the list *ppTail = pTemp->pNext; // recycle pTemp Cut_CutRecycle( p, pTemp ); } else ppTail = &pTemp->pNext; } assert( *ppTail == NULL ); return 0; } /**Function************************************************************* Synopsis [Processes two cuts.] Description [Returns 1 if the limit has been reached.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cut_CutProcessTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, Cut_List_t * pSuperList ) { Cut_Cut_t * pCut; // merge the cuts if ( pCut0->nLeaves >= pCut1->nLeaves ) pCut = Cut_CutMergeTwo( p, pCut0, pCut1 ); else pCut = Cut_CutMergeTwo( p, pCut1, pCut0 ); if ( pCut == NULL ) return 0; assert( p->pParams->fSeq || pCut->nLeaves > 1 ); // set the signature pCut->uSign = pCut0->uSign | pCut1->uSign; if ( p->pParams->fRecord ) pCut->Num0 = pCut0->Num0, pCut->Num1 = pCut1->Num0; // check containment if ( p->pParams->fFilter ) { if ( Cut_CutFilterOne(p, pSuperList, pCut) ) // if ( Cut_CutFilterOneEqual(p, pSuperList, pCut) ) return 0; if ( p->pParams->fSeq ) { if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) ) return 0; if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) ) return 0; } } if ( p->pParams->fGlobal ) { assert( p->vNodeAttrs != NULL ); if ( Cut_CutFilterGlobal( p, pCut ) ) return 0; } // compute the truth table if ( p->pParams->fTruth ) Cut_TruthCompute( p, pCut, pCut0, pCut1, p->fCompl0, p->fCompl1 ); // add to the list Cut_ListAdd( pSuperList, pCut ); // return status (0 if okay; 1 if exceeded the limit) return ++p->nNodeCuts == p->pParams->nKeepMax; } /**Function************************************************************* Synopsis [Computes the cuts by merging cuts at two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode ) { Cut_List_t Super, * pSuper = &Super; Cut_Cut_t * pList, * pCut; abctime clk; // start the number of cuts at the node p->nNodes++; p->nNodeCuts = 0; // prepare information for recording if ( p->pParams->fRecord ) { Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node0) ); Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node1) ); } // compute the cuts clk = Abc_Clock(); Cut_ListStart( pSuper ); Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, Cut_NodeReadCutsNew(p, Node0), Cut_NodeReadCutsNew(p, Node1), fTriv, TreeCode ); pList = Cut_ListFinish( pSuper ); p->timeMerge += Abc_Clock() - clk; // verify the result of cut computation // Cut_CutListVerify( pList ); // performing the recording if ( p->pParams->fRecord ) { Vec_IntWriteEntry( p->vNodeStarts, Node, Vec_IntSize(p->vCutPairs) ); Cut_ListForEachCut( pList, pCut ) Vec_IntPush( p->vCutPairs, ((pCut->Num1 << 16) | pCut->Num0) ); Vec_IntWriteEntry( p->vNodeCuts, Node, Vec_IntSize(p->vCutPairs) - Vec_IntEntry(p->vNodeStarts, Node) ); } if ( p->pParams->fRecordAig ) { extern void Aig_RManRecord( unsigned * pTruth, int nVarsInit ); Cut_ListForEachCut( pList, pCut ) if ( Cut_CutReadLeaveNum(pCut) > 4 ) Aig_RManRecord( Cut_CutReadTruth(pCut), Cut_CutReadLeaveNum(pCut) ); } // check if the node is over the list if ( p->nNodeCuts == p->pParams->nKeepMax ) p->nCutsLimit++; // set the list at the node Vec_PtrFillExtra( p->vCutsNew, Node + 1, NULL ); assert( Cut_NodeReadCutsNew(p, Node) == NULL ); ///// // pList->pNext = NULL; ///// Cut_NodeWriteCutsNew( p, Node, pList ); // filter the cuts //clk = Abc_Clock(); // if ( p->pParams->fFilter ) // Cut_CutFilter( p, pList0 ); //p->timeFilter += Abc_Clock() - clk; // perform mapping of this node with these cuts clk = Abc_Clock(); if ( p->pParams->fMap && !p->pParams->fSeq ) { // int Delay1, Delay2; // Delay1 = Cut_NodeMapping( p, pList, Node, Node0, Node1 ); // Delay2 = Cut_NodeMapping2( p, pList, Node, Node0, Node1 ); // assert( Delay1 >= Delay2 ); Cut_NodeMapping( p, pList, Node, Node0, Node1 ); } p->timeMap += Abc_Clock() - clk; return pList; } /**Function************************************************************* Synopsis [Returns optimum delay mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ) { Cut_Cut_t * pCut; int DelayMin, DelayCur, i; if ( pCuts == NULL ) p->nDelayMin = -1; if ( p->nDelayMin == -1 ) return -1; DelayMin = 1000000; Cut_ListForEachCut( pCuts, pCut ) { if ( pCut->nLeaves == 1 ) continue; DelayCur = 0; for ( i = 0; i < (int)pCut->nLeaves; i++ ) if ( DelayCur < Vec_IntEntry(p->vDelays, pCut->pLeaves[i]) ) DelayCur = Vec_IntEntry(p->vDelays, pCut->pLeaves[i]); if ( DelayMin > DelayCur ) DelayMin = DelayCur; } if ( DelayMin == 1000000 ) { p->nDelayMin = -1; return -1; } DelayMin++; Vec_IntWriteEntry( p->vDelays, Node, DelayMin ); if ( p->nDelayMin < DelayMin ) p->nDelayMin = DelayMin; return DelayMin; } /**Function************************************************************* Synopsis [Returns optimum delay mapping using the largest cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ) { Cut_Cut_t * pCut0, * pCut1, * pCut; int Delay0, Delay1, Delay; // get the fanin cuts Delay0 = Vec_IntEntry( p->vDelays2, Node0 ); Delay1 = Vec_IntEntry( p->vDelays2, Node1 ); pCut0 = (Delay0 == 0) ? (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node0 ) : (Cut_Cut_t *)Vec_PtrEntry( p->vCutsMax, Node0 ); pCut1 = (Delay1 == 0) ? (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node1 ) : (Cut_Cut_t *)Vec_PtrEntry( p->vCutsMax, Node1 ); if ( Delay0 == Delay1 ) Delay = (Delay0 == 0) ? Delay0 + 1: Delay0; else if ( Delay0 > Delay1 ) { Delay = Delay0; pCut1 = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node1 ); assert( pCut1->nLeaves == 1 ); } else // if ( Delay0 < Delay1 ) { Delay = Delay1; pCut0 = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node0 ); assert( pCut0->nLeaves == 1 ); } // merge the cuts if ( pCut0->nLeaves < pCut1->nLeaves ) pCut = Cut_CutMergeTwo( p, pCut1, pCut0 ); else pCut = Cut_CutMergeTwo( p, pCut0, pCut1 ); if ( pCut == NULL ) { Delay++; pCut = Cut_CutAlloc( p ); pCut->nLeaves = 2; pCut->pLeaves[0] = Node0 < Node1 ? Node0 : Node1; pCut->pLeaves[1] = Node0 < Node1 ? Node1 : Node0; } assert( Delay > 0 ); Vec_IntWriteEntry( p->vDelays2, Node, Delay ); Vec_PtrWriteEntry( p->vCutsMax, Node, pCut ); if ( p->nDelayMin < Delay ) p->nDelayMin = Delay; return Delay; } /**Function************************************************************* Synopsis [Computes area after mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node ) { Cut_Cut_t * pCut; int i, Counter; if ( p->vCutsMax == NULL ) return 0; pCut = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsMax, Node ); if ( pCut == NULL || pCut->nLeaves == 1 ) return 0; Counter = 0; for ( i = 0; i < (int)pCut->nLeaves; i++ ) Counter += Cut_ManMappingArea_rec( p, pCut->pLeaves[i] ); Vec_PtrWriteEntry( p->vCutsMax, Node, NULL ); return 1 + Counter; } /**Function************************************************************* Synopsis [Computes the cuts by merging cuts at two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode ) { Cut_Cut_t * pStop0, * pStop1, * pTemp0, * pTemp1; Cut_Cut_t * pStore0 = NULL, * pStore1 = NULL; // Suppress "might be used uninitialized" int i, nCutsOld, Limit; // start with the elementary cut if ( fTriv ) { // printf( "Creating trivial cut %d.\n", Node ); pTemp0 = Cut_CutCreateTriv( p, Node ); Cut_ListAdd( pSuper, pTemp0 ); p->nNodeCuts++; } // get the cut lists of children if ( pList0 == NULL || pList1 == NULL || (p->pParams->fLocal && TreeCode) ) return; // remember the old number of cuts nCutsOld = p->nCutsCur; Limit = p->pParams->nVarsMax; // get the simultation bit of the node p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul); // set temporary variables p->fCompl0 = fCompl0; p->fCompl1 = fCompl1; // if tree cuts are computed, make sure only the unit cuts propagate over the DAG nodes if ( TreeCode & 1 ) { assert( pList0->nLeaves == 1 ); pStore0 = pList0->pNext; pList0->pNext = NULL; } if ( TreeCode & 2 ) { assert( pList1->nLeaves == 1 ); pStore1 = pList1->pNext; pList1->pNext = NULL; } // find the point in the list where the max-var cuts begin Cut_ListForEachCut( pList0, pStop0 ) if ( pStop0->nLeaves == (unsigned)Limit ) break; Cut_ListForEachCut( pList1, pStop1 ) if ( pStop1->nLeaves == (unsigned)Limit ) break; // small by small Cut_ListForEachCutStop( pList0, pTemp0, pStop0 ) Cut_ListForEachCutStop( pList1, pTemp1, pStop1 ) { if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) goto Quits; } // small by large Cut_ListForEachCutStop( pList0, pTemp0, pStop0 ) Cut_ListForEachCut( pStop1, pTemp1 ) { if ( (pTemp0->uSign & pTemp1->uSign) != pTemp0->uSign ) continue; if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) goto Quits; } // small by large Cut_ListForEachCutStop( pList1, pTemp1, pStop1 ) Cut_ListForEachCut( pStop0, pTemp0 ) { if ( (pTemp0->uSign & pTemp1->uSign) != pTemp1->uSign ) continue; if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) goto Quits; } // large by large Cut_ListForEachCut( pStop0, pTemp0 ) Cut_ListForEachCut( pStop1, pTemp1 ) { assert( pTemp0->nLeaves == (unsigned)Limit && pTemp1->nLeaves == (unsigned)Limit ); if ( pTemp0->uSign != pTemp1->uSign ) continue; for ( i = 0; i < Limit; i++ ) if ( pTemp0->pLeaves[i] != pTemp1->pLeaves[i] ) break; if ( i < Limit ) continue; if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) goto Quits; } if ( p->nNodeCuts == 0 ) p->nNodesNoCuts++; Quits: if ( TreeCode & 1 ) pList0->pNext = pStore0; if ( TreeCode & 2 ) pList1->pNext = pStore1; } /**Function************************************************************* Synopsis [Computes the cuts by unioning cuts at a choice node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes ) { Cut_List_t Super, * pSuper = &Super; Cut_Cut_t * pList, * pListStart, * pCut, * pCut2; Cut_Cut_t * pTop = NULL; // Suppress "might be used uninitialized" int i, k, Node, Root, Limit = p->pParams->nVarsMax; abctime clk = Abc_Clock(); // start the new list Cut_ListStart( pSuper ); // remember the root node to save the resulting cuts Root = Vec_IntEntry( vNodes, 0 ); p->nNodeCuts = 1; // collect small cuts first Vec_PtrClear( p->vTemp ); Vec_IntForEachEntry( vNodes, Node, i ) { // get the cuts of this node pList = Cut_NodeReadCutsNew( p, Node ); Cut_NodeWriteCutsNew( p, Node, NULL ); assert( pList ); // remember the starting point pListStart = pList->pNext; pList->pNext = NULL; // save or recycle the elementary cut if ( i == 0 ) Cut_ListAdd( pSuper, pList ), pTop = pList; else Cut_CutRecycle( p, pList ); // save all the cuts that are smaller than the limit Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) { if ( pCut->nLeaves == (unsigned)Limit ) { Vec_PtrPush( p->vTemp, pCut ); break; } // check containment if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) continue; // set the complemented bit by comparing the first cut with the current cut pCut->fCompl = pTop->fSimul ^ pCut->fSimul; pListStart = pCut->pNext; pCut->pNext = NULL; // add to the list Cut_ListAdd( pSuper, pCut ); if ( ++p->nNodeCuts == p->pParams->nKeepMax ) { // recycle the rest of the cuts of this node Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); // recycle all cuts of other nodes Vec_IntForEachEntryStart( vNodes, Node, k, i+1 ) Cut_NodeFreeCuts( p, Node ); // recycle the saved cuts of other nodes Vec_PtrForEachEntry( Cut_Cut_t *, p->vTemp, pList, k ) Cut_ListForEachCutSafe( pList, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); goto finish; } } } // collect larger cuts next Vec_PtrForEachEntry( Cut_Cut_t *, p->vTemp, pList, i ) { Cut_ListForEachCutSafe( pList, pCut, pCut2 ) { // check containment if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) continue; // set the complemented bit pCut->fCompl = pTop->fSimul ^ pCut->fSimul; pListStart = pCut->pNext; pCut->pNext = NULL; // add to the list Cut_ListAdd( pSuper, pCut ); if ( ++p->nNodeCuts == p->pParams->nKeepMax ) { // recycle the rest of the cuts Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); // recycle the saved cuts of other nodes Vec_PtrForEachEntryStart( Cut_Cut_t *, p->vTemp, pList, k, i+1 ) Cut_ListForEachCutSafe( pList, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); goto finish; } } } finish : // set the cuts at the node assert( Cut_NodeReadCutsNew(p, Root) == NULL ); pList = Cut_ListFinish( pSuper ); Cut_NodeWriteCutsNew( p, Root, pList ); p->timeUnion += Abc_Clock() - clk; // filter the cuts //clk = Abc_Clock(); // if ( p->pParams->fFilter ) // Cut_CutFilter( p, pList ); //p->timeFilter += Abc_Clock() - clk; p->nNodes -= vNodes->nSize - 1; return pList; } /**Function************************************************************* Synopsis [Computes the cuts by unioning cuts at a choice node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst ) { Cut_List_t Super, * pSuper = &Super; Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop; int i, k, Node, Root, Limit = p->pParams->nVarsMax; abctime clk = Abc_Clock(); // start the new list Cut_ListStart( pSuper ); // remember the root node to save the resulting cuts Root = Vec_IntEntry( vNodes, 0 ); p->nNodeCuts = 1; // store the original lists for comparison p->pCompareOld = Cut_NodeReadCutsOld( p, Root ); p->pCompareNew = (CutSetNum >= 0)? Cut_NodeReadCutsNew( p, Root ) : NULL; // get the topmost cut pTop = NULL; if ( (pTop = Cut_NodeReadCutsOld( p, Root )) == NULL ) pTop = Cut_NodeReadCutsNew( p, Root ); assert( pTop != NULL ); // collect small cuts first Vec_PtrClear( p->vTemp ); Vec_IntForEachEntry( vNodes, Node, i ) { // get the cuts of this node if ( i == 0 && CutSetNum >= 0 ) { pList = Cut_NodeReadCutsTemp( p, CutSetNum ); Cut_NodeWriteCutsTemp( p, CutSetNum, NULL ); } else { pList = Cut_NodeReadCutsNew( p, Node ); Cut_NodeWriteCutsNew( p, Node, NULL ); } if ( pList == NULL ) continue; // process the cuts if ( fFirst ) { // remember the starting point pListStart = pList->pNext; pList->pNext = NULL; // save or recycle the elementary cut if ( i == 0 ) Cut_ListAdd( pSuper, pList ); else Cut_CutRecycle( p, pList ); } else pListStart = pList; // save all the cuts that are smaller than the limit Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) { if ( pCut->nLeaves == (unsigned)Limit ) { Vec_PtrPush( p->vTemp, pCut ); break; } // check containment // if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) // continue; if ( p->pParams->fFilter ) { if ( Cut_CutFilterOne(p, pSuper, pCut) ) continue; if ( p->pParams->fSeq ) { if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) ) continue; if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) ) continue; } } // set the complemented bit by comparing the first cut with the current cut pCut->fCompl = pTop->fSimul ^ pCut->fSimul; pListStart = pCut->pNext; pCut->pNext = NULL; // add to the list Cut_ListAdd( pSuper, pCut ); if ( ++p->nNodeCuts == p->pParams->nKeepMax ) { // recycle the rest of the cuts of this node Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); // recycle all cuts of other nodes Vec_IntForEachEntryStart( vNodes, Node, k, i+1 ) Cut_NodeFreeCuts( p, Node ); // recycle the saved cuts of other nodes Vec_PtrForEachEntry( Cut_Cut_t *, p->vTemp, pList, k ) Cut_ListForEachCutSafe( pList, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); goto finish; } } } // collect larger cuts next Vec_PtrForEachEntry( Cut_Cut_t *, p->vTemp, pList, i ) { Cut_ListForEachCutSafe( pList, pCut, pCut2 ) { // check containment // if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) // continue; if ( p->pParams->fFilter ) { if ( Cut_CutFilterOne(p, pSuper, pCut) ) continue; if ( p->pParams->fSeq ) { if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) ) continue; if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) ) continue; } } // set the complemented bit pCut->fCompl = pTop->fSimul ^ pCut->fSimul; pListStart = pCut->pNext; pCut->pNext = NULL; // add to the list Cut_ListAdd( pSuper, pCut ); if ( ++p->nNodeCuts == p->pParams->nKeepMax ) { // recycle the rest of the cuts Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); // recycle the saved cuts of other nodes Vec_PtrForEachEntryStart( Cut_Cut_t *, p->vTemp, pList, k, i+1 ) Cut_ListForEachCutSafe( pList, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); goto finish; } } } finish : // set the cuts at the node pList = Cut_ListFinish( pSuper ); // set the lists at the node // assert( Cut_NodeReadCutsNew(p, Root) == NULL ); // Cut_NodeWriteCutsNew( p, Root, pList ); if ( CutSetNum >= 0 ) { assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL ); Cut_NodeWriteCutsTemp( p, CutSetNum, pList ); } else { assert( Cut_NodeReadCutsNew(p, Root) == NULL ); Cut_NodeWriteCutsNew( p, Root, pList ); } p->timeUnion += Abc_Clock() - clk; // filter the cuts //clk = Abc_Clock(); // if ( p->pParams->fFilter ) // Cut_CutFilter( p, pList ); //p->timeFilter += Abc_Clock() - clk; // if ( fFirst ) // p->nNodes -= vNodes->nSize - 1; return pList; } /**Function************************************************************* Synopsis [Verifies that the list contains only non-dominated cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_CutListVerify( Cut_Cut_t * pList ) { Cut_Cut_t * pCut, * pDom; Cut_ListForEachCut( pList, pCut ) { Cut_ListForEachCutStop( pList, pDom, pCut ) { if ( Cut_CutCheckDominance( pDom, pCut ) ) { printf( "******************* These are contained cuts:\n" ); Cut_CutPrint( pDom, 1 ); Cut_CutPrint( pDom, 1 ); return 0; } } } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END