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