summaryrefslogtreecommitdiffstats
path: root/src/base/wlc
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/wlc')
-rw-r--r--src/base/wlc/wlc.h9
-rw-r--r--src/base/wlc/wlcBlast.c617
-rw-r--r--src/base/wlc/wlcCom.c151
-rw-r--r--src/base/wlc/wlcMem.c129
-rw-r--r--src/base/wlc/wlcNdr.c8
-rw-r--r--src/base/wlc/wlcNtk.c35
-rw-r--r--src/base/wlc/wlcReadVer.c22
-rw-r--r--src/base/wlc/wlcWriteVer.c73
8 files changed, 986 insertions, 58 deletions
diff --git a/src/base/wlc/wlc.h b/src/base/wlc/wlc.h
index 02921722..3a84031e 100644
--- a/src/base/wlc/wlc.h
+++ b/src/base/wlc/wlc.h
@@ -100,7 +100,8 @@ typedef enum {
WLC_OBJ_WRITE, // 55: write port
WLC_OBJ_ARI_ADDSUB, // 56: adder-subtractor
WLC_OBJ_SEL, // 57: positionally encoded selector
- WLC_OBJ_NUMBER // 57: unused
+ WLC_OBJ_DEC, // 58: decoder
+ WLC_OBJ_NUMBER // 59: unused
} Wlc_ObjType_t;
// when adding new types, remember to update table Wlc_Names in "wlcNtk.c"
@@ -139,6 +140,7 @@ struct Wlc_Ntk_t_
Vec_Int_t vCis; // combinational inputs
Vec_Int_t vCos; // combinational outputs
Vec_Int_t vFfs; // flops
+ Vec_Int_t vFfs2; // flops
Vec_Int_t * vInits; // initial values
char * pInits; // initial values
int nObjs[WLC_OBJ_NUMBER]; // counter of objects of each type
@@ -208,6 +210,7 @@ struct Wlc_BstPar_t_
int fAddOutputs;
int fMulti;
int fBooth;
+ int fCla;
int fNoCleanup;
int fCreateMiter;
int fDecMuxes;
@@ -226,6 +229,7 @@ static inline void Wlc_BstParDefault( Wlc_BstPar_t * pPar )
pPar->fAddOutputs = 0;
pPar->fMulti = 0;
pPar->fBooth = 0;
+ pPar->fCla = 0;
pPar->fCreateMiter = 0;
pPar->fDecMuxes = 0;
pPar->fVerbose = 0;
@@ -272,6 +276,7 @@ static inline Wlc_Obj_t * Wlc_NtkPo( Wlc_Ntk_t * p, int i )
static inline Wlc_Obj_t * Wlc_NtkCi( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vCis, i) ); }
static inline Wlc_Obj_t * Wlc_NtkCo( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vCos, i) ); }
static inline Wlc_Obj_t * Wlc_NtkFf( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vFfs, i) ); }
+static inline Wlc_Obj_t * Wlc_NtkFf2( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vFfs2, i) ); }
static inline int Wlc_ObjIsPi( Wlc_Obj_t * p ) { return p->Type == WLC_OBJ_PI; }
static inline int Wlc_ObjIsPo( Wlc_Obj_t * p ) { return p->fIsPo; }
@@ -347,6 +352,8 @@ static inline Wlc_Obj_t * Wlc_ObjCo2PoFo( Wlc_Ntk_t * p, int iCoId )
for ( i = 0; (i < Wlc_NtkCoNum(p)) && (((pCo) = Wlc_NtkCo(p, i)), 1); i++ )
#define Wlc_NtkForEachFf( p, pFf, i ) \
for ( i = 0; (i < Vec_IntSize(&p->vFfs)) && (((pFf) = Wlc_NtkFf(p, i)), 1); i++ )
+#define Wlc_NtkForEachFf2( p, pFf, i ) \
+ for ( i = 0; (i < Vec_IntSize(&p->vFfs2)) && (((pFf) = Wlc_NtkFf2(p, i)), 1); i++ )
#define Wlc_ObjForEachFanin( pObj, iFanin, i ) \
for ( i = 0; (i < Wlc_ObjFaninNum(pObj)) && (((iFanin) = Wlc_ObjFaninId(pObj, i)), 1); i++ )
diff --git a/src/base/wlc/wlcBlast.c b/src/base/wlc/wlcBlast.c
index b97dfdad..e4088f9c 100644
--- a/src/base/wlc/wlcBlast.c
+++ b/src/base/wlc/wlcBlast.c
@@ -131,6 +131,12 @@ int Wlc_NtkMuxTree2( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData
Vec_IntPush( vTemp, Abc_LitNot( Gia_ManHashAnd(pNew, iLit, Vec_IntEntry(vData, m)) ) );
return Abc_LitNot( Gia_ManHashAndMulti(pNew, vTemp) );
}
+void Wlc_NtkPrintNameArray( Vec_Ptr_t * vNames )
+{
+ int i; char * pTemp;
+ Vec_PtrForEachEntry( char *, vNames, pTemp, i )
+ printf( "%2d : %s\n", i, pTemp );
+}
/**Function*************************************************************
@@ -345,9 +351,9 @@ void Wlc_BlastAdder( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int
for ( b = 0; b < nBits; b++ )
Wlc_BlastFullAdder( pNew, pAdd0[b], pAdd1[b], Carry, &Carry, &pAdd0[b] );
}
-void Wlc_BlastSubtract( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits ) // result is in pAdd0
+void Wlc_BlastSubtract( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int Carry ) // result is in pAdd0
{
- int b, Carry = 1;
+ int b;
for ( b = 0; b < nBits; b++ )
Wlc_BlastFullAdder( pNew, pAdd0[b], Abc_LitNot(pAdd1[b]), Carry, &Carry, &pAdd0[b] );
}
@@ -375,7 +381,7 @@ void Wlc_BlastAdderCLA_rec( Gia_Man_t * pNew, int * pGen, int * pPro, int * pCar
Wlc_BlastAdderCLA_one( pNew, pGen2, pPro2, pCar, pGen1, pPro1, pCar+nBits/2 ); // returns *pGen1, *pPro1, pCar[nBits/2]
}
}
-void Wlc_BlastAdderCLA( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits ) // result is in pAdd0
+void Wlc_BlastAdderCLA_int( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int CarryIn ) // result is in pAdd0
{
int * pGen = ABC_CALLOC( int, nBits );
int * pPro = ABC_CALLOC( int, nBits );
@@ -383,12 +389,12 @@ void Wlc_BlastAdderCLA( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits )
int b, Gen, Pro;
if ( nBits == 1 )
{
- int Carry = 0;
+ int Carry = CarryIn;
Wlc_BlastFullAdder( pNew, pAdd0[0], pAdd1[0], Carry, &Carry, &pAdd0[0] );
return;
}
assert( nBits >= 2 );
- pCar[0] = 0;
+ pCar[0] = CarryIn;
for ( b = 0; b < nBits; b++ )
{
pGen[b] = Gia_ManHashAnd(pNew, pAdd0[b], pAdd1[b]);
@@ -401,6 +407,117 @@ void Wlc_BlastAdderCLA( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits )
ABC_FREE(pPro);
ABC_FREE(pCar);
}
+void Wlc_BlastAdderCLA( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int fSign, int CarryIn ) // result is in pAdd0
+{
+ int i, Log2 = Abc_Base2Log(nBits);
+ int * pAdd0n = ABC_CALLOC( int, 1<<Log2 );
+ int * pAdd1n = ABC_CALLOC( int, 1<<Log2 );
+ for ( i = 0; i < nBits; i++ )
+ {
+ pAdd0n[i] = pAdd0[i];
+ pAdd1n[i] = pAdd1[i];
+ }
+ for ( ; i < (1<<Log2); i++ )
+ {
+ pAdd0n[i] = fSign ? pAdd0[nBits-1] : 0;
+ pAdd1n[i] = fSign ? pAdd1[nBits-1] : 0;
+ }
+ Wlc_BlastAdderCLA_int( pNew, pAdd0n, pAdd1n, 1<<Log2, CarryIn );
+ for ( i = 0; i < nBits; i++ )
+ pAdd0[i] = pAdd0n[i];
+ ABC_FREE(pAdd0n);
+ ABC_FREE(pAdd1n);
+}
+
+void Wlc_BlastAdderFast_int( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int Log2, int CarryIn ) // result is in pAdd0
+{
+ int i, b, Gen, Pro, nBits = 1 << Log2;
+ int * pGen = ABC_CALLOC( int, nBits+1 );
+ int * pPro = ABC_CALLOC( int, nBits+1 );
+ int * pPro2= ABC_CALLOC( int, nBits+1 );
+ if ( nBits == 1 )
+ {
+ int Carry = CarryIn;
+ Wlc_BlastFullAdder( pNew, pAdd0[0], pAdd1[0], Carry, &Carry, &pAdd0[0] );
+ ABC_FREE(pGen);
+ ABC_FREE(pPro);
+ ABC_FREE(pPro2);
+ return;
+ }
+ assert( nBits >= 2 );
+ pGen[0] = CarryIn;
+ pPro[0] = 0;
+ pPro2[0]= 0;
+ for ( b = 1; b <= nBits; b++ )
+ {
+ pGen[b] = Gia_ManHashAnd(pNew, pAdd0[b-1], pAdd1[b-1]);
+ pPro[b] = Gia_ManHashXor(pNew, pAdd0[b-1], pAdd1[b-1]);
+ pPro2[b]= pPro[b];
+ }
+
+ // Han-Carlson adder from http://www.aoki.ecei.tohoku.ac.jp/arith/mg/algorithm.html
+ for ( b = 1; b <= nBits; b += 2 )
+ {
+ Gen = Gia_ManHashOr( pNew, pGen[b], Gia_ManHashAnd(pNew, pPro[b], pGen[b-1]) );
+ Pro = Gia_ManHashAnd(pNew, pPro[b], pPro[b-1]);
+ pPro[b] = Pro;
+ pGen[b] = Gen;
+ }
+ for ( i = 1; i < Log2-1; i++ )
+ {
+ for ( b = 1 + 2*i; b <= nBits; b += 2 )
+ {
+ Gen = Gia_ManHashOr( pNew, pGen[b], Gia_ManHashAnd(pNew, pPro[b], pGen[b-i*2]) );
+ Pro = Gia_ManHashAnd(pNew, pPro[b], pPro[b-i*2]);
+ pPro[b] = Pro;
+ pGen[b] = Gen;
+ }
+ }
+ for ( b = nBits/2 + 1; b <= nBits; b += 2 )
+ {
+ Gen = Gia_ManHashOr( pNew, pGen[b], Gia_ManHashAnd(pNew, pPro[b], pGen[b-nBits/2]) );
+ Pro = Gia_ManHashAnd(pNew, pPro[b], pPro[b-nBits/2]);
+ pPro[b] = Pro;
+ pGen[b] = Gen;
+ }
+ for ( b = 2; b <= nBits; b += 2 )
+ {
+ Gen = Gia_ManHashOr( pNew, pGen[b], Gia_ManHashAnd(pNew, pPro[b], pGen[b-1]) );
+ Pro = Gia_ManHashAnd(pNew, pPro[b], pPro[b-1]);
+ pPro[b] = Pro;
+ pGen[b] = Gen;
+ }
+
+ for ( b = 0; b < nBits; b++ )
+ pAdd0[b] = Gia_ManHashXor(pNew, pPro2[b+1], pGen[b]);
+ pAdd0[nBits] = pGen[nBits];
+
+ ABC_FREE(pGen);
+ ABC_FREE(pPro);
+ ABC_FREE(pPro2);
+}
+void Wlc_BlastAdderFast( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits, int fSign, int CarryIn ) // result is in pAdd0
+{
+ int i, Log2 = Abc_Base2Log(nBits);
+ int * pAdd0n = ABC_CALLOC( int, (1<<Log2)+1 );
+ int * pAdd1n = ABC_CALLOC( int, (1<<Log2)+1 );
+ for ( i = 0; i < nBits; i++ )
+ {
+ pAdd0n[i] = pAdd0[i];
+ pAdd1n[i] = pAdd1[i];
+ }
+ for ( ; i < (1<<Log2); i++ )
+ {
+ pAdd0n[i] = fSign ? pAdd0[nBits-1] : 0;
+ pAdd1n[i] = fSign ? pAdd1[nBits-1] : 0;
+ }
+ Wlc_BlastAdderFast_int( pNew, pAdd0n, pAdd1n, Log2, CarryIn );
+ for ( i = 0; i <= nBits; i++ )
+ pAdd0[i] = pAdd0n[i];
+ ABC_FREE(pAdd0n);
+ ABC_FREE(pAdd1n);
+}
+
void Wlc_BlastMinus( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vRes )
{
int * pRes = Wlc_VecCopy( vRes, pNum, nNum );
@@ -700,7 +817,7 @@ void Wlc_BlastPrintMatrix( Gia_Man_t * p, Vec_Wec_t * vProds )
Vec_IntFree( vSupp );
Vec_WrdFree( vTemp );
}
-void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vLevels, Vec_Int_t * vRes )
+void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vLevels, Vec_Int_t * vRes, int fSigned, int fCla )
{
Vec_Int_t * vLevel, * vProd;
int i, NodeS, NodeC, LevelS, LevelC, Node1, Node2, Node3, Level1, Level2, Level3;
@@ -758,9 +875,112 @@ void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vL
}
Vec_IntPush( vRes, 0 );
Vec_IntPush( vLevel, 0 );
- Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), Vec_IntSize(vRes), 0 );
+
+ if ( fCla )
+ 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 );
+}
+
+int Wlc_BlastAddLevel( Gia_Man_t * pNew, int Start )
+{
+ int i;
+ if ( Start == 0 )
+ Gia_ManCleanLevels( pNew, 5 * Gia_ManObjNum(pNew) );
+ for ( i = Start; i < Gia_ManObjNum(pNew); i++ )
+ {
+ Gia_Obj_t * pObj = Gia_ManObj( pNew, i );
+ if ( Gia_ObjIsAnd(pObj) )
+ Gia_ObjSetAndLevel( pNew, pObj );
+ }
+ return Gia_ManObjNum(pNew);
+}
+void Wlc_IntInsert2( Gia_Man_t * pNew, Vec_Int_t * vProd, int iLit )
+{
+ int i, Entry, Level = Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit));
+ Vec_IntForEachEntryReverse( vProd, Entry, i )
+ if ( Gia_ObjLevelId(pNew, Abc_Lit2Var(Entry)) >= Level )
+ break;
+ Vec_IntInsert( vProd, i + 1, iLit );
+// Vec_IntForEachEntry( vProd, Entry, i )
+// printf( "Obj=%d(%d) ", Abc_Lit2Var(Entry), Gia_ObjLevelId(pNew, Abc_Lit2Var(Entry)) );
+// printf( "\n" );
+}
+void Wlc_IntSortCostReverse( Gia_Man_t * pNew, int * pArray, int nSize )
+{
+ int i, j, best_i;
+ for ( i = 0; i < nSize-1; i++ )
+ {
+ best_i = i;
+ for ( j = i+1; j < nSize; j++ )
+ if ( Gia_ObjLevelId(pNew, Abc_Lit2Var(pArray[j])) > Gia_ObjLevelId(pNew, Abc_Lit2Var(pArray[best_i])) )
+ best_i = j;
+ ABC_SWAP( int, pArray[i], pArray[best_i] );
+ }
+}
+void Wlc_BlastReduceMatrix2( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Int_t * vRes, int fSigned, int fCla )
+{
+ Vec_Int_t * vProd, * vTemp;
+ int i, NodeS, NodeC, Node1, Node2, Node3;
+ int Start = Wlc_BlastAddLevel( pNew, 0 );
+ int nSize = Vec_WecSize(vProds);
+ Vec_WecForEachLevel( vProds, vProd, i )
+ Wlc_IntSortCostReverse( pNew, Vec_IntArray(vProd), Vec_IntSize(vProd) );
+ for ( i = 0; i < nSize; i++ )
+ {
+ while ( 1 )
+ {
+ vProd = Vec_WecEntry( vProds, i );
+ if ( Vec_IntSize(vProd) < 3 )
+ break;
+
+ Node1 = Vec_IntPop( vProd );
+ Node2 = Vec_IntPop( vProd );
+ Node3 = Vec_IntPop( vProd );
+
+ assert( Gia_ObjLevelId(pNew, Abc_Lit2Var(Node3)) >= Gia_ObjLevelId(pNew, Abc_Lit2Var(Node2)) );
+ assert( Gia_ObjLevelId(pNew, Abc_Lit2Var(Node2)) >= Gia_ObjLevelId(pNew, Abc_Lit2Var(Node1)) );
+
+ Wlc_BlastFullAdder( pNew, Node1, Node2, Node3, &NodeC, &NodeS );
+ Start = Wlc_BlastAddLevel( pNew, Start );
+
+ Wlc_IntInsert2( pNew, vProd, NodeS );
+
+ vProd = Vec_WecEntry( vProds, i+1 );
+ Wlc_IntInsert2( pNew, vProd, NodeC );
+ }
+ }
+
+ // make all ranks have two products
+ for ( i = 0; i < nSize; i++ )
+ {
+ vProd = Vec_WecEntry( vProds, i );
+ while ( Vec_IntSize(vProd) < 2 )
+ Vec_IntPush( vProd, 0 );
+ assert( Vec_IntSize(vProd) == 2 );
+ }
+// Vec_WecPrint( vProds, 0 );
+
+ Vec_IntClear( vRes );
+ vTemp = Vec_IntAlloc( 100 );
+ for ( i = 0; i < nSize; i++ )
+ {
+ vProd = Vec_WecEntry( vProds, i );
+ Vec_IntPush( vRes, Vec_IntEntry(vProd, 0) );
+ Vec_IntPush( vTemp, Vec_IntEntry(vProd, 1) );
+ }
+ Vec_IntPush( vRes, 0 );
+ Vec_IntPush( vTemp, 0 );
+
+ if ( fCla )
+ Wlc_BlastAdderCLA( pNew, Vec_IntArray(vRes), Vec_IntArray(vTemp), Vec_IntSize(vRes), fSigned, 0 );
+ else
+ Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vTemp), Vec_IntSize(vRes), 0 );
+ Vec_IntFree( vTemp );
}
-void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes )
+
+
+void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla )
{
Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB );
Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB );
@@ -768,11 +988,21 @@ void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA
for ( i = 0; i < nArgA; i++ )
for ( k = 0; k < nArgB; k++ )
{
- Vec_WecPush( vProds, i+k, Gia_ManHashAnd(pNew, pArgA[i], pArgB[k]) );
+ int fCompl = fSigned && ((i == nArgA-1) ^ (k == nArgB-1));
+ Vec_WecPush( vProds, i+k, Abc_LitNotCond(Gia_ManHashAnd(pNew, pArgA[i], pArgB[k]), fCompl) );
Vec_WecPush( vLevels, i+k, 0 );
}
+ if ( fSigned )
+ {
+ Vec_WecPush( vProds, nArgA, 1 );
+ Vec_WecPush( vLevels, nArgA, 0 );
+
+ Vec_WecPush( vProds, nArgA+nArgB-1, 1 );
+ Vec_WecPush( vLevels, nArgA+nArgB-1, 0 );
+ }
- Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes );
+ Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes, fSigned, fCla );
+// Wlc_BlastReduceMatrix2( pNew, vProds, vRes, fSigned, fCla );
Vec_WecFree( vProds );
Vec_WecFree( vLevels );
@@ -797,12 +1027,24 @@ void Wlc_BlastSquare( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp,
}
}
- Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes );
+ Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes, 0, 0 );
Vec_WecFree( vProds );
Vec_WecFree( vLevels );
}
-void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned )
+void Wlc_BlastDecoder( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, Vec_Int_t * vRes )
+{
+ int i, k, nMints = 1 << nNum;
+ Vec_IntClear( vRes );
+ for ( i = 0; i < nMints; i++ )
+ {
+ int iMint = 1;
+ for ( k = 0; k < nNum; k++ )
+ iMint = Gia_ManHashAnd( pNew, iMint, Abc_LitNotCond(pNum[k], !((i >> k) & 1)) );
+ Vec_IntPush( vRes, iMint );
+ }
+}
+void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned, int fCla )
{
Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB + 3 );
Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB + 3 );
@@ -871,7 +1113,8 @@ void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int
//Vec_WecPrint( vProds, 0 );
//Wlc_BlastPrintMatrix( pNew, vProds );
//printf( "Cutoff ID for partial products = %d.\n", Gia_ManObjNum(pNew) );
- Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes );
+ Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes, fSigned, fCla );
+// Wlc_BlastReduceMatrix2( pNew, vProds, vRes, fSigned, fCla );
Vec_WecFree( vProds );
Vec_WecFree( vLevels );
@@ -897,13 +1140,15 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
Tim_Man_t * pManTime = NULL;
If_LibBox_t * pBoxLib = NULL;
Vec_Ptr_t * vTables = NULL;
+ Vec_Int_t * vFf2Ci = Vec_IntAlloc( 100 );
+ Vec_Int_t * vRegClasses = NULL;
Gia_Man_t * pTemp, * pNew, * pExtra = NULL;
Wlc_Obj_t * pObj, * pObj2;
Vec_Int_t * vBits = &p->vBits, * vTemp0, * vTemp1, * vTemp2, * vRes, * vAddOutputs = NULL, * vAddObjs = NULL;
int nBits = Wlc_NtkPrepareBits( p );
- int nRange, nRange0, nRange1, nRange2;
- int i, k, b, iFanin, iLit, nAndPrev, * pFans0, * pFans1, * pFans2;
- int nFFins = 0, nFFouts = 0, curPi = 0, curPo = 0;
+ int nRange, nRange0, nRange1, nRange2, nRange3;
+ int i, k, b, iFanin, iLit, nAndPrev, * pFans0, * pFans1, * pFans2, * pFans3;
+ int nFFins = 0, nFFouts = 0, curPi = 0, curPo = 0, nFf2Regs = 0;
int nBitCis = 0, nBitCos = 0, fAdded = 0;
Wlc_BstPar_t Par, * pPar = &Par;
Wlc_BstParDefault( pPar );
@@ -930,6 +1175,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
if ( pPar->vBoxIds )
{
int nNewCis = 0, nNewCos = 0;
+ assert( Vec_IntSize(&p->vFfs2) == 0 );
Wlc_NtkForEachObj( p, pObj, i )
pObj->Mark = 0;
// count bit-width of regular CIs/COs
@@ -961,6 +1207,61 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
// create box library
pBoxLib = If_LibBoxStart();
}
+ if ( Vec_IntSize(&p->vFfs2) > 0 )
+ {
+ Vec_Int_t * vSignature;
+ int nNewCis = 0, nNewCos = 0;
+ assert( pPar->vBoxIds == 0 );
+ // count bit-width of regular CIs/COs
+ Wlc_NtkForEachCi( p, pObj, i )
+ nBitCis += Wlc_ObjRange( pObj );
+ Wlc_NtkForEachCo( p, pObj, i )
+ nBitCos += Wlc_ObjRange( pObj );
+ // count bit-width of additional CIs/COs due to selected multipliers
+ Wlc_NtkForEachFf2( p, pObj, i )
+ {
+ // currently works only for multipliers
+ assert( pObj->Type == WLC_OBJ_FF );
+ assert( Wlc_ObjRange(pObj) == Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) );
+ nNewCis += Wlc_ObjRange(pObj);
+ nNewCos += 2*Wlc_ObjRange(pObj) + 3;
+ nFf2Regs+= Wlc_ObjRange(pObj);
+ }
+ // create hierarchy manager
+ pManTime = Tim_ManStart( nBitCis + nNewCis + nFf2Regs, nBitCos + nNewCos + nFf2Regs );
+ curPi = nBitCis + nFf2Regs;
+ curPo = 0;
+ // create AIG manager for logic of the boxes
+ pExtra = Gia_ManStart( Wlc_NtkObjNum(p) );
+ Gia_ManHashAlloc( pExtra );
+ assert( !pPar->fGiaSimple );
+ // create register classes
+ vRegClasses = Vec_IntAlloc(0);
+ vSignature = Vec_IntAlloc( 100 );
+ Vec_IntPushTwo( vSignature, -1, -1 );
+ Wlc_NtkForEachFf2( p, pObj, i )
+ {
+ int iClk0, iClk = Wlc_ObjFaninId( pObj, 1 );
+ int iAsyn0, iAsyn = Wlc_ObjFaninId( pObj, 5 );
+ nRange = Wlc_ObjRange(pObj);
+ Vec_IntForEachEntryDouble( vSignature, iClk0, iAsyn0, k )
+ if ( iClk == iClk0 && iAsyn == iAsyn0 )
+ {
+ for ( b = 0; b < nRange; b++ )
+ Vec_IntPush( vRegClasses, k/2 );
+ break;
+ }
+ if ( k < Vec_IntSize(vSignature) )
+ continue;
+ for ( b = 0; b < nRange; b++ )
+ Vec_IntPush( vRegClasses, k/2 );
+ Vec_IntPushTwo( vSignature, iClk, iAsyn );
+ }
+ assert( Vec_IntSize(vRegClasses) == nFf2Regs );
+ Vec_IntFree( vSignature );
+ // create box library
+ pBoxLib = If_LibBoxStart();
+ }
// blast in the topological order
Wlc_NtkForEachObj( p, pObj, i )
{
@@ -972,9 +1273,11 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
nRange0 = Wlc_ObjFaninNum(pObj) > 0 ? Wlc_ObjRange( Wlc_ObjFanin0(p, pObj) ) : -1;
nRange1 = Wlc_ObjFaninNum(pObj) > 1 ? Wlc_ObjRange( Wlc_ObjFanin1(p, pObj) ) : -1;
nRange2 = Wlc_ObjFaninNum(pObj) > 2 ? Wlc_ObjRange( Wlc_ObjFanin2(p, pObj) ) : -1;
- pFans0 = Wlc_ObjFaninNum(pObj) > 0 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId0(pObj)) ) : NULL;
- pFans1 = Wlc_ObjFaninNum(pObj) > 1 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId1(pObj)) ) : NULL;
- pFans2 = Wlc_ObjFaninNum(pObj) > 2 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId2(pObj)) ) : NULL;
+ nRange3 = Wlc_ObjFaninNum(pObj) > 3 ? Wlc_ObjRange( Wlc_ObjFanin(p, pObj, 3) ) : -1;
+ pFans0 = pObj->Type != WLC_OBJ_FF && Wlc_ObjFaninNum(pObj) > 0 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId0(pObj)) ) : NULL;
+ pFans1 = pObj->Type != WLC_OBJ_FF && Wlc_ObjFaninNum(pObj) > 1 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId1(pObj)) ) : NULL;
+ pFans2 = pObj->Type != WLC_OBJ_FF && Wlc_ObjFaninNum(pObj) > 2 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId2(pObj)) ) : NULL;
+ pFans3 = pObj->Type != WLC_OBJ_FF && Wlc_ObjFaninNum(pObj) > 3 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId(pObj,3)) ) : NULL;
Vec_IntClear( vRes );
assert( nRange > 0 );
if ( pPar->vBoxIds && pObj->Mark )
@@ -1043,7 +1346,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
if ( pObj->Type == WLC_OBJ_ARI_ADD )
Wlc_BlastAdder( pExtra, pArg0, pArg1, nRange, CarryIn ); // result is in pFan0 (vRes)
else
- Wlc_BlastSubtract( pExtra, pArg0, pArg1, nRange ); // result is in pFan0 (vRes)
+ Wlc_BlastSubtract( pExtra, pArg0, pArg1, nRange, 1 ); // result is in pFan0 (vRes)
Vec_IntShrink( vRes, nRange );
}
else if ( fUseOldMultiplierBlasting )
@@ -1078,13 +1381,15 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
// add box to the library
sprintf( Buffer, "%s%03d", pObj->Type == WLC_OBJ_ARI_ADD ? "add":"mul", 1+If_LibBoxNum(pBoxLib) );
- pBox = If_BoxStart( Abc_UtilStrsav(Buffer), 1+If_LibBoxNum(pBoxLib), nRange, nRange0 + nRange1 + nRange2, 0, 0, 0 );
+ pBox = If_BoxStart( Abc_UtilStrsav(Buffer), 1+If_LibBoxNum(pBoxLib), nRange0 + nRange1 + nRange2, nRange, 0, 0, 0 );
If_LibBoxAdd( pBoxLib, pBox );
for ( k = 0; k < pBox->nPis * pBox->nPos; k++ )
pBox->pDelays[k] = 1;
}
- else if ( Wlc_ObjIsCi(pObj) )
+ else if ( Wlc_ObjIsCi(pObj) || pObj->Type == WLC_OBJ_FF ) // assuming that FFs are ordered immediately after PIs
{
+ if ( pObj->Type == WLC_OBJ_FF )
+ Vec_IntPush( vFf2Ci, Gia_ManCiNum(pNew) );
if ( Wlc_ObjRangeIsReversed(pObj) )
{
for ( k = 0; k < nRange; k++ )
@@ -1099,6 +1404,10 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
}
if ( pObj->Type == WLC_OBJ_FO )
nFFouts += Vec_IntSize(vRes);
+ if ( pObj->Type == WLC_OBJ_FF )
+ {
+ // complement flop output whose init state is 1
+ }
}
else if ( pObj->Type == WLC_OBJ_BUF )
{
@@ -1391,12 +1700,31 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) );
int CarryIn = Wlc_ObjFaninNum(pObj) == 3 ? pFans2[0] : 0;
if ( pObj->Type == WLC_OBJ_ARI_ADD )
- Wlc_BlastAdder( pNew, pArg0, pArg1, nRange, CarryIn ); // result is in pFan0 (vRes)
-// Wlc_BlastAdderCLA( pNew, pArg0, pArg1, nRange ); // result is in pFan0 (vRes)
+ {
+ if ( pPar->fCla )
+ Wlc_BlastAdderCLA( pNew, pArg0, pArg1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj), CarryIn ); // result is in pFan0 (vRes)
+ //Wlc_BlastAdderFast( pNew, pArg0, pArg1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj), CarryIn ); // result is in pFan0 (vRes)
+ else
+ Wlc_BlastAdder( pNew, pArg0, pArg1, nRangeMax, CarryIn ); // result is in pFan0 (vRes)
+ }
else
- Wlc_BlastSubtract( pNew, pArg0, pArg1, nRange ); // result is in pFan0 (vRes)
+ Wlc_BlastSubtract( pNew, pArg0, pArg1, nRange, 1 ); // result is in pFan0 (vRes)
Vec_IntShrink( vRes, nRange );
}
+ else if ( pObj->Type == WLC_OBJ_ARI_ADDSUB )
+ {
+ int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange2, nRange3) );
+ int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans2, nRange2, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) );
+ int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans2, nRange2, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) );
+ int * pArg2 = Wlc_VecLoadFanins( vTemp2, pFans3, nRange3, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) );
+ int ModeIn = pFans0[0];
+ int CarryIn = pFans1[0]; int j;
+ Wlc_BlastAdder ( pNew, pArg0, pArg2, nRangeMax, CarryIn ); // result is in pArg0 (vTemp0)
+ Wlc_BlastSubtract( pNew, pArg1, pArg2, nRangeMax, Abc_LitNot(CarryIn) ); // result is in pArg1 (vTemp1)
+ Vec_IntClear( vRes );
+ for ( j = 0; j < nRange; j++ )
+ Vec_IntPush( vRes, Gia_ManHashMux(pNew, ModeIn, pArg0[j], pArg1[j]) );
+ }
else if ( pObj->Type == WLC_OBJ_ARI_MULTI )
{
if ( fUseOldMultiplierBlasting )
@@ -1416,10 +1744,11 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
if ( Wlc_NtkCountConstBits(pArg0, nRangeMax) < Wlc_NtkCountConstBits(pArg1, nRangeMax) )
ABC_SWAP( int *, pArg0, pArg1 );
if ( pPar->fBooth )
- Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned );
+ Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned, pPar->fCla );
+ else if ( pPar->fCla )
+ Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes, Wlc_ObjIsSignedFanin01(p, pObj), pPar->fCla );
else
Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned );
- //Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes );
if ( nRange > Vec_IntSize(vRes) )
Vec_IntFillExtra( vRes, nRange, fSigned ? Vec_IntEntryLast(vRes) : 0 );
else
@@ -1475,6 +1804,15 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
else
Vec_IntShrink( vRes, nRange );
}
+ else if ( pObj->Type == WLC_OBJ_DEC )
+ {
+ int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRange0, 0 );
+ Wlc_BlastDecoder( pNew, pArg0, nRange0, vTemp2, vRes );
+ if ( nRange > Vec_IntSize(vRes) )
+ Vec_IntFillExtra( vRes, nRange, 0 );
+ else
+ Vec_IntShrink( vRes, nRange );
+ }
else if ( pObj->Type == WLC_OBJ_TABLE )
Wlc_BlastTable( pNew, Wlc_ObjTable(p, pObj), pFans0, nRange0, nRange, vRes );
else assert( 0 );
@@ -1499,6 +1837,102 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
Vec_IntFree( vTemp1 );
Vec_IntFree( vTemp2 );
Vec_IntFree( vRes );
+ // create flop boxes
+ Wlc_NtkForEachFf2( p, pObj, i )
+ {
+ If_Box_t * pBox;
+ char Buffer[100];
+ float * pTable;
+ Vec_Int_t * vTemp0 = Vec_IntAlloc( 100 );
+ Vec_Int_t * vTemp1 = Vec_IntAlloc( 100 );
+ int iLit, nRange = Wlc_ObjRange(pObj);
+ int * pFans0, * pFans1, * pFans2, * pFans3;
+ int iReset, iSet, iEnable;
+ int nRangeIn = 2*nRange + 3; // D, reset, set, enable, Q
+ int iSre = Wlc_ObjFaninId(pObj, 6);
+
+ assert( pObj->Type == WLC_OBJ_FF );
+
+ // create new box
+ if ( vTables == NULL )
+ Tim_ManSetDelayTables( pManTime, (vTables = Vec_PtrAlloc(100)) );
+ Tim_ManCreateBox( pManTime, curPo, nRangeIn, curPi, nRange, Vec_PtrSize(vTables), 0 );
+ curPi += nRange;
+ curPo += nRangeIn;
+
+ // create delay table
+ pTable = ABC_ALLOC( float, 3 + nRange * nRangeIn );
+ pTable[0] = Vec_PtrSize(vTables);
+ pTable[1] = nRangeIn;
+ pTable[2] = nRange;
+ for ( k = 0; k < nRange * nRangeIn; k++ )
+ pTable[3 + k] = 1.0;
+ Vec_PtrPush( vTables, pTable );
+
+ // create combinational outputs in the normal manager
+ pFans0 = Wlc_ObjFaninNum(pObj) > 0 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId0(pObj)) ) : NULL;
+ pFans1 = Wlc_ObjFaninNum(pObj) > 1 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId1(pObj)) ) : NULL;
+ pFans2 = Wlc_ObjFaninNum(pObj) > 2 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId2(pObj)) ) : NULL;
+ pFans3 = Wlc_ObjFaninNum(pObj) > 3 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId(pObj,3)) ) : NULL;
+ for ( k = 0; k < nRange; k++ )
+ Gia_ManAppendCo( pNew, pFans0[k] );
+ Gia_ManAppendCo( pNew, pFans1[0] );
+ Gia_ManAppendCo( pNew, pFans2[0] );
+ Gia_ManAppendCo( pNew, pFans3[0] );
+ for ( k = 0; k < nRange; k++ )
+ Gia_ManAppendCo( pNew, Gia_Obj2Lit(pNew, Gia_ManCi(pNew, Vec_IntEntry(vFf2Ci, i)+k)) );
+
+ // make sure there is enough primary inputs in the manager
+ for ( k = Gia_ManPiNum(pExtra); k < nRangeIn; k++ )
+ Gia_ManAppendCi( pExtra );
+ // create combinational inputs
+ for ( k = 0; k < nRange; k++ )
+ Vec_IntPush( vTemp0, Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, k)) );
+ iReset = Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRange+0));
+ iSet = Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRange+1));
+ iEnable = Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRange+2));
+ for ( k = 0; k < nRange; k++ )
+ Vec_IntPush( vTemp1, Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRangeIn-nRange+k)) );
+
+ // bit-blast in the external manager
+ for ( k = 0; k < nRange; k++ )
+ {
+ // enable
+ //iLitFlop = Gia_LitNotCond( Gia_ObjCopy(pObj), Gia_FlopIsOne(pObj) );
+ //iLit = Gia_ManHashMux( Gia_ObjGia(pObj), Gia_FlopEnableCopy(pObj), iLit, iLitFlop );
+ iLit = Gia_ManHashMux( pExtra, iEnable, Vec_IntEntry(vTemp0, k), Vec_IntEntry(vTemp1, k) );
+ if ( iSre )
+ {
+ // reset
+ //iLit = Gia_ManHashAnd( Gia_ObjGia(pObj), iLit, Gia_LitNot(Gia_FlopResetCopy(pObj)) );
+ iLit = Gia_ManHashAnd( pExtra, iLit, Abc_LitNot(iReset) );
+ // set
+ //iLit = Gia_ManHashOr( Gia_ObjGia(pObj), iLit, Gia_FlopSetCopy(pObj) );
+ iLit = Gia_ManHashOr( pExtra, iLit, iSet );
+ }
+ else
+ {
+ // set
+ //iLit = Gia_ManHashOr( Gia_ObjGia(pObj), iLit, Gia_FlopSetCopy(pObj) );
+ iLit = Gia_ManHashOr( pExtra, iLit, iSet );
+ // reset
+ //iLit = Gia_ManHashAnd( Gia_ObjGia(pObj), iLit, Gia_LitNot(Gia_FlopResetCopy(pObj)) );
+ iLit = Gia_ManHashAnd( pExtra, iLit, Abc_LitNot(iReset) );
+ }
+ // create outputs in the external manager
+ Gia_ManAppendCo( pExtra, iLit );
+ }
+
+ // add box to the library
+ sprintf( Buffer, "%s%03d", "ff_comb", 1+If_LibBoxNum(pBoxLib) );
+ pBox = If_BoxStart( Abc_UtilStrsav(Buffer), 1+If_LibBoxNum(pBoxLib), nRangeIn, nRange, 0, 0, 0 );
+ If_LibBoxAdd( pBoxLib, pBox );
+ for ( k = 0; k < pBox->nPis * pBox->nPos; k++ )
+ pBox->pDelays[k] = 1;
+ Vec_IntFree( vTemp0 );
+ Vec_IntFree( vTemp1 );
+ }
+ Vec_IntFree( vFf2Ci );
// create COs
if ( pPar->fCreateMiter )
{
@@ -1588,8 +2022,19 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
//Vec_IntErase( vBits );
//Vec_IntErase( &p->vCopies );
// set the number of registers
- assert( nFFins == nFFouts );
- Gia_ManSetRegNum( pNew, nFFins );
+ if ( Vec_IntSize(&p->vFfs2) > 0 )
+ {
+ assert( nFFins == 0 && nFFouts == 0 );
+ // complement flop inputs whose init state is 1
+ for ( i = 0; i < nFf2Regs; i++ )
+ Gia_ManAppendCo( pNew, Gia_ManAppendCi(pNew) );
+ //Gia_ManSetRegNum( pNew, nFf2Regs );
+ }
+ else
+ {
+ assert( nFFins == nFFouts );
+ Gia_ManSetRegNum( pNew, nFFins );
+ }
// finalize AIG
if ( !pPar->fGiaSimple && !pPar->fNoCleanup )
{
@@ -1614,6 +2059,24 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
}
}
// finalize AIG with boxes
+ if ( Vec_IntSize(&p->vFfs2) > 0 )
+ {
+ curPo += nBitCos + nFf2Regs;
+ assert( curPi == Tim_ManCiNum(pManTime) );
+ assert( curPo == Tim_ManCoNum(pManTime) );
+ // finalize the extra AIG
+ pExtra = Gia_ManCleanup( pTemp = pExtra );
+ Gia_ManStop( pTemp );
+ assert( Gia_ManPoNum(pExtra) == Gia_ManCiNum(pNew) - nBitCis - nFf2Regs );
+ // attach
+ pNew->pAigExtra = pExtra;
+ pNew->pManTime = pManTime;
+ // normalize AIG
+ pNew = Gia_ManDupNormalize( pTemp = pNew, 0 );
+ Gia_ManTransferTiming( pNew, pTemp );
+ Gia_ManStop( pTemp );
+ //Tim_ManPrint( pManTime );
+ }
if ( pPar->vBoxIds )
{
curPo += nBitCos;
@@ -1622,7 +2085,7 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
// finalize the extra AIG
pExtra = Gia_ManCleanup( pTemp = pExtra );
Gia_ManStop( pTemp );
- assert( Gia_ManPoNum(pExtra) == Gia_ManCiNum(pNew) - nBitCis );
+ assert( Gia_ManPoNum(pExtra) == Gia_ManCiNum(pNew) - nBitCis - nFf2Regs );
// attach
pNew->pAigExtra = pExtra;
pNew->pManTime = pManTime;
@@ -1676,6 +2139,38 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) );
}
}
+ Wlc_NtkForEachFf2( p, pObj, i )
+ {
+ char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj));
+ nRange = Wlc_ObjRange( pObj );
+ if ( fSkipBitRange && nRange == 1 )
+ {
+ char Buffer[1000];
+ sprintf( Buffer, "%s_fo", pName );
+ Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) );
+ }
+ else
+ for ( k = 0; k < nRange; k++ )
+ {
+ char Buffer[1000];
+ sprintf( Buffer, "%s_fo[%d]", pName, k );
+ Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) );
+ }
+ }
+ Wlc_NtkForEachFf2( p, pObj, i )
+ {
+ char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj));
+ nRange = Wlc_ObjRange( pObj );
+ if ( fSkipBitRange && nRange == 1 )
+ Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(pName) );
+ else
+ for ( k = 0; k < nRange; k++ )
+ {
+ char Buffer[1000];
+ sprintf( Buffer, "%s[%d]", pName, k );
+ Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) );
+ }
+ }
if ( p->pInits && fAdded )
Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav("abc_reset_flop") );
if ( pPar->vBoxIds )
@@ -1696,6 +2191,43 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
assert( Vec_PtrSize(pNew->vNamesIn) == Gia_ManCiNum(pNew) );
// create output names
pNew->vNamesOut = Vec_PtrAlloc( Gia_ManCoNum(pNew) );
+ Wlc_NtkForEachFf2( p, pObj, i )
+ {
+ int iFanin;
+ Wlc_ObjForEachFanin( pObj, iFanin, b )
+ {
+ char * pName = Wlc_ObjName(p, iFanin);
+ nRange = Wlc_ObjRange( Wlc_NtkObj(p, iFanin) );
+ if ( fSkipBitRange && nRange == 1 )
+ Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(pName) );
+ else
+ for ( k = 0; k < nRange; k++ )
+ {
+ char Buffer[1000];
+ sprintf( Buffer, "%s[%d]", pName, k );
+ Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) );
+ }
+ if ( b == 3 )
+ break;
+ }
+ {
+ char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj));
+ nRange = Wlc_ObjRange( pObj );
+ if ( fSkipBitRange && nRange == 1 )
+ {
+ char Buffer[1000];
+ sprintf( Buffer, "%s_in", pName );
+ Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) );
+ }
+ else
+ for ( k = 0; k < nRange; k++ )
+ {
+ char Buffer[1000];
+ sprintf( Buffer, "%s_in[%d]", pName, k );
+ Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) );
+ }
+ }
+ }
if ( pPar->vBoxIds )
{
Wlc_NtkForEachObjVec( pPar->vBoxIds, p, pObj, i )
@@ -1786,6 +2318,24 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) );
}
}
+ Wlc_NtkForEachFf2( p, pObj, i )
+ {
+ char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj));
+ nRange = Wlc_ObjRange( pObj );
+ if ( fSkipBitRange && nRange == 1 )
+ {
+ char Buffer[1000];
+ sprintf( Buffer, "%s_fi", pName );
+ Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) );
+ }
+ else
+ for ( k = 0; k < nRange; k++ )
+ {
+ char Buffer[1000];
+ sprintf( Buffer, "%s_fi[%d]", pName, k );
+ Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) );
+ }
+ }
assert( Vec_PtrSize(pNew->vNamesOut) == Gia_ManCoNum(pNew) );
// replace the current library
@@ -1815,11 +2365,14 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
ABC_FREE( pNameGeneric );
printf( "Dumped two parts of the miter into files \"%s\" and \"%s\".\n", pFileName0, pFileName1 );
}
+ //Wlc_NtkPrintNameArray( pNew->vNamesIn );
+ //Wlc_NtkPrintNameArray( pNew->vNamesOut );
if ( pPar->vBoxIds )
{
- Vec_PtrFreeP( &pNew->vNamesIn );
- Vec_PtrFreeP( &pNew->vNamesOut );
+ Vec_PtrFreeFree( pNew->vNamesIn ); pNew->vNamesIn = NULL;
+ Vec_PtrFreeFree( pNew->vNamesOut ); pNew->vNamesOut = NULL;
}
+ pNew->vRegClasses = vRegClasses;
return pNew;
}
diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c
index 711763c7..5b99cb00 100644
--- a/src/base/wlc/wlcCom.c
+++ b/src/base/wlc/wlcCom.c
@@ -38,7 +38,9 @@ static int Abc_CommandPdrAbs ( Abc_Frame_t * pAbc, int argc, char ** argv )
static int Abc_CommandAbs2 ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandMemAbs ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandBlast ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBlastMem ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandGraft ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandProfile ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -82,7 +84,9 @@ void Wlc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Word level", "%abs2", Abc_CommandAbs2, 0 );
Cmd_CommandAdd( pAbc, "Word level", "%memabs", Abc_CommandMemAbs, 0 );
Cmd_CommandAdd( pAbc, "Word level", "%blast", Abc_CommandBlast, 0 );
+ Cmd_CommandAdd( pAbc, "Word level", "%blastmem", Abc_CommandBlastMem, 0 );
Cmd_CommandAdd( pAbc, "Word level", "%graft", Abc_CommandGraft, 0 );
+ Cmd_CommandAdd( pAbc, "Word level", "%retime", Abc_CommandRetime, 0 );
Cmd_CommandAdd( pAbc, "Word level", "%profile", Abc_CommandProfile, 0 );
Cmd_CommandAdd( pAbc, "Word level", "%short_names", Abc_CommandShortNames, 0 );
Cmd_CommandAdd( pAbc, "Word level", "%show", Abc_CommandShow, 0 );
@@ -967,12 +971,12 @@ usage:
int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc);
- Gia_Man_t * pNew = NULL; int c;
+ Gia_Man_t * pNew = NULL; int c, fMiter = 0, fDumpNames = 0;
Wlc_BstPar_t Par, * pPar = &Par;
Wlc_BstParDefault( pPar );
pPar->nOutputRange = 2;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "ORAMcombdsvh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "ORAMcombadstnvh" ) ) != EOF )
{
switch ( c )
{
@@ -1032,12 +1036,22 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'b':
pPar->fBooth ^= 1;
break;
+ case 'a':
+ pPar->fCla ^= 1;
+ break;
case 'd':
pPar->fCreateMiter ^= 1;
break;
case 's':
pPar->fDecMuxes ^= 1;
break;
+ case 't':
+ pPar->fCreateMiter ^= 1;
+ fMiter ^= 1;
+ break;
+ case 'n':
+ fDumpNames ^= 1;
+ break;
case 'v':
pPar->fVerbose ^= 1;
break;
@@ -1080,10 +1094,31 @@ int Abc_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Print( 1, "Abc_CommandBlast(): Bit-blasting has failed.\n" );
return 0;
}
+ // generate miter
+ if ( fMiter )
+ {
+ Gia_Man_t * pTemp = pNew;
+ pNew = Gia_ManTransformMiter( pNew );
+ Gia_ManStop( pTemp );
+ Abc_Print( 1, "Bit-blasting created a traditional multi-output miter by XORing POs pair-wise.\n" );
+ if ( fDumpNames )
+ {
+ int i; char * pName;
+ FILE * pFile = fopen( "pio_name_map.txt", "wb" );
+ if ( pNew->vNamesIn )
+ Vec_PtrForEachEntry( char *, pNew->vNamesIn, pName, i )
+ fprintf( pFile, "i%d %s\n", i, pName );
+ if ( pNew->vNamesOut )
+ Vec_PtrForEachEntry( char *, pNew->vNamesOut, pName, i )
+ fprintf( pFile, "o%d %s\n", i, pName );
+ fclose( pFile );
+ Abc_Print( 1, "Finished dumping file \"pio_name_map.txt\" containing PI/PO name mapping.\n" );
+ }
+ }
Abc_FrameUpdateGia( pAbc, pNew );
return 0;
usage:
- Abc_Print( -2, "usage: %%blast [-ORAM num] [-combdsvh]\n" );
+ Abc_Print( -2, "usage: %%blast [-ORAM num] [-combadstnvh]\n" );
Abc_Print( -2, "\t performs bit-blasting of the word-level design\n" );
Abc_Print( -2, "\t-O num : zero-based index of the first word-level PO to bit-blast [default = %d]\n", pPar->iOutput );
Abc_Print( -2, "\t-R num : the total number of word-level POs to bit-blast [default = %d]\n", pPar->nOutputRange );
@@ -1093,8 +1128,11 @@ usage:
Abc_Print( -2, "\t-o : toggle using additional POs on the word-level boundaries [default = %s]\n", pPar->fAddOutputs? "yes": "no" );
Abc_Print( -2, "\t-m : toggle creating boxes for all multipliers in the design [default = %s]\n", pPar->fMulti? "yes": "no" );
Abc_Print( -2, "\t-b : toggle generating radix-4 Booth multipliers [default = %s]\n", pPar->fBooth? "yes": "no" );
- Abc_Print( -2, "\t-d : toggle creating dual-output miter [default = %s]\n", pPar->fCreateMiter? "yes": "no" );
+ Abc_Print( -2, "\t-a : toggle generating carry-look-ahead adder [default = %s]\n", pPar->fCla? "yes": "no" );
+ Abc_Print( -2, "\t-d : toggle creating dual-output multi-output miter [default = %s]\n", pPar->fCreateMiter? "yes": "no" );
Abc_Print( -2, "\t-s : toggle creating decoded MUXes [default = %s]\n", pPar->fDecMuxes? "yes": "no" );
+ Abc_Print( -2, "\t-t : toggle creating regular multi-output miter [default = %s]\n", fMiter? "yes": "no" );
+ Abc_Print( -2, "\t-n : toggle dumping signal names into a text file [default = %s]\n", fDumpNames? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPar->fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
@@ -1111,6 +1149,52 @@ usage:
SeeAlso []
******************************************************************************/
+int Abc_CommandBlastMem( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ extern Wlc_Ntk_t * Wlc_NtkMemBlast( Wlc_Ntk_t * p );
+ Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc);
+ int c, fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pNtk == NULL )
+ {
+ Abc_Print( 1, "Abc_CommandBlastMem(): There is no current design.\n" );
+ return 0;
+ }
+ pNtk = Wlc_NtkMemBlast( pNtk );
+ Wlc_AbcUpdateNtk( pAbc, pNtk );
+ return 0;
+usage:
+ Abc_Print( -2, "usage: %%blastmem [-vh]\n" );
+ Abc_Print( -2, "\t performs blasting of memory read/write ports\n" );
+ Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ Abc_Print( -2, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function********************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
int Abc_CommandGraft( Abc_Frame_t * pAbc, int argc, char ** argv )
{
extern Wlc_Ntk_t * Wlc_NtkGraftMulti( Wlc_Ntk_t * p, int fVerbose );
@@ -1157,6 +1241,63 @@ usage:
SeeAlso []
******************************************************************************/
+int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ extern void Wln_NtkRetimeTest( char * pFileName );
+ FILE * pFile;
+ char * pFileName = NULL;
+ int c, fVerbose = 0;
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'v':
+ fVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( argc != globalUtilOptind + 1 )
+ {
+ printf( "Abc_CommandRetime(): Input file name should be given on the command line.\n" );
+ return 0;
+ }
+ // get the file name
+ pFileName = argv[globalUtilOptind];
+ if ( (pFile = fopen( pFileName, "r" )) == NULL )
+ {
+ Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName );
+ if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".ndr", NULL, NULL, NULL, NULL )) )
+ Abc_Print( 1, "Did you mean \"%s\"?", pFileName );
+ Abc_Print( 1, "\n" );
+ return 0;
+ }
+ fclose( pFile );
+ Wln_NtkRetimeTest( pFileName );
+ return 0;
+usage:
+ Abc_Print( -2, "usage: %%retime [-vh]\n" );
+ Abc_Print( -2, "\t performs retiming for the NDR design\n" );
+ Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
+ Abc_Print( -2, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function********************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
int Abc_CommandProfile( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc);
@@ -1672,7 +1813,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
//Wlc_NtkSimulateTest( (Wlc_Ntk_t *)pAbc->pAbcWlc );
//pNtk = Wlc_NtkDupSingleNodes( pNtk );
//Wlc_AbcUpdateNtk( pAbc, pNtk );
- Ndr_ModuleTestSelSel();
+ //Wln_ReadNdrTest();
//pNtk = Wlc_NtkMemAbstractTest( pNtk );
//Wlc_AbcUpdateNtk( pAbc, pNtk );
return 0;
diff --git a/src/base/wlc/wlcMem.c b/src/base/wlc/wlcMem.c
index b310afb6..ccc319e5 100644
--- a/src/base/wlc/wlcMem.c
+++ b/src/base/wlc/wlcMem.c
@@ -35,6 +35,133 @@ ABC_NAMESPACE_IMPL_START
/**Function*************************************************************
+ Synopsis [Memory blasting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Wlc_NtkMemBlast_rec( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, int iObj, Vec_Int_t * vFanins )
+{
+ Wlc_Obj_t * pObj;
+ int i, iFanin;
+ if ( Wlc_ObjCopy(p, iObj) )
+ return;
+ pObj = Wlc_NtkObj( p, iObj );
+ Wlc_ObjForEachFanin( pObj, iFanin, i )
+ Wlc_NtkMemBlast_rec( pNew, p, iFanin, vFanins );
+ if ( pObj->Type == WLC_OBJ_WRITE )
+ {
+ Vec_Int_t * vTemp = Vec_IntAlloc( 1 );
+ Vec_Int_t * vBits = Vec_IntAlloc( 100 );
+ Wlc_Obj_t * pMem = Wlc_ObjFanin0(p, pObj);
+ Wlc_Obj_t * pAddr = Wlc_ObjFanin1(p, pObj);
+ Wlc_Obj_t * pData = Wlc_ObjFanin2(p, pObj);
+ int DataW = Wlc_ObjRange(pData);
+ int AddrW = Wlc_ObjRange(pAddr);
+ int nRegs = 1 << AddrW, iObjNew, iObjDec;
+ assert( nRegs * DataW == Wlc_ObjRange(pMem) );
+ assert( Wlc_ObjRange(pObj) == Wlc_ObjRange(pMem) );
+ // create decoder
+ iObjDec = Wlc_ObjAlloc( pNew, WLC_OBJ_DEC, 0, nRegs-1, 0 );
+ Vec_IntFill( vTemp, 1, Wlc_ObjCopy(p, Wlc_ObjId(p, pAddr)) );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObjDec), vTemp );
+ // create decoder bits
+ for ( i = 0; i < nRegs; i++ )
+ {
+ int iObj2 = Wlc_ObjAlloc( pNew, WLC_OBJ_BIT_SELECT, 0, i, i );
+ Vec_IntFill( vTemp, 1, iObjDec );
+ Vec_IntPushTwo( vTemp, i, i );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObj2), vTemp );
+ Vec_IntPush( vBits, iObj2 );
+ }
+ // create data words
+ Vec_IntClear( vFanins );
+ for ( i = 0; i < nRegs; i++ )
+ {
+ int iObj2 = Wlc_ObjAlloc( pNew, WLC_OBJ_BIT_SELECT, 0, i*DataW+DataW-1, i*DataW );
+ Vec_IntFill( vTemp, 1, Wlc_ObjCopy(p, Wlc_ObjId(p, pMem)) );
+ Vec_IntPushTwo( vTemp, i*DataW+DataW-1, i*DataW );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObj2), vTemp );
+ Vec_IntPush( vFanins, iObj2 );
+ }
+ // create MUXes of data words controlled by decoder bits
+ for ( i = 0; i < nRegs; i++ )
+ {
+ int iObj2 = Wlc_ObjAlloc( pNew, WLC_OBJ_MUX, 0, DataW-1, 0 );
+ Vec_IntFill( vTemp, 1, Vec_IntEntry(vBits, i) );
+ Vec_IntPushTwo( vTemp, Wlc_ObjCopy(p, Wlc_ObjId(p, pData)), Vec_IntEntry(vFanins, i) );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObj2), vTemp );
+ Vec_IntWriteEntry( vFanins, i, iObj2 );
+ }
+ // concatenate the results
+ iObjNew = Wlc_ObjAlloc( pNew, WLC_OBJ_BIT_CONCAT, 0, nRegs*DataW-1, 0 );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObjNew), vFanins );
+ Wlc_ObjSetCopy( p, iObj, iObjNew );
+ Vec_IntFree( vTemp );
+ Vec_IntFree( vBits );
+ }
+ else if ( pObj->Type == WLC_OBJ_READ )
+ {
+ Vec_Int_t * vTemp = Vec_IntAlloc( 1 );
+ Wlc_Obj_t * pMem = Wlc_ObjFanin0(p, pObj);
+ Wlc_Obj_t * pAddr = Wlc_ObjFanin1(p, pObj);
+ int DataW = Wlc_ObjRange(pObj);
+ int AddrW = Wlc_ObjRange(pAddr);
+ int nRegs = 1 << AddrW, iObjNew;
+ assert( nRegs * DataW == Wlc_ObjRange(pMem) );
+ Vec_IntClear( vFanins );
+ Vec_IntPush( vFanins, Wlc_ObjCopy(p, Wlc_ObjId(p, pAddr)) );
+ for ( i = 0; i < nRegs; i++ )
+ {
+ int iObj2 = Wlc_ObjAlloc( pNew, WLC_OBJ_BIT_SELECT, 0, i*DataW+DataW-1, i*DataW );
+ Vec_IntFill( vTemp, 1, Wlc_ObjCopy(p, Wlc_ObjId(p, pMem)) );
+ Vec_IntPushTwo( vTemp, i*DataW+DataW-1, i*DataW );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObj2), vTemp );
+ Vec_IntPush( vFanins, iObj2 );
+ }
+ iObjNew = Wlc_ObjAlloc( pNew, WLC_OBJ_MUX, 0, DataW-1, 0 );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObjNew), vFanins );
+ Wlc_ObjSetCopy( p, iObj, iObjNew );
+ Vec_IntFree( vTemp );
+ }
+ else
+ Wlc_ObjDup( pNew, p, iObj, vFanins );
+}
+Wlc_Ntk_t * Wlc_NtkMemBlast( Wlc_Ntk_t * p )
+{
+ Wlc_Ntk_t * pNew;
+ Wlc_Obj_t * pObj;
+ Vec_Int_t * vFanins;
+ int i;
+ Wlc_NtkCleanCopy( p );
+ vFanins = Vec_IntAlloc( 100 );
+ pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc );
+ pNew->fSmtLib = p->fSmtLib;
+ pNew->fMemPorts = p->fMemPorts;
+ pNew->fEasyFfs = p->fEasyFfs;
+ Wlc_NtkForEachCi( p, pObj, i )
+ Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins );
+ Wlc_NtkForEachCo( p, pObj, i )
+ Wlc_NtkMemBlast_rec( pNew, p, Wlc_ObjId(p, pObj), vFanins );
+ Wlc_NtkForEachCo( p, pObj, i )
+ Wlc_ObjSetCo( pNew, Wlc_ObjCopyObj(pNew, p, pObj), pObj->fIsFi );
+ if ( p->vInits )
+ pNew->vInits = Vec_IntDup( p->vInits );
+ if ( p->pInits )
+ pNew->pInits = Abc_UtilStrsav( p->pInits );
+ Vec_IntFree( vFanins );
+ if ( p->pSpec )
+ pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+ return pNew;
+}
+
+
+/**Function*************************************************************
+
Synopsis [Collect memory nodes.]
Description []
@@ -827,7 +954,7 @@ int Wlc_NtkMemAbstract( Wlc_Ntk_t * p, int nIterMax, int fDumpAbs, int fPdrVerbo
Vec_Wec_t * vRefines = Vec_WecAlloc( 100 );
Vec_Int_t * vNodeFrames = Vec_IntAlloc( 100 );
Vec_Int_t * vMemObjs, * vMemFanins, * vFirstTotal, * vRefine;
- int RetValue, iFirstMemPi, iFirstCi, iFirstMemCi, nDcBits, nIters;
+ int RetValue = -1, iFirstMemPi, iFirstCi, iFirstMemCi, nDcBits, nIters;
vMemObjs = Wlc_NtkCollectMemory( p );
vMemFanins = Wlc_NtkCollectMemFanins( p, vMemObjs );
diff --git a/src/base/wlc/wlcNdr.c b/src/base/wlc/wlcNdr.c
index 3e6600c3..16c7d778 100644
--- a/src/base/wlc/wlcNdr.c
+++ b/src/base/wlc/wlcNdr.c
@@ -71,6 +71,7 @@ int Ndr_TypeNdr2Wlc( int Type )
if ( Type == ABC_OPER_LOGIC_XOR ) return WLC_OBJ_LOGIC_XOR; // 30: logic XOR
if ( Type == ABC_OPER_SEL_NMUX ) return WLC_OBJ_MUX; // 08: multiplexer
if ( Type == ABC_OPER_SEL_SEL ) return WLC_OBJ_SEL; // 57: selector
+ if ( Type == ABC_OPER_SEL_DEC ) return WLC_OBJ_DEC; // 58: decoder
if ( Type == ABC_OPER_COMP_EQU ) return WLC_OBJ_COMP_EQU; // 31: compare equal
if ( Type == ABC_OPER_COMP_NOTEQU ) return WLC_OBJ_COMP_NOTEQU; // 32: compare not equal
if ( Type == ABC_OPER_COMP_LESS ) return WLC_OBJ_COMP_LESS; // 33: compare less
@@ -129,6 +130,7 @@ int Ndr_TypeWlc2Ndr( int Type )
if ( Type == WLC_OBJ_LOGIC_OR ) return ABC_OPER_LOGIC_OR; // 29: logic OR
if ( Type == WLC_OBJ_LOGIC_XOR ) return ABC_OPER_LOGIC_XOR; // 30: logic XOR
if ( Type == WLC_OBJ_SEL ) return ABC_OPER_SEL_SEL; // 57: selector
+ if ( Type == WLC_OBJ_DEC ) return ABC_OPER_SEL_DEC; // 58: decoder
if ( Type == WLC_OBJ_COMP_EQU ) return ABC_OPER_COMP_EQU; // 31: compare equal
if ( Type == WLC_OBJ_COMP_NOTEQU ) return ABC_OPER_COMP_NOTEQU; // 32: compare not equal
if ( Type == WLC_OBJ_COMP_LESS ) return ABC_OPER_COMP_LESS; // 33: compare less
@@ -342,9 +344,10 @@ void Wlc_NtkCheckIntegrity( void * pData )
}
Ndr_ModForEachObj( p, Mod, Obj )
{
+ int Type = Ndr_ObjReadBody( p, Obj, NDR_OPERTYPE );
int i, * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
for ( i = 0; i < nArray; i++ )
- if ( Vec_IntGetEntry(vMap, pArray[i]) == 0 )
+ if ( Vec_IntGetEntry(vMap, pArray[i]) == 0 && !(Type == ABC_OPER_DFFRSE && (i >= 5 || i <= 7)) )
printf( "Input name %d appearing as fanin %d of obj %d is not used as output name in any object.\n", pArray[i], i, Obj );
}
Vec_IntFree( vMap );
@@ -396,6 +399,8 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData )
Vec_IntPush( &pNtk->vFfs, Vec_IntEntry(vFanins, 0) );
continue;
}
+ if ( Type == ABC_OPER_DFFRSE )
+ Vec_IntPush( &pNtk->vFfs2, iObj );
if ( Type == ABC_OPER_SLICE )
Vec_IntPushTwo( vFanins, End, Beg );
else if ( Type == ABC_OPER_CONST )
@@ -467,6 +472,7 @@ Wlc_Ntk_t * Wlc_NtkFromNdr( void * pData )
assert( !fFound && i == NameId );
}
//Ndr_NtkPrintNodes( pNtk );
+ //Wlc_WriteVer( pNtk, "temp_ndr.v", 0, 0 );
// derive topological order
pNtk = Wlc_NtkDupDfs( pTemp = pNtk, 0, 1 );
Wlc_NtkFree( pTemp );
diff --git a/src/base/wlc/wlcNtk.c b/src/base/wlc/wlcNtk.c
index b8a4b9b1..4ac0c66c 100644
--- a/src/base/wlc/wlcNtk.c
+++ b/src/base/wlc/wlcNtk.c
@@ -87,7 +87,10 @@ static char * Wlc_Names[WLC_OBJ_NUMBER+1] = {
"table", // 53: bit table
"READ", // 54: mem read port
"WRITE", // 55: mem write port
- NULL // 56: unused
+ "addsub", // 56: adder/subtractor
+ "sel", // 57: selector
+ "dec", // 58: decoder
+ NULL // 58: unused
};
char * Wlc_ObjTypeName( Wlc_Obj_t * p ) { return Wlc_Names[p->Type]; }
@@ -261,6 +264,7 @@ void Wlc_NtkFree( Wlc_Ntk_t * p )
ABC_FREE( p->vCis.pArray );
ABC_FREE( p->vCos.pArray );
ABC_FREE( p->vFfs.pArray );
+ ABC_FREE( p->vFfs2.pArray );
Vec_IntFreeP( &p->vInits );
ABC_FREE( p->vTravIds.pArray );
ABC_FREE( p->vNameIds.pArray );
@@ -283,6 +287,7 @@ int Wlc_NtkMemUsage( Wlc_Ntk_t * p )
Mem += 4 * p->vCis.nCap;
Mem += 4 * p->vCos.nCap;
Mem += 4 * p->vFfs.nCap;
+ Mem += 4 * p->vFfs2.nCap;
Mem += sizeof(Wlc_Obj_t) * p->nObjsAlloc;
Mem += Abc_NamMemUsed(p->pManName);
Mem += Mem_FlexReadMemUsage(p->pMemFanin);
@@ -637,6 +642,11 @@ void Wlc_NtkPrintNode( Wlc_Ntk_t * p, Wlc_Obj_t * pObj )
printf( "FO\n" );
return;
}
+ if ( pObj->Type != WLC_OBJ_CONST && Wlc_ObjFaninNum(pObj) == 0 )
+ {
+ printf( "Unknown object without fanins\n" );
+ return;
+ }
if ( pObj->Type != WLC_OBJ_CONST )
{
printf( "%6d%s %5s ", Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin0(p, pObj)) ? "s" : " ", Wlc_Names[(int)pObj->Type] );
@@ -858,10 +868,13 @@ void Wlc_NtkDupDfs_rec( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, int iObj, Vec_Int_t * v
{
Wlc_Obj_t * pObj;
int i, iFanin;
+ if ( iObj == 0 )
+ return;
if ( Wlc_ObjCopy(p, iObj) )
return;
//printf( "Visiting node %d\n", iObj );
pObj = Wlc_NtkObj( p, iObj );
+ assert( pObj->Type != WLC_OBJ_FF );
Wlc_ObjForEachFanin( pObj, iFanin, i )
Wlc_NtkDupDfs_rec( pNew, p, iFanin, vFanins );
Wlc_ObjDup( pNew, p, iObj, vFanins );
@@ -898,9 +911,9 @@ Wlc_Ntk_t * Wlc_NtkDupDfsSimple( Wlc_Ntk_t * p )
Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p, int fMarked, int fSeq )
{
Wlc_Ntk_t * pNew;
- Wlc_Obj_t * pObj;
+ Wlc_Obj_t * pObj, * pObjNew;
Vec_Int_t * vFanins;
- int i;
+ int i, k, iObj, iFanin;
vFanins = Vec_IntAlloc( 100 );
Wlc_NtkCleanCopy( p );
pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc );
@@ -915,12 +928,28 @@ Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p, int fMarked, int fSeq )
Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins );
pObj->Type = Type;
}
+ Wlc_NtkForEachFf2( p, pObj, i )
+ {
+ int iObjNew = Wlc_ObjAlloc( pNew, pObj->Type, Wlc_ObjIsSigned(pObj), pObj->End, pObj->Beg );
+ Wlc_ObjSetCopy( p, Wlc_ObjId(p, pObj), iObjNew );
+ Vec_IntPush( &pNew->vFfs2, iObjNew );
+ }
Wlc_NtkForEachCo( p, pObj, i )
if ( !fMarked || pObj->Mark )
Wlc_NtkDupDfs_rec( pNew, p, Wlc_ObjId(p, pObj), vFanins );
Wlc_NtkForEachCo( p, pObj, i )
if ( !fMarked || pObj->Mark )
Wlc_ObjSetCo( pNew, Wlc_ObjCopyObj(pNew, p, pObj), fSeq ? pObj->fIsFi : 0 );
+ Wlc_NtkForEachFf2( p, pObj, i )
+ {
+ iObj = Wlc_ObjId(p, pObj);
+ Wlc_ObjForEachFanin( pObj, iFanin, k )
+ Wlc_NtkDupDfs_rec( pNew, p, iFanin, vFanins );
+ Wlc_ObjCollectCopyFanins( p, iObj, vFanins );
+ pObjNew = Wlc_NtkObj( pNew, Wlc_ObjCopy(p, iObj) );
+ Wlc_ObjAddFanins( pNew, pObjNew, vFanins );
+ pObjNew->fXConst = pObj->fXConst;
+ }
Vec_IntFree( vFanins );
if ( fSeq )
{
diff --git a/src/base/wlc/wlcReadVer.c b/src/base/wlc/wlcReadVer.c
index 9974dd44..34966777 100644
--- a/src/base/wlc/wlcReadVer.c
+++ b/src/base/wlc/wlcReadVer.c
@@ -1277,7 +1277,7 @@ startword:
}
else if ( Wlc_PrsStrCmp( pStart, "ABC_DFFRSE" ) )
{
- int NameId[8], fFound, nBits = 1, fFlopIn, fFlopOut, fFlopClk, fFlopRst, fFlopSet, fFlopEna, fFlopAsync, fFlopInit;
+ int NameId[10] = {0}, fFound, fFlopIn, fFlopClk, fFlopRst, fFlopSet, fFlopEna, fFlopAsync, fFlopSre, fFlopInit, fFlopOut;
pStart += strlen("ABC_DFF");
while ( 1 )
{
@@ -1286,13 +1286,14 @@ startword:
break;
pStart = Wlc_PrsSkipSpaces( pStart+1 );
fFlopIn = (pStart[0] == 'd');
- fFlopOut = (pStart[0] == 'q');
fFlopClk = (pStart[0] == 'c');
fFlopRst = (pStart[0] == 'r');
- fFlopSet = (pStart[0] == 's');
+ fFlopSet = (pStart[0] == 's' && pStart[1] == 'e');
fFlopEna = (pStart[0] == 'e');
fFlopAsync = (pStart[0] == 'a');
+ fFlopSre = (pStart[0] == 's' && pStart[1] == 'r');
fFlopInit = (pStart[0] == 'i');
+ fFlopOut = (pStart[0] == 'q');
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." );
@@ -1301,8 +1302,6 @@ startword:
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." );
if ( fFlopIn )
NameId[0] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
- else if ( fFlopOut )
- NameId[7] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopClk )
NameId[1] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopRst )
@@ -1313,8 +1312,12 @@ startword:
NameId[4] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopAsync )
NameId[5] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
- else if ( fFlopInit )
+ else if ( fFlopSre )
NameId[6] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
+ else if ( fFlopInit )
+ NameId[7] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
+ else if ( fFlopOut )
+ NameId[8] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else
assert( 0 );
if ( !fFound )
@@ -1323,7 +1326,7 @@ startword:
if ( NameId[0] == -1 || NameId[7] == -1 )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name of flop input or flop output is missing." );
// create output
- pObj = Wlc_NtkObj( p->pNtk, NameId[7] );
+ pObj = Wlc_NtkObj( p->pNtk, NameId[8] );
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_FF );
Vec_IntClear( p->vFanins );
Vec_IntPush( p->vFanins, NameId[0] );
@@ -1333,6 +1336,7 @@ startword:
Vec_IntPush( p->vFanins, NameId[4] );
Vec_IntPush( p->vFanins, NameId[5] );
Vec_IntPush( p->vFanins, NameId[6] );
+ Vec_IntPush( p->vFanins, NameId[7] );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
}
else if ( Wlc_PrsStrCmp( pStart, "ABC_DFF" ) )
@@ -1571,6 +1575,10 @@ Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr )
// derive topological order
if ( p->pNtk )
{
+ Wlc_Obj_t * pObj; int i;
+ Wlc_NtkForEachObj( p->pNtk, pObj, i )
+ if ( pObj->Type == WLC_OBJ_FF )
+ Vec_IntPush( &p->pNtk->vFfs2, Wlc_ObjId(p->pNtk, pObj) );
pNtk = Wlc_NtkDupDfs( p->pNtk, 0, 1 );
pNtk->pSpec = Abc_UtilStrsav( pFileName );
}
diff --git a/src/base/wlc/wlcWriteVer.c b/src/base/wlc/wlcWriteVer.c
index dbf24e68..30f10e14 100644
--- a/src/base/wlc/wlcWriteVer.c
+++ b/src/base/wlc/wlcWriteVer.c
@@ -192,7 +192,7 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
continue;
fprintf( pFile, " assign " );
}
- else if ( (pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3) || pObj->Type == WLC_OBJ_FF )
+ else if ( (pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3) || pObj->Type == WLC_OBJ_SEL )
fprintf( pFile, "reg %s ", Range );
else
fprintf( pFile, "wire %s ", Range );
@@ -275,12 +275,62 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
fprintf( pFile, " : %s = ", Wlc_ObjName(p, i) );
fprintf( pFile, "%s ;\n", Wlc_ObjName(p, Wlc_ObjFaninId(pObj, k)) );
}
+ fprintf( pFile, " " );
+ fprintf( pFile, "default" );
+ fprintf( pFile, " : %s = ", Wlc_ObjName(p, i) );
+ fprintf( pFile, "%d\'b", Wlc_ObjRange(pObj) );
+ for ( j = Wlc_ObjRange(pObj)-1; j >= 0; j-- )
+ fprintf( pFile, "%d", 0 );
+ fprintf( pFile, " ;\n" );
fprintf( pFile, " " );
fprintf( pFile, "endcase\n" );
fprintf( pFile, " " );
fprintf( pFile, "end\n" );
continue;
}
+ else if ( pObj->Type == WLC_OBJ_DEC )
+ {
+ int nRange = Wlc_ObjRange(Wlc_ObjFanin0(p, pObj));
+ assert( (1 << nRange) == Wlc_ObjRange(pObj) );
+ fprintf( pFile, "%s ;\n", Wlc_ObjName(p, i) );
+ for ( k = 0; k < Wlc_ObjRange(pObj); k++ )
+ {
+ fprintf( pFile, " " );
+ fprintf( pFile, "wire " );
+ fprintf( pFile, "%s_", Wlc_ObjName(p, i) );
+ for ( j = 0; j < nRange; j++ )
+ fprintf( pFile, "%d", (k >> (nRange-1-j)) & 1 );
+ fprintf( pFile, " = " );
+ for ( j = 0; j < nRange; j++ )
+ fprintf( pFile, "%s%s%s[%d]",
+ j ? " & ":"", ((k >> (nRange-1-j)) & 1) ? " ":"~",
+ Wlc_ObjName(p, Wlc_ObjFaninId(pObj, 0)), nRange-1-j );
+ fprintf( pFile, " ;\n" );
+ }
+ fprintf( pFile, " " );
+ fprintf( pFile, "assign %s = { ", Wlc_ObjName(p, i) );
+ for ( k = Wlc_ObjRange(pObj)-1; k >= 0; k-- )
+ {
+ fprintf( pFile, "%s%s_", k < Wlc_ObjRange(pObj)-1 ? ", ":"", Wlc_ObjName(p, i) );
+ for ( j = 0; j < nRange; j++ )
+ fprintf( pFile, "%d", (k >> (nRange-1-j)) & 1 );
+ }
+ fprintf( pFile, " } ;\n" );
+ continue;
+ }
+ else if ( pObj->Type == WLC_OBJ_ARI_ADDSUB )
+ {
+ // out = mode ? a+b+cin : a-b-cin
+ fprintf( pFile, "%s ;\n", Wlc_ObjName(p, i) );
+ fprintf( pFile, " " );
+ fprintf( pFile, "assign " );
+ fprintf( pFile, "%s = %s ? %s + %s + %s : %s - %s - %s ;\n",
+ Wlc_ObjName(p, i), Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)),
+ Wlc_ObjName(p, Wlc_ObjFaninId2(pObj)), Wlc_ObjName(p, Wlc_ObjFaninId(pObj,3)), Wlc_ObjName(p, Wlc_ObjFaninId1(pObj)),
+ Wlc_ObjName(p, Wlc_ObjFaninId2(pObj)), Wlc_ObjName(p, Wlc_ObjFaninId(pObj,3)), Wlc_ObjName(p, Wlc_ObjFaninId1(pObj))
+ );
+ continue;
+ }
else if ( pObj->Type == WLC_OBJ_READ || pObj->Type == WLC_OBJ_WRITE )
{
if ( p->fMemPorts )
@@ -311,13 +361,7 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
}
else if ( pObj->Type == WLC_OBJ_FF )
{
- char * pInNames[8] = {"d", "clk", "reset", "set", "enable", "async", "sre", "init"};
fprintf( pFile, "%s ;\n", Wlc_ObjName(p, i) );
- fprintf( pFile, " " );
- fprintf( pFile, "%s (", "ABC_DFFRSE" );
- Wlc_ObjForEachFanin( pObj, iFanin, k )
- fprintf( pFile, " .%s(%s),", pInNames[k], Wlc_ObjName(p, iFanin) );
- fprintf( pFile, " .%s(%s) ) ;\n", "q", Wlc_ObjName(p, i) );
continue;
}
else
@@ -425,7 +469,8 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
fprintf( pFile, "#" );
else
{
- assert( 0 );
+ //assert( 0 );
+ printf( "Failed to write node \"%s\" with unknown operator type (%d).\n", Wlc_ObjName(p, i), pObj->Type );
fprintf( pFile, "???\n" );
continue;
}
@@ -510,6 +555,18 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
}
assert( !p->vInits || iFanin == (int)strlen(p->pInits) );
}
+ // write DFFs in the end
+ fprintf( pFile, "\n" );
+ Wlc_NtkForEachFf2( p, pObj, i )
+ {
+ char * pInNames[8] = {"d", "clk", "reset", "set", "enable", "async", "sre", "init"};
+ fprintf( pFile, " " );
+ fprintf( pFile, "%s (", "ABC_DFFRSE" );
+ Wlc_ObjForEachFanin( pObj, iFanin, k )
+ if ( iFanin ) fprintf( pFile, " .%s(%s),", pInNames[k], Wlc_ObjName(p, iFanin) );
+ fprintf( pFile, " .%s(%s) ) ;\n", "q", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) );
+ }
+ fprintf( pFile, "\n" );
fprintf( pFile, "endmodule\n\n" );
}
void Wlc_WriteVer( Wlc_Ntk_t * p, char * pFileName, int fAddCos, int fNoFlops )