/**CFile**************************************************************** FileName [wlcBlast.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Bit-blasting.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlcBlast.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "wlc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Wlc_NtkPrepareBits( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i, nBits = 0; Wlc_NtkCleanCopy( p ); Wlc_NtkForEachObj( p, pObj, i ) { Wlc_ObjSetCopy( p, i, nBits ); nBits += Wlc_ObjRange(pObj); } return nBits; } int Wlc_NtkComputeReduction( Gia_Man_t * pNew, int * pFans, int nFans, int Type ) { if ( Type == WLC_OBJ_REDUCT_AND ) { int k, iLit = 1; for ( k = 0; k < nFans; k++ ) iLit = Gia_ManHashAnd( pNew, iLit, pFans[k] ); return iLit; } if ( Type == WLC_OBJ_REDUCT_OR ) { int k, iLit = 0; for ( k = 0; k < nFans; k++ ) iLit = Gia_ManHashOr( pNew, iLit, pFans[k] ); return iLit; } if ( Type == WLC_OBJ_REDUCT_XOR ) { int k, iLit = 0; for ( k = 0; k < nFans; k++ ) iLit = Gia_ManHashXor( pNew, iLit, pFans[k] ); return iLit; } assert( 0 ); return -1; } int Wlc_NtkMuxTree_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData, int Shift ) { int iLit0, iLit1; if ( nCtrl == 0 ) return Vec_IntEntry( vData, Shift ); iLit0 = Wlc_NtkMuxTree_rec( pNew, pCtrl, nCtrl-1, vData, Shift ); iLit1 = Wlc_NtkMuxTree_rec( pNew, pCtrl, nCtrl-1, vData, Shift + (1<<(nCtrl-1)) ); return Gia_ManHashMux( pNew, pCtrl[nCtrl-1], iLit1, iLit0 ); } void Wlc_NtkAdderChain( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits ) { int iCarry = 0, iTerm1, iTerm2, iTerm3, iSum, b; for ( b = 0; b < nBits; b++ ) { iSum = Gia_ManHashXor( pNew, iCarry, Gia_ManHashXor(pNew, pAdd0[b], pAdd1[b]) ); iTerm1 = Gia_ManHashAnd( pNew, pAdd0[b], pAdd1[b] ); iTerm2 = Gia_ManHashAnd( pNew, pAdd0[b], iCarry ); iTerm3 = Gia_ManHashAnd( pNew, pAdd1[b], iCarry ); iCarry = Gia_ManHashOr( pNew, iTerm1, Gia_ManHashOr(pNew, iTerm2, iTerm3) ); pAdd0[b] = iSum; } } Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p ) { Gia_Man_t * pTemp, * pNew; Wlc_Obj_t * pObj; Vec_Int_t * vBits, * vTemp0, * vTemp1, * vTemp2, * vTemp3; int nBits = Wlc_NtkPrepareBits( p ); int nRange, nRange0, nRange1, nRange2; int i, k, b, iLit, * pFans0, * pFans1, * pFans2; vBits = Vec_IntAlloc( nBits ); vTemp0 = Vec_IntAlloc( 1000 ); vTemp1 = Vec_IntAlloc( 1000 ); vTemp2 = Vec_IntAlloc( 1000 ); vTemp3 = Vec_IntAlloc( 1000 ); // craete AIG manager pNew = Gia_ManStart( 5 * Wlc_NtkObjNum(p) + 1000 ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); // create primary inputs Wlc_NtkForEachObj( p, pObj, i ) { // char * pName = Wlc_ObjName(p, i); nRange = Wlc_ObjRange( pObj ); 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; if ( pObj->Type == WLC_OBJ_PI ) { for ( k = 0; k < nRange; k++ ) Vec_IntPush( vBits, Gia_ManAppendCi(pNew) ); } else if ( pObj->Type == WLC_OBJ_PO || pObj->Type == WLC_OBJ_BUF ) { // assert( nRange <= nRange0 ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vBits, k < nRange0 ? pFans0[k] : 0 ); } else if ( pObj->Type == WLC_OBJ_CONST ) { word * pTruth = (word *)Wlc_ObjFanins(pObj); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vBits, Abc_TtGetBit(pTruth, k) ); } else if ( pObj->Type == WLC_OBJ_MUX ) { assert( nRange0 == 1 ); assert( nRange1 == nRange ); assert( nRange2 == nRange ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vBits, Gia_ManHashMux(pNew, pFans0[0], pFans1[k], pFans2[k]) ); } else if ( pObj->Type == WLC_OBJ_SHIFT_R || pObj->Type == WLC_OBJ_SHIFT_RA ) { // prepare data int Fill = pObj->Type == WLC_OBJ_SHIFT_R ? 0 : pFans0[nRange0-1]; int nTotal = nRange + (1 << nRange1); Vec_IntClear( vTemp0 ); for ( k = 0; k < nRange0; k++ ) Vec_IntPush( vTemp0, pFans0[k] ); for ( k = 0; k < nTotal; k++ ) Vec_IntPush( vTemp0, Fill ); // derive the result for ( k = 0; k < nRange; k++ ) Vec_IntPush( vBits, Wlc_NtkMuxTree_rec(pNew, pFans1, nRange1, vTemp0, k) ); } else if ( pObj->Type == WLC_OBJ_SHIFT_L || pObj->Type == WLC_OBJ_SHIFT_LA ) { // prepare data int Fill = pObj->Type == WLC_OBJ_SHIFT_L ? 0 : pFans0[0]; int nTotal = nRange + (1 << nRange1); Vec_IntClear( vTemp0 ); for ( k = 0; k < nRange0; k++ ) Vec_IntPush( vTemp0, pFans0[k] ); for ( k = 0; k < nTotal; k++ ) Vec_IntPush( vTemp0, Fill ); // derive the result for ( k = 0; k < nRange; k++ ) Vec_IntPush( vBits, Wlc_NtkMuxTree_rec(pNew, pFans1, nRange1, vTemp0, k) ); } else if ( pObj->Type == WLC_OBJ_BIT_NOT ) { assert( nRange == nRange0 ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vBits, Abc_LitNot(pFans0[k]) ); } else if ( pObj->Type == WLC_OBJ_BIT_AND ) { assert( nRange0 == nRange && nRange1 == nRange ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vBits, Gia_ManHashAnd(pNew, pFans0[k], pFans1[k]) ); } else if ( pObj->Type == WLC_OBJ_BIT_OR ) { assert( nRange0 == nRange && nRange1 == nRange ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vBits, Gia_ManHashOr(pNew, pFans0[k], pFans1[k]) ); } else if ( pObj->Type == WLC_OBJ_BIT_XOR ) { assert( nRange0 == nRange && nRange1 == nRange ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vBits, Gia_ManHashXor(pNew, pFans0[k], pFans1[k]) ); } else if ( pObj->Type == WLC_OBJ_BIT_SELECT ) { int End = Wlc_ObjRangeEnd(pObj); int Beg = Wlc_ObjRangeBeg(pObj); assert( nRange == End - Beg + 1 ); for ( k = Beg; k <= End; k++ ) Vec_IntPush( vBits, pFans0[k] ); } else if ( pObj->Type == WLC_OBJ_BIT_CONCAT ) { int iFanin, nTotal = 0; Wlc_ObjForEachFanin( pObj, iFanin, k ) nTotal += Wlc_ObjRange( Wlc_NtkObj(p, iFanin) ); assert( nRange == nTotal ); Wlc_ObjForEachFaninReverse( pObj, iFanin, k ) { nRange0 = Wlc_ObjRange( Wlc_NtkObj(p, iFanin) ); pFans0 = Vec_IntEntryP( vBits, Wlc_ObjCopy(p, iFanin) ); for ( b = 0; b < nRange0; b++ ) Vec_IntPush( vBits, pFans0[b] ); } } else if ( pObj->Type == WLC_OBJ_BIT_ZEROPAD || pObj->Type == WLC_OBJ_BIT_SIGNEXT ) { int Pad = pObj->Type == WLC_OBJ_BIT_ZEROPAD ? 0 : pFans0[nRange0-1]; assert( nRange0 < nRange ); for ( k = 0; k < nRange0; k++ ) Vec_IntPush( vBits, pFans0[k] ); for ( ; k < nRange; k++ ) Vec_IntPush( vBits, Pad ); } else if ( pObj->Type == WLC_OBJ_LOGIC_NOT ) { iLit = Wlc_NtkComputeReduction( pNew, pFans0, nRange, WLC_OBJ_REDUCT_OR ); assert( nRange == 1 ); Vec_IntPush( vBits, Abc_LitNot(iLit) ); } else if ( pObj->Type == WLC_OBJ_LOGIC_AND ) { int iLit0 = Wlc_NtkComputeReduction( pNew, pFans0, nRange, WLC_OBJ_REDUCT_OR ); int iLit1 = Wlc_NtkComputeReduction( pNew, pFans0, nRange, WLC_OBJ_REDUCT_OR ); assert( nRange == 1 ); Vec_IntPush( vBits, Gia_ManHashAnd(pNew, iLit0, iLit1) ); } else if ( pObj->Type == WLC_OBJ_LOGIC_OR ) { int iLit0 = Wlc_NtkComputeReduction( pNew, pFans0, nRange, WLC_OBJ_REDUCT_OR ); int iLit1 = Wlc_NtkComputeReduction( pNew, pFans0, nRange, WLC_OBJ_REDUCT_OR ); assert( nRange == 1 ); Vec_IntPush( vBits, Gia_ManHashOr(pNew, iLit0, iLit1) ); } else if ( pObj->Type == WLC_OBJ_COMP_EQU || pObj->Type == WLC_OBJ_COMP_NOT ) { int iLit = 0; assert( nRange == 1 ); assert( nRange0 == nRange1 ); for ( k = 0; k < nRange0; k++ ) iLit = Gia_ManHashOr( pNew, iLit, Gia_ManHashXor(pNew, pFans0[k], pFans1[k]) ); Vec_IntPush( vBits, Abc_LitNotCond(iLit, pObj->Type == WLC_OBJ_COMP_EQU) ); } else if ( pObj->Type == WLC_OBJ_COMP_LESS || pObj->Type == WLC_OBJ_COMP_MOREEQU || pObj->Type == WLC_OBJ_COMP_MORE || pObj->Type == WLC_OBJ_COMP_LESSEQU ) { int iTerm, iEqu = 1, iLit = 0; assert( nRange == 1 ); assert( nRange0 == nRange1 ); if ( pObj->Type == WLC_OBJ_COMP_MORE || pObj->Type == WLC_OBJ_COMP_LESSEQU ) ABC_SWAP( int *, pFans0, pFans1 ); for ( k = nRange0 - 1; k >= 0; k-- ) { iTerm = Gia_ManHashAnd( pNew, Abc_LitNot(pFans0[k]), pFans1[k] ); iTerm = Gia_ManHashAnd( pNew, iTerm, iEqu ); iLit = Gia_ManHashOr( pNew, iLit, iTerm ); iEqu = Abc_LitNot( Gia_ManHashXor( pNew, pFans0[k], pFans1[k] ) ); } Vec_IntPush( vBits, Abc_LitNotCond(iLit, pObj->Type == WLC_OBJ_COMP_MOREEQU) ); } else if ( pObj->Type == WLC_OBJ_REDUCT_AND || pObj->Type == WLC_OBJ_REDUCT_OR || pObj->Type == WLC_OBJ_REDUCT_XOR ) Vec_IntPush( vBits, Wlc_NtkComputeReduction( pNew, pFans0, nRange, pObj->Type ) ); else if ( pObj->Type == WLC_OBJ_ARI_ADD ) { int Pad0 = Wlc_ObjFanin0(p, pObj)->Signed ? pFans0[nRange0-1] : 0; int Pad1 = Wlc_ObjFanin1(p, pObj)->Signed ? pFans1[nRange1-1] : 0; assert( nRange0 <= nRange && nRange1 <= nRange ); Vec_IntClear( vTemp0 ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vTemp0, k < nRange0 ? pFans0[k] : Pad0 ); Vec_IntClear( vTemp1 ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vTemp1, k < nRange1 ? pFans1[k] : Pad1 ); Wlc_NtkAdderChain( pNew, Vec_IntArray(vTemp0), Vec_IntArray(vTemp1), nRange ); Vec_IntAppend( vBits, vTemp0 ); } else if ( pObj->Type == WLC_OBJ_ARI_MULTI ) { int Pad0 = Wlc_ObjFanin0(p, pObj)->Signed ? pFans0[nRange0-1] : 0; int Pad1 = Wlc_ObjFanin1(p, pObj)->Signed ? pFans1[nRange1-1] : 0; assert( nRange0 <= nRange && nRange1 <= nRange ); Vec_IntClear( vTemp0 ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vTemp0, k < nRange0 ? pFans0[k] : Pad0 ); Vec_IntClear( vTemp1 ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vTemp1, k < nRange1 ? pFans1[k] : Pad1 ); // iterate Vec_IntFill( vTemp3, nRange, 0 ); for ( k = 0; k < nRange; k++ ) { Vec_IntFill( vTemp2, k, 0 ); Vec_IntForEachEntry( vTemp0, iLit, b ) { Vec_IntPush( vTemp2, Gia_ManHashAnd(pNew, iLit, Vec_IntEntry(vTemp1, k)) ); if ( Vec_IntSize(vTemp2) == nRange ) break; } assert( Vec_IntSize(vTemp2) == nRange ); Wlc_NtkAdderChain( pNew, Vec_IntArray(vTemp3), Vec_IntArray(vTemp2), nRange ); } assert( Vec_IntSize(vTemp3) == nRange ); Vec_IntAppend( vBits, vTemp3 ); } else assert( 0 ); } assert( nBits == Vec_IntSize(vBits) ); Vec_IntFree( vTemp0 ); Vec_IntFree( vTemp1 ); Vec_IntFree( vTemp2 ); Vec_IntFree( vTemp3 ); // create POs Wlc_NtkForEachPo( p, pObj, i ) { nRange = Wlc_ObjRange( pObj ); nRange0 = Wlc_ObjFaninNum(pObj) > 0 ? Wlc_ObjRange( Wlc_ObjFanin0(p, pObj) ) : -1; assert( nRange == nRange0 ); pFans0 = Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjId(p, pObj)) ); for ( k = 0; k < nRange; k++ ) Gia_ManAppendCo( pNew, pFans0[k] ); } Vec_IntFree( vBits ); Vec_IntErase( &p->vCopies ); // finalize and cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END