| /**CFile**************************************************************** |
| |
| FileName [amapRule.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Technology mapper for standard cells.] |
| |
| Synopsis [Matching rules.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: amapRule.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 /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| extern int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, char * pArray ); |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks if the three-argument rule exist.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Amap_CreateRulesPrime( Amap_Lib_t * p, Vec_Int_t * vNods0, Vec_Int_t * vNods1, Vec_Int_t * vNods2 ) |
| { |
| Vec_Int_t * vRes; |
| int i, k, j, iNod, iNod0, iNod1, iNod2; |
| if ( p->vRules3 == NULL ) |
| p->vRules3 = Vec_IntAlloc( 100 ); |
| vRes = Vec_IntAlloc( 10 ); |
| Vec_IntForEachEntry( vNods0, iNod0, i ) |
| Vec_IntForEachEntry( vNods1, iNod1, k ) |
| Vec_IntForEachEntry( vNods2, iNod2, j ) |
| { |
| iNod = Amap_LibFindMux( p, iNod0, iNod1, iNod2 ); |
| if ( iNod == -1 ) |
| iNod = Amap_LibCreateMux( p, iNod0, iNod1, iNod2 ); |
| Vec_IntPush( vRes, Abc_Var2Lit(iNod, 0) ); |
| } |
| return vRes; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Amap_CreateRulesTwo( Amap_Lib_t * p, Vec_Int_t * vNods, Vec_Int_t * vNods0, Vec_Int_t * vNods1, int fXor ) |
| { |
| int i, k, iNod, iNod0, iNod1; |
| Vec_IntForEachEntry( vNods0, iNod0, i ) |
| Vec_IntForEachEntry( vNods1, iNod1, k ) |
| { |
| iNod = Amap_LibFindNode( p, iNod0, iNod1, fXor ); |
| if ( iNod == -1 ) |
| iNod = Amap_LibCreateNode( p, iNod0, iNod1, fXor ); |
| Vec_IntPushUnique( vNods, Abc_Var2Lit(iNod, 0) ); |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Amap_CreateCheckAllZero( Vec_Ptr_t * vVecNods ) |
| { |
| Vec_Int_t * vNods; |
| int i; |
| Vec_PtrForEachEntryReverse( Vec_Int_t *, vVecNods, vNods, i ) |
| if ( Vec_IntSize(vNods) != 1 || Vec_IntEntry(vNods,0) != 0 ) |
| return 0; |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Amap_CreateRulesVector_rec( Amap_Lib_t * p, Vec_Ptr_t * vVecNods, int fXor ) |
| { |
| Vec_Ptr_t * vVecNods0, * vVecNods1; |
| Vec_Int_t * vRes, * vNods, * vNods0, * vNods1; |
| int i, k; |
| if ( Vec_PtrSize(vVecNods) == 1 ) |
| return Vec_IntDup( (Vec_Int_t *)Vec_PtrEntry(vVecNods, 0) ); |
| vRes = Vec_IntAlloc( 10 ); |
| vVecNods0 = Vec_PtrAlloc( Vec_PtrSize(vVecNods) ); |
| vVecNods1 = Vec_PtrAlloc( Vec_PtrSize(vVecNods) ); |
| if ( Amap_CreateCheckAllZero(vVecNods) ) |
| { |
| for ( i = Vec_PtrSize(vVecNods)-1; i > 0; i-- ) |
| { |
| Vec_PtrClear( vVecNods0 ); |
| Vec_PtrClear( vVecNods1 ); |
| Vec_PtrForEachEntryStop( Vec_Int_t *, vVecNods, vNods, k, i ) |
| Vec_PtrPush( vVecNods0, vNods ); |
| Vec_PtrForEachEntryStart( Vec_Int_t *, vVecNods, vNods, k, i ) |
| Vec_PtrPush( vVecNods1, vNods ); |
| vNods0 = Amap_CreateRulesVector_rec( p, vVecNods0, fXor ); |
| vNods1 = Amap_CreateRulesVector_rec( p, vVecNods1, fXor ); |
| Amap_CreateRulesTwo( p, vRes, vNods0, vNods1, fXor ); |
| Vec_IntFree( vNods0 ); |
| Vec_IntFree( vNods1 ); |
| } |
| } |
| else |
| { |
| int Limit = (1 << Vec_PtrSize(vVecNods))-2; |
| for ( i = 1; i < Limit; i++ ) |
| { |
| Vec_PtrClear( vVecNods0 ); |
| Vec_PtrClear( vVecNods1 ); |
| Vec_PtrForEachEntryReverse( Vec_Int_t *, vVecNods, vNods, k ) |
| { |
| if ( i & (1 << k) ) |
| Vec_PtrPush( vVecNods1, vNods ); |
| else |
| Vec_PtrPush( vVecNods0, vNods ); |
| } |
| assert( Vec_PtrSize(vVecNods0) > 0 ); |
| assert( Vec_PtrSize(vVecNods1) > 0 ); |
| assert( Vec_PtrSize(vVecNods0) < Vec_PtrSize(vVecNods) ); |
| assert( Vec_PtrSize(vVecNods1) < Vec_PtrSize(vVecNods) ); |
| vNods0 = Amap_CreateRulesVector_rec( p, vVecNods0, fXor ); |
| vNods1 = Amap_CreateRulesVector_rec( p, vVecNods1, fXor ); |
| Amap_CreateRulesTwo( p, vRes, vNods0, vNods1, fXor ); |
| Vec_IntFree( vNods0 ); |
| Vec_IntFree( vNods1 ); |
| } |
| } |
| Vec_PtrFree( vVecNods0 ); |
| Vec_PtrFree( vVecNods1 ); |
| return vRes; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Amap_CreateRulesFromDsd_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * p, int iLit ) |
| { |
| Vec_Int_t * vRes = NULL; |
| Vec_Ptr_t * vVecNods; |
| Vec_Int_t * vNodsFanin; |
| Kit_DsdObj_t * pObj; |
| unsigned i; |
| int iFanin, iNod, k; |
| assert( !Abc_LitIsCompl(iLit) ); |
| pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); |
| if ( pObj == NULL ) |
| return Vec_IntStartNatural( 1 ); |
| // solve for the inputs |
| vVecNods = Vec_PtrAlloc( pObj->nFans ); |
| Kit_DsdObjForEachFanin( p, pObj, iFanin, i ) |
| { |
| vNodsFanin = Amap_CreateRulesFromDsd_rec( pLib, p, Abc_LitRegular(iFanin) ); |
| if ( Abc_LitIsCompl(iFanin) ) |
| { |
| Vec_IntForEachEntry( vNodsFanin, iNod, k ) |
| if ( iNod > 0 ) |
| Vec_IntWriteEntry( vNodsFanin, k, Abc_LitNot(iNod) ); |
| } |
| Vec_PtrPush( vVecNods, vNodsFanin ); |
| } |
| if ( pObj->Type == KIT_DSD_AND ) |
| vRes = Amap_CreateRulesVector_rec( pLib, vVecNods, 0 ); |
| else if ( pObj->Type == KIT_DSD_XOR ) |
| vRes = Amap_CreateRulesVector_rec( pLib, vVecNods, 1 ); |
| else if ( pObj->Type == KIT_DSD_PRIME ) |
| { |
| assert( pObj->nFans == 3 ); |
| assert( Kit_DsdObjTruth(pObj)[0] == 0xCACACACA ); |
| vRes = Amap_CreateRulesPrime( pLib, (Vec_Int_t *)Vec_PtrEntry(vVecNods, 0), |
| (Vec_Int_t *)Vec_PtrEntry(vVecNods, 1), (Vec_Int_t *)Vec_PtrEntry(vVecNods, 2) ); |
| } |
| else assert( 0 ); |
| Vec_PtrForEachEntry( Vec_Int_t *, vVecNods, vNodsFanin, k ) |
| Vec_IntFree( vNodsFanin ); |
| Vec_PtrFree( vVecNods ); |
| return vRes; |
| } |
| Vec_Int_t * Amap_CreateRulesFromDsd( Amap_Lib_t * pLib, Kit_DsdNtk_t * p ) |
| { |
| Vec_Int_t * vNods; |
| int iNod, i; |
| assert( p->nVars >= 2 ); |
| vNods = Amap_CreateRulesFromDsd_rec( pLib, p, Abc_LitRegular(p->Root) ); |
| if ( vNods == NULL ) |
| return NULL; |
| if ( Abc_LitIsCompl(p->Root) ) |
| { |
| Vec_IntForEachEntry( vNods, iNod, i ) |
| Vec_IntWriteEntry( vNods, i, Abc_LitNot(iNod) ); |
| } |
| return vNods; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns 1 if DSD network contains asymentry due to complements.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Amap_CreateCheckEqual_rec( Kit_DsdNtk_t * p, int iLit0, int iLit1 ) |
| { |
| Kit_DsdObj_t * pObj0, * pObj1; |
| int i; |
| assert( !Abc_LitIsCompl(iLit0) ); |
| assert( !Abc_LitIsCompl(iLit1) ); |
| pObj0 = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit0) ); |
| pObj1 = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit1) ); |
| if ( pObj0 == NULL && pObj1 == NULL ) |
| return 1; |
| if ( pObj0 == NULL || pObj1 == NULL ) |
| return 0; |
| if ( pObj0->Type != pObj1->Type ) |
| return 0; |
| if ( pObj0->nFans != pObj1->nFans ) |
| return 0; |
| if ( pObj0->Type == KIT_DSD_PRIME ) |
| return 0; |
| assert( pObj0->Type == KIT_DSD_AND || pObj0->Type == KIT_DSD_XOR ); |
| for ( i = 0; i < (int)pObj0->nFans; i++ ) |
| { |
| if ( Abc_LitIsCompl(pObj0->pFans[i]) != Abc_LitIsCompl(pObj1->pFans[i]) ) |
| return 0; |
| if ( !Amap_CreateCheckEqual_rec( p, Abc_LitRegular(pObj0->pFans[i]), Abc_LitRegular(pObj1->pFans[i]) ) ) |
| return 0; |
| } |
| return 1; |
| } |
| void Amap_CreateCheckAsym_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t ** pvSyms ) |
| { |
| Kit_DsdObj_t * pObj; |
| int i, k, iFanin; |
| assert( !Abc_LitIsCompl(iLit) ); |
| pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); |
| if ( pObj == NULL ) |
| return; |
| Kit_DsdObjForEachFanin( p, pObj, iFanin, i ) |
| Amap_CreateCheckAsym_rec( p, Abc_LitRegular(iFanin), pvSyms ); |
| if ( pObj->Type == KIT_DSD_PRIME ) |
| return; |
| assert( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ); |
| for ( i = 0; i < (int)pObj->nFans; i++ ) |
| for ( k = i+1; k < (int)pObj->nFans; k++ ) |
| { |
| if ( Abc_LitIsCompl(pObj->pFans[i]) != Abc_LitIsCompl(pObj->pFans[k]) && |
| Kit_DsdNtkObj(p, Abc_Lit2Var(pObj->pFans[i])) == NULL && |
| Kit_DsdNtkObj(p, Abc_Lit2Var(pObj->pFans[k])) == NULL ) |
| { |
| if ( *pvSyms == NULL ) |
| *pvSyms = Vec_IntAlloc( 16 ); |
| Vec_IntPush( *pvSyms, (Abc_Lit2Var(pObj->pFans[i]) << 8) | Abc_Lit2Var(pObj->pFans[k]) ); |
| } |
| } |
| } |
| void Amap_CreateCheckAsym( Kit_DsdNtk_t * p, Vec_Int_t ** pvSyms ) |
| { |
| Amap_CreateCheckAsym_rec( p, Abc_LitRegular(p->Root), pvSyms ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates rules for the given gate] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Amap_CreateRulesForGate( Amap_Lib_t * pLib, Amap_Gat_t * pGate ) |
| { |
| Kit_DsdNtk_t * pNtk, * pTemp; |
| Vec_Int_t * vSyms = NULL; |
| Vec_Int_t * vNods; |
| Amap_Nod_t * pNod; |
| Amap_Set_t * pSet, * pSet2; |
| int iNod, i, k, Entry; |
| // if ( pGate->nPins > 4 ) |
| // return; |
| pNtk = Kit_DsdDecomposeMux( pGate->pFunc, pGate->nPins, 2 ); |
| if ( pGate->nPins == 2 && (pGate->pFunc[0] == 0x66666666 || pGate->pFunc[0] == ~0x66666666) ) |
| pLib->fHasXor = 1; |
| if ( Kit_DsdNonDsdSizeMax(pNtk) == 3 ) |
| pLib->fHasMux = pGate->fMux = 1; |
| pNtk = Kit_DsdExpand( pTemp = pNtk ); |
| Kit_DsdNtkFree( pTemp ); |
| Kit_DsdVerify( pNtk, pGate->pFunc, pGate->nPins ); |
| // check symmetries |
| Amap_CreateCheckAsym( pNtk, &vSyms ); |
| // if ( vSyms ) |
| // Kit_DsdPrint( stdout, pNtk ), printf( "\n" ); |
| |
| if ( pLib->fVerbose ) |
| //if ( pGate->fMux ) |
| { |
| printf( "\nProcessing library gate %4d: %10s ", pGate->Id, pGate->pName ); |
| Kit_DsdPrint( stdout, pNtk ); |
| } |
| vNods = Amap_CreateRulesFromDsd( pLib, pNtk ); |
| if ( vNods ) |
| { |
| Vec_IntForEachEntry( vNods, iNod, i ) |
| { |
| assert( iNod > 1 ); |
| pNod = Amap_LibNod( pLib, Abc_Lit2Var(iNod) ); |
| // assert( pNod->Type == AMAP_OBJ_MUX || pNod->nSuppSize == pGate->nPins ); |
| pSet = (Amap_Set_t *)Aig_MmFlexEntryFetch( pLib->pMemSet, sizeof(Amap_Set_t) ); |
| memset( pSet, 0, sizeof(Amap_Set_t) ); |
| pSet->iGate = pGate->Id; |
| pSet->fInv = Abc_LitIsCompl(iNod); |
| pSet->nIns = pGate->nPins; |
| if ( Amap_LibDeriveGatePerm( pLib, pGate, pNtk, pNod, pSet->Ins ) == 0 ) |
| { |
| if ( pLib->fVerbose ) |
| { |
| printf( "Cound not prepare gate \"%s\": ", pGate->pName ); |
| Kit_DsdPrint( stdout, pNtk ); |
| } |
| continue; |
| } |
| pSet->pNext = pNod->pSets; |
| pNod->pSets = pSet; |
| pLib->nSets++; |
| if ( vSyms == NULL ) |
| continue; |
| // continue; |
| // add sets equivalent due to symmetry |
| Vec_IntForEachEntry( vSyms, Entry, k ) |
| { |
| int iThis = Entry & 0xff; |
| int iThat = Entry >> 8; |
| // printf( "%d %d\n", iThis, iThat ); |
| // create new set |
| pSet2 = (Amap_Set_t *)Aig_MmFlexEntryFetch( pLib->pMemSet, sizeof(Amap_Set_t) ); |
| memset( pSet2, 0, sizeof(Amap_Set_t) ); |
| pSet2->iGate = pGate->Id; |
| pSet2->fInv = Abc_LitIsCompl(iNod); |
| pSet2->nIns = pGate->nPins; |
| memcpy( pSet2->Ins, pSet->Ins, pGate->nPins ); |
| // update inputs |
| pSet2->Ins[iThis] = Abc_Var2Lit( Abc_Lit2Var(pSet->Ins[iThat]), Abc_LitIsCompl(pSet->Ins[iThis]) ); |
| pSet2->Ins[iThat] = Abc_Var2Lit( Abc_Lit2Var(pSet->Ins[iThis]), Abc_LitIsCompl(pSet->Ins[iThat]) ); |
| // add set to collection |
| pSet2->pNext = pNod->pSets; |
| pNod->pSets = pSet2; |
| pLib->nSets++; |
| } |
| } |
| Vec_IntFree( vNods ); |
| } |
| Kit_DsdNtkFree( pNtk ); |
| Vec_IntFreeP( &vSyms ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates rules for the given gate] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Amap_LibCreateRules( Amap_Lib_t * pLib, int fVeryVerbose ) |
| { |
| Amap_Gat_t * pGate; |
| int i, nGates = 0; |
| // abctime clk = Abc_Clock(); |
| pLib->fVerbose = fVeryVerbose; |
| pLib->vRules = Vec_PtrAlloc( 100 ); |
| pLib->vRulesX = Vec_PtrAlloc( 100 ); |
| pLib->vRules3 = Vec_IntAlloc( 100 ); |
| Amap_LibCreateVar( pLib ); |
| Vec_PtrForEachEntry( Amap_Gat_t *, pLib->vSelect, pGate, i ) |
| { |
| if ( pGate->nPins < 2 ) |
| continue; |
| if ( pGate->pFunc == NULL ) |
| { |
| printf( "Amap_LibCreateRules(): Skipping gate %s (%s).\n", pGate->pName, pGate->pForm ); |
| continue; |
| } |
| Amap_CreateRulesForGate( pLib, pGate ); |
| nGates++; |
| } |
| assert( Vec_PtrSize(pLib->vRules) == 2*pLib->nNodes ); |
| assert( Vec_PtrSize(pLib->vRulesX) == 2*pLib->nNodes ); |
| pLib->pRules = Amap_LibLookupTableAlloc( pLib->vRules, 0 ); |
| pLib->pRulesX = Amap_LibLookupTableAlloc( pLib->vRulesX, 0 ); |
| Vec_VecFree( (Vec_Vec_t *)pLib->vRules ); pLib->vRules = NULL; |
| Vec_VecFree( (Vec_Vec_t *)pLib->vRulesX ); pLib->vRulesX = NULL; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |