mirror of https://github.com/YosysHQ/abc.git
317 lines
12 KiB
C
317 lines
12 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [mpmAbc.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Configurable technology mapper.]
|
|
|
|
Synopsis [Interface with ABC data structures.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 1, 2013.]
|
|
|
|
Revision [$Id: mpmAbc.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "aig/gia/gia.h"
|
|
#include "mpmInt.h"
|
|
#include "misc/util/utilTruth.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline int Mig_ObjFanin0Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); }
|
|
static inline int Mig_ObjFanin1Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) ); }
|
|
Mig_Man_t * Mig_ManCreate( void * pGia )
|
|
{
|
|
Gia_Man_t * p = (Gia_Man_t *)pGia;
|
|
Mig_Man_t * pNew;
|
|
Gia_Obj_t * pObj;
|
|
int i;
|
|
// create the new manager
|
|
pNew = Mig_ManStart();
|
|
pNew->pName = Abc_UtilStrsav( p->pName );
|
|
Gia_ManConst0(p)->Value = 0;
|
|
// create objects
|
|
Gia_ManForEachObj1( p, pObj, i )
|
|
{
|
|
if ( Gia_ObjIsMux(p, i) )
|
|
pObj->Value = Mig_ManAppendMux( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin2Copy(p, pObj) );
|
|
else if ( Gia_ObjIsXor(pObj) )
|
|
pObj->Value = Mig_ManAppendXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
|
else if ( Gia_ObjIsAnd(pObj) )
|
|
pObj->Value = Mig_ManAppendAnd( pNew, Mig_ObjFanin0Copy(pObj), Mig_ObjFanin1Copy(pObj) );
|
|
else if ( Gia_ObjIsCi(pObj) )
|
|
pObj->Value = Mig_ManAppendCi( pNew );
|
|
else if ( Gia_ObjIsCo(pObj) )
|
|
pObj->Value = Mig_ManAppendCo( pNew, Mig_ObjFanin0Copy(pObj) );
|
|
else assert( 0 );
|
|
}
|
|
Mig_ManSetRegNum( pNew, Gia_ManRegNum(p) );
|
|
return pNew;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Recursively derives the local AIG for the cut.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline unsigned Mpm_CutDataInt( Mpm_Cut_t * pCut ) { return pCut->hNext; }
|
|
static inline void Mpm_CutSetDataInt( Mpm_Cut_t * pCut, unsigned Data ) { pCut->hNext = Data; }
|
|
int Mpm_ManNodeIfToGia_rec( Gia_Man_t * pNew, Mpm_Man_t * pMan, Mig_Obj_t * pObj, Vec_Ptr_t * vVisited, int fHash )
|
|
{
|
|
Mig_Obj_t * pTemp;
|
|
Mpm_Cut_t * pCut;
|
|
int iFunc, iFunc0, iFunc1, iFunc2 = 0;
|
|
assert( fHash == 0 );
|
|
// get the best cut
|
|
pCut = Mpm_ObjCutBestP( pMan, pObj );
|
|
// if the cut is visited, return the result
|
|
if ( Mpm_CutDataInt(pCut) )
|
|
return Mpm_CutDataInt(pCut);
|
|
// mark the node as visited
|
|
Vec_PtrPush( vVisited, pCut );
|
|
// insert the worst case
|
|
Mpm_CutSetDataInt( pCut, ~0 );
|
|
// skip in case of primary input
|
|
if ( Mig_ObjIsCi(pObj) )
|
|
return Mpm_CutDataInt(pCut);
|
|
// compute the functions of the children
|
|
for ( pTemp = pObj; pTemp; pTemp = Mig_ObjSibl(pTemp) )
|
|
{
|
|
iFunc0 = Mpm_ManNodeIfToGia_rec( pNew, pMan, Mig_ObjFanin0(pTemp), vVisited, fHash );
|
|
if ( iFunc0 == ~0 )
|
|
continue;
|
|
iFunc1 = Mpm_ManNodeIfToGia_rec( pNew, pMan, Mig_ObjFanin1(pTemp), vVisited, fHash );
|
|
if ( iFunc1 == ~0 )
|
|
continue;
|
|
if ( Mig_ObjIsNode3(pTemp) )
|
|
{
|
|
iFunc2 = Mpm_ManNodeIfToGia_rec( pNew, pMan, Mig_ObjFanin2(pTemp), vVisited, fHash );
|
|
if ( iFunc2 == ~0 )
|
|
continue;
|
|
iFunc2 = Abc_LitNotCond(iFunc2, Mig_ObjFaninC2(pTemp));
|
|
}
|
|
iFunc0 = Abc_LitNotCond(iFunc0, Mig_ObjFaninC0(pTemp));
|
|
iFunc1 = Abc_LitNotCond(iFunc1, Mig_ObjFaninC1(pTemp));
|
|
// both branches are solved
|
|
if ( fHash )
|
|
{
|
|
if ( Mig_ObjIsMux(pTemp) )
|
|
iFunc = Gia_ManHashMux( pNew, iFunc2, iFunc1, iFunc0 );
|
|
else if ( Mig_ObjIsXor(pTemp) )
|
|
iFunc = Gia_ManHashXor( pNew, iFunc0, iFunc1 );
|
|
else
|
|
iFunc = Gia_ManHashAnd( pNew, iFunc0, iFunc1 );
|
|
}
|
|
else
|
|
{
|
|
if ( Mig_ObjIsMux(pTemp) )
|
|
iFunc = Gia_ManAppendMux( pNew, iFunc2, iFunc1, iFunc0 );
|
|
else if ( Mig_ObjIsXor(pTemp) )
|
|
iFunc = Gia_ManAppendXor( pNew, iFunc0, iFunc1 );
|
|
else
|
|
iFunc = Gia_ManAppendAnd( pNew, iFunc0, iFunc1 );
|
|
}
|
|
if ( Mig_ObjPhase(pTemp) != Mig_ObjPhase(pObj) )
|
|
iFunc = Abc_LitNot(iFunc);
|
|
Mpm_CutSetDataInt( pCut, iFunc );
|
|
break;
|
|
}
|
|
return Mpm_CutDataInt(pCut);
|
|
}
|
|
int Mpm_ManNodeIfToGia( Gia_Man_t * pNew, Mpm_Man_t * pMan, Mig_Obj_t * pObj, Vec_Int_t * vLeaves, int fHash )
|
|
{
|
|
Mpm_Cut_t * pCut;
|
|
Mig_Obj_t * pFanin;
|
|
int i, iRes;
|
|
// get the best cut
|
|
pCut = Mpm_ObjCutBestP( pMan, pObj );
|
|
assert( pCut->nLeaves > 1 );
|
|
// set the leaf variables
|
|
Mpm_CutForEachLeaf( pMan->pMig, pCut, pFanin, i )
|
|
Mpm_CutSetDataInt( Mpm_ObjCutBestP(pMan, pFanin), Vec_IntEntry(vLeaves, i) );
|
|
// recursively compute the function while collecting visited cuts
|
|
Vec_PtrClear( pMan->vTemp );
|
|
iRes = Mpm_ManNodeIfToGia_rec( pNew, pMan, pObj, pMan->vTemp, fHash );
|
|
if ( iRes == ~0 )
|
|
{
|
|
Abc_Print( -1, "Mpm_ManNodeIfToGia(): Computing local AIG has failed.\n" );
|
|
return ~0;
|
|
}
|
|
// clean the cuts
|
|
Mpm_CutForEachLeaf( pMan->pMig, pCut, pFanin, i )
|
|
Mpm_CutSetDataInt( Mpm_ObjCutBestP(pMan, pFanin), 0 );
|
|
Vec_PtrForEachEntry( Mpm_Cut_t *, pMan->vTemp, pCut, i )
|
|
Mpm_CutSetDataInt( pCut, 0 );
|
|
return iRes;
|
|
}
|
|
void * Mpm_ManFromIfLogic( Mpm_Man_t * pMan )
|
|
{
|
|
Gia_Man_t * pNew;
|
|
Mpm_Cut_t * pCutBest;
|
|
Mig_Obj_t * pObj, * pFanin;
|
|
Vec_Int_t * vMapping, * vMapping2, * vPacking = NULL;
|
|
Vec_Int_t * vLeaves, * vLeaves2, * vCover;
|
|
word uTruth, * pTruth = &uTruth;
|
|
int i, k, Entry, iLitNew;
|
|
// assert( !pMan->pPars->fDeriveLuts || pMan->pPars->fTruth );
|
|
// start mapping and packing
|
|
vMapping = Vec_IntStart( Mig_ManObjNum(pMan->pMig) );
|
|
vMapping2 = Vec_IntStart( 1 );
|
|
if ( 0 ) // pMan->pPars->fDeriveLuts && pMan->pPars->pLutStruct )
|
|
{
|
|
vPacking = Vec_IntAlloc( 1000 );
|
|
Vec_IntPush( vPacking, 0 );
|
|
}
|
|
// create new manager
|
|
pNew = Gia_ManStart( Mig_ManObjNum(pMan->pMig) );
|
|
// iterate through nodes used in the mapping
|
|
vCover = Vec_IntAlloc( 1 << 16 );
|
|
vLeaves = Vec_IntAlloc( 16 );
|
|
vLeaves2 = Vec_IntAlloc( 16 );
|
|
Mig_ManCleanCopy( pMan->pMig );
|
|
Mig_ManForEachObj( pMan->pMig, pObj )
|
|
{
|
|
if ( !Mpm_ObjMapRef(pMan, pObj) && !Mig_ObjIsTerm(pObj) )
|
|
continue;
|
|
if ( Mig_ObjIsNode(pObj) )
|
|
{
|
|
// collect leaves of the best cut
|
|
Vec_IntClear( vLeaves );
|
|
pCutBest = Mpm_ObjCutBestP( pMan, pObj );
|
|
Mpm_CutForEachLeaf( pMan->pMig, pCutBest, pFanin, k )
|
|
Vec_IntPush( vLeaves, Mig_ObjCopy(pFanin) );
|
|
if ( pMan->pPars->fDeriveLuts && (pMan->pPars->fUseTruth || pMan->pPars->fUseDsd) )
|
|
{
|
|
extern int Gia_ManFromIfLogicNode( Gia_Man_t * pNew, int iObj, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp,
|
|
word * pRes, char * pStr, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking );
|
|
if ( pMan->pPars->fUseTruth )
|
|
pTruth = Mpm_CutTruth(pMan, Abc_Lit2Var(pCutBest->iFunc));
|
|
else
|
|
uTruth = Mpm_CutTruthFromDsd( pMan, pCutBest, Abc_Lit2Var(pCutBest->iFunc) );
|
|
// Kit_DsdPrintFromTruth( pTruth, Vec_IntSize(vLeaves) ); printf( "\n" );
|
|
// perform decomposition of the cut
|
|
iLitNew = Gia_ManFromIfLogicNode( pNew, Mig_ObjId(pObj), vLeaves, vLeaves2, pTruth, NULL, vCover, vMapping, vMapping2, vPacking );
|
|
iLitNew = Abc_LitNotCond( iLitNew, pCutBest->fCompl ^ Abc_LitIsCompl(pCutBest->iFunc) );
|
|
}
|
|
else
|
|
{
|
|
// perform one of the two types of mapping: with and without structures
|
|
iLitNew = Mpm_ManNodeIfToGia( pNew, pMan, pObj, vLeaves, 0 );
|
|
// write mapping
|
|
Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLitNew), Vec_IntSize(vMapping2) );
|
|
Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) );
|
|
Vec_IntForEachEntry( vLeaves, Entry, k )
|
|
assert( Abc_Lit2Var(Entry) < Abc_Lit2Var(iLitNew) );
|
|
Vec_IntForEachEntry( vLeaves, Entry, k )
|
|
Vec_IntPush( vMapping2, Abc_Lit2Var(Entry) );
|
|
Vec_IntPush( vMapping2, Abc_Lit2Var(iLitNew) );
|
|
}
|
|
}
|
|
else if ( Mig_ObjIsCi(pObj) )
|
|
iLitNew = Gia_ManAppendCi(pNew);
|
|
else if ( Mig_ObjIsCo(pObj) )
|
|
iLitNew = Gia_ManAppendCo( pNew, Abc_LitNotCond(Mig_ObjCopy(Mig_ObjFanin0(pObj)), Mig_ObjFaninC0(pObj)) );
|
|
else if ( Mig_ObjIsConst0(pObj) )
|
|
{
|
|
iLitNew = 0;
|
|
// create const LUT
|
|
Vec_IntWriteEntry( vMapping, 0, Vec_IntSize(vMapping2) );
|
|
Vec_IntPush( vMapping2, 0 );
|
|
Vec_IntPush( vMapping2, 0 );
|
|
}
|
|
else assert( 0 );
|
|
Mig_ObjSetCopy( pObj, iLitNew );
|
|
}
|
|
Vec_IntFree( vCover );
|
|
Vec_IntFree( vLeaves );
|
|
Vec_IntFree( vLeaves2 );
|
|
// printf( "Mapping array size: IfMan = %d. Gia = %d. Increase = %.2f\n",
|
|
// Mig_ManObjNum(pMan), Gia_ManObjNum(pNew), 1.0 * Gia_ManObjNum(pNew) / Mig_ManObjNum(pMan) );
|
|
// finish mapping
|
|
if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) )
|
|
Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) );
|
|
else
|
|
Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 );
|
|
assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) );
|
|
Vec_IntForEachEntry( vMapping, Entry, i )
|
|
if ( Entry > 0 )
|
|
Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) );
|
|
Vec_IntAppend( vMapping, vMapping2 );
|
|
Vec_IntFree( vMapping2 );
|
|
// attach mapping and packing
|
|
assert( pNew->vMapping == NULL );
|
|
assert( pNew->vPacking == NULL );
|
|
pNew->vMapping = vMapping;
|
|
pNew->vPacking = vPacking;
|
|
// verify that COs have mapping
|
|
{
|
|
Gia_Obj_t * pObj;
|
|
Gia_ManForEachCo( pNew, pObj, i )
|
|
assert( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) || Gia_ObjIsLut(pNew, Gia_ObjFaninId0p(pNew, pObj)) );
|
|
}
|
|
return pNew;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
/*
|
|
void Mig_ManTest2( Gia_Man_t * pGia )
|
|
{
|
|
extern int Gia_ManSuppSizeTest( Gia_Man_t * p );
|
|
Mig_Man_t * p;
|
|
Gia_ManSuppSizeTest( pGia );
|
|
p = Mig_ManCreate( pGia );
|
|
Mig_ManSuppSizeTest( p );
|
|
Mig_ManStop( p );
|
|
}
|
|
*/
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|