/**CFile**************************************************************** FileName [abcFanOrder.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Fanin ordering procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcFanOrder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reorder fanins of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkOrderFaninsById( Abc_Ntk_t * pNtk ) { Vec_Int_t * vOrder; Vec_Str_t * vStore; Abc_Obj_t * pNode; char * pSop, * pSopNew; char * pCube, * pCubeNew; int nVars, i, v, * pOrder; assert( Abc_NtkHasSop(pNtk) ); vOrder = Vec_IntAlloc( 100 ); vStore = Vec_StrAlloc( 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) { pSop = (char *)pNode->pData; nVars = Abc_SopGetVarNum(pSop); assert( nVars == Abc_ObjFaninNum(pNode) ); Vec_IntClear( vOrder ); for ( v = 0; v < nVars; v++ ) Vec_IntPush( vOrder, v ); pOrder = Vec_IntArray(vOrder); Vec_IntSelectSortCost( pOrder, nVars, &pNode->vFanins ); // copy the cover Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); memcpy( Vec_StrArray(vStore), pSop, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); pSopNew = pCubeNew = pSop; pSop = Vec_StrArray(vStore); // generate permuted one Abc_SopForEachCube( pSop, nVars, pCube ) { for ( v = 0; v < nVars; v++ ) pCubeNew[v] = '-'; for ( v = 0; v < nVars; v++ ) if ( pCube[pOrder[v]] == '0' ) pCubeNew[v] = '0'; else if ( pCube[pOrder[v]] == '1' ) pCubeNew[v] = '1'; pCubeNew += nVars + 3; } pNode->pData = pSopNew; Vec_IntSort( &pNode->vFanins, 0 ); // Vec_IntPrint( vOrder ); } Vec_IntFree( vOrder ); Vec_StrFree( vStore ); } void Abc_NtkOrderFaninsByLitCount( Abc_Ntk_t * pNtk ) { Vec_Int_t * vOrder; Vec_Int_t * vCounts; Vec_Int_t * vFanins; Vec_Str_t * vStore; Abc_Obj_t * pNode; char * pSop, * pSopNew; char * pCube, * pCubeNew; int nVars, i, v, * pOrder; assert( Abc_NtkHasSop(pNtk) ); vOrder = Vec_IntAlloc( 100 ); vStore = Vec_StrAlloc( 100 ); vCounts = Vec_IntAlloc( 100 ); vFanins = Vec_IntAlloc( 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) { pSop = (char *)pNode->pData; nVars = Abc_SopGetVarNum(pSop); assert( nVars == Abc_ObjFaninNum(pNode) ); // count literals Vec_IntFill( vCounts, nVars, 0 ); Abc_SopForEachCube( pSop, nVars, pCube ) for ( v = 0; v < nVars; v++ ) if ( pCube[v] != '-' ) Vec_IntAddToEntry( vCounts, v, 1 ); // find good order Vec_IntClear( vOrder ); for ( v = 0; v < nVars; v++ ) Vec_IntPush( vOrder, v ); pOrder = Vec_IntArray(vOrder); Vec_IntSelectSortCost( pOrder, nVars, vCounts ); // copy the cover Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); memcpy( Vec_StrArray(vStore), pSop, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); pSopNew = pCubeNew = pSop; pSop = Vec_StrArray(vStore); // generate permuted one Abc_SopForEachCube( pSop, nVars, pCube ) { for ( v = 0; v < nVars; v++ ) pCubeNew[v] = '-'; for ( v = 0; v < nVars; v++ ) if ( pCube[pOrder[v]] == '0' ) pCubeNew[v] = '0'; else if ( pCube[pOrder[v]] == '1' ) pCubeNew[v] = '1'; pCubeNew += nVars + 3; } pNode->pData = pSopNew; // generate the fanin order Vec_IntClear( vFanins ); for ( v = 0; v < nVars; v++ ) Vec_IntPush( vFanins, Abc_ObjFaninId( pNode, pOrder[v] ) ); Vec_IntClear( &pNode->vFanins ); Vec_IntAppend( &pNode->vFanins, vFanins ); } Vec_IntFree( vFanins ); Vec_IntFree( vCounts ); Vec_IntFree( vOrder ); Vec_StrFree( vStore ); } void Abc_NtkOrderFaninsByLitCountAndCubeCount( Abc_Ntk_t * pNtk ) { // assuming that the fanins are sorted by the number of literals in each cube // this procedure sorts the literals appearing only once by the number of their cube Vec_Int_t * vOrder; Vec_Int_t * vCounts; Vec_Int_t * vFanins; Vec_Int_t * vCubeNum; Vec_Str_t * vStore; Abc_Obj_t * pNode; char * pSop, * pSopNew; char * pCube, * pCubeNew; int nVars, i, v, iCube, * pOrder; assert( Abc_NtkHasSop(pNtk) ); vStore = Vec_StrAlloc( 100 ); vOrder = Vec_IntAlloc( 100 ); vCounts = Vec_IntAlloc( 100 ); vFanins = Vec_IntAlloc( 100 ); vCubeNum = Vec_IntAlloc( 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) { pSop = (char *)pNode->pData; nVars = Abc_SopGetVarNum(pSop); assert( nVars == Abc_ObjFaninNum(pNode) ); // count literals and remember the cube where each literal appears Vec_IntFill( vCounts, nVars, 0 ); Vec_IntFill( vCubeNum, nVars, 0 ); iCube = 0; Abc_SopForEachCube( pSop, nVars, pCube ) { for ( v = 0; v < nVars; v++ ) if ( pCube[v] != '-' ) { Vec_IntAddToEntry( vCounts, v, 1 ); Vec_IntWriteEntry( vCubeNum, v, iCube ); } iCube++; } // create new order for ( v = 0; v < nVars; v++ ) if ( Vec_IntEntry(vCounts, v) == 1 ) Vec_IntWriteEntry( vCounts, v, Vec_IntEntry(vCubeNum, v) ); else Vec_IntWriteEntry( vCounts, v, ABC_INFINITY ); // find good order Vec_IntClear( vOrder ); for ( v = 0; v < nVars; v++ ) Vec_IntPush( vOrder, v ); pOrder = Vec_IntArray(vOrder); Vec_IntSelectSortCost( pOrder, nVars, vCounts ); // copy the cover Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); memcpy( Vec_StrArray(vStore), pSop, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); pSopNew = pCubeNew = pSop; pSop = Vec_StrArray(vStore); // generate permuted one Abc_SopForEachCube( pSop, nVars, pCube ) { for ( v = 0; v < nVars; v++ ) pCubeNew[v] = '-'; for ( v = 0; v < nVars; v++ ) if ( pCube[pOrder[v]] == '0' ) pCubeNew[v] = '0'; else if ( pCube[pOrder[v]] == '1' ) pCubeNew[v] = '1'; pCubeNew += nVars + 3; } pNode->pData = pSopNew; // generate the fanin order Vec_IntClear( vFanins ); for ( v = 0; v < nVars; v++ ) Vec_IntPush( vFanins, Abc_ObjFaninId( pNode, pOrder[v] ) ); Vec_IntClear( &pNode->vFanins ); Vec_IntAppend( &pNode->vFanins, vFanins ); } Vec_IntFree( vCubeNum ); Vec_IntFree( vFanins ); Vec_IntFree( vCounts ); Vec_IntFree( vOrder ); Vec_StrFree( vStore ); } /**Function************************************************************* Synopsis [Split large nodes by dividing their SOPs in half.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSplitLarge( Abc_Obj_t * pNode ) { Abc_Obj_t * pNode1, * pNode2, * pFanin; int CutPoint, nVars = Abc_ObjFaninNum(pNode); int i, nCubes = Abc_SopGetCubeNum((char *)pNode->pData); pNode1 = Abc_NtkDupObj( pNode->pNtk, pNode, 0 ); pNode2 = Abc_NtkDupObj( pNode->pNtk, pNode, 0 ); Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_ObjAddFanin( pNode1, pFanin ); Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_ObjAddFanin( pNode2, pFanin ); // update the node Abc_ObjRemoveFanins( pNode ); Abc_ObjAddFanin( pNode, pNode1 ); Abc_ObjAddFanin( pNode, pNode2 ); pNode->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNode->pNtk->pManFunc, 2, NULL ); // update covers of the nodes assert( nCubes > 1 ); CutPoint = (nCubes / 2) * (nVars + 3); ((char *)pNode1->pData)[CutPoint] = 0; pNode2->pData = (char *)pNode2->pData + CutPoint; } void Abc_NtkSplitLarge( Abc_Ntk_t * pNtk, int nFaninsMax, int nCubesMax ) { Abc_Obj_t * pNode; int nObjOld = Abc_NtkObjNumMax(pNtk); int i, nCubes; assert( Abc_NtkHasSop(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( i == nObjOld ) break; nCubes = Abc_SopGetCubeNum((char *)pNode->pData); if ( (Abc_ObjFaninNum(pNode) > nFaninsMax && nCubes > 1) || nCubes > nCubesMax ) Abc_NodeSplitLarge( pNode ); } } /**Function************************************************************* Synopsis [Sorts the cubes in a topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCompareCubes( char ** pp1, char ** pp2 ) { return strcmp( *pp1, *pp2 ); } void Abc_NodeSortCubes( Abc_Obj_t * pNode, Vec_Ptr_t * vCubes, Vec_Str_t * vStore ) { char * pCube, * pPivot; char * pSop = (char *)pNode->pData; int i, nVars = Abc_ObjFaninNum(pNode); Vec_PtrClear( vCubes ); Abc_SopForEachCube( pSop, nVars, pCube ) { assert( pCube[nVars] == ' ' ); pCube[nVars] = 0; Vec_PtrPush( vCubes, pCube ); } Vec_PtrSort( vCubes, (int (*)())Abc_NodeCompareCubes ); Vec_StrGrow( vStore, Vec_PtrSize(vCubes) * (nVars + 3) ); pPivot = Vec_StrArray( vStore ); Vec_PtrForEachEntry( char *, vCubes, pCube, i ) { assert( pCube[nVars] == 0 ); pCube[nVars] = ' '; memcpy( pPivot, pCube, nVars + 3 ); pPivot += nVars + 3; } memcpy( pSop, Vec_StrArray(vStore), Vec_PtrSize(vCubes) * (nVars + 3) ); } void Abc_NtkSortCubes( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vCubes; Vec_Str_t * vStore; Abc_Obj_t * pNode; int i; assert( Abc_NtkHasSop(pNtk) ); vCubes = Vec_PtrAlloc( 1000 ); vStore = Vec_StrAlloc( 1000 ); Abc_NtkForEachNode( pNtk, pNode, i ) Abc_NodeSortCubes( pNode, vCubes, vStore ); Vec_StrFree( vStore ); Vec_PtrFree( vCubes ); } /**Function************************************************************* Synopsis [Sorts fanins of each node to make SOPs more readable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSortSops( Abc_Ntk_t * pNtk ) { Abc_NtkOrderFaninsByLitCount( pNtk ); Abc_NtkSortCubes( pNtk ); Abc_NtkOrderFaninsByLitCountAndCubeCount( pNtk ); Abc_NtkSortCubes( pNtk ); } /**Function************************************************************* Synopsis [Makes cover legitimate for "fast_extract".] Description [Iteratively removes distance-1 and contained cubes.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_CubeContain( char * pCube1, char * pCube2, int nVars ) { int v, fCont12 = 1, fCont21 = 1; for ( v = 0; v < nVars; v++ ) { if ( pCube1[v] == pCube2[v] ) continue; if ( pCube1[v] == '-' ) fCont21 = 0; else if ( pCube2[v] == '-' ) fCont12 = 0; else return 0; if ( !fCont21 && !fCont21 ) return 0; } assert( fCont21 || fCont12 ); return (fCont21 << 1) | fCont12; } int Abc_NodeMakeSCCFree( Abc_Obj_t * pNode ) { char * pSop = (char *)pNode->pData; char * pCube, * pCube2, * pSopNew; int nVars = Abc_ObjFaninNum(pNode); int Status, nCount = 0; Abc_SopForEachCubePair( pSop, nVars, pCube, pCube2 ) { if ( pCube[0] == 'z' || pCube2[0] == 'z' ) continue; Status = Abc_CubeContain( pCube, pCube2, nVars ); nCount += (int)(Status > 0); if ( Status & 1 ) pCube2[0] = 'z'; else if ( Status & 2 ) pCube[0] = 'z'; } if ( nCount == 0 ) return 0; // create new cover pSopNew = (char *)pNode->pData; Abc_SopForEachCube( pSop, nVars, pCube ) { if ( pCube[0] == 'z' ) continue; memcpy( pSopNew, pCube, nVars + 3 ); pSopNew += nVars + 3; } *pSopNew = 0; return 1; } void Abc_NodeMakeDist1Free( Abc_Obj_t * pNode ) { char * pSop = (char *)pNode->pData; char * pCube, * pCube2; int i, nVars = Abc_ObjFaninNum(pNode); Abc_SopForEachCube( pSop, nVars, pCube ) Abc_SopForEachCube( pCube + nVars + 3, nVars, pCube2 ) { int Counter = 0, iDiff = -1; for ( i = 0; i < nVars; i++ ) if ( pCube[i] != pCube2[i] ) Counter++, iDiff = i; if ( Counter == 1 && ((pCube[iDiff] == '0' && pCube2[iDiff] == '1') || (pCube[iDiff] == '1' && pCube2[iDiff] == '0')) ) pCube[iDiff] = pCube2[iDiff] = '-'; } } void Abc_NodeCheckDist1Free( Abc_Obj_t * pNode ) { char * pSop = (char *)pNode->pData; char * pCube, * pCube2; int i, nVars = Abc_ObjFaninNum(pNode); Abc_SopForEachCube( pSop, nVars, pCube ) Abc_SopForEachCube( pSop, nVars, pCube2 ) { int Counter = 0; if ( pCube == pCube2 ) continue; for ( i = 0; i < nVars; i++ ) if ( pCube[i] != pCube2[i] ) Counter++; assert( Counter > 1 ); } } int Abc_NodeMakeLegit( Abc_Obj_t * pNode ) { int i, fChanges = 1; for ( i = 0; fChanges; i++ ) { Abc_NodeMakeDist1Free( pNode ); fChanges = Abc_NodeMakeSCCFree( pNode ); } // Abc_NodeCheckDist1Free( pNode ); return i > 1; } int Abc_NtkMakeLegit( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, Counter = 0; assert( Abc_NtkHasSop(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) Counter += Abc_NodeMakeLegit( pNode ); if ( Counter ) Abc_Print( 0, "%d nodes were made dist1-cube-free and/or single-cube-containment-free.\n", Counter ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END