blob: 99c260c6b73eb26daeef688a976064a7a1d4e672 [file] [log] [blame]
/**CFile****************************************************************************************************************
FileName [ FxchDiv.c ]
PackageName [ Fast eXtract with Cube Hashing (FXCH) ]
Synopsis [ Divisor handling functions ]
Author [ Bruno Schmitt - boschmitt at inf.ufrgs.br ]
Affiliation [ UFRGS ]
Date [ Ver. 1.0. Started - March 6, 2016. ]
Revision []
***********************************************************************************************************************/
#include "Fxch.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTION DEFINITIONS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static inline int Fxch_DivNormalize( Vec_Int_t* vCubeFree )
{
int * L = Vec_IntArray(vCubeFree);
int RetValue = 0, LitA0 = -1, LitB0 = -1, LitA1 = -1, LitB1 = -1;
assert( Vec_IntSize(vCubeFree) == 4 );
if ( Abc_LitIsCompl(L[0]) != Abc_LitIsCompl(L[1]) && (L[0] >> 2) == (L[1] >> 2) ) // diff cubes, same vars
{
if ( Abc_LitIsCompl(L[2]) == Abc_LitIsCompl(L[3]) )
return -1;
LitA0 = Abc_Lit2Var(L[0]), LitB0 = Abc_Lit2Var(L[1]);
if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[2]) )
{
assert( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[3]) );
LitA1 = Abc_Lit2Var(L[2]), LitB1 = Abc_Lit2Var(L[3]);
}
else
{
assert( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[3]) );
assert( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[2]) );
LitA1 = Abc_Lit2Var(L[3]), LitB1 = Abc_Lit2Var(L[2]);
}
}
else if ( Abc_LitIsCompl(L[1]) != Abc_LitIsCompl(L[2]) && (L[1] >> 2) == (L[2] >> 2) )
{
if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[3]) )
return -1;
LitA0 = Abc_Lit2Var(L[1]), LitB0 = Abc_Lit2Var(L[2]);
if ( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[0]) )
LitA1 = Abc_Lit2Var(L[0]), LitB1 = Abc_Lit2Var(L[3]);
else
LitA1 = Abc_Lit2Var(L[3]), LitB1 = Abc_Lit2Var(L[0]);
}
else if ( Abc_LitIsCompl(L[2]) != Abc_LitIsCompl(L[3]) && (L[2] >> 2) == (L[3] >> 2) )
{
if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[1]) )
return -1;
LitA0 = Abc_Lit2Var(L[2]), LitB0 = Abc_Lit2Var(L[3]);
if ( Abc_LitIsCompl(L[2]) == Abc_LitIsCompl(L[0]) )
LitA1 = Abc_Lit2Var(L[0]), LitB1 = Abc_Lit2Var(L[1]);
else
LitA1 = Abc_Lit2Var(L[1]), LitB1 = Abc_Lit2Var(L[0]);
}
else
return -1;
assert( LitA0 == Abc_LitNot(LitB0) );
if ( Abc_LitIsCompl(LitA0) )
{
ABC_SWAP( int, LitA0, LitB0 );
ABC_SWAP( int, LitA1, LitB1 );
}
assert( !Abc_LitIsCompl(LitA0) );
if ( Abc_LitIsCompl(LitA1) )
{
LitA1 = Abc_LitNot(LitA1);
LitB1 = Abc_LitNot(LitB1);
RetValue = 1;
}
assert( !Abc_LitIsCompl(LitA1) );
// arrange literals in such as a way that
// - the first two literals are control literals from different cubes
// - the third literal is non-complented data input
// - the forth literal is possibly complemented data input
L[0] = Abc_Var2Lit( LitA0, 0 );
L[1] = Abc_Var2Lit( LitB0, 1 );
L[2] = Abc_Var2Lit( LitA1, 0 );
L[3] = Abc_Var2Lit( LitB1, 1 );
return RetValue;
}
/**Function*************************************************************
Synopsis [ Creates a Divisor. ]
Description [ This functions receive as input two sub-cubes and creates
a divisor using their information. The divisor is stored
in vCubeFree vector of the pFxchMan structure.
It returns the base value, which is the number of elements
that the cubes pair used to generate the devisor have in
common. ]
SideEffects []
SeeAlso []
***********************************************************************/
int Fxch_DivCreate( Fxch_Man_t* pFxchMan,
Fxch_SubCube_t* pSubCube0,
Fxch_SubCube_t* pSubCube1 )
{
int Base = 0;
int SC0_Lit0,
SC0_Lit1,
SC1_Lit0,
SC1_Lit1;
int Cube0Size,
Cube1Size;
Vec_IntClear( pFxchMan->vCubeFree );
SC0_Lit0 = Fxch_ManGetLit( pFxchMan, pSubCube0->iCube, pSubCube0->iLit0 );
SC0_Lit1 = 0;
SC1_Lit0 = Fxch_ManGetLit( pFxchMan, pSubCube1->iCube, pSubCube1->iLit0 );
SC1_Lit1 = 0;
if ( pSubCube0->iLit1 == 0 && pSubCube1->iLit1 == 0 )
{
Vec_IntPush( pFxchMan->vCubeFree, SC0_Lit0 );
Vec_IntPush( pFxchMan->vCubeFree, SC1_Lit0 );
}
else if ( pSubCube0->iLit1 > 0 && pSubCube1->iLit1 > 0 )
{
int RetValue;
SC0_Lit1 = Fxch_ManGetLit( pFxchMan, pSubCube0->iCube, pSubCube0->iLit1 );
SC1_Lit1 = Fxch_ManGetLit( pFxchMan, pSubCube1->iCube, pSubCube1->iLit1 );
if ( SC0_Lit0 < SC1_Lit0 )
{
Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit0, 0 ) );
Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit0, 1 ) );
Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit1, 0 ) );
Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit1, 1 ) );
}
else
{
Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit0, 0 ) );
Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit0, 1 ) );
Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit1, 0 ) );
Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit1, 1 ) );
}
RetValue = Fxch_DivNormalize( pFxchMan->vCubeFree );
if ( RetValue == -1 )
return -1;
}
else
{
if ( pSubCube0->iLit1 > 0 )
{
SC0_Lit1 = Fxch_ManGetLit( pFxchMan, pSubCube0->iCube, pSubCube0->iLit1 );
Vec_IntPush( pFxchMan->vCubeFree, SC1_Lit0 );
if ( SC0_Lit0 == Abc_LitNot( SC1_Lit0 ) )
Vec_IntPush( pFxchMan->vCubeFree, SC0_Lit1 );
else if ( SC0_Lit1 == Abc_LitNot( SC1_Lit0 ) )
Vec_IntPush( pFxchMan->vCubeFree, SC0_Lit0 );
}
else
{
SC1_Lit1 = Fxch_ManGetLit( pFxchMan, pSubCube1->iCube, pSubCube1->iLit1 );
Vec_IntPush( pFxchMan->vCubeFree, SC0_Lit0 );
if ( SC1_Lit0 == Abc_LitNot( SC0_Lit0 ) )
Vec_IntPush( pFxchMan->vCubeFree, SC1_Lit1 );
else if ( SC1_Lit1 == Abc_LitNot( SC0_Lit0 ) )
Vec_IntPush( pFxchMan->vCubeFree, SC1_Lit0 );
}
}
if ( Vec_IntSize( pFxchMan->vCubeFree ) == 0 )
return -1;
if ( Vec_IntSize ( pFxchMan->vCubeFree ) == 2 )
{
Vec_IntSort( pFxchMan->vCubeFree, 0 );
Vec_IntWriteEntry( pFxchMan->vCubeFree, 0, Abc_Var2Lit( Vec_IntEntry( pFxchMan->vCubeFree, 0 ), 0 ) );
Vec_IntWriteEntry( pFxchMan->vCubeFree, 1, Abc_Var2Lit( Vec_IntEntry( pFxchMan->vCubeFree, 1 ), 1 ) );
}
Cube0Size = Vec_IntSize( Fxch_ManGetCube( pFxchMan, pSubCube0->iCube ) );
Cube1Size = Vec_IntSize( Fxch_ManGetCube( pFxchMan, pSubCube1->iCube ) );
if ( Vec_IntSize( pFxchMan->vCubeFree ) % 2 == 0 )
{
Base = Abc_MinInt( Cube0Size, Cube1Size )
-( Vec_IntSize( pFxchMan->vCubeFree ) / 2) - 1; /* 1 or 2 Lits, 1 SOP NodeID */
}
else
return -1;
return Base;
}
/**Function*************************************************************
Synopsis [ Add a divisor to the divisors hash table. ]
Description [ This functions will try to add the divisor store in
vCubeFree to the divisor hash table. If the divisor
is already present in the hash table it will just
increment its weight, otherwise it will add the divisor
and asign an initial weight. ]
SideEffects [ If the fUpdate option is set, the function will also
update the divisor priority queue. ]
SeeAlso []
***********************************************************************/
int Fxch_DivAdd( Fxch_Man_t* pFxchMan,
int fUpdate,
int fSingleCube,
int fBase )
{
int iDiv = Hsh_VecManAdd( pFxchMan->pDivHash, pFxchMan->vCubeFree );
/* Verify if the divisor already exist */
if ( iDiv == Vec_FltSize( pFxchMan->vDivWeights ) )
{
Vec_WecPushLevel( pFxchMan->vDivCubePairs );
/* Assign initial weight */
if ( fSingleCube )
{
Vec_FltPush( pFxchMan->vDivWeights,
-Vec_IntSize( pFxchMan->vCubeFree ) + 0.9
-0.001 * Fxch_ManComputeLevelDiv( pFxchMan, pFxchMan->vCubeFree ) );
}
else
{
Vec_FltPush( pFxchMan->vDivWeights,
-Vec_IntSize( pFxchMan->vCubeFree ) + 0.9
-0.0009 * Fxch_ManComputeLevelDiv( pFxchMan, pFxchMan->vCubeFree ) );
}
}
/* Increment weight */
if ( fSingleCube )
Vec_FltAddToEntry( pFxchMan->vDivWeights, iDiv, 1 );
else
Vec_FltAddToEntry( pFxchMan->vDivWeights, iDiv, fBase + Vec_IntSize( pFxchMan->vCubeFree ) - 1 );
assert( iDiv < Vec_FltSize( pFxchMan->vDivWeights ) );
if ( fUpdate )
if ( pFxchMan->vDivPrio )
{
if ( Vec_QueIsMember( pFxchMan->vDivPrio, iDiv ) )
Vec_QueUpdate( pFxchMan->vDivPrio, iDiv );
else
Vec_QuePush( pFxchMan->vDivPrio, iDiv );
}
return iDiv;
}
/**Function*************************************************************
Synopsis [ Removes a divisor to the divisors hash table. ]
Description [ This function don't effectively removes a divisor from
the hash table (the hash table implementation don't
support such operation). It only assures its existence
and decrement its weight. ]
SideEffects [ If the fUpdate option is set, the function will also
update the divisor priority queue. ]
SeeAlso []
***********************************************************************/
int Fxch_DivRemove( Fxch_Man_t* pFxchMan,
int fUpdate,
int fSingleCube,
int fBase )
{
int iDiv = Hsh_VecManAdd( pFxchMan->pDivHash, pFxchMan->vCubeFree );
assert( iDiv < Vec_FltSize( pFxchMan->vDivWeights ) );
/* Decrement weight */
if ( fSingleCube )
Vec_FltAddToEntry( pFxchMan->vDivWeights, iDiv, -1 );
else
Vec_FltAddToEntry( pFxchMan->vDivWeights, iDiv, -( fBase + Vec_IntSize( pFxchMan->vCubeFree ) - 1 ) );
if ( fUpdate )
if ( pFxchMan->vDivPrio )
{
if ( Vec_QueIsMember( pFxchMan->vDivPrio, iDiv ) )
Vec_QueUpdate( pFxchMan->vDivPrio, iDiv );
}
return iDiv;
}
/**Function*************************************************************
Synopsis [ Separete the cubes in present in a divisor ]
Description [ In this implementation *all* stored divsors are composed
of two cubes.
In order to save space and to be able to use the Vec_Int_t
hash table both cubes are stored in the same vector - using
a little hack to differentiate which literal belongs to each
cube.
This function separetes the two cubes in their own vectors
so that they can be added to the cover.
*Note* that this also applies to single cube
divisors beacuse of the DeMorgan Law: ab = ( a! + !b )! ]
SideEffects []
SeeAlso []
***********************************************************************/
void Fxch_DivSepareteCubes( Vec_Int_t* vDiv,
Vec_Int_t* vCube0,
Vec_Int_t* vCube1 )
{
int* pArray;
int i,
Lit;
Vec_IntForEachEntry( vDiv, Lit, i )
if ( Abc_LitIsCompl(Lit) )
Vec_IntPush( vCube1, Abc_Lit2Var( Lit ) );
else
Vec_IntPush( vCube0, Abc_Lit2Var( Lit ) );
if ( ( Vec_IntSize( vDiv ) == 4 ) && ( Vec_IntSize( vCube0 ) == 3 ) )
{
assert( Vec_IntSize( vCube1 ) == 3 );
pArray = Vec_IntArray( vCube0 );
if ( pArray[1] > pArray[2] )
ABC_SWAP( int, pArray[1], pArray[2] );
pArray = Vec_IntArray( vCube1 );
if ( pArray[1] > pArray[2] )
ABC_SWAP( int, pArray[1], pArray[2] );
}
}
/**Function*************************************************************
Synopsis [ Removes the literals present in the divisor from their
original cubes. ]
Description [ This function returns the numeber of removed literals
which should be equal to the size of the divisor. ]
SideEffects []
SeeAlso []
***********************************************************************/
int Fxch_DivRemoveLits( Vec_Int_t* vCube0,
Vec_Int_t* vCube1,
Vec_Int_t* vDiv,
int *fCompl )
{
int i,
Lit,
CountP = 0,
CountN = 0,
Count = 0,
ret = 0;
Vec_IntForEachEntry( vDiv, Lit, i )
if ( Abc_LitIsCompl( Abc_Lit2Var( Lit ) ) )
CountN += Vec_IntRemove1( vCube0, Abc_Lit2Var( Lit ) );
else
CountP += Vec_IntRemove1( vCube0, Abc_Lit2Var( Lit ) );
Vec_IntForEachEntry( vDiv, Lit, i )
Count += Vec_IntRemove1( vCube1, Abc_Lit2Var( Lit ) );
if ( Vec_IntSize( vDiv ) == 2 )
Vec_IntForEachEntry( vDiv, Lit, i )
{
Vec_IntRemove1( vCube0, Abc_LitNot( Abc_Lit2Var( Lit ) ) );
Vec_IntRemove1( vCube1, Abc_LitNot( Abc_Lit2Var( Lit ) ) );
}
ret = Count + CountP + CountN;
if ( Vec_IntSize( vDiv ) == 4 )
{
int Lit0 = Abc_Lit2Var( Vec_IntEntry( vDiv, 0 ) ),
Lit1 = Abc_Lit2Var( Vec_IntEntry( vDiv, 1 ) ),
Lit2 = Abc_Lit2Var( Vec_IntEntry( vDiv, 2 ) ),
Lit3 = Abc_Lit2Var( Vec_IntEntry( vDiv, 3 ) );
if ( Lit0 == Abc_LitNot( Lit1 ) && Lit2 == Abc_LitNot( Lit3 ) && CountN == 1 )
*fCompl = 1;
if ( Lit0 == Abc_LitNot( Lit1 ) && ret == 2 )
{
*fCompl = 1;
Vec_IntForEachEntry( vDiv, Lit, i )
ret += Vec_IntRemove1( vCube0, ( Abc_Lit2Var( Lit ) ^ (fCompl && i > 1) ) );
Vec_IntForEachEntry( vDiv, Lit, i )
ret += Vec_IntRemove1( vCube1, ( Abc_Lit2Var( Lit ) ^ (fCompl && i > 1) ) );
}
}
return ret;
}
/**Function*************************************************************
Synopsis [ Print the divisor identified by iDiv. ]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fxch_DivPrint( Fxch_Man_t* pFxchMan,
int iDiv )
{
Vec_Int_t* vDiv = Hsh_VecReadEntry( pFxchMan->pDivHash, iDiv );
int i,
Lit;
printf( "Div %7d : ", iDiv );
printf( "Weight %12.5f ", Vec_FltEntry( pFxchMan->vDivWeights, iDiv ) );
Vec_IntForEachEntry( vDiv, Lit, i )
if ( !Abc_LitIsCompl( Lit ) )
printf( "%d(1)", Abc_Lit2Var( Lit ) );
printf( " + " );
Vec_IntForEachEntry( vDiv, Lit, i )
if ( Abc_LitIsCompl( Lit ) )
printf( "%d(2)", Abc_Lit2Var( Lit ) );
printf( " Lits =%7d ", pFxchMan->nLits );
printf( "Divs =%8d \n", Hsh_VecSize( pFxchMan->pDivHash ) );
}
int Fxch_DivIsNotConstant1( Vec_Int_t* vDiv )
{
int Lit0 = Abc_Lit2Var( Vec_IntEntry( vDiv, 0 ) ),
Lit1 = Abc_Lit2Var( Vec_IntEntry( vDiv, 1 ) );
if ( ( Vec_IntSize( vDiv ) == 2 ) && ( Lit0 == Abc_LitNot( Lit1 ) ) )
return 0;
return 1;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END