/**CFile**************************************************************** FileName [nwkUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" #include "kit.h" #include //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Increments the current traversal ID of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManIncrementTravId( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pObj; int i; if ( pNtk->nTravIds >= (1<<26)-1 ) { pNtk->nTravIds = 0; Nwk_ManForEachObj( pNtk, pObj, i ) pObj->TravId = 0; } pNtk->nTravIds++; } /**Function************************************************************* Synopsis [Reads the maximum number of fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManGetFaninMax( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pNode; int i, nFaninsMax = 0; Nwk_ManForEachNode( pNtk, pNode, i ) { if ( nFaninsMax < Nwk_ObjFaninNum(pNode) ) nFaninsMax = Nwk_ObjFaninNum(pNode); } return nFaninsMax; } /**Function************************************************************* Synopsis [Reads the total number of all fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManGetTotalFanins( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pNode; int i, nFanins = 0; Nwk_ManForEachNode( pNtk, pNode, i ) nFanins += Nwk_ObjFaninNum(pNode); return nFanins; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPiNum( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pNode; int i, Counter = 0; Nwk_ManForEachCi( pNtk, pNode, i ) Counter += Nwk_ObjIsPi( pNode ); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPoNum( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pNode; int i, Counter = 0; Nwk_ManForEachCo( pNtk, pNode, i ) Counter += Nwk_ObjIsPo( pNode ); return Counter; } /**Function************************************************************* Synopsis [Reads the number of BDD nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManGetAigNodeNum( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pNode; int i, nNodes = 0; Nwk_ManForEachNode( pNtk, pNode, i ) { if ( pNode->pFunc == NULL ) { printf( "Nwk_ManGetAigNodeNum(): Local AIG of node %d is not assigned.\n", pNode->Id ); continue; } if ( Nwk_ObjFaninNum(pNode) < 2 ) continue; nNodes += Hop_DagSize( pNode->pFunc ); } return nNodes; } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in increasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_NodeCompareLevelsIncrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ) { int Diff = (*pp1)->Level - (*pp2)->Level; if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_NodeCompareLevelsDecrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ) { int Diff = (*pp1)->Level - (*pp2)->Level; if ( Diff > 0 ) return -1; if ( Diff < 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Deletes the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ObjPrint( Nwk_Obj_t * pObj ) { Nwk_Obj_t * pNext; int i; printf( "ObjId = %5d. ", pObj->Id ); if ( Nwk_ObjIsPi(pObj) ) printf( "PI" ); if ( Nwk_ObjIsPo(pObj) ) printf( "PO" ); if ( Nwk_ObjIsNode(pObj) ) printf( "Node" ); printf( " Fanins = " ); Nwk_ObjForEachFanin( pObj, pNext, i ) printf( "%d ", pNext->Id ); printf( " Fanouts = " ); Nwk_ObjForEachFanout( pObj, pNext, i ) printf( "%d ", pNext->Id ); printf( "\n" ); } /**Function************************************************************* Synopsis [Deletes the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames ) { FILE * pFile; Vec_Ptr_t * vNodes; Vec_Int_t * vTruth; Vec_Int_t * vCover; Nwk_Obj_t * pObj, * pFanin; Aig_MmFlex_t * pMem; char * pSop = NULL; unsigned * pTruth; int i, k, nDigits, Counter = 0; if ( Nwk_ManPoNum(pNtk) == 0 ) { printf( "Nwk_ManDumpBlif(): Network does not have POs.\n" ); return; } // collect nodes in the DFS order nDigits = Aig_Base10Log( Nwk_ManObjNumMax(pNtk) ); // write the file pFile = fopen( pFileName, "w" ); fprintf( pFile, "# BLIF file written by procedure Nwk_ManDumpBlif()\n" ); // fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); fprintf( pFile, ".model %s\n", pNtk->pName ); // write PIs fprintf( pFile, ".inputs" ); Nwk_ManForEachCi( pNtk, pObj, i ) if ( vPiNames ) fprintf( pFile, " %s", Vec_PtrEntry(vPiNames, i) ); else fprintf( pFile, " n%0*d", nDigits, pObj->Id ); fprintf( pFile, "\n" ); // write POs fprintf( pFile, ".outputs" ); Nwk_ManForEachCo( pNtk, pObj, i ) if ( vPoNames ) fprintf( pFile, " %s", Vec_PtrEntry(vPoNames, i) ); else fprintf( pFile, " n%0*d", nDigits, pObj->Id ); fprintf( pFile, "\n" ); // write nodes pMem = Aig_MmFlexStart(); vTruth = Vec_IntAlloc( 1 << 16 ); vCover = Vec_IntAlloc( 1 << 16 ); vNodes = Nwk_ManDfs( pNtk ); Vec_PtrForEachEntry( vNodes, pObj, i ) { if ( !Nwk_ObjIsNode(pObj) ) continue; // derive SOP for the AIG pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 ); if ( Hop_IsComplement(pObj->pFunc) ) Kit_TruthNot( pTruth, pTruth, Nwk_ObjFaninNum(pObj) ); pSop = Kit_PlaFromTruth( pMem, pTruth, Nwk_ObjFaninNum(pObj), vCover ); // write the node fprintf( pFile, ".names" ); if ( !Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) && !Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) ) { Nwk_ObjForEachFanin( pObj, pFanin, k ) if ( vPiNames && Nwk_ObjIsPi(pFanin) ) fprintf( pFile, " %s", Vec_PtrEntry(vPiNames, Nwk_ObjPioNum(pFanin)) ); else fprintf( pFile, " n%0*d", nDigits, pFanin->Id ); } fprintf( pFile, " n%0*d\n", nDigits, pObj->Id ); // write the function fprintf( pFile, "%s", pSop ); } Vec_IntFree( vCover ); Vec_IntFree( vTruth ); Vec_PtrFree( vNodes ); Aig_MmFlexStop( pMem, 0 ); // write POs Nwk_ManForEachCo( pNtk, pObj, i ) { fprintf( pFile, ".names" ); if ( vPiNames && Nwk_ObjIsPi(Nwk_ObjFanin0(pObj)) ) fprintf( pFile, " %s", Vec_PtrEntry(vPiNames, Nwk_ObjPioNum(Nwk_ObjFanin0(pObj))) ); else fprintf( pFile, " n%0*d", nDigits, Nwk_ObjFanin0(pObj)->Id ); if ( vPoNames ) fprintf( pFile, " %s\n", Vec_PtrEntry(vPoNames, Nwk_ObjPioNum(pObj)) ); else fprintf( pFile, " n%0*d\n", nDigits, pObj->Id ); fprintf( pFile, "%d 1\n", !pObj->fInvert ); } fprintf( pFile, ".end\n\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Prints the distribution of fanins/fanouts in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManPrintFanioNew( Nwk_Man_t * pNtk ) { char Buffer[100]; Nwk_Obj_t * pNode; Vec_Int_t * vFanins, * vFanouts; int nFanins, nFanouts, nFaninsMax, nFanoutsMax, nFaninsAll, nFanoutsAll; int i, k, nSizeMax; // determine the largest fanin and fanout nFaninsMax = nFanoutsMax = 0; nFaninsAll = nFanoutsAll = 0; Nwk_ManForEachNode( pNtk, pNode, i ) { nFanins = Nwk_ObjFaninNum(pNode); nFanouts = Nwk_ObjFanoutNum(pNode); nFaninsAll += nFanins; nFanoutsAll += nFanouts; nFaninsMax = AIG_MAX( nFaninsMax, nFanins ); nFanoutsMax = AIG_MAX( nFanoutsMax, nFanouts ); } // allocate storage for fanin/fanout numbers nSizeMax = AIG_MAX( 10 * (Aig_Base10Log(nFaninsMax) + 1), 10 * (Aig_Base10Log(nFanoutsMax) + 1) ); vFanins = Vec_IntStart( nSizeMax ); vFanouts = Vec_IntStart( nSizeMax ); // count the number of fanins and fanouts Nwk_ManForEachNode( pNtk, pNode, i ) { nFanins = Nwk_ObjFaninNum(pNode); nFanouts = Nwk_ObjFanoutNum(pNode); // nFanouts = Nwk_NodeMffcSize(pNode); if ( nFanins < 10 ) Vec_IntAddToEntry( vFanins, nFanins, 1 ); else if ( nFanins < 100 ) Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 ); else if ( nFanins < 1000 ) Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 ); else if ( nFanins < 10000 ) Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 ); else if ( nFanins < 100000 ) Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 ); else if ( nFanins < 1000000 ) Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 ); else if ( nFanins < 10000000 ) Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 ); if ( nFanouts < 10 ) Vec_IntAddToEntry( vFanouts, nFanouts, 1 ); else if ( nFanouts < 100 ) Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 ); else if ( nFanouts < 1000 ) Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 ); else if ( nFanouts < 10000 ) Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 ); else if ( nFanouts < 100000 ) Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 ); else if ( nFanouts < 1000000 ) Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 ); else if ( nFanouts < 10000000 ) Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 ); } printf( "The distribution of fanins and fanouts in the network:\n" ); printf( " Number Nodes with fanin Nodes with fanout\n" ); for ( k = 0; k < nSizeMax; k++ ) { if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 ) continue; if ( k < 10 ) printf( "%15d : ", k ); else { sprintf( Buffer, "%d - %d", (int)pow(10, k/10) * (k%10), (int)pow(10, k/10) * (k%10+1) - 1 ); printf( "%15s : ", Buffer ); } if ( vFanins->pArray[k] == 0 ) printf( " " ); else printf( "%12d ", vFanins->pArray[k] ); printf( " " ); if ( vFanouts->pArray[k] == 0 ) printf( " " ); else printf( "%12d ", vFanouts->pArray[k] ); printf( "\n" ); } Vec_IntFree( vFanins ); Vec_IntFree( vFanouts ); printf( "Fanins: Max = %d. Ave = %.2f. Fanouts: Max = %d. Ave = %.2f.\n", nFaninsMax, 1.0*nFaninsAll/Nwk_ManNodeNum(pNtk), nFanoutsMax, 1.0*nFanoutsAll/Nwk_ManNodeNum(pNtk) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManCleanMarks( Nwk_Man_t * pMan ) { Nwk_Obj_t * pObj; int i; Nwk_ManForEachObj( pMan, pObj, i ) pObj->MarkA = pObj->MarkB = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManMarkCone_rec( Nwk_Obj_t * pObj ) { Nwk_Obj_t * pNext; int i; if ( pObj->MarkA ) return; pObj->MarkA = 1; Nwk_ObjForEachFanin( pObj, pNext, i ) Nwk_ManMarkCone_rec( pNext ); } /**Function************************************************************* Synopsis [Returns 1 if the flow can be pushed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushFlow_rec( Nwk_Obj_t * pObj ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjIsTravIdCurrent( pObj ) ) return 0; Nwk_ObjSetTravIdCurrent( pObj ); // check the case when there is no flow if ( !pObj->MarkB ) { if ( pObj->MarkA ) return pObj->MarkB = 1; Nwk_ObjForEachFanin( pObj, pNext, i ) if ( Nwk_ManPushFlow_rec( pNext ) ) return pObj->MarkB = 1; } // check the case when there is no flow or we could not push the flow Nwk_ObjForEachFanout( pObj, pNext, i ) if ( Nwk_ManPushFlow_rec( pNext ) ) return 1; return 0; } /**Function************************************************************* Synopsis [Computes min-cut using max-flow.] Description [MarkA means the sink. MarkB means the flow is present.] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManComputeCut( Nwk_Man_t * pMan, int nLatches ) { Vec_Ptr_t * vNodes; Nwk_Obj_t * pObj, * pNext; int i, k, RetValue, Counter = 0; // set the sequential parameters pMan->nLatches = nLatches; pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; // mark the CIs Nwk_ManForEachCi( pMan, pObj, i ) pObj->MarkA = 1; // mark the TFI of the POs Nwk_ManForEachPoSeq( pMan, pObj, i ) Nwk_ManMarkCone_rec( pObj ); // start flow computation from each LI // Nwk_ManIncrementTravId( pMan ); Nwk_ManForEachLiSeq( pMan, pObj, i ) { Nwk_ManIncrementTravId( pMan ); if ( !Nwk_ManPushFlow_rec( pObj ) ) continue; // Nwk_ManIncrementTravId( pMan ); Counter++; } // mark the nodes reachable from the LIs Nwk_ManIncrementTravId( pMan ); Nwk_ManForEachLiSeq( pMan, pObj, i ) { RetValue = Nwk_ManPushFlow_rec( pObj ); assert( RetValue == 0 ); } // collect labeled nodes whose all fanins are labeled vNodes = Vec_PtrAlloc( Counter ); Nwk_ManForEachObj( pMan, pObj, i ) { // skip unlabeled if ( !Nwk_ObjIsTravIdCurrent(pObj) ) continue; // visit the fanins Nwk_ObjForEachFanin( pObj, pNext, k ) if ( !Nwk_ObjIsTravIdCurrent(pNext) ) break; if ( k == Nwk_ObjFaninNum(pObj) ) Vec_PtrPush( vNodes, pObj ); } // unlabel these nodes Nwk_ManIncrementTravId( pMan ); Vec_PtrForEachEntry( vNodes, pObj, i ) Nwk_ObjSetTravIdCurrent( pObj ); // collect labeled nodes having unlabeled fanouts Vec_PtrClear( vNodes ); Nwk_ManForEachObj( pMan, pObj, i ) { // skip unreachable nodes if ( !Nwk_ObjIsTravIdPrevious(pObj) ) continue; if ( Nwk_ObjIsCo(pObj) ) { Vec_PtrPush( vNodes, pObj ); continue; } Nwk_ObjForEachFanout( pObj, pNext, k ) if ( Nwk_ObjIsTravIdCurrent(pNext) ) break; if ( k < Nwk_ObjFanoutNum(pObj) ) Vec_PtrPush( vNodes, pObj ); } // clean the marks Nwk_ManCleanMarks( pMan ); printf( "Flow = %5d. Cut = %5d. \n", Counter, Vec_PtrSize(vNodes) ); Vec_PtrFree( vNodes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// ////////////////////////////////////////////////////////////////////////