blob: 66c8caddfa49b19cdb6af818e6a408e913017ee2 [file] [log] [blame]
/**CFile****************************************************************
FileName [cutMerge.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [K-feasible cut computation package.]
Synopsis [Procedure to merge two cuts.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: cutMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "cutInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Merges two cuts.]
Description [This procedure works.]
SideEffects []
SeeAlso []
***********************************************************************/
Cut_Cut_t * Cut_CutMergeTwo2( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
{
static int M[7][3] = {{0},{0},{0},{0},{0},{0},{0}};
Cut_Cut_t * pRes;
int * pRow;
int nLeaves0, nLeaves1, Limit;
int i, k, Count, nNodes;
assert( pCut0->nLeaves >= pCut1->nLeaves );
// the case of the largest cut sizes
Limit = p->pParams->nVarsMax;
nLeaves0 = pCut0->nLeaves;
nLeaves1 = pCut1->nLeaves;
if ( nLeaves0 == Limit && nLeaves1 == Limit )
{
for ( i = 0; i < nLeaves0; i++ )
if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] )
return NULL;
pRes = Cut_CutAlloc( p );
for ( i = 0; i < nLeaves0; i++ )
pRes->pLeaves[i] = pCut0->pLeaves[i];
pRes->nLeaves = nLeaves0;
return pRes;
}
// the case when one of the cuts is the largest
if ( nLeaves0 == Limit )
{
for ( i = 0; i < nLeaves1; i++ )
{
for ( k = nLeaves0 - 1; k >= 0; k-- )
if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] )
break;
if ( k == -1 ) // did not find
return NULL;
}
pRes = Cut_CutAlloc( p );
for ( i = 0; i < nLeaves0; i++ )
pRes->pLeaves[i] = pCut0->pLeaves[i];
pRes->nLeaves = nLeaves0;
return pRes;
}
// other cases
nNodes = nLeaves0;
for ( i = 0; i < nLeaves1; i++ )
{
for ( k = nLeaves0 - 1; k >= 0; k-- )
{
if ( pCut0->pLeaves[k] > pCut1->pLeaves[i] )
continue;
if ( pCut0->pLeaves[k] < pCut1->pLeaves[i] )
{
pRow = M[k+1];
if ( pRow[0] == 0 )
pRow[0] = pCut1->pLeaves[i], pRow[1] = 0;
else if ( pRow[1] == 0 )
pRow[1] = pCut1->pLeaves[i], pRow[2] = 0;
else if ( pRow[2] == 0 )
pRow[2] = pCut1->pLeaves[i];
else
assert( 0 );
if ( ++nNodes > Limit )
{
for ( i = 0; i <= nLeaves0; i++ )
M[i][0] = 0;
return NULL;
}
}
break;
}
if ( k == -1 )
{
pRow = M[0];
if ( pRow[0] == 0 )
pRow[0] = pCut1->pLeaves[i], pRow[1] = 0;
else if ( pRow[1] == 0 )
pRow[1] = pCut1->pLeaves[i], pRow[2] = 0;
else if ( pRow[2] == 0 )
pRow[2] = pCut1->pLeaves[i];
else
assert( 0 );
if ( ++nNodes > Limit )
{
for ( i = 0; i <= nLeaves0; i++ )
M[i][0] = 0;
return NULL;
}
continue;
}
}
pRes = Cut_CutAlloc( p );
for ( Count = 0, i = 0; i <= nLeaves0; i++ )
{
if ( i > 0 )
pRes->pLeaves[Count++] = pCut0->pLeaves[i-1];
pRow = M[i];
if ( pRow[0] )
{
pRes->pLeaves[Count++] = pRow[0];
if ( pRow[1] )
{
pRes->pLeaves[Count++] = pRow[1];
if ( pRow[2] )
pRes->pLeaves[Count++] = pRow[2];
}
pRow[0] = 0;
}
}
assert( Count == nNodes );
pRes->nLeaves = nNodes;
return pRes;
}
/**Function*************************************************************
Synopsis [Merges two cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
{
Cut_Cut_t * pRes;
int * pLeaves;
int Limit, nLeaves0, nLeaves1;
int i, k, c;
assert( pCut0->nLeaves >= pCut1->nLeaves );
// consider two cuts
nLeaves0 = pCut0->nLeaves;
nLeaves1 = pCut1->nLeaves;
// the case of the largest cut sizes
Limit = p->pParams->nVarsMax;
if ( nLeaves0 == Limit && nLeaves1 == Limit )
{
for ( i = 0; i < nLeaves0; i++ )
if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] )
return NULL;
pRes = Cut_CutAlloc( p );
for ( i = 0; i < nLeaves0; i++ )
pRes->pLeaves[i] = pCut0->pLeaves[i];
pRes->nLeaves = pCut0->nLeaves;
return pRes;
}
// the case when one of the cuts is the largest
if ( nLeaves0 == Limit )
{
for ( i = 0; i < nLeaves1; i++ )
{
for ( k = nLeaves0 - 1; k >= 0; k-- )
if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] )
break;
if ( k == -1 ) // did not find
return NULL;
}
pRes = Cut_CutAlloc( p );
for ( i = 0; i < nLeaves0; i++ )
pRes->pLeaves[i] = pCut0->pLeaves[i];
pRes->nLeaves = pCut0->nLeaves;
return pRes;
}
// prepare the cut
if ( p->pReady == NULL )
p->pReady = Cut_CutAlloc( p );
pLeaves = p->pReady->pLeaves;
// compare two cuts with different numbers
i = k = 0;
for ( c = 0; c < Limit; c++ )
{
if ( k == nLeaves1 )
{
if ( i == nLeaves0 )
{
p->pReady->nLeaves = c;
pRes = p->pReady; p->pReady = NULL;
return pRes;
}
pLeaves[c] = pCut0->pLeaves[i++];
continue;
}
if ( i == nLeaves0 )
{
if ( k == nLeaves1 )
{
p->pReady->nLeaves = c;
pRes = p->pReady; p->pReady = NULL;
return pRes;
}
pLeaves[c] = pCut1->pLeaves[k++];
continue;
}
if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] )
{
pLeaves[c] = pCut0->pLeaves[i++];
continue;
}
if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] )
{
pLeaves[c] = pCut1->pLeaves[k++];
continue;
}
pLeaves[c] = pCut0->pLeaves[i++];
k++;
}
if ( i < nLeaves0 || k < nLeaves1 )
return NULL;
p->pReady->nLeaves = c;
pRes = p->pReady; p->pReady = NULL;
return pRes;
}
/**Function*************************************************************
Synopsis [Merges two cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Cut_Cut_t * Cut_CutMergeTwo3( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
{
Cut_Cut_t * pRes;
int * pLeaves;
int Limit, nLeaves0, nLeaves1;
int i, k, c;
assert( pCut0->nLeaves >= pCut1->nLeaves );
// prepare the cut
if ( p->pReady == NULL )
p->pReady = Cut_CutAlloc( p );
pLeaves = p->pReady->pLeaves;
// consider two cuts
Limit = p->pParams->nVarsMax;
nLeaves0 = pCut0->nLeaves;
nLeaves1 = pCut1->nLeaves;
if ( nLeaves0 == Limit )
{ // the case when one of the cuts is the largest
if ( nLeaves1 == Limit )
{ // the case when both cuts are the largest
for ( i = 0; i < nLeaves0; i++ )
{
pLeaves[i] = pCut0->pLeaves[i];
if ( pLeaves[i] != pCut1->pLeaves[i] )
return NULL;
}
}
else
{
for ( i = k = 0; i < nLeaves0; i++ )
{
pLeaves[i] = pCut0->pLeaves[i];
if ( k == (int)nLeaves1 )
continue;
if ( pLeaves[i] < pCut1->pLeaves[k] )
continue;
if ( pLeaves[i] == pCut1->pLeaves[k++] )
continue;
return NULL;
}
if ( k < nLeaves1 )
return NULL;
}
p->pReady->nLeaves = nLeaves0;
pRes = p->pReady; p->pReady = NULL;
return pRes;
}
// compare two cuts with different numbers
i = k = 0;
for ( c = 0; c < Limit; c++ )
{
if ( k == nLeaves1 )
{
if ( i == nLeaves0 )
{
p->pReady->nLeaves = c;
pRes = p->pReady; p->pReady = NULL;
return pRes;
}
pLeaves[c] = pCut0->pLeaves[i++];
continue;
}
if ( i == nLeaves0 )
{
if ( k == nLeaves1 )
{
p->pReady->nLeaves = c;
pRes = p->pReady; p->pReady = NULL;
return pRes;
}
pLeaves[c] = pCut1->pLeaves[k++];
continue;
}
if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] )
{
pLeaves[c] = pCut0->pLeaves[i++];
continue;
}
if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] )
{
pLeaves[c] = pCut1->pLeaves[k++];
continue;
}
pLeaves[c] = pCut0->pLeaves[i++];
k++;
}
if ( i < nLeaves0 || k < nLeaves1 )
return NULL;
p->pReady->nLeaves = c;
pRes = p->pReady; p->pReady = NULL;
return pRes;
}
/**Function*************************************************************
Synopsis [Merges two cuts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Cut_Cut_t * Cut_CutMergeTwo4( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
{
Cut_Cut_t * pRes;
int * pLeaves;
int i, k, min, NodeTemp, Limit, nTotal;
assert( pCut0->nLeaves >= pCut1->nLeaves );
// prepare the cut
if ( p->pReady == NULL )
p->pReady = Cut_CutAlloc( p );
pLeaves = p->pReady->pLeaves;
// consider two cuts
Limit = p->pParams->nVarsMax;
if ( pCut0->nLeaves == (unsigned)Limit )
{ // the case when one of the cuts is the largest
if ( pCut1->nLeaves == (unsigned)Limit )
{ // the case when both cuts are the largest
for ( i = 0; i < (int)pCut0->nLeaves; i++ )
{
pLeaves[i] = pCut0->pLeaves[i];
if ( pLeaves[i] != pCut1->pLeaves[i] )
return NULL;
}
}
else
{
for ( i = k = 0; i < (int)pCut0->nLeaves; i++ )
{
pLeaves[i] = pCut0->pLeaves[i];
if ( k == (int)pCut1->nLeaves )
continue;
if ( pLeaves[i] < pCut1->pLeaves[k] )
continue;
if ( pLeaves[i] == pCut1->pLeaves[k++] )
continue;
return NULL;
}
if ( k < (int)pCut1->nLeaves )
return NULL;
}
p->pReady->nLeaves = pCut0->nLeaves;
pRes = p->pReady; p->pReady = NULL;
return pRes;
}
// count the number of unique entries in pCut1
nTotal = pCut0->nLeaves;
for ( i = 0; i < (int)pCut1->nLeaves; i++ )
{
// try to find this entry among the leaves of pCut0
for ( k = 0; k < (int)pCut0->nLeaves; k++ )
if ( pCut1->pLeaves[i] == pCut0->pLeaves[k] )
break;
if ( k < (int)pCut0->nLeaves ) // found
continue;
// we found a new entry to add
if ( nTotal == Limit )
return NULL;
pLeaves[nTotal++] = pCut1->pLeaves[i];
}
// we know that the feasible cut exists
// add the starting entries
for ( k = 0; k < (int)pCut0->nLeaves; k++ )
pLeaves[k] = pCut0->pLeaves[k];
// selection-sort the entries
for ( i = 0; i < nTotal - 1; i++ )
{
min = i;
for ( k = i+1; k < nTotal; k++ )
if ( pLeaves[k] < pLeaves[min] )
min = k;
NodeTemp = pLeaves[i];
pLeaves[i] = pLeaves[min];
pLeaves[min] = NodeTemp;
}
p->pReady->nLeaves = nTotal;
pRes = p->pReady; p->pReady = NULL;
return pRes;
}
/**Function*************************************************************
Synopsis [Merges two cuts.]
Description [This procedure works.]
SideEffects []
SeeAlso []
***********************************************************************/
Cut_Cut_t * Cut_CutMergeTwo5( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
{
static int M[7][3] = {{0},{0},{0},{0},{0},{0},{0}};
Cut_Cut_t * pRes;
int * pRow;
unsigned uSign0, uSign1;
int i, k, nNodes, Count;
unsigned Limit = p->pParams->nVarsMax;
assert( pCut0->nLeaves >= pCut1->nLeaves );
// the case of the largest cut sizes
if ( pCut0->nLeaves == Limit && pCut1->nLeaves == Limit )
{
for ( i = 0; i < (int)pCut0->nLeaves; i++ )
if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] )
return NULL;
pRes = Cut_CutAlloc( p );
for ( i = 0; i < (int)pCut0->nLeaves; i++ )
pRes->pLeaves[i] = pCut0->pLeaves[i];
pRes->nLeaves = pCut0->nLeaves;
return pRes;
}
// the case when one of the cuts is the largest
if ( pCut0->nLeaves == Limit )
{
if ( !p->pParams->fTruth )
{
for ( i = 0; i < (int)pCut1->nLeaves; i++ )
{
for ( k = pCut0->nLeaves - 1; k >= 0; k-- )
if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] )
break;
if ( k == -1 ) // did not find
return NULL;
}
pRes = Cut_CutAlloc( p );
}
else
{
uSign1 = 0;
for ( i = 0; i < (int)pCut1->nLeaves; i++ )
{
for ( k = pCut0->nLeaves - 1; k >= 0; k-- )
if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] )
{
uSign1 |= (1 << i);
break;
}
if ( k == -1 ) // did not find
return NULL;
}
pRes = Cut_CutAlloc( p );
pRes->Num1 = uSign1;
}
for ( i = 0; i < (int)pCut0->nLeaves; i++ )
pRes->pLeaves[i] = pCut0->pLeaves[i];
pRes->nLeaves = pCut0->nLeaves;
return pRes;
}
// other cases
nNodes = pCut0->nLeaves;
for ( i = 0; i < (int)pCut1->nLeaves; i++ )
{
for ( k = pCut0->nLeaves - 1; k >= 0; k-- )
{
if ( pCut0->pLeaves[k] > pCut1->pLeaves[i] )
continue;
if ( pCut0->pLeaves[k] < pCut1->pLeaves[i] )
{
pRow = M[k+1];
if ( pRow[0] == 0 )
pRow[0] = pCut1->pLeaves[i], pRow[1] = 0;
else if ( pRow[1] == 0 )
pRow[1] = pCut1->pLeaves[i], pRow[2] = 0;
else if ( pRow[2] == 0 )
pRow[2] = pCut1->pLeaves[i];
else
assert( 0 );
if ( ++nNodes > (int)Limit )
{
for ( i = 0; i <= (int)pCut0->nLeaves; i++ )
M[i][0] = 0;
return NULL;
}
}
break;
}
if ( k == -1 )
{
pRow = M[0];
if ( pRow[0] == 0 )
pRow[0] = pCut1->pLeaves[i], pRow[1] = 0;
else if ( pRow[1] == 0 )
pRow[1] = pCut1->pLeaves[i], pRow[2] = 0;
else if ( pRow[2] == 0 )
pRow[2] = pCut1->pLeaves[i];
else
assert( 0 );
if ( ++nNodes > (int)Limit )
{
for ( i = 0; i <= (int)pCut0->nLeaves; i++ )
M[i][0] = 0;
return NULL;
}
continue;
}
}
pRes = Cut_CutAlloc( p );
if ( !p->pParams->fTruth )
{
for ( Count = 0, i = 0; i <= (int)pCut0->nLeaves; i++ )
{
if ( i > 0 )
pRes->pLeaves[Count++] = pCut0->pLeaves[i-1];
pRow = M[i];
if ( pRow[0] )
{
pRes->pLeaves[Count++] = pRow[0];
if ( pRow[1] )
{
pRes->pLeaves[Count++] = pRow[1];
if ( pRow[2] )
pRes->pLeaves[Count++] = pRow[2];
}
pRow[0] = 0;
}
}
assert( Count == nNodes );
pRes->nLeaves = nNodes;
/*
// make sure that the cut is correct
{
for ( i = 1; i < (int)pRes->nLeaves; i++ )
if ( pRes->pLeaves[i-1] >= pRes->pLeaves[i] )
{
int v = 0;
}
}
*/
return pRes;
}
uSign0 = uSign1 = 0;
for ( Count = 0, i = 0; i <= (int)pCut0->nLeaves; i++ )
{
if ( i > 0 )
{
uSign0 |= (1 << Count);
pRes->pLeaves[Count++] = pCut1->pLeaves[i-1];
}
pRow = M[i];
if ( pRow[0] )
{
uSign1 |= (1 << Count);
pRes->pLeaves[Count++] = pRow[0];
if ( pRow[1] )
{
uSign1 |= (1 << Count);
pRes->pLeaves[Count++] = pRow[1];
if ( pRow[2] )
{
uSign1 |= (1 << Count);
pRes->pLeaves[Count++] = pRow[2];
}
}
pRow[0] = 0;
}
}
assert( Count == nNodes );
pRes->nLeaves = nNodes;
pRes->Num1 = uSign1;
pRes->Num0 = uSign0;
return pRes;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END