/**CFile**************************************************************** FileName [lpkMulti.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpkMulti.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "lpkInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Records variable order.] Description [Increaments Order[x][y] by 1 if x should be above y in the DSD.] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_CreateVarOrder( Kit_DsdNtk_t * pNtk, char pTable[][16] ) { Kit_DsdObj_t * pObj; unsigned uSuppFanins, k; int Above[16], Below[16]; int nAbove, nBelow, iFaninLit, i, x, y; // iterate through the nodes Kit_DsdNtkForEachObj( pNtk, pObj, i ) { // collect fanin support of this node nAbove = 0; uSuppFanins = 0; Kit_DsdObjForEachFanin( pNtk, pObj, iFaninLit, k ) { if ( Kit_DsdLitIsLeaf( pNtk, iFaninLit ) ) Above[nAbove++] = Abc_Lit2Var(iFaninLit); else uSuppFanins |= Kit_DsdLitSupport( pNtk, iFaninLit ); } // find the below variables nBelow = 0; for ( y = 0; y < 16; y++ ) if ( uSuppFanins & (1 << y) ) Below[nBelow++] = y; // create all pairs for ( x = 0; x < nAbove; x++ ) for ( y = 0; y < nBelow; y++ ) pTable[Above[x]][Below[y]]++; } } /**Function************************************************************* Synopsis [Creates commmon variable order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_CreateCommonOrder( char pTable[][16], int piCofVar[], int nCBars, int pPrios[], int nVars, int fVerbose ) { int Score[16] = {0}, pPres[16]; int i, y, x, iVarBest, ScoreMax, PrioCount; // mark the present variables for ( i = 0; i < nVars; i++ ) pPres[i] = 1; // remove cofactored variables for ( i = 0; i < nCBars; i++ ) pPres[piCofVar[i]] = 0; // compute scores for each leaf for ( i = 0; i < nVars; i++ ) { if ( pPres[i] == 0 ) continue; for ( y = 0; y < nVars; y++ ) Score[i] += pTable[i][y]; for ( x = 0; x < nVars; x++ ) Score[i] -= pTable[x][i]; } // print the scores if ( fVerbose ) { printf( "Scores: " ); for ( i = 0; i < nVars; i++ ) printf( "%c=%d ", 'a'+i, Score[i] ); printf( " " ); printf( "Prios: " ); } // derive variable priority // variables with equal score receive the same priority for ( i = 0; i < nVars; i++ ) pPrios[i] = 16; // iterate until variables remain for ( PrioCount = 1; ; PrioCount++ ) { // find the present variable with the highest score iVarBest = -1; ScoreMax = -100000; for ( i = 0; i < nVars; i++ ) { if ( pPres[i] == 0 ) continue; if ( ScoreMax < Score[i] ) { ScoreMax = Score[i]; iVarBest = i; } } if ( iVarBest == -1 ) break; // give the next priority to all vars having this score if ( fVerbose ) printf( "%d=", PrioCount ); for ( i = 0; i < nVars; i++ ) { if ( pPres[i] == 0 ) continue; if ( Score[i] == ScoreMax ) { pPrios[i] = PrioCount; pPres[i] = 0; if ( fVerbose ) printf( "%c", 'a'+i ); } } if ( fVerbose ) printf( " " ); } if ( fVerbose ) printf( "\n" ); } /**Function************************************************************* Synopsis [Finds components with the highest priority.] Description [Returns the number of components selected.] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_FindHighest( Kit_DsdNtk_t ** ppNtks, int * piLits, int nSize, int * pPrio, int * pDecision ) { Kit_DsdObj_t * pObj; unsigned uSupps[8], uSuppFanin, uSuppTotal, uSuppLarge; int i, pTriv[8], PrioMin, iVarMax, nComps, fOneNonTriv; // find individual support and total support uSuppTotal = 0; for ( i = 0; i < nSize; i++ ) { pTriv[i] = 1; if ( piLits[i] < 0 ) uSupps[i] = 0; else if ( Kit_DsdLitIsLeaf(ppNtks[i], piLits[i]) ) uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] ); else { pObj = Kit_DsdNtkObj( ppNtks[i], Abc_Lit2Var(piLits[i]) ); if ( pObj->Type == KIT_DSD_PRIME ) { pTriv[i] = 0; uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[0] ); } else { assert( pObj->nFans == 2 ); if ( !Kit_DsdLitIsLeaf(ppNtks[i], pObj->pFans[0]) ) pTriv[i] = 0; uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[1] ); } uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] ) & ~uSuppFanin; } assert( uSupps[i] <= 0xFFFF ); uSuppTotal |= uSupps[i]; } if ( uSuppTotal == 0 ) return 0; // find one support variable with the highest priority PrioMin = ABC_INFINITY; iVarMax = -1; for ( i = 0; i < 16; i++ ) if ( uSuppTotal & (1 << i) ) if ( PrioMin > pPrio[i] ) { PrioMin = pPrio[i]; iVarMax = i; } assert( iVarMax != -1 ); // select components, which have this variable nComps = 0; fOneNonTriv = 0; uSuppLarge = 0; for ( i = 0; i < nSize; i++ ) if ( uSupps[i] & (1<pIfMan) ); // iterate over the nodes if ( p->pPars->fVeryVerbose ) printf( "Decision: " ); for ( i = 0; i < nSize; i++ ) { if ( pDecision[i] ) { if ( p->pPars->fVeryVerbose ) printf( "%d ", i ); assert( piLits[i] >= 0 ); pObj = Kit_DsdNtkObj( ppNtks[i], Abc_Lit2Var(piLits[i]) ); if ( pObj == NULL ) piLitsNew[i] = -2; else if ( pObj->Type == KIT_DSD_PRIME ) piLitsNew[i] = pObj->pFans[0]; else piLitsNew[i] = pObj->pFans[1]; } else piLitsNew[i] = piLits[i]; } if ( p->pPars->fVeryVerbose ) printf( "\n" ); // call again pResPrev = Lpk_MapTreeMulti_rec( p, ppNtks, piLitsNew, piCofVar, nCBars, ppLeaves, nLeaves, pPrio ); // create new set of nodes for ( i = 0; i < nSize; i++ ) { if ( pDecision[i] ) pObjsNew[nCBars][i] = Lpk_MapTree_rec( p, ppNtks[i], ppLeaves, piLits[i], pResPrev ); else if ( piLits[i] == -1 ) pObjsNew[nCBars][i] = If_ManConst1(p->pIfMan); else if ( piLits[i] == -2 ) pObjsNew[nCBars][i] = If_Not( If_ManConst1(p->pIfMan) ); else pObjsNew[nCBars][i] = pResPrev; } // create MUX using these outputs for ( k = nCBars; k > 0; k-- ) { nSize /= 2; for ( i = 0; i < nSize; i++ ) pObjsNew[k-1][i] = If_ManCreateMux( p->pIfMan, pObjsNew[k][2*i+0], pObjsNew[k][2*i+1], ppLeaves[piCofVar[k-1]] ); } assert( nSize == 1 ); return pObjsNew[0][0]; } /**Function************************************************************* Synopsis [Prepares the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * Lpk_MapTreeMulti( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) { static int Counter = 0; If_Obj_t * pResult; Kit_DsdNtk_t * ppNtks[8] = {0}, * pTemp; Kit_DsdObj_t * pRoot; int piCofVar[4], pPrios[16], pFreqs[16] = {0}, piLits[16]; int i, k, nCBars, nSize, nMemSize; unsigned * ppCofs[4][8], uSupport; char pTable[16][16] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; int fVerbose = p->pPars->fVeryVerbose; Counter++; // printf( "Run %d.\n", Counter ); // allocate storage for cofactors nMemSize = Kit_TruthWordNum(nVars); ppCofs[0][0] = ABC_ALLOC( unsigned, 32 * nMemSize ); nSize = 0; for ( i = 0; i < 4; i++ ) for ( k = 0; k < 8; k++ ) ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++; assert( nSize == 32 ); // find the best cofactoring variables nCBars = Kit_DsdCofactoring( pTruth, nVars, piCofVar, p->pPars->nVarsShared, 0 ); // nCBars = 2; // piCofVar[0] = 0; // piCofVar[1] = 1; // copy the function Kit_TruthCopy( ppCofs[0][0], pTruth, nVars ); // decompose w.r.t. these variables for ( k = 0; k < nCBars; k++ ) { nSize = (1 << k); for ( i = 0; i < nSize; i++ ) { Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); } } nSize = (1 << nCBars); // compute DSD networks for ( i = 0; i < nSize; i++ ) { ppNtks[i] = Kit_DsdDecompose( ppCofs[nCBars][i], nVars ); ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); Kit_DsdNtkFree( pTemp ); if ( fVerbose ) { printf( "Cof%d%d: ", nCBars, i ); Kit_DsdPrint( stdout, ppNtks[i] ); } } // compute variable frequences for ( i = 0; i < nSize; i++ ) { uSupport = Kit_TruthSupport( ppCofs[nCBars][i], nVars ); for ( k = 0; k < nVars; k++ ) if ( uSupport & (1<pSupps[0] <= 0xFFFF ); // undec nodes should be rotated in such a way that the first input has as many shared inputs as possible Kit_DsdRotate( ppNtks[i], pFreqs ); // print the resulting networks if ( fVerbose ) { printf( "Cof%d%d: ", nCBars, i ); Kit_DsdPrint( stdout, ppNtks[i] ); } } for ( i = 0; i < nSize; i++ ) { // collect the roots pRoot = Kit_DsdNtkRoot(ppNtks[i]); if ( pRoot->Type == KIT_DSD_CONST1 ) piLits[i] = Abc_LitIsCompl(ppNtks[i]->Root)? -2: -1; else if ( pRoot->Type == KIT_DSD_VAR ) piLits[i] = Abc_LitNotCond( pRoot->pFans[0], Abc_LitIsCompl(ppNtks[i]->Root) ); else piLits[i] = ppNtks[i]->Root; } // recursively construct AIG for mapping p->fCofactoring = 1; pResult = Lpk_MapTreeMulti_rec( p, ppNtks, piLits, piCofVar, nCBars, ppLeaves, nVars, pPrios ); p->fCofactoring = 0; if ( fVerbose ) printf( "\n" ); // verify the transformations nSize = (1 << nCBars); for ( i = 0; i < nSize; i++ ) Kit_DsdTruth( ppNtks[i], ppCofs[nCBars][i] ); // mux the truth tables for ( k = nCBars-1; k >= 0; k-- ) { nSize = (1 << k); for ( i = 0; i < nSize; i++ ) Kit_TruthMuxVar( ppCofs[k][i], ppCofs[k+1][2*i+0], ppCofs[k+1][2*i+1], nVars, piCofVar[k] ); } if ( !Extra_TruthIsEqual( pTruth, ppCofs[0][0], nVars ) ) printf( "Verification failed.\n" ); // free the networks for ( i = 0; i < 8; i++ ) if ( ppNtks[i] ) Kit_DsdNtkFree( ppNtks[i] ); ABC_FREE( ppCofs[0][0] ); return pResult; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END