/**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