blob: ec4775ca461445009f8d930b5375a0a9a373b9e1 [file] [log] [blame]
/**CFile****************************************************************
FileName [kitFactor.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Computation kit.]
Synopsis [Algebraic factoring.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - Dec 6, 2006.]
Revision [$Id: kitFactor.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $]
***********************************************************************/
#include "kit.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// factoring fails if intermediate memory usage exceed this limit
#define KIT_FACTOR_MEM_LIMIT (1<<20)
static Kit_Edge_t Kit_SopFactor_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory );
static Kit_Edge_t Kit_SopFactorLF_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, Kit_Sop_t * cSimple, int nLits, Vec_Int_t * vMemory );
static Kit_Edge_t Kit_SopFactorTrivial( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits );
static Kit_Edge_t Kit_SopFactorTrivialCube( Kit_Graph_t * pFForm, unsigned uCube, int nLits );
extern int Kit_SopFactorVerify( Vec_Int_t * cSop, Kit_Graph_t * pFForm, int nVars );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Factors the cover.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Kit_Graph_t * Kit_SopFactor( Vec_Int_t * vCover, int fCompl, int nVars, Vec_Int_t * vMemory )
{
Kit_Sop_t Sop, * cSop = &Sop;
Kit_Graph_t * pFForm;
Kit_Edge_t eRoot;
// int nCubes;
// works for up to 15 variables because division procedure
// used the last bit for marking the cubes going to the remainder
assert( nVars < 16 );
// check for trivial functions
if ( Vec_IntSize(vCover) == 0 )
return Kit_GraphCreateConst0();
if ( Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover, 0) == 0 )
return Kit_GraphCreateConst1();
// prepare memory manager
// Vec_IntClear( vMemory );
Vec_IntGrow( vMemory, KIT_FACTOR_MEM_LIMIT );
// perform CST
Kit_SopCreateInverse( cSop, vCover, 2 * nVars, vMemory ); // CST
// start the factored form
pFForm = Kit_GraphCreate( nVars );
// factor the cover
eRoot = Kit_SopFactor_rec( pFForm, cSop, 2 * nVars, vMemory );
// finalize the factored form
Kit_GraphSetRoot( pFForm, eRoot );
if ( fCompl )
Kit_GraphComplement( pFForm );
// verify the factored form
// nCubes = Vec_IntSize(vCover);
// Vec_IntShrink( vCover, nCubes );
// if ( !Kit_SopFactorVerify( vCover, pFForm, nVars ) )
// printf( "Verification has failed.\n" );
return pFForm;
}
/**Function*************************************************************
Synopsis [Recursive factoring procedure.]
Description [For the pseudo-code, see Hachtel/Somenzi,
Logic synthesis and verification algorithms, Kluwer, 1996, p. 432.]
SideEffects []
SeeAlso []
***********************************************************************/
Kit_Edge_t Kit_SopFactor_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory )
{
Kit_Sop_t Div, Quo, Rem, Com;
Kit_Sop_t * cDiv = &Div, * cQuo = &Quo, * cRem = &Rem, * cCom = &Com;
Kit_Edge_t eNodeDiv, eNodeQuo, eNodeRem, eNodeAnd;
// make sure the cover contains some cubes
assert( Kit_SopCubeNum(cSop) > 0 );
// get the divisor
if ( !Kit_SopDivisor(cDiv, cSop, nLits, vMemory) )
return Kit_SopFactorTrivial( pFForm, cSop, nLits );
// divide the cover by the divisor
Kit_SopDivideInternal( cSop, cDiv, cQuo, cRem, vMemory );
// check the trivial case
assert( Kit_SopCubeNum(cQuo) > 0 );
if ( Kit_SopCubeNum(cQuo) == 1 )
return Kit_SopFactorLF_rec( pFForm, cSop, cQuo, nLits, vMemory );
// make the quotient cube ABC_FREE
Kit_SopMakeCubeFree( cQuo );
// divide the cover by the quotient
Kit_SopDivideInternal( cSop, cQuo, cDiv, cRem, vMemory );
// check the trivial case
if ( Kit_SopIsCubeFree( cDiv ) )
{
eNodeDiv = Kit_SopFactor_rec( pFForm, cDiv, nLits, vMemory );
eNodeQuo = Kit_SopFactor_rec( pFForm, cQuo, nLits, vMemory );
eNodeAnd = Kit_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo );
if ( Kit_SopCubeNum(cRem) == 0 )
return eNodeAnd;
eNodeRem = Kit_SopFactor_rec( pFForm, cRem, nLits, vMemory );
return Kit_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem );
}
// get the common cube
Kit_SopCommonCubeCover( cCom, cDiv, vMemory );
// solve the simple problem
return Kit_SopFactorLF_rec( pFForm, cSop, cCom, nLits, vMemory );
}
/**Function*************************************************************
Synopsis [Internal recursive factoring procedure for the leaf case.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Kit_Edge_t Kit_SopFactorLF_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, Kit_Sop_t * cSimple, int nLits, Vec_Int_t * vMemory )
{
Kit_Sop_t Div, Quo, Rem;
Kit_Sop_t * cDiv = &Div, * cQuo = &Quo, * cRem = &Rem;
Kit_Edge_t eNodeDiv, eNodeQuo, eNodeRem, eNodeAnd;
assert( Kit_SopCubeNum(cSimple) == 1 );
// get the most often occurring literal
Kit_SopBestLiteralCover( cDiv, cSop, Kit_SopCube(cSimple, 0), nLits, vMemory );
// divide the cover by the literal
Kit_SopDivideByCube( cSop, cDiv, cQuo, cRem, vMemory );
// get the node pointer for the literal
eNodeDiv = Kit_SopFactorTrivialCube( pFForm, Kit_SopCube(cDiv, 0), nLits );
// factor the quotient and remainder
eNodeQuo = Kit_SopFactor_rec( pFForm, cQuo, nLits, vMemory );
eNodeAnd = Kit_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo );
if ( Kit_SopCubeNum(cRem) == 0 )
return eNodeAnd;
eNodeRem = Kit_SopFactor_rec( pFForm, cRem, nLits, vMemory );
return Kit_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem );
}
/**Function*************************************************************
Synopsis [Factoring cube.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Kit_Edge_t Kit_SopFactorTrivialCube_rec( Kit_Graph_t * pFForm, unsigned uCube, int nStart, int nFinish )
{
Kit_Edge_t eNode1, eNode2;
int i, iLit = -1, nLits, nLits1, nLits2;
assert( uCube );
// count the number of literals in this interval
nLits = 0;
for ( i = nStart; i < nFinish; i++ )
if ( Kit_CubeHasLit(uCube, i) )
{
iLit = i;
nLits++;
}
assert( iLit != -1 );
// quit if there is only one literal
if ( nLits == 1 )
return Kit_EdgeCreate( iLit/2, iLit%2 ); // CST
// split the literals into two parts
nLits1 = nLits/2;
nLits2 = nLits - nLits1;
// nLits2 = nLits/2;
// nLits1 = nLits - nLits2;
// find the splitting point
nLits = 0;
for ( i = nStart; i < nFinish; i++ )
if ( Kit_CubeHasLit(uCube, i) )
{
if ( nLits == nLits1 )
break;
nLits++;
}
// recursively construct the tree for the parts
eNode1 = Kit_SopFactorTrivialCube_rec( pFForm, uCube, nStart, i );
eNode2 = Kit_SopFactorTrivialCube_rec( pFForm, uCube, i, nFinish );
return Kit_GraphAddNodeAnd( pFForm, eNode1, eNode2 );
}
/**Function*************************************************************
Synopsis [Factoring cube.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Kit_Edge_t Kit_SopFactorTrivialCube( Kit_Graph_t * pFForm, unsigned uCube, int nLits )
{
return Kit_SopFactorTrivialCube_rec( pFForm, uCube, 0, nLits );
}
/**Function*************************************************************
Synopsis [Factoring SOP.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Kit_Edge_t Kit_SopFactorTrivial_rec( Kit_Graph_t * pFForm, unsigned * pCubes, int nCubes, int nLits )
{
Kit_Edge_t eNode1, eNode2;
int nCubes1, nCubes2;
if ( nCubes == 1 )
return Kit_SopFactorTrivialCube_rec( pFForm, pCubes[0], 0, nLits );
// split the cubes into two parts
nCubes1 = nCubes/2;
nCubes2 = nCubes - nCubes1;
// nCubes2 = nCubes/2;
// nCubes1 = nCubes - nCubes2;
// recursively construct the tree for the parts
eNode1 = Kit_SopFactorTrivial_rec( pFForm, pCubes, nCubes1, nLits );
eNode2 = Kit_SopFactorTrivial_rec( pFForm, pCubes + nCubes1, nCubes2, nLits );
return Kit_GraphAddNodeOr( pFForm, eNode1, eNode2 );
}
/**Function*************************************************************
Synopsis [Factoring the cover, which has no algebraic divisors.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Kit_Edge_t Kit_SopFactorTrivial( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits )
{
return Kit_SopFactorTrivial_rec( pFForm, cSop->pCubes, cSop->nCubes, nLits );
}
/**Function*************************************************************
Synopsis [Testing procedure for the factoring code.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Kit_FactorTest( unsigned * pTruth, int nVars )
{
Vec_Int_t * vCover, * vMemory;
Kit_Graph_t * pGraph;
// unsigned uTruthRes;
int RetValue;
// derive SOP
vCover = Vec_IntAlloc( 0 );
RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 0 );
assert( RetValue == 0 );
// derive factored form
vMemory = Vec_IntAlloc( 0 );
pGraph = Kit_SopFactor( vCover, 0, nVars, vMemory );
/*
// derive truth table
assert( nVars <= 5 );
uTruthRes = Kit_GraphToTruth( pGraph );
if ( uTruthRes != pTruth[0] )
printf( "Verification failed!" );
*/
printf( "Vars = %2d. Cubes = %3d. FFNodes = %3d. FF_memory = %3d.\n",
nVars, Vec_IntSize(vCover), Kit_GraphNodeNum(pGraph), Vec_IntSize(vMemory) );
Vec_IntFree( vMemory );
Vec_IntFree( vCover );
Kit_GraphFree( pGraph );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END