| /**CFile**************************************************************** |
| |
| FileName [acecCl.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: acecCl.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 [] |
| |
| ***********************************************************************/ |
| void Acec_ManDerive_rec( Gia_Man_t * pNew, Gia_Man_t * p, int Node, Vec_Int_t * vMirrors ) |
| { |
| Gia_Obj_t * pObj; |
| int Obj = Node; |
| if ( Vec_IntEntry(vMirrors, Node) >= 0 ) |
| Obj = Abc_Lit2Var( Vec_IntEntry(vMirrors, Node) ); |
| pObj = Gia_ManObj( p, Obj ); |
| if ( !~pObj->Value ) |
| { |
| assert( Gia_ObjIsAnd(pObj) ); |
| Acec_ManDerive_rec( pNew, p, Gia_ObjFaninId0(pObj, Obj), vMirrors ); |
| Acec_ManDerive_rec( pNew, p, Gia_ObjFaninId1(pObj, Obj), vMirrors ); |
| if ( Gia_ObjIsXor(pObj) ) |
| pObj->Value = Gia_ManAppendXorReal( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); |
| else |
| pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); |
| } |
| // set the original node as well |
| if ( Obj != Node ) |
| Gia_ManObj(p, Node)->Value = Abc_LitNotCond( pObj->Value, Abc_LitIsCompl(Vec_IntEntry(vMirrors, Node)) ); |
| } |
| Gia_Man_t * Acec_ManDerive( Gia_Man_t * p, Vec_Int_t * vMirrors ) |
| { |
| Gia_Man_t * pNew; |
| Gia_Obj_t * pObj; |
| int i; |
| assert( p->pMuxes == NULL ); |
| Gia_ManFillValue( p ); |
| pNew = Gia_ManStart( Gia_ManObjNum(p) ); |
| pNew->pName = Abc_UtilStrsav( p->pName ); |
| pNew->pSpec = Abc_UtilStrsav( p->pSpec ); |
| Gia_ManConst0(p)->Value = 0; |
| Gia_ManHashAlloc( pNew ); |
| Gia_ManForEachCi( p, pObj, i ) |
| pObj->Value = Gia_ManAppendCi(pNew); |
| Gia_ManForEachCo( p, pObj, i ) |
| Acec_ManDerive_rec( pNew, p, Gia_ObjFaninId0p(p, pObj), vMirrors ); |
| Gia_ManForEachCo( p, pObj, i ) |
| pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); |
| Gia_ManHashStop( pNew ); |
| Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); |
| return pNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Acec_CollectXorTops( Gia_Man_t * p ) |
| { |
| Vec_Int_t * vRootXorSet = Vec_IntAlloc( Gia_ManCoNum(p) ); |
| Gia_Obj_t * pObj, * pFan0, * pFan1, * pFan00, * pFan01, * pFan10, * pFan11; |
| int i, fXor0, fXor1, fFirstXor = 0; |
| Gia_ManForEachCoDriver( p, pObj, i ) |
| { |
| if ( !Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) |
| { |
| if ( fFirstXor ) |
| { |
| printf( "XORs do not form a continuous sequence\n" ); |
| Vec_IntFreeP( &vRootXorSet ); |
| break; |
| } |
| continue; |
| } |
| fFirstXor = 1; |
| fXor0 = Gia_ObjRecognizeExor(Gia_Regular(pFan0), &pFan00, &pFan01); |
| fXor1 = Gia_ObjRecognizeExor(Gia_Regular(pFan1), &pFan10, &pFan11); |
| if ( fXor0 == fXor1 ) |
| { |
| printf( "Both inputs of top level XOR have XOR/non-XOR\n" ); |
| Vec_IntFreeP( &vRootXorSet ); |
| break; |
| } |
| Vec_IntPush( vRootXorSet, Gia_ObjId(p, pObj) ); |
| Vec_IntPush( vRootXorSet, fXor1 ? Gia_ObjId(p, Gia_Regular(pFan0)) : Gia_ObjId(p, Gia_Regular(pFan1)) ); |
| Vec_IntPush( vRootXorSet, fXor1 ? Gia_ObjId(p, Gia_Regular(pFan10)) : Gia_ObjId(p, Gia_Regular(pFan00)) ); |
| Vec_IntPush( vRootXorSet, fXor1 ? Gia_ObjId(p, Gia_Regular(pFan11)) : Gia_ObjId(p, Gia_Regular(pFan01)) ); |
| } |
| for ( i = 0; 4*i < Vec_IntSize(vRootXorSet); i++ ) |
| { |
| printf( "%2d : ", i ); |
| printf( "%4d <- ", Vec_IntEntry(vRootXorSet, 4*i) ); |
| printf( "%4d ", Vec_IntEntry(vRootXorSet, 4*i+1) ); |
| printf( "%4d ", Vec_IntEntry(vRootXorSet, 4*i+2) ); |
| printf( "%4d ", Vec_IntEntry(vRootXorSet, 4*i+3) ); |
| printf( "\n" ); |
| } |
| return vRootXorSet; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Acec_DetectLitPolarity( Gia_Man_t * p, int Node, int Leaf ) |
| { |
| Gia_Obj_t * pNode; |
| int Lit0, Lit1; |
| if ( Node < Leaf ) |
| return -1; |
| if ( Node == Leaf ) |
| return Abc_Var2Lit(Node, 0); |
| pNode = Gia_ManObj( p, Node ); |
| Lit0 = Acec_DetectLitPolarity( p, Gia_ObjFaninId0(pNode, Node), Leaf ); |
| Lit1 = Acec_DetectLitPolarity( p, Gia_ObjFaninId1(pNode, Node), Leaf ); |
| Lit0 = Lit0 == -1 ? Lit0 : Abc_LitNotCond( Lit0, Gia_ObjFaninC0(pNode) ); |
| Lit1 = Lit1 == -1 ? Lit1 : Abc_LitNotCond( Lit1, Gia_ObjFaninC1(pNode) ); |
| if ( Lit0 == -1 && Lit1 == -1 ) |
| return -1; |
| assert( Lit0 != -1 || Lit1 != -1 ); |
| if ( Lit0 != -1 && Lit1 != -1 ) |
| { |
| assert( Lit0 == Lit1 ); |
| printf( "Problem for leaf %d\n", Leaf ); |
| return Lit0; |
| } |
| return Lit0 != -1 ? Lit0 : Lit1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Acec_DetectComputeSuppOne_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp, Vec_Int_t * vNods ) |
| { |
| if ( Gia_ObjIsTravIdCurrent(p, pObj) ) |
| return; |
| Gia_ObjSetTravIdCurrent(p, pObj); |
| if ( pObj->fMark0 ) |
| { |
| Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); |
| return; |
| } |
| assert( Gia_ObjIsAnd(pObj) ); |
| Acec_DetectComputeSuppOne_rec( p, Gia_ObjFanin0(pObj), vSupp, vNods ); |
| Acec_DetectComputeSuppOne_rec( p, Gia_ObjFanin1(pObj), vSupp, vNods ); |
| Vec_IntPush( vNods, Gia_ObjId(p, pObj) ); |
| } |
| void Acec_DetectComputeSupports( Gia_Man_t * p, Vec_Int_t * vRootXorSet ) |
| { |
| Vec_Int_t * vNods = Vec_IntAlloc( 100 ); |
| Vec_Int_t * vPols = Vec_IntAlloc( 100 ); |
| Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); int i, k, Node, Pol; |
| for ( i = 0; 4*i < Vec_IntSize(vRootXorSet); i++ ) |
| { |
| Gia_ManObj( p, Vec_IntEntry(vRootXorSet, 4*i+1) )->fMark0 = 1; |
| Gia_ManObj( p, Vec_IntEntry(vRootXorSet, 4*i+2) )->fMark0 = 1; |
| Gia_ManObj( p, Vec_IntEntry(vRootXorSet, 4*i+3) )->fMark0 = 1; |
| } |
| for ( i = 1; 4*i < Vec_IntSize(vRootXorSet); i++ ) |
| { |
| Vec_IntClear( vSupp ); |
| Gia_ManIncrementTravId( p ); |
| |
| Gia_ManObj( p, Vec_IntEntry(vRootXorSet, 4*i+1) )->fMark0 = 0; |
| Acec_DetectComputeSuppOne_rec( p, Gia_ManObj( p, Vec_IntEntry(vRootXorSet, 4*i+1) ), vSupp, vNods ); |
| Gia_ManObj( p, Vec_IntEntry(vRootXorSet, 4*i+1) )->fMark0 = 1; |
| |
| Vec_IntSort( vSupp, 0 ); |
| |
| printf( "Out %4d : %4d \n", i, Vec_IntEntry(vRootXorSet, 4*i+1) ); |
| Vec_IntPrint( vSupp ); |
| |
| printf( "Cone:\n" ); |
| Vec_IntForEachEntry( vNods, Node, k ) |
| Gia_ObjPrint( p, Gia_ManObj(p, Node) ); |
| |
| |
| Vec_IntClear( vPols ); |
| Vec_IntForEachEntry( vSupp, Node, k ) |
| Vec_IntPush( vPols, Acec_DetectLitPolarity(p, Vec_IntEntry(vRootXorSet, 4*i+1), Node) ); |
| |
| Vec_IntForEachEntryTwo( vSupp, vPols, Node, Pol, k ) |
| printf( "%d(%d) ", Node, Abc_LitIsCompl(Pol) ); |
| |
| printf( "\n" ); |
| |
| Vec_IntPrint( vSupp ); |
| } |
| for ( i = 0; 4*i < Vec_IntSize(vRootXorSet); i++ ) |
| { |
| Gia_ManObj( p, Vec_IntEntry(vRootXorSet, 4*i+1) )->fMark0 = 0; |
| Gia_ManObj( p, Vec_IntEntry(vRootXorSet, 4*i+2) )->fMark0 = 0; |
| Gia_ManObj( p, Vec_IntEntry(vRootXorSet, 4*i+3) )->fMark0 = 0; |
| } |
| Vec_IntFree( vSupp ); |
| Vec_IntFree( vPols ); |
| Vec_IntFree( vNods ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Gia_Man_t * Acec_DetectXorBuildNew( Gia_Man_t * p, Vec_Int_t * vRootXorSet ) |
| { |
| Gia_Man_t * pNew; |
| int i, k, iOr1, iAnd1, iAnd2, pLits[3]; // carry, in1, in2 |
| Vec_Int_t * vMirrors = Vec_IntStart( Gia_ManObjNum(p) ); |
| for ( i = 0; 4*i < Vec_IntSize(vRootXorSet); i++ ) |
| { |
| pLits[0] = Acec_DetectLitPolarity( p, Vec_IntEntry(vRootXorSet, 4*i), Vec_IntEntry(vRootXorSet, 4*i+1) ); |
| // get polarity of two new ones |
| for ( k = 1; k < 3; k++ ) |
| pLits[k] = Acec_DetectLitPolarity( p, Vec_IntEntry(vRootXorSet, 4*i), Vec_IntEntry(vRootXorSet, 4*i+k+1) ); |
| // create the gate |
| iOr1 = Gia_ManAppendOr( p, pLits[1], pLits[2] ); |
| iAnd1 = Gia_ManAppendAnd( p, pLits[0], iOr1 ); |
| iAnd2 = Gia_ManAppendAnd( p, pLits[1], pLits[2] ); |
| pLits[0] = Gia_ManAppendOr( p, iAnd1, iAnd2 ); |
| Vec_IntWriteEntry( vMirrors, Vec_IntEntry(vRootXorSet, 4*i+1), pLits[0] ); |
| } |
| // remap the AIG using map |
| pNew = Acec_ManDerive( p, vMirrors ); |
| Vec_IntFree( vMirrors ); |
| return pNew; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Gia_Man_t * Acec_DetectAdditional( Gia_Man_t * p, int fVerbose ) |
| { |
| abctime clk = Abc_Clock(); |
| Gia_Man_t * pNew; |
| Vec_Int_t * vRootXorSet; |
| // Vec_Int_t * vXors, * vAdds = Ree_ManComputeCuts( p, &vXors, 0 ); |
| |
| //Ree_ManPrintAdders( vAdds, 1 ); |
| // printf( "Detected %d full-adders and %d half-adders. Found %d XOR-cuts. ", Ree_ManCountFadds(vAdds), Vec_IntSize(vAdds)/6-Ree_ManCountFadds(vAdds), Vec_IntSize(vXors)/4 ); |
| // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| |
| clk = Abc_Clock(); |
| vRootXorSet = Acec_CollectXorTops( p ); |
| if ( vRootXorSet ) |
| { |
| Acec_DetectComputeSupports( p, vRootXorSet ); |
| |
| pNew = Acec_DetectXorBuildNew( p, vRootXorSet ); |
| Vec_IntFree( vRootXorSet ); |
| } |
| else |
| pNew = Gia_ManDup( p ); |
| |
| printf( "Detected %d top XORs. ", Vec_IntSize(vRootXorSet)/4 ); |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| |
| // Vec_IntFree( vXors ); |
| // Vec_IntFree( vAdds ); |
| return pNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Acec_RewriteTop( Gia_Man_t * p, Acec_Box_t * pBox ) |
| { |
| Vec_Int_t * vRes = Vec_IntAlloc( Gia_ManCoNum(p) + 1 ); |
| Vec_Int_t * vLevel; |
| int i, k, iStart, iLit, Driver, Count = 0; |
| // determine how much to shift |
| Driver = Gia_ObjFaninId0p( p, Gia_ManCo(p, 0) ); |
| Vec_WecForEachLevel( pBox->vRootLits, vLevel, iStart ) |
| if ( Abc_Lit2Var(Vec_IntEntry(vLevel,0)) == Driver ) |
| break; |
| assert( iStart < Gia_ManCoNum(p) ); |
| //Vec_WecPrintLits( pBox->vRootLits ); |
| Vec_WecForEachLevelStart( pBox->vRootLits, vLevel, i, iStart ) |
| { |
| int In[3] = {0}, Out[2]; |
| assert( Vec_IntSize(vLevel) > 0 ); |
| assert( Vec_IntSize(vLevel) <= 3 ); |
| if ( Vec_IntSize(vLevel) == 1 ) |
| { |
| Vec_IntPush( vRes, Vec_IntEntry(vLevel, 0) ); |
| continue; |
| } |
| Vec_IntForEachEntry( vLevel, iLit, k ) |
| In[k] = iLit; |
| Acec_InsertFadd( p, In, Out ); |
| Vec_IntPush( vRes, Out[0] ); |
| if ( i+1 < Vec_WecSize(pBox->vRootLits) ) |
| Vec_IntPush( Vec_WecEntry(pBox->vRootLits, i+1), Out[1] ); |
| else |
| Vec_IntPush( Vec_WecPushLevel(pBox->vRootLits), Out[1] ); |
| Count++; |
| } |
| assert( Vec_IntSize(vRes) >= Gia_ManCoNum(p) ); |
| Vec_IntShrink( vRes, Gia_ManCoNum(p) ); |
| printf( "Added %d adders for replace CLAs. ", Count ); |
| return vRes; |
| } |
| Gia_Man_t * Acec_RewriteReplace( Gia_Man_t * p, Vec_Int_t * vRes ) |
| { |
| Gia_Man_t * pNew, * pTemp; |
| Gia_Obj_t * pObj; int i; |
| assert( Gia_ManCoNum(p) == Vec_IntSize(vRes) ); |
| // create new manager |
| pNew = Gia_ManStart( Gia_ManObjNum(p) ); |
| pNew->pName = Abc_UtilStrsav( p->pName ); |
| pNew->pSpec = Abc_UtilStrsav( p->pSpec ); |
| Gia_ManFillValue( p ); |
| Gia_ManConst0(p)->Value = 0; |
| Gia_ManForEachCi( p, pObj, i ) |
| pObj->Value = Gia_ManAppendCi(pNew); |
| Gia_ManForEachAnd( p, pObj, i ) |
| pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); |
| Gia_ManForEachCo( p, pObj, i ) |
| { |
| int iLit = Vec_IntEntry( vRes, i ); |
| Gia_Obj_t * pRepr = Gia_ManObj( p, Abc_Lit2Var(iLit) ); |
| pObj->Value = Gia_ManAppendCo( pNew, pRepr->Value ); |
| } |
| // set correct phase |
| Gia_ManSetPhase( p ); |
| Gia_ManSetPhase( pNew ); |
| Gia_ManForEachCo( pNew, pObj, i ) |
| if ( Gia_ObjPhase(pObj) != Gia_ObjPhase(Gia_ManCo(p, i)) ) |
| Gia_ObjFlipFaninC0( pObj ); |
| // remove dangling nodes |
| pNew = Gia_ManCleanup( pTemp = pNew ); |
| Gia_ManStop( pTemp ); |
| return pNew; |
| } |
| Gia_Man_t * Acec_ManDecla( Gia_Man_t * pGia, int fBooth, int fVerbose ) |
| { |
| abctime clk = Abc_Clock(); |
| Gia_Man_t * pNew = NULL; |
| Vec_Bit_t * vIgnore = fBooth ? Acec_BoothFindPPG(pGia) : NULL; |
| Acec_Box_t * pBox = Acec_DeriveBox( pGia, vIgnore, 0, 0, fVerbose ); |
| Vec_Int_t * vResult; |
| Vec_BitFreeP( &vIgnore ); |
| if ( pBox == NULL ) // cannot match |
| { |
| printf( "Cannot find arithmetic boxes.\n" ); |
| return Gia_ManDup( pGia ); |
| } |
| vResult = Acec_RewriteTop( pGia, pBox ); |
| Acec_BoxFreeP( &pBox ); |
| pNew = Acec_RewriteReplace( pGia, vResult ); |
| Vec_IntFree( vResult ); |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| return pNew; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |