mirror of https://github.com/YosysHQ/abc.git
295 lines
9.7 KiB
C
295 lines
9.7 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [lpkAbcDec.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Fast Boolean matching for LUT structures.]
|
|
|
|
Synopsis [The new core procedure.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - April 28, 2007.]
|
|
|
|
Revision [$Id: lpkAbcDec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "lpkInt.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Implements the function.]
|
|
|
|
Description [Returns the node implementing this function.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Abc_Obj_t * Lpk_ImplementFun( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * p )
|
|
{
|
|
extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
|
|
unsigned * pTruth;
|
|
Abc_Obj_t * pObjNew;
|
|
int i;
|
|
if ( p->fMark )
|
|
pMan->nMuxes++;
|
|
else
|
|
pMan->nDsds++;
|
|
// create the new node
|
|
pObjNew = Abc_NtkCreateNode( pNtk );
|
|
for ( i = 0; i < (int)p->nVars; i++ )
|
|
Abc_ObjAddFanin( pObjNew, Abc_ObjRegular((Abc_Obj_t *)Vec_PtrEntry(vLeaves, p->pFanins[i])) );
|
|
Abc_ObjSetLevel( pObjNew, Abc_ObjLevelNew(pObjNew) );
|
|
// assign the node's function
|
|
pTruth = Lpk_FunTruth(p, 0);
|
|
if ( p->nVars == 0 )
|
|
{
|
|
pObjNew->pData = Hop_NotCond( Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc), !(pTruth[0] & 1) );
|
|
return pObjNew;
|
|
}
|
|
if ( p->nVars == 1 )
|
|
{
|
|
pObjNew->pData = Hop_NotCond( Hop_ManPi((Hop_Man_t *)pNtk->pManFunc, 0), (pTruth[0] & 1) );
|
|
return pObjNew;
|
|
}
|
|
// create the logic function
|
|
pObjNew->pData = Kit_TruthToHop( (Hop_Man_t *)pNtk->pManFunc, pTruth, p->nVars, NULL );
|
|
return pObjNew;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Implements the function.]
|
|
|
|
Description [Returns the node implementing this function.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Abc_Obj_t * Lpk_Implement_rec( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * pFun )
|
|
{
|
|
Abc_Obj_t * pFanin, * pRes;
|
|
int i;
|
|
// prepare the leaves of the function
|
|
for ( i = 0; i < (int)pFun->nVars; i++ )
|
|
{
|
|
pFanin = (Abc_Obj_t *)Vec_PtrEntry( vLeaves, pFun->pFanins[i] );
|
|
if ( !Abc_ObjIsComplement(pFanin) )
|
|
Lpk_Implement_rec( pMan, pNtk, vLeaves, (Lpk_Fun_t *)pFanin );
|
|
pFanin = (Abc_Obj_t *)Vec_PtrEntry( vLeaves, pFun->pFanins[i] );
|
|
assert( Abc_ObjIsComplement(pFanin) );
|
|
}
|
|
// construct the function
|
|
pRes = Lpk_ImplementFun( pMan, pNtk, vLeaves, pFun );
|
|
// replace the function
|
|
Vec_PtrWriteEntry( vLeaves, pFun->Id, Abc_ObjNot(pRes) );
|
|
Lpk_FunFree( pFun );
|
|
return pRes;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Implements the function.]
|
|
|
|
Description [Returns the node implementing this function.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Abc_Obj_t * Lpk_Implement( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, int nLeavesOld )
|
|
{
|
|
Abc_Obj_t * pFanin, * pRes;
|
|
int i;
|
|
assert( nLeavesOld < Vec_PtrSize(vLeaves) );
|
|
// mark implemented nodes
|
|
Vec_PtrForEachEntryStop( Abc_Obj_t *, vLeaves, pFanin, i, nLeavesOld )
|
|
Vec_PtrWriteEntry( vLeaves, i, Abc_ObjNot(pFanin) );
|
|
// recursively construct starting from the first entry
|
|
pRes = Lpk_Implement_rec( pMan, pNtk, vLeaves, (Lpk_Fun_t *)Vec_PtrEntry( vLeaves, nLeavesOld ) );
|
|
Vec_PtrShrink( vLeaves, nLeavesOld );
|
|
return pRes;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Decomposes the function using recursive MUX decomposition.]
|
|
|
|
Description [Returns the ID of the top-most decomposition node
|
|
implementing this function, or 0 if there is no decomposition satisfying
|
|
the constraints on area and delay.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Lpk_Decompose_rec( Lpk_Man_t * pMan, Lpk_Fun_t * p )
|
|
{
|
|
Lpk_Res_t * pResMux, * pResDsd;
|
|
Lpk_Fun_t * p2;
|
|
abctime clk;
|
|
|
|
// is only called for non-trivial blocks
|
|
assert( p->nLutK >= 3 && p->nLutK <= 6 );
|
|
assert( p->nVars > p->nLutK );
|
|
// skip if area bound is exceeded
|
|
if ( Lpk_LutNumLuts(p->nVars, p->nLutK) > (int)p->nAreaLim )
|
|
return 0;
|
|
// skip if delay bound is exceeded
|
|
if ( Lpk_SuppDelay(p->uSupp, p->pDelays) > (int)p->nDelayLim )
|
|
return 0;
|
|
|
|
// compute supports if needed
|
|
if ( !p->fSupports )
|
|
Lpk_FunComputeCofSupps( p );
|
|
|
|
// check DSD decomposition
|
|
clk = Abc_Clock();
|
|
pResDsd = Lpk_DsdAnalize( pMan, p, pMan->pPars->nVarsShared );
|
|
pMan->timeEvalDsdAn += Abc_Clock() - clk;
|
|
if ( pResDsd && (pResDsd->nBSVars == (int)p->nLutK || pResDsd->nBSVars == (int)p->nLutK - 1) &&
|
|
pResDsd->AreaEst <= (int)p->nAreaLim && pResDsd->DelayEst <= (int)p->nDelayLim )
|
|
{
|
|
clk = Abc_Clock();
|
|
p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars );
|
|
pMan->timeEvalDsdSp += Abc_Clock() - clk;
|
|
assert( p2->nVars <= (int)p->nLutK );
|
|
if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
// check MUX decomposition
|
|
clk = Abc_Clock();
|
|
pResMux = Lpk_MuxAnalize( pMan, p );
|
|
pMan->timeEvalMuxAn += Abc_Clock() - clk;
|
|
// pResMux = NULL;
|
|
assert( !pResMux || (pResMux->DelayEst <= (int)p->nDelayLim && pResMux->AreaEst <= (int)p->nAreaLim) );
|
|
// accept MUX decomposition if it is "good"
|
|
if ( pResMux && pResMux->nSuppSizeS <= (int)p->nLutK && pResMux->nSuppSizeL <= (int)p->nLutK )
|
|
pResDsd = NULL;
|
|
else if ( pResMux && pResDsd )
|
|
{
|
|
// compare two decompositions
|
|
if ( pResMux->AreaEst < pResDsd->AreaEst ||
|
|
(pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL < pResDsd->nSuppSizeL) ||
|
|
(pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL == pResDsd->nSuppSizeL && pResMux->DelayEst < pResDsd->DelayEst) )
|
|
pResDsd = NULL;
|
|
else
|
|
pResMux = NULL;
|
|
}
|
|
assert( pResMux == NULL || pResDsd == NULL );
|
|
if ( pResMux )
|
|
{
|
|
clk = Abc_Clock();
|
|
p2 = Lpk_MuxSplit( pMan, p, pResMux->Variable, pResMux->Polarity );
|
|
pMan->timeEvalMuxSp += Abc_Clock() - clk;
|
|
if ( p2->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p2 ) )
|
|
return 0;
|
|
if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
if ( pResDsd )
|
|
{
|
|
clk = Abc_Clock();
|
|
p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars );
|
|
pMan->timeEvalDsdSp += Abc_Clock() - clk;
|
|
assert( p2->nVars <= (int)p->nLutK );
|
|
if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Removes decomposed nodes from the array of fanins.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Lpk_DecomposeClean( Vec_Ptr_t * vLeaves, int nLeavesOld )
|
|
{
|
|
Lpk_Fun_t * pFunc;
|
|
int i;
|
|
Vec_PtrForEachEntryStart( Lpk_Fun_t *, vLeaves, pFunc, i, nLeavesOld )
|
|
Lpk_FunFree( pFunc );
|
|
Vec_PtrShrink( vLeaves, nLeavesOld );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Decomposes the function using recursive MUX decomposition.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Abc_Obj_t * Lpk_Decompose( Lpk_Man_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, unsigned * puSupps, int nLutK, int AreaLim, int DelayLim )
|
|
{
|
|
Lpk_Fun_t * pFun;
|
|
Abc_Obj_t * pObjNew = NULL;
|
|
int nLeaves = Vec_PtrSize( vLeaves );
|
|
pFun = Lpk_FunCreate( pNtk, vLeaves, pTruth, nLutK, AreaLim, DelayLim );
|
|
if ( puSupps[0] || puSupps[1] )
|
|
{
|
|
/*
|
|
int i;
|
|
Lpk_FunComputeCofSupps( pFun );
|
|
for ( i = 0; i < nLeaves; i++ )
|
|
{
|
|
assert( pFun->puSupps[2*i+0] == puSupps[2*i+0] );
|
|
assert( pFun->puSupps[2*i+1] == puSupps[2*i+1] );
|
|
}
|
|
*/
|
|
memcpy( pFun->puSupps, puSupps, sizeof(unsigned) * 2 * nLeaves );
|
|
pFun->fSupports = 1;
|
|
}
|
|
Lpk_FunSuppMinimize( pFun );
|
|
if ( pFun->nVars <= pFun->nLutK )
|
|
pObjNew = Lpk_ImplementFun( p, pNtk, vLeaves, pFun );
|
|
else if ( Lpk_Decompose_rec(p, pFun) )
|
|
pObjNew = Lpk_Implement( p, pNtk, vLeaves, nLeaves );
|
|
Lpk_DecomposeClean( vLeaves, nLeaves );
|
|
return pObjNew;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|