blob: 05be202fe66ef6496cd69d22d7bbf5737a0e03f2 [file] [log] [blame]
/**CFile****************************************************************
FileName [ftFactor.c]
PackageName [MVSIS 2.0: Multi-valued logic synthesis system.]
Synopsis [Procedures for algebraic factoring.]
Author [MVSIS Group]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - February 1, 2003.]
Revision [$Id: ftFactor.c,v 1.3 2003/09/01 04:56:43 alanmi Exp $]
***********************************************************************/
#include "base/abc/abc.h"
#include "base/main/main.h"
#include "misc/mvc/mvc.h"
#include "dec.h"
#ifdef ABC_USE_CUDD
#include "bdd/extrab/extraBdd.h"
#endif
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover );
static Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple );
static Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover );
static Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits );
static Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr );
static int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm );
static Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Factors the cover.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Dec_Graph_t * Dec_Factor( char * pSop )
{
Mvc_Cover_t * pCover;
Dec_Graph_t * pFForm;
Dec_Edge_t eRoot;
if ( Abc_SopIsConst0(pSop) )
return Dec_GraphCreateConst0();
if ( Abc_SopIsConst1(pSop) )
return Dec_GraphCreateConst1();
// derive the cover from the SOP representation
pCover = Dec_ConvertSopToMvc( pSop );
// make sure the cover is CCS free (should be done before CST)
Mvc_CoverContain( pCover );
// check for trivial functions
assert( !Mvc_CoverIsEmpty(pCover) );
assert( !Mvc_CoverIsTautology(pCover) );
// perform CST
Mvc_CoverInverse( pCover ); // CST
// start the factored form
pFForm = Dec_GraphCreate( Abc_SopGetVarNum(pSop) );
// factor the cover
eRoot = Dec_Factor_rec( pFForm, pCover );
// finalize the factored form
Dec_GraphSetRoot( pFForm, eRoot );
// complement the factored form if SOP is complemented
if ( Abc_SopIsComplement(pSop) )
Dec_GraphComplement( pFForm );
// verify the factored form
// if ( !Dec_FactorVerify( pSop, pFForm ) )
// printf( "Verification has failed.\n" );
// Mvc_CoverInverse( pCover ); // undo CST
Mvc_CoverFree( pCover );
return pFForm;
}
/**Function*************************************************************
Synopsis [Internal recursive factoring procedure.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover )
{
Mvc_Cover_t * pDiv, * pQuo, * pRem, * pCom;
Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem;
Dec_Edge_t eNodeAnd, eNode;
// make sure the cover contains some cubes
assert( Mvc_CoverReadCubeNum(pCover) );
// get the divisor
pDiv = Mvc_CoverDivisor( pCover );
if ( pDiv == NULL )
return Dec_FactorTrivial( pFForm, pCover );
// divide the cover by the divisor
Mvc_CoverDivideInternal( pCover, pDiv, &pQuo, &pRem );
assert( Mvc_CoverReadCubeNum(pQuo) );
Mvc_CoverFree( pDiv );
Mvc_CoverFree( pRem );
// check the trivial case
if ( Mvc_CoverReadCubeNum(pQuo) == 1 )
{
eNode = Dec_FactorLF_rec( pFForm, pCover, pQuo );
Mvc_CoverFree( pQuo );
return eNode;
}
// make the quotient cube ABC_FREE
Mvc_CoverMakeCubeFree( pQuo );
// divide the cover by the quotient
Mvc_CoverDivideInternal( pCover, pQuo, &pDiv, &pRem );
// check the trivial case
if ( Mvc_CoverIsCubeFree( pDiv ) )
{
eNodeDiv = Dec_Factor_rec( pFForm, pDiv );
eNodeQuo = Dec_Factor_rec( pFForm, pQuo );
Mvc_CoverFree( pDiv );
Mvc_CoverFree( pQuo );
eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo );
if ( Mvc_CoverReadCubeNum(pRem) == 0 )
{
Mvc_CoverFree( pRem );
return eNodeAnd;
}
else
{
eNodeRem = Dec_Factor_rec( pFForm, pRem );
Mvc_CoverFree( pRem );
return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem );
}
}
// get the common cube
pCom = Mvc_CoverCommonCubeCover( pDiv );
Mvc_CoverFree( pDiv );
Mvc_CoverFree( pQuo );
Mvc_CoverFree( pRem );
// solve the simple problem
eNode = Dec_FactorLF_rec( pFForm, pCover, pCom );
Mvc_CoverFree( pCom );
return eNode;
}
/**Function*************************************************************
Synopsis [Internal recursive factoring procedure for the leaf case.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple )
{
Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec();
Vec_Int_t * vEdgeLits = pManDec->vLits;
Mvc_Cover_t * pDiv, * pQuo, * pRem;
Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem;
Dec_Edge_t eNodeAnd;
// get the most often occurring literal
pDiv = Mvc_CoverBestLiteralCover( pCover, pSimple );
// divide the cover by the literal
Mvc_CoverDivideByLiteral( pCover, pDiv, &pQuo, &pRem );
// get the node pointer for the literal
eNodeDiv = Dec_FactorTrivialCube( pFForm, pDiv, Mvc_CoverReadCubeHead(pDiv), vEdgeLits );
Mvc_CoverFree( pDiv );
// factor the quotient and remainder
eNodeQuo = Dec_Factor_rec( pFForm, pQuo );
Mvc_CoverFree( pQuo );
eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo );
if ( Mvc_CoverReadCubeNum(pRem) == 0 )
{
Mvc_CoverFree( pRem );
return eNodeAnd;
}
else
{
eNodeRem = Dec_Factor_rec( pFForm, pRem );
Mvc_CoverFree( pRem );
return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem );
}
}
/**Function*************************************************************
Synopsis [Factoring the cover, which has no algebraic divisors.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover )
{
Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec();
Vec_Int_t * vEdgeCubes = pManDec->vCubes;
Vec_Int_t * vEdgeLits = pManDec->vLits;
Dec_Edge_t eNode;
Mvc_Cube_t * pCube;
// create the factored form for each cube
Vec_IntClear( vEdgeCubes );
Mvc_CoverForEachCube( pCover, pCube )
{
eNode = Dec_FactorTrivialCube( pFForm, pCover, pCube, vEdgeLits );
Vec_IntPush( vEdgeCubes, Dec_EdgeToInt_(eNode) );
}
// balance the factored forms
return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeCubes->pArray, vEdgeCubes->nSize, 1 );
}
/**Function*************************************************************
Synopsis [Factoring the cube.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits )
{
Dec_Edge_t eNode;
int iBit, Value;
// create the factored form for each literal
Vec_IntClear( vEdgeLits );
Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
if ( Value )
{
eNode = Dec_EdgeCreate( iBit/2, iBit%2 ); // CST
Vec_IntPush( vEdgeLits, Dec_EdgeToInt_(eNode) );
}
// balance the factored forms
return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeLits->pArray, vEdgeLits->nSize, 0 );
}
/**Function*************************************************************
Synopsis [Create the well-balanced tree of nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr )
{
Dec_Edge_t eNode1, eNode2;
int nNodes1, nNodes2;
if ( nNodes == 1 )
return peNodes[0];
// split the nodes into two parts
nNodes1 = nNodes/2;
nNodes2 = nNodes - nNodes1;
// nNodes2 = nNodes/2;
// nNodes1 = nNodes - nNodes2;
// recursively construct the tree for the parts
eNode1 = Dec_FactorTrivialTree_rec( pFForm, peNodes, nNodes1, fNodeOr );
eNode2 = Dec_FactorTrivialTree_rec( pFForm, peNodes + nNodes1, nNodes2, fNodeOr );
if ( fNodeOr )
return Dec_GraphAddNodeOr( pFForm, eNode1, eNode2 );
else
return Dec_GraphAddNodeAnd( pFForm, eNode1, eNode2 );
}
/**Function*************************************************************
Synopsis [Converts SOP into MVC.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop )
{
Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec();
Mvc_Manager_t * pMem = (Mvc_Manager_t *)pManDec->pMvcMem;
Mvc_Cover_t * pMvc;
Mvc_Cube_t * pMvcCube;
char * pCube;
int nVars, Value, v;
// start the cover
nVars = Abc_SopGetVarNum(pSop);
assert( nVars > 0 );
pMvc = Mvc_CoverAlloc( pMem, nVars * 2 );
// check the logic function of the node
Abc_SopForEachCube( pSop, nVars, pCube )
{
// create and add the cube
pMvcCube = Mvc_CubeAlloc( pMvc );
Mvc_CoverAddCubeTail( pMvc, pMvcCube );
// fill in the literals
Mvc_CubeBitFill( pMvcCube );
Abc_CubeForEachVar( pCube, Value, v )
{
if ( Value == '0' )
Mvc_CubeBitRemove( pMvcCube, v * 2 + 1 );
else if ( Value == '1' )
Mvc_CubeBitRemove( pMvcCube, v * 2 );
}
}
return pMvc;
}
#ifdef ABC_USE_CUDD
/**Function*************************************************************
Synopsis [Verifies that the factoring is correct.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm )
{
extern DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, DdNode ** pbVars );
extern DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph );
DdManager * dd = (DdManager *)Abc_FrameReadManDd();
DdNode * bFunc1, * bFunc2;
int RetValue;
bFunc1 = Abc_ConvertSopToBdd( dd, pSop, NULL ); Cudd_Ref( bFunc1 );
bFunc2 = Dec_GraphDeriveBdd( dd, pFForm ); Cudd_Ref( bFunc2 );
//Extra_bddPrint( dd, bFunc1 ); printf("\n");
//Extra_bddPrint( dd, bFunc2 ); printf("\n");
RetValue = (bFunc1 == bFunc2);
if ( bFunc1 != bFunc2 )
{
int s;
Extra_bddPrint( dd, bFunc1 ); printf("\n");
Extra_bddPrint( dd, bFunc2 ); printf("\n");
s = 0;
}
Cudd_RecursiveDeref( dd, bFunc1 );
Cudd_RecursiveDeref( dd, bFunc2 );
return RetValue;
}
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END