blob: 244b4702e7cbc4e4b52e5fbd3385c570edcdc08b [file] [log] [blame]
/**CFile****************************************************************
FileName [covMinSop.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Mapping into network of SOPs/ESOPs.]
Synopsis [SOP manipulation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: covMinSop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "covInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static void Min_SopRewrite( Min_Man_t * p );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Min_SopMinimize( Min_Man_t * p )
{
int nCubesInit, nCubesOld, nIter;
if ( p->nCubes < 3 )
return;
nIter = 0;
nCubesInit = p->nCubes;
do {
nCubesOld = p->nCubes;
Min_SopRewrite( p );
nIter++;
// printf( "%d:%d->%d ", nIter, nCubesInit, p->nCubes );
}
while ( 100.0*(nCubesOld - p->nCubes)/nCubesOld > 3.0 );
// printf( "\n" );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Min_SopRewrite( Min_Man_t * p )
{
Min_Cube_t * pCube, ** ppPrev;
Min_Cube_t * pThis, ** ppPrevT;
Min_Cube_t * pTemp;
int v00, v01, v10, v11, Var0, Var1, Index, fCont0, fCont1, nCubesOld;
int nPairs = 0;
/*
{
Min_Cube_t * pCover;
pCover = Min_CoverCollect( p, p->nVars );
printf( "\n\n" );
Min_CoverWrite( stdout, pCover );
Min_CoverExpand( p, pCover );
}
*/
// insert the bubble before the first cube
p->pBubble->pNext = p->ppStore[0];
p->ppStore[0] = p->pBubble;
p->pBubble->nLits = 0;
// go through the cubes
while ( 1 )
{
// get the index of the bubble
Index = p->pBubble->nLits;
// find the bubble
Min_CoverForEachCubePrev( p->ppStore[Index], pCube, ppPrev )
if ( pCube == p->pBubble )
break;
assert( pCube == p->pBubble );
// remove the bubble, get the next cube after the bubble
*ppPrev = p->pBubble->pNext;
pCube = p->pBubble->pNext;
if ( pCube == NULL )
for ( Index++; Index <= p->nVars; Index++ )
if ( p->ppStore[Index] )
{
ppPrev = &(p->ppStore[Index]);
pCube = p->ppStore[Index];
break;
}
// stop if there is no more cubes
if ( pCube == NULL )
break;
// find the first dist2 cube
Min_CoverForEachCubePrev( pCube->pNext, pThis, ppPrevT )
if ( Min_CubesDistTwo( pCube, pThis, &Var0, &Var1 ) )
break;
if ( pThis == NULL && Index < p->nVars )
Min_CoverForEachCubePrev( p->ppStore[Index+1], pThis, ppPrevT )
if ( Min_CubesDistTwo( pCube, pThis, &Var0, &Var1 ) )
break;
// continue if there is no dist2 cube
if ( pThis == NULL )
{
// insert the bubble after the cube
p->pBubble->pNext = pCube->pNext;
pCube->pNext = p->pBubble;
p->pBubble->nLits = pCube->nLits;
continue;
}
nPairs++;
/*
printf( "\n" );
Min_CubeWrite( stdout, pCube );
Min_CubeWrite( stdout, pThis );
*/
// remove the cubes, insert the bubble instead of pCube
*ppPrevT = pThis->pNext;
*ppPrev = p->pBubble;
p->pBubble->pNext = pCube->pNext;
p->pBubble->nLits = pCube->nLits;
p->nCubes -= 2;
assert( pCube != p->pBubble && pThis != p->pBubble );
// save the dist2 parameters
v00 = Min_CubeGetVar( pCube, Var0 );
v01 = Min_CubeGetVar( pCube, Var1 );
v10 = Min_CubeGetVar( pThis, Var0 );
v11 = Min_CubeGetVar( pThis, Var1 );
assert( v00 != v10 && v01 != v11 );
assert( v00 != 3 || v01 != 3 );
assert( v10 != 3 || v11 != 3 );
//printf( "\n" );
//Min_CubeWrite( stdout, pCube );
//Min_CubeWrite( stdout, pThis );
//printf( "\n" );
//Min_CubeWrite( stdout, pCube );
//Min_CubeWrite( stdout, pThis );
// consider the case when both cubes have non-empty literals
if ( v00 != 3 && v01 != 3 && v10 != 3 && v11 != 3 )
{
assert( v00 == (v10 ^ 3) );
assert( v01 == (v11 ^ 3) );
// create the temporary cube equal to the first corner
Min_CubeXorVar( pCube, Var0, 3 );
// check if this cube is contained
fCont0 = Min_CoverContainsCube( p, pCube );
// create the temporary cube equal to the first corner
Min_CubeXorVar( pCube, Var0, 3 );
Min_CubeXorVar( pCube, Var1, 3 );
//printf( "\n" );
//Min_CubeWrite( stdout, pCube );
//Min_CubeWrite( stdout, pThis );
// check if this cube is contained
fCont1 = Min_CoverContainsCube( p, pCube );
// undo the change
Min_CubeXorVar( pCube, Var1, 3 );
// check if the cubes can be overwritten
if ( fCont0 && fCont1 )
{
// one of the cubes can be recycled, the other expanded and added
Min_CubeRecycle( p, pThis );
// remove the literals
Min_CubeXorVar( pCube, Var0, v00 ^ 3 );
Min_CubeXorVar( pCube, Var1, v01 ^ 3 );
pCube->nLits -= 2;
Min_SopAddCube( p, pCube );
}
else if ( fCont0 )
{
// expand both cubes and add them
Min_CubeXorVar( pCube, Var0, v00 ^ 3 );
pCube->nLits--;
Min_SopAddCube( p, pCube );
Min_CubeXorVar( pThis, Var1, v11 ^ 3 );
pThis->nLits--;
Min_SopAddCube( p, pThis );
}
else if ( fCont1 )
{
// expand both cubes and add them
Min_CubeXorVar( pCube, Var1, v01 ^ 3 );
pCube->nLits--;
Min_SopAddCube( p, pCube );
Min_CubeXorVar( pThis, Var0, v10 ^ 3 );
pThis->nLits--;
Min_SopAddCube( p, pThis );
}
else
{
Min_SopAddCube( p, pCube );
Min_SopAddCube( p, pThis );
}
// otherwise, no change is possible
continue;
}
// if one of them does not have DC lit, move it
if ( v00 != 3 && v01 != 3 )
{
assert( v10 == 3 || v11 == 3 );
pTemp = pCube; pCube = pThis; pThis = pTemp;
Index = v00; v00 = v10; v10 = Index;
Index = v01; v01 = v11; v11 = Index;
}
// make sure the first cube has first var DC
if ( v00 != 3 )
{
assert( v01 == 3 );
Index = Var0; Var0 = Var1; Var1 = Index;
Index = v00; v00 = v01; v01 = Index;
Index = v10; v10 = v11; v11 = Index;
}
// consider both cases: both have DC lit
if ( v00 == 3 && v11 == 3 )
{
assert( v01 != 3 && v10 != 3 );
// try the remaining minterm
// create the temporary cube equal to the first corner
Min_CubeXorVar( pCube, Var0, v10 );
Min_CubeXorVar( pCube, Var1, 3 );
pCube->nLits++;
// check if this cube is contained
fCont0 = Min_CoverContainsCube( p, pCube );
// undo the cube transformations
Min_CubeXorVar( pCube, Var0, v10 );
Min_CubeXorVar( pCube, Var1, 3 );
pCube->nLits--;
// check the case when both are covered
if ( fCont0 )
{
// one of the cubes can be recycled, the other expanded and added
Min_CubeRecycle( p, pThis );
// remove the literals
Min_CubeXorVar( pCube, Var1, v01 ^ 3 );
pCube->nLits--;
Min_SopAddCube( p, pCube );
}
else
{
// try two reduced cubes
Min_CubeXorVar( pCube, Var0, v10 );
pCube->nLits++;
// remember the cubes
nCubesOld = p->nCubes;
Min_SopAddCube( p, pCube );
// check if the cube is absorbed
if ( p->nCubes < nCubesOld + 1 )
{ // absorbed - add the second cube
Min_SopAddCube( p, pThis );
}
else
{ // remove this cube, and try another one
assert( pCube == p->ppStore[pCube->nLits] );
p->ppStore[pCube->nLits] = pCube->pNext;
p->nCubes--;
// return the cube to the previous state
Min_CubeXorVar( pCube, Var0, v10 );
pCube->nLits--;
// generate another reduced cube
Min_CubeXorVar( pThis, Var1, v01 );
pThis->nLits++;
// add both cubes
Min_SopAddCube( p, pCube );
Min_SopAddCube( p, pThis );
}
}
}
else // the first cube has DC lit
{
assert( v01 != 3 && v10 != 3 && v11 != 3 );
// try the remaining minterm
// create the temporary cube equal to the minterm
Min_CubeXorVar( pThis, Var0, 3 );
// check if this cube is contained
fCont0 = Min_CoverContainsCube( p, pThis );
// undo the cube transformations
Min_CubeXorVar( pThis, Var0, 3 );
// check the case when both are covered
if ( fCont0 )
{
// one of the cubes can be recycled, the other expanded and added
Min_CubeRecycle( p, pThis );
// remove the literals
Min_CubeXorVar( pCube, Var1, v01 ^ 3 );
pCube->nLits--;
Min_SopAddCube( p, pCube );
}
else
{
// try reshaping the cubes
// reduce the first cube
Min_CubeXorVar( pCube, Var0, v10 );
pCube->nLits++;
// expand the second cube
Min_CubeXorVar( pThis, Var1, v11 ^ 3 );
pThis->nLits--;
// add both cubes
Min_SopAddCube( p, pCube );
Min_SopAddCube( p, pThis );
}
}
}
// printf( "Pairs = %d ", nPairs );
}
/**Function*************************************************************
Synopsis [Adds cube to the SOP cover stored in the manager.]
Description [Returns 0 if the cube is added or removed. Returns 1
if the cube is glued with some other cube and has to be added again.]
SideEffects []
SeeAlso []
***********************************************************************/
int Min_SopAddCubeInt( Min_Man_t * p, Min_Cube_t * pCube )
{
Min_Cube_t * pThis, * pThis2, ** ppPrev;
int i;
// try to find the identical cube
Min_CoverForEachCube( p->ppStore[pCube->nLits], pThis )
{
if ( Min_CubesAreEqual( pCube, pThis ) )
{
Min_CubeRecycle( p, pCube );
return 0;
}
}
// try to find a containing cube
for ( i = 0; i < (int)pCube->nLits; i++ )
Min_CoverForEachCube( p->ppStore[i], pThis )
{
if ( pThis != p->pBubble && Min_CubeIsContained( pThis, pCube ) )
{
Min_CubeRecycle( p, pCube );
return 0;
}
}
// try to find distance one in the same bin
Min_CoverForEachCubePrev( p->ppStore[pCube->nLits], pThis, ppPrev )
{
if ( Min_CubesDistOne( pCube, pThis, NULL ) )
{
*ppPrev = pThis->pNext;
Min_CubesTransformOr( pCube, pThis );
pCube->nLits--;
Min_CubeRecycle( p, pThis );
p->nCubes--;
return 1;
}
}
// clean the other cubes using this one
for ( i = pCube->nLits + 1; i <= (int)pCube->nVars; i++ )
{
ppPrev = &p->ppStore[i];
Min_CoverForEachCubeSafe( p->ppStore[i], pThis, pThis2 )
{
if ( pThis != p->pBubble && Min_CubeIsContained( pCube, pThis ) )
{
*ppPrev = pThis->pNext;
Min_CubeRecycle( p, pThis );
p->nCubes--;
}
else
ppPrev = &pThis->pNext;
}
}
// add the cube
pCube->pNext = p->ppStore[pCube->nLits];
p->ppStore[pCube->nLits] = pCube;
p->nCubes++;
return 0;
}
/**Function*************************************************************
Synopsis [Adds the cube to storage.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Min_SopAddCube( Min_Man_t * p, Min_Cube_t * pCube )
{
assert( Min_CubeCheck( pCube ) );
assert( pCube != p->pBubble );
assert( (int)pCube->nLits == Min_CubeCountLits(pCube) );
while ( Min_SopAddCubeInt( p, pCube ) );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Min_SopContain( Min_Man_t * p )
{
Min_Cube_t * pCube, * pCube2, ** ppPrev;
int i, k;
for ( i = 0; i <= p->nVars; i++ )
{
Min_CoverForEachCube( p->ppStore[i], pCube )
Min_CoverForEachCubePrev( pCube->pNext, pCube2, ppPrev )
{
if ( !Min_CubesAreEqual( pCube, pCube2 ) )
continue;
*ppPrev = pCube2->pNext;
Min_CubeRecycle( p, pCube2 );
p->nCubes--;
}
for ( k = i + 1; k <= p->nVars; k++ )
Min_CoverForEachCubePrev( p->ppStore[k], pCube2, ppPrev )
{
if ( !Min_CubeIsContained( pCube, pCube2 ) )
continue;
*ppPrev = pCube2->pNext;
Min_CubeRecycle( p, pCube2 );
p->nCubes--;
}
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Min_SopDist1Merge( Min_Man_t * p )
{
Min_Cube_t * pCube, * pCube2, * pCubeNew;
int i;
for ( i = p->nVars; i >= 0; i-- )
{
Min_CoverForEachCube( p->ppStore[i], pCube )
Min_CoverForEachCube( pCube->pNext, pCube2 )
{
assert( pCube->nLits == pCube2->nLits );
if ( !Min_CubesDistOne( pCube, pCube2, NULL ) )
continue;
pCubeNew = Min_CubesXor( p, pCube, pCube2 );
assert( pCubeNew->nLits == pCube->nLits - 1 );
pCubeNew->pNext = p->ppStore[pCubeNew->nLits];
p->ppStore[pCubeNew->nLits] = pCubeNew;
p->nCubes++;
}
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Min_Cube_t * Min_SopComplement( Min_Man_t * p, Min_Cube_t * pSharp )
{
Vec_Int_t * vVars;
Min_Cube_t * pCover, * pCube, * pNext, * pReady, * pThis, ** ppPrev;
int Num, Value, i;
// get the variables
vVars = Vec_IntAlloc( 100 );
// create the tautology cube
pCover = Min_CubeAlloc( p );
// sharp it with all cubes
Min_CoverForEachCube( pSharp, pCube )
Min_CoverForEachCubePrev( pCover, pThis, ppPrev )
{
if ( Min_CubesDisjoint( pThis, pCube ) )
continue;
// remember the next pointer
pNext = pThis->pNext;
// get the variables, in which pThis is '-' while pCube is fixed
Min_CoverGetDisjVars( pThis, pCube, vVars );
// generate the disjoint cubes
pReady = pThis;
Vec_IntForEachEntryReverse( vVars, Num, i )
{
// correct the literal
Min_CubeXorVar( pReady, vVars->pArray[i], 3 );
if ( i == 0 )
break;
// create the new cube and clean this value
Value = Min_CubeGetVar( pReady, vVars->pArray[i] );
pReady = Min_CubeDup( p, pReady );
Min_CubeXorVar( pReady, vVars->pArray[i], 3 ^ Value );
// add to the cover
*ppPrev = pReady;
ppPrev = &pReady->pNext;
}
pThis = pReady;
pThis->pNext = pNext;
}
Vec_IntFree( vVars );
// perform dist-1 merge and contain
Min_CoverExpandRemoveEqual( p, pCover );
Min_SopDist1Merge( p );
Min_SopContain( p );
return Min_CoverCollect( p, p->nVars );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Min_SopCheck( Min_Man_t * p )
{
Min_Cube_t * pCube, * pThis;
int i;
pCube = Min_CubeAlloc( p );
Min_CubeXorBit( pCube, 2*0+1 );
Min_CubeXorBit( pCube, 2*1+1 );
Min_CubeXorBit( pCube, 2*2+0 );
Min_CubeXorBit( pCube, 2*3+0 );
Min_CubeXorBit( pCube, 2*4+0 );
Min_CubeXorBit( pCube, 2*5+1 );
Min_CubeXorBit( pCube, 2*6+1 );
pCube->nLits = 7;
// Min_CubeWrite( stdout, pCube );
// check that the cubes contain it
for ( i = 0; i <= p->nVars; i++ )
Min_CoverForEachCube( p->ppStore[i], pThis )
if ( pThis != p->pBubble && Min_CubeIsContained( pThis, pCube ) )
{
Min_CubeRecycle( p, pCube );
return 1;
}
Min_CubeRecycle( p, pCube );
return 0;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END