/**CFile**************************************************************** FileName [amapPerm.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Deriving permutation for the gate.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapPerm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects fanins of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibCollectFanins_rec( Amap_Lib_t * pLib, Amap_Nod_t * pNod, Vec_Int_t * vFanins ) { Amap_Nod_t * pFan0, * pFan1; if ( pNod->Id == 0 ) { Vec_IntPush( vFanins, 0 ); return; } pFan0 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan0) ); if ( Abc_LitIsCompl(pNod->iFan0) || pFan0->Type != pNod->Type ) Vec_IntPush( vFanins, pNod->iFan0 ); else Amap_LibCollectFanins_rec( pLib, pFan0, vFanins ); pFan1 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan1) ); if ( Abc_LitIsCompl(pNod->iFan1) || pFan1->Type != pNod->Type ) Vec_IntPush( vFanins, pNod->iFan1 ); else Amap_LibCollectFanins_rec( pLib, pFan1, vFanins ); } /**Function************************************************************* Synopsis [Collects fanins of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Amap_LibCollectFanins( Amap_Lib_t * pLib, Amap_Nod_t * pNod ) { Vec_Int_t * vFanins = Vec_IntAlloc( 10 ); Amap_LibCollectFanins_rec( pLib, pNod, vFanins ); return vFanins; } /**Function************************************************************* Synopsis [Matches the node with the DSD node.] Description [Returns perm if the node can be matched.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Amap_LibDeriveGatePerm_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * pNtk, int iLit, Amap_Nod_t * pNod ) { Vec_Int_t * vPerm, * vPermFanin, * vNodFanin, * vDsdLits; Kit_DsdObj_t * pDsdObj, * pDsdFanin; Amap_Nod_t * pNodFanin; int iDsdFanin, iNodFanin, Value, iDsdLit, i, k, j; // assert( !Abc_LitIsCompl(iLit) ); pDsdObj = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iLit) ); if ( pDsdObj == NULL ) { vPerm = Vec_IntAlloc( 1 ); Vec_IntPush( vPerm, iLit ); return vPerm; } if ( pDsdObj->Type == KIT_DSD_PRIME && pNod->Type == AMAP_OBJ_MUX ) { vPerm = Vec_IntAlloc( 10 ); iDsdFanin = pDsdObj->pFans[0]; pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan0) ); vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin ); if ( vPermFanin == NULL ) { Vec_IntFree( vPerm ); return NULL; } Vec_IntForEachEntry( vPermFanin, Value, k ) Vec_IntPush( vPerm, Value ); Vec_IntFree( vPermFanin ); iDsdFanin = pDsdObj->pFans[1]; pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan1) ); vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin ); if ( vPermFanin == NULL ) { Vec_IntFree( vPerm ); return NULL; } Vec_IntForEachEntry( vPermFanin, Value, k ) Vec_IntPush( vPerm, Value ); Vec_IntFree( vPermFanin ); iDsdFanin = pDsdObj->pFans[2]; pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan2) ); vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin ); if ( vPermFanin == NULL ) { Vec_IntFree( vPerm ); return NULL; } Vec_IntForEachEntry( vPermFanin, Value, k ) Vec_IntPush( vPerm, Value ); Vec_IntFree( vPermFanin ); return vPerm; } // return if wrong types if ( pDsdObj->Type == KIT_DSD_PRIME || pNod->Type == AMAP_OBJ_MUX ) return NULL; // return if sizes do not agree vNodFanin = Amap_LibCollectFanins( pLib, pNod ); if ( Vec_IntSize(vNodFanin) != (int)pDsdObj->nFans ) { Vec_IntFree( vNodFanin ); return NULL; } // match fanins of DSD with fanins of nodes // clean the mark and save variable literals vPerm = Vec_IntAlloc( 10 ); vDsdLits = Vec_IntAlloc( 10 ); Kit_DsdObjForEachFaninReverse( pNtk, pDsdObj, iDsdFanin, i ) { pDsdFanin = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iDsdFanin) ); if ( pDsdFanin ) pDsdFanin->fMark = 0; else Vec_IntPush( vDsdLits, iDsdFanin ); } // match each fanins of the node iDsdLit = 0; Vec_IntForEachEntry( vNodFanin, iNodFanin, k ) { if ( iNodFanin == 0 ) { if ( iDsdLit >= Vec_IntSize(vDsdLits) ) { Vec_IntFree( vPerm ); Vec_IntFree( vDsdLits ); Vec_IntFree( vNodFanin ); return NULL; } iDsdFanin = Vec_IntEntry( vDsdLits, iDsdLit++ ); Vec_IntPush( vPerm, iDsdFanin ); continue; } // find a matching component pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(iNodFanin) ); Kit_DsdObjForEachFaninReverse( pNtk, pDsdObj, iDsdFanin, i ) { pDsdFanin = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iDsdFanin) ); if ( pDsdFanin == NULL ) continue; if ( pDsdFanin->fMark == 1 ) continue; if ( !((pDsdFanin->Type == KIT_DSD_AND && pNodFanin->Type == AMAP_OBJ_AND) || (pDsdFanin->Type == KIT_DSD_XOR && pNodFanin->Type == AMAP_OBJ_XOR) || (pDsdFanin->Type == KIT_DSD_PRIME && pNodFanin->Type == AMAP_OBJ_MUX)) ) continue; vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Abc_LitRegular(iDsdFanin), pNodFanin ); if ( vPermFanin == NULL ) { Vec_IntFree( vNodFanin ); Vec_IntFree( vDsdLits ); Vec_IntFree( vPerm ); return NULL; } pDsdFanin->fMark = 1; Vec_IntForEachEntry( vPermFanin, Value, j ) Vec_IntPush( vPerm, Value ); Vec_IntFree( vPermFanin ); break; } } // assert( iDsdLit == Vec_IntSize(vDsdLits) ); if ( iDsdLit != Vec_IntSize(vDsdLits) ) Vec_IntFreeP( &vPerm ); Vec_IntFree( vNodFanin ); Vec_IntFree( vDsdLits ); return vPerm; } /**Function************************************************************* Synopsis [Performs verification of one gate and one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Amap_LibVerifyPerm_rec( Amap_Lib_t * pLib, Amap_Nod_t * pNod, Vec_Ptr_t * vTtElems, Vec_Int_t * vTruth, int nWords, int * piInput ) { Amap_Nod_t * pFan0, * pFan1; unsigned * pTruth0, * pTruth1, * pTruth; int i; assert( pNod->Type != AMAP_OBJ_MUX ); if ( pNod->Id == 0 ) return (unsigned *)Vec_PtrEntry( vTtElems, (*piInput)++ ); pFan0 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan0) ); pTruth0 = Amap_LibVerifyPerm_rec( pLib, pFan0, vTtElems, vTruth, nWords, piInput ); pFan1 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan1) ); pTruth1 = Amap_LibVerifyPerm_rec( pLib, pFan1, vTtElems, vTruth, nWords, piInput ); pTruth = Vec_IntFetch( vTruth, nWords ); if ( pNod->Type == AMAP_OBJ_XOR ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] ^ pTruth1[i]; else if ( !Abc_LitIsCompl(pNod->iFan0) && !Abc_LitIsCompl(pNod->iFan1) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & pTruth1[i]; else if ( !Abc_LitIsCompl(pNod->iFan0) && Abc_LitIsCompl(pNod->iFan1) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & ~pTruth1[i]; else if ( Abc_LitIsCompl(pNod->iFan0) && !Abc_LitIsCompl(pNod->iFan1) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & pTruth1[i]; else // if ( Abc_LitIsCompl(pNod->iFan0) && Hop_ObjFaninC1(pObj) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; return pTruth; } /**Function************************************************************* Synopsis [Performs verification of one gate and one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibVerifyPerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, int * pArray ) { Vec_Ptr_t * vTtElems; Vec_Ptr_t * vTtElemsPol; Vec_Int_t * vTruth; unsigned * pTruth; int i, nWords; int iInput = 0; // allocate storage for truth tables assert( pGate->nPins > 1 ); nWords = Kit_TruthWordNum( pGate->nPins ); vTruth = Vec_IntAlloc( nWords * AMAP_MAXINS ); vTtElems = Vec_PtrAllocTruthTables( pGate->nPins ); vTtElemsPol = Vec_PtrAlloc( pGate->nPins ); for ( i = 0; i < (int)pGate->nPins; i++ ) { pTruth = (unsigned *)Vec_PtrEntry( vTtElems, Abc_Lit2Var(pArray[i]) ); if ( Abc_LitIsCompl( pArray[i] ) ) Kit_TruthNot( pTruth, pTruth, pGate->nPins ); Vec_PtrPush( vTtElemsPol, pTruth ); } //Extra_PrintBinary( stdout, Vec_PtrEntry(vTtElemsPol, 0), 4 ); printf("\n" ); //Extra_PrintBinary( stdout, Vec_PtrEntry(vTtElemsPol, 1), 4 ); printf("\n" ); // compute the truth table recursively pTruth = Amap_LibVerifyPerm_rec( pLib, pNod, vTtElemsPol, vTruth, nWords, &iInput ); assert( iInput == (int)pGate->nPins ); if ( Abc_LitIsCompl(pNtk->Root) ) Kit_TruthNot( pTruth, pTruth, pGate->nPins ); //Extra_PrintBinary( stdout, pTruth, 4 ); printf("\n" ); //Extra_PrintBinary( stdout, pGate->pFunc, 4 ); printf("\n" ); // compare if ( !Kit_TruthIsEqual(pGate->pFunc, pTruth, pGate->nPins) ) printf( "Verification failed for gate %d (%s) and node %d.\n", pGate->Id, pGate->pForm, pNod->Id ); Vec_IntFree( vTruth ); Vec_PtrFree( vTtElems ); Vec_PtrFree( vTtElemsPol ); } /**Function************************************************************* Synopsis [Matches the node with the DSD of a gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, char * pArray ) { int fVerbose = 0; Vec_Int_t * vPerm; int Entry, Entry2, i, k; // Kit_DsdPrint( stdout, pNtk ); vPerm = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Abc_LitRegular(pNtk->Root), pNod ); if ( vPerm == NULL ) return 0; // check that the permutation is valid assert( Vec_IntSize(vPerm) == (int)pNod->nSuppSize ); Vec_IntForEachEntry( vPerm, Entry, i ) Vec_IntForEachEntryStart( vPerm, Entry2, k, i+1 ) if ( Abc_Lit2Var(Entry) == Abc_Lit2Var(Entry2) ) { Vec_IntFree( vPerm ); return 0; } // reverse the permutation Vec_IntForEachEntry( vPerm, Entry, i ) { assert( Entry < 2 * (int)pNod->nSuppSize ); pArray[Abc_Lit2Var(Entry)] = Abc_Var2Lit( i, Abc_LitIsCompl(Entry) ); // pArray[i] = Entry; //printf( "%d=%d%c ", Abc_Lit2Var(Entry), i, Abc_LitIsCompl(Entry)?'-':'+' ); } //printf( "\n" ); // if ( Kit_DsdNonDsdSizeMax(pNtk) < 3 ) // Amap_LibVerifyPerm( pLib, pGate, pNtk, pNod, Vec_IntArray(vPerm) ); Vec_IntFree( vPerm ); // print the result if ( fVerbose ) { printf( "node %4d : ", pNod->Id ); for ( i = 0; i < (int)pNod->nSuppSize; i++ ) printf( "%d=%d%c ", i, Abc_Lit2Var(pArray[i]), Abc_LitIsCompl(pArray[i])?'-':'+' ); printf( "\n" ); } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END