| /**CFile**************************************************************** | |
| FileName [cutOracle.c] | |
| SystemName [ABC: Logic synthesis and verification system.] | |
| PackageName [K-feasible cut computation package.] | |
| Synopsis [Procedures to compute cuts for a node using the oracle.] | |
| Author [Alan Mishchenko] | |
| Affiliation [UC Berkeley] | |
| Date [Ver. 1.0. Started - June 20, 2005.] | |
| Revision [$Id: cutOracle.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] | |
| ***********************************************************************/ | |
| #include "cutInt.h" | |
| ABC_NAMESPACE_IMPL_START | |
| //////////////////////////////////////////////////////////////////////// | |
| /// DECLARATIONS /// | |
| //////////////////////////////////////////////////////////////////////// | |
| struct Cut_OracleStruct_t_ | |
| { | |
| // cut comptupatation parameters | |
| Cut_Params_t * pParams; | |
| Vec_Int_t * vFanCounts; | |
| int fSimul; | |
| // storage for cuts | |
| Vec_Ptr_t * vCutsNew; | |
| Vec_Ptr_t * vCuts0; | |
| Vec_Ptr_t * vCuts1; | |
| // oracle info | |
| Vec_Int_t * vNodeCuts; | |
| Vec_Int_t * vNodeStarts; | |
| Vec_Int_t * vCutPairs; | |
| // memory management | |
| Extra_MmFixed_t * pMmCuts; | |
| int EntrySize; | |
| int nTruthWords; | |
| // stats | |
| abctime timeTotal; | |
| int nCuts; | |
| int nCutsTriv; | |
| }; | |
| static Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p ); | |
| static Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node ); | |
| static Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); | |
| //////////////////////////////////////////////////////////////////////// | |
| /// FUNCTION DEFINITIONS /// | |
| //////////////////////////////////////////////////////////////////////// | |
| /**Function************************************************************* | |
| Synopsis [Starts the cut oracle.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| Cut_Oracle_t * Cut_OracleStart( Cut_Man_t * pMan ) | |
| { | |
| Cut_Oracle_t * p; | |
| assert( pMan->pParams->nVarsMax >= 3 && pMan->pParams->nVarsMax <= CUT_SIZE_MAX ); | |
| assert( pMan->pParams->fRecord ); | |
| p = ABC_ALLOC( Cut_Oracle_t, 1 ); | |
| memset( p, 0, sizeof(Cut_Oracle_t) ); | |
| // set and correct parameters | |
| p->pParams = pMan->pParams; | |
| // transfer the recording info | |
| p->vNodeCuts = pMan->vNodeCuts; pMan->vNodeCuts = NULL; | |
| p->vNodeStarts = pMan->vNodeStarts; pMan->vNodeStarts = NULL; | |
| p->vCutPairs = pMan->vCutPairs; pMan->vCutPairs = NULL; | |
| // prepare storage for cuts | |
| p->vCutsNew = Vec_PtrAlloc( p->pParams->nIdsMax ); | |
| Vec_PtrFill( p->vCutsNew, p->pParams->nIdsMax, NULL ); | |
| p->vCuts0 = Vec_PtrAlloc( 100 ); | |
| p->vCuts1 = Vec_PtrAlloc( 100 ); | |
| // entry size | |
| p->EntrySize = sizeof(Cut_Cut_t) + p->pParams->nVarsMax * sizeof(int); | |
| if ( p->pParams->fTruth ) | |
| { | |
| if ( p->pParams->nVarsMax > 8 ) | |
| { | |
| p->pParams->fTruth = 0; | |
| printf( "Skipping computation of truth table for more than 8 inputs.\n" ); | |
| } | |
| else | |
| { | |
| p->nTruthWords = Cut_TruthWords( p->pParams->nVarsMax ); | |
| p->EntrySize += p->nTruthWords * sizeof(unsigned); | |
| } | |
| } | |
| // memory for cuts | |
| p->pMmCuts = Extra_MmFixedStart( p->EntrySize ); | |
| return p; | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Stop the cut oracle.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void Cut_OracleStop( Cut_Oracle_t * p ) | |
| { | |
| // if ( p->pParams->fVerbose ) | |
| { | |
| printf( "Cut computation statistics with oracle:\n" ); | |
| printf( "Current cuts = %8d. (Trivial = %d.)\n", p->nCuts-p->nCutsTriv, p->nCutsTriv ); | |
| ABC_PRT( "Total time ", p->timeTotal ); | |
| } | |
| if ( p->vCuts0 ) Vec_PtrFree( p->vCuts0 ); | |
| if ( p->vCuts1 ) Vec_PtrFree( p->vCuts1 ); | |
| if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew ); | |
| if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts ); | |
| if ( p->vNodeCuts ) Vec_IntFree( p->vNodeCuts ); | |
| if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts ); | |
| if ( p->vCutPairs ) Vec_IntFree( p->vCutPairs ); | |
| Extra_MmFixedStop( p->pMmCuts ); | |
| ABC_FREE( p ); | |
| } | |
| /**Function************************************************************* | |
| Synopsis [] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts ) | |
| { | |
| p->vFanCounts = vFanCounts; | |
| } | |
| /**Function************************************************************* | |
| Synopsis [] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| int Cut_OracleReadDrop( Cut_Oracle_t * p ) | |
| { | |
| return p->pParams->fDrop; | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Sets the trivial cut for the node.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node ) | |
| { | |
| assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL ); | |
| Vec_PtrWriteEntry( p->vCutsNew, Node, Cut_CutTriv(p, Node) ); | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Allocates the cut.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p ) | |
| { | |
| Cut_Cut_t * pCut; | |
| // cut allocation | |
| pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts ); | |
| memset( pCut, 0, sizeof(Cut_Cut_t) ); | |
| pCut->nVarsMax = p->pParams->nVarsMax; | |
| pCut->fSimul = p->fSimul; | |
| p->nCuts++; | |
| return pCut; | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Creates the trivial cut.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node ) | |
| { | |
| Cut_Cut_t * pCut; | |
| pCut = Cut_CutStart( p ); | |
| pCut->nLeaves = 1; | |
| pCut->pLeaves[0] = Node; | |
| if ( p->pParams->fTruth ) | |
| { | |
| unsigned * pTruth = Cut_CutReadTruth(pCut); | |
| int i; | |
| for ( i = 0; i < p->nTruthWords; i++ ) | |
| pTruth[i] = 0xAAAAAAAA; | |
| } | |
| p->nCutsTriv++; | |
| return pCut; | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Merges two cuts.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) | |
| { | |
| Cut_Cut_t * pCut; | |
| int Limit, i, k, c; | |
| // create the leaves of the new cut | |
| pCut = Cut_CutStart( p ); | |
| Limit = p->pParams->nVarsMax; | |
| for ( i = k = c = 0; c < Limit; c++ ) | |
| { | |
| if ( k == (int)pCut1->nLeaves ) | |
| { | |
| if ( i == (int)pCut0->nLeaves ) | |
| { | |
| pCut->nLeaves = c; | |
| return pCut; | |
| } | |
| pCut->pLeaves[c] = pCut0->pLeaves[i++]; | |
| continue; | |
| } | |
| if ( i == (int)pCut0->nLeaves ) | |
| { | |
| if ( k == (int)pCut1->nLeaves ) | |
| { | |
| pCut->nLeaves = c; | |
| return pCut; | |
| } | |
| pCut->pLeaves[c] = pCut1->pLeaves[k++]; | |
| continue; | |
| } | |
| if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] ) | |
| { | |
| pCut->pLeaves[c] = pCut0->pLeaves[i++]; | |
| continue; | |
| } | |
| if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] ) | |
| { | |
| pCut->pLeaves[c] = pCut1->pLeaves[k++]; | |
| continue; | |
| } | |
| pCut->pLeaves[c] = pCut0->pLeaves[i++]; | |
| k++; | |
| } | |
| assert( i == (int)pCut0->nLeaves && k == (int)pCut1->nLeaves ); | |
| pCut->nLeaves = c; | |
| return pCut; | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Reconstruct the cuts of the node.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 ) | |
| { | |
| Cut_Cut_t * pList = NULL, ** ppTail = &pList; | |
| Cut_Cut_t * pCut, * pCut0, * pCut1, * pList0, * pList1; | |
| int iCutStart, nCuts, i, Entry; | |
| abctime clk = Abc_Clock(); | |
| // get the cuts of the children | |
| pList0 = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node0 ); | |
| pList1 = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node1 ); | |
| assert( pList0 && pList1 ); | |
| // get the complemented attribute of the cut | |
| p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul); | |
| // collect the cuts | |
| Vec_PtrClear( p->vCuts0 ); | |
| Cut_ListForEachCut( pList0, pCut ) | |
| Vec_PtrPush( p->vCuts0, pCut ); | |
| Vec_PtrClear( p->vCuts1 ); | |
| Cut_ListForEachCut( pList1, pCut ) | |
| Vec_PtrPush( p->vCuts1, pCut ); | |
| // get the first and last cuts of this node | |
| nCuts = Vec_IntEntry(p->vNodeCuts, Node); | |
| iCutStart = Vec_IntEntry(p->vNodeStarts, Node); | |
| // create trivial cut | |
| assert( Vec_IntEntry(p->vCutPairs, iCutStart) == 0 ); | |
| pCut = Cut_CutTriv( p, Node ); | |
| *ppTail = pCut; | |
| ppTail = &pCut->pNext; | |
| // create other cuts | |
| for ( i = 1; i < nCuts; i++ ) | |
| { | |
| Entry = Vec_IntEntry( p->vCutPairs, iCutStart + i ); | |
| pCut0 = (Cut_Cut_t *)Vec_PtrEntry( p->vCuts0, Entry & 0xFFFF ); | |
| pCut1 = (Cut_Cut_t *)Vec_PtrEntry( p->vCuts1, Entry >> 16 ); | |
| pCut = Cut_CutMerge( p, pCut0, pCut1 ); | |
| *ppTail = pCut; | |
| ppTail = &pCut->pNext; | |
| // compute the truth table | |
| if ( p->pParams->fTruth ) | |
| Cut_TruthComputeOld( pCut, pCut0, pCut1, fCompl0, fCompl1 ); | |
| } | |
| *ppTail = NULL; | |
| // write the new cut | |
| assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL ); | |
| Vec_PtrWriteEntry( p->vCutsNew, Node, pList ); | |
| p->timeTotal += Abc_Clock() - clk; | |
| return pList; | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Deallocates the cuts at the node.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void Cut_OracleFreeCuts( Cut_Oracle_t * p, int Node ) | |
| { | |
| Cut_Cut_t * pList, * pCut, * pCut2; | |
| pList = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node ); | |
| if ( pList == NULL ) | |
| return; | |
| Cut_ListForEachCutSafe( pList, pCut, pCut2 ) | |
| Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut ); | |
| Vec_PtrWriteEntry( p->vCutsNew, Node, pList ); | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Consider dropping cuts if they are useless by now.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node ) | |
| { | |
| int nFanouts; | |
| assert( p->vFanCounts ); | |
| nFanouts = Vec_IntEntry( p->vFanCounts, Node ); | |
| assert( nFanouts > 0 ); | |
| if ( --nFanouts == 0 ) | |
| Cut_OracleFreeCuts( p, Node ); | |
| Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts ); | |
| } | |
| //////////////////////////////////////////////////////////////////////// | |
| /// END OF FILE /// | |
| //////////////////////////////////////////////////////////////////////// | |
| ABC_NAMESPACE_IMPL_END | |