mirror of https://github.com/YosysHQ/abc.git
476 lines
16 KiB
C
476 lines
16 KiB
C
/**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 );
|
|
|
|
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 ) );
|
|
|
|
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
|