| /**CFile**************************************************************** |
| |
| FileName [plaFxch.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [SOP manager.] |
| |
| Synopsis [Scalable SOP transformations.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - March 18, 2015.] |
| |
| Revision [$Id: plaFxch.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "pla.h" |
| #include "misc/vec/vecHash.h" |
| #include "misc/vec/vecQue.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| typedef struct Fxch_Obj_t_ Fxch_Obj_t; |
| struct Fxch_Obj_t_ |
| { |
| unsigned Table : 30; |
| unsigned MarkN : 1; |
| unsigned MarkP : 1; |
| int Next; |
| int Prev; |
| int Cube; |
| }; |
| |
| typedef struct Fxch_Man_t_ Fxch_Man_t; |
| struct Fxch_Man_t_ |
| { |
| // user's data |
| Vec_Wec_t vCubes; // cube -> lit |
| // internal data |
| Vec_Wec_t vLits; // lit -> cube |
| Vec_Int_t vRands; // random numbers for each literal |
| Vec_Int_t vCubeLinks; // first link for each cube |
| Fxch_Obj_t * pBins; // hash table (lits -> cube + lit) |
| Hash_IntMan_t * vHash; // divisor hash table |
| Vec_Que_t * vPrio; // priority queue for divisors by weight |
| Vec_Flt_t vWeights; // divisor weights |
| Vec_Wec_t vPairs; // cube pairs for each div |
| Vec_Wrd_t vDivs; // extracted divisors |
| // temporary data |
| Vec_Int_t vCubesS; // cube pairs for single |
| Vec_Int_t vCubesD; // cube pairs for double |
| Vec_Int_t vCube1; // first cube |
| Vec_Int_t vCube2; // second cube |
| // statistics |
| abctime timeStart; // starting time |
| int SizeMask; // hash table mask |
| int nVars; // original problem variables |
| int nLits; // the number of SOP literals |
| int nCompls; // the number of complements |
| int nPairsS; // number of lit pairs |
| int nPairsD; // number of cube pairs |
| }; |
| |
| #define Fxch_ManForEachCubeVec( vVec, vCubes, vCube, i ) \ |
| for ( i = 0; (i < Vec_IntSize(vVec)) && ((vCube) = Vec_WecEntry(vCubes, Vec_IntEntry(vVec, i))); i++ ) |
| |
| static inline Vec_Int_t * Fxch_ManCube( Fxch_Man_t * p, int hCube ) { return Vec_WecEntry(&p->vCubes, Pla_CubeNum(hCube)); } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Writes the current state of the manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Fxch_ManWriteBlif( char * pFileName, Vec_Wec_t * vCubes, Vec_Wrd_t * vDivs ) |
| { |
| // find the number of original variables |
| int nVarsInit = Vec_WrdCountZero(vDivs); |
| FILE * pFile = fopen( pFileName, "wb" ); |
| if ( pFile == NULL ) |
| printf( "Cannot open file \"%s\" for writing.\n", pFileName ); |
| else |
| { |
| //char * pLits = "-01?"; |
| Vec_Str_t * vStr; |
| Vec_Int_t * vCube; |
| int i, k, Lit; |
| word Div; |
| // comment |
| fprintf( pFile, "# BLIF file written via PLA package in ABC on " ); |
| fprintf( pFile, "%s", Extra_TimeStamp() ); |
| fprintf( pFile, "\n\n" ); |
| // header |
| fprintf( pFile, ".model %s\n", pFileName ); |
| fprintf( pFile, ".inputs" ); |
| for ( i = 0; i < nVarsInit; i++ ) |
| fprintf( pFile, " i%d", i ); |
| fprintf( pFile, "\n" ); |
| fprintf( pFile, ".outputs o" ); |
| fprintf( pFile, "\n" ); |
| // SOP header |
| fprintf( pFile, ".names" ); |
| for ( i = 0; i < Vec_WrdSize(vDivs); i++ ) |
| fprintf( pFile, " i%d", i ); |
| fprintf( pFile, " o\n" ); |
| // SOP cubes |
| vStr = Vec_StrStart( Vec_WrdSize(vDivs) + 1 ); |
| Vec_WecForEachLevel( vCubes, vCube, i ) |
| { |
| if ( !Vec_IntSize(vCube) ) |
| continue; |
| for ( k = 0; k < Vec_WrdSize(vDivs); k++ ) |
| Vec_StrWriteEntry( vStr, k, '-' ); |
| Vec_IntForEachEntry( vCube, Lit, k ) |
| Vec_StrWriteEntry( vStr, Abc_Lit2Var(Lit), (char)(Abc_LitIsCompl(Lit) ? '0' : '1') ); |
| fprintf( pFile, "%s 1\n", Vec_StrArray(vStr) ); |
| } |
| Vec_StrFree( vStr ); |
| // divisors |
| Vec_WrdForEachEntryStart( vDivs, Div, i, nVarsInit ) |
| { |
| int pLits[2] = { (int)(Div & 0xFFFFFFFF), (int)(Div >> 32) }; |
| fprintf( pFile, ".names" ); |
| fprintf( pFile, " i%d", Abc_Lit2Var(pLits[0]) ); |
| fprintf( pFile, " i%d", Abc_Lit2Var(pLits[1]) ); |
| fprintf( pFile, " i%d\n", i ); |
| fprintf( pFile, "%d%d 1\n", !Abc_LitIsCompl(pLits[0]), !Abc_LitIsCompl(pLits[1]) ); |
| } |
| fprintf( pFile, ".end\n\n" ); |
| fclose( pFile ); |
| printf( "Written BLIF file \"%s\".\n", pFileName ); |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Starting the manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Fxch_Man_t * Fxch_ManStart( Vec_Wec_t * vCubes, Vec_Wec_t * vLits ) |
| { |
| Vec_Int_t * vCube; int i, LogSize; |
| Fxch_Man_t * p = ABC_CALLOC( Fxch_Man_t, 1 ); |
| p->vCubes = *vCubes; |
| p->vLits = *vLits; |
| p->nVars = Vec_WecSize(vLits)/2; |
| p->nLits = 0; |
| // random numbers |
| Gia_ManRandom( 1 ); |
| Vec_IntGrow( &p->vRands, 2*p->nVars ); |
| for ( i = 0; i < 2*p->nVars; i++ ) |
| Vec_IntPush( &p->vRands, Gia_ManRandom(0) & 0x3FFFFFF ); // assert( LogSize <= 26 ); |
| // create cube links |
| Vec_IntGrow( &p->vCubeLinks, Vec_WecSize(&p->vCubes) ); |
| Vec_WecForEachLevel( vCubes, vCube, i ) |
| { |
| Vec_IntPush( &p->vCubeLinks, p->nLits+1 ); |
| p->nLits += Vec_IntSize(vCube); |
| } |
| assert( Vec_IntSize(&p->vCubeLinks) == Vec_WecSize(&p->vCubes) ); |
| // create table |
| LogSize = Abc_Base2Log( p->nLits+1 ); |
| assert( LogSize <= 26 ); |
| p->SizeMask = (1 << LogSize) - 1; |
| p->pBins = ABC_CALLOC( Fxch_Obj_t, p->SizeMask + 1 ); |
| assert( p->nLits+1 < p->SizeMask+1 ); |
| // divisor weights and cube pairs |
| Vec_FltGrow( &p->vWeights, 1000 ); |
| Vec_FltPush( &p->vWeights, -1 ); |
| Vec_WecGrow( &p->vPairs, 1000 ); |
| Vec_WecPushLevel( &p->vPairs ); |
| // prepare divisors |
| Vec_WrdGrow( &p->vDivs, p->nVars + 1000 ); |
| Vec_WrdFill( &p->vDivs, p->nVars, 0 ); |
| return p; |
| } |
| void Fxch_ManStop( Fxch_Man_t * p ) |
| { |
| Vec_WecErase( &p->vCubes ); |
| Vec_WecErase( &p->vLits ); |
| Vec_IntErase( &p->vRands ); |
| Vec_IntErase( &p->vCubeLinks ); |
| Hash_IntManStop( p->vHash ); |
| Vec_QueFree( p->vPrio ); |
| Vec_FltErase( &p->vWeights ); |
| Vec_WecErase( &p->vPairs ); |
| Vec_WrdErase( &p->vDivs ); |
| Vec_IntErase( &p->vCubesS ); |
| Vec_IntErase( &p->vCubesD ); |
| Vec_IntErase( &p->vCube1 ); |
| Vec_IntErase( &p->vCube2 ); |
| ABC_FREE( p->pBins ); |
| ABC_FREE( p ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Fxch_TabCompare( Fxch_Man_t * p, int hCube1, int hCube2 ) |
| { |
| Vec_Int_t * vCube1 = Fxch_ManCube( p, hCube1 ); |
| Vec_Int_t * vCube2 = Fxch_ManCube( p, hCube2 ); |
| if ( !Vec_IntSize(vCube1) || !Vec_IntSize(vCube2) || Vec_IntSize(vCube1) != Vec_IntSize(vCube2) ) |
| return 0; |
| Vec_IntClear( &p->vCube1 ); |
| Vec_IntClear( &p->vCube2 ); |
| Vec_IntAppendSkip( &p->vCube1, vCube1, Pla_CubeLit(hCube1) ); |
| Vec_IntAppendSkip( &p->vCube2, vCube2, Pla_CubeLit(hCube2) ); |
| return Vec_IntEqual( &p->vCube1, &p->vCube2 ); |
| } |
| static inline void Fxch_CompressCubes( Fxch_Man_t * p, Vec_Int_t * vLit2Cube ) |
| { |
| int i, hCube, k = 0; |
| Vec_IntForEachEntry( vLit2Cube, hCube, i ) |
| if ( Vec_IntSize(Vec_WecEntry(&p->vCubes, hCube)) > 0 ) |
| Vec_IntWriteEntry( vLit2Cube, k++, hCube ); |
| Vec_IntShrink( vLit2Cube, k ); |
| } |
| static inline int Fxch_CollectSingles( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vArr ) |
| { |
| int * pBeg1 = vArr1->pArray; |
| int * pBeg2 = vArr2->pArray; |
| int * pEnd1 = vArr1->pArray + vArr1->nSize; |
| int * pEnd2 = vArr2->pArray + vArr2->nSize; |
| int * pBeg1New = vArr1->pArray; |
| int * pBeg2New = vArr2->pArray; |
| Vec_IntClear( vArr ); |
| while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) |
| { |
| if ( Pla_CubeNum(*pBeg1) == Pla_CubeNum(*pBeg2) ) |
| Vec_IntPushTwo( vArr, *pBeg1, *pBeg2 ), pBeg1++, pBeg2++; |
| else if ( *pBeg1 < *pBeg2 ) |
| *pBeg1New++ = *pBeg1++; |
| else |
| *pBeg2New++ = *pBeg2++; |
| } |
| while ( pBeg1 < pEnd1 ) |
| *pBeg1New++ = *pBeg1++; |
| while ( pBeg2 < pEnd2 ) |
| *pBeg2New++ = *pBeg2++; |
| Vec_IntShrink( vArr1, pBeg1New - vArr1->pArray ); |
| Vec_IntShrink( vArr2, pBeg2New - vArr2->pArray ); |
| return Vec_IntSize(vArr); |
| } |
| static inline void Fxch_CollectDoubles( Fxch_Man_t * p, Vec_Int_t * vPairs, Vec_Int_t * vRes, int Lit0, int Lit1 ) |
| { |
| int i, hCube1, hCube2; |
| Vec_IntClear( vRes ); |
| Vec_IntForEachEntryDouble( vPairs, hCube1, hCube2, i ) |
| if ( Fxch_TabCompare(p, hCube1, hCube2) && |
| Vec_IntEntry(Fxch_ManCube(p, hCube1), Pla_CubeLit(hCube1)) == Lit0 && |
| Vec_IntEntry(Fxch_ManCube(p, hCube2), Pla_CubeLit(hCube2)) == Lit1 ) |
| Vec_IntPushTwo( vRes, hCube1, hCube2 ); |
| Vec_IntClear( vPairs ); |
| // order pairs in the increasing order of the first cube |
| //Vec_IntSortPairs( vRes ); |
| } |
| static inline void Fxch_CompressLiterals2( Vec_Int_t * p, int iInd1, int iInd2 ) |
| { |
| int i, Lit, k = 0; |
| assert( iInd1 >= 0 && iInd1 < Vec_IntSize(p) ); |
| if ( iInd2 != -1 ) |
| assert( iInd1 >= 0 && iInd1 < Vec_IntSize(p) ); |
| Vec_IntForEachEntry( p, Lit, i ) |
| if ( i != iInd1 && i != iInd2 ) |
| Vec_IntWriteEntry( p, k++, Lit ); |
| Vec_IntShrink( p, k ); |
| } |
| static inline void Fxch_CompressLiterals( Vec_Int_t * p, int iLit1, int iLit2 ) |
| { |
| int i, Lit, k = 0; |
| Vec_IntForEachEntry( p, Lit, i ) |
| if ( Lit != iLit1 && Lit != iLit2 ) |
| Vec_IntWriteEntry( p, k++, Lit ); |
| assert( Vec_IntSize(p) == k + 2 ); |
| Vec_IntShrink( p, k ); |
| } |
| static inline void Fxch_FilterCubes( Fxch_Man_t * p, Vec_Int_t * vCubesS, int Lit0, int Lit1 ) |
| { |
| Vec_Int_t * vCube; |
| int i, k, Lit, iCube, n = 0; |
| int fFound0, fFound1; |
| Vec_IntForEachEntry( vCubesS, iCube, i ) |
| { |
| vCube = Vec_WecEntry( &p->vCubes, iCube ); |
| fFound0 = fFound1 = 0; |
| Vec_IntForEachEntry( vCube, Lit, k ) |
| { |
| if ( Lit == Lit0 ) |
| fFound0 = 1; |
| else if ( Lit == Lit1 ) |
| fFound1 = 1; |
| } |
| if ( fFound0 && fFound1 ) |
| Vec_IntWriteEntry( vCubesS, n++, Pla_CubeHandle(iCube, 255) ); |
| } |
| Vec_IntShrink( vCubesS, n ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Divisor addition removal.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Fxch_DivisorAdd( Fxch_Man_t * p, int Lit0, int Lit1, int Weight ) |
| { |
| int iDiv; |
| assert( Lit0 != Lit1 ); |
| if ( Lit0 < Lit1 ) |
| iDiv = Hash_Int2ManInsert( p->vHash, Lit0, Lit1, 0 ); |
| else |
| iDiv = Hash_Int2ManInsert( p->vHash, Lit1, Lit0, 0 ); |
| if ( iDiv == Vec_FltSize(&p->vWeights) ) |
| { |
| Vec_FltPush( &p->vWeights, -2 ); |
| Vec_WecPushLevel( &p->vPairs ); |
| assert( Vec_FltSize(&p->vWeights) == Vec_WecSize(&p->vPairs) ); |
| } |
| Vec_FltAddToEntry( &p->vWeights, iDiv, Weight ); |
| if ( p->vPrio ) |
| { |
| if ( Vec_QueIsMember(p->vPrio, iDiv) ) |
| Vec_QueUpdate( p->vPrio, iDiv ); |
| else |
| Vec_QuePush( p->vPrio, iDiv ); |
| //assert( iDiv < Vec_QueSize(p->vPrio) ); |
| } |
| return iDiv; |
| } |
| void Fxch_DivisorRemove( Fxch_Man_t * p, int Lit0, int Lit1, int Weight ) |
| { |
| int iDiv; |
| assert( Lit0 != Lit1 ); |
| if ( Lit0 < Lit1 ) |
| iDiv = *Hash_Int2ManLookup( p->vHash, Lit0, Lit1 ); |
| else |
| iDiv = *Hash_Int2ManLookup( p->vHash, Lit1, Lit0 ); |
| assert( iDiv > 0 && iDiv < Vec_FltSize(&p->vWeights) ); |
| Vec_FltAddToEntry( &p->vWeights, iDiv, -Weight ); |
| if ( Vec_QueIsMember(p->vPrio, iDiv) ) |
| Vec_QueUpdate( p->vPrio, iDiv ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Starting the manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline Fxch_Obj_t * Fxch_TabBin( Fxch_Man_t * p, int Value ) { return p->pBins + (Value & p->SizeMask); } |
| static inline Fxch_Obj_t * Fxch_TabEntry( Fxch_Man_t * p, int i ) { return i ? p->pBins + i : NULL; } |
| static inline int Fxch_TabEntryId( Fxch_Man_t * p, Fxch_Obj_t * pEnt ) { assert(pEnt > p->pBins); return pEnt - p->pBins; } |
| |
| static inline void Fxch_TabMarkPair( Fxch_Man_t * p, int i, int j ) |
| { |
| Fxch_Obj_t * pI = Fxch_TabEntry(p, i); |
| Fxch_Obj_t * pJ = Fxch_TabEntry(p, j); |
| assert( pI->Next == j ); |
| assert( pJ->Prev == i ); |
| assert( pI->MarkN == 0 ); |
| assert( pI->MarkP == 0 ); |
| assert( pJ->MarkN == 0 ); |
| assert( pJ->MarkP == 0 ); |
| pI->MarkN = 1; |
| pJ->MarkP = 1; |
| } |
| static inline void Fxch_TabUnmarkPair( Fxch_Man_t * p, int i, int j ) |
| { |
| Fxch_Obj_t * pI = Fxch_TabEntry(p, i); |
| Fxch_Obj_t * pJ = Fxch_TabEntry(p, j); |
| assert( pI->Next == j ); |
| assert( pJ->Prev == i ); |
| assert( pI->MarkN == 1 ); |
| assert( pI->MarkP == 0 ); |
| assert( pJ->MarkN == 0 ); |
| assert( pJ->MarkP == 1 ); |
| pI->MarkN = 0; |
| pJ->MarkP = 0; |
| } |
| static inline void Fxch_TabInsertLink( Fxch_Man_t * p, int i, int j, int fSkipCheck ) |
| { |
| Fxch_Obj_t * pI = Fxch_TabEntry(p, i); |
| Fxch_Obj_t * pN = Fxch_TabEntry(p, pI->Next); |
| Fxch_Obj_t * pJ = Fxch_TabEntry(p, j); |
| //assert( pJ->Cube != 0 ); |
| assert( pN->Prev == i ); |
| assert( fSkipCheck || pI->MarkN == 0 ); |
| assert( fSkipCheck || pN->MarkP == 0 ); |
| assert( fSkipCheck || pJ->MarkN == 0 ); |
| assert( fSkipCheck || pJ->MarkP == 0 ); |
| pJ->Next = pI->Next; pI->Next = j; |
| pJ->Prev = i; pN->Prev = j; |
| } |
| static inline void Fxch_TabExtractLink( Fxch_Man_t * p, int i, int j ) |
| { |
| Fxch_Obj_t * pI = Fxch_TabEntry(p, i); |
| Fxch_Obj_t * pJ = Fxch_TabEntry(p, j); |
| Fxch_Obj_t * pN = Fxch_TabEntry(p, pJ->Next); |
| //assert( pJ->Cube != 0 ); |
| assert( pI->Next == j ); |
| assert( pJ->Prev == i ); |
| assert( pN->Prev == j ); |
| assert( pI->MarkN == 0 ); |
| assert( pJ->MarkP == 0 ); |
| assert( pJ->MarkN == 0 ); |
| assert( pN->MarkP == 0 ); |
| pI->Next = pJ->Next; pJ->Next = 0; |
| pN->Prev = pJ->Prev; pJ->Prev = 0; |
| } |
| static inline void Fxch_TabInsert( Fxch_Man_t * p, int iLink, int Value, int hCube ) |
| { |
| int iEnt, iDiv, Lit0, Lit1, fStart = 1; |
| Fxch_Obj_t * pEnt; |
| Fxch_Obj_t * pBin = Fxch_TabBin( p, Value ); |
| Fxch_Obj_t * pCell = Fxch_TabEntry( p, iLink ); |
| assert( pCell->MarkN == 0 ); |
| assert( pCell->MarkP == 0 ); |
| assert( pCell->Cube == 0 ); |
| pCell->Cube = hCube; |
| if ( pBin->Table == 0 ) |
| { |
| pBin->Table = pCell->Next = pCell->Prev = iLink; |
| return; |
| } |
| // find equal cubes |
| for ( iEnt = pBin->Table; iEnt != (int)pBin->Table || fStart; iEnt = pEnt->Next, fStart = 0 ) |
| { |
| pEnt = Fxch_TabBin( p, iEnt ); |
| if ( pEnt->MarkN || pEnt->MarkP || !Fxch_TabCompare(p, pEnt->Cube, hCube) ) |
| continue; |
| Fxch_TabInsertLink( p, iEnt, iLink, 0 ); |
| Fxch_TabMarkPair( p, iEnt, iLink ); |
| // get literals |
| Lit0 = Vec_IntEntry( Fxch_ManCube(p, hCube), Pla_CubeLit(hCube) ); |
| Lit1 = Vec_IntEntry( Fxch_ManCube(p, pEnt->Cube), Pla_CubeLit(pEnt->Cube) ); |
| // increment divisor weight |
| iDiv = Fxch_DivisorAdd( p, Abc_LitNot(Lit0), Abc_LitNot(Lit1), Vec_IntSize(Fxch_ManCube(p, hCube)) ); |
| // add divisor pair |
| assert( iDiv < Vec_WecSize(&p->vPairs) ); |
| if ( Lit0 < Lit1 ) |
| { |
| Vec_WecPush( &p->vPairs, iDiv, hCube ); |
| Vec_WecPush( &p->vPairs, iDiv, pEnt->Cube ); |
| } |
| else |
| { |
| Vec_WecPush( &p->vPairs, iDiv, pEnt->Cube ); |
| Vec_WecPush( &p->vPairs, iDiv, hCube ); |
| } |
| p->nPairsD++; |
| return; |
| } |
| assert( iEnt == (int)pBin->Table ); |
| pEnt = Fxch_TabBin( p, iEnt ); |
| Fxch_TabInsertLink( p, pEnt->Prev, iLink, 1 ); |
| } |
| static inline void Fxch_TabExtract( Fxch_Man_t * p, int iLink, int Value, int hCube ) |
| { |
| int Lit0, Lit1; |
| Fxch_Obj_t * pPair = NULL; |
| Fxch_Obj_t * pBin = Fxch_TabBin( p, Value ); |
| Fxch_Obj_t * pLink = Fxch_TabEntry( p, iLink ); |
| assert( pLink->Cube == hCube ); |
| if ( pLink->MarkN ) |
| { |
| pPair = Fxch_TabEntry( p, pLink->Next ); |
| Fxch_TabUnmarkPair( p, iLink, pLink->Next ); |
| } |
| else if ( pLink->MarkP ) |
| { |
| pPair = Fxch_TabEntry( p, pLink->Prev ); |
| Fxch_TabUnmarkPair( p, pLink->Prev, iLink ); |
| } |
| if ( (int)pBin->Table == iLink ) |
| pBin->Table = pLink->Next != iLink ? pLink->Next : 0; |
| if ( pLink->Next == iLink ) |
| { |
| assert( pLink->Prev == iLink ); |
| pLink->Next = pLink->Prev = 0; |
| } |
| else |
| Fxch_TabExtractLink( p, pLink->Prev, iLink ); |
| pLink->Cube = 0; |
| if ( pPair == NULL ) |
| return; |
| assert( Fxch_TabCompare(p, pPair->Cube, hCube) ); |
| // get literals |
| Lit0 = Vec_IntEntry( Fxch_ManCube(p, hCube), Pla_CubeLit(hCube) ); |
| Lit1 = Vec_IntEntry( Fxch_ManCube(p, pPair->Cube), Pla_CubeLit(pPair->Cube) ); |
| // decrement divisor weight |
| Fxch_DivisorRemove( p, Abc_LitNot(Lit0), Abc_LitNot(Lit1), Vec_IntSize(Fxch_ManCube(p, hCube)) ); |
| p->nPairsD--; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Starting the manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Fxch_TabSingleDivisors( Fxch_Man_t * p, int iCube, int fAdd ) |
| { |
| Vec_Int_t * vCube = Vec_WecEntry( &p->vCubes, iCube ); |
| int i, k, Lit, Lit2; |
| if ( Vec_IntSize(vCube) < 2 ) |
| return 0; |
| Vec_IntForEachEntry( vCube, Lit, i ) |
| Vec_IntForEachEntryStart( vCube, Lit2, k, i+1 ) |
| { |
| assert( Lit < Lit2 ); |
| if ( fAdd ) |
| Fxch_DivisorAdd( p, Lit, Lit2, 1 ), p->nPairsS++; |
| else |
| Fxch_DivisorRemove( p, Lit, Lit2, 1 ), p->nPairsS--; |
| } |
| return Vec_IntSize(vCube) * (Vec_IntSize(vCube) - 1) / 2; |
| } |
| int Fxch_TabDoubleDivisors( Fxch_Man_t * p, int iCube, int fAdd ) |
| { |
| Vec_Int_t * vCube = Vec_WecEntry( &p->vCubes, iCube ); |
| int iLinkFirst = Vec_IntEntry( &p->vCubeLinks, iCube ); |
| int k, Lit, Value = 0; |
| Vec_IntForEachEntry( vCube, Lit, k ) |
| Value += Vec_IntEntry(&p->vRands, Lit); |
| Vec_IntForEachEntry( vCube, Lit, k ) |
| { |
| Value -= Vec_IntEntry(&p->vRands, Lit); |
| if ( fAdd ) |
| Fxch_TabInsert( p, iLinkFirst + k, Value, Pla_CubeHandle(iCube, k) ); |
| else |
| Fxch_TabExtract( p, iLinkFirst + k, Value, Pla_CubeHandle(iCube, k) ); |
| Value += Vec_IntEntry(&p->vRands, Lit); |
| } |
| return 1; |
| } |
| void Fxch_ManCreateDivisors( Fxch_Man_t * p ) |
| { |
| float Weight; int i; |
| // alloc hash table |
| assert( p->vHash == NULL ); |
| p->vHash = Hash_IntManStart( 1000 ); |
| // create single-cube two-literal divisors |
| for ( i = 0; i < Vec_WecSize(&p->vCubes); i++ ) |
| Fxch_TabSingleDivisors( p, i, 1 ); // add - no update |
| // create two-cube divisors |
| for ( i = 0; i < Vec_WecSize(&p->vCubes); i++ ) |
| Fxch_TabDoubleDivisors( p, i, 1 ); // add - no update |
| // create queue with all divisors |
| p->vPrio = Vec_QueAlloc( Vec_FltSize(&p->vWeights) ); |
| Vec_QueSetPriority( p->vPrio, Vec_FltArrayP(&p->vWeights) ); |
| Vec_FltForEachEntry( &p->vWeights, Weight, i ) |
| if ( Weight > 0.0 ) |
| Vec_QuePush( p->vPrio, i ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Updates the data-structure when one divisor is selected.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Fxch_ManUpdate( Fxch_Man_t * p, int iDiv ) |
| { |
| Vec_Int_t * vCube1, * vCube2, * vLitP, * vLitN; |
| //int nLitsNew = p->nLits - (int)Vec_FltEntry(&p->vWeights, iDiv); |
| int i, Lit0, Lit1, hCube1, hCube2, iVarNew; |
| //float Diff = Vec_FltEntry(&p->vWeights, iDiv) - (float)((int)Vec_FltEntry(&p->vWeights, iDiv)); |
| //assert( Diff > 0.0 && Diff < 1.0 ); |
| |
| // get the divisor and select pivot variables |
| Vec_IntPush( &p->vRands, Gia_ManRandom(0) & 0x3FFFFFF ); |
| Vec_IntPush( &p->vRands, Gia_ManRandom(0) & 0x3FFFFFF ); |
| Lit0 = Hash_IntObjData0( p->vHash, iDiv ); |
| Lit1 = Hash_IntObjData1( p->vHash, iDiv ); |
| assert( Lit0 >= 0 && Lit1 >= 0 && Lit0 < Lit1 ); |
| Vec_WrdPush( &p->vDivs, ((word)Lit1 << 32) | (word)Lit0 ); |
| |
| // if the input cover is not prime, it may happen that we are extracting divisor (x + !x) |
| // although it is not strictly correct, it seems to be fine to just skip such divisors |
| // if ( Abc_Lit2Var(Lit0) == Abc_Lit2Var(Lit1) && Vec_IntSize(Hsh_VecReadEntry(p->vHash, iDiv)) == 2 ) |
| // return; |
| |
| // collect single-cube-divisor cubes |
| vLitP = Vec_WecEntry(&p->vLits, Lit0); |
| vLitN = Vec_WecEntry(&p->vLits, Lit1); |
| Fxch_CompressCubes( p, vLitP ); |
| Fxch_CompressCubes( p, vLitN ); |
| // Fxch_CollectSingles( vLitP, vLitN, &p->vCubesS ); |
| // assert( Vec_IntSize(&p->vCubesS) % 2 == 0 ); |
| Vec_IntTwoRemoveCommon( vLitP, vLitN, &p->vCubesS ); |
| Fxch_FilterCubes( p, &p->vCubesS, Lit0, Lit1 ); |
| |
| // collect double-cube-divisor cube pairs |
| Fxch_CollectDoubles( p, Vec_WecEntry(&p->vPairs, iDiv), &p->vCubesD, Abc_LitNot(Lit0), Abc_LitNot(Lit1) ); |
| assert( Vec_IntSize(&p->vCubesD) % 2 == 0 ); |
| Vec_IntUniqifyPairs( &p->vCubesD ); |
| assert( Vec_IntSize(&p->vCubesD) % 2 == 0 ); |
| |
| // subtract cost of single-cube divisors |
| // Vec_IntForEachEntryDouble( &p->vCubesS, hCube1, hCube2, i ) |
| Vec_IntForEachEntry( &p->vCubesS, hCube1, i ) |
| Fxch_TabSingleDivisors( p, Pla_CubeNum(hCube1), 0 ); // remove - update |
| Vec_IntForEachEntryDouble( &p->vCubesD, hCube1, hCube2, i ) |
| Fxch_TabSingleDivisors( p, Pla_CubeNum(hCube1), 0 ), // remove - update |
| Fxch_TabSingleDivisors( p, Pla_CubeNum(hCube2), 0 ); // remove - update |
| |
| // subtract cost of double-cube divisors |
| // Vec_IntForEachEntryDouble( &p->vCubesS, hCube1, hCube2, i ) |
| Vec_IntForEachEntry( &p->vCubesS, hCube1, i ) |
| { |
| //printf( "%d ", Pla_CubeNum(hCube1) ); |
| Fxch_TabDoubleDivisors( p, Pla_CubeNum(hCube1), 0 ); // remove - update |
| } |
| //printf( "\n" ); |
| |
| Vec_IntForEachEntryDouble( &p->vCubesD, hCube1, hCube2, i ) |
| { |
| //printf( "%d ", Pla_CubeNum(hCube1) ); |
| //printf( "%d ", Pla_CubeNum(hCube2) ); |
| Fxch_TabDoubleDivisors( p, Pla_CubeNum(hCube1), 0 ), // remove - update |
| Fxch_TabDoubleDivisors( p, Pla_CubeNum(hCube2), 0 ); // remove - update |
| } |
| //printf( "\n" ); |
| |
| // create new literals |
| p->nLits += 2; |
| iVarNew = Vec_WecSize( &p->vLits ) / 2; |
| vLitP = Vec_WecPushLevel( &p->vLits ); |
| vLitN = Vec_WecPushLevel( &p->vLits ); |
| vLitP = Vec_WecEntry( &p->vLits, Vec_WecSize(&p->vLits) - 2 ); |
| // update single-cube divisor cubes |
| // Vec_IntForEachEntryDouble( &p->vCubesS, hCube1, hCube2, i ) |
| Vec_IntForEachEntry( &p->vCubesS, hCube1, i ) |
| { |
| // int Lit0s, Lit1s; |
| vCube1 = Fxch_ManCube( p, hCube1 ); |
| // Lit0s = Vec_IntEntry(vCube1, Pla_CubeLit(hCube1)); |
| // Lit1s = Vec_IntEntry(vCube1, Pla_CubeLit(hCube2)); |
| // assert( Pla_CubeNum(hCube1) == Pla_CubeNum(hCube2) ); |
| // assert( Vec_IntEntry(vCube1, Pla_CubeLit(hCube1)) == Lit0 ); |
| // assert( Vec_IntEntry(vCube1, Pla_CubeLit(hCube2)) == Lit1 ); |
| Fxch_CompressLiterals( vCube1, Lit0, Lit1 ); |
| // Vec_IntPush( vLitP, Pla_CubeHandle(Pla_CubeNum(hCube1), Vec_IntSize(vCube1)) ); |
| Vec_IntPush( vLitP, Pla_CubeNum(hCube1) ); |
| Vec_IntPush( vCube1, Abc_Var2Lit(iVarNew, 0) ); |
| |
| //if ( Pla_CubeNum(hCube1) == 3 ) |
| // printf( "VecSize = %d\n", Vec_IntSize(vCube1) ); |
| |
| p->nLits--; |
| } |
| // update double-cube divisor cube pairs |
| Vec_IntForEachEntryDouble( &p->vCubesD, hCube1, hCube2, i ) |
| { |
| vCube1 = Fxch_ManCube( p, hCube1 ); |
| vCube2 = Fxch_ManCube( p, hCube2 ); |
| assert( Vec_IntEntry(vCube1, Pla_CubeLit(hCube1)) == Abc_LitNot(Lit0) ); |
| assert( Vec_IntEntry(vCube2, Pla_CubeLit(hCube2)) == Abc_LitNot(Lit1) ); |
| Fxch_CompressLiterals2( vCube1, Pla_CubeLit(hCube1), -1 ); |
| // Vec_IntPush( vLitN, Pla_CubeHandle(Pla_CubeNum(hCube1), Vec_IntSize(vCube1)) ); |
| Vec_IntPush( vLitN, Pla_CubeNum(hCube1) ); |
| Vec_IntPush( vCube1, Abc_Var2Lit(iVarNew, 1) ); |
| p->nLits -= Vec_IntSize(vCube2); |
| |
| //if ( Pla_CubeNum(hCube1) == 3 ) |
| // printf( "VecSize = %d\n", Vec_IntSize(vCube1) ); |
| |
| // remove second cube |
| Vec_IntClear( vCube2 ); |
| } |
| Vec_IntSort( vLitN, 0 ); |
| Vec_IntSort( vLitP, 0 ); |
| |
| // add cost of single-cube divisors |
| // Vec_IntForEachEntryDouble( &p->vCubesS, hCube1, hCube2, i ) |
| Vec_IntForEachEntry( &p->vCubesS, hCube1, i ) |
| Fxch_TabSingleDivisors( p, Pla_CubeNum(hCube1), 1 ); // add - update |
| Vec_IntForEachEntryDouble( &p->vCubesD, hCube1, hCube2, i ) |
| Fxch_TabSingleDivisors( p, Pla_CubeNum(hCube1), 1 ); // add - update |
| |
| // add cost of double-cube divisors |
| // Vec_IntForEachEntryDouble( &p->vCubesS, hCube1, hCube2, i ) |
| Vec_IntForEachEntry( &p->vCubesS, hCube1, i ) |
| Fxch_TabDoubleDivisors( p, Pla_CubeNum(hCube1), 1 ); // add - update |
| Vec_IntForEachEntryDouble( &p->vCubesD, hCube1, hCube2, i ) |
| Fxch_TabDoubleDivisors( p, Pla_CubeNum(hCube1), 1 ); // add - update |
| |
| // check predicted improvement: (new SOP lits == old SOP lits - divisor weight) |
| //assert( p->nLits == nLitsNew ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Implements the improved fast_extract algorithm.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static void Fxch_PrintStats( Fxch_Man_t * p, abctime clk ) |
| { |
| printf( "Num =%6d ", Vec_WrdSize(&p->vDivs) - p->nVars ); |
| printf( "Cubes =%8d ", Vec_WecSizeUsed(&p->vCubes) ); |
| printf( "Lits =%8d ", p->nLits ); |
| printf( "Divs =%8d ", Hash_IntManEntryNum(p->vHash) ); |
| printf( "Divs+ =%8d ", Vec_QueSize(p->vPrio) ); |
| printf( "PairS =%6d ", p->nPairsS ); |
| printf( "PairD =%6d ", p->nPairsD ); |
| Abc_PrintTime( 1, "Time", clk ); |
| // printf( "\n" ); |
| } |
| static inline void Fxch_PrintDivOne( Fxch_Man_t * p, int iDiv ) |
| { |
| int i; |
| int Lit0 = Hash_IntObjData0( p->vHash, iDiv ); |
| int Lit1 = Hash_IntObjData1( p->vHash, iDiv ); |
| assert( Lit0 >= 0 && Lit1 >= 0 && Lit0 < Lit1 ); |
| printf( "Div %4d : ", iDiv ); |
| printf( "Weight %12.5f ", Vec_FltEntry(&p->vWeights, iDiv) ); |
| printf( "Pairs = %5d ", Vec_IntSize(Vec_WecEntry(&p->vPairs, iDiv))/2 ); |
| for ( i = 0; i < Vec_WrdSize(&p->vDivs); i++ ) |
| { |
| if ( i == Abc_Lit2Var(Lit0) ) |
| printf( "%d", !Abc_LitIsCompl(Lit0) ); |
| else if ( i == Abc_Lit2Var(Lit1) ) |
| printf( "%d", !Abc_LitIsCompl(Lit1) ); |
| else |
| printf( "-" ); |
| } |
| printf( "\n" ); |
| } |
| static void Fxch_PrintDivisors( Fxch_Man_t * p ) |
| { |
| int iDiv; |
| for ( iDiv = 1; iDiv < Vec_FltSize(&p->vWeights); iDiv++ ) |
| Fxch_PrintDivOne( p, iDiv ); |
| printf( "\n" ); |
| } |
| |
| int Fxch_ManFastExtract( Fxch_Man_t * p, int fVerbose, int fVeryVerbose ) |
| { |
| int nNewNodesMax = ABC_INFINITY; |
| abctime clk = Abc_Clock(); |
| int i, iDiv; |
| Fxch_ManCreateDivisors( p ); |
| // Fxch_PrintDivisors( p ); |
| if ( fVerbose ) |
| Fxch_PrintStats( p, Abc_Clock() - clk ); |
| p->timeStart = Abc_Clock(); |
| for ( i = 0; i < nNewNodesMax && Vec_QueTopPriority(p->vPrio) > 0.0; i++ ) |
| { |
| iDiv = Vec_QuePop(p->vPrio); |
| //if ( fVerbose ) |
| // Fxch_PrintStats( p, Abc_Clock() - clk ); |
| if ( fVeryVerbose ) |
| Fxch_PrintDivOne( p, iDiv ); |
| Fxch_ManUpdate( p, iDiv ); |
| } |
| if ( fVerbose ) |
| Fxch_PrintStats( p, Abc_Clock() - clk ); |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Implements the improved fast_extract algorithm.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Pla_ManPerformFxch( Pla_Man_t * p ) |
| { |
| char pFileName[1000]; |
| Fxch_Man_t * pFxch; |
| Pla_ManConvertFromBits( p ); |
| pFxch = Fxch_ManStart( &p->vCubeLits, &p->vOccurs ); |
| Vec_WecZero( &p->vCubeLits ); |
| Vec_WecZero( &p->vOccurs ); |
| Fxch_ManFastExtract( pFxch, 1, 0 ); |
| sprintf( pFileName, "%s.blif", Pla_ManName(p) ); |
| //Fxch_ManWriteBlif( pFileName, &pFxch->vCubes, &pFxch->vDivs ); |
| Fxch_ManStop( pFxch ); |
| return 1; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |