mirror of https://github.com/YosysHQ/abc.git
290 lines
9.4 KiB
C
290 lines
9.4 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [fxuSingle.c]
|
|
|
|
PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
|
|
|
|
Synopsis [Procedures to compute the set of single-cube divisors.]
|
|
|
|
Author [MVSIS Group]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - February 1, 2003.]
|
|
|
|
Revision [$Id: fxuSingle.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "fxuInt.h"
|
|
#include "misc/vec/vec.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
static void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles );
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes and adds all single-cube divisors to storage.]
|
|
|
|
Description [This procedure should be called once when the matrix is
|
|
already contructed before the process of logic extraction begins..]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax )
|
|
{
|
|
Fxu_Var * pVar;
|
|
Vec_Ptr_t * vSingles;
|
|
int i, k;
|
|
// set the weight limit
|
|
p->nWeightLimit = 1 - fUse0;
|
|
// iterate through columns in the matrix and collect single-cube divisors
|
|
vSingles = Vec_PtrAlloc( 10000 );
|
|
Fxu_MatrixForEachVariable( p, pVar )
|
|
Fxu_MatrixComputeSinglesOneCollect( p, pVar, vSingles );
|
|
p->nSingleTotal = Vec_PtrSize(vSingles) / 3;
|
|
// check if divisors should be filtered
|
|
if ( Vec_PtrSize(vSingles) > nSingleMax )
|
|
{
|
|
int * pWeigtCounts, nDivCount, Weight, i, c;;
|
|
assert( Vec_PtrSize(vSingles) % 3 == 0 );
|
|
// count how many divisors have the given weight
|
|
pWeigtCounts = ABC_ALLOC( int, 1000 );
|
|
memset( pWeigtCounts, 0, sizeof(int) * 1000 );
|
|
for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 )
|
|
{
|
|
Weight = (int)(ABC_PTRUINT_T)Vec_PtrEntry(vSingles, i);
|
|
if ( Weight >= 999 )
|
|
pWeigtCounts[999]++;
|
|
else
|
|
pWeigtCounts[Weight]++;
|
|
}
|
|
// select the bound on the weight (above this bound, singles will be included)
|
|
nDivCount = 0;
|
|
for ( c = 999; c >= 0; c-- )
|
|
{
|
|
nDivCount += pWeigtCounts[c];
|
|
if ( nDivCount >= nSingleMax )
|
|
break;
|
|
}
|
|
ABC_FREE( pWeigtCounts );
|
|
// collect singles with the given costs
|
|
k = 0;
|
|
for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 )
|
|
{
|
|
Weight = (int)(ABC_PTRUINT_T)Vec_PtrEntry(vSingles, i);
|
|
if ( Weight < c )
|
|
continue;
|
|
Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-2) );
|
|
Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-1) );
|
|
Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i) );
|
|
if ( k/3 == nSingleMax )
|
|
break;
|
|
}
|
|
Vec_PtrShrink( vSingles, k );
|
|
// adjust the weight limit
|
|
p->nWeightLimit = c;
|
|
}
|
|
// collect the selected divisors
|
|
assert( Vec_PtrSize(vSingles) % 3 == 0 );
|
|
for ( i = 0; i < Vec_PtrSize(vSingles); i += 3 )
|
|
{
|
|
Fxu_MatrixAddSingle( p,
|
|
(Fxu_Var *)Vec_PtrEntry(vSingles,i),
|
|
(Fxu_Var *)Vec_PtrEntry(vSingles,i+1),
|
|
(int)(ABC_PTRUINT_T)Vec_PtrEntry(vSingles,i+2) );
|
|
}
|
|
Vec_PtrFree( vSingles );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Adds the single-cube divisors associated with a new column.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles )
|
|
{
|
|
Fxu_Lit * pLitV, * pLitH;
|
|
Fxu_Var * pVar2;
|
|
int Coin;
|
|
int WeightCur;
|
|
|
|
// start collecting the affected vars
|
|
Fxu_MatrixRingVarsStart( p );
|
|
// go through all the literals of this variable
|
|
for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext )
|
|
// for this literal, go through all the horizontal literals
|
|
for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev )
|
|
{
|
|
// get another variable
|
|
pVar2 = pLitH->pVar;
|
|
// skip the var if it is already used
|
|
if ( pVar2->pOrder )
|
|
continue;
|
|
// skip the var if it belongs to the same node
|
|
// if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] )
|
|
// continue;
|
|
// collect the var
|
|
Fxu_MatrixRingVarsAdd( p, pVar2 );
|
|
}
|
|
// stop collecting the selected vars
|
|
Fxu_MatrixRingVarsStop( p );
|
|
|
|
// iterate through the selected vars
|
|
Fxu_MatrixForEachVarInRing( p, pVar2 )
|
|
{
|
|
// count the coincidence
|
|
Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar );
|
|
assert( Coin > 0 );
|
|
// get the new weight
|
|
WeightCur = Coin - 2;
|
|
// peformance fix (August 24, 2007)
|
|
if ( WeightCur >= p->nWeightLimit )
|
|
{
|
|
Vec_PtrPush( vSingles, pVar2 );
|
|
Vec_PtrPush( vSingles, pVar );
|
|
Vec_PtrPush( vSingles, (void *)(ABC_PTRUINT_T)WeightCur );
|
|
}
|
|
}
|
|
|
|
// unmark the vars
|
|
Fxu_MatrixRingVarsUnmark( p );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Adds the single-cube divisors associated with a new column.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar )
|
|
{
|
|
Fxu_Lit * pLitV, * pLitH;
|
|
Fxu_Var * pVar2;
|
|
int Coin;
|
|
int WeightCur;
|
|
|
|
// start collecting the affected vars
|
|
Fxu_MatrixRingVarsStart( p );
|
|
// go through all the literals of this variable
|
|
for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext )
|
|
// for this literal, go through all the horizontal literals
|
|
for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev )
|
|
{
|
|
// get another variable
|
|
pVar2 = pLitH->pVar;
|
|
// skip the var if it is already used
|
|
if ( pVar2->pOrder )
|
|
continue;
|
|
// skip the var if it belongs to the same node
|
|
// if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] )
|
|
// continue;
|
|
// collect the var
|
|
Fxu_MatrixRingVarsAdd( p, pVar2 );
|
|
}
|
|
// stop collecting the selected vars
|
|
Fxu_MatrixRingVarsStop( p );
|
|
|
|
// iterate through the selected vars
|
|
Fxu_MatrixForEachVarInRing( p, pVar2 )
|
|
{
|
|
// count the coincidence
|
|
Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar );
|
|
assert( Coin > 0 );
|
|
// get the new weight
|
|
WeightCur = Coin - 2;
|
|
// peformance fix (August 24, 2007)
|
|
// if ( WeightCur >= 0 )
|
|
// Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur );
|
|
if ( WeightCur >= p->nWeightLimit )
|
|
Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur );
|
|
}
|
|
// unmark the vars
|
|
Fxu_MatrixRingVarsUnmark( p );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes the coincidence count of two columns.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 )
|
|
{
|
|
Fxu_Lit * pLit1, * pLit2;
|
|
int Result;
|
|
|
|
// compute the coincidence count
|
|
Result = 0;
|
|
pLit1 = pVar1->lLits.pHead;
|
|
pLit2 = pVar2->lLits.pHead;
|
|
while ( 1 )
|
|
{
|
|
if ( pLit1 && pLit2 )
|
|
{
|
|
if ( pLit1->pCube->pVar->iVar == pLit2->pCube->pVar->iVar )
|
|
{ // the variables are the same
|
|
if ( pLit1->iCube == pLit2->iCube )
|
|
{ // the literals are the same
|
|
pLit1 = pLit1->pVNext;
|
|
pLit2 = pLit2->pVNext;
|
|
// add this literal to the coincidence
|
|
Result++;
|
|
}
|
|
else if ( pLit1->iCube < pLit2->iCube )
|
|
pLit1 = pLit1->pVNext;
|
|
else
|
|
pLit2 = pLit2->pVNext;
|
|
}
|
|
else if ( pLit1->pCube->pVar->iVar < pLit2->pCube->pVar->iVar )
|
|
pLit1 = pLit1->pVNext;
|
|
else
|
|
pLit2 = pLit2->pVNext;
|
|
}
|
|
else if ( pLit1 && !pLit2 )
|
|
pLit1 = pLit1->pVNext;
|
|
else if ( !pLit1 && pLit2 )
|
|
pLit2 = pLit2->pVNext;
|
|
else
|
|
break;
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|