| /**CFile**************************************************************** | |
| FileName [abcCut.c] | |
| SystemName [ABC: Logic synthesis and verification system.] | |
| PackageName [Network and node package.] | |
| Synopsis [Interface to cut computation.] | |
| Author [Alan Mishchenko] | |
| Affiliation [UC Berkeley] | |
| Date [Ver. 1.0. Started - June 20, 2005.] | |
| Revision [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] | |
| ***********************************************************************/ | |
| #include "base/abc/abc.h" | |
| #include "cut.h" | |
| ABC_NAMESPACE_IMPL_START | |
| //////////////////////////////////////////////////////////////////////// | |
| /// DECLARATIONS /// | |
| //////////////////////////////////////////////////////////////////////// | |
| static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ); | |
| static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ); | |
| extern int nTotal, nGood, nEqual; | |
| // temporary | |
| //Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) { return NULL; } | |
| Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) | |
| { | |
| Vec_Int_t * vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); | |
| int i; | |
| Abc_Obj_t * pObj; | |
| // Abc_NtkForEachCi( pNtk, pObj, i ) | |
| // Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); | |
| Abc_NtkForEachObj( pNtk, pObj, i ) | |
| { | |
| // if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) ) | |
| if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) ) | |
| Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); | |
| } | |
| return vAttrs; | |
| } | |
| //////////////////////////////////////////////////////////////////////// | |
| /// FUNCTION DEFINITIONS /// | |
| //////////////////////////////////////////////////////////////////////// | |
| /**Function************************************************************* | |
| Synopsis [Computes the cuts for the network.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) | |
| { | |
| ProgressBar * pProgress; | |
| Cut_Man_t * p; | |
| Abc_Obj_t * pObj, * pNode; | |
| Vec_Ptr_t * vNodes; | |
| Vec_Int_t * vChoices; | |
| int i; | |
| clock_t clk = clock(); | |
| extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ); | |
| extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ); | |
| nTotal = nGood = nEqual = 0; | |
| assert( Abc_NtkIsStrash(pNtk) ); | |
| // start the manager | |
| pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); | |
| p = Cut_ManStart( pParams ); | |
| // compute node attributes if local or global cuts are requested | |
| if ( pParams->fGlobal || pParams->fLocal ) | |
| { | |
| extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ); | |
| Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) ); | |
| } | |
| // prepare for cut dropping | |
| if ( pParams->fDrop ) | |
| Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); | |
| // set cuts for PIs | |
| Abc_NtkForEachCi( pNtk, pObj, i ) | |
| if ( Abc_ObjFanoutNum(pObj) > 0 ) | |
| Cut_NodeSetTriv( p, pObj->Id ); | |
| // compute cuts for internal nodes | |
| vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs | |
| vChoices = Vec_IntAlloc( 100 ); | |
| pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) ); | |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) | |
| { | |
| // when we reached a CO, it is time to deallocate the cuts | |
| if ( Abc_ObjIsCo(pObj) ) | |
| { | |
| if ( pParams->fDrop ) | |
| Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); | |
| continue; | |
| } | |
| // skip constant node, it has no cuts | |
| // if ( Abc_NodeIsConst(pObj) ) | |
| // continue; | |
| Extra_ProgressBarUpdate( pProgress, i, NULL ); | |
| // compute the cuts to the internal node | |
| Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree ); | |
| // consider dropping the fanins cuts | |
| if ( pParams->fDrop ) | |
| { | |
| Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); | |
| Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); | |
| } | |
| // add cuts due to choices | |
| if ( Abc_AigNodeIsChoice(pObj) ) | |
| { | |
| Vec_IntClear( vChoices ); | |
| for ( pNode = pObj; pNode; pNode = pNode->pData ) | |
| Vec_IntPush( vChoices, pNode->Id ); | |
| Cut_NodeUnionCuts( p, vChoices ); | |
| } | |
| } | |
| Extra_ProgressBarStop( pProgress ); | |
| Vec_PtrFree( vNodes ); | |
| Vec_IntFree( vChoices ); | |
| PRT( "Total", clock() - clk ); | |
| //Abc_NtkPrintCuts( p, pNtk, 0 ); | |
| // Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk ); | |
| // temporary printout of stats | |
| if ( nTotal ) | |
| printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal ); | |
| return p; | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Cut computation using the oracle.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p ) | |
| { | |
| Abc_Obj_t * pObj; | |
| Vec_Ptr_t * vNodes; | |
| int i; | |
| clock_t clk = clock(); | |
| int fDrop = Cut_OracleReadDrop(p); | |
| assert( Abc_NtkIsStrash(pNtk) ); | |
| // prepare cut droppping | |
| if ( fDrop ) | |
| Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); | |
| // set cuts for PIs | |
| Abc_NtkForEachCi( pNtk, pObj, i ) | |
| if ( Abc_ObjFanoutNum(pObj) > 0 ) | |
| Cut_OracleNodeSetTriv( p, pObj->Id ); | |
| // compute cuts for internal nodes | |
| vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs | |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) | |
| { | |
| // when we reached a CO, it is time to deallocate the cuts | |
| if ( Abc_ObjIsCo(pObj) ) | |
| { | |
| if ( fDrop ) | |
| Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); | |
| continue; | |
| } | |
| // skip constant node, it has no cuts | |
| // if ( Abc_NodeIsConst(pObj) ) | |
| // continue; | |
| // compute the cuts to the internal node | |
| Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), | |
| Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); | |
| // consider dropping the fanins cuts | |
| if ( fDrop ) | |
| { | |
| Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); | |
| Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); | |
| } | |
| } | |
| Vec_PtrFree( vNodes ); | |
| //PRT( "Total", clock() - clk ); | |
| //Abc_NtkPrintCuts_( p, pNtk, 0 ); | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Computes the cuts for the network.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) | |
| { | |
| /* | |
| Cut_Man_t * p; | |
| Abc_Obj_t * pObj, * pNode; | |
| int i, nIters, fStatus; | |
| Vec_Int_t * vChoices; | |
| clock_t clk = clock(); | |
| assert( Abc_NtkIsSeq(pNtk) ); | |
| assert( pParams->fSeq ); | |
| // assert( Abc_NtkIsDfsOrdered(pNtk) ); | |
| // start the manager | |
| pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); | |
| pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk ); | |
| p = Cut_ManStart( pParams ); | |
| // set cuts for the constant node and the PIs | |
| pObj = Abc_AigConst1(pNtk); | |
| if ( Abc_ObjFanoutNum(pObj) > 0 ) | |
| Cut_NodeSetTriv( p, pObj->Id ); | |
| Abc_NtkForEachPi( pNtk, pObj, i ) | |
| { | |
| //printf( "Setting trivial cut %d.\n", pObj->Id ); | |
| Cut_NodeSetTriv( p, pObj->Id ); | |
| } | |
| // label the cutset nodes and set their number in the array | |
| // assign the elementary cuts to the cutset nodes | |
| Abc_SeqForEachCutsetNode( pNtk, pObj, i ) | |
| { | |
| assert( pObj->fMarkC == 0 ); | |
| pObj->fMarkC = 1; | |
| pObj->pCopy = (Abc_Obj_t *)i; | |
| Cut_NodeSetTriv( p, pObj->Id ); | |
| //printf( "Setting trivial cut %d.\n", pObj->Id ); | |
| } | |
| // process the nodes | |
| vChoices = Vec_IntAlloc( 100 ); | |
| for ( nIters = 0; nIters < 10; nIters++ ) | |
| { | |
| //printf( "ITERATION %d:\n", nIters ); | |
| // compute the cuts for the internal nodes | |
| Abc_AigForEachAnd( pNtk, pObj, i ) | |
| { | |
| Abc_NodeGetCutsSeq( p, pObj, nIters==0 ); | |
| // add cuts due to choices | |
| if ( Abc_AigNodeIsChoice(pObj) ) | |
| { | |
| Vec_IntClear( vChoices ); | |
| for ( pNode = pObj; pNode; pNode = pNode->pData ) | |
| Vec_IntPush( vChoices, pNode->Id ); | |
| Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 ); | |
| } | |
| } | |
| // merge the new cuts with the old cuts | |
| Abc_NtkForEachPi( pNtk, pObj, i ) | |
| Cut_NodeNewMergeWithOld( p, pObj->Id ); | |
| Abc_AigForEachAnd( pNtk, pObj, i ) | |
| Cut_NodeNewMergeWithOld( p, pObj->Id ); | |
| // for the cutset, transfer temp cuts to new cuts | |
| fStatus = 0; | |
| Abc_SeqForEachCutsetNode( pNtk, pObj, i ) | |
| fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i ); | |
| if ( fStatus == 0 ) | |
| break; | |
| } | |
| Vec_IntFree( vChoices ); | |
| // if the status is not finished, transfer new to old for the cutset | |
| Abc_SeqForEachCutsetNode( pNtk, pObj, i ) | |
| Cut_NodeNewMergeWithOld( p, pObj->Id ); | |
| // transfer the old cuts to the new positions | |
| Abc_NtkForEachObj( pNtk, pObj, i ) | |
| Cut_NodeOldTransferToNew( p, pObj->Id ); | |
| // unlabel the cutset nodes | |
| Abc_SeqForEachCutsetNode( pNtk, pObj, i ) | |
| pObj->fMarkC = 0; | |
| if ( pParams->fVerbose ) | |
| { | |
| PRT( "Total", clock() - clk ); | |
| printf( "Converged after %d iterations.\n", nIters ); | |
| } | |
| //Abc_NtkPrintCuts( p, pNtk, 1 ); | |
| return p; | |
| */ | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Computes the cuts for the network.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) | |
| { | |
| void * pList; | |
| if ( pList = Abc_NodeReadCuts( p, pObj ) ) | |
| return pList; | |
| Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree ); | |
| Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree ); | |
| return Abc_NodeGetCuts( p, pObj, fDag, fTree ); | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Computes the cuts for the network.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) | |
| { | |
| Abc_Obj_t * pFanin; | |
| int fDagNode, fTriv, TreeCode = 0; | |
| // assert( Abc_NtkIsStrash(pObj->pNtk) ); | |
| assert( Abc_ObjFaninNum(pObj) == 2 ); | |
| // check if the node is a DAG node | |
| fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)); | |
| // increment the counter of DAG nodes | |
| if ( fDagNode ) Cut_ManIncrementDagNodes( p ); | |
| // add the trivial cut if the node is a DAG node, or if we compute all cuts | |
| fTriv = fDagNode || !fDag; | |
| // check if fanins are DAG nodes | |
| if ( fTree ) | |
| { | |
| pFanin = Abc_ObjFanin0(pObj); | |
| TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)); | |
| pFanin = Abc_ObjFanin1(pObj); | |
| TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1); | |
| } | |
| // changes due to the global/local cut computation | |
| { | |
| Cut_Params_t * pParams = Cut_ManReadParams(p); | |
| if ( pParams->fLocal ) | |
| { | |
| Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs(p); | |
| fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id ); | |
| if ( fDagNode ) Cut_ManIncrementDagNodes( p ); | |
| // fTriv = fDagNode || !pParams->fGlobal; | |
| fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id ); | |
| TreeCode = 0; | |
| pFanin = Abc_ObjFanin0(pObj); | |
| TreeCode |= Vec_IntEntry( vNodeAttrs, pFanin->Id ); | |
| pFanin = Abc_ObjFanin1(pObj); | |
| TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1); | |
| } | |
| } | |
| return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), | |
| Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode ); | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Computes the cuts for the network.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv ) | |
| { | |
| int CutSetNum; | |
| assert( Abc_NtkIsSeq(pObj->pNtk) ); | |
| assert( Abc_ObjFaninNum(pObj) == 2 ); | |
| fTriv = pObj->fMarkC ? 0 : fTriv; | |
| CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1; | |
| Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), | |
| Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum ); | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Computes the cuts for the network.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ) | |
| { | |
| return Cut_NodeReadCutsNew( p, pObj->Id ); | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Computes the cuts for the network.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ) | |
| { | |
| Cut_NodeFreeCuts( p, pObj->Id ); | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Computes the cuts for the network.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ) | |
| { | |
| Cut_Man_t * pMan = p; | |
| Cut_Cut_t * pList; | |
| Abc_Obj_t * pObj; | |
| int i; | |
| printf( "Cuts of the network:\n" ); | |
| Abc_NtkForEachObj( pNtk, pObj, i ) | |
| { | |
| pList = Abc_NodeReadCuts( p, pObj ); | |
| printf( "Node %s:\n", Abc_ObjName(pObj) ); | |
| Cut_CutPrintList( pList, fSeq ); | |
| } | |
| } | |
| /**Function************************************************************* | |
| Synopsis [Computes the cuts for the network.] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ) | |
| { | |
| Cut_Man_t * pMan = p; | |
| Cut_Cut_t * pList; | |
| Abc_Obj_t * pObj; | |
| pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 ); | |
| pList = Abc_NodeReadCuts( p, pObj ); | |
| printf( "Node %s:\n", Abc_ObjName(pObj) ); | |
| Cut_CutPrintList( pList, fSeq ); | |
| } | |
| //////////////////////////////////////////////////////////////////////// | |
| /// END OF FILE /// | |
| //////////////////////////////////////////////////////////////////////// | |
| ABC_NAMESPACE_IMPL_END | |