/**CFile**************************************************************** FileName [abcLut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Superchoicing for K-LUTs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "opt/cut/cut.h" ABC_NAMESPACE_IMPL_START #define LARGE_LEVEL 1000000 //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define SCL_LUT_MAX 6 // the maximum LUT size #define SCL_VARS_MAX 15 // the maximum number of variables #define SCL_NODE_MAX 1000 // the maximum number of nodes typedef struct Abc_ManScl_t_ Abc_ManScl_t; struct Abc_ManScl_t_ { // paramers int nLutSize; // the LUT size int nCutSizeMax; // the max number of leaves of the cone int nNodesMax; // the max number of divisors in the cone int nWords; // the number of machine words in sim info // structural representation of the cone Vec_Ptr_t * vLeaves; // leaves of the cut Vec_Ptr_t * vVolume; // volume of the cut int pBSet[SCL_VARS_MAX]; // bound set // functional representation of the cone unsigned * uTruth; // truth table of the cone // representation of truth tables unsigned ** uVars; // elementary truth tables unsigned ** uSims; // truth tables of the nodes unsigned ** uCofs; // truth tables of the cofactors }; static Vec_Ptr_t * s_pLeaves = NULL; static Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize ); static Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax ); static void Abc_ManSclStop( Abc_ManScl_t * p ); static void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj ); static Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * pManScl, Abc_Obj_t * pObj ); static int Abc_NodeDecomposeStep( Abc_ManScl_t * pManScl ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs superchoicing for K-LUTs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose ) { ProgressBar * pProgress; Abc_ManCut_t * pManCut; Abc_ManScl_t * pManScl; Cut_Man_t * pManCuts; Abc_Obj_t * pObj, * pFanin, * pObjTop; int i, LevelMax, nNodes; int nNodesTried, nNodesDec, nNodesExist, nNodesUsed; assert( Abc_NtkIsSopLogic(pNtk) ); if ( nLutSize < 3 || nLutSize > SCL_LUT_MAX ) { printf( "LUT size (%d) does not belong to the interval: 3 <= LUT size <= %d\n", nLutSize, SCL_LUT_MAX ); return 0; } if ( nCutSizeMax <= nLutSize || nCutSizeMax > SCL_VARS_MAX ) { printf( "Cut size (%d) does not belong to the interval: LUT size (%d) < Cut size <= %d\n", nCutSizeMax, nLutSize, SCL_VARS_MAX ); return 0; } assert( nLutSize <= SCL_LUT_MAX ); assert( nCutSizeMax <= SCL_VARS_MAX ); nNodesTried = nNodesDec = nNodesExist = nNodesUsed = 0; // set the delays of the CIs Abc_NtkForEachCi( pNtk, pObj, i ) pObj->Level = 0; //Abc_NtkLevel( pNtk ); // start the managers pManScl = Abc_ManSclStart( nLutSize, nCutSizeMax, 1000 ); pManCuts = Abc_NtkStartCutManForScl( pNtk, nLutSize ); pManCut = Abc_NtkManCutStart( nCutSizeMax, 100000, 100000, 100000 ); s_pLeaves = Abc_NtkManCutReadCutSmall( pManCut ); pManScl->vVolume = Abc_NtkManCutReadVisited( pManCut ); // process each internal node (assuming topological order of nodes!!!) nNodes = Abc_NtkObjNumMax(pNtk); pProgress = Extra_ProgressBarStart( stdout, nNodes ); Abc_NtkForEachObj( pNtk, pObj, i ) { // if ( i != nNodes-1 ) // continue; Extra_ProgressBarUpdate( pProgress, i, NULL ); if ( i >= nNodes ) break; if ( Abc_ObjFaninNum(pObj) != 2 ) continue; nNodesTried++; // map this node using regular cuts // pObj->Level = 0; Abc_NodeLutMap( pManCuts, pObj ); // compute the cut pManScl->vLeaves = Abc_NodeFindCut( pManCut, pObj, 0 ); if ( Vec_PtrSize(pManScl->vLeaves) <= nLutSize ) continue; // get the volume of the cut if ( Vec_PtrSize(pManScl->vVolume) > SCL_NODE_MAX ) continue; nNodesDec++; // decompose the cut pObjTop = Abc_NodeSuperChoiceLut( pManScl, pObj ); if ( pObjTop == NULL ) continue; nNodesExist++; // if there is no delay improvement, skip; otherwise, update level if ( pObjTop->Level >= pObj->Level ) { Abc_NtkDeleteObj_rec( pObjTop, 1 ); continue; } pObj->Level = pObjTop->Level; nNodesUsed++; } Extra_ProgressBarStop( pProgress ); // delete the managers Abc_ManSclStop( pManScl ); Abc_NtkManCutStop( pManCut ); Cut_ManStop( pManCuts ); // get the largest arrival time LevelMax = 0; Abc_NtkForEachCo( pNtk, pObj, i ) { pFanin = Abc_ObjFanin0( pObj ); // skip inv/buf if ( Abc_ObjFaninNum(pFanin) == 1 ) pFanin = Abc_ObjFanin0( pFanin ); // get the new level LevelMax = Abc_MaxInt( LevelMax, (int)pFanin->Level ); } if ( fVerbose ) printf( "Try = %d. Dec = %d. Exist = %d. Use = %d. SUPER = %d levels of %d-LUTs.\n", nNodesTried, nNodesDec, nNodesExist, nNodesUsed, LevelMax, nLutSize ); // if ( fVerbose ) // printf( "The network is superchoiced for %d levels of %d-LUTs.\n", LevelMax, nLutSize ); // clean the data field Abc_NtkForEachObj( pNtk, pObj, i ) pObj->pNext = NULL; // check if ( !Abc_NtkCheck( pNtk ) ) { printf( "Abc_NtkSuperChoiceLut: The network check has failed.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [Performs LUT mapping of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj ) { Cut_Cut_t * pCut; Abc_Obj_t * pFanin; int i, DelayMax; pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCuts, pObj, 0, 0 ); assert( pCut != NULL ); assert( pObj->Level == 0 ); // go through the cuts pObj->Level = LARGE_LEVEL; for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) { DelayMax = 0; for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pFanin = Abc_NtkObj( pObj->pNtk, pCut->pLeaves[i] ); // assert( Abc_ObjIsCi(pFanin) || pFanin->Level > 0 ); // should hold if node ordering is topological if ( DelayMax < (int)pFanin->Level ) DelayMax = pFanin->Level; } if ( (int)pObj->Level > DelayMax ) pObj->Level = DelayMax; } assert( pObj->Level < LARGE_LEVEL ); pObj->Level++; // printf( "%d(%d) ", pObj->Id, pObj->Level ); } /**Function************************************************************* Synopsis [Starts the cut manager for rewriting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize ) { static Cut_Params_t Params, * pParams = &Params; Cut_Man_t * pManCut; Abc_Obj_t * pObj; int i; // start the cut manager memset( pParams, 0, sizeof(Cut_Params_t) ); pParams->nVarsMax = nLutSize; // the max cut size ("k" of the k-feasible cuts) pParams->nKeepMax = 500; // the max number of cuts kept at a node pParams->fTruth = 0; // compute truth tables pParams->fFilter = 1; // filter dominated cuts pParams->fSeq = 0; // compute sequential cuts pParams->fDrop = 0; // drop cuts on the fly pParams->fVerbose = 0; // the verbosiness flag pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); pManCut = Cut_ManStart( pParams ); if ( pParams->fDrop ) Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); // set cuts for PIs Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) > 0 ) Cut_NodeSetTriv( pManCut, pObj->Id ); return pManCut; } /**Function************************************************************* Synopsis [Starts the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax ) { Abc_ManScl_t * p; int i, k; assert( sizeof(unsigned) == 4 ); p = ABC_ALLOC( Abc_ManScl_t, 1 ); memset( p, 0, sizeof(Abc_ManScl_t) ); p->nLutSize = nLutSize; p->nCutSizeMax = nCutSizeMax; p->nNodesMax = nNodesMax; p->nWords = Extra_TruthWordNum(nCutSizeMax); // allocate simulation info p->uVars = (unsigned **)Extra_ArrayAlloc( nCutSizeMax, p->nWords, 4 ); p->uSims = (unsigned **)Extra_ArrayAlloc( nNodesMax, p->nWords, 4 ); p->uCofs = (unsigned **)Extra_ArrayAlloc( 2 << nLutSize, p->nWords, 4 ); memset( p->uVars[0], 0, nCutSizeMax * p->nWords * 4 ); // assign elementary truth tables for ( k = 0; k < p->nCutSizeMax; k++ ) for ( i = 0; i < p->nWords * 32; i++ ) if ( i & (1 << k) ) p->uVars[k][i>>5] |= (1 << (i&31)); // other data structures // p->vBound = Vec_IntAlloc( nCutSizeMax ); return p; } /**Function************************************************************* Synopsis [Stops the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManSclStop( Abc_ManScl_t * p ) { // Vec_IntFree( p->vBound ); ABC_FREE( p->uVars ); ABC_FREE( p->uSims ); ABC_FREE( p->uCofs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Abc_NodeSuperChoiceTruth( Abc_ManScl_t * pManScl ) { Abc_Obj_t * pObj; unsigned * puData0, * puData1, * puData = NULL; char * pSop; int i, k; // set elementary truth tables Vec_PtrForEachEntry( Abc_Obj_t *, pManScl->vLeaves, pObj, i ) pObj->pNext = (Abc_Obj_t *)pManScl->uVars[i]; // compute truth tables for internal nodes Vec_PtrForEachEntry( Abc_Obj_t *, pManScl->vVolume, pObj, i ) { // set storage for the node's simulation info pObj->pNext = (Abc_Obj_t *)pManScl->uSims[i]; // get pointer to the simulation info puData = (unsigned *)pObj->pNext; puData0 = (unsigned *)Abc_ObjFanin0(pObj)->pNext; puData1 = (unsigned *)Abc_ObjFanin1(pObj)->pNext; // simulate pSop = (char *)pObj->pData; if ( pSop[0] == '0' && pSop[1] == '0' ) for ( k = 0; k < pManScl->nWords; k++ ) puData[k] = ~puData0[k] & ~puData1[k]; else if ( pSop[0] == '0' ) for ( k = 0; k < pManScl->nWords; k++ ) puData[k] = ~puData0[k] & puData1[k]; else if ( pSop[1] == '0' ) for ( k = 0; k < pManScl->nWords; k++ ) puData[k] = puData0[k] & ~puData1[k]; else for ( k = 0; k < pManScl->nWords; k++ ) puData[k] = puData0[k] & puData1[k]; } return puData; } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSuperChoiceCollect2_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vVolume ) { if ( pObj->fMarkC ) return; pObj->fMarkC = 1; assert( Abc_ObjFaninNum(pObj) == 2 ); Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin0(pObj), vVolume ); Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin1(pObj), vVolume ); Vec_PtrPush( vVolume, pObj ); } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSuperChoiceCollect2( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) { Abc_Obj_t * pObj; int i; Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) pObj->fMarkC = 1; Vec_PtrClear( vVolume ); Abc_NodeSuperChoiceCollect2_rec( pRoot, vVolume ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) pObj->fMarkC = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vVolume, pObj, i ) pObj->fMarkC = 0; } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSuperChoiceCollect_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) { if ( pObj->fMarkB ) { Vec_PtrPush( vLeaves, pObj ); pObj->fMarkB = 0; } if ( pObj->fMarkC ) return; pObj->fMarkC = 1; assert( Abc_ObjFaninNum(pObj) == 2 ); Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin0(pObj), vLeaves, vVolume ); Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin1(pObj), vLeaves, vVolume ); Vec_PtrPush( vVolume, pObj ); } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [Orders the leaves topologically.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSuperChoiceCollect( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) { Abc_Obj_t * pObj; int i, nLeaves; nLeaves = Vec_PtrSize(vLeaves); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) pObj->fMarkB = pObj->fMarkC = 1; Vec_PtrClear( vVolume ); Vec_PtrClear( vLeaves ); Abc_NodeSuperChoiceCollect_rec( pRoot, vLeaves, vVolume ); assert( Vec_PtrSize(vLeaves) == nLeaves ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) pObj->fMarkC = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vVolume, pObj, i ) pObj->fMarkC = 0; } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeLeavesRemove( Vec_Ptr_t * vLeaves, unsigned uPhase, int nVars ) { int i; for ( i = nVars - 1; i >= 0; i-- ) if ( uPhase & (1 << i) ) Vec_PtrRemove( vLeaves, Vec_PtrEntry(vLeaves, i) ); } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeGetLevel( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i, Level; Level = 0; Abc_ObjForEachFanin( pObj, pFanin, i ) Level = Abc_MaxInt( Level, (int)pFanin->Level ); return Level + 1; } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin, * pObjNew; int i, nVars, uSupport, nSuppVars; // collect the cone using DFS (excluding leaves) Abc_NodeSuperChoiceCollect2( pObj, p->vLeaves, p->vVolume ); assert( Vec_PtrEntryLast(p->vVolume) == pObj ); // compute the truth table p->uTruth = Abc_NodeSuperChoiceTruth( p ); // get the support of this truth table nVars = Vec_PtrSize(p->vLeaves); uSupport = Extra_TruthSupport(p->uTruth, nVars); nSuppVars = Extra_WordCountOnes(uSupport); assert( nSuppVars <= nVars ); if ( nSuppVars == 0 ) { pObj->Level = 0; return NULL; } if ( nSuppVars == 1 ) { // find the variable for ( i = 0; i < nVars; i++ ) if ( uSupport & (1 << i) ) break; assert( i < nVars ); pFanin = (Abc_Obj_t *)Vec_PtrEntry( p->vLeaves, i ); pObj->Level = pFanin->Level; return NULL; } // support-minimize the truth table if ( nSuppVars != nVars ) { Extra_TruthShrink( p->uCofs[0], p->uTruth, nSuppVars, nVars, uSupport ); Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars ); Abc_NodeLeavesRemove( p->vLeaves, ((1 << nVars) - 1) & ~uSupport, nVars ); } // return NULL; // decompose the truth table recursively while ( Vec_PtrSize(p->vLeaves) > p->nLutSize ) if ( !Abc_NodeDecomposeStep( p ) ) { Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pFanin, i ) if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 0 ) Abc_NtkDeleteObj_rec( pFanin, 1 ); return NULL; } // create the topmost node pObjNew = Abc_NtkCreateNode( pObj->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pFanin, i ) Abc_ObjAddFanin( pObjNew, pFanin ); // create the function pObjNew->pData = Abc_SopCreateFromTruth( (Mem_Flex_t *)pObj->pNtk->pManFunc, Vec_PtrSize(p->vLeaves), p->uTruth ); // need ISOP pObjNew->Level = Abc_NodeGetLevel( pObjNew ); return pObjNew; } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in increasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCompareLevelsInc( int * pp1, int * pp2 ) { Abc_Obj_t * pNode1, * pNode2; pNode1 = (Abc_Obj_t *)Vec_PtrEntry(s_pLeaves, *pp1); pNode2 = (Abc_Obj_t *)Vec_PtrEntry(s_pLeaves, *pp2); if ( pNode1->Level < pNode2->Level ) return -1; if ( pNode1->Level > pNode2->Level ) return 1; return 0; } /**Function************************************************************* Synopsis [Selects the earliest arriving nodes from the array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeDecomposeSort( Abc_Obj_t ** pLeaves, int nVars, int * pBSet, int nLutSize ) { Abc_Obj_t * pTemp[SCL_VARS_MAX]; int i, k, kBest, LevelMin; assert( nLutSize < nVars ); assert( nVars <= SCL_VARS_MAX ); // copy nodes into the internal storage // printf( "(" ); for ( i = 0; i < nVars; i++ ) { pTemp[i] = pLeaves[i]; // printf( " %d", pLeaves[i]->Level ); } // printf( " )\n" ); // choose one node at a time for ( i = 0; i < nLutSize; i++ ) { kBest = -1; LevelMin = LARGE_LEVEL; for ( k = 0; k < nVars; k++ ) if ( pTemp[k] && LevelMin > (int)pTemp[k]->Level ) { LevelMin = pTemp[k]->Level; kBest = k; } pBSet[i] = kBest; pTemp[kBest] = NULL; } } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeDecomposeStep( Abc_ManScl_t * p ) { static char pCofClasses[1<vLeaves, 0))->pNtk; // find the earliest nodes nVars = Vec_PtrSize(p->vLeaves); assert( nVars > p->nLutSize ); /* for ( v = 0; v < nVars; v++ ) p->pBSet[v] = v; qsort( (void *)p->pBSet, nVars, sizeof(int), (int (*)(const void *, const void *)) Abc_NodeCompareLevelsInc ); */ Abc_NodeDecomposeSort( (Abc_Obj_t **)Vec_PtrArray(p->vLeaves), Vec_PtrSize(p->vLeaves), p->pBSet, p->nLutSize ); assert( ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[0]))->Level <= ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[1]))->Level ); // cofactor w.r.t. the selected variables Extra_TruthCopy( p->uCofs[1], p->uTruth, nVars ); c = 2; for ( v = 0; v < p->nLutSize; v++ ) for ( k = 0; k < (1<uCofs[c], p->uCofs[c/2], nVars ); Extra_TruthCopy( p->uCofs[c+1], p->uCofs[c/2], nVars ); Extra_TruthCofactor0( p->uCofs[c], nVars, p->pBSet[v] ); Extra_TruthCofactor1( p->uCofs[c+1], nVars, p->pBSet[v] ); c += 2; } assert( c == (2 << p->nLutSize) ); // count unique cofactors nClasses = 0; nCofs = (1 << p->nLutSize); for ( i = 0; i < nCofs; i++ ) { pTruthCof = p->uCofs[ nCofs + i ]; for ( k = 0; k < nClasses; k++ ) { pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ]; if ( Extra_TruthIsEqual( pTruthCof, pTruthClass, nVars ) ) { pCofClasses[k][(int)nCofClasses[k]++ ] = i; break; } } if ( k != nClasses ) continue; // not found pCofClasses[nClasses][0] = i; nCofClasses[nClasses] = 1; nClasses++; if ( nClasses > nCofs/2 ) return 0; } // the number of cofactors is acceptable nVarsNew = Abc_Base2Log( nClasses ); assert( nVarsNew < p->nLutSize ); // create the remainder truth table // for each class of cofactors, multiply cofactor truth table by its code Extra_TruthClear( p->uTruth, nVars ); for ( k = 0; k < nClasses; k++ ) { pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ]; for ( v = 0; v < nVarsNew; v++ ) if ( k & (1 << v) ) Extra_TruthAnd( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars ); else Extra_TruthSharp( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars ); Extra_TruthOr( p->uTruth, p->uTruth, pTruthClass, nVars ); } // create nodes pTruth = p->uCofs[0]; for ( v = 0; v < nVarsNew; v++ ) { Extra_TruthClear( pTruth, p->nLutSize ); for ( k = 0; k < nClasses; k++ ) if ( k & (1 << v) ) for ( i = 0; i < nCofClasses[k]; i++ ) { pTruthCof = p->uCofs[1]; Extra_TruthFill( pTruthCof, p->nLutSize ); for ( w = 0; w < p->nLutSize; w++ ) if ( pCofClasses[k][i] & (1 << (p->nLutSize-1-w)) ) Extra_TruthAnd( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize ); else Extra_TruthSharp( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize ); Extra_TruthOr( pTruth, pTruth, pTruthCof, p->nLutSize ); } // implement the node pObjNew = Abc_NtkCreateNode( pNtk ); for ( i = 0; i < p->nLutSize; i++ ) { pFanin = (Abc_Obj_t *)Vec_PtrEntry( p->vLeaves, p->pBSet[i] ); Abc_ObjAddFanin( pObjNew, pFanin ); } // create the function pObjNew->pData = Abc_SopCreateFromTruth( (Mem_Flex_t *)pNtk->pManFunc, p->nLutSize, pTruth ); // need ISOP pObjNew->Level = Abc_NodeGetLevel( pObjNew ); pNodesNew[v] = pObjNew; } // put the new nodes back into the list for ( v = 0; v < nVarsNew; v++ ) Vec_PtrWriteEntry( p->vLeaves, p->pBSet[v], pNodesNew[v] ); // compute the variables that should be removed uPhase = 0; for ( v = nVarsNew; v < p->nLutSize; v++ ) uPhase |= (1 << p->pBSet[v]); // remove entries from the array Abc_NodeLeavesRemove( p->vLeaves, uPhase, nVars ); // update truth table Extra_TruthShrink( p->uCofs[0], p->uTruth, nVars - p->nLutSize + nVarsNew, nVars, ((1 << nVars) - 1) & ~uPhase ); Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars ); assert( !Extra_TruthVarInSupport( p->uTruth, nVars, nVars - p->nLutSize + nVarsNew ) ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END