mirror of https://github.com/YosysHQ/abc.git
Improvements to LUT cascade mapping.
This commit is contained in:
parent
8912d3aabe
commit
b7bf6c20b6
|
|
@ -8905,6 +8905,7 @@ usage:
|
|||
int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
extern Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose );
|
||||
extern Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose );
|
||||
Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes;
|
||||
int c, nLutSize = 6, nLuts = 8, nRails = 1, nIters = 1, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
|
|
@ -8987,7 +8988,7 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
Abc_NtkCiNum(pNtk), nRails, nLuts, nLutSize, nLutSize + (nLutSize - nRails) * (nLuts - 1) );
|
||||
return 1;
|
||||
}
|
||||
pNtkRes = Abc_NtkLutCascade( pNtk, nLutSize, nLuts, nRails, nIters, fVerbose );
|
||||
pNtkRes = Abc_NtkLutCascade2( pNtk, nLutSize, nLuts, nRails, nIters, fVerbose );
|
||||
if ( pNtkRes == NULL )
|
||||
{
|
||||
Abc_Print( -1, "LUT cascade mapping failed.\n" );
|
||||
|
|
@ -8997,8 +8998,8 @@ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
return 0;
|
||||
|
||||
usage:
|
||||
Abc_Print( -2, "usage: lutcas [-KNRI <num>] [-vh]\n" );
|
||||
Abc_Print( -2, "\t derives single-rail LUT cascade for the primary output function\n" );
|
||||
Abc_Print( -2, "usage: lutcasdec [-KNRI <num>] [-vh]\n" );
|
||||
Abc_Print( -2, "\t decomposes the primary output functions into LUT cascades\n" );
|
||||
Abc_Print( -2, "\t-K <num> : the number of LUT inputs [default = %d]\n", nLutSize );
|
||||
Abc_Print( -2, "\t-N <num> : the number of LUTs in the cascade [default = %d]\n", nLuts );
|
||||
Abc_Print( -2, "\t-R <num> : the number of direct connections (rails) [default = %d]\n", nRails );
|
||||
|
|
|
|||
|
|
@ -255,17 +255,29 @@ Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nR
|
|||
{
|
||||
extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk );
|
||||
extern Mini_Aig_t * Gia_ManToMiniAig( Gia_Man_t * pGia );
|
||||
extern word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose );
|
||||
extern word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose );
|
||||
Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk );
|
||||
Mini_Aig_t * pM = Gia_ManToMiniAig( pGia );
|
||||
word * pLuts = Abc_LutCascade( pM, nLutSize, nLuts, nRails, nIters, fVerbose );
|
||||
//word * pLuts = Abc_LutCascadeTest( pM, nLutSize, 0 );
|
||||
//word * pLuts = Abc_LutCascade( pM, nLutSize, nLuts, nRails, nIters, fVerbose );
|
||||
word * pLuts = Abc_LutCascadeTest( pM, nLutSize, 0 );
|
||||
Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, pNtk, nLutSize, fVerbose ) : NULL;
|
||||
ABC_FREE( pLuts );
|
||||
Mini_AigStop( pM );
|
||||
Gia_ManStop( pGia );
|
||||
return pNew;
|
||||
}
|
||||
Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose )
|
||||
{
|
||||
extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk );
|
||||
extern word * Abc_LutCascade2( word * p, int nVars, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose );
|
||||
Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk );
|
||||
word * pTruth = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, 0) );
|
||||
word * pLuts = Abc_LutCascade2( pTruth, Gia_ManCiNum(pGia), nLutSize, nLuts, nRails, nIters, fVerbose );
|
||||
Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, pNtk, nLutSize, fVerbose ) : NULL;
|
||||
ABC_FREE( pLuts );
|
||||
Gia_ManStop( pGia );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@
|
|||
#include "misc/extra/extra.h"
|
||||
#include "misc/util/utilTruth.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <intrin.h>
|
||||
# define __builtin_popcount __popcnt
|
||||
#endif
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -43,6 +48,8 @@ struct Abc_BSEval_t_
|
|||
Vec_Int_t * vTable; // hash table
|
||||
Vec_Int_t * vUsed; // used entries
|
||||
Vec_Wrd_t * vStore; // cofactors
|
||||
Vec_Wec_t * vSets; // sets
|
||||
Vec_Wrd_t * vCofs; // cofactors
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -334,14 +341,13 @@ int Abc_TtCheck1Shared( word * pPat, int nVars, int nFVars, int nMyu )
|
|||
if ( fVerbose ) printf( "Not found\n" );
|
||||
return nRails;
|
||||
}
|
||||
int Abc_TtGetCMPat( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed )
|
||||
int Abc_TtGetCMInt( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed, word * pPat )
|
||||
{
|
||||
word pPat[1024];
|
||||
int nMintsBS = 1 << (nVars - nFVars);
|
||||
int nWordsBS = Abc_TtWordNum(nVars - nFVars);
|
||||
assert( nMintsBS * nWordsBS <= 1024 );
|
||||
memset( pPat, 0, 8 * nMintsBS * nWordsBS );
|
||||
int nMyu = 0, nRails;
|
||||
int nMyu = 0;
|
||||
if ( nFVars == 1 )
|
||||
nMyu = Abc_TtGetCM1Pat( p, nVars, pPat );
|
||||
else if ( nFVars == 2 )
|
||||
|
|
@ -355,6 +361,13 @@ int Abc_TtGetCMPat( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_In
|
|||
else if ( nFVars == 6 )
|
||||
nMyu = Abc_TtGetCM6Pat( p, nVars, nFVars, vTable, vStore, vUsed, pPat );
|
||||
else assert( 0 );
|
||||
return nMyu;
|
||||
}
|
||||
|
||||
int Abc_TtGetCMPat( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed )
|
||||
{
|
||||
word pPat[1024];
|
||||
int nRails, nMyu = Abc_TtGetCMInt( p, nVars, nFVars, vCounts, vTable, vStore, vUsed, pPat );
|
||||
if ( nMyu <= 2 )
|
||||
nRails = 1;
|
||||
else
|
||||
|
|
@ -553,6 +566,8 @@ void Abc_BSEvalFree( Abc_BSEval_t * p )
|
|||
Vec_IntFree( p->vTable );
|
||||
Vec_IntFree( p->vUsed );
|
||||
Vec_WrdFree( p->vStore );
|
||||
Vec_WecFreeP( &p->vSets );
|
||||
Vec_WrdFreeP( &p->vCofs );
|
||||
ABC_FREE( p );
|
||||
}
|
||||
void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose )
|
||||
|
|
@ -588,7 +603,7 @@ int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int n
|
|||
if ( CostBest > CostThis ) {
|
||||
CostBest = CostThis;
|
||||
if ( pBest ) Abc_TtCopy( pBest, pIn, Abc_Truth6WordNum(nVars), 0 );
|
||||
if ( pPermBest ) memcpy( pPermBest, Pla2Var, sizeof(int)*nPermVars );
|
||||
if ( pPermBest ) memcpy( pPermBest, Pla2Var, sizeof(int)*nVars );
|
||||
}
|
||||
if ( fVerbose )
|
||||
{
|
||||
|
|
@ -746,6 +761,235 @@ void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryA
|
|||
Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Finds shared variables.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline Vec_Wrd_t * Vec_WrdStartTruthTables6( int nVars )
|
||||
{
|
||||
Vec_Wrd_t * p;
|
||||
word Masks[6] = {
|
||||
ABC_CONST(0xAAAAAAAAAAAAAAAA),
|
||||
ABC_CONST(0xCCCCCCCCCCCCCCCC),
|
||||
ABC_CONST(0xF0F0F0F0F0F0F0F0),
|
||||
ABC_CONST(0xFF00FF00FF00FF00),
|
||||
ABC_CONST(0xFFFF0000FFFF0000),
|
||||
ABC_CONST(0xFFFFFFFF00000000)
|
||||
};
|
||||
int i, k, nWords = nVars <= 6 ? 1 : (1 << (nVars - 6));
|
||||
p = Vec_WrdStart( nWords * nVars );
|
||||
for ( i = 0; i < nVars; i++ )
|
||||
{
|
||||
word * pTruth = p->pArray + nWords * i;
|
||||
if ( i < 6 )
|
||||
{
|
||||
for ( k = 0; k < nWords; k++ )
|
||||
pTruth[k] = Masks[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( k = 0; k < nWords; k++ )
|
||||
if ( k & (1 << (i-6)) )
|
||||
pTruth[k] = ~(word)0;
|
||||
else
|
||||
pTruth[k] = 0;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void Abc_BSEvalCreateCofs( int iSet, int nVars, Vec_Wrd_t * vCofs, Vec_Wrd_t * vElems )
|
||||
{
|
||||
int nWords = Abc_Truth6WordNum(nVars);
|
||||
int m, i, nUsed = 0, pUsed[32], Start = Vec_WrdSize(vCofs);
|
||||
for ( i = 0; i < nVars; i++ )
|
||||
if ( (iSet >> i) & 1 )
|
||||
pUsed[nUsed++] = i;
|
||||
Vec_WrdFillExtra( vCofs, Start + nWords*(1 << nUsed), ~(word)0 );
|
||||
for ( m = 0; m < (1 << nUsed); m++ )
|
||||
{
|
||||
word * pCof = Vec_WrdEntryP(vCofs, Start + m*nWords);
|
||||
for ( i = 0; i < nUsed; i++ )
|
||||
Abc_TtAndSharp( pCof, pCof, Vec_WrdEntryP(vElems, nWords*pUsed[i]), nWords, ((m >> i) & 1) == 0 );
|
||||
}
|
||||
}
|
||||
Vec_Wrd_t * Abc_BSEvalCreateCofactorSets( int nVars, Vec_Wec_t ** pvSets )
|
||||
{
|
||||
Vec_Wrd_t * vElems = Vec_WrdStartTruthTables6( nVars );
|
||||
Vec_Wrd_t * vCofs = Vec_WrdAlloc( 1000 );
|
||||
Vec_Wec_t * vSets = Vec_WecStart( nVars+1 );
|
||||
int m, nMints = 1 << nVars;
|
||||
for ( m = 0; m < nMints; m++ )
|
||||
{
|
||||
int nOnes = __builtin_popcount(m);
|
||||
Vec_WecPushTwo( vSets, nOnes, m, Vec_WrdSize(vCofs) );
|
||||
Abc_BSEvalCreateCofs( m, nVars, vCofs, vElems );
|
||||
}
|
||||
Vec_WrdFree( vElems );
|
||||
*pvSets = vSets;
|
||||
return vCofs;
|
||||
}
|
||||
|
||||
static inline int Abc_BSEvalCountUnique( word * pISets, int nISets, int nBSWords, word * pCof )
|
||||
{
|
||||
int i, Count = 0;
|
||||
for ( i = 0; i < nISets; i++ )
|
||||
Count += Abc_TtIntersect(pISets + i*nBSWords, pCof, nBSWords, 0);
|
||||
return Count;
|
||||
}
|
||||
static inline int Abc_BSEvalCountUniqueMax( word * pISets, int nISets, int nBSWords, word * pCofs, int nOnes, int nISetsMaxHave )
|
||||
{
|
||||
int m, nMints = (1 << nOnes), CountMax = 0;
|
||||
assert( nOnes > 0 && nOnes < 5 );
|
||||
for ( m = 0; m < nMints; m++ )
|
||||
{
|
||||
int Count = Abc_BSEvalCountUnique( pISets, nISets, nBSWords, pCofs + m * nBSWords );
|
||||
if ( Count > nISetsMaxHave )
|
||||
return 0;
|
||||
CountMax = Abc_MaxInt( CountMax, Count );
|
||||
}
|
||||
return CountMax;
|
||||
}
|
||||
int Abc_BSEvalFindShared( int nVars, word * pISets, int nISets, int nBSWords, Vec_Wec_t * vSets, Vec_Wrd_t * vCofs, int nSharedMax )
|
||||
{
|
||||
Vec_Int_t * vLevel; int i, k, iSet, iStart, nMinMyu = nISets, nMinRails = Abc_Base2Log(nISets), MinShared = 0, MinSet = -1;
|
||||
Vec_WecForEachLevelStartStop( vSets, vLevel, i, 1, nSharedMax+1 ) {
|
||||
Vec_IntForEachEntryDouble( vLevel, iSet, iStart, k ) {
|
||||
int Count = Abc_BSEvalCountUniqueMax( pISets, nISets, nBSWords, Vec_WrdEntryP(vCofs, iStart), i, 1 << (nMinRails-1) );
|
||||
if ( Count == 0 )
|
||||
continue;
|
||||
int CountRails = Abc_Base2Log(Count);
|
||||
if ( nMinRails > CountRails || (nMinRails == CountRails && nMinMyu > Count && MinShared == i) ) {
|
||||
nMinRails = CountRails;
|
||||
nMinMyu = Count;
|
||||
MinShared = i;
|
||||
MinSet = iSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (MinSet << 16) | nMinMyu;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_SharedEvalBest( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars, int nFVars, int MyuMin, int nRails, int fVerbose, int * pSetShared, word * pPat )
|
||||
{
|
||||
int nBSWords = Abc_Truth6WordNum( nVars - nFVars ), CVarMask = Abc_InfoMask(nCVars) << (nVars - nFVars - nCVars);
|
||||
int MyuCur, Myu = Abc_TtGetCMInt( pTruth, nVars, nFVars, p->vCounts, p->vTable, p->vStore, p->vUsed, pPat );
|
||||
int nRailsCur = Abc_Base2Log( Myu ); Vec_Int_t * vLevel;
|
||||
assert( Myu == MyuMin && nRailsCur > nRails );
|
||||
int i, k, iSet, iStart, nSharedMax = nVars - nFVars - 1, nRailsMin = 100;
|
||||
Vec_WecForEachLevelStartStop( p->vSets, vLevel, i, 1, nSharedMax+1 ) {
|
||||
Vec_IntForEachEntryDouble( vLevel, iSet, iStart, k ) {
|
||||
if ( iSet & CVarMask )
|
||||
continue;
|
||||
MyuCur = Abc_BSEvalCountUniqueMax( pPat, Myu, nBSWords, Vec_WrdEntryP(p->vCofs, iStart), i, 1 << nRails );
|
||||
if ( MyuCur == 0 )
|
||||
continue;
|
||||
nRailsCur = Abc_Base2Log(MyuCur);
|
||||
if ( nRailsCur > nRails )
|
||||
continue;
|
||||
if ( nRailsMin > nRailsCur ) {
|
||||
nRailsMin = nRailsCur;
|
||||
*pSetShared = iSet;
|
||||
}
|
||||
}
|
||||
if ( nRailsMin <= nRails )
|
||||
break;
|
||||
}
|
||||
return nRailsMin;
|
||||
}
|
||||
int Abc_DeriveLutDec( word * pTruth, int nVars, int nCVars, int nFVars, int * pPerm, int nRails, int Shared, int fVerbose, Vec_Wrd_t * vRes )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Decomposing truth table into a K-LUT cascade with R rails.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
word * Abc_LutCascade2( word * pFunc, int nVars, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose )
|
||||
{
|
||||
Abc_BSEval_t * p = Abc_BSEvalAlloc();
|
||||
Vec_Wrd_t * vRes = Vec_WrdStart( 1 ); word * pRes = NULL;
|
||||
word * pTruth = ABC_ALLOC( word, Abc_TtWordNum(nVars) );
|
||||
word * pBest = ABC_ALLOC( word, Abc_TtWordNum(nVars) );
|
||||
Abc_TtCopy( pTruth, pFunc, Abc_TtWordNum(nVars), 0 );
|
||||
int i, nVarsCur = nVars, nOutVars = 0; word pPat[1024];
|
||||
while ( nVarsCur > nLutSize )
|
||||
{
|
||||
int pPerm[32] = {0};
|
||||
if ( p->nVars != nVarsCur || p->nBVars != nLutSize ) {
|
||||
Vec_IntFreeP( &p->vPairs );
|
||||
if ( p->nBVars != nLutSize ) {
|
||||
Vec_WecFreeP( &p->vSets );
|
||||
Vec_WrdFreeP( &p->vCofs );
|
||||
p->vCofs = Abc_BSEvalCreateCofactorSets( nLutSize, &p->vSets );
|
||||
}
|
||||
p->vPairs = Abc_GenChasePairs( nVarsCur, nLutSize );
|
||||
p->nVars = nVarsCur;
|
||||
p->nBVars = nLutSize;
|
||||
}
|
||||
int MyuMin = Abc_BSEvalBest( p, pTruth, pBest, nVarsCur, nOutVars, nVarsCur-nLutSize, fVerbose, pPerm, 0 );
|
||||
int Shared = 0, nRailsMin = Abc_Base2Log( MyuMin );
|
||||
if ( nRailsMin > nRails )
|
||||
nRailsMin = Abc_SharedEvalBest( p, pBest, nVarsCur, nOutVars, nVarsCur-nLutSize, MyuMin, nRails, fVerbose, &Shared, pPat );
|
||||
if ( nRailsMin > nRails ) {
|
||||
Vec_WrdFreeP( &vRes );
|
||||
break;
|
||||
}
|
||||
// update nVarsCur, pTruth, nOutVars, and vRes
|
||||
nVarsCur = Abc_DeriveLutDec( pBest, nVarsCur, nOutVars, nVarsCur-nLutSize, pPerm, nRailsMin, Shared, fVerbose, vRes );
|
||||
Abc_TtCopy( pTruth, pBest, Abc_TtWordNum(nVarsCur), 0 );
|
||||
nOutVars = nRailsMin;
|
||||
}
|
||||
if ( vRes ) // decomposition succeeded
|
||||
{
|
||||
// create the last node
|
||||
assert( nVarsCur <= nLutSize );
|
||||
Vec_WrdAddToEntry( vRes, 0, 1 );
|
||||
Vec_WrdPush( vRes, nVarsCur+4 );
|
||||
Vec_WrdPush( vRes, nVarsCur );
|
||||
for ( i = 0; i < nVarsCur; i++ )
|
||||
Vec_WrdPush( vRes, i );
|
||||
Vec_WrdPush( vRes, 0 );
|
||||
Vec_WrdPush( vRes, pTruth[0] );
|
||||
// extract the output array
|
||||
pRes = Vec_WrdReleaseArray( vRes );
|
||||
Vec_WrdFree( vRes );
|
||||
}
|
||||
// cleanup and return
|
||||
Abc_BSEvalFree(p);
|
||||
ABC_FREE( pTruth );
|
||||
ABC_FREE( pBest );
|
||||
return pRes;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
Loading…
Reference in New Issue