mirror of https://github.com/YosysHQ/abc.git
Experiments with LUT mapping for small functions.
This commit is contained in:
parent
03bb1e49bf
commit
5f8d4e72d1
|
|
@ -158,7 +158,7 @@ Gia_Man_t * Vec_WrdReadTest( char * pFileName )
|
|||
Vec_WecForEachLevel( vRes, vPart, i )
|
||||
{
|
||||
assert( Vec_IntSize(vPart) <= nBitsI );
|
||||
pPart = Gia_TryPermOptCare( pFuncs + i * nBitsO * nWords, nBitsI, nBitsO, nWords, 10, 0 );
|
||||
pPart = Gia_TryPermOptCare( pFuncs + i * nBitsO * nWords, nBitsI, nBitsO, nWords, 20, 0 );
|
||||
Gia_ManFillValue( pPart );
|
||||
Gia_ManConst0(pPart)->Value = 0;
|
||||
Gia_ManForEachCi( pPart, pObj, k )
|
||||
|
|
|
|||
|
|
@ -504,6 +504,209 @@ word * Abc_TtMinArray( word * p, int nOuts, int nVars, int * pnNodes, int fVerbo
|
|||
return pResult;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline word Abc_TtSimple6Min_rec( Gia_Man_t * p, word uF, word uC, int nVars, Vec_Wrd_t * vNodes, int * piLit, int * pPerm )
|
||||
{
|
||||
word uF0, uF1, uC0, uC1, uRes0, uRes1, uRes2; int i, Var, iLit0, iLit1;
|
||||
word uFC = uF & uC;
|
||||
word uRC = ~uF & uC;
|
||||
assert( nVars <= 6 );
|
||||
*piLit = 0;
|
||||
if ( !uFC )
|
||||
{
|
||||
*piLit = 0;
|
||||
return 0;
|
||||
}
|
||||
if ( !uRC )
|
||||
{
|
||||
*piLit = 1;
|
||||
return ~(word)0;
|
||||
}
|
||||
assert( nVars > 0 );
|
||||
if ( 1 && vNodes )
|
||||
{
|
||||
int iLit;
|
||||
int s = 0;
|
||||
Vec_WrdForEachEntryDouble( vNodes, uRes2, iLit, i )
|
||||
if ( !((uF ^ uRes2) & uC) )
|
||||
{
|
||||
*piLit = (unsigned)iLit;
|
||||
return uRes2;
|
||||
}
|
||||
else if ( !((uF ^ ~uRes2) & uC) )
|
||||
{
|
||||
*piLit = Abc_LitNot( (unsigned)iLit );
|
||||
return ~uRes2;
|
||||
}
|
||||
}
|
||||
for ( Var = nVars-1; Var >= 0; Var-- )
|
||||
if ( Abc_Tt6HasVar( uF, Var ) )
|
||||
break;
|
||||
else
|
||||
uC = Abc_Tt6Cofactor0(uC, Var) | Abc_Tt6Cofactor1(uC, Var);
|
||||
assert( Var >= 0 );
|
||||
uF0 = Abc_Tt6Cofactor0( uF, Var );
|
||||
uF1 = Abc_Tt6Cofactor1( uF, Var );
|
||||
uC0 = Abc_Tt6Cofactor0( uC, Var );
|
||||
uC1 = Abc_Tt6Cofactor1( uC, Var );
|
||||
uRes0 = Abc_TtSimple6Min_rec( p, uF0, uC0, Var, vNodes, &iLit0, pPerm );
|
||||
uRes1 = Abc_TtSimple6Min_rec( p, uF1, uC1, Var, vNodes, &iLit1, pPerm );
|
||||
if ( uRes0 == uRes1 )
|
||||
{
|
||||
*piLit = iLit0;
|
||||
return uRes0;
|
||||
}
|
||||
uRes2 = (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]);
|
||||
Var = pPerm ? pPerm[Var] : Var;
|
||||
//if ( !(uRes0 & ~uRes1 & uC1) )
|
||||
if ( !(uRes0 & ~uRes1) )
|
||||
*piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 );
|
||||
//else if ( !(uRes1 & ~uRes0 & uC0) )
|
||||
else if ( !(uRes1 & ~uRes0) )
|
||||
*piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 );
|
||||
else
|
||||
*piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 );
|
||||
assert( !(uFC & ~uRes2) );
|
||||
assert( !(uRes2 & uRC) );
|
||||
if ( vNodes )
|
||||
Vec_WrdPushTwo( vNodes, uRes2, (word)*piLit );
|
||||
return uRes2;
|
||||
}
|
||||
word * Abc_TtSimpleMin_rec( Gia_Man_t * p, word * pF, word * pC, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2, int * piLit, int * pPerm )
|
||||
{
|
||||
int i, Entry, Var, iLit0, iLit1, nWords = Abc_TtWordNum(nVars);
|
||||
word * pRes0, * pRes1, * pRes2 = Vec_WrdFetch( vMemory, nWords );
|
||||
*piLit = 0;
|
||||
if ( nVars <= 6 )
|
||||
{
|
||||
pRes2[0] = Abc_TtSimple6Min_rec( p, pF[0], pC[0], nVars, vNodes, piLit, pPerm );
|
||||
return pRes2;
|
||||
}
|
||||
if ( !Abc_TtIntersect(pF, pC, nWords, 0) )
|
||||
{
|
||||
*piLit = 0;
|
||||
Abc_TtClear( pRes2, nWords );
|
||||
return pRes2;
|
||||
}
|
||||
if ( !Abc_TtIntersect(pF, pC, nWords, 1) )
|
||||
{
|
||||
*piLit = 1;
|
||||
Abc_TtFill( pRes2, nWords );
|
||||
return pRes2;
|
||||
}
|
||||
nWords >>= 1;
|
||||
if ( !Abc_TtHasVar( pF, nVars, nVars-1 ) )
|
||||
{
|
||||
word * pCn = Vec_WrdFetch( vMemory, nWords );
|
||||
Abc_TtOr( pCn, pC, pC + nWords, nWords );
|
||||
pRes0 = Abc_TtSimpleMin_rec( p, pF, pCn, nVars-1, vMemory, vNodes, vNodes2, piLit, pPerm );
|
||||
Abc_TtCopy( pRes2, pRes0, nWords, 0 );
|
||||
Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 );
|
||||
return pRes2;
|
||||
}
|
||||
if ( 1 && vNodes2 )
|
||||
{
|
||||
Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); int iLit;
|
||||
Vec_IntForEachEntryDouble( vLayer, Entry, iLit, i )
|
||||
{
|
||||
word * pTemp = Vec_WrdEntryP( vMemory, Entry );
|
||||
if ( Abc_TtEqualCare(pTemp, pF, pC, 0, 2*nWords) )
|
||||
{
|
||||
*piLit = iLit;
|
||||
return pTemp;
|
||||
}
|
||||
else if ( Abc_TtEqualCare(pTemp, pF, pC, 1, 2*nWords) )
|
||||
{
|
||||
*piLit = Abc_LitNot(iLit);
|
||||
Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 );
|
||||
return pRes2;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert( nVars > 6 );
|
||||
pRes0 = Abc_TtSimpleMin_rec( p, pF, pC, nVars-1, vMemory, vNodes, vNodes2, &iLit0, pPerm );
|
||||
pRes1 = Abc_TtSimpleMin_rec( p, pF + nWords, pC + nWords, nVars-1, vMemory, vNodes, vNodes2, &iLit1, pPerm );
|
||||
if ( Abc_TtEqual(pRes0, pRes1, nWords) )
|
||||
{
|
||||
*piLit = iLit0;
|
||||
Abc_TtCopy( pRes2, pRes0, nWords, 0 );
|
||||
Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 );
|
||||
return pRes2;
|
||||
}
|
||||
Abc_TtCopy( pRes2, pRes0, nWords, 0 );
|
||||
Abc_TtCopy( pRes2 + nWords, pRes1, nWords, 0 );
|
||||
Var = pPerm ? pPerm[nVars-1] : nVars-1;
|
||||
//if ( !Abc_TtIntersectCare(pRes1, pRes0, pC + nWords, nWords, 1) )
|
||||
if ( !Abc_TtIntersect(pRes1, pRes0, nWords, 1) )
|
||||
*piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 );
|
||||
//else if ( !Abc_TtIntersectCare(pRes0, pRes1, pC, nWords, 1) )
|
||||
else if ( !Abc_TtIntersect(pRes0, pRes1, nWords, 1) )
|
||||
*piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 );
|
||||
else
|
||||
*piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 );
|
||||
assert( Abc_TtEqualCare(pRes2, pF, pC, 0, 2*nWords) );
|
||||
if ( vNodes2 )
|
||||
{
|
||||
Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars );
|
||||
Vec_IntPushTwo( vLayer, pRes2 - Vec_WrdArray(vMemory), *piLit );
|
||||
}
|
||||
return pRes2;
|
||||
}
|
||||
Gia_Man_t * Abc_TtSimpleMinArrayNew( word * p, int nVars, int nOuts, int * pnNodes, int fVerbose, int * pIPerm )
|
||||
{
|
||||
Gia_Man_t * pNew, * pTemp;
|
||||
int o, i, iLit, nWords = Abc_TtWordNum(nVars);
|
||||
word * pF = ABC_ALLOC( word, nWords );
|
||||
word * pR = ABC_ALLOC( word, nWords );
|
||||
Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 );
|
||||
Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 );
|
||||
Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 );
|
||||
Vec_WrdGrow( vMemory, 1 << 20 );
|
||||
pNew = Gia_ManStart( 1000 );
|
||||
pNew->pName = Abc_UtilStrsav( "muxes" );
|
||||
for ( i = 0; i < nVars; i++ )
|
||||
Gia_ManAppendCi(pNew);
|
||||
Gia_ManHashAlloc( pNew );
|
||||
|
||||
for ( o = 0; o < nOuts; o++ )
|
||||
{
|
||||
word * pCare = p + nOuts*nWords;
|
||||
word * pTruth = p + o*nWords;
|
||||
for ( i = nVars; i < 6; i++ )
|
||||
assert( !Abc_Tt6HasVar(pTruth[0], i) && !Abc_Tt6HasVar(pCare[0], i) );
|
||||
Abc_TtSimpleMin_rec( pNew, pTruth, pCare, nVars, vMemory, vNodes, vNodes2, &iLit, pIPerm );
|
||||
Gia_ManAppendCo( pNew, iLit );
|
||||
}
|
||||
if ( fVerbose )
|
||||
printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ",
|
||||
Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) );
|
||||
//printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords );
|
||||
if ( pnNodes )
|
||||
*pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2);
|
||||
Vec_WrdFree( vMemory );
|
||||
Vec_WrdFree( vNodes );
|
||||
Vec_WecFree( vNodes2 );
|
||||
ABC_FREE( pF );
|
||||
ABC_FREE( pR );
|
||||
|
||||
Gia_ManHashStop( pNew );
|
||||
pNew = Gia_ManCleanup( pTemp = pNew );
|
||||
Gia_ManStop( pTemp );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -906,7 +1109,7 @@ Gia_Man_t * Gia_TryPermOptCare( word * pTruths, int nIns, int nOuts, int nWords,
|
|||
abctime clk = Abc_Clock();
|
||||
Gia_Man_t * pNew;
|
||||
word * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 );
|
||||
word * pTruthBest = ABC_ALLOC( word, nOuts*nWords );
|
||||
word * pTruthBest = ABC_FALLOC( word, (nOuts+1)*nWords );
|
||||
int pIPermBest[TREE_MAX_VARS] = {0};
|
||||
int pIPerm[TREE_MAX_VARS] = {0};
|
||||
int r, rBest = -1, nNodes = -1, nNodesBest = ABC_INFINITY;
|
||||
|
|
@ -932,7 +1135,8 @@ Gia_Man_t * Gia_TryPermOptCare( word * pTruths, int nIns, int nOuts, int nWords,
|
|||
ABC_FREE( pTruthDup );
|
||||
if ( fVerbose )
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
||||
pNew = Gia_ManCreateMuxGia( pTruthBest, nIns, nOuts, nWords, pIPermBest );
|
||||
//pNew = Gia_ManCreateMuxGia( pTruthBest, nIns, nOuts, nWords, pIPermBest );
|
||||
pNew = Abc_TtSimpleMinArrayNew( pTruthBest, nIns, nOuts, NULL, 0, pIPermBest );
|
||||
//Gia_ManDumpMuxGia( pTruthBest, nIns, nOuts, nWords, pIPermBest, "tt_end.aig" );
|
||||
ABC_FREE( pTruthBest );
|
||||
return pNew;
|
||||
|
|
@ -1033,7 +1237,8 @@ Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords,
|
|||
{
|
||||
int nNodesAll = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose );
|
||||
Abc_TtPermute( pTruthDup + nOuts*nWords, pIPerm, nIns );
|
||||
pTemp = Abc_TtGiaMinArrayNew( pTruthDup, nIns, nOuts, NULL, 0, pIPerm );
|
||||
//pTemp = Abc_TtGiaMinArrayNew( pTruthDup, nIns, nOuts, NULL, 0, pIPerm );
|
||||
pTemp = Abc_TtSimpleMinArrayNew( pTruthDup, nIns, nOuts, NULL, 0, pIPerm );
|
||||
nNodes2 = Gia_ManAndNum(pTemp);
|
||||
if ( nNodesBest > nNodes2 )
|
||||
{
|
||||
|
|
@ -1046,6 +1251,14 @@ Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords,
|
|||
pTemp = NULL;
|
||||
}
|
||||
Gia_ManStopP( &pTemp );
|
||||
/*
|
||||
for ( i = 0; i <= nOuts; i++ )
|
||||
{
|
||||
Abc_TtUnpermute( pTruthDup + i*nWords, pIPerm, nIns );
|
||||
if ( !Abc_TtEqual(pTruthDup + i*nWords, pTruths + i*nWords, nWords) )
|
||||
printf( "Verification failed for output %d (out of %d).\n", i, nOuts );
|
||||
}
|
||||
*/
|
||||
Abc_TtCopy( pTruthDup, pTruths, (nOuts+1)*nWords, 0 );
|
||||
if ( fVerbose )
|
||||
printf( "Permuted = %5d. AIG = %5d.\n", nNodesAll, nNodes2 );
|
||||
|
|
|
|||
|
|
@ -41464,9 +41464,9 @@ int Abc_CommandAbc9LNetOpt( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
extern Gia_Man_t * Gia_ManPerformLNetOptNew( Gia_Man_t * p, char * pFileName, int nIns, int nOuts, int Thresh, int nRounds, int fVerbose );
|
||||
Gia_Man_t * pTemp;
|
||||
char * pFileName = NULL;
|
||||
int c, fTryNew = 1, nIns = 6, nOuts = 2, Limit = 0, nRounds = 100, fVerbose = 0;
|
||||
int c, nIns = 6, nOuts = 2, Limit = 0, nRounds = 20, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "IORXxvh" ) ) != EOF )
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "IORXvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
|
|
@ -41506,9 +41506,6 @@ int Abc_CommandAbc9LNetOpt( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
nRounds = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
break;
|
||||
case 'x':
|
||||
fTryNew ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
|
|
@ -41542,13 +41539,12 @@ int Abc_CommandAbc9LNetOpt( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
return 0;
|
||||
|
||||
usage:
|
||||
Abc_Print( -2, "usage: &lnetopt [-IORX num] [-xvh] <file>\n" );
|
||||
Abc_Print( -2, "usage: &lnetopt [-IORX num] [-vh] <file>\n" );
|
||||
Abc_Print( -2, "\t performs specialized AIG optimization\n" );
|
||||
Abc_Print( -2, "\t-I num : the input support size [default = %d]\n", nIns );
|
||||
Abc_Print( -2, "\t-O num : the output group size [default = %d]\n", nOuts );
|
||||
Abc_Print( -2, "\t-R num : patterns are cares starting this value [default = %d]\n", Limit );
|
||||
Abc_Print( -2, "\t-X num : the number of optimization rounds [default = %d]\n", nRounds );
|
||||
Abc_Print( -2, "\t-x : toggles using another computation [default = %s]\n", fTryNew? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : prints the command usage\n");
|
||||
Abc_Print( -2, "\t<file> : file name with simulation information\n");
|
||||
|
|
|
|||
|
|
@ -399,7 +399,23 @@ static inline int Abc_TtIntersect( word * pIn1, word * pIn2, int nWords, int fCo
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
static inline int Abc_TtIntersectOne( word * pOut, int fComp, word * pIn, int fComp0, int nWords )
|
||||
static inline int Abc_TtIntersectCare( word * pIn1, word * pIn2, word * pCare, int nWords, int fCompl )
|
||||
{
|
||||
int w;
|
||||
if ( fCompl )
|
||||
{
|
||||
for ( w = 0; w < nWords; w++ )
|
||||
if ( ~pIn1[w] & pIn2[w] & pCare[w] )
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( w = 0; w < nWords; w++ )
|
||||
if ( pIn1[w] & pIn2[w] & pCare[w] )
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}static inline int Abc_TtIntersectOne( word * pOut, int fComp, word * pIn, int fComp0, int nWords )
|
||||
{
|
||||
int w;
|
||||
if ( fComp0 )
|
||||
|
|
@ -542,6 +558,23 @@ static inline int Abc_TtEqual( word * pIn1, word * pIn2, int nWords )
|
|||
return 0;
|
||||
return 1;
|
||||
}
|
||||
static inline int Abc_TtEqualCare( word * pIn1, word * pIn2, word * pCare, int fComp, int nWords )
|
||||
{
|
||||
int w;
|
||||
if ( fComp )
|
||||
{
|
||||
for ( w = 0; w < nWords; w++ )
|
||||
if ( (~pIn1[w] ^ pIn2[w]) & pCare[w] )
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( w = 0; w < nWords; w++ )
|
||||
if ( (pIn1[w] ^ pIn2[w]) & pCare[w] )
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static inline int Abc_TtOpposite( word * pIn1, word * pIn2, int nWords )
|
||||
{
|
||||
int w;
|
||||
|
|
@ -1803,6 +1836,25 @@ static inline word Abc_Tt6Permute_rec( word t, int * pPerm, int nVars )
|
|||
return (uRes0 & s_Truths6Neg[pPerm[Var]]) | (uRes1 & s_Truths6[pPerm[Var]]);
|
||||
}
|
||||
static inline void Abc_TtPermute( word * p, int * pPerm, int nVars )
|
||||
{
|
||||
int v, UnPerm[16], Perm[16];
|
||||
assert( nVars <= 16 );
|
||||
for ( v = 0; v < nVars; v++ )
|
||||
UnPerm[v] = Perm[v] = v;
|
||||
for ( v = nVars-1; v >= 0; v-- )
|
||||
{
|
||||
int Lev = UnPerm[pPerm[v]];
|
||||
if ( v == Lev )
|
||||
continue;
|
||||
Abc_TtSwapVars( p, nVars, v, Lev );
|
||||
ABC_SWAP( int, Perm[v], Perm[Lev] );
|
||||
UnPerm[Perm[Lev]] = Lev;
|
||||
UnPerm[Perm[v]] = v;
|
||||
}
|
||||
for ( v = 0; v < nVars; v++ )
|
||||
assert( Perm[v] == pPerm[v] );
|
||||
}
|
||||
static inline void Abc_TtUnpermute( word * p, int * pPerm, int nVars )
|
||||
{
|
||||
int v, Perm[16];
|
||||
assert( nVars <= 16 );
|
||||
|
|
@ -1818,6 +1870,8 @@ static inline void Abc_TtPermute( word * p, int * pPerm, int nVars )
|
|||
Perm[vCur]= vCur;
|
||||
}
|
||||
}
|
||||
for ( v = 0; v < nVars; v++ )
|
||||
assert( Perm[v] == v );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
|
|||
Loading…
Reference in New Issue