mirror of https://github.com/YosysHQ/abc.git
345 lines
11 KiB
C
345 lines
11 KiB
C
/**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
|
|
|