Experiments with circuit generators.

This commit is contained in:
Alan Mishchenko 2024-07-31 17:39:11 -07:00
parent 572b80b230
commit 9062ed964c
4 changed files with 917 additions and 4 deletions

View File

@ -214,6 +214,8 @@ static int Abc_CommandCareSet ( Abc_Frame_t * pAbc, int argc, cha
static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandEspresso ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandGen ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandGenTF ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandGenAT ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandGenFsm ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandCover ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandDouble ( Abc_Frame_t * pAbc, int argc, char ** argv );
@ -1005,6 +1007,8 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Various", "cut", Abc_CommandCut, 0 );
Cmd_CommandAdd( pAbc, "Various", "espresso", Abc_CommandEspresso, 1 );
Cmd_CommandAdd( pAbc, "Various", "gen", Abc_CommandGen, 0 );
Cmd_CommandAdd( pAbc, "Various", "gentf", Abc_CommandGenTF, 0 );
Cmd_CommandAdd( pAbc, "Various", "genat", Abc_CommandGenAT, 0 );
Cmd_CommandAdd( pAbc, "Various", "genfsm", Abc_CommandGenFsm, 0 );
Cmd_CommandAdd( pAbc, "Various", "cover", Abc_CommandCover, 1 );
Cmd_CommandAdd( pAbc, "Various", "double", Abc_CommandDouble, 1 );
@ -14078,6 +14082,195 @@ usage:
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_CommandGenTF( Abc_Frame_t * pAbc, int argc, char ** argv )
{
extern void Abc_GenThresh( char * pFileName, int nBits, Vec_Int_t * vNums, int nLutSize, char * pArch );
int c, nBits = 0, nLutSize = -1, fVerbose = 0, nSum = 0;
char Command[1000], * pFileName = "out.blif", * pArch = NULL;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "WKAvh" ) ) != EOF )
{
switch ( c )
{
case 'W':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
goto usage;
}
nBits = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( nBits < 0 )
goto usage;
break;
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 'A':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-A\" should be followed by a file name.\n" );
goto usage;
}
pArch = argv[globalUtilOptind];
globalUtilOptind++;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( argc == globalUtilOptind )
goto usage;
if ( nBits == 0 )
{
Abc_Print( -1, "Bit-width should be specified.\n" );
return 0;
}
if ( nLutSize != -1 && nLutSize != 4 && nLutSize != 6 )
{
Abc_Print( -1, "LUT size %d is not supported.\n", nLutSize );
return 0;
}
if ( pArch )
{
int Counts[2] = {0};
for ( c = 0; c < strlen(pArch); c++ )
if ( pArch[c] == '(' )
Counts[0]++;
else if ( pArch[c] == ')' )
Counts[1]++;
else if ( pArch[c] >= '1' && pArch[c] <= '9' )
nSum += pArch[c] - '0';
else if ( pArch[c] >= 'A' && pArch[c] <= 'Z' )
nSum += pArch[c] - 'A' + 10;
else {
Abc_Print( -1, "Architecture description contains a wrong symbol (%c).\n", pArch[c] );
return 0;
}
if ( Counts[0] != Counts[1] )
{
Abc_Print( -1, "Mismatching number of opening and closing parentheses (%d and %d).\n", Counts[0], Counts[1] );
return 0;
}
}
Vec_Int_t * vNums = Vec_IntAlloc( argc );
for ( c = globalUtilOptind; c < argc; c++ )
Vec_IntPush( vNums, atoi(argv[c]) );
if ( Vec_IntSize(vNums) < 3 ) {
Vec_IntFree( vNums );
Abc_Print( -1, "Expecting that at least two weights and a threshold are specified on the command line.\n" );
return 0;
}
if ( pArch && nSum != Vec_IntSize(vNums)-1 ) {
Vec_IntFree( vNums );
Abc_Print( -1, "The architecture assumes %d sum inputs while there are %d weights.\n", nSum, Vec_IntSize(vNums)-1 );
return 0;
}
printf( "Generating threshold function with %d inputs and bit-width %d.\n", Vec_IntSize(vNums)-1, nBits );
Abc_GenThresh( pFileName, nBits, vNums, nLutSize, pArch );
if ( nLutSize == 4 || nLutSize == 6 )
sprintf(Command, "read %s; strash; if -K %d -am; mfs2 -W 10 -L 10 -M 1000", pFileName, nLutSize );
else
sprintf(Command, "read %s", pFileName );
Cmd_CommandExecute( pAbc, Command );
Vec_IntFree( vNums );
return 0;
usage:
Abc_Print( -2, "usage: gentf [-WK num] [-A str] [-vh] <w1> <w2> ... <wn> <thresh>\n" );
Abc_Print( -2, "\t generates threshold function\n" );
Abc_Print( -2, "\t-W num : the bit-width [default = none]\n" );
Abc_Print( -2, "\t-K num : the LUT size [default = none]\n" );
Abc_Print( -2, "\t-A str : the circuit architecture [default = none]\n");
Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
Abc_Print( -2, "\t<nums> : weights and threshold\n");
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_CommandGenAT( Abc_Frame_t * pAbc, int argc, char ** argv )
{
extern void Abc_GenAT( char * pFileName, Vec_Int_t * vNums );
extern void Abc_GenATDual( char * pFileName, Vec_Int_t * vNums );
int c, fDual = 0, fVerbose = 0;
char Command[1000], * pFileName = "out.blif";
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "dvh" ) ) != EOF )
{
switch ( c )
{
case 'd':
fDual ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( argc == globalUtilOptind )
goto usage;
Vec_Int_t * vNums = Vec_IntAlloc( argc );
for ( c = globalUtilOptind; c < argc; c++ )
Vec_IntPush( vNums, atoi(argv[c]) );
if ( fDual )
Abc_GenATDual( pFileName, vNums );
else
Abc_GenAT( pFileName, vNums );
sprintf(Command, "read %s", pFileName );
Cmd_CommandExecute( pAbc, Command );
Vec_IntFree( vNums );
return 0;
usage:
Abc_Print( -2, "usage: genat [-dvh] <n1> <n2> ... <nn>\n" );
Abc_Print( -2, "\t generates the adder tree\n" );
Abc_Print( -2, "\t-d : toggle building dual tree [default = %s]\n", fDual? "yes": "no" );
Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
Abc_Print( -2, "\t<nums> : input counts by rank\n");
return 1;
}
/**Function*************************************************************
Synopsis []

View File

@ -42,6 +42,32 @@ ABC_NAMESPACE_IMPL_START
SeeAlso []
***********************************************************************/
void Abc_WriteHalfAdder( FILE * pFile )
{
int fNaive = 0;
fprintf( pFile, ".model HA\n" );
fprintf( pFile, ".inputs a b\n" );
fprintf( pFile, ".outputs s cout\n" );
if ( fNaive )
{
fprintf( pFile, ".names a b s\n" );
fprintf( pFile, "10 1\n" );
fprintf( pFile, "01 1\n" );
fprintf( pFile, ".names a b cout\n" );
fprintf( pFile, "11 1\n" );
}
else
{
fprintf( pFile, ".names a b cout\n" );
fprintf( pFile, "11 1\n" );
fprintf( pFile, ".names a b and1_\n" );
fprintf( pFile, "00 1\n" );
fprintf( pFile, ".names cout and1_ s\n" );
fprintf( pFile, "00 1\n" );
}
fprintf( pFile, ".end\n" );
fprintf( pFile, "\n" );
}
void Abc_WriteFullAdder( FILE * pFile )
{
int fNaive = 0;
@ -50,6 +76,7 @@ void Abc_WriteFullAdder( FILE * pFile )
fprintf( pFile, ".outputs s cout\n" );
if ( fNaive )
{
/*
fprintf( pFile, ".names a b k\n" );
fprintf( pFile, "10 1\n" );
fprintf( pFile, "01 1\n" );
@ -60,6 +87,19 @@ void Abc_WriteFullAdder( FILE * pFile )
fprintf( pFile, "11- 1\n" );
fprintf( pFile, "1-1 1\n" );
fprintf( pFile, "-11 1\n" );
*/
fprintf( pFile, ".names a b s0\n" );
fprintf( pFile, "10 1\n" );
fprintf( pFile, "01 1\n" );
fprintf( pFile, ".names a b c0\n" );
fprintf( pFile, "11 1\n" );
fprintf( pFile, ".names s0 cin s\n" );
fprintf( pFile, "10 1\n" );
fprintf( pFile, "01 1\n" );
fprintf( pFile, ".names s0 cin c1\n" );
fprintf( pFile, "11 1\n" );
fprintf( pFile, ".names c0 c1 cout\n" );
fprintf( pFile, "00 0\n" );
}
else
{
@ -1205,6 +1245,679 @@ void Abc_GenGraph( char * pFileName, int nPis )
ABC_FREE( pTruth );
}
/**Function*************************************************************
Synopsis [Threshold function generation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_GenComp63a4( FILE * pFile )
{
fprintf( pFile, ".model C63a\n" );
fprintf( pFile, ".inputs x0 x1 x2 x3 x4 x5\n" );
fprintf( pFile, ".outputs z0 z1 z2\n" );
fprintf( pFile, ".names x1 x2 x3 x0 n10\n" );
fprintf( pFile, "--00 1\n" );
fprintf( pFile, "-0-0 1\n" );
fprintf( pFile, "0--0 1\n" );
fprintf( pFile, "000- 1\n" );
fprintf( pFile, ".names x4 x5 n13 n10 z0\n" );
fprintf( pFile, "--00 1\n" );
fprintf( pFile, "-1-0 1\n" );
fprintf( pFile, "1--0 1\n" );
fprintf( pFile, "111- 1\n" );
fprintf( pFile, ".names x1 x2 x3 x0 n13\n" );
fprintf( pFile, "-110 1\n" );
fprintf( pFile, "1-10 1\n" );
fprintf( pFile, "11-0 1\n" );
fprintf( pFile, "-001 1\n" );
fprintf( pFile, "0-01 1\n" );
fprintf( pFile, "00-1 1\n" );
fprintf( pFile, ".names x4 x5 n13 n16 z1\n" );
fprintf( pFile, "1-00 1\n" );
fprintf( pFile, "0-10 1\n" );
fprintf( pFile, "-101 1\n" );
fprintf( pFile, "-011 1\n" );
fprintf( pFile, ".names x1 x2 x3 x4 n16\n" );
fprintf( pFile, "1000 1\n" );
fprintf( pFile, "0100 1\n" );
fprintf( pFile, "0010 1\n" );
fprintf( pFile, "1110 1\n" );
fprintf( pFile, "0001 1\n" );
fprintf( pFile, "1101 1\n" );
fprintf( pFile, "1011 1\n" );
fprintf( pFile, "0111 1\n" );
fprintf( pFile, ".names x5 n16 z2\n" );
fprintf( pFile, "10 1\n" );
fprintf( pFile, "01 1\n" );
fprintf( pFile, ".end\n\n" );
}
void Abc_GenComp63a6( FILE * pFile )
{
fprintf( pFile, ".model C63a\n" );
fprintf( pFile, ".inputs x0 x1 x2 x3 x4 x5\n" );
fprintf( pFile, ".outputs z0 z1 z2\n" );
fprintf( pFile, ".names x1 x2 x3 x4 x5 x0 z0\n" );
fprintf( pFile, "---111 1\n" );
fprintf( pFile, "--1-11 1\n" );
fprintf( pFile, "--11-1 1\n" );
fprintf( pFile, "-1--11 1\n" );
fprintf( pFile, "-1-1-1 1\n" );
fprintf( pFile, "-11--1 1\n" );
fprintf( pFile, "-1111- 1\n" );
fprintf( pFile, "1---11 1\n" );
fprintf( pFile, "1--1-1 1\n" );
fprintf( pFile, "1-1--1 1\n" );
fprintf( pFile, "1-111- 1\n" );
fprintf( pFile, "11---1 1\n" );
fprintf( pFile, "11-11- 1\n" );
fprintf( pFile, "111-1- 1\n" );
fprintf( pFile, "1111-- 1\n" );
fprintf( pFile, ".names x1 x2 x3 x4 x5 x0 z1\n" );
fprintf( pFile, "-00001 1\n" );
fprintf( pFile, "-00110 1\n" );
fprintf( pFile, "-01010 1\n" );
fprintf( pFile, "-01100 1\n" );
fprintf( pFile, "-10010 1\n" );
fprintf( pFile, "-10100 1\n" );
fprintf( pFile, "-11000 1\n" );
fprintf( pFile, "-11111 1\n" );
fprintf( pFile, "0-0001 1\n" );
fprintf( pFile, "0-0110 1\n" );
fprintf( pFile, "0-1010 1\n" );
fprintf( pFile, "0-1100 1\n" );
fprintf( pFile, "00-001 1\n" );
fprintf( pFile, "00-110 1\n" );
fprintf( pFile, "000-01 1\n" );
fprintf( pFile, "0000-1 1\n" );
fprintf( pFile, "1-0010 1\n" );
fprintf( pFile, "1-0100 1\n" );
fprintf( pFile, "1-1000 1\n" );
fprintf( pFile, "1-1111 1\n" );
fprintf( pFile, "11-000 1\n" );
fprintf( pFile, "11-111 1\n" );
fprintf( pFile, "111-11 1\n" );
fprintf( pFile, "1111-1 1\n" );
fprintf( pFile, ".names x1 x2 x3 x4 x5 z2\n" );
fprintf( pFile, "00001 1\n" );
fprintf( pFile, "00010 1\n" );
fprintf( pFile, "00100 1\n" );
fprintf( pFile, "00111 1\n" );
fprintf( pFile, "01000 1\n" );
fprintf( pFile, "01011 1\n" );
fprintf( pFile, "01101 1\n" );
fprintf( pFile, "01110 1\n" );
fprintf( pFile, "10000 1\n" );
fprintf( pFile, "10011 1\n" );
fprintf( pFile, "10101 1\n" );
fprintf( pFile, "10110 1\n" );
fprintf( pFile, "11001 1\n" );
fprintf( pFile, "11010 1\n" );
fprintf( pFile, "11100 1\n" );
fprintf( pFile, "11111 1\n" );
fprintf( pFile, ".end\n\n" );
}
void Abc_GenAdder4( FILE * pFile, int nBits, int nLutSize )
{
int i, n;
fprintf( pFile, ".model A%02d_4x\n", nBits );
for ( n = 0; n < 4; n++ ) {
fprintf( pFile, ".inputs" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " %c%02d", 'a'+n, i );
fprintf( pFile, "\n" );
}
fprintf( pFile, ".outputs" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " s%02d", i );
fprintf( pFile, "\n" );
fprintf( pFile, ".names v00\n" );
fprintf( pFile, ".names w00\n" );
for ( i = 0; i < nBits; i++ ) {
fprintf( pFile, ".subckt C63a" );
fprintf( pFile, " x0=w%02d", i );
fprintf( pFile, " x1=v%02d", i );
fprintf( pFile, " x2=a%02d", i );
fprintf( pFile, " x3=b%02d", i );
fprintf( pFile, " x4=c%02d", i );
fprintf( pFile, " x5=d%02d", i );
fprintf( pFile, " z0=w%02d", i+1 );
fprintf( pFile, " z1=v%02d", i+1 );
fprintf( pFile, " z2=s%02d", i );
fprintf( pFile, "\n" );
}
fprintf( pFile, ".end\n\n" );
if ( nLutSize == 4 )
Abc_GenComp63a4( pFile );
else if ( nLutSize == 6 )
Abc_GenComp63a6( pFile );
else assert( 0 );
}
void Abc_WriteAdder2( FILE * pFile, int nVars )
{
int i;
assert( nVars > 0 );
fprintf( pFile, ".model A%02d\n", nVars );
fprintf( pFile, ".inputs c\n" );
fprintf( pFile, ".inputs" );
for ( i = 0; i < nVars; i++ )
fprintf( pFile, " a%02d", i );
fprintf( pFile, "\n" );
fprintf( pFile, ".inputs" );
for ( i = 0; i < nVars; i++ )
fprintf( pFile, " b%02d", i );
fprintf( pFile, "\n" );
fprintf( pFile, ".outputs" );
for ( i = 0; i <= nVars; i++ )
fprintf( pFile, " s%02d", i );
fprintf( pFile, "\n" );
fprintf( pFile, ".names c t00\n1 1\n" );
for ( i = 0; i < nVars; i++ )
fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=t%02d s=s%02d cout=t%02d\n", i, i, i, i, i+1 );
fprintf( pFile, ".names t%02d s%02d\n1 1\n", nVars, nVars );
fprintf( pFile, ".end\n\n" );
Abc_WriteFullAdder( pFile );
}
void Abc_GenAdder4test( FILE * pFile, int nBits )
{
int i, n;
fprintf( pFile, ".model A%02d_4x\n", nBits );
for ( n = 0; n < 4; n++ ) {
fprintf( pFile, ".inputs" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " %c%02d", 'a'+n, i );
fprintf( pFile, "\n" );
}
fprintf( pFile, ".outputs" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " o%02d", i );
fprintf( pFile, "\n" );
fprintf( pFile, ".names zero\n" );
fprintf( pFile, ".subckt A%02d c=zero", nBits );
fprintf( pFile, " \\\n" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " a%0d=a%02d", i, i );
fprintf( pFile, " \\\n" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " b%0d=b%02d", i, i );
fprintf( pFile, " \\\n" );
for ( i = 0; i <= nBits; i++ )
fprintf( pFile, " s%0d=t%02d", i, i );
fprintf( pFile, "\n" );
fprintf( pFile, ".subckt A%02d c=zero", nBits );
fprintf( pFile, " \\\n" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " a%0d=c%02d", i, i );
fprintf( pFile, " \\\n" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " b%0d=t%02d", i, i );
fprintf( pFile, " \\\n" );
for ( i = 0; i <= nBits; i++ )
fprintf( pFile, " s%0d=u%02d", i, i );
fprintf( pFile, "\n" );
fprintf( pFile, ".subckt A%02d c=zero", nBits );
fprintf( pFile, " \\\n" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " a%0d=d%02d", i, i );
fprintf( pFile, " \\\n" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " b%0d=u%02d", i, i );
fprintf( pFile, " \\\n" );
for ( i = 0; i <= nBits; i++ )
fprintf( pFile, " s%0d=o%02d", i, i );
fprintf( pFile, "\n" );
fprintf( pFile, ".end\n\n" );
Abc_WriteAdder( pFile, nBits );
}
void Abc_WriteWeight( FILE * pFile, int Num, int nBits, int Weight )
{
int i;
fprintf( pFile, ".model W%02d\n", Num );
fprintf( pFile, ".inputs i\n" );
fprintf( pFile, ".outputs" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " o%02d", i );
fprintf( pFile, "\n" );
for ( i = 0; i < nBits; i++ )
if ( (Weight >> i) & 1 )
fprintf( pFile, ".names i o%02d\n1 1\n", i );
else
fprintf( pFile, ".names o%02d\n", i );
fprintf( pFile, ".end\n\n" );
}
Vec_Int_t * Abc_GenTreeFindGroups( char * pTree, int iPos )
{
Vec_Int_t * vRes = NULL;
int Counter = 1;
assert( pTree[iPos] == '(' );
while ( pTree[++iPos] ) {
if ( pTree[iPos] == '(' ) {
if ( Counter++ == 1 ) {
if ( vRes == NULL )
vRes = Vec_IntAlloc( 4 );
Vec_IntPush( vRes, iPos );
}
}
if ( pTree[iPos] == ')' )
Counter--;
if ( Counter == 0 )
return vRes;
}
assert( 0 );
return NULL;
}
int Abc_GenTree_rec( FILE * pFile, int nBits, char * pTree, int iPos, int * pSig, int * pUsed )
{
Vec_Int_t * vGroups = Abc_GenTreeFindGroups( pTree, iPos );
if ( vGroups == NULL )
return atoi(pTree+iPos+1);
int i, g, Group;
Vec_IntForEachEntry( vGroups, Group, g ) {
Group = Abc_GenTree_rec( pFile, nBits, pTree, Group, pSig, pUsed );
Vec_IntWriteEntry( vGroups, g, Group );
}
if ( Vec_IntSize(vGroups) == 3 )
Vec_IntPush(vGroups, 0);
if ( Vec_IntSize(vGroups) == 4 )
fprintf( pFile, ".subckt A%02d_4x", nBits ), *pUsed = 1;
else if ( Vec_IntSize(vGroups) == 2 )
fprintf( pFile, ".subckt A%02d c=zero", nBits );
else assert( 0 );
Vec_IntForEachEntry( vGroups, Group, g ) {
fprintf( pFile, " \\\n" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " %c%02d=%02d_%02d", 'a'+g, i, Group, i );
}
fprintf( pFile, " \\\n" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " s%02d=%02d_%02d", i, *pSig, i );
fprintf( pFile, "\n\n" );
return (*pSig)++;
}
void Abc_GenThreshAdder( FILE * pFile, int nBits, int A, int B, int S, int fOne )
{
if ( A > B ) ABC_SWAP( int, A, B ); int i;
fprintf( pFile, ".subckt A%02d c=%s", nBits, fOne ? "one" : "zero" );
fprintf( pFile, " \\\n" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " a%02d=%02d_%02d", i, A, i );
fprintf( pFile, " \\\n" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " b%02d=%02d_%02d", i, B, i );
fprintf( pFile, " \\\n" );
for ( i = 0; i <= nBits; i++ )
fprintf( pFile, " s%02d=%02d_%02d", i, S, i );
fprintf( pFile, "\n" );
}
void Abc_GenThresh( char * pFileName, int nBits, Vec_Int_t * vNums, int nLutSize, char * pArch )
{
FILE * pFile = fopen( pFileName, "w" );
int c, i, k, Temp, iPrev = 1, nNums = 1, nSigs = 1, fUsed = 0;
fprintf( pFile, "# %d-bit threshold function with %d variables generated by ABC on %s\n",
nBits, Vec_IntSize(vNums)-1, Extra_TimeStamp() );
fprintf( pFile, "# Weights:" );
Vec_IntForEachEntryStop( vNums, Temp, i, Vec_IntSize(vNums)-1 )
fprintf( pFile, " %d", Temp );
fprintf( pFile, "\n# Threshold: %d\n", Vec_IntEntryLast(vNums) );
fprintf( pFile, ".model TF%d_%d\n", Vec_IntSize(vNums)-1, nBits );
fprintf( pFile, ".inputs" );
for ( i = 0; i < Vec_IntSize(vNums)-1; i++ )
fprintf( pFile, " x%02d", i );
fprintf( pFile, "\n" );
fprintf( pFile, ".outputs F\n" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, ".names %02d_%02d\n", 0, i );
fprintf( pFile, ".names zero\n" );
fprintf( pFile, ".names one\n 1\n" );
Vec_IntForEachEntry( vNums, Temp, k ) {
fprintf( pFile, ".subckt W%02d", k );
if ( k < Vec_IntSize(vNums)-1 )
fprintf( pFile, " i=x%02d", k );
else
fprintf( pFile, " i=one" );
for ( i = 0; i < nBits; i++ )
fprintf( pFile, " o%02d=%02d_%02d", i, nSigs, i );
fprintf( pFile, "\n" );
nSigs++;
}
fprintf( pFile, "\n" );
if ( pArch == NULL )
{
Vec_IntForEachEntryStart( vNums, Temp, k, 1 ) {
Abc_GenThreshAdder( pFile, nBits, iPrev, k+1, nSigs, k == Vec_IntSize(vNums)-1 );
iPrev = nSigs++;
}
fprintf( pFile, ".names %02d_%02d F\n0 1\n", iPrev, nBits-1 );
}
else
{
Vec_Str_t * vArch = Vec_StrAlloc( 100 );
for ( c = 0; c < strlen(pArch); c++ ) {
if ( pArch[c] == '(' || pArch[c] == ')' ) {
Vec_StrPush( vArch, pArch[c] );
continue;
}
Temp = pArch[c] >= '0' && pArch[c] <= '9' ? pArch[c] - '0' : pArch[c] - 'A' + 10;
assert( Temp > 0 );
if ( Temp == 1 ) {
if ( nNums + Temp == Vec_IntSize(vNums) )
Abc_GenThreshAdder( pFile, nBits, nNums, nNums+1, iPrev = nSigs++, 1 );
else
iPrev = nNums++;
}
else {
int kLast = 0;
assert( nNums + Temp <= Vec_IntSize(vNums) );
if ( nNums + Temp == Vec_IntSize(vNums) )
kLast = Temp++;
iPrev = nNums++;
for ( k = 1; k < Temp; k++ ) {
Abc_GenThreshAdder( pFile, nBits, iPrev, nNums++, nSigs, k == kLast );
iPrev = nSigs++;
}
fprintf( pFile, "\n" );
}
Vec_StrPrintF( vArch, "(%d)", iPrev );
}
Vec_StrPush( vArch, '\0' );
Temp = Abc_GenTree_rec( pFile, nBits, Vec_StrArray(vArch), 0, &nSigs, &fUsed );
fprintf( pFile, ".names %02d_%02d F\n0 1\n", Temp, nBits-1 );
Vec_StrFree( vArch );
}
fprintf( pFile, ".end\n\n" );
Vec_IntForEachEntry( vNums, Temp, k )
Abc_WriteWeight( pFile, k, nBits, k == Vec_IntSize(vNums)-1 ? ~Temp : Temp );
Abc_WriteAdder2( pFile, nBits );
if ( fUsed )
Abc_GenAdder4( pFile, nBits, nLutSize == 4 ? 4 : 6 );
fclose( pFile );
}
/**Function*************************************************************
Synopsis [Adder tree generation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
// Based on the paper: E. Demenkov, A. Kojevnikov, A. Kulikov, and G. Yaroslavtsev,
// "New upper bounds on the Boolean circuit complexity of symmetric functions".
// Information Processing Letters, Vol 110(7), March 2010, Pages 264-267.
// https://grigory.us/files/publications/2010_upper_bounds_symmetric_ipl.pdf
void Abc_WriteMDFA( FILE * pFile )
{
fprintf( pFile, ".model MDFA\n" );
fprintf( pFile, ".inputs z x1 y1 x2 y2\n" );
fprintf( pFile, ".outputs s c1 c2\n" );
fprintf( pFile, ".names x1 z g1\n" );
fprintf( pFile, "10 1\n" );
fprintf( pFile, "01 1\n" );
fprintf( pFile, ".names y1 g1 g2\n" );
fprintf( pFile, "00 0\n" );
fprintf( pFile, ".names y1 z g3\n" );
fprintf( pFile, "10 1\n" );
fprintf( pFile, "01 1\n" );
fprintf( pFile, ".names g2 g3 g4\n" );
fprintf( pFile, "10 1\n" );
fprintf( pFile, "01 1\n" );
fprintf( pFile, ".names x2 g3 g5\n" );
fprintf( pFile, "10 1\n" );
fprintf( pFile, "01 1\n" );
fprintf( pFile, ".names g3 y2 g6\n" );
fprintf( pFile, "10 1\n" );
fprintf( pFile, "01 1\n" );
fprintf( pFile, ".names g5 y2 g7\n" );
fprintf( pFile, "10 1\n" );
fprintf( pFile, ".names g2 g7 g8\n" );
fprintf( pFile, "10 1\n" );
fprintf( pFile, "01 1\n" );
fprintf( pFile, ".names g6 s\n" );
fprintf( pFile, "1 1\n" );
fprintf( pFile, ".names g4 c1\n" );
fprintf( pFile, "1 1\n" );
fprintf( pFile, ".names g8 c2\n" );
fprintf( pFile, "1 1\n" );
fprintf( pFile, ".end\n" );
}
void Abc_GenAT( char * pFileName, Vec_Int_t * vNums )
{
word Sum = 0; int i, k, Num, nBits = 0;
Vec_IntForEachEntry( vNums, Num, i )
Sum += ((word)1 << i) * Num;
while ( Sum )
nBits++, Sum >>= 1;
Vec_Int_t * vTemp; int nFAs = 0, nHAs = 0, nItem = 0;
Vec_Wec_t * vItems = Vec_WecStart( nBits );
Vec_IntForEachEntry( vNums, Num, i )
for ( k = 0; k < Num; k++ )
Vec_WecPush( vItems, i, nItem++ );
FILE * pFile = fopen( pFileName, "w" );
fprintf( pFile, "# %d-bit %d-input adder tree generated by ABC on %s\n", nBits, nItem, Extra_TimeStamp() );
fprintf( pFile, "# Profile:" );
Vec_IntForEachEntry( vNums, Num, i )
fprintf( pFile, " %d", Num );
fprintf( pFile, "\n" );
fprintf( pFile, ".model AT%d_%d\n", nItem, nBits );
Vec_WecForEachLevel( vItems, vTemp, i ) {
if ( Vec_IntSize(vTemp) == 0 )
continue;
fprintf( pFile, ".inputs" );
Vec_IntForEachEntry( vTemp, Num, k )
fprintf( pFile, " %02d", Num );
fprintf( pFile, "\n" );
}
fprintf( pFile, ".outputs" );
for ( k = 0; k < nBits; k++ )
fprintf( pFile, " o%02d", k );
fprintf( pFile, "\n\n" );
assert( nItem == Vec_IntSum(vNums) );
Vec_WecForEachLevel( vItems, vTemp, i ) {
fprintf( pFile, "# Rank %d:\n", i );
Vec_IntForEachEntry( vTemp, Num, k ) {
if ( Vec_IntSize(vTemp) < 2 )
continue;
while ( Vec_IntSize(vTemp) > 2 ) {
int i1 = Vec_IntPop(vTemp);
int i2 = Vec_IntPop(vTemp);
int i3 = Vec_IntPop(vTemp);
int i4 = nItem++;
int i5 = nItem++;
fprintf( pFile, ".subckt FA a=%02d b=%02d cin=%02d s=%02d cout=%02d\n", i3, i2, i1, i4, i5 ); nFAs++;
Vec_IntPush( vTemp, i4 );
if ( i+1 < Vec_WecSize(vItems) )
Vec_WecPush( vItems, i+1, i5 );
}
if ( Vec_IntSize(vTemp) == 2 ) {
int i1 = Vec_IntPop(vTemp);
int i2 = Vec_IntPop(vTemp);
int i4 = nItem++;
int i5 = nItem++;
fprintf( pFile, ".subckt HA a=%02d b=%02d s=%02d cout=%02d\n", i2, i1, i4, i5 ); nHAs++;
Vec_IntPush( vTemp, i4 );
if ( i+1 < Vec_WecSize(vItems) )
Vec_WecPush( vItems, i+1, i5 );
}
assert( Vec_IntSize(vTemp) == 1 );
}
}
Vec_WecForEachLevel( vItems, vTemp, i )
if ( Vec_IntSize(vTemp) == 0 )
fprintf( pFile, ".names o%02d\n", i );
else if ( Vec_IntSize(vTemp) == 1 )
fprintf( pFile, ".names %02d o%02d\n1 1\n", Vec_IntEntry(vTemp, 0), i );
else assert( 0 );
fprintf( pFile, ".end\n\n" );
Abc_WriteHalfAdder( pFile );
Abc_WriteFullAdder( pFile );
printf( "Created %d-bit %d-input AT with %d FAs and %d HAs.\n", nBits, Vec_IntSum(vNums), nFAs, nHAs );
fclose( pFile );
Vec_WecFree( vItems );
}
void Abc_GenATDual( char * pFileName, Vec_Int_t * vNums )
{
word Sum = 0; int i, k, Num, nBits = 0, Iter = 0, fUsed = 0;
Vec_IntForEachEntry( vNums, Num, i )
Sum += ((word)1 << i) * Num;
while ( Sum )
nBits++, Sum >>= 1;
Vec_Int_t * vTemp; int nFAs = 0, nHAs = 0, nXors = 0, nItem = 1;
Vec_Wec_t * vItems = Vec_WecStart( nBits );
Vec_IntForEachEntry( vNums, Num, i )
for ( k = 0; k < Num; k++ )
Vec_WecPush( vItems, i, nItem++ );
FILE * pFile = fopen( pFileName, "w" );
fprintf( pFile, "# %d-bit %d-input adder tree generated by ABC on %s\n", nBits, Vec_IntSum(vNums), Extra_TimeStamp() );
fprintf( pFile, "# Profile:" );
Vec_IntForEachEntry( vNums, Num, i )
fprintf( pFile, " %d", Num );
fprintf( pFile, "\n" );
fprintf( pFile, ".model AT%d_%d\n", nItem, nBits );
Vec_WecForEachLevel( vItems, vTemp, i ) {
if ( Vec_IntSize(vTemp) == 0 )
continue;
fprintf( pFile, ".inputs" );
Vec_IntForEachEntry( vTemp, Num, k )
fprintf( pFile, " %02d", Num );
fprintf( pFile, "\n" );
}
fprintf( pFile, ".outputs" );
for ( k = 0; k < nBits; k++ )
fprintf( pFile, " o%02d", k );
fprintf( pFile, "\n\n" );
fprintf( pFile, ".names %02d\n", 0 );
while ( Vec_WecMaxLevelSize(vItems) > 2 )
{
fprintf( pFile, "# Iter %d:\n", Iter++ );
Vec_Wec_t * vItems2 = Vec_WecStart( nBits );
Vec_WecForEachLevel( vItems, vTemp, i ) {
while ( Vec_IntSize(vTemp) > 3 ) {
int i0 = Vec_IntEntry(vTemp, 0); Vec_IntDrop(vTemp, 0);
int i1 = Vec_IntEntry(vTemp, 0); Vec_IntDrop(vTemp, 0);
int i2 = Vec_IntEntry(vTemp, 0); Vec_IntDrop(vTemp, 0);
int i3 = Vec_IntEntry(vTemp, 0); Vec_IntDrop(vTemp, 0);
int i4 = (Vec_IntSize(vTemp) > 0 && Vec_IntEntryLast(vTemp) > 0) ? Vec_IntPop(vTemp) : 0;
assert( (i0 < 0) == (i1 < 0) );
assert( (i2 < 0) == (i3 < 0) );
if ( i1 > 0 )
fprintf( pFile, ".names %02d %02d %02d\n01 1\n10 1\n", i0, i1, nItem ), i1 = nItem++, nXors++;
else
i1 = -i1, i0 = -i0;
if ( i3 > 0 )
fprintf( pFile, ".names %02d %02d %02d\n01 1\n10 1\n", i2, i3, nItem ), i3 = nItem++, nXors++;
else
i3 = -i3, i2 = -i2;
int o0 = nItem++;
int o1 = nItem++;
int o2 = nItem++;
fprintf( pFile, ".subckt MDFA z=%02d x1=%02d y1=%02d x2=%02d y2=%02d s=%02d c1=%02d c2=%02d\n", i4, i0, i1, i2, i3, o0, o1, o2 ); nFAs += 2, fUsed = 1;
Vec_WecPush( vItems2, i, o0 );
if ( i+1 < Vec_WecSize(vItems2) ) {
Vec_WecPush( vItems2, i+1, -o1 );
Vec_WecPush( vItems2, i+1, -o2 );
}
}
if ( Vec_IntSize(vTemp) == 3 ) {
int i2 = Vec_IntPop(vTemp);
int i1 = Vec_IntPop(vTemp);
int i0 = Vec_IntPop(vTemp);
assert( (i0 < 0) == (i1 < 0) );
assert( i2 > 0 );
if ( i1 < 0 )
fprintf( pFile, ".names %02d %02d %02d\n01 1\n10 1\n", -i0, -i1, nItem ), i0 = -i0, i1 = nItem++, nXors++;
int o0 = nItem++;
int o1 = nItem++;
fprintf( pFile, ".subckt FA a=%02d b=%02d cin=%02d s=%02d cout=%02d\n", i0, i1, i2, o0, o1 ); nFAs++;
Vec_WecPush( vItems2, i, o0 );
if ( i+1 < Vec_WecSize(vItems2) )
Vec_WecPush( vItems2, i+1, o1 );
}
if ( Vec_IntSize(vTemp) == 2 ) {
int i1 = Vec_IntPop(vTemp);
int i0 = Vec_IntPop(vTemp);
assert( (i0 < 0) == (i1 < 0) );
if ( i1 < 0 ) {
Vec_IntInsert( Vec_WecEntry(vItems2, i), 0, i1 );
Vec_IntInsert( Vec_WecEntry(vItems2, i), 0, i0 );
}
else {
Vec_WecPush( vItems2, i, i0 );
Vec_WecPush( vItems2, i, i1 );
}
}
if ( Vec_IntSize(vTemp) == 1 ) {
int i0 = Vec_IntPop(vTemp);
assert( i0 > 0 );
Vec_WecPush( vItems2, i, i0 );
}
assert( Vec_IntSize(vTemp) == 0 );
}
Vec_WecFree( vItems );
vItems = vItems2;
}
Vec_WecForEachLevel( vItems, vTemp, i ) {
if ( Vec_IntSize(vTemp) == 2 ) {
int i1 = Vec_IntPop(vTemp);
int i0 = Vec_IntPop(vTemp);
assert( (i0 < 0) == (i1 < 0) );
if ( i1 < 0 )
fprintf( pFile, ".names %02d %02d %02d\n01 1\n10 1\n", -i0, -i1, nItem ), i0 = -i0, i1 = nItem++, nXors++;
Vec_IntPush( vTemp, i0 );
Vec_IntPush( vTemp, i1 );
}
if ( Vec_IntSize(vTemp) == 1 ) {
int i0 = Vec_IntPop(vTemp);
assert( i0 > 0 );
Vec_IntPush( vTemp, i0 );
Vec_IntPush( vTemp, 0 );
}
if ( Vec_IntSize(vTemp) == 0 ) {
Vec_IntPush( vTemp, 0 );
Vec_IntPush( vTemp, 0 );
}
assert( Vec_IntSize(vTemp) == 2 );
}
int cin = 0;
Vec_WecForEachLevel( vItems, vTemp, i ) {
int i1 = Vec_IntPop(vTemp);
int i0 = Vec_IntPop(vTemp);
assert( i0 >= 0 && i1 >= 0 );
fprintf( pFile, ".subckt FA a=%02d b=%02d cin=%02d s=o%02d cout=%02d\n", i0, i1, cin, i, nItem ); nFAs++;
cin = nItem++;
}
fprintf( pFile, ".end\n\n" );
Abc_WriteFullAdder( pFile );
if ( fUsed )
Abc_WriteMDFA( pFile );
printf( "Created %d-bit %d-input AT with %d FAs, %d HAs, and %d XORs.\n", nBits, Vec_IntSum(vNums), nFAs, nHAs, nXors );
fclose( pFile );
Vec_WecFree( vItems );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////

View File

@ -1411,14 +1411,14 @@ static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine )
Last = k+Last+1;
break;
}
/*
if ( k == nEquals )
{
sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.",
Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) );
return 0;
}
*/
if ( pName2 == NULL )
{
Abc_Obj_t * pNode = Abc_NtkCreateNodeConst0( p->pNtk );

View File

@ -891,7 +891,7 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL
{
Vec_Int_t * vLevel, * vProd;
int i, NodeS, NodeC, LevelS, LevelC, Node1, Node2, Node3, Level1, Level2, Level3;
int nSize = Vec_WecSize(vProds);
int nSize = Vec_WecSize(vProds), nFAs = Vec_WecSize(vProds), nHAs = 0;
assert( nSize == Vec_WecSize(vLevels) );
for ( i = 0; i < nSize; i++ )
{
@ -911,6 +911,12 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL
Level2 = Vec_IntPop( vLevel );
Level3 = Vec_IntPop( vLevel );
int nInputs = (Node1 > 1) + (Node2 > 1) + (Node3 > 1);
if ( nInputs == 3 )
nFAs++;
else if ( nInputs == 2 )
nHAs++;
Wlc_BlastFullAdder( pNew, Node1, Node2, Node3, &NodeC, &NodeS );
LevelS = Abc_MaxInt( Abc_MaxInt(Level1, Level2), Level3 ) + 2;
LevelC = LevelS - 1;
@ -929,7 +935,7 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL
{
vProd = Vec_WecEntry( vProds, i );
while ( Vec_IntSize(vProd) < 2 )
Vec_IntPush( vProd, 0 );
Vec_IntPush( vProd, 0 ), nFAs--, nHAs++;
assert( Vec_IntSize(vProd) == 2 );
}
// Vec_WecPrint( vProds, 0 );
@ -950,6 +956,7 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL
Wlc_BlastAdderCLA( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), Vec_IntSize(vRes), fSigned, 0 );
else
Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), Vec_IntSize(vRes), 0 );
//printf( "Created %d-bit %d-input AT with %d FAs and %d HAs.\n", Vec_WecSize(vProds), Vec_WecSizeSize(vProds), nFAs, nHAs );
}
int Wlc_BlastAddLevel( Gia_Man_t * pNew, int Start )