| /**CFile**************************************************************** |
| |
| FileName [giaTruth.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Scalable AIG package.] |
| |
| Synopsis [Truth table computation.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: giaTruth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "gia.h" |
| #include "misc/vec/vecMem.h" |
| #include "misc/vec/vecWec.h" |
| #include "misc/util/utilTruth.h" |
| #include "opt/dau/dau.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| static word s_Truth6[6] = { |
| ABC_CONST(0xAAAAAAAAAAAAAAAA), |
| ABC_CONST(0xCCCCCCCCCCCCCCCC), |
| ABC_CONST(0xF0F0F0F0F0F0F0F0), |
| ABC_CONST(0xFF00FF00FF00FF00), |
| ABC_CONST(0xFFFF0000FFFF0000), |
| ABC_CONST(0xFFFFFFFF00000000) |
| }; |
| |
| static inline word * Gla_ObjTruthElem( Gia_Man_t * p, int i ) { return (word *)Vec_PtrEntry( p->vTtInputs, i ); } |
| static inline word * Gla_ObjTruthNodeId( Gia_Man_t * p, int Id ) { return Vec_WrdArray(p->vTtMemory) + p->nTtWords * Id; } |
| static inline word * Gla_ObjTruthNode( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_WrdArray(p->vTtMemory) + p->nTtWords * Gia_ObjNum(p, pObj); } |
| static inline word * Gla_ObjTruthFree1( Gia_Man_t * p ) { return Vec_WrdArray(p->vTtMemory) + Vec_WrdSize(p->vTtMemory) - p->nTtWords * 1; } |
| static inline word * Gla_ObjTruthFree2( Gia_Man_t * p ) { return Vec_WrdArray(p->vTtMemory) + Vec_WrdSize(p->vTtMemory) - p->nTtWords * 2; } |
| static inline word * Gla_ObjTruthConst0( Gia_Man_t * p, word * pDst ) { int w; for ( w = 0; w < p->nTtWords; w++ ) pDst[w] = 0; return pDst; } |
| static inline word * Gla_ObjTruthDup( Gia_Man_t * p, word * pDst, word * pSrc, int c ) { int w; for ( w = 0; w < p->nTtWords; w++ ) pDst[w] = c ? ~pSrc[w] : pSrc[w]; return pDst; } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compute truth table.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| word Gia_LutComputeTruth6_rec( Gia_Man_t * p, int iNode, Vec_Wrd_t * vTruths ) |
| { |
| Gia_Obj_t * pObj; |
| word Truth0, Truth1; |
| if ( Gia_ObjIsTravIdCurrentId(p, iNode) ) |
| return Vec_WrdEntry(vTruths, iNode); |
| Gia_ObjSetTravIdCurrentId(p, iNode); |
| pObj = Gia_ManObj( p, iNode ); |
| assert( Gia_ObjIsAnd(pObj) ); |
| Truth0 = Gia_LutComputeTruth6_rec( p, Gia_ObjFaninId0p(p, pObj), vTruths ); |
| Truth1 = Gia_LutComputeTruth6_rec( p, Gia_ObjFaninId1p(p, pObj), vTruths ); |
| if ( Gia_ObjFaninC0(pObj) ) |
| Truth0 = ~Truth0; |
| if ( Gia_ObjFaninC1(pObj) ) |
| Truth1 = ~Truth1; |
| Vec_WrdWriteEntry( vTruths, iNode, Truth0 & Truth1 ); |
| return Truth0 & Truth1; |
| } |
| word Gia_LutComputeTruth6( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTruths ) |
| { |
| int k, iFan; |
| assert( Gia_ObjIsLut(p, iObj) ); |
| Gia_ManIncrementTravId( p ); |
| Gia_LutForEachFanin( p, iObj, iFan, k ) |
| { |
| Vec_WrdWriteEntry( vTruths, iFan, s_Truths6[k] ); |
| Gia_ObjSetTravIdCurrentId( p, iFan ); |
| } |
| return Gia_LutComputeTruth6_rec( p, iObj, vTruths ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes truth table of a 6-LUT.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Gia_ObjComputeTruthTable6Lut_rec( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTemp ) |
| { |
| word uTruth0, uTruth1; |
| Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); |
| if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) |
| return; |
| Gia_ObjSetTravIdCurrentId(p, iObj); |
| assert( Gia_ObjIsAnd(pObj) ); |
| Gia_ObjComputeTruthTable6Lut_rec( p, Gia_ObjFaninId0p(p, pObj), vTemp ); |
| Gia_ObjComputeTruthTable6Lut_rec( p, Gia_ObjFaninId1p(p, pObj), vTemp ); |
| uTruth0 = Vec_WrdEntry( vTemp, Gia_ObjFaninId0p(p, pObj) ); |
| uTruth0 = Gia_ObjFaninC0(pObj) ? ~uTruth0 : uTruth0; |
| uTruth1 = Vec_WrdEntry( vTemp, Gia_ObjFaninId1p(p, pObj) ); |
| uTruth1 = Gia_ObjFaninC1(pObj) ? ~uTruth1 : uTruth1; |
| Vec_WrdWriteEntry( vTemp, iObj, uTruth0 & uTruth1 ); |
| } |
| word Gia_ObjComputeTruthTable6Lut( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTemp ) |
| { |
| int i, Fanin; |
| assert( Vec_WrdSize(vTemp) == Gia_ManObjNum(p) ); |
| assert( Gia_ObjIsLut(p, iObj) ); |
| Gia_ManIncrementTravId( p ); |
| Gia_LutForEachFanin( p, iObj, Fanin, i ) |
| { |
| Gia_ObjSetTravIdCurrentId( p, Fanin ); |
| Vec_WrdWriteEntry( vTemp, Fanin, s_Truth6[i] ); |
| } |
| assert( i <= 6 ); |
| Gia_ObjComputeTruthTable6Lut_rec( p, iObj, vTemp ); |
| return Vec_WrdEntry( vTemp, iObj ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes truth table up to 6 inputs in terms of CIs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| word Gia_ObjComputeTruth6( Gia_Man_t * p, int iObj, Vec_Int_t * vSupp, Vec_Wrd_t * vTemp ) |
| { |
| int i, Fanin; |
| assert( Vec_WrdSize(vTemp) == Gia_ManObjNum(p) ); |
| assert( Vec_IntSize(vSupp) <= 6 ); |
| Gia_ManIncrementTravId( p ); |
| Vec_IntForEachEntry( vSupp, Fanin, i ) |
| { |
| Gia_ObjSetTravIdCurrentId( p, Fanin ); |
| Vec_WrdWriteEntry( vTemp, Fanin, s_Truth6[i] ); |
| } |
| Gia_ObjComputeTruthTable6Lut_rec( p, iObj, vTemp ); |
| return Vec_WrdEntry( vTemp, iObj ); |
| } |
| void Gia_ObjComputeTruth6CisSupport_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vSupp ) |
| { |
| Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); |
| if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) |
| return; |
| Gia_ObjSetTravIdCurrentId(p, iObj); |
| if ( Gia_ObjIsCi(pObj) ) |
| { |
| Vec_IntPushOrder( vSupp, iObj ); |
| return; |
| } |
| assert( Gia_ObjIsAnd(pObj) ); |
| Gia_ObjComputeTruth6CisSupport_rec( p, Gia_ObjFaninId0p(p, pObj), vSupp ); |
| Gia_ObjComputeTruth6CisSupport_rec( p, Gia_ObjFaninId1p(p, pObj), vSupp ); |
| } |
| word Gia_ObjComputeTruth6Cis( Gia_Man_t * p, int iLit, Vec_Int_t * vSupp, Vec_Wrd_t * vTemp ) |
| { |
| int iObj = Abc_Lit2Var(iLit); |
| Vec_IntClear( vSupp ); |
| if ( !iObj ) return Abc_LitIsCompl(iLit) ? ~(word)0 : (word)0; |
| Gia_ManIncrementTravId( p ); |
| Gia_ObjComputeTruth6CisSupport_rec( p, iObj, vSupp ); |
| if ( Vec_IntSize(vSupp) > 6 ) |
| return 0; |
| Gia_ObjComputeTruth6( p, iObj, vSupp, vTemp ); |
| return Abc_LitIsCompl(iLit) ? ~Vec_WrdEntry(vTemp, iObj) : Vec_WrdEntry(vTemp, iObj); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes truth table up to 6 inputs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Gia_ObjComputeTruthTable6_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Wrd_t * vTruths ) |
| { |
| word uTruth0, uTruth1; |
| if ( Gia_ObjIsTravIdCurrent(p, pObj) ) |
| return; |
| Gia_ObjSetTravIdCurrent(p, pObj); |
| assert( !pObj->fMark0 ); |
| assert( Gia_ObjIsAnd(pObj) ); |
| Gia_ObjComputeTruthTable6_rec( p, Gia_ObjFanin0(pObj), vTruths ); |
| Gia_ObjComputeTruthTable6_rec( p, Gia_ObjFanin1(pObj), vTruths ); |
| uTruth0 = Vec_WrdEntry( vTruths, Gia_ObjFanin0(pObj)->Value ); |
| uTruth0 = Gia_ObjFaninC0(pObj) ? ~uTruth0 : uTruth0; |
| uTruth1 = Vec_WrdEntry( vTruths, Gia_ObjFanin1(pObj)->Value ); |
| uTruth1 = Gia_ObjFaninC1(pObj) ? ~uTruth1 : uTruth1; |
| pObj->Value = Vec_WrdSize(vTruths); |
| Vec_WrdPush( vTruths, uTruth0 & uTruth1 ); |
| } |
| word Gia_ObjComputeTruthTable6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp, Vec_Wrd_t * vTruths ) |
| { |
| Gia_Obj_t * pLeaf; |
| int i; |
| assert( Vec_IntSize(vSupp) <= 6 ); |
| assert( Gia_ObjIsAnd(pObj) ); |
| assert( !pObj->fMark0 ); |
| Vec_WrdClear( vTruths ); |
| Gia_ManIncrementTravId( p ); |
| Gia_ManForEachObjVec( vSupp, p, pLeaf, i ) |
| { |
| assert( pLeaf->fMark0 || Gia_ObjIsRo(p, pLeaf) ); |
| pLeaf->Value = Vec_WrdSize(vTruths); |
| Vec_WrdPush( vTruths, s_Truth6[i] ); |
| Gia_ObjSetTravIdCurrent(p, pLeaf); |
| } |
| Gia_ObjComputeTruthTable6_rec( p, pObj, vTruths ); |
| return Vec_WrdEntryLast( vTruths ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects internal nodes reachable from the given node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Gia_ObjCollectInternal_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) |
| { |
| if ( !Gia_ObjIsAnd(pObj) ) |
| return; |
| if ( pObj->fMark0 ) |
| return; |
| pObj->fMark0 = 1; |
| Gia_ObjCollectInternal_rec( p, Gia_ObjFanin0(pObj) ); |
| Gia_ObjCollectInternal_rec( p, Gia_ObjFanin1(pObj) ); |
| Gia_ObjSetNum( p, pObj, Vec_IntSize(p->vTtNodes) ); |
| Vec_IntPush( p->vTtNodes, Gia_ObjId(p, pObj) ); |
| } |
| void Gia_ObjCollectInternal( Gia_Man_t * p, Gia_Obj_t * pObj ) |
| { |
| Vec_IntClear( p->vTtNodes ); |
| Gia_ObjCollectInternal_rec( p, pObj ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computing the truth table for GIA object.] |
| |
| Description [The truth table should be used by the calling application |
| (or saved into the user's storage) before this procedure is called again.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| word * Gia_ObjComputeTruthTable( Gia_Man_t * p, Gia_Obj_t * pObj ) |
| { |
| Gia_Obj_t * pTemp, * pRoot; |
| word * pTruth, * pTruthL, * pTruth0, * pTruth1; |
| int i; |
| if ( p->vTtMemory == NULL ) |
| { |
| p->nTtVars = Gia_ManPiNum( p ); |
| p->nTtWords = Abc_Truth6WordNum( p->nTtVars ); |
| p->vTtNums = Vec_IntStart( Gia_ManObjNum(p) + 1000 ); |
| p->vTtNodes = Vec_IntAlloc( 256 ); |
| p->vTtInputs = Vec_PtrAllocTruthTables( Abc_MaxInt(6, p->nTtVars) ); |
| p->vTtMemory = Vec_WrdStart( p->nTtWords * 256 ); |
| } |
| else |
| { |
| // make sure the number of primary inputs did not change |
| // since the truth table computation storage was prepared |
| assert( p->nTtVars == Gia_ManPiNum(p) ); |
| } |
| // extend ID numbers |
| if ( Vec_IntSize(p->vTtNums) < Gia_ManObjNum(p) ) |
| Vec_IntFillExtra( p->vTtNums, Gia_ManObjNum(p), 0 ); |
| // collect internal nodes |
| pRoot = Gia_ObjIsCo(pObj) ? Gia_ObjFanin0(pObj) : pObj; |
| Gia_ObjCollectInternal( p, pRoot ); |
| // extend TT storage |
| if ( Vec_WrdSize(p->vTtMemory) < p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2) ) |
| Vec_WrdFillExtra( p->vTtMemory, p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2), 0 ); |
| // compute the truth table for internal nodes |
| Gia_ManForEachObjVec( p->vTtNodes, p, pTemp, i ) |
| { |
| pTemp->fMark0 = 0; // unmark nodes marked by Gia_ObjCollectInternal() |
| pTruth = Gla_ObjTruthNode(p, pTemp); |
| pTruthL = pTruth + p->nTtWords; |
| pTruth0 = Gia_ObjIsAnd(Gia_ObjFanin0(pTemp)) ? Gla_ObjTruthNode(p, Gia_ObjFanin0(pTemp)) : Gla_ObjTruthElem(p, Gia_ObjCioId(Gia_ObjFanin0(pTemp)) ); |
| pTruth1 = Gia_ObjIsAnd(Gia_ObjFanin1(pTemp)) ? Gla_ObjTruthNode(p, Gia_ObjFanin1(pTemp)) : Gla_ObjTruthElem(p, Gia_ObjCioId(Gia_ObjFanin1(pTemp)) ); |
| if ( Gia_ObjFaninC0(pTemp) ) |
| { |
| if ( Gia_ObjFaninC1(pTemp) ) |
| while ( pTruth < pTruthL ) |
| *pTruth++ = ~*pTruth0++ & ~*pTruth1++; |
| else |
| while ( pTruth < pTruthL ) |
| *pTruth++ = ~*pTruth0++ & *pTruth1++; |
| } |
| else |
| { |
| if ( Gia_ObjFaninC1(pTemp) ) |
| while ( pTruth < pTruthL ) |
| *pTruth++ = *pTruth0++ & ~*pTruth1++; |
| else |
| while ( pTruth < pTruthL ) |
| *pTruth++ = *pTruth0++ & *pTruth1++; |
| } |
| } |
| // compute the final table |
| if ( Gia_ObjIsConst0(pRoot) ) |
| pTruth = Gla_ObjTruthConst0( p, Gla_ObjTruthFree1(p) ); |
| else if ( Gia_ObjIsPi(p, pRoot) ) |
| pTruth = Gla_ObjTruthElem( p, Gia_ObjCioId(pRoot) ); |
| else if ( Gia_ObjIsAnd(pRoot) ) |
| pTruth = Gla_ObjTruthNode( p, pRoot ); |
| else |
| pTruth = NULL; |
| return Gla_ObjTruthDup( p, Gla_ObjTruthFree2(p), pTruth, Gia_ObjIsCo(pObj) && Gia_ObjFaninC0(pObj) ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Testing truth table computation.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Gia_ObjComputeTruthTableTest( Gia_Man_t * p ) |
| { |
| Gia_Obj_t * pObj; |
| unsigned * pTruth; |
| abctime clk = Abc_Clock(); |
| int i; |
| Gia_ManForEachPo( p, pObj, i ) |
| { |
| pTruth = (unsigned *)Gia_ObjComputeTruthTable( p, pObj ); |
| // Extra_PrintHex( stdout, pTruth, Gia_ManPiNum(p) ); printf( "\n" ); |
| } |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Gia_ObjComputeTruthTableStart( Gia_Man_t * p, int nVarsMax ) |
| { |
| assert( p->vTtMemory == NULL ); |
| p->nTtVars = nVarsMax; |
| p->nTtWords = Abc_Truth6WordNum( p->nTtVars ); |
| p->vTtNodes = Vec_IntAlloc( 256 ); |
| p->vTtInputs = Vec_PtrAllocTruthTables( Abc_MaxInt(6, p->nTtVars) ); |
| p->vTtMemory = Vec_WrdStart( p->nTtWords * 64 ); |
| p->vTtNums = Vec_IntAlloc( Gia_ManObjNum(p) + 1000 ); |
| Vec_IntFill( p->vTtNums, Vec_IntCap(p->vTtNums), -ABC_INFINITY ); |
| } |
| void Gia_ObjComputeTruthTableStop( Gia_Man_t * p ) |
| { |
| p->nTtVars = 0; |
| p->nTtWords = 0; |
| Vec_IntFreeP( &p->vTtNums ); |
| Vec_IntFreeP( &p->vTtNodes ); |
| Vec_PtrFreeP( &p->vTtInputs ); |
| Vec_WrdFreeP( &p->vTtMemory ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects internal nodes reachable from the given node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Gia_ObjCollectInternalCut_rec( Gia_Man_t * p, int iObj ) |
| { |
| if ( Gia_ObjHasNumId(p, iObj) ) |
| return; |
| assert( Gia_ObjIsAnd(Gia_ManObj(p, iObj)) ); |
| Gia_ObjCollectInternalCut_rec( p, Gia_ObjFaninId0(Gia_ManObj(p, iObj), iObj) ); |
| Gia_ObjCollectInternalCut_rec( p, Gia_ObjFaninId1(Gia_ManObj(p, iObj), iObj) ); |
| Gia_ObjSetNumId( p, iObj, Vec_IntSize(p->vTtNodes) ); |
| Vec_IntPush( p->vTtNodes, iObj ); |
| } |
| void Gia_ObjCollectInternalCut( Gia_Man_t * p, int iRoot, Vec_Int_t * vLeaves ) |
| { |
| int i, iObj; |
| assert( !Gia_ObjHasNumId(p, iRoot) ); |
| assert( Gia_ObjIsAnd(Gia_ManObj(p, iRoot)) ); |
| Vec_IntForEachEntry( vLeaves, iObj, i ) |
| { |
| if ( Gia_ObjHasNumId(p, iObj) ) // if cuts have repeated variables, skip |
| continue; |
| assert( !Gia_ObjHasNumId(p, iObj) ); |
| Gia_ObjSetNumId( p, iObj, -i ); |
| } |
| assert( !Gia_ObjHasNumId(p, iRoot) ); // the root cannot be one of the leaves |
| Vec_IntClear( p->vTtNodes ); |
| Vec_IntPush( p->vTtNodes, -1 ); |
| Gia_ObjCollectInternalCut_rec( p, iRoot ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes the truth table of pRoot in terms of leaves.] |
| |
| Description [The root cannot be one of the leaves.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| word * Gia_ObjComputeTruthTableCut( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves ) |
| { |
| Gia_Obj_t * pTemp; |
| word * pTruth, * pTruthL, * pTruth0, * pTruth1; |
| int i, iObj, Id0, Id1; |
| assert( p->vTtMemory != NULL ); |
| assert( Vec_IntSize(vLeaves) <= p->nTtVars ); |
| // extend ID numbers |
| if ( Vec_IntSize(p->vTtNums) < Gia_ManObjNum(p) ) |
| Vec_IntFillExtra( p->vTtNums, Gia_ManObjNum(p), -ABC_INFINITY ); |
| // collect internal nodes |
| Gia_ObjCollectInternalCut( p, Gia_ObjId(p, pRoot), vLeaves ); |
| // extend TT storage |
| if ( Vec_WrdSize(p->vTtMemory) < p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2) ) |
| Vec_WrdFillExtra( p->vTtMemory, p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2), 0 ); |
| // compute the truth table for internal nodes |
| Vec_IntForEachEntryStart( p->vTtNodes, iObj, i, 1 ) |
| { |
| assert( i == Gia_ObjNumId(p, iObj) ); |
| pTemp = Gia_ManObj( p, iObj ); |
| pTruth = Gla_ObjTruthNodeId( p, i ); |
| pTruthL = pTruth + p->nTtWords; |
| Id0 = Gia_ObjNumId( p, Gia_ObjFaninId0(pTemp, iObj) ); |
| Id1 = Gia_ObjNumId( p, Gia_ObjFaninId1(pTemp, iObj) ); |
| pTruth0 = (Id0 > 0) ? Gla_ObjTruthNodeId(p, Id0) : Gla_ObjTruthElem(p, -Id0); |
| pTruth1 = (Id1 > 0) ? Gla_ObjTruthNodeId(p, Id1) : Gla_ObjTruthElem(p, -Id1); |
| if ( Gia_ObjFaninC0(pTemp) ) |
| { |
| if ( Gia_ObjFaninC1(pTemp) ) |
| while ( pTruth < pTruthL ) |
| *pTruth++ = ~*pTruth0++ & ~*pTruth1++; |
| else |
| while ( pTruth < pTruthL ) |
| *pTruth++ = ~*pTruth0++ & *pTruth1++; |
| } |
| else |
| { |
| if ( Gia_ObjFaninC1(pTemp) ) |
| while ( pTruth < pTruthL ) |
| *pTruth++ = *pTruth0++ & ~*pTruth1++; |
| else |
| while ( pTruth < pTruthL ) |
| *pTruth++ = *pTruth0++ & *pTruth1++; |
| } |
| } |
| pTruth = Gla_ObjTruthNode( p, pRoot ); |
| // unmark leaves marked by Gia_ObjCollectInternal() |
| Vec_IntForEachEntry( vLeaves, iObj, i ) |
| Gia_ObjResetNumId( p, iObj ); |
| Vec_IntForEachEntryStart( p->vTtNodes, iObj, i, 1 ) |
| Gia_ObjResetNumId( p, iObj ); |
| return pTruth; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Reduces GIA to contain isomorphic POs.] |
| |
| Description [The root cannot be one of the leaves.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Gia_Man_t * Gia_ManIsoNpnReduce( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, int fVerbose ) |
| { |
| char pCanonPerm[16]; |
| int i, iObj, uCanonPhase, nVars, lastId, truthId; |
| int IndexCon = -1, IndexVar = -1; |
| Vec_Wec_t * vPosEquivs = Vec_WecAlloc( 100 ); |
| word * pTruth; |
| Gia_Obj_t * pObj; |
| Vec_Mem_t * vTtMem[17]; // truth table memory and hash table |
| Gia_Man_t * pNew = NULL; |
| Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); |
| Vec_Int_t * vFirsts; |
| Vec_Int_t * vTt2Class[17]; |
| for ( i = 0; i < 17; i++ ) |
| { |
| vTtMem[i] = Vec_MemAlloc( Abc_TtWordNum(i), 10 ); |
| Vec_MemHashAlloc( vTtMem[i], 1000 ); |
| vTt2Class[i] = Vec_IntStartFull( Gia_ManCoNum(p)+1 ); |
| } |
| Gia_ObjComputeTruthTableStart( p, 16 ); |
| Gia_ManForEachPo( p, pObj, i ) |
| { |
| iObj = Gia_ObjId(p, pObj); |
| Gia_ManCollectCis( p, &iObj, 1, vLeaves ); |
| if ( Vec_IntSize(vLeaves) > 16 ) |
| { |
| Vec_IntPush( Vec_WecPushLevel(vPosEquivs), i ); |
| continue; |
| } |
| pObj = Gia_ObjFanin0(pObj); |
| if ( Gia_ObjIsConst0(pObj) ) |
| { |
| if ( IndexCon == -1 ) |
| { |
| IndexCon = Vec_WecSize(vPosEquivs); |
| Vec_WecPushLevel(vPosEquivs); |
| } |
| Vec_WecPush( vPosEquivs, IndexCon, i ); |
| continue; |
| } |
| if ( Gia_ObjIsCi(pObj) ) |
| { |
| if ( IndexVar == -1 ) |
| { |
| IndexVar = Vec_WecSize(vPosEquivs); |
| Vec_WecPushLevel(vPosEquivs); |
| } |
| Vec_WecPush( vPosEquivs, IndexVar, i ); |
| continue; |
| } |
| assert( Gia_ObjIsAnd(pObj) ); |
| pTruth = Gia_ObjComputeTruthTableCut( p, pObj, vLeaves ); |
| Abc_TtMinimumBase( pTruth, NULL, Vec_IntSize(vLeaves), &nVars ); |
| if ( nVars == 0 ) |
| { |
| if ( IndexCon == -1 ) |
| { |
| IndexCon = Vec_WecSize(vPosEquivs); |
| Vec_WecPushLevel(vPosEquivs); |
| } |
| Vec_WecPush( vPosEquivs, IndexCon, i ); |
| continue; |
| } |
| if ( nVars == 1 ) |
| { |
| if ( IndexVar == -1 ) |
| { |
| IndexVar = Vec_WecSize(vPosEquivs); |
| Vec_WecPushLevel(vPosEquivs); |
| } |
| Vec_WecPush( vPosEquivs, IndexVar, i ); |
| continue; |
| } |
| uCanonPhase = Abc_TtCanonicize( pTruth, nVars, pCanonPerm ); |
| lastId = Vec_MemEntryNum( vTtMem[nVars] ); |
| truthId = Vec_MemHashInsert( vTtMem[nVars], pTruth ); |
| if ( lastId != Vec_MemEntryNum( vTtMem[nVars] ) ) // new one |
| { |
| assert( Vec_IntEntry(vTt2Class[nVars], truthId) == -1 ); |
| Vec_IntWriteEntry( vTt2Class[nVars], truthId, Vec_WecSize(vPosEquivs) ); |
| Vec_WecPushLevel(vPosEquivs); |
| } |
| assert( Vec_IntEntry(vTt2Class[nVars], truthId) >= 0 ); |
| Vec_WecPush( vPosEquivs, Vec_IntEntry(vTt2Class[nVars], truthId), i ); |
| } |
| Gia_ObjComputeTruthTableStop( p ); |
| Vec_IntFree( vLeaves ); |
| for ( i = 0; i < 17; i++ ) |
| { |
| Vec_MemHashFree( vTtMem[i] ); |
| Vec_MemFree( vTtMem[i] ); |
| Vec_IntFree( vTt2Class[i] ); |
| } |
| |
| // find the first outputs and derive GIA |
| vFirsts = Vec_WecCollectFirsts( vPosEquivs ); |
| pNew = Gia_ManDupCones( p, Vec_IntArray(vFirsts), Vec_IntSize(vFirsts), 0 ); |
| Vec_IntFree( vFirsts ); |
| // report and return |
| if ( fVerbose ) |
| { |
| printf( "Nontrivial classes:\n" ); |
| Vec_WecPrint( vPosEquivs, 1 ); |
| } |
| if ( pvPosEquivs ) |
| *pvPosEquivs = Vec_WecConvertToVecPtr( vPosEquivs ); |
| Vec_WecFree( vPosEquivs ); |
| return pNew; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |