/**CFile**************************************************************** FileName [acecPa.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acecPa.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "acecInt.h" #include "misc/vec/vecWec.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pas_ManVerifyPhaseOne_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { int Truth0, Truth1; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return pObj->Value; Gia_ObjSetTravIdCurrent(p, pObj); assert( Gia_ObjIsAnd(pObj) ); assert( !Gia_ObjIsXor(pObj) ); Truth0 = Pas_ManVerifyPhaseOne_rec( p, Gia_ObjFanin0(pObj) ); Truth1 = Pas_ManVerifyPhaseOne_rec( p, Gia_ObjFanin1(pObj) ); Truth0 = Gia_ObjFaninC0(pObj) ? 0xFF & ~Truth0 : Truth0; Truth1 = Gia_ObjFaninC1(pObj) ? 0xFF & ~Truth1 : Truth1; return (pObj->Value = Truth0 & Truth1); } void Pas_ManVerifyPhaseOne( Gia_Man_t * p, Vec_Int_t * vAdds, int iBox, Vec_Bit_t * vPhase ) { Gia_Obj_t * pObj; unsigned TruthXor, TruthMaj, Truths[3] = { 0xAA, 0xCC, 0xF0 }; int k, iObj, fFadd = Vec_IntEntry(vAdds, 6*iBox+2) > 0; if ( !fFadd ) return; Gia_ManIncrementTravId( p ); for ( k = 0; k < 3; k++ ) { iObj = Vec_IntEntry( vAdds, 6*iBox+k ); if ( iObj == 0 ) continue; pObj = Gia_ManObj( p, iObj ); pObj->Value = Vec_BitEntry(vPhase, iObj) ? 0xFF & ~Truths[k] : Truths[k]; Gia_ObjSetTravIdCurrent( p, pObj ); } iObj = Vec_IntEntry( vAdds, 6*iBox+3 ); TruthXor = Pas_ManVerifyPhaseOne_rec( p, Gia_ManObj(p, iObj) ); TruthXor = Vec_BitEntry(vPhase, iObj) ? 0xFF & ~TruthXor : TruthXor; iObj = Vec_IntEntry( vAdds, 6*iBox+4 ); TruthMaj = Pas_ManVerifyPhaseOne_rec( p, Gia_ManObj(p, iObj) ); TruthMaj = Vec_BitEntry(vPhase, iObj) ? 0xFF & ~TruthMaj : TruthMaj; if ( fFadd ) // FADD { if ( TruthXor != 0x96 ) printf( "Fadd %d sum is wrong.\n", iBox ); if ( TruthMaj != 0xE8 ) printf( "Fadd %d carry is wrong.\n", iBox ); } else { if ( TruthXor != 0x66 ) printf( "Hadd %d sum is wrong.\n", iBox ); if ( TruthMaj != 0x88 ) printf( "Hadd %d carry is wrong.\n", iBox ); } } void Pas_ManVerifyPhase( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vOrder, Vec_Bit_t * vPhase ) { int k, iBox; Vec_IntForEachEntry( vOrder, iBox, k ) Pas_ManVerifyPhaseOne( p, vAdds, iBox, vPhase ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pas_ManPhase_rec( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vMap, Gia_Obj_t * pObj, int fPhase, Vec_Bit_t * vPhase, Vec_Bit_t * vConstPhase ) { int k, iBox, iXor, Sign, fXorPhase; assert( pObj != Gia_ManConst0(p) ); if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( fPhase ) Vec_BitWriteEntry( vPhase, Gia_ObjId(p, pObj), fPhase ); if ( !Gia_ObjIsAnd(pObj) ) return; iBox = Vec_IntEntry( vMap, Gia_ObjId(p, pObj) ); if ( iBox == -1 ) return; iXor = Vec_IntEntry( vAdds, 6*iBox+3 ); Sign = Vec_IntEntry( vAdds, 6*iBox+5 ); fXorPhase = ((Sign >> 3) & 1); // remember complemented HADD if ( Vec_IntEntry(vAdds, 6*iBox+2) == 0 && fPhase ) Vec_BitWriteEntry( vConstPhase, iBox, 1 ); for ( k = 0; k < 3; k++ ) { int iObj = Vec_IntEntry( vAdds, 6*iBox+k ); int fPhaseThis = ((Sign >> k) & 1) ^ fPhase; fXorPhase ^= fPhaseThis; if ( iObj == 0 ) continue; Pas_ManPhase_rec( p, vAdds, vMap, Gia_ManObj(p, iObj), fPhaseThis, vPhase, vConstPhase ); } Vec_BitWriteEntry( vPhase, iXor, fXorPhase ); } Vec_Bit_t * Pas_ManPhase( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vMap, Vec_Int_t * vRoots, Vec_Bit_t ** pvConstPhase ) { Vec_Bit_t * vPhase = Vec_BitStart( Vec_IntSize(vMap) ); Vec_Bit_t * vConstPhase = Vec_BitStart( Vec_IntSize(vAdds)/6 ); int i, iRoot; Gia_ManIncrementTravId( p ); Vec_IntForEachEntry( vRoots, iRoot, i ) Pas_ManPhase_rec( p, vAdds, vMap, Gia_ManObj(p, iRoot), 1, vPhase, vConstPhase ); *pvConstPhase = vConstPhase; return vPhase; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pas_ManComputeCuts( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vOrder, Vec_Int_t * vIns, Vec_Int_t * vOuts ) { Vec_Bit_t * vUnique = Vec_BitStart( Gia_ManObjNum(p) ); Vec_Bit_t * vUsed = Vec_BitStart( Gia_ManObjNum(p) ); Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); Vec_Int_t * vRoots = Vec_IntAlloc( 100 ); Vec_Bit_t * vPhase, * vConstPhase; int i, k, Entry, nTrees; // map carries into adder indexes and mark driven nodes Vec_IntForEachEntry( vOrder, i, k ) { int Carry = Vec_IntEntry(vAdds, 6*i+4); if ( Vec_BitEntry(vUnique, Carry) ) printf( "Carry %d participates more than once.\n", Carry ); Vec_BitWriteEntry( vUnique, Carry, 1 ); Vec_IntWriteEntry( vMap, Carry, i ); // mark driven Vec_BitWriteEntry( vUsed, Vec_IntEntry(vAdds, 6*i+0), 1 ); Vec_BitWriteEntry( vUsed, Vec_IntEntry(vAdds, 6*i+1), 1 ); Vec_BitWriteEntry( vUsed, Vec_IntEntry(vAdds, 6*i+2), 1 ); } // collect carries that do not drive other adders for ( i = 0; i < Gia_ManObjNum(p); i++ ) if ( Vec_BitEntry(vUnique, i) && !Vec_BitEntry(vUsed, i) ) Vec_IntPush( vRoots, i ); nTrees = Vec_IntSize( vRoots ); Vec_IntPrint( vRoots ); // compute phases if ( Vec_IntSize(vRoots) > 0 ) { int nCompls = 0; vPhase = Pas_ManPhase( p, vAdds, vMap, vRoots, &vConstPhase ); Pas_ManVerifyPhase( p, vAdds, vOrder, vPhase ); printf( "Outputs: " ); Vec_IntForEachEntry( vOuts, Entry, i ) printf( "%d(%d) ", Entry, Vec_BitEntry(vPhase, Entry) ); printf( "\n" ); printf( "Inputs: " ); Vec_IntForEachEntry( vIns, Entry, i ) { printf( "%d(%d) ", Entry, Vec_BitEntry(vPhase, Entry) ); nCompls += Vec_BitEntry(vPhase, Entry); } printf( " Compl = %d\n", nCompls ); Vec_BitFreeP( &vPhase ); Vec_BitFreeP( &vConstPhase ); } Vec_IntFree( vRoots ); Vec_IntFree( vMap ); Vec_BitFree( vUnique ); Vec_BitFree( vUsed ); return nTrees; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pas_ManComputeCutsTest( Gia_Man_t * p ) { abctime clk = Abc_Clock(); Vec_Int_t * vAdds = Ree_ManComputeCuts( p, NULL, 1 ); Vec_Int_t * vIns, * vOuts; Vec_Int_t * vOrder = Gia_PolynCoreOrder( p, vAdds, NULL, &vIns, &vOuts ); int nTrees, nFadds = Ree_ManCountFadds( vAdds ); //Ree_ManPrintAdders( vAdds, 1 ); printf( "Detected %d FAs and %d HAs. Collected %d adders. ", nFadds, Vec_IntSize(vAdds)/6-nFadds, Vec_IntSize(vOrder) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // detect trees clk = Abc_Clock(); nTrees = Pas_ManComputeCuts( p, vAdds, vOrder, vIns, vOuts ); Vec_IntFree( vAdds ); Vec_IntFree( vOrder ); Vec_IntFree( vIns ); Vec_IntFree( vOuts ); printf( "Detected %d adder trees. ", nTrees ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END