Skip to content

Commit

Permalink
New command for LUT cascade decomposition.
Browse files Browse the repository at this point in the history
  • Loading branch information
alanminko committed Aug 6, 2024
1 parent 1963422 commit 43adbc7
Show file tree
Hide file tree
Showing 4 changed files with 300 additions and 0 deletions.
4 changes: 4 additions & 0 deletions abclib.dsp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

77 changes: 77 additions & 0 deletions src/base/abci/abc.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ static int Abc_CommandResubCore ( Abc_Frame_t * pAbc, int argc, cha
static int Abc_CommandResubCheck ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandLutCas ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandVarMin ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandFaultClasses ( Abc_Frame_t * pAbc, int argc, char ** argv );
Expand Down Expand Up @@ -947,6 +948,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Synthesis", "resub_check", Abc_CommandResubCheck, 0 );
// Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "lutcas", Abc_CommandLutCas, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "extract", Abc_CommandExtract, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "varmin", Abc_CommandVarMin, 0 );
Cmd_CommandAdd( pAbc, "Synthesis", "faultclasses", Abc_CommandFaultClasses, 0 );
Expand Down Expand Up @@ -8820,6 +8822,81 @@ int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}

/**Function*************************************************************

Synopsis []

Description []

SideEffects []

SeeAlso []

***********************************************************************/
int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv )
{
extern Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose );
Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes;
int c, nLutSize = 6, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF )
{
switch ( c )
{
case 'K':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
goto usage;
}
nLutSize = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( nLutSize < 0 )
goto usage;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}

if ( pNtk == NULL )
{
Abc_Print( -1, "Empty network.\n" );
return 1;
}
if ( Abc_NtkCoNum(pNtk) != 1 )
{
Abc_Print( -1, "This command is currently applicable only to single-output networks.\n" );
return 1;
}
if ( !Abc_NtkIsStrash(pNtk) )
{
Abc_Print( -1, "Run command \"strash\" to convert the network into an AIG.\n" );
return 1;
}
pNtkRes = Abc_NtkLutCascade( pNtk, nLutSize, fVerbose );
if ( pNtkRes == NULL )
{
Abc_Print( -1, "LUT cascade mapping failed.\n" );
return 1;
}
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
return 0;

usage:
Abc_Print( -2, "usage: lutcas [-K <num>] [-vh]\n" );
Abc_Print( -2, "\t derives single-rail LUT cascade for the primary output function\n" );
Abc_Print( -2, "\t-K <num> : the number of LUT inputs [default = %d]\n", nLutSize );
Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}

/**Function*************************************************************

Synopsis []
Expand Down
147 changes: 147 additions & 0 deletions src/base/abci/abcCas.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@
***********************************************************************/

#include "base/abc/abc.h"
#include "bool/kit/kit.h"
#include "aig/miniaig/miniaig.h"

#ifdef ABC_USE_CUDD
#include "bdd/extrab/extraBdd.h"
#include "bdd/extrab/extraLutCas.h"
#endif

ABC_NAMESPACE_IMPL_START
Expand Down Expand Up @@ -116,9 +119,153 @@ Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVer
#else

Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ) { return NULL; }
word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int fVerbose ) { return NULL; }

#endif


/*
The decomposed structure of the LUT cascade is represented as an array of 64-bit integers (words).
The first word in the record is the number of LUT info blocks in the record, which follow one by one.
Each LUT info block contains the following:
- the number of words in this block
- the number of fanins
- the list of fanins
- the variable ID of the output (can be one of the fanin variables)
- truth tables (one word for 6 vars or less; more words as needed for more than 6 vars)
For a 6-input node, the LUT info block takes 10 words (block size, fanin count, 6 fanins, output ID, truth table).
For a 4-input node, the LUT info block takes 8 words (block size, fanin count, 4 fanins, output ID, truth table).
If the LUT cascade contains a 6-LUT followed by a 4-LUT, the record contains 1+10+8=19 words.
*/

/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
word * Abc_LutCascadeGenTest()
{
word * pLuts = ABC_CALLOC( word, 20 ); int i;
// node count
pLuts[0] = 2;
// first node
pLuts[1+0] = 10;
pLuts[1+1] = 6;
for ( i = 0; i < 6; i++ )
pLuts[1+2+i] = i;
pLuts[1+8] = 0;
pLuts[1+9] = ABC_CONST(0x8000000000000000);
// second node
pLuts[11+0] = 8;
pLuts[11+1] = 4;
for ( i = 0; i < 4; i++ )
pLuts[11+2+i] = i ? i + 5 : 0;
pLuts[11+6] = 1;
pLuts[11+7] = ABC_CONST(0xFFFEFFFEFFFEFFFE);
return pLuts;
}
void Abc_LutCascadePrint( word * pLuts )
{
int n, i, k;
printf( "Single-rail LUT cascade has %d nodes:\n", (int)pLuts[0] );
for ( n = 0, i = 1; n < pLuts[0]; n++, i += pLuts[i] )
{
word nIns = pLuts[i+1];
word * pIns = pLuts+i+2;
word * pT = pLuts+i+2+nIns+1;
printf( "LUT%d : ", n );
printf( "%02d = F( ", (int)pIns[nIns] );
for ( k = 0; k < nIns; k++ )
printf( "%02d ", (int)pIns[k] );
for ( ; k < 8; k++ )
printf( " " );
printf( ") " );
Extra_PrintHex2( stdout, (unsigned *)pT, nIns );
printf( "\n" );
}
}
word * Abc_LutCascadeTest( Mini_Aig_t * p, int nLutSize, int fVerbose )
{
word * pLuts = Abc_LutCascadeGenTest();
Abc_LutCascadePrint( pLuts );
return pLuts;
}


/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_NtkLutCascadeDeriveSop( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeNew, word * pT, int nIns, Vec_Int_t * vCover )
{
int RetValue = Kit_TruthIsop( (unsigned *)pT, nIns, vCover, 1 );
assert( RetValue == 0 || RetValue == 1 );
if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) ) {
assert( RetValue == 0 );
pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, nIns, NULL );
return (Vec_IntSize(vCover) == 0) ? Abc_NtkCreateNodeConst0(pNtkNew) : Abc_NtkCreateNodeConst1(pNtkNew);
}
else {
char * pSop = Abc_SopCreateFromIsop( (Mem_Flex_t *)pNtkNew->pManFunc, nIns, vCover );
if ( RetValue ) Abc_SopComplement( (char *)pSop );
pNodeNew->pData = pSop;
return pNodeNew;
}
}
Abc_Ntk_t * Abc_NtkLutCascadeFromLuts( word * pLuts, Abc_Ntk_t * pNtk, int nLutSize, int fVerbose )
{
Abc_Ntk_t * pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
Vec_Int_t * vCover = Vec_IntAlloc( 1000 ); word n, i, k, iLastLut = -1;
assert( Abc_NtkCoNum(pNtk) == 1 );
for ( n = 0, i = 1; n < pLuts[0]; n++, i += pLuts[i] )
{
word nIns = pLuts[i+1];
word * pIns = pLuts+i+2;
word * pT = pLuts+i+2+nIns+1;
Abc_Obj_t * pNodeNew = Abc_NtkCreateNode( pNtkNew );
for ( k = 0; k < nIns; k++ )
Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtk, pIns[k])->pCopy );
Abc_NtkCi(pNtk, pIns[nIns])->pCopy = Abc_NtkLutCascadeDeriveSop( pNtkNew, pNodeNew, pT, nIns, vCover );
iLastLut = pIns[nIns];
}
Vec_IntFree( vCover );
Abc_ObjAddFanin( Abc_NtkCo(pNtk, 0)->pCopy, Abc_NtkCi(pNtk, iLastLut)->pCopy );
if ( !Abc_NtkCheck( pNtkNew ) )
{
printf( "Abc_NtkLutCascadeFromLuts: The network check has failed.\n" );
Abc_NtkDelete( pNtkNew );
return NULL;
}
return pNtkNew;
}
Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose )
{
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 fVerbose );
Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk );
Mini_Aig_t * pM = Gia_ManToMiniAig( pGia );
word * pLuts = Abc_LutCascade( pM, nLutSize, fVerbose );
Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, pNtk, nLutSize, fVerbose ) : NULL;
ABC_FREE( pLuts );
Mini_AigStop( pM );
Gia_ManStop( pGia );
return pNew;
}

////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
Expand Down
72 changes: 72 additions & 0 deletions src/bdd/extrab/extraLutCas.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**CFile****************************************************************
FileName [extraLutCas.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [extra]
Synopsis [LUT cascade decomposition.]
Description [LUT cascade decomposition.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - August 6, 2024.]
Revision [$Id: extraLutCas.h,v 1.00 2024/08/06 00:00:00 alanmi Exp $]
***********************************************************************/

#ifndef ABC__misc__extra__extra_lutcas_h
#define ABC__misc__extra__extra_lutcas_h

#ifdef _WIN32
#define inline __inline // compatible with MS VS 6.0
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "bdd/cudd/cuddInt.h"

ABC_NAMESPACE_HEADER_START

/*
The decomposed structure of the LUT cascade is represented as an array of 64-bit integers (words).
The first word in the record is the number of LUT info blocks in the record, which follow one by one.
Each LUT info block contains the following:
- the number of words in this block
- the number of fanins
- the list of fanins
- the variable ID of the output (can be one of the fanin variables)
- truth tables (one word for 6 vars or less; more words as needed for more than 6 vars)
For a 6-input node, the LUT info block takes 10 words (block size, fanin count, 6 fanins, output ID, truth table).
For a 4-input node, the LUT info block takes 8 words (block size, fanin count, 4 fanins, output ID, truth table).
If the LUT cascade contains a 6-LUT followed by a 4-LUT, the record contains 1+10+8=19 words.
*/

/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int fVerbose )
{
word * pLuts = NULL;
return pLuts;
}

ABC_NAMESPACE_HEADER_END

#endif /* __EXTRA_H__ */

0 comments on commit 43adbc7

Please sign in to comment.