mirror of https://github.com/YosysHQ/abc.git
381 lines
13 KiB
C
381 lines
13 KiB
C
/**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
|
|
|