New command for LUT cascade decomposition.

This commit is contained in:
Alan Mishchenko 2024-08-06 11:50:54 -07:00
parent 1963422c10
commit 43adbc77e8
4 changed files with 300 additions and 0 deletions

View File

@ -1195,6 +1195,10 @@ SOURCE=.\src\bdd\extrab\extraBdd.h
# End Source File
# Begin Source File
SOURCE=.\src\bdd\extrab\extraLutCas.h
# End Source File
# Begin Source File
SOURCE=.\src\bdd\extrab\extraBddAuto.c
# End Source File
# Begin Source File

View File

@ -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 );
@ -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 );
@ -8820,6 +8822,81 @@ usage:
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 []

View File

@ -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
@ -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 ///
////////////////////////////////////////////////////////////////////////

View File

@ -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__ */