mirror of https://github.com/YosysHQ/abc.git
New command 'testnpn' to compare semi-canonical forms.
This commit is contained in:
parent
094bdc0572
commit
41fa9a1016
|
|
@ -109,6 +109,7 @@ static int Abc_CommandPowerdown ( Abc_Frame_t * pAbc, int argc, cha
|
|||
static int Abc_CommandAddBuffs ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
//static int Abc_CommandMerge ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandTestDec ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandTestNpn ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
|
||||
static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
|
|
@ -571,6 +572,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
|
|||
Cmd_CommandAdd( pAbc, "Synthesis", "addbuffs", Abc_CommandAddBuffs, 1 );
|
||||
// Cmd_CommandAdd( pAbc, "Synthesis", "merge", Abc_CommandMerge, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "testdec", Abc_CommandTestDec, 0 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "testnpn", Abc_CommandTestNpn, 0 );
|
||||
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 );
|
||||
|
|
@ -4865,6 +4867,73 @@ usage:
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_CommandTestNpn( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
extern int Abc_NpnTest( char * pFileName, int NpnType, int fVerbose );
|
||||
char * pFileName;
|
||||
int c;
|
||||
int fVerbose = 0;
|
||||
int NpnType = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "Avh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'A':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
NpnType = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( NpnType < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( argc != globalUtilOptind + 1 )
|
||||
{
|
||||
printf( "Input file is not given.\n" );
|
||||
goto usage;
|
||||
}
|
||||
// get the output file name
|
||||
pFileName = argv[globalUtilOptind];
|
||||
// call the testbench
|
||||
Abc_NpnTest( pFileName, NpnType, fVerbose );
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
Abc_Print( -2, "usage: testnpn [-A <num>] [-vh] <file_name>\n" );
|
||||
Abc_Print( -2, "\t testbench for computing semi-canonical forms of Boolean functions\n" );
|
||||
Abc_Print( -2, "\t-A <num> : semi-caninical form computation algorithm [default = %d]\n", NpnType );
|
||||
Abc_Print( -2, "\t 0: none (reading and writing the file)\n" );
|
||||
Abc_Print( -2, "\t 1: semi-canonical form by counting 1s in cofactors\n" );
|
||||
Abc_Print( -2, "\t 2: semi-canonical form by minimizing truth table value\n" );
|
||||
Abc_Print( -2, "\t 3: exact canonical form (slow for more than 6 variables)\n" );
|
||||
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*************************************************************
|
||||
|
||||
|
|
|
|||
|
|
@ -42,10 +42,10 @@ ABC_NAMESPACE_IMPL_START
|
|||
typedef struct Abc_TtStore_t_ Abc_TtStore_t;
|
||||
struct Abc_TtStore_t_
|
||||
{
|
||||
int nVars;
|
||||
int nwords;
|
||||
int nFuncs;
|
||||
word ** pFuncs;
|
||||
int nVars;
|
||||
int nWords;
|
||||
int nFuncs;
|
||||
word ** pFuncs;
|
||||
};
|
||||
|
||||
// read/write/flip i-th bit of a bit string table:
|
||||
|
|
@ -88,8 +88,8 @@ static inline void Abc_TruthWriteHexDigit( FILE * pFile, int HexDigit )
|
|||
// read one truth table in hexadecimal
|
||||
void Abc_TruthReadHex( word * pTruth, char * pString, int nVars )
|
||||
{
|
||||
int nwords = (nVars < 7)? 1 : (1 << (nVars-6));
|
||||
int k, Digit, nDigits = (nwords << 4);
|
||||
int nWords = (nVars < 7)? 1 : (1 << (nVars-6));
|
||||
int k, Digit, nDigits = (nWords << 4);
|
||||
char EndSymbol;
|
||||
// skip the first 2 symbols if they are "0x"
|
||||
if ( pString[0] == '0' && pString[1] == 'x' )
|
||||
|
|
@ -143,15 +143,15 @@ Abc_TtStore_t * Abc_TruthStoreAlloc( int nVars, int nFuncs )
|
|||
int i;
|
||||
p = (Abc_TtStore_t *)malloc( sizeof(Abc_TtStore_t) );
|
||||
p->nVars = nVars;
|
||||
p->nwords = (nVars < 7) ? 1 : (1 << (nVars-6));
|
||||
p->nWords = (nVars < 7) ? 1 : (1 << (nVars-6));
|
||||
p->nFuncs = nFuncs;
|
||||
// alloc array of 'nFuncs' pointers to truth tables
|
||||
p->pFuncs = (word **)malloc( sizeof(word *) * p->nFuncs );
|
||||
// alloc storage for 'nFuncs' truth tables as one chunk of memory
|
||||
p->pFuncs[0] = (word *)calloc( sizeof(word), p->nFuncs * p->nwords );
|
||||
p->pFuncs[0] = (word *)calloc( sizeof(word), p->nFuncs * p->nWords );
|
||||
// split it up into individual truth tables
|
||||
for ( i = 1; i < p->nFuncs; i++ )
|
||||
p->pFuncs[i] = p->pFuncs[i-1] + p->nwords;
|
||||
p->pFuncs[i] = p->pFuncs[i-1] + p->nWords;
|
||||
return p;
|
||||
}
|
||||
void Abc_TruthStoreFree( Abc_TtStore_t * p )
|
||||
|
|
@ -338,23 +338,46 @@ void Abc_TruthStoreWrite( char * pFileName, Abc_TtStore_t * p )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_TruthStoreTest( char * pFileName )
|
||||
Abc_TtStore_t * Abc_TruthStoreLoad( char * pFileName )
|
||||
{
|
||||
Abc_TtStore_t * p;
|
||||
char * pFileInput = pFileName;
|
||||
char * pFileOutput = "out.txt";
|
||||
int nVars, nTruths;
|
||||
|
||||
// figure out how many truth table and how many variables
|
||||
Abc_TruthGetParams( pFileInput, &nVars, &nTruths );
|
||||
if ( nVars < 2 || nVars > 16 || nTruths == 0 )
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
// allocate data-structure
|
||||
p = Abc_TruthStoreAlloc( nVars, nTruths );
|
||||
|
||||
// read info from file
|
||||
Abc_TruthStoreRead( pFileInput, p );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Read truth tables from input file and write them into output file.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_TruthStoreTest( char * pFileName )
|
||||
{
|
||||
Abc_TtStore_t * p;
|
||||
char * pFileInput = pFileName;
|
||||
char * pFileOutput = "out.txt";
|
||||
|
||||
// read info from file
|
||||
p = Abc_TruthStoreLoad( pFileInput );
|
||||
if ( p == NULL )
|
||||
return;
|
||||
|
||||
// write into another file
|
||||
Abc_TruthStoreWrite( pFileOutput, p );
|
||||
|
|
|
|||
|
|
@ -0,0 +1,230 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [abcNpn.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Network and node package.]
|
||||
|
||||
Synopsis [Procedures for testing and comparing semi-canonical forms.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: abcNpn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "misc/extra/extra.h"
|
||||
#include "misc/vec/vec.h"
|
||||
|
||||
#include "bool/kit/kit.h"
|
||||
#include "bool/lucky/lucky.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// semi-canonical form types
|
||||
// 0 - none
|
||||
// 1 - based on counting 1s in cofactors
|
||||
// 2 - based on minimum truth table value
|
||||
// 3 - exact NPN
|
||||
|
||||
// data-structure to store a bunch of truth tables
|
||||
typedef struct Abc_TtStore_t_ Abc_TtStore_t;
|
||||
struct Abc_TtStore_t_
|
||||
{
|
||||
int nVars;
|
||||
int nWords;
|
||||
int nFuncs;
|
||||
word ** pFuncs;
|
||||
};
|
||||
|
||||
extern Abc_TtStore_t * Abc_TruthStoreLoad( char * pFileName );
|
||||
extern void Abc_TruthStoreFree( Abc_TtStore_t * p );
|
||||
extern void Abc_TruthStoreTest( char * pFileName );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Counts the number of unique truth tables.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int nWords = 0; // unfortunate global variable
|
||||
int Abc_TruthCompare( word * p1, word * p2 ) { return memcmp(p1, p2, sizeof(word) * nWords); }
|
||||
int Abc_TruthNpnCountUnique( Abc_TtStore_t * p )
|
||||
{
|
||||
int i, nUnique;
|
||||
// sort them by value
|
||||
nWords = p->nWords;
|
||||
assert( nWords > 0 );
|
||||
qsort( (void *)p->pFuncs[0], p->nFuncs, nWords * sizeof(word), (int(*)(const void *,const void *))Abc_TruthCompare );
|
||||
// count the number of unqiue functions
|
||||
nUnique = p->nFuncs;
|
||||
for ( i = 1; i < p->nFuncs; i++ )
|
||||
if ( !memcmp( p->pFuncs[i-1], p->pFuncs[i], sizeof(word) * nWords ) )
|
||||
nUnique--;
|
||||
return nUnique;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Apply decomposition to the truth table.]
|
||||
|
||||
Description [Returns the number of AIG nodes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_TruthNpnPerform( Abc_TtStore_t * p, int NpnType, int fVerbose )
|
||||
{
|
||||
short pStore[16];
|
||||
char pCanonPerm[16];
|
||||
unsigned pAux[2048];
|
||||
|
||||
clock_t clk = clock();
|
||||
int i, nFuncs = 0;
|
||||
|
||||
char * pAlgoName = NULL;
|
||||
if ( NpnType == 1 )
|
||||
pAlgoName = "counting 1s ";
|
||||
else if ( NpnType == 2 )
|
||||
pAlgoName = "minimizing TT";
|
||||
else if ( NpnType == 3 )
|
||||
pAlgoName = "exact NPN ";
|
||||
|
||||
assert( p->nVars <= 16 );
|
||||
if ( pAlgoName )
|
||||
printf( "Applying %-10s to %8d func%s of %2d vars... ",
|
||||
pAlgoName, p->nFuncs, (p->nFuncs == 1 ? "":"s"), p->nVars );
|
||||
if ( fVerbose )
|
||||
printf( "\n" );
|
||||
|
||||
if ( NpnType == 1 )
|
||||
{
|
||||
for ( i = 0; i < p->nFuncs; i++ )
|
||||
{
|
||||
if ( fVerbose )
|
||||
printf( "%7d : ", i );
|
||||
Kit_TruthSemiCanonicize( (unsigned *)p->pFuncs[i], pAux, p->nVars, pCanonPerm, pStore );
|
||||
if ( fVerbose )
|
||||
Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), printf( "\n" );
|
||||
}
|
||||
}
|
||||
else if ( NpnType == 2 )
|
||||
{
|
||||
for ( i = 0; i < p->nFuncs; i++ )
|
||||
{
|
||||
if ( fVerbose )
|
||||
printf( "%7d : ", i );
|
||||
Kit_TruthSemiCanonicize_new( (unsigned *)p->pFuncs[i], pAux, p->nVars, pCanonPerm );
|
||||
if ( fVerbose )
|
||||
Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), printf( "\n" );
|
||||
}
|
||||
}
|
||||
else if ( NpnType == 3 )
|
||||
{
|
||||
int * pComp = Extra_GreyCodeSchedule( p->nVars );
|
||||
int * pPerm = Extra_PermSchedule( p->nVars );
|
||||
if ( p->nVars == 6 )
|
||||
{
|
||||
for ( i = 0; i < p->nFuncs; i++ )
|
||||
{
|
||||
if ( fVerbose )
|
||||
printf( "%7d : ", i );
|
||||
*((word *)p->pFuncs[i]) = Extra_Truth6Minimum( *((word *)p->pFuncs[i]), pComp, pPerm );
|
||||
if ( fVerbose )
|
||||
Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), printf( "\n" );
|
||||
}
|
||||
}
|
||||
else
|
||||
printf( "This feature only works for 6-variable functions.\n" );
|
||||
ABC_FREE( pComp );
|
||||
ABC_FREE( pPerm );
|
||||
}
|
||||
else assert( 0 );
|
||||
|
||||
clk = clock() - clk;
|
||||
printf( "Classes =%9d ", Abc_TruthNpnCountUnique(p) );
|
||||
Abc_PrintTime( 1, "Time", clk );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Apply decomposition to truth tables.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_TruthNpnTest( char * pFileName, int NpnType, int fVerbose )
|
||||
{
|
||||
Abc_TtStore_t * p;
|
||||
|
||||
// read info from file
|
||||
p = Abc_TruthStoreLoad( pFileName );
|
||||
if ( p == NULL )
|
||||
return;
|
||||
|
||||
// consider functions from the file
|
||||
Abc_TruthNpnPerform( p, NpnType, fVerbose );
|
||||
|
||||
// delete data-structure
|
||||
Abc_TruthStoreFree( p );
|
||||
// printf( "Finished computing canonical forms for functions from file \"%s\".\n", pFileName );
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Testbench for decomposition algorithms.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NpnTest( char * pFileName, int NpnType, int fVerbose )
|
||||
{
|
||||
if ( fVerbose )
|
||||
printf( "Using truth tables from file \"%s\"...\n", pFileName );
|
||||
if ( NpnType == 0 )
|
||||
Abc_TruthStoreTest( pFileName );
|
||||
else if ( NpnType >= 1 && NpnType <= 3 )
|
||||
Abc_TruthNpnTest( pFileName, NpnType, fVerbose );
|
||||
else
|
||||
printf( "Unknown canonical form value (%d).\n", NpnType );
|
||||
fflush( stdout );
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -35,6 +35,7 @@ SRC += src/base/abci/abc.c \
|
|||
src/base/abci/abcMiter.c \
|
||||
src/base/abci/abcMulti.c \
|
||||
src/base/abci/abcNtbdd.c \
|
||||
src/base/abci/abcNpn.c \
|
||||
src/base/abci/abcNpnSave.c \
|
||||
src/base/abci/abcOdc.c \
|
||||
src/base/abci/abcOrder.c \
|
||||
|
|
|
|||
|
|
@ -203,6 +203,7 @@ extern void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fI
|
|||
/* complementation/permutation generation */
|
||||
extern int * Extra_GreyCodeSchedule( int n );
|
||||
extern int * Extra_PermSchedule( int n );
|
||||
extern word Extra_Truth6Minimum( word t, int * pComp, int * pPerm );
|
||||
|
||||
/*=== extraUtilCanon.c ========================================================*/
|
||||
|
||||
|
|
|
|||
|
|
@ -2283,7 +2283,7 @@ static inline word Extra_Truth6ChangePhase( word t, int v )
|
|||
assert( v < 6 );
|
||||
return ((t & ~Truth6[v]) << (1 << v)) | ((t & Truth6[v]) >> (1 << v));
|
||||
}
|
||||
static inline word Extra_Truth6Minimum( word t, int * pComp, int * pPerm )
|
||||
word Extra_Truth6Minimum( word t, int * pComp, int * pPerm )
|
||||
{
|
||||
word tMin = ~(word)0;
|
||||
word tCur, tTemp1, tTemp2;
|
||||
|
|
|
|||
Loading…
Reference in New Issue