blob: 94c5bb9fe05dd9dfff3075dc5ddc63d45fab0ed0 [file] [log] [blame]
/**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