mirror of https://github.com/YosysHQ/abc.git
575 lines
16 KiB
C
575 lines
16 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [kitSop.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Computation kit.]
|
|
|
|
Synopsis [Procedures involving SOPs.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - Dec 6, 2006.]
|
|
|
|
Revision [$Id: kitSop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "kit.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates SOP from the cube array.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Kit_SopCreate( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory )
|
|
{
|
|
unsigned uCube;
|
|
int i;
|
|
// start the cover
|
|
cResult->nCubes = 0;
|
|
cResult->pCubes = Vec_IntFetch( vMemory, Vec_IntSize(vInput) );
|
|
// add the cubes
|
|
Vec_IntForEachEntry( vInput, uCube, i )
|
|
Kit_SopPushCube( cResult, uCube );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates SOP from the cube array.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Kit_SopCreateInverse( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nLits, Vec_Int_t * vMemory )
|
|
{
|
|
unsigned uCube, uMask = 0;
|
|
int i, nCubes = Vec_IntSize(vInput);
|
|
// start the cover
|
|
cResult->nCubes = 0;
|
|
cResult->pCubes = Vec_IntFetch( vMemory, nCubes );
|
|
// add the cubes
|
|
// Vec_IntForEachEntry( vInput, uCube, i )
|
|
for ( i = 0; i < nCubes; i++ )
|
|
{
|
|
uCube = Vec_IntEntry( vInput, i );
|
|
uMask = ((uCube | (uCube >> 1)) & 0x55555555);
|
|
uMask |= (uMask << 1);
|
|
Kit_SopPushCube( cResult, uCube ^ uMask );
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Duplicates SOP.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Kit_SopDup( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory )
|
|
{
|
|
unsigned uCube;
|
|
int i;
|
|
// start the cover
|
|
cResult->nCubes = 0;
|
|
cResult->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) );
|
|
// add the cubes
|
|
Kit_SopForEachCube( cSop, uCube, i )
|
|
Kit_SopPushCube( cResult, uCube );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derives the quotient of division by literal.]
|
|
|
|
Description [Reduces the cover to be equal to the result of
|
|
division of the given cover by the literal.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Kit_SopDivideByLiteralQuo( Kit_Sop_t * cSop, int iLit )
|
|
{
|
|
unsigned uCube;
|
|
int i, k = 0;
|
|
Kit_SopForEachCube( cSop, uCube, i )
|
|
{
|
|
if ( Kit_CubeHasLit(uCube, iLit) )
|
|
Kit_SopWriteCube( cSop, Kit_CubeRemLit(uCube, iLit), k++ );
|
|
}
|
|
Kit_SopShrink( cSop, k );
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Divides cover by one cube.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Kit_SopDivideByCube( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory )
|
|
{
|
|
unsigned uCube, uDiv;
|
|
int i;
|
|
// get the only cube
|
|
assert( Kit_SopCubeNum(cDiv) == 1 );
|
|
uDiv = Kit_SopCube(cDiv, 0);
|
|
// allocate covers
|
|
vQuo->nCubes = 0;
|
|
vQuo->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) );
|
|
vRem->nCubes = 0;
|
|
vRem->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) );
|
|
// sort the cubes
|
|
Kit_SopForEachCube( cSop, uCube, i )
|
|
{
|
|
if ( Kit_CubeContains( uCube, uDiv ) )
|
|
Kit_SopPushCube( vQuo, Kit_CubeSharp(uCube, uDiv) );
|
|
else
|
|
Kit_SopPushCube( vRem, uCube );
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Divides cover by one cube.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Kit_SopDivideInternal( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory )
|
|
{
|
|
unsigned uCube, uDiv;
|
|
unsigned uCube2 = 0; // Suppress "might be used uninitialized"
|
|
unsigned uDiv2, uQuo;
|
|
int i, i2, k, k2, nCubesRem;
|
|
assert( Kit_SopCubeNum(cSop) >= Kit_SopCubeNum(cDiv) );
|
|
// consider special case
|
|
if ( Kit_SopCubeNum(cDiv) == 1 )
|
|
{
|
|
Kit_SopDivideByCube( cSop, cDiv, vQuo, vRem, vMemory );
|
|
return;
|
|
}
|
|
// allocate quotient
|
|
vQuo->nCubes = 0;
|
|
vQuo->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) / Kit_SopCubeNum(cDiv) );
|
|
// for each cube of the cover
|
|
// it either belongs to the quotient or to the remainder
|
|
Kit_SopForEachCube( cSop, uCube, i )
|
|
{
|
|
// skip taken cubes
|
|
if ( Kit_CubeIsMarked(uCube) )
|
|
continue;
|
|
// find a matching cube in the divisor
|
|
uDiv = ~0;
|
|
Kit_SopForEachCube( cDiv, uDiv, k )
|
|
if ( Kit_CubeContains( uCube, uDiv ) )
|
|
break;
|
|
// the cube is not found
|
|
if ( k == Kit_SopCubeNum(cDiv) )
|
|
continue;
|
|
// the quotient cube exists
|
|
uQuo = Kit_CubeSharp( uCube, uDiv );
|
|
// find corresponding cubes for other cubes of the divisor
|
|
uDiv2 = ~0;
|
|
Kit_SopForEachCube( cDiv, uDiv2, k2 )
|
|
{
|
|
if ( k2 == k )
|
|
continue;
|
|
// find a matching cube
|
|
Kit_SopForEachCube( cSop, uCube2, i2 )
|
|
{
|
|
// skip taken cubes
|
|
if ( Kit_CubeIsMarked(uCube2) )
|
|
continue;
|
|
// check if the cube can be used
|
|
if ( Kit_CubeContains( uCube2, uDiv2 ) && uQuo == Kit_CubeSharp( uCube2, uDiv2 ) )
|
|
break;
|
|
}
|
|
// the case when the cube is not found
|
|
if ( i2 == Kit_SopCubeNum(cSop) )
|
|
break;
|
|
}
|
|
// we did not find some cubes - continue looking at other cubes
|
|
if ( k2 != Kit_SopCubeNum(cDiv) )
|
|
continue;
|
|
// we found all cubes - add the quotient cube
|
|
Kit_SopPushCube( vQuo, uQuo );
|
|
|
|
// mark the first cube
|
|
Kit_SopWriteCube( cSop, Kit_CubeMark(uCube), i );
|
|
// mark other cubes that have this quotient
|
|
Kit_SopForEachCube( cDiv, uDiv2, k2 )
|
|
{
|
|
if ( k2 == k )
|
|
continue;
|
|
// find a matching cube
|
|
Kit_SopForEachCube( cSop, uCube2, i2 )
|
|
{
|
|
// skip taken cubes
|
|
if ( Kit_CubeIsMarked(uCube2) )
|
|
continue;
|
|
// check if the cube can be used
|
|
if ( Kit_CubeContains( uCube2, uDiv2 ) && uQuo == Kit_CubeSharp( uCube2, uDiv2 ) )
|
|
break;
|
|
}
|
|
assert( i2 < Kit_SopCubeNum(cSop) );
|
|
// the cube is found, mark it
|
|
// (later we will add all unmarked cubes to the remainder)
|
|
Kit_SopWriteCube( cSop, Kit_CubeMark(uCube2), i2 );
|
|
}
|
|
}
|
|
// determine the number of cubes in the remainder
|
|
nCubesRem = Kit_SopCubeNum(cSop) - Kit_SopCubeNum(vQuo) * Kit_SopCubeNum(cDiv);
|
|
// allocate remainder
|
|
vRem->nCubes = 0;
|
|
vRem->pCubes = Vec_IntFetch( vMemory, nCubesRem );
|
|
// finally add the remaining unmarked cubes to the remainder
|
|
// and clean the marked cubes in the cover
|
|
Kit_SopForEachCube( cSop, uCube, i )
|
|
{
|
|
if ( !Kit_CubeIsMarked(uCube) )
|
|
{
|
|
Kit_SopPushCube( vRem, uCube );
|
|
continue;
|
|
}
|
|
Kit_SopWriteCube( cSop, Kit_CubeUnmark(uCube), i );
|
|
}
|
|
assert( nCubesRem == Kit_SopCubeNum(vRem) );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the common cube.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline unsigned Kit_SopCommonCube( Kit_Sop_t * cSop )
|
|
{
|
|
unsigned uMask, uCube;
|
|
int i;
|
|
uMask = ~(unsigned)0;
|
|
Kit_SopForEachCube( cSop, uCube, i )
|
|
uMask &= uCube;
|
|
return uMask;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Makes the cover cube-free.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Kit_SopMakeCubeFree( Kit_Sop_t * cSop )
|
|
{
|
|
unsigned uMask, uCube;
|
|
int i;
|
|
uMask = Kit_SopCommonCube( cSop );
|
|
if ( uMask == 0 )
|
|
return;
|
|
// remove the common cube
|
|
Kit_SopForEachCube( cSop, uCube, i )
|
|
Kit_SopWriteCube( cSop, Kit_CubeSharp(uCube, uMask), i );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Checks if the cover is cube-free.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Kit_SopIsCubeFree( Kit_Sop_t * cSop )
|
|
{
|
|
return Kit_SopCommonCube( cSop ) == 0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates SOP composes of the common cube of the given SOP.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Kit_SopCommonCubeCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory )
|
|
{
|
|
assert( Kit_SopCubeNum(cSop) > 0 );
|
|
cResult->nCubes = 0;
|
|
cResult->pCubes = Vec_IntFetch( vMemory, 1 );
|
|
Kit_SopPushCube( cResult, Kit_SopCommonCube(cSop) );
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Find any literal that occurs more than once.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Kit_SopAnyLiteral( Kit_Sop_t * cSop, int nLits )
|
|
{
|
|
unsigned uCube;
|
|
int i, k, nLitsCur;
|
|
// go through each literal
|
|
for ( i = 0; i < nLits; i++ )
|
|
{
|
|
// go through all the cubes
|
|
nLitsCur = 0;
|
|
Kit_SopForEachCube( cSop, uCube, k )
|
|
if ( Kit_CubeHasLit(uCube, i) )
|
|
nLitsCur++;
|
|
if ( nLitsCur > 1 )
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Find the least often occurring literal.]
|
|
|
|
Description [Find the least often occurring literal among those
|
|
that occur more than once.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Kit_SopWorstLiteral( Kit_Sop_t * cSop, int nLits )
|
|
{
|
|
unsigned uCube;
|
|
int i, k, iMin, nLitsMin, nLitsCur;
|
|
int fUseFirst = 1;
|
|
|
|
// go through each literal
|
|
iMin = -1;
|
|
nLitsMin = 1000000;
|
|
for ( i = 0; i < nLits; i++ )
|
|
{
|
|
// go through all the cubes
|
|
nLitsCur = 0;
|
|
Kit_SopForEachCube( cSop, uCube, k )
|
|
if ( Kit_CubeHasLit(uCube, i) )
|
|
nLitsCur++;
|
|
// skip the literal that does not occur or occurs once
|
|
if ( nLitsCur < 2 )
|
|
continue;
|
|
// check if this is the best literal
|
|
if ( fUseFirst )
|
|
{
|
|
if ( nLitsMin > nLitsCur )
|
|
{
|
|
nLitsMin = nLitsCur;
|
|
iMin = i;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( nLitsMin >= nLitsCur )
|
|
{
|
|
nLitsMin = nLitsCur;
|
|
iMin = i;
|
|
}
|
|
}
|
|
}
|
|
if ( nLitsMin < 1000000 )
|
|
return iMin;
|
|
return -1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Find the least often occurring literal.]
|
|
|
|
Description [Find the least often occurring literal among those
|
|
that occur more than once.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Kit_SopBestLiteral( Kit_Sop_t * cSop, int nLits, unsigned uMask )
|
|
{
|
|
unsigned uCube;
|
|
int i, k, iMax, nLitsMax, nLitsCur;
|
|
int fUseFirst = 1;
|
|
|
|
// go through each literal
|
|
iMax = -1;
|
|
nLitsMax = -1;
|
|
for ( i = 0; i < nLits; i++ )
|
|
{
|
|
if ( !Kit_CubeHasLit(uMask, i) )
|
|
continue;
|
|
// go through all the cubes
|
|
nLitsCur = 0;
|
|
Kit_SopForEachCube( cSop, uCube, k )
|
|
if ( Kit_CubeHasLit(uCube, i) )
|
|
nLitsCur++;
|
|
// skip the literal that does not occur or occurs once
|
|
if ( nLitsCur < 2 )
|
|
continue;
|
|
// check if this is the best literal
|
|
if ( fUseFirst )
|
|
{
|
|
if ( nLitsMax < nLitsCur )
|
|
{
|
|
nLitsMax = nLitsCur;
|
|
iMax = i;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( nLitsMax <= nLitsCur )
|
|
{
|
|
nLitsMax = nLitsCur;
|
|
iMax = i;
|
|
}
|
|
}
|
|
}
|
|
if ( nLitsMax >= 0 )
|
|
return iMax;
|
|
return -1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes a level-zero kernel.]
|
|
|
|
Description [Modifies the cover to contain one level-zero kernel.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Kit_SopDivisorZeroKernel_rec( Kit_Sop_t * cSop, int nLits )
|
|
{
|
|
int iLit;
|
|
// find any literal that occurs at least two times
|
|
iLit = Kit_SopWorstLiteral( cSop, nLits );
|
|
if ( iLit == -1 )
|
|
return;
|
|
// derive the cube-free quotient
|
|
Kit_SopDivideByLiteralQuo( cSop, iLit ); // the same cover
|
|
Kit_SopMakeCubeFree( cSop ); // the same cover
|
|
// call recursively
|
|
Kit_SopDivisorZeroKernel_rec( cSop, nLits ); // the same cover
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes the quick divisor of the cover.]
|
|
|
|
Description [Returns 0, if there is no divisor other than trivial.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Kit_SopDivisor( Kit_Sop_t * cResult, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory )
|
|
{
|
|
if ( Kit_SopCubeNum(cSop) <= 1 )
|
|
return 0;
|
|
if ( Kit_SopAnyLiteral( cSop, nLits ) == -1 )
|
|
return 0;
|
|
// duplicate the cover
|
|
Kit_SopDup( cResult, cSop, vMemory );
|
|
// perform the kerneling
|
|
Kit_SopDivisorZeroKernel_rec( cResult, nLits );
|
|
assert( Kit_SopCubeNum(cResult) > 0 );
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Create the one-literal cover with the best literal from cSop.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Kit_SopBestLiteralCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, unsigned uCube, int nLits, Vec_Int_t * vMemory )
|
|
{
|
|
int iLitBest;
|
|
// get the best literal
|
|
iLitBest = Kit_SopBestLiteral( cSop, nLits, uCube );
|
|
// start the cover
|
|
cResult->nCubes = 0;
|
|
cResult->pCubes = Vec_IntFetch( vMemory, 1 );
|
|
// set the cube
|
|
Kit_SopPushCube( cResult, Kit_CubeSetLit(0, iLitBest) );
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|