Commit 3a1705e8 by Alan Mishchenko

Adding option 'gen -b' to generate signed Booth multipliers.

parent 395614a4
......@@ -12406,6 +12406,7 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv )
int fSorter;
int fMesh;
int fMulti;
int fBooth;
int fFpga;
int fOneHot;
int fRandom;
......@@ -12416,6 +12417,7 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv )
extern void Abc_GenSorter( char * pFileName, int nVars );
extern void Abc_GenMesh( char * pFileName, int nVars );
extern void Abc_GenMulti( char * pFileName, int nVars );
extern void Abc_GenBooth( char * pFileName, int nVars );
extern void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars );
extern void Abc_GenOneHot( char * pFileName, int nVars );
extern void Abc_GenRandom( char * pFileName, int nPis );
......@@ -12429,12 +12431,13 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv )
fSorter = 0;
fMesh = 0;
fMulti = 0;
fBooth = 0;
fFpga = 0;
fOneHot = 0;
fRandom = 0;
fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "NAKLabsemftrvh" ) ) != EOF )
while ( ( c = Extra_UtilGetopt( argc, argv, "NAKLatsembfnrvh" ) ) != EOF )
{
switch ( c )
{
......@@ -12485,7 +12488,7 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'a':
fAdder ^= 1;
break;
case 'b':
case 't':
fAdderTree ^= 1;
break;
case 's':
......@@ -12497,10 +12500,13 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'm':
fMulti ^= 1;
break;
case 'b':
fBooth ^= 1;
break;
case 'f':
fFpga ^= 1;
break;
case 't':
case 'n':
fOneHot ^= 1;
break;
case 'r':
......@@ -12535,6 +12541,8 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_GenMesh( FileName, nVars );
else if ( fMulti )
Abc_GenMulti( FileName, nVars );
else if ( fBooth )
Abc_GenBooth( FileName, nVars );
else if ( fFpga )
Abc_GenFpga( FileName, nLutSize, nLuts, nVars );
// Abc_GenFpga( FileName, 2, 2, 3 );
......@@ -12562,19 +12570,20 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
Abc_Print( -2, "usage: gen [-NAKL num] [-asemftrvh] <file>\n" );
Abc_Print( -2, "usage: gen [-NAKL num] [-atsembfnrvh] <file>\n" );
Abc_Print( -2, "\t generates simple circuits\n" );
Abc_Print( -2, "\t-N num : the number of variables [default = %d]\n", nVars );
Abc_Print( -2, "\t-A num : the number of agruments (for adder tree) [default = %d]\n", nArgs );
Abc_Print( -2, "\t-K num : the LUT size (to be used with switch -f) [default = %d]\n", nLutSize );
Abc_Print( -2, "\t-L num : the LUT count (to be used with switch -f) [default = %d]\n", nLuts );
Abc_Print( -2, "\t-a : generate ripple-carry adder [default = %s]\n", fAdder? "yes": "no" );
Abc_Print( -2, "\t-b : generate an adder tree [default = %s]\n", fAdderTree? "yes": "no" );
Abc_Print( -2, "\t-t : generate an adder tree [default = %s]\n", fAdderTree? "yes": "no" );
Abc_Print( -2, "\t-s : generate a sorter [default = %s]\n", fSorter? "yes": "no" );
Abc_Print( -2, "\t-e : generate a mesh [default = %s]\n", fMesh? "yes": "no" );
Abc_Print( -2, "\t-m : generate a multiplier [default = %s]\n", fMulti? "yes": "no" );
Abc_Print( -2, "\t-b : generate a signed Booth multiplier [default = %s]\n", fBooth? "yes": "no" );
Abc_Print( -2, "\t-f : generate a LUT FPGA structure [default = %s]\n", fFpga? "yes": "no" );
Abc_Print( -2, "\t-t : generate one-hotness conditions [default = %s]\n", fOneHot? "yes": "no" );
Abc_Print( -2, "\t-n : generate one-hotness conditions [default = %s]\n", fOneHot? "yes": "no" );
Abc_Print( -2, "\t-r : generate random single-output function [default = %s]\n", fRandom? "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");
......@@ -19,6 +19,7 @@
***********************************************************************/
#include "base/abc/abc.h"
#include "aig/miniaig/miniaig.h"
ABC_NAMESPACE_IMPL_START
......@@ -870,6 +871,276 @@ void Abc_GenAdderTree( char * pFileName, int nArgs, int nBits )
fclose( pFile );
}
/**Function*************************************************************
Synopsis [Generating signed Booth multiplier.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_GenSignedBoothPP( Gia_Man_t * p, int a, int b, int c, int d, int e )
{
/*
abc> lutexact -I 5 -N 7 -g F335ACC0
05 = 4'b0110( d e )
06 = 4'b0110( c d )
07 = 4'b0100( a 06 )
08 = 4'b1000( b 06 )
09 = 4'b0100( 05 07 )
10 = 4'b0110( 08 09 )
11 = 4'b0110( d 10 )
*/
int n05 = Gia_ManHashXor( p, d, e );
int n06 = Gia_ManHashXor( p, c, d );
int n07 = Gia_ManHashAnd( p, a, Abc_LitNot(n06) );
int n08 = Gia_ManHashAnd( p, b, n06 );
int n09 = Gia_ManHashAnd( p, n05, Abc_LitNot(n07) );
int n10 = Gia_ManHashXor( p, n08, n09 );
int n11 = Gia_ManHashXor( p, d, n10 );
return n11;
}
Gia_Man_t * Abc_GenSignedBoothPPTest( int nArgA, int nArgB )
{
Gia_Man_t * pNew; int i, iLit;
pNew = Gia_ManStart( 1000 );
pNew->pName = Abc_UtilStrsav( "booth" );
for ( i = 0; i < 5; i++ )
Gia_ManAppendCi(pNew);
iLit = Abc_GenSignedBoothPP( pNew, 2, 4, 6, 8, 10 );
Gia_ManAppendCo(pNew, iLit);
return pNew;
}
/*
// parametrized implementation of signed Booth multiplier
module booth #(
parameter N = 4 // bit-width of input a
,parameter M = 4 // bit-width of input b
)(
input [N-1:0] a // input data
,input [M-1:0] b // input data
,output [N+M-1:0] z // output data
);
localparam TT = 32'hF335ACC0;
localparam W = N+M+1;
localparam L = (M+1)/2;
wire [W-1:0] data1[L:0];
wire [W-1:0] data2[L:0];
assign data2[0] = data1[0];
assign z = data2[L][N+M-1:0];
wire [N+1:0] a2 = {a[N-1], a, 1'b0};
wire [M+1:0] b2 = {b[M-1], b, 1'b0};
genvar j;
generate
for ( j = 0; j < W; j = j + 1 ) begin : J
assign data1[0][j] = (j%2 == 0 && j/2 < L) ? b2[j+2] : 1'b0;
end
endgenerate
genvar k, i0, i1, i2;
generate
for ( k = 0; k < 2*L; k = k + 2 ) begin : K
for ( i0 = 0; i0 < k; i0 = i0 + 1 ) begin : I0
assign data1[k/2+1][i0] = 1'b0;
end
for ( i1 = 0; i1 <= N; i1 = i1 + 1 ) begin : I1
wire [4:0] in = {b2[k+2], b2[k+1], b2[k], a2[i1+1], a2[i1]};
assign data1[k/2+1][k+i1] = (k > 0 && i1 == N) ? ~TT[in] : TT[in];
end
assign data1[k/2+1][k+N+1] = k > 0 ? 1'b1 : data1[k/2+1][k+N];
for ( i2 = k+N+2; i2 < W; i2 = i2 + 1 ) begin : I2
assign data1[k/2+1][i2] = (k > 0 || i2 > k+N+2)? 1'b0 : ~data1[k/2+1][k+N];
end
assign data2[k/2+1] = data2[k/2] + data1[k/2+1];
end
endgenerate
endmodule
*/
Gia_Man_t * Abc_GenSignedBooth( int nArgN, int nArgM )
{
int nWidth = nArgN + nArgM + 1;
int Length = (nArgM + 1) / 2;
int i, k, iLit;
Vec_Int_t * vPPs = Vec_IntAlloc( nWidth * (Length + 1) );
Vec_Int_t * vArgN = Vec_IntAlloc( nArgN + 2 );
Vec_Int_t * vArgM = Vec_IntAlloc( nArgM + 2 );
int * pArgN = Vec_IntArray( vArgN );
int * pArgM = Vec_IntArray( vArgM );
Gia_Man_t * pTemp, * pNew;
pNew = Gia_ManStart( 1000 );
pNew->pName = Abc_UtilStrsav( "booth" );
Vec_IntPush( vArgN, 0 );
for ( i = 0; i < nArgN; i++ )
Vec_IntPush( vArgN, Gia_ManAppendCi(pNew) );
Vec_IntPush( vArgN, Vec_IntEntryLast(vArgN) );
Vec_IntPush( vArgM, 0 );
for ( i = 0; i < nArgM; i++ )
Vec_IntPush( vArgM, Gia_ManAppendCi(pNew) );
Vec_IntPush( vArgM, Vec_IntEntryLast(vArgM) );
for ( i = 0; i < nWidth; i++ )
Vec_IntPush( vPPs, (i%2 == 0 && i/2 < Length) ? pArgM[i+2] : 0 );
Gia_ManHashAlloc( pNew );
for ( k = 0; k < 2*Length; k += 2 )
{
for ( i = 0; i < k; i++ )
Vec_IntPush( vPPs, 0 );
for ( i = 0; i <= nArgN; i++ )
{
iLit = Abc_GenSignedBoothPP( pNew, pArgN[i], pArgN[i+1], pArgM[k], pArgM[k+1], pArgM[k+2] );
Vec_IntPush( vPPs, Abc_LitNotCond( iLit, k > 0 && i == nArgN ) );
}
iLit = Vec_IntEntryLast(vPPs);
Vec_IntPush( vPPs, k > 0 ? 1 : iLit );
for ( i = k+nArgN+2; i < nWidth; i++ )
Vec_IntPush( vPPs, (k > 0 || i > k+nArgN+2) ? 0 : Abc_LitNot(iLit) );
}
Gia_ManHashStop( pNew );
for ( k = 0; k <= Length; k++ )
for ( i = 0; i < nArgN+nArgM; i++ )
Gia_ManAppendCo( pNew, Vec_IntEntry(vPPs, k*(nArgN+nArgM+1) + i) );
Vec_IntFree( vPPs );
Vec_IntFree( vArgN );
Vec_IntFree( vArgM );
pNew = Gia_ManCleanup( pTemp = pNew );
Gia_ManStop( pTemp );
return pNew;
}
Mini_Aig_t * Abc_GenSignedBoothMini( int nArgN, int nArgM )
{
extern Mini_Aig_t * Gia_ManToMiniAig( Gia_Man_t * pGia );
Gia_Man_t * pGia = Abc_GenSignedBooth( nArgN, nArgM );
Mini_Aig_t * pMini = Gia_ManToMiniAig( pGia );
Gia_ManStop( pGia );
return pMini;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_WriteBoothPartialProducts( FILE * pFile, int nVars )
{
Mini_Aig_t * p = Abc_GenSignedBoothMini( nVars, nVars );
int i, nNodes = Mini_AigNodeNum(p);
int nDigits = Abc_Base10Log( nVars );
int nDigits2 = Abc_Base10Log( 2*nVars );
int nDigits3 = Abc_Base10Log( nNodes );
int nOut = 0;
fprintf( pFile, ".names pp%0*d\n", nDigits3, 0 );
for ( i = 1; i < nNodes; i++ )
{
if ( Mini_AigNodeIsPi( p, i ) )
{
if ( i > 0 && i <= nVars )
fprintf( pFile, ".names a%0*d pp%0*d\n1 1\n", nDigits, i-1, nDigits3, i );
else if ( i > nVars && i <= 2*nVars )
fprintf( pFile, ".names b%0*d pp%0*d\n1 1\n", nDigits, i-1-nVars, nDigits3, i );
else assert( 0 );
}
else if ( Mini_AigNodeIsPo( p, i ) )
{
int Lit = Mini_AigNodeFanin0( p, i );
fprintf( pFile, ".names pp%0*d y%0*d_%0*d\n%d 1\n", nDigits3, Abc_Lit2Var(Lit), nDigits, nOut/(2*nVars), nDigits2, nOut%(2*nVars), !Abc_LitIsCompl(Lit) );
nOut++;
}
else if ( Mini_AigNodeIsAnd( p, i ) )
{
int Lit0 = Mini_AigNodeFanin0( p, i );
int Lit1 = Mini_AigNodeFanin1( p, i );
fprintf( pFile, ".names pp%0*d pp%0*d pp%0*d\n%d%d 1\n",
nDigits3, Abc_Lit2Var(Lit0), nDigits3, Abc_Lit2Var(Lit1), nDigits3, i, !Abc_LitIsCompl(Lit0), !Abc_LitIsCompl(Lit1) );
}
else assert( 0 );
}
Mini_AigStop( p );
}
void Abc_WriteBooth( FILE * pFile, int nVars )
{
int i, k, nDigits = Abc_Base10Log( nVars ), nDigits2 = Abc_Base10Log( 2*nVars );
int Length = 1+(nVars + 1)/2;
assert( nVars > 0 );
fprintf( pFile, ".model Multi%d\n", nVars );
fprintf( pFile, ".inputs" );
for ( i = 0; i < nVars; i++ )
fprintf( pFile, " a%0*d", nDigits, i );
for ( i = 0; i < nVars; i++ )
fprintf( pFile, " b%0*d", nDigits, i );
fprintf( pFile, "\n" );
fprintf( pFile, ".outputs" );
for ( i = 0; i < 2*nVars; i++ )
fprintf( pFile, " m%0*d", nDigits2, i );
fprintf( pFile, "\n" );
Abc_WriteBoothPartialProducts( pFile, nVars );
for ( i = 0; i < 2*nVars; i++ )
fprintf( pFile, ".names x%0*d_%0*d\n", nDigits, 0, nDigits2, i );
for ( k = 0; k < Length; k++ )
{
fprintf( pFile, ".subckt ADD%d", 2*nVars );
for ( i = 0; i < 2*nVars; i++ )
fprintf( pFile, " a%0*d=x%0*d_%0*d", nDigits2, i, nDigits, k, nDigits2, i );
for ( i = 0; i < 2*nVars; i++ )
fprintf( pFile, " b%0*d=y%0*d_%0*d", nDigits2, i, nDigits, k, nDigits2, i );
for ( i = 0; i <= 2*nVars; i++ )
fprintf( pFile, " s%0*d=x%0*d_%0*d", nDigits2, i, nDigits, k+1, nDigits2, i );
fprintf( pFile, "\n" );
}
for ( i = 0; i < 2 * nVars; i++ )
fprintf( pFile, ".names x%0*d_%0*d m%0*d\n1 1\n", nDigits, k, nDigits2, i, nDigits2, i );
fprintf( pFile, ".end\n" );
fprintf( pFile, "\n" );
Abc_WriteAdder( pFile, 2*nVars );
}
void Abc_GenBooth( char * pFileName, int nVars )
{
FILE * pFile;
assert( nVars > 0 );
pFile = fopen( pFileName, "w" );
fprintf( pFile, "# %d-bit signed Booth multiplier generated by ABC on %s\n", nVars, Extra_TimeStamp() );
Abc_WriteBooth( pFile, nVars );
fclose( pFile );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment