diff options
Diffstat (limited to 'src/bdd/dsd')
-rw-r--r-- | src/bdd/dsd/dsd.h | 129 | ||||
-rw-r--r-- | src/bdd/dsd/dsdApi.c | 97 | ||||
-rw-r--r-- | src/bdd/dsd/dsdCheck.c | 314 | ||||
-rw-r--r-- | src/bdd/dsd/dsdInt.h | 91 | ||||
-rw-r--r-- | src/bdd/dsd/dsdLocal.c | 337 | ||||
-rw-r--r-- | src/bdd/dsd/dsdMan.c | 114 | ||||
-rw-r--r-- | src/bdd/dsd/dsdProc.c | 1617 | ||||
-rw-r--r-- | src/bdd/dsd/dsdTree.c | 1068 | ||||
-rw-r--r-- | src/bdd/dsd/module.make | 6 |
9 files changed, 0 insertions, 3773 deletions
diff --git a/src/bdd/dsd/dsd.h b/src/bdd/dsd/dsd.h deleted file mode 100644 index b73b81ab..00000000 --- a/src/bdd/dsd/dsd.h +++ /dev/null @@ -1,129 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsd.h] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [External declarations of the package. - This fast BDD-based recursive algorithm for simple - (single-output) DSD is based on the following papers: - (1) V. Bertacco and M. Damiani, "Disjunctive decomposition of - logic functions," Proc. ICCAD '97, pp. 78-82. - (2) Y. Matsunaga, "An exact and efficient algorithm for disjunctive - decomposition", Proc. SASIMI '98, pp. 44-50. - The scope of detected decompositions is the same as in the paper: - T. Sasao and M. Matsuura, "DECOMPOS: An integrated system for - functional decomposition," Proc. IWLS '98, pp. 471-477.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsd.h,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DSD_H__ -#define __DSD_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// TYPEDEF DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Dsd_Manager_t_ Dsd_Manager_t; -typedef struct Dsd_Node_t_ Dsd_Node_t; -typedef enum Dsd_Type_t_ Dsd_Type_t; - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -// types of DSD nodes -enum Dsd_Type_t_ { - DSD_NODE_NONE = 0, - DSD_NODE_CONST1 = 1, - DSD_NODE_BUF = 2, - DSD_NODE_OR = 3, - DSD_NODE_EXOR = 4, - DSD_NODE_PRIME = 5, -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// complementation and testing for pointers for decomposition entries -#define Dsd_IsComplement(p) (((int)((unsigned long) (p) & 01))) -#define Dsd_Regular(p) ((Dsd_Node_t *)((unsigned long)(p) & ~01)) -#define Dsd_Not(p) ((Dsd_Node_t *)((unsigned long)(p) ^ 01)) -#define Dsd_NotCond(p,c) ((Dsd_Node_t *)((unsigned long)(p) ^ (c))) - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator through the transitions -#define Dsd_NodeForEachChild( Node, Index, Child ) \ - for ( Index = 0; \ - Index < Dsd_NodeReadDecsNum(Node) && \ - ((Child = Dsd_NodeReadDec(Node,Index))>=0); \ - Index++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== dsdApi.c =======================================================*/ -extern Dsd_Type_t Dsd_NodeReadType( Dsd_Node_t * p ); -extern DdNode * Dsd_NodeReadFunc( Dsd_Node_t * p ); -extern DdNode * Dsd_NodeReadSupp( Dsd_Node_t * p ); -extern Dsd_Node_t ** Dsd_NodeReadDecs( Dsd_Node_t * p ); -extern Dsd_Node_t * Dsd_NodeReadDec ( Dsd_Node_t * p, int i ); -extern int Dsd_NodeReadDecsNum( Dsd_Node_t * p ); -extern int Dsd_NodeReadMark( Dsd_Node_t * p ); -extern void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ); -extern DdManager * Dsd_ManagerReadDd( Dsd_Manager_t * pMan ); -extern Dsd_Node_t * Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i ); -extern Dsd_Node_t * Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i ); -extern Dsd_Node_t * Dsd_ManagerReadConst1( Dsd_Manager_t * pMan ); -/*=== dsdMan.c =======================================================*/ -extern Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose ); -extern void Dsd_ManagerStop( Dsd_Manager_t * dMan ); -/*=== dsdProc.c =======================================================*/ -extern void Dsd_Decompose( Dsd_Manager_t * dMan, DdNode ** pbFuncs, int nFuncs ); -extern Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc ); -/*=== dsdTree.c =======================================================*/ -extern void Dsd_TreeNodeGetInfo( Dsd_Manager_t * dMan, int * DepthMax, int * GateSizeMax ); -extern void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax ); -extern int Dsd_TreeGetAigCost( Dsd_Node_t * pNode ); -extern int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * dMan ); -extern int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot ); -extern int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan ); -extern int Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot ); -extern int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * dMan, int * pVars ); -extern Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * dMan, int * pnNodes ); -extern Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes ); -extern void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * dMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output ); -extern void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode ); -/*=== dsdLocal.c =======================================================*/ -extern DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdApi.c b/src/bdd/dsd/dsdApi.c deleted file mode 100644 index d1c90e23..00000000 --- a/src/bdd/dsd/dsdApi.c +++ /dev/null @@ -1,97 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdApi.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Implementation of API functions.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdApi.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [APIs of the DSD node.] - - Description [The node's type can be retrieved by calling - Dsd_NodeReadType(). The type is one of the following: constant 1 node, - the buffer (or the elementary variable), OR gate, EXOR gate, or - PRIME function (a non-DSD-decomposable function with more than two - inputs). The return value of Dsd_NodeReadFunc() is the global function - of the DSD node. The return value of Dsd_NodeReadSupp() is the support - of the global function of the DSD node. The array of DSD nodes - returned by Dsd_NodeReadDecs() is the array of decomposition nodes for - the formal inputs of the given node. The number of decomposition entries - returned by Dsd_NodeReadDecsNum() is the number of formal inputs. - The mark is explained below.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Type_t Dsd_NodeReadType( Dsd_Node_t * p ) { return p->Type; } -DdNode * Dsd_NodeReadFunc( Dsd_Node_t * p ) { return p->G; } -DdNode * Dsd_NodeReadSupp( Dsd_Node_t * p ) { return p->S; } -Dsd_Node_t ** Dsd_NodeReadDecs( Dsd_Node_t * p ) { return p->pDecs; } -Dsd_Node_t * Dsd_NodeReadDec ( Dsd_Node_t * p, int i ) { return p->pDecs[i]; } -int Dsd_NodeReadDecsNum( Dsd_Node_t * p ) { return p->nDecs; } -int Dsd_NodeReadMark( Dsd_Node_t * p ) { return p->Mark; } - -/**Function************************************************************* - - Synopsis [APIs of the DSD node.] - - Description [This API allows the user to set the integer mark in the - given DSD node. The mark is guaranteed to persist as long as the - calls to the decomposition are not performed. In any case, the mark - is useful to associate the node with some temporary information, such - as its number in the DFS ordered list of the DSD nodes or its number in - the BLIF file that it being written.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ){ p->Mark = Mark; } - -/**Function************************************************************* - - Synopsis [APIs of the DSD manager.] - - Description [Allows the use to get hold of an individual leave of - the DSD tree (Dsd_ManagerReadInput) or an individual root of the - decomposition tree (Dsd_ManagerReadRoot). The root may have the - complemented attribute.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i ) { return pMan->pRoots[i]; } -Dsd_Node_t * Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i ) { return pMan->pInputs[i]; } -Dsd_Node_t * Dsd_ManagerReadConst1( Dsd_Manager_t * pMan ) { return pMan->pConst1; } -DdManager * Dsd_ManagerReadDd( Dsd_Manager_t * pMan ) { return pMan->dd; } - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdCheck.c b/src/bdd/dsd/dsdCheck.c deleted file mode 100644 index 58b824d2..00000000 --- a/src/bdd/dsd/dsdCheck.c +++ /dev/null @@ -1,314 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdCheck.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Procedures to check the identity of root functions.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdCheck.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Dsd_Cache_t_ Dds_Cache_t; -typedef struct Dsd_Entry_t_ Dsd_Entry_t; - -struct Dsd_Cache_t_ -{ - Dsd_Entry_t * pTable; - int nTableSize; - int nSuccess; - int nFailure; -}; - -struct Dsd_Entry_t_ -{ - DdNode * bX[5]; -}; - -static Dds_Cache_t * pCache; - -static int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function******************************************************************** - - Synopsis [(Re)allocates the local cache.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Dsd_CheckCacheAllocate( int nEntries ) -{ - int nRequested; - - pCache = ALLOC( Dds_Cache_t, 1 ); - memset( pCache, 0, sizeof(Dds_Cache_t) ); - - // check what is the size of the current cache - nRequested = Cudd_Prime( nEntries ); - if ( pCache->nTableSize != nRequested ) - { // the current size is different - // deallocate the old, allocate the new - if ( pCache->nTableSize ) - Dsd_CheckCacheDeallocate(); - // allocate memory for the hash table - pCache->nTableSize = nRequested; - pCache->pTable = ALLOC( Dsd_Entry_t, nRequested ); - } - // otherwise, there is no need to allocate, just clean - Dsd_CheckCacheClear(); -// printf( "\nThe number of allocated cache entries = %d.\n\n", pCache->nTableSize ); -} - -/**Function******************************************************************** - - Synopsis [Deallocates the local cache.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Dsd_CheckCacheDeallocate() -{ - free( pCache->pTable ); - free( pCache ); -} - -/**Function******************************************************************** - - Synopsis [Clears the local cache.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Dsd_CheckCacheClear() -{ - int i; - for ( i = 0; i < pCache->nTableSize; i++ ) - pCache->pTable[0].bX[0] = NULL; -} - - -/**Function******************************************************************** - - Synopsis [Checks whether it is true that bF1(bC1=0) == bF2(bC2=0).] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ) -{ - int RetValue; -// pCache->nSuccess = 0; -// pCache->nFailure = 0; - RetValue = Dsd_CheckRootFunctionIdentity_rec(dd, bF1, bF2, bC1, bC2); -// printf( "Cache success = %d. Cache failure = %d.\n", pCache->nSuccess, pCache->nFailure ); - return RetValue; -} - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Dsd_CheckRootFunctionIdentity().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ) -{ - unsigned HKey; - - // if either bC1 or bC2 is zero, the test is true -// if ( bC1 == b0 || bC2 == b0 ) return 1; - assert( bC1 != b0 ); - assert( bC2 != b0 ); - - // if both bC1 and bC2 are one - perform comparison - if ( bC1 == b1 && bC2 == b1 ) return (int)( bF1 == bF2 ); - - if ( bF1 == b0 ) - return Cudd_bddLeq( dd, bC2, Cudd_Not(bF2) ); - - if ( bF1 == b1 ) - return Cudd_bddLeq( dd, bC2, bF2 ); - - if ( bF2 == b0 ) - return Cudd_bddLeq( dd, bC1, Cudd_Not(bF1) ); - - if ( bF2 == b1 ) - return Cudd_bddLeq( dd, bC1, bF1 ); - - // otherwise, keep expanding - - // check cache -// HKey = _Hash( ((unsigned)bF1), ((unsigned)bF2), ((unsigned)bC1), ((unsigned)bC2) ); - HKey = hashKey4( bF1, bF2, bC1, bC2, pCache->nTableSize ); - if ( pCache->pTable[HKey].bX[0] == bF1 && - pCache->pTable[HKey].bX[1] == bF2 && - pCache->pTable[HKey].bX[2] == bC1 && - pCache->pTable[HKey].bX[3] == bC2 ) - { - pCache->nSuccess++; - return (int)pCache->pTable[HKey].bX[4]; // the last bit records the result (yes/no) - } - else - { - - // determine the top variables - int RetValue; - DdNode * bA[4] = { bF1, bF2, bC1, bC2 }; // arguments - DdNode * bAR[4] = { Cudd_Regular(bF1), Cudd_Regular(bF2), Cudd_Regular(bC1), Cudd_Regular(bC2) }; // regular arguments - int CurLevel[4] = { cuddI(dd,bAR[0]->index), cuddI(dd,bAR[1]->index), cuddI(dd,bAR[2]->index), cuddI(dd,bAR[3]->index) }; - int TopLevel = CUDD_CONST_INDEX; - int i; - DdNode * bE[4], * bT[4]; - DdNode * bF1next, * bF2next, * bC1next, * bC2next; - - pCache->nFailure++; - - // determine the top level - for ( i = 0; i < 4; i++ ) - if ( TopLevel > CurLevel[i] ) - TopLevel = CurLevel[i]; - - // compute the cofactors - for ( i = 0; i < 4; i++ ) - if ( TopLevel == CurLevel[i] ) - { - if ( bA[i] != bAR[i] ) // complemented - { - bE[i] = Cudd_Not(cuddE(bAR[i])); - bT[i] = Cudd_Not(cuddT(bAR[i])); - } - else - { - bE[i] = cuddE(bAR[i]); - bT[i] = cuddT(bAR[i]); - } - } - else - bE[i] = bT[i] = bA[i]; - - // solve subproblems - // three cases are possible - - // (1) the top var belongs to both C1 and C2 - // in this case, any cofactor of F1 and F2 will do, - // as long as the corresponding cofactor of C1 and C2 is not equal to 0 - if ( TopLevel == CurLevel[2] && TopLevel == CurLevel[3] ) - { - if ( bE[2] != b0 ) // C1 - { - bF1next = bE[0]; - bC1next = bE[2]; - } - else - { - bF1next = bT[0]; - bC1next = bT[2]; - } - if ( bE[3] != b0 ) // C2 - { - bF2next = bE[1]; - bC2next = bE[3]; - } - else - { - bF2next = bT[1]; - bC2next = bT[3]; - } - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bF2next, bC1next, bC2next ); - } - // (2) the top var belongs to either C1 or C2 - // in this case normal splitting of cofactors - else if ( TopLevel == CurLevel[2] && TopLevel != CurLevel[3] ) - { - if ( bE[2] != b0 ) // C1 - { - bF1next = bE[0]; - bC1next = bE[2]; - } - else - { - bF1next = bT[0]; - bC1next = bT[2]; - } - // split around this variable - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bE[1], bC1next, bE[3] ); - if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bT[1], bC1next, bT[3] ); - } - else if ( TopLevel != CurLevel[2] && TopLevel == CurLevel[3] ) - { - if ( bE[3] != b0 ) // C2 - { - bF2next = bE[1]; - bC2next = bE[3]; - } - else - { - bF2next = bT[1]; - bC2next = bT[3]; - } - // split around this variable - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bF2next, bE[2], bC2next ); - if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bF2next, bT[2], bC2next ); - } - // (3) the top var does not belong to C1 and C2 - // in this case normal splitting of cofactors - else // if ( TopLevel != CurLevel[2] && TopLevel != CurLevel[3] ) - { - // split around this variable - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bE[1], bE[2], bE[3] ); - if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bT[1], bT[2], bT[3] ); - } - - // set cache - for ( i = 0; i < 4; i++ ) - pCache->pTable[HKey].bX[i] = bA[i]; - pCache->pTable[HKey].bX[4] = (DdNode*)RetValue; - - return RetValue; - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/dsd/dsdInt.h b/src/bdd/dsd/dsdInt.h deleted file mode 100644 index 62ce7e99..00000000 --- a/src/bdd/dsd/dsdInt.h +++ /dev/null @@ -1,91 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdInt.h] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Internal declarations of the package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdInt.h,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DSD_INT_H__ -#define __DSD_INT_H__ - -#include "extra.h" -#include "dsd.h" - -//////////////////////////////////////////////////////////////////////// -/// TYPEDEF DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef unsigned char byte; - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// DSD manager -struct Dsd_Manager_t_ -{ - DdManager * dd; // the BDD manager - st_table * Table; // the mapping of BDDs into their DEs - int nInputs; // the number of primary inputs - int nRoots; // the number of primary outputs - int nRootsAlloc;// the number of primary outputs - Dsd_Node_t ** pInputs; // the primary input nodes - Dsd_Node_t ** pRoots; // the primary output nodes - Dsd_Node_t * pConst1; // the constant node - int fVerbose; // the verbosity level -}; - -// DSD node -struct Dsd_Node_t_ -{ - Dsd_Type_t Type; // decomposition type - DdNode * G; // function of the node - DdNode * S; // support of this function - Dsd_Node_t ** pDecs; // pointer to structures for formal inputs - int Mark; // the mark used by CASE 4 of disjoint decomposition - short nDecs; // the number of formal inputs - short nVisits; // the counter of visits -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define MAXINPUTS 1000 - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== dsdCheck.c =======================================================*/ -extern void Dsd_CheckCacheAllocate( int nEntries ); -extern void Dsd_CheckCacheDeallocate(); -extern void Dsd_CheckCacheClear(); -extern int Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ); -/*=== dsdTree.c =======================================================*/ -extern Dsd_Node_t * Dsd_TreeNodeCreate( int Type, int nDecs, int BlockNum ); -extern void Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode ); -extern void Dsd_TreeUnmark( Dsd_Manager_t * dMan ); -extern DdNode * Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/dsd/dsdLocal.c b/src/bdd/dsd/dsdLocal.c deleted file mode 100644 index 6dd6e7d1..00000000 --- a/src/bdd/dsd/dsdLocal.c +++ /dev/null @@ -1,337 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdLocal.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Deriving the local function of the DSD node.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdLocal.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STATIC VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -static DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bFunc, st_table * pCache, - int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ); -static DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the local function of the DSD node. ] - - Description [The local function is computed using the global function - of the node and the global functions of the formal inputs. The resulting - local function is mapped using the topmost N variables of the manager. - The number of variables N is equal to the number of formal inputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ) -{ - int * pForm2Var; // the mapping of each formal input into its first var - int * pVar2Form; // the mapping of each var into its formal inputs - int i, iVar, iLev, * pPermute; - DdNode ** pbCube0, ** pbCube1; - DdNode * bFunc, * bRes, * bTemp; - st_table * pCache; - - pPermute = ALLOC( int, dd->size ); - pVar2Form = ALLOC( int, dd->size ); - pForm2Var = ALLOC( int, dd->size ); - - pbCube0 = ALLOC( DdNode *, dd->size ); - pbCube1 = ALLOC( DdNode *, dd->size ); - - // remap the global function in such a way that - // the support variables of each formal input are adjacent - iLev = 0; - for ( i = 0; i < pNode->nDecs; i++ ) - { - pForm2Var[i] = dd->invperm[i]; - for ( bTemp = pNode->pDecs[i]->S; bTemp != b1; bTemp = cuddT(bTemp) ) - { - iVar = dd->invperm[iLev]; - pPermute[bTemp->index] = iVar; - pVar2Form[iVar] = i; - iLev++; - } - - // collect the cubes representing each assignment - pbCube0[i] = Extra_bddGetOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); - Cudd_Ref( pbCube0[i] ); - pbCube1[i] = Extra_bddGetOneCube( dd, pNode->pDecs[i]->G ); - Cudd_Ref( pbCube1[i] ); - } - - // remap the function - bFunc = Cudd_bddPermute( dd, pNode->G, pPermute ); Cudd_Ref( bFunc ); - // remap the cube - for ( i = 0; i < pNode->nDecs; i++ ) - { - pbCube0[i] = Cudd_bddPermute( dd, bTemp = pbCube0[i], pPermute ); Cudd_Ref( pbCube0[i] ); - Cudd_RecursiveDeref( dd, bTemp ); - pbCube1[i] = Cudd_bddPermute( dd, bTemp = pbCube1[i], pPermute ); Cudd_Ref( pbCube1[i] ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - // remap the function - pCache = st_init_table(st_ptrcmp,st_ptrhash); - bRes = Extra_dsdRemap( dd, bFunc, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes ); - st_free_table( pCache ); - - Cudd_RecursiveDeref( dd, bFunc ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - Cudd_RecursiveDeref( dd, pbCube0[i] ); - Cudd_RecursiveDeref( dd, pbCube1[i] ); - } -/* -//////////// - // permute the function once again - // in such a way that i-th var stood for i-th formal input - for ( i = 0; i < dd->size; i++ ) - pPermute[i] = -1; - for ( i = 0; i < pNode->nDecs; i++ ) - pPermute[dd->invperm[i]] = i; - bRes = Cudd_bddPermute( dd, bTemp = bRes, pPermute ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); -//////////// -*/ - FREE(pPermute); - FREE(pVar2Form); - FREE(pForm2Var); - FREE(pbCube0); - FREE(pbCube1); - - Cudd_Deref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bF, st_table * pCache, - int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ) -{ - DdNode * bFR, * bF0, * bF1; - DdNode * bRes0, * bRes1, * bRes; - int iForm; - - bFR = Cudd_Regular(bF); - if ( cuddIsConstant(bFR) ) - return bF; - - // check the hash-table - if ( bFR->ref != 1 ) - { - if ( st_lookup( pCache, (char *)bF, (char **)&bRes ) ) - return bRes; - } - - // get the formal input - iForm = pVar2Form[bFR->index]; - - // get the nodes pointed to by the cube - bF0 = Extra_bddNodePointedByCube( dd, bF, pbCube0[iForm] ); - bF1 = Extra_bddNodePointedByCube( dd, bF, pbCube1[iForm] ); - - // call recursively for these nodes - bRes0 = Extra_dsdRemap( dd, bF0, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes0 ); - bRes1 = Extra_dsdRemap( dd, bF1, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes1 ); - - // derive the result using ITE - bRes = Cudd_bddIte( dd, dd->vars[ pForm2Var[iForm] ], bRes1, bRes0 ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bRes1 ); - - // add to the hash table - if ( bFR->ref != 1 ) - st_insert( pCache, (char *)bF, (char *)bRes ); - Cudd_Deref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC ) -{ - DdNode * bFR, * bCR; - DdNode * bF0, * bF1; - DdNode * bC0, * bC1; - int LevelF, LevelC; - - assert( bC != b0 ); - if ( bC == b1 ) - return bF; - -// bRes = cuddCacheLookup2( dd, Extra_bddNodePointedByCube, bF, bC ); -// if ( bRes ) -// return bRes; - // there is no need for caching because this operation is very fast - // there will no gain reusing the results of this operations - // instead, it will flush CUDD cache of other useful entries - - - bFR = Cudd_Regular( bF ); - bCR = Cudd_Regular( bC ); - assert( !cuddIsConstant( bFR ) ); - - LevelF = dd->perm[bFR->index]; - LevelC = dd->perm[bCR->index]; - - if ( LevelF <= LevelC ) - { - if ( bFR != bF ) - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - } - else - { - bF0 = bF1 = bF; - } - - if ( LevelC <= LevelF ) - { - if ( bCR != bC ) - { - bC0 = Cudd_Not( cuddE(bCR) ); - bC1 = Cudd_Not( cuddT(bCR) ); - } - else - { - bC0 = cuddE(bCR); - bC1 = cuddT(bCR); - } - } - else - { - bC0 = bC1 = bC; - } - - assert( bC0 == b0 || bC1 == b0 ); - if ( bC0 == b0 ) - return Extra_bddNodePointedByCube( dd, bF1, bC1 ); - return Extra_bddNodePointedByCube( dd, bF0, bC0 ); -} - -#if 0 - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * dsdTreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) -{ - DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; - int i; - int fAllBuffs = 1; - static int Permute[MAXINPUTS]; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->Type == DT_PRIME ); - - // transform the function of this block to depend on inputs - // corresponding to the formal inputs - - // first, substitute those inputs that have some blocks associated with them - // second, remap the inputs to the top of the manager (then, it is easy to output them) - - // start the function - bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); - // go over all primary inputs - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pNode->pDecs[i]->Type != DT_BUF ) // remap only if it is not the buffer - { - bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); - bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); - Cudd_RecursiveDeref( dd, bCube0 ); - - bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); - bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); - Cudd_RecursiveDeref( dd, bCube1 ); - - Cudd_RecursiveDeref( dd, bNewFunc ); - - // use the variable in the i-th level of the manager -// bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); - // use the first variale in the support of the component - bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); - Cudd_RecursiveDeref( dd, bCof0 ); - Cudd_RecursiveDeref( dd, bCof1 ); - } - - if ( fRemap ) - { - // remap the function to the top of the manager - // remap the function to the first variables of the manager - for ( i = 0; i < pNode->nDecs; i++ ) - // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; - Permute[ pNode->pDecs[i]->S->index ] = i; - - bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - Cudd_Deref( bNewFunc ); - return bNewFunc; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdMan.c b/src/bdd/dsd/dsdMan.c deleted file mode 100644 index 6e43f0f4..00000000 --- a/src/bdd/dsd/dsdMan.c +++ /dev/null @@ -1,114 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdMan.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [APIs of the DSD manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdMan.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// API OF DSD MANAGER /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the DSD manager.] - - Description [Takes the started BDD manager and the maximum support size - of the function to be DSD-decomposed. The manager should have at least as - many variables as there are variables in the support. The functions should - be expressed using the first nSuppSizeMax variables in the manager (these - may be ordered not necessarily on top of the manager).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose ) -{ - Dsd_Manager_t * dMan; - Dsd_Node_t * pNode; - int i; - - assert( nSuppMax <= dd->size ); - - dMan = ALLOC( Dsd_Manager_t, 1 ); - memset( dMan, 0, sizeof(Dsd_Manager_t) ); - dMan->dd = dd; - dMan->nInputs = nSuppMax; - dMan->fVerbose = fVerbose; - dMan->nRoots = 0; - dMan->nRootsAlloc = 50; - dMan->pRoots = (Dsd_Node_t **) malloc( dMan->nRootsAlloc * sizeof(Dsd_Node_t *) ); - dMan->pInputs = (Dsd_Node_t **) malloc( dMan->nInputs * sizeof(Dsd_Node_t *) ); - - // create the primary inputs and insert them into the table - dMan->Table = st_init_table(st_ptrcmp, st_ptrhash); - for ( i = 0; i < dMan->nInputs; i++ ) - { - pNode = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, 0 ); - pNode->G = dd->vars[i]; Cudd_Ref( pNode->G ); - pNode->S = dd->vars[i]; Cudd_Ref( pNode->S ); - st_insert( dMan->Table, (char*)dd->vars[i], (char*)pNode ); - dMan->pInputs[i] = pNode; - } - pNode = Dsd_TreeNodeCreate( DSD_NODE_CONST1, 0, 0 ); - pNode->G = b1; Cudd_Ref( pNode->G ); - pNode->S = b1; Cudd_Ref( pNode->S ); - st_insert( dMan->Table, (char*)b1, (char*)pNode ); - dMan->pConst1 = pNode; - - Dsd_CheckCacheAllocate( 5000 ); - return dMan; -} - -/**Function************************************************************* - - Synopsis [Stops the DSD manager.] - - Description [Stopping the DSD manager automatically derefereces and - deallocates all the DSD nodes that were created during the life time - of the DSD manager. As a result, the user does not need to deref or - deallocate any DSD nodes or trees that are derived and placed in - the manager while it exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_ManagerStop( Dsd_Manager_t * dMan ) -{ - st_generator * gen; - Dsd_Node_t * pNode; - DdNode * bFunc; - // delete the nodes - st_foreach_item( dMan->Table, gen, (char**)&bFunc, (char**)&pNode ) - Dsd_TreeNodeDelete( dMan->dd, Dsd_Regular(pNode) ); - st_free_table(dMan->Table); - free( dMan->pInputs ); - free( dMan->pRoots ); - free( dMan ); - Dsd_CheckCacheDeallocate(); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdProc.c b/src/bdd/dsd/dsdProc.c deleted file mode 100644 index 543ad387..00000000 --- a/src/bdd/dsd/dsdProc.c +++ /dev/null @@ -1,1617 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdProc.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [The core procedures of the package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdProc.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the most important procedures -void dsdKernelDecompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs ); -static Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * F ); - -// additional procedures -static Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity ); -static int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH ); -static void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor ); -static int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall ); - -// list copying -static void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize ); -static void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int Skipped ); - -// debugging procedures -static int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE ); - -//////////////////////////////////////////////////////////////////////// -/// STATIC VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -// the counter of marks -static int s_Mark; - -// debugging flag -static int s_Show = 0; -// temporary var used for debugging -static int Depth = 0; - -static int s_Loops1; -static int s_Loops2; -static int s_Loops3; -static int s_Pivot; -static int s_PivotNo; -static int s_Common; -static int s_CommonNo; - -static int s_Case4Calls; -static int s_Case4CallsSpecial; - -static int s_Case5; -static int s_Loops2Useless; - - -static int s_DecNodesTotal; -static int s_DecNodesUsed; - -// statistical variables -static int s_nDecBlocks; -static int s_nLiterals; -static int s_nExorGates; -static int s_nReusedBlocks; -static int s_nCascades; -static float s_nArea; -static float s_MaxDelay; -static long s_Time; -static int s_nInvertors; -static int s_nPrimeBlocks; - -static int HashSuccess = 0; -static int HashFailure = 0; - -static int s_CacheEntries; - - -//////////////////////////////////////////////////////////////////////// -/// DECOMPOSITION FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs DSD for the array of functions represented by BDDs.] - - Description [This function takes the DSD manager, which should be - previously allocated by the call to Dsd_ManagerStart(). The resulting - DSD tree is stored in the DSD manager (pDsdMan->pRoots, pDsdMan->nRoots). - Access to the tree is through the APIs of the manager. The resulting - tree is a shared DSD DAG for the functions given in the array. For one - function the resulting DAG is always a tree. The root node pointers can - be complemented, as discussed in the literature referred to in "dsd.h". - This procedure can be called repeatedly for different functions. There is - no need to remove the decomposition tree after it is returned, because - the next call to the DSD manager will "recycle" the tree. The user should - not modify or dereference any data associated with the nodes of the - DSD trees (the user can only change the contents of a temporary - mark associated with each node by the calling to Dsd_NodeSetMark()). - All the decomposition trees and intermediate nodes will be removed when - the DSD manager is deallocated at the end by calling Dsd_ManagerStop().] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_Decompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs ) -{ - DdManager * dd = pDsdMan->dd; - int i; - long clk; - Dsd_Node_t * pTemp; - int SumMaxGateSize = 0; - int nDecOutputs = 0; - int nCBFOutputs = 0; -/* -s_Loops1 = 0; -s_Loops2 = 0; -s_Loops3 = 0; -s_Case4Calls = 0; -s_Case4CallsSpecial = 0; -s_Case5 = 0; -s_Loops2Useless = 0; -*/ - // resize the number of roots in the manager - if ( pDsdMan->nRootsAlloc < nFuncs ) - { - if ( pDsdMan->nRootsAlloc > 0 ) - free( pDsdMan->pRoots ); - pDsdMan->nRootsAlloc = nFuncs; - pDsdMan->pRoots = (Dsd_Node_t **) malloc( pDsdMan->nRootsAlloc * sizeof(Dsd_Node_t *) ); - } - - if ( pDsdMan->fVerbose ) - printf( "\nDecomposability statistics for individual outputs:\n" ); - - // set the counter of decomposition nodes - s_nDecBlocks = 0; - - // perform decomposition for all outputs - clk = clock(); - pDsdMan->nRoots = 0; - s_nCascades = 0; - for ( i = 0; i < nFuncs; i++ ) - { - int nLiteralsPrev; - int nDecBlocksPrev; - int nExorGatesPrev; - int nReusedBlocksPres; - int nCascades; - int MaxBlock; - int nPrimeBlocks; - long clk; - - clk = clock(); - nLiteralsPrev = s_nLiterals; - nDecBlocksPrev = s_nDecBlocks; - nExorGatesPrev = s_nExorGates; - nReusedBlocksPres = s_nReusedBlocks; - nPrimeBlocks = s_nPrimeBlocks; - - pDsdMan->pRoots[ pDsdMan->nRoots++ ] = dsdKernelDecompose_rec( pDsdMan, pbFuncs[i] ); - - Dsd_TreeNodeGetInfoOne( pDsdMan->pRoots[i], &nCascades, &MaxBlock ); - s_nCascades = ddMax( s_nCascades, nCascades ); - pTemp = Dsd_Regular(pDsdMan->pRoots[i]); - if ( pTemp->Type != DSD_NODE_PRIME || pTemp->nDecs != Extra_bddSuppSize(dd,pTemp->S) ) - nDecOutputs++; - if ( MaxBlock < 3 ) - nCBFOutputs++; - SumMaxGateSize += MaxBlock; - - if ( pDsdMan->fVerbose ) - { - printf("#%02d: ", i ); - printf("Ins=%2d. ", Cudd_SupportSize(dd,pbFuncs[i]) ); - printf("Gts=%3d. ", Dsd_TreeCountNonTerminalNodesOne( pDsdMan->pRoots[i] ) ); - printf("Pri=%3d. ", Dsd_TreeCountPrimeNodesOne( pDsdMan->pRoots[i] ) ); - printf("Max=%3d. ", MaxBlock ); - printf("Reuse=%2d. ", s_nReusedBlocks-nReusedBlocksPres ); - printf("Csc=%2d. ", nCascades ); - printf("T= %.2f s. ", (float)(clock()-clk)/(float)(CLOCKS_PER_SEC) ) ; - printf("Bdd=%2d. ", Cudd_DagSize(pbFuncs[i]) ); - printf("\n"); - fflush( stdout ); - } - } - assert( pDsdMan->nRoots == nFuncs ); - - if ( pDsdMan->fVerbose ) - { - printf( "\n" ); - printf( "The cumulative decomposability statistics:\n" ); - printf( " Total outputs = %5d\n", nFuncs ); - printf( " Decomposable outputs = %5d\n", nDecOutputs ); - printf( " Completely decomposable outputs = %5d\n", nCBFOutputs ); - printf( " The sum of max gate sizes = %5d\n", SumMaxGateSize ); - printf( " Shared BDD size = %5d\n", Cudd_SharingSize( pbFuncs, nFuncs ) ); - printf( " Decomposition entries = %5d\n", st_count( pDsdMan->Table ) ); - printf( " Pure decomposition time = %.2f sec\n", (float)(clock() - clk)/(float)(CLOCKS_PER_SEC) ); - } -/* - printf( "s_Loops1 = %d.\n", s_Loops1 ); - printf( "s_Loops2 = %d.\n", s_Loops2 ); - printf( "s_Loops3 = %d.\n", s_Loops3 ); - printf( "s_Case4Calls = %d.\n", s_Case4Calls ); - printf( "s_Case4CallsSpecial = %d.\n", s_Case4CallsSpecial ); - printf( "s_Case5 = %d.\n", s_Case5 ); - printf( "s_Loops2Useless = %d.\n", s_Loops2Useless ); -*/ -} - -/**Function************************************************************* - - Synopsis [Performs decomposition for one function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc ) -{ - return dsdKernelDecompose_rec( pDsdMan, bFunc ); -} - -/**Function************************************************************* - - Synopsis [The main function of this module. Recursive implementation of DSD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * bFunc0 ) -{ - DdManager * dd = pDsdMan->dd; - DdNode * bLow; - DdNode * bLowR; - DdNode * bHigh; - - int VarInt; - DdNode * bVarCur; - Dsd_Node_t * pVarCurDE; - // works only if var indices start from 0!!! - DdNode * bSuppNew = NULL, * bTemp; - - int fContained; - int nSuppLH; - int nSuppL; - int nSuppH; - - - - // various decomposition nodes - Dsd_Node_t * pThis, * pL, * pH, * pLR, * pHR; - - Dsd_Node_t * pSmallR, * pLargeR; - Dsd_Node_t * pTableEntry; - - - // treat the complemented case - DdNode * bF = Cudd_Regular(bFunc0); - int fCompF = (int)(bF != bFunc0); - - // check cache - if ( st_lookup( pDsdMan->Table, (char*)bF, (char**)&pTableEntry ) ) - { // the entry is present - HashSuccess++; - return Dsd_NotCond( pTableEntry, fCompF ); - } - HashFailure++; - Depth++; - - // proceed to consider "four cases" - ////////////////////////////////////////////////////////////////////// - // TERMINAL CASES - CASES 1 and 2 - ////////////////////////////////////////////////////////////////////// - bLow = cuddE(bF); - bLowR = Cudd_Regular(bLow); - bHigh = cuddT(bF); - VarInt = bF->index; - bVarCur = dd->vars[VarInt]; - pVarCurDE = pDsdMan->pInputs[VarInt]; - // works only if var indices start from 0!!! - bSuppNew = NULL; - - if ( bLowR->index == CUDD_CONST_INDEX || bHigh->index == CUDD_CONST_INDEX ) - { // one of the cofactors in the constant - if ( bHigh == b1 ) // bHigh cannot be equal to b0, because then it will be complemented - if ( bLow == b0 ) // bLow cannot be equal to b1, because then the node will have bLow == bHigh - ///////////////////////////////////////////////////////////////// - // bLow == 0, bHigh == 1, F = x'&0 + x&1 = x - ///////////////////////////////////////////////////////////////// - { // create the elementary variable node - assert(0); // should be already in the hash table - pThis = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, s_nDecBlocks++ ); - pThis->pDecs[0] = NULL; - } - else // if ( bLow != constant ) - ///////////////////////////////////////////////////////////////// - // bLow != const, bHigh == 1, F = x'&bLow + x&1 = bLow + x --- DSD_NODE_OR(x,bLow) - ///////////////////////////////////////////////////////////////// - { - pL = dsdKernelDecompose_rec( pDsdMan, bLow ); - pLR = Dsd_Regular( pL ); - bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew); - if ( pLR->Type == DSD_NODE_OR && pL == pLR ) // OR and no complement - { // add to the components - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pL->nDecs+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pVarCurDE, pL->pDecs, pL->nDecs ); - } - else // all other cases - { // create a new 2-input OR-gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 ); - } - } - else // if ( bHigh != const ) // meaning that bLow should be a constant - { - pH = dsdKernelDecompose_rec( pDsdMan, bHigh ); - pHR = Dsd_Regular( pH ); - bSuppNew = Cudd_bddAnd( dd, bVarCur, pHR->S ); Cudd_Ref(bSuppNew); - if ( bLow == b0 ) - ///////////////////////////////////////////////////////////////// - // Low == 0, High != 1, F = x'&0+x&High = (x'+High')'--- NOR(x',High') - ///////////////////////////////////////////////////////////////// - if ( pHR->Type == DSD_NODE_OR && pH != pHR ) // DSD_NODE_OR and complement - { // add to the components - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pHR->nDecs+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pHR->pDecs, pHR->nDecs ); - pThis = Dsd_Not(pThis); - } - else // all other cases - { // create a new 2-input NOR gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); - pH = Dsd_Not(pH); - dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 ); - pThis = Dsd_Not(pThis); - } - else // if ( bLow == b1 ) - ///////////////////////////////////////////////////////////////// - // Low == 1, High != 1, F = x'&1 + x&High = x' + High --- DSD_NODE_OR(x',High) - ///////////////////////////////////////////////////////////////// - if ( pHR->Type == DSD_NODE_OR && pH == pHR ) // OR and no complement - { // add to the components - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pH->nDecs+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pH->pDecs, pH->nDecs ); - } - else // all other cases - { // create a new 2-input OR-gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 ); - } - } - goto EXIT; - } - // else if ( bLow != const && bHigh != const ) - - // the case of equal cofactors (up to complementation) - if ( bLowR == bHigh ) - ///////////////////////////////////////////////////////////////// - // Low == G, High == G', F = x'&G + x&G' = (x(+)G) --- EXOR(x,Low) - ///////////////////////////////////////////////////////////////// - { - pL = dsdKernelDecompose_rec( pDsdMan, bLow ); - pLR = Dsd_Regular( pL ); - bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew); - if ( pLR->Type == DSD_NODE_EXOR ) // complemented or not - does not matter! - { // add to the components - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, pLR->nDecs+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pVarCurDE, pLR->pDecs, pLR->nDecs ); - if ( pL != pLR ) - pThis = Dsd_Not( pThis ); - } - else // all other cases - { // create a new 2-input EXOR-gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ ); - if ( pL != pLR ) // complemented - { - dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pLR, 1 ); - pThis = Dsd_Not( pThis ); - } - else // non-complemented - dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 ); - } - goto EXIT; - } - - ////////////////////////////////////////////////////////////////////// - // solve subproblems - ////////////////////////////////////////////////////////////////////// - pL = dsdKernelDecompose_rec( pDsdMan, bLow ); - pH = dsdKernelDecompose_rec( pDsdMan, bHigh ); - pLR = Dsd_Regular( pL ); - pHR = Dsd_Regular( pH ); - - assert( pLR->Type == DSD_NODE_BUF || pLR->Type == DSD_NODE_OR || pLR->Type == DSD_NODE_EXOR || pLR->Type == DSD_NODE_PRIME ); - assert( pHR->Type == DSD_NODE_BUF || pHR->Type == DSD_NODE_OR || pHR->Type == DSD_NODE_EXOR || pHR->Type == DSD_NODE_PRIME ); - -/* -if ( Depth == 1 ) -{ -// PRK(bLow,pDecTreeTotal->nInputs); -// PRK(bHigh,pDecTreeTotal->nInputs); -if ( s_Show ) -{ - PRD( pL ); - PRD( pH ); -} -} -*/ - // compute the new support - bTemp = Cudd_bddAnd( dd, pLR->S, pHR->S ); Cudd_Ref( bTemp ); - nSuppL = Extra_bddSuppSize( dd, pLR->S ); - nSuppH = Extra_bddSuppSize( dd, pHR->S ); - nSuppLH = Extra_bddSuppSize( dd, bTemp ); - bSuppNew = Cudd_bddAnd( dd, bTemp, bVarCur ); Cudd_Ref( bSuppNew ); - Cudd_RecursiveDeref( dd, bTemp ); - - - // several possibilities are possible - // (1) support of one component contains another - // (2) none of the supports is contained in another - fContained = dsdKernelCheckContainment( pDsdMan, pLR, pHR, &pLargeR, &pSmallR ); - - ////////////////////////////////////////////////////////////////////// - // CASE 3.b One of the cofactors in a constant (OR and EXOR) - ////////////////////////////////////////////////////////////////////// - // the support of the larger component should contain the support of the smaller - // it is possible to have PRIME function in this role - // for example: F = ITE( a+b, c(+)d, e+f ), F0 = ITE( b, c(+)d, e+f ), F1 = c(+)d - if ( fContained ) - { - Dsd_Node_t * pSmall, * pLarge; - int c, iCompLarge; // the number of the component is Large is equal to the whole of Small - int fLowIsLarge; - - DdNode * bFTemp; // the changed input function - Dsd_Node_t * pDETemp, * pDENew; - - Dsd_Node_t * pComp = NULL; - int nComp; - - if ( pSmallR == pLR ) - { // Low is Small => High is Large - pSmall = pL; - pLarge = pH; - fLowIsLarge = 0; - } - else - { // vice versa - pSmall = pH; - pLarge = pL; - fLowIsLarge = 1; - } - - // treat the situation when the larger is PRIME - if ( pLargeR->Type == DSD_NODE_PRIME ) //&& pLargeR->nDecs != pSmallR->nDecs ) - { - // QUESTION: Is it possible for pLargeR->nDecs > 3 - // and pSmall contained as one of input in pLarge? - // Yes, for example F = a'c + a & MUX(b,c',d) = a'c + abc' + ab'd is non-decomposable - // Consider the function H(a->xy) = F( xy, b, c, d ) - // H0 = H(x=0) = F(0,b,c,d) = c - // H1 = F(x=1) = F(y,b,c,d) - non-decomposable - // - // QUESTION: Is it possible that pLarge is PRIME(3) and pSmall is OR(2), - // which is not contained in PRIME as one input? - // Yes, for example F = abcd + b'c'd' + a'c'd' = PRIME(ab, c, d) - // F(a=0) = c'd' = NOT(OR(a,d)) F(a=1) = bcd + b'c'd' = PRIME(b,c,d) - // To find decomposition, we have to prove that F(a=1)|b=0 = F(a=0) - - // Is it possible that (pLargeR->nDecs == pSmallR->nDecs) and yet this case holds? - // Yes, consider the function such that F(a=0) = PRIME(a,b+c,d,e) and F(a=1) = OR(b,c,d,e) - // They have the same number of inputs and it is possible that they will be the cofactors - // as discribed in the previous example. - - // find the component, which when substituted for 0 or 1, produces the desired result - int g, fFoundComp; // {0,1} depending on whether setting cofactor to 0 or 1 worked out - - DdNode * bLarge, * bSmall; - if ( fLowIsLarge ) - { - bLarge = bLow; - bSmall = bHigh; - } - else - { - bLarge = bHigh; - bSmall = bLow; - } - - for ( g = 0; g < pLargeR->nDecs; g++ ) -// if ( g != c ) - { - pDETemp = pLargeR->pDecs[g]; // cannot be complemented - if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, pDETemp->G, b1 ) ) - { - fFoundComp = 1; - break; - } - - s_Loops1++; - - if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, Cudd_Not(pDETemp->G), b1 ) ) - { - fFoundComp = 0; - break; - } - - s_Loops1++; - } - - if ( g != pLargeR->nDecs ) - { // decomposition is found - if ( fFoundComp ) - if ( fLowIsLarge ) - bFTemp = Cudd_bddOr( dd, bVarCur, pLargeR->pDecs[g]->G ); - else - bFTemp = Cudd_bddOr( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G ); - else - if ( fLowIsLarge ) - bFTemp = Cudd_bddAnd( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G ); - else - bFTemp = Cudd_bddAnd( dd, bVarCur, pLargeR->pDecs[g]->G ); - Cudd_Ref( bFTemp ); - - pDENew = dsdKernelDecompose_rec( pDsdMan, bFTemp ); - pDENew = Dsd_Regular( pDENew ); - Cudd_RecursiveDeref( dd, bFTemp ); - - // get the new gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLargeR->nDecs, s_nDecBlocks++ ); - dsdKernelCopyListPlusOneMinusOne( pThis, pDENew, pLargeR->pDecs, pLargeR->nDecs, g ); - goto EXIT; - } - } - - // try to find one component in the pLarger that is equal to the whole of pSmaller - for ( c = 0; c < pLargeR->nDecs; c++ ) - if ( pLargeR->pDecs[c] == pSmall || pLargeR->pDecs[c] == Dsd_Not(pSmall) ) - { - iCompLarge = c; - break; - } - - // assign the equal component - if ( c != pLargeR->nDecs ) // the decomposition is possible! - { - pComp = pLargeR->pDecs[iCompLarge]; - nComp = 1; - } - else // the decomposition is still possible - { // for example F = OR(ab,c,d), F(a=0) = OR(c,d), F(a=1) = OR(b,c,d) - // supp(F0) is contained in supp(F1), Polarity(F(a=0)) == Polarity(F(a=1)) - - // try to find a group of common components - if ( pLargeR->Type == pSmallR->Type && - (pLargeR->Type == DSD_NODE_EXOR || pSmallR->Type == DSD_NODE_OR&& ((pLarge==pLargeR) == (pSmall==pSmallR))) ) - { - Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; - int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLargeR, pSmallR, &pCommon, &pLastDiffL, &pLastDiffH ); - // if all the components of pSmall are contained in pLarge, - // then the decomposition exists - if ( nCommon == pSmallR->nDecs ) - { - pComp = pSmallR; - nComp = pSmallR->nDecs; - } - } - } - - if ( pComp ) // the decomposition is possible! - { -// Dsd_Node_t * pComp = pLargeR->pDecs[iCompLarge]; - Dsd_Node_t * pCompR = Dsd_Regular( pComp ); - int fComp1 = (int)( pLarge != pLargeR ); - int fComp2 = (int)( pComp != pCompR ); - int fComp3 = (int)( pSmall != pSmallR ); - - DdNode * bFuncComp; // the function of the given component - DdNode * bFuncNew; // the function of the input component - - if ( pLargeR->Type == DSD_NODE_OR ) // Figure 4 of Matsunaga's paper - { - // the decomposition exists only if the polarity assignment - // along the paths is the same - if ( (fComp1 ^ fComp2) == fComp3 ) - { // decomposition exists = consider 4 cases - // consideration of cases leads to the following conclusion - // fComp1 gives the polarity of the resulting DSD_NODE_OR gate - // fComp2 gives the polarity of the common component feeding into the DSD_NODE_OR gate - // - // | fComp1 pL/ |pS - // <> .........<=>....... <> | - // | / | - // [OR] [OR] | fComp3 - // / \ fComp2 / | \ | - // <> <> .......<=>... /..|..<> | - // / \ / | \| - // [OR] [C] S1 S2 C - // / \ - // <> \ - // / \ - // [OR] [x] - // / \ - // S1 S2 - // - - - // at this point we have the function F (bFTemp) and the common component C (bFuncComp) - // to get the remainder, R, in the relationship F = R + C, supp(R) & supp(C) = 0 - // we compute the following R = Exist( F - C, supp(C) ) - bFTemp = (fComp1)? Cudd_Not( bF ): bF; - bFuncComp = (fComp2)? Cudd_Not( pCompR->G ): pCompR->G; - bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bFuncComp), pCompR->S ); Cudd_Ref( bFuncNew ); - - // there is no need to copy the dec entry list first, because pComp is a component - // which will not be destroyed by the recursive call to decomposition - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); - assert( Dsd_IsComplement(pDENew) ); // follows from the consideration of cases - Cudd_RecursiveDeref( dd, bFuncNew ); - - // get the new gate - if ( nComp == 1 ) - { - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); - pThis->pDecs[0] = pDENew; - pThis->pDecs[1] = pComp; // takes the complement - } - else - { // pComp is not complemented - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nComp+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp ); - } - - if ( fComp1 ) - pThis = Dsd_Not( pThis ); - goto EXIT; - } - } - else if ( pLargeR->Type == DSD_NODE_EXOR ) // Figure 5 of Matsunaga's paper (with correction) - { // decomposition always exists = consider 4 cases - - // consideration of cases leads to the following conclusion - // fComp3 gives the COMPLEMENT of the polarity of the resulting EXOR gate - // (if fComp3 is 0, the EXOR gate is complemented, and vice versa) - // - // | fComp1 pL/ |pS - // <> .........<=>....... /....| fComp3 - // | / | - // [XOR] [XOR] | - // / \ fComp2==0 / | \ | - // / \ / | \ | - // / \ / | \| - // [OR] [C] S1 S2 C - // / \ - // <> \ - // / \ - // [XOR] [x] - // / \ - // S1 S2 - // - - assert( fComp2 == 0 ); - // find the functionality of the lower gates - bFTemp = (fComp3)? bF: Cudd_Not( bF ); - bFuncNew = Cudd_bddXor( dd, bFTemp, pComp->G ); Cudd_Ref( bFuncNew ); - - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); - assert( !Dsd_IsComplement(pDENew) ); // follows from the consideration of cases - Cudd_RecursiveDeref( dd, bFuncNew ); - - // get the new gate - if ( nComp == 1 ) - { - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ ); - pThis->pDecs[0] = pDENew; - pThis->pDecs[1] = pComp; - } - else - { // pComp is not complemented - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nComp+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp ); - } - - if ( !fComp3 ) - pThis = Dsd_Not( pThis ); - goto EXIT; - } - } - } - - // this case was added to fix the trivial bug found November 4, 2002 in Japan - // by running the example provided by T. Sasao - if ( nSuppLH == nSuppL + nSuppH ) // the supports of the components are disjoint - { - // create a new component of the type ITE( a, pH, pL ) - pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, 3, s_nDecBlocks++ ); - if ( dd->perm[pLR->S->index] < dd->perm[pHR->S->index] ) // pLR is higher in the varible order - { - pThis->pDecs[1] = pLR; - pThis->pDecs[2] = pHR; - } - else // pHR is higher in the varible order - { - pThis->pDecs[1] = pHR; - pThis->pDecs[2] = pLR; - } - // add the first component - pThis->pDecs[0] = pVarCurDE; - goto EXIT; - } - - - ////////////////////////////////////////////////////////////////////// - // CASE 3.a Neither of the cofactors is a constant (OR, EXOR, PRIME) - ////////////////////////////////////////////////////////////////////// - // the component types are identical - // and if they are OR, they are either both complemented or both not complemented - // and if they are PRIME, their dec numbers should be the same - if ( pLR->Type == pHR->Type && - pLR->Type != DSD_NODE_BUF && - (pLR->Type != DSD_NODE_OR || ( pL == pLR && pH == pHR || pL != pLR && pH != pHR ) ) && - (pLR->Type != DSD_NODE_PRIME || pLR->nDecs == pHR->nDecs) ) - { - // array to store common comps in pL and pH - Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; - int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLR, pHR, &pCommon, &pLastDiffL, &pLastDiffH ); - if ( nCommon ) - { - if ( pLR->Type == DSD_NODE_OR ) // Figure 2 of Matsunaga's paper - { // at this point we have the function F and the group of common components C - // to get the remainder, R, in the relationship F = R + C, supp(R) & supp(C) = 0 - // we compute the following R = Exist( F - C, supp(C) ) - - // compute the sum total of the common components and the union of their supports - DdNode * bCommF, * bCommS, * bFTemp, * bFuncNew; - Dsd_Node_t * pDENew; - - dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, &bCommS, 0 ); - Cudd_Ref( bCommF ); - Cudd_Ref( bCommS ); - bFTemp = ( pL != pLR )? Cudd_Not(bF): bF; - - bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bCommF), bCommS ); Cudd_Ref( bFuncNew ); - Cudd_RecursiveDeref( dd, bCommF ); - Cudd_RecursiveDeref( dd, bCommS ); - - // get the new gate - - // copy the components first, then call the decomposition - // because decomposition will distroy the list used for copying - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nCommon + 1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); - - // call the decomposition recursively - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); -// assert( !Dsd_IsComplement(pDENew) ); // follows from the consideration of cases - Cudd_RecursiveDeref( dd, bFuncNew ); - - // add the first component - pThis->pDecs[0] = pDENew; - - if ( pL != pLR ) - pThis = Dsd_Not( pThis ); - goto EXIT; - } - else - if ( pLR->Type == DSD_NODE_EXOR ) // Figure 3 of Matsunaga's paper - { - // compute the sum total of the common components and the union of their supports - DdNode * bCommF, * bFuncNew; - Dsd_Node_t * pDENew; - int fCompExor; - - dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, 1 ); - Cudd_Ref( bCommF ); - - bFuncNew = Cudd_bddXor( dd, bF, bCommF ); Cudd_Ref( bFuncNew ); - Cudd_RecursiveDeref( dd, bCommF ); - - // get the new gate - - // copy the components first, then call the decomposition - // because decomposition will distroy the list used for copying - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nCommon + 1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); - - // call the decomposition recursively - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); - Cudd_RecursiveDeref( dd, bFuncNew ); - - // remember the fact that it was complemented - fCompExor = Dsd_IsComplement(pDENew); - pDENew = Dsd_Regular(pDENew); - - // add the first component - pThis->pDecs[0] = pDENew; - - - if ( fCompExor ) - pThis = Dsd_Not( pThis ); - goto EXIT; - } - else - if ( pLR->Type == DSD_NODE_PRIME && (nCommon == pLR->nDecs-1 || nCommon == pLR->nDecs) ) - { - // for example the function F(a,b,c,d) = ITE(b,c,a(+)d) produces - // two cofactors F(a=0) = PRIME(b,c,d) and F(a=1) = PRIME(b,c,d) - // with exactly the same list of common components - - Dsd_Node_t * pDENew; - DdNode * bFuncNew; - int fCompComp = 0; // this flag can be {0,1,2} - // if it is 0 there is no identity - // if it is 1/2, the cofactored functions are equal in the direct/complemented polarity - - if ( nCommon == pLR->nDecs ) - { // all the components are the same - // find the formal input, in which pLow and pHigh differ (if such input exists) - int m; - Dsd_Node_t * pTempL, * pTempH; - - s_Common++; - for ( m = 0; m < pLR->nDecs; m++ ) - { - pTempL = pLR->pDecs[m]; // cannot be complemented - pTempH = pHR->pDecs[m]; // cannot be complemented - - if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pTempL->G, Cudd_Not(pTempH->G) ) && - Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pTempL->G), pTempH->G ) ) - { - pLastDiffL = pTempL; - pLastDiffH = pTempH; - assert( pLastDiffL == pLastDiffH ); - fCompComp = 2; - break; - } - - s_Loops2++; - s_Loops2++; -/* - if ( s_Loops2 % 10000 == 0 ) - { - int i; - for ( i = 0; i < pLR->nDecs; i++ ) - printf( " %d(s=%d)", pLR->pDecs[i]->Type, - Extra_bddSuppSize(dd, pLR->pDecs[i]->S) ); - printf( "\n" ); - } -*/ - - } -// if ( pLR->nDecs == Extra_bddSuppSize(dd, pLR->S) ) -// s_Loops2Useless += pLR->nDecs * 2; - - if ( fCompComp ) - { // put the equal components into pCommon, so that they could be copied into the new dec entry - nCommon = 0; - for ( m = 0; m < pLR->nDecs; m++ ) - if ( pLR->pDecs[m] != pLastDiffL ) - pCommon[nCommon++] = pLR->pDecs[m]; - assert( nCommon = pLR->nDecs-1 ); - } - } - else - { // the differing components are known - check that they have compatible PRIME function - - s_CommonNo++; - - // find the numbers of different components - assert( pLastDiffL ); - assert( pLastDiffH ); - // also, they cannot be complemented, because the decomposition type is PRIME - - if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), Cudd_Not(pLastDiffH->G) ) && - Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pLastDiffL->G, pLastDiffH->G ) ) - fCompComp = 1; - else if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pLastDiffL->G, Cudd_Not(pLastDiffH->G) ) && - Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), pLastDiffH->G ) ) - fCompComp = 2; - - s_Loops3 += 4; - } - - if ( fCompComp ) - { - if ( fCompComp == 1 ) // it is true that bLow(G=0) == bHigh(H=0) && bLow(G=1) == bHigh(H=1) - bFuncNew = Cudd_bddIte( dd, bVarCur, pLastDiffH->G, pLastDiffL->G ); - else // it is true that bLow(G=0) == bHigh(H=1) && bLow(G=1) == bHigh(H=0) - bFuncNew = Cudd_bddIte( dd, bVarCur, Cudd_Not(pLastDiffH->G), pLastDiffL->G ); - Cudd_Ref( bFuncNew ); - - // get the new gate - - // copy the components first, then call the decomposition - // because decomposition will distroy the list used for copying - pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLR->nDecs, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); - - // create a new component - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); - Cudd_RecursiveDeref( dd, bFuncNew ); - // the BDD of the argument function in PRIME decomposition, should be regular - pDENew = Dsd_Regular(pDENew); - - // add the first component - pThis->pDecs[0] = pDENew; - goto EXIT; - } - } // end of PRIME type - } // end of existing common components - } // end of CASE 3.a - -// if ( Depth != 1) -// { - -//CASE4: - ////////////////////////////////////////////////////////////////////// - // CASE 4 - ////////////////////////////////////////////////////////////////////// - { - // estimate the number of entries in the list - int nEntriesMax = pDsdMan->nInputs - dd->perm[VarInt]; - - // create the new decomposition entry - int nEntries = 0; - - DdNode * SuppL, * SuppH, * SuppL_init, * SuppH_init; - Dsd_Node_t *pHigher, *pLower, * pTemp, * pDENew; - - - int levTopSuppL; - int levTopSuppH; - int levTop; - - pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, nEntriesMax, s_nDecBlocks++ ); - pThis->pDecs[ nEntries++ ] = pVarCurDE; - // other entries will be added to this list one-by-one during analysis - - // count how many times does it happen that the decomposition entries are - s_Case4Calls++; - - // consider the simplest case: when the supports are equal - // and at least one of the components - // is the PRIME without decompositions, or - // when both of them are without decomposition - if ( (((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) || (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) && pLR->S == pHR->S) || - ((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) && (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) ) - { - - s_Case4CallsSpecial++; - // walk through both supports and create the decomposition list composed of simple entries - SuppL = pLR->S; - SuppH = pHR->S; - do - { - // determine levels - levTopSuppL = cuddI(dd,SuppL->index); - levTopSuppH = cuddI(dd,SuppH->index); - - // skip the topmost variable in both supports - if ( levTopSuppL <= levTopSuppH ) - { - levTop = levTopSuppL; - SuppL = cuddT(SuppL); - } - else - levTop = levTopSuppH; - - if ( levTopSuppH <= levTopSuppL ) - SuppH = cuddT(SuppH); - - // set the new decomposition entry - pThis->pDecs[ nEntries++ ] = pDsdMan->pInputs[ dd->invperm[levTop] ]; - } - while ( SuppL != b1 || SuppH != b1 ); - } - else - { - - // compare two different decomposition lists - SuppL_init = pLR->S; - SuppH_init = pHR->S; - // start references (because these supports will change) - SuppL = pLR->S; Cudd_Ref( SuppL ); - SuppH = pHR->S; Cudd_Ref( SuppH ); - while ( SuppL != b1 || SuppH != b1 ) - { - // determine the top level in cofactors and - // whether they have the same top level - int TopLevL = cuddI(dd,SuppL->index); - int TopLevH = cuddI(dd,SuppH->index); - int TopLevel = TopLevH; - int fEqualLevel = 0; - - DdNode * bVarTop; - DdNode * bSuppSubract; - - - if ( TopLevL < TopLevH ) - { - pHigher = pLR; - pLower = pHR; - TopLevel = TopLevL; - } - else if ( TopLevL > TopLevH ) - { - pHigher = pHR; - pLower = pLR; - } - else - fEqualLevel = 1; - assert( TopLevel != CUDD_CONST_INDEX ); - - - // find the currently top variable in the decomposition lists - bVarTop = dd->vars[dd->invperm[TopLevel]]; - - if ( !fEqualLevel ) - { - // find the lower support - DdNode * bSuppLower = (TopLevL < TopLevH)? SuppH_init: SuppL_init; - - // find the first component in pHigher - // whose support does not overlap with supp(Lower) - // and remember the previous component - int fPolarity; - Dsd_Node_t * pPrev = NULL; // the pointer to the component proceeding pCur - Dsd_Node_t * pCur = pHigher; // the first component not contained in supp(Lower) - while ( Extra_bddSuppOverlapping( dd, pCur->S, bSuppLower ) ) - { // get the next component - pPrev = pCur; - pCur = dsdKernelFindContainingComponent( pDsdMan, pCur, bVarTop, &fPolarity ); - }; - - // look for the possibility to subtract more than one component - if ( pPrev == NULL || pPrev->Type == DSD_NODE_PRIME ) - { // if there is no previous component, or if the previous component is PRIME - // there is no way to subtract more than one component - - // add the new decomposition entry (it is already regular) - pThis->pDecs[ nEntries++ ] = pCur; - // assign the support to be subtracted from both components - bSuppSubract = pCur->S; - } - else // all other types - { - // go through the decomposition list of pPrev and find components - // whose support does not overlap with supp(Lower) - - static Dsd_Node_t * pNonOverlap[MAXINPUTS]; - int i, nNonOverlap = 0; - for ( i = 0; i < pPrev->nDecs; i++ ) - { - pTemp = Dsd_Regular( pPrev->pDecs[i] ); - if ( !Extra_bddSuppOverlapping( dd, pTemp->S, bSuppLower ) ) - pNonOverlap[ nNonOverlap++ ] = pPrev->pDecs[i]; - } - assert( nNonOverlap > 0 ); - - if ( nNonOverlap == 1 ) - { // one one component was found, which is the original one - assert( Dsd_Regular(pNonOverlap[0]) == pCur); - // add the new decomposition entry - pThis->pDecs[ nEntries++ ] = pCur; - // assign the support to be subtracted from both components - bSuppSubract = pCur->S; - } - else // more than one components was found - { - // find the OR (EXOR) of the non-overlapping components - DdNode * bCommF; - dsdKernelComputeSumOfComponents( pDsdMan, pNonOverlap, nNonOverlap, &bCommF, NULL, (int)(pPrev->Type==DSD_NODE_EXOR) ); - Cudd_Ref( bCommF ); - - // create a new gated - pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF ); - Cudd_RecursiveDeref(dd, bCommF); - // make it regular... it must be regular already - assert( !Dsd_IsComplement(pDENew) ); - - // add the new decomposition entry - pThis->pDecs[ nEntries++ ] = pDENew; - // assign the support to be subtracted from both components - bSuppSubract = pDENew->S; - } - } - - // subtract its support from the support of upper component - if ( TopLevL < TopLevH ) - { - SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ); Cudd_Ref( SuppL ); - Cudd_RecursiveDeref(dd, bTemp); - } - else - { - SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ); Cudd_Ref( SuppH ); - Cudd_RecursiveDeref(dd, bTemp); - } - } // end of if ( !fEqualLevel ) - else // if ( fEqualLevel ) -- they have the same top level var - { - static Dsd_Node_t * pMarkedLeft[MAXINPUTS]; // the pointers to the marked blocks - static char pMarkedPols[MAXINPUTS]; // polarities of the marked blocks - int nMarkedLeft = 0; - - int fPolarity = 0; - Dsd_Node_t * pTempL = pLR; - - int fPolarityCurH = 0; - Dsd_Node_t * pPrevH = NULL, * pCurH = pHR; - - int fPolarityCurL = 0; - Dsd_Node_t * pPrevL = NULL, * pCurL = pLR; // = pMarkedLeft[0]; - int index = 1; - - // set the new mark - s_Mark++; - - // go over the dec list of pL, mark all components that contain the given variable - assert( Extra_bddSuppContainVar( dd, pLR->S, bVarTop ) ); - assert( Extra_bddSuppContainVar( dd, pHR->S, bVarTop ) ); - do { - pTempL->Mark = s_Mark; - pMarkedLeft[ nMarkedLeft ] = pTempL; - pMarkedPols[ nMarkedLeft ] = fPolarity; - nMarkedLeft++; - } while ( pTempL = dsdKernelFindContainingComponent( pDsdMan, pTempL, bVarTop, &fPolarity ) ); - - // go over the dec list of pH, and find the component that is marked and the previos one - // (such component always exists, because they have common variables) - while ( pCurH->Mark != s_Mark ) - { - pPrevH = pCurH; - pCurH = dsdKernelFindContainingComponent( pDsdMan, pCurH, bVarTop, &fPolarityCurH ); - assert( pCurH ); - } - - // go through the first list once again and find - // the component proceeding the one marked found in the second list - while ( pCurL != pCurH ) - { - pPrevL = pCurL; - pCurL = pMarkedLeft[index]; - fPolarityCurL = pMarkedPols[index]; - index++; - } - - // look for the possibility to subtract more than one component - if ( !pPrevL || !pPrevH || pPrevL->Type != pPrevH->Type || pPrevL->Type == DSD_NODE_PRIME || fPolarityCurL != fPolarityCurH ) - { // there is no way to extract more than one - pThis->pDecs[ nEntries++ ] = pCurH; - // assign the support to be subtracted from both components - bSuppSubract = pCurH->S; - } - else - { - // find the equal components in two decomposition lists - Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; - int nCommon = dsdKernelFindCommonComponents( pDsdMan, pPrevL, pPrevH, &pCommon, &pLastDiffL, &pLastDiffH ); - - if ( nCommon == 0 || nCommon == 1 ) - { // one one component was found, which is the original one - // assert( Dsd_Regular(pCommon[0]) == pCurL); - // add the new decomposition entry - pThis->pDecs[ nEntries++ ] = pCurL; - // assign the support to be subtracted from both components - bSuppSubract = pCurL->S; - } - else // more than one components was found - { - // find the OR (EXOR) of the non-overlapping components - DdNode * bCommF; - dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, (int)(pPrevL->Type==DSD_NODE_EXOR) ); - Cudd_Ref( bCommF ); - - pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF ); - assert( !Dsd_IsComplement(pDENew) ); // cannot be complemented because of construction - Cudd_RecursiveDeref( dd, bCommF ); - - // add the new decomposition entry - pThis->pDecs[ nEntries++ ] = pDENew; - - // assign the support to be subtracted from both components - bSuppSubract = pDENew->S; - } - } - - SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ), Cudd_Ref( SuppL ); - Cudd_RecursiveDeref(dd, bTemp); - - SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ), Cudd_Ref( SuppH ); - Cudd_RecursiveDeref(dd, bTemp); - - } // end of if ( fEqualLevel ) - - } // end of decomposition list comparison - Cudd_RecursiveDeref( dd, SuppL ); - Cudd_RecursiveDeref( dd, SuppH ); - - } - - // check that the estimation of the number of entries was okay - assert( nEntries <= nEntriesMax ); - -// if ( nEntries != Extra_bddSuppSize(dd, bSuppNew) ) -// s_Case5++; - - // update the number of entries in the new decomposition list - pThis->nDecs = nEntries; - } -//} -EXIT: - - { - // if the component created is complemented, it represents a function without complement - // therefore, as it is, without complement, it should recieve the complemented function - Dsd_Node_t * pThisR = Dsd_Regular( pThis ); - assert( pThisR->G == NULL ); - assert( pThisR->S == NULL ); - - if ( pThisR == pThis ) // set regular function - pThisR->G = bF; - else // set complemented function - pThisR->G = Cudd_Not(bF); - Cudd_Ref(bF); // reference the function in the component - - assert( bSuppNew ); - pThisR->S = bSuppNew; // takes the reference from the new support - if ( st_insert( pDsdMan->Table, (char*)bF, (char*)pThis ) ) - { - assert( 0 ); - } - s_CacheEntries++; - - -/* - if ( dsdKernelVerifyDecomposition(dd, pThis) == 0 ) - { - // write the function, for which verification does not work - cout << endl << "Internal verification failed!"" ); - - // create the variable mask - static int s_pVarMask[MAXINPUTS]; - int nInputCounter = 0; - - Cudd_SupportArray( dd, bF, s_pVarMask ); - int k; - for ( k = 0; k < dd->size; k++ ) - if ( s_pVarMask[k] ) - nInputCounter++; - - cout << endl << "The problem function is "" ); - - DdNode * zNewFunc = Cudd_zddIsopCover( dd, bF, bF ); Cudd_Ref( zNewFunc ); - cuddWriteFunctionSop( stdout, dd, zNewFunc, -1, dd->size, "1", s_pVarMask ); - Cudd_RecursiveDerefZdd( dd, zNewFunc ); - } -*/ - - } - - Depth--; - return Dsd_NotCond( pThis, fCompF ); -} - - -//////////////////////////////////////////////////////////////////////// -/// OTHER FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Finds the corresponding decomposition entry.] - - Description [This function returns the non-complemented pointer to the - DecEntry of that component which contains the given variable in its - support, or NULL if no such component exists] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity ) - -{ - Dsd_Node_t * pTemp; - int i; - -// assert( !Dsd_IsComplement( pWhere ) ); -// assert( Extra_bddSuppContainVar( pDsdMan->dd, pWhere->S, Var ) ); - - if ( pWhere->nDecs == 1 ) - return NULL; - - for( i = 0; i < pWhere->nDecs; i++ ) - { - pTemp = Dsd_Regular( pWhere->pDecs[i] ); - if ( Extra_bddSuppContainVar( pDsdMan->dd, pTemp->S, Var ) ) - { - *fPolarity = (int)( pTemp != pWhere->pDecs[i] ); - return pTemp; - } - } - assert( 0 ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Find the common decomposition components.] - - Description [This function determines the common components. It counts - the number of common components in the decomposition lists of pL and pH - and returns their number and the lists of common components. It assumes - that pL and pH are regular pointers. It retuns also the pointers to the - last different components encountered in pL and pH.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH ) -{ - static Dsd_Node_t * Common[MAXINPUTS]; - int nCommon = 0; - - // pointers to the current decomposition entries - Dsd_Node_t * pLcur; - Dsd_Node_t * pHcur; - - // the pointers to their supports - DdNode * bSLcur; - DdNode * bSHcur; - - // the top variable in the supports - int TopVar; - - // the indices running through the components - int iCurL = 0; - int iCurH = 0; - while ( iCurL < pL->nDecs && iCurH < pH->nDecs ) - { // both did not run out - - pLcur = Dsd_Regular(pL->pDecs[iCurL]); - pHcur = Dsd_Regular(pH->pDecs[iCurH]); - - bSLcur = pLcur->S; - bSHcur = pHcur->S; - - // find out what component is higher in the BDD - if ( pDsdMan->dd->perm[bSLcur->index] < pDsdMan->dd->perm[bSHcur->index] ) - TopVar = bSLcur->index; - else - TopVar = bSHcur->index; - - if ( TopVar == bSLcur->index && TopVar == bSHcur->index ) - { - // the components may be equal - should match exactly! - if ( pL->pDecs[iCurL] == pH->pDecs[iCurH] ) - Common[nCommon++] = pL->pDecs[iCurL]; - else - { - *pLastDiffL = pL->pDecs[iCurL]; - *pLastDiffH = pH->pDecs[iCurH]; - } - - // skip both - iCurL++; - iCurH++; - } - else if ( TopVar == bSLcur->index ) - { // the components cannot be equal - // skip the top-most one - *pLastDiffL = pL->pDecs[iCurL++]; - } - else // if ( TopVar == bSHcur->index ) - { // the components cannot be equal - // skip the top-most one - *pLastDiffH = pH->pDecs[iCurH++]; - } - } - - // if one of the lists still has components, write the first one down - if ( iCurL < pL->nDecs ) - *pLastDiffL = pL->pDecs[iCurL]; - - if ( iCurH < pH->nDecs ) - *pLastDiffH = pH->pDecs[iCurH]; - - // return the pointer to the array - *pCommon = Common; - // return the number of common components - return nCommon; -} - -/**Function************************************************************* - - Synopsis [Computes the sum (OR or EXOR) of the functions of the components.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor ) -{ - DdManager * dd = pDsdMan->dd; - DdNode * bF, * bS, * bFadd, * bTemp; - Dsd_Node_t * pDE, * pDER; - int i; - - // start the function - bF = b0; Cudd_Ref( bF ); - // start the support - if ( pCompS ) - bS = b1, Cudd_Ref( bS ); - - assert( nCommon > 0 ); - for ( i = 0; i < nCommon; i++ ) - { - pDE = pCommon[i]; - pDER = Dsd_Regular( pDE ); - bFadd = (pDE != pDER)? Cudd_Not(pDER->G): pDER->G; - // add to the function - if ( fExor ) - bF = Cudd_bddXor( dd, bTemp = bF, bFadd ); - else - bF = Cudd_bddOr( dd, bTemp = bF, bFadd ); - Cudd_Ref( bF ); - Cudd_RecursiveDeref( dd, bTemp ); - if ( pCompS ) - { - // add to the support - bS = Cudd_bddAnd( dd, bTemp = bS, pDER->S ); Cudd_Ref( bS ); - Cudd_RecursiveDeref( dd, bTemp ); - } - } - // return the function - Cudd_Deref( bF ); - *pCompF = bF; - - // return the support - if ( pCompS ) - Cudd_Deref( bS ), *pCompS = bS; -} - -/**Function************************************************************* - - Synopsis [Checks support containment of the decomposition components.] - - Description [This function returns 1 if support of one component is contained - in that of another. In this case, pLarge (pSmall) is assigned to point to the - larger (smaller) support. If the supports are identical return 0, and does not - assign the components.] -] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall ) -{ - DdManager * dd = pDsdMan->dd; - DdNode * bSuppLarge, * bSuppSmall; - int RetValue; - - RetValue = Extra_bddSuppCheckContainment( dd, pL->S, pH->S, &bSuppLarge, &bSuppSmall ); - - if ( RetValue == 0 ) - return 0; - - if ( pH->S == bSuppLarge ) - { - *pLarge = pH; - *pSmall = pL; - } - else // if ( pL->S == bSuppLarge ) - { - *pLarge = pL; - *pSmall = pH; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Copies the list of components plus one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize ) -{ - int i; - assert( nListSize+1 == p->nDecs ); - p->pDecs[0] = First; - for( i = 0; i < nListSize; i++ ) - p->pDecs[i+1] = ppList[i]; -} - -/**Function************************************************************* - - Synopsis [Copies the list of components plus one, and skips one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int iSkipped ) -{ - int i, Counter; - assert( nListSize == p->nDecs ); - p->pDecs[0] = First; - for( i = 0, Counter = 1; i < nListSize; i++ ) - if ( i != iSkipped ) - p->pDecs[Counter++] = ppList[i]; -} - -/**Function************************************************************* - - Synopsis [Debugging procedure to compute the functionality of the decomposed structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE ) -{ - DdManager * dd = pDsdMan->dd; - Dsd_Node_t * pR = Dsd_Regular(pDE); - int fCompP = (int)( pDE != pR ); - int RetValue; - - DdNode * bRes; - if ( pR->Type == DSD_NODE_CONST1 ) - bRes = b1; - else if ( pR->Type == DSD_NODE_BUF ) - bRes = pR->G; - else if ( pR->Type == DSD_NODE_OR || pR->Type == DSD_NODE_EXOR ) - dsdKernelComputeSumOfComponents( pDsdMan, pR->pDecs, pR->nDecs, &bRes, NULL, (int)(pR->Type == DSD_NODE_EXOR) ); - else if ( pR->Type == DSD_NODE_PRIME ) - { - int i; - static DdNode * bGVars[MAXINPUTS]; - // transform the function of this block, so that it depended on inputs - // corresponding to the formal inputs - DdNode * bNewFunc = Dsd_TreeGetPrimeFunctionOld( dd, pR, 1 ); Cudd_Ref( bNewFunc ); - - // compose this function with the inputs - // create the elementary permutation - for ( i = 0; i < dd->size; i++ ) - bGVars[i] = dd->vars[i]; - - // assign functions to be composed - for ( i = 0; i < pR->nDecs; i++ ) - bGVars[dd->invperm[i]] = pR->pDecs[i]->G; - - // perform the composition - bRes = Cudd_bddVectorCompose( dd, bNewFunc, bGVars ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bNewFunc ); - - ///////////////////////////////////////////////////////// - RetValue = (int)( bRes == pR->G );//|| bRes == Cudd_Not(pR->G) ); - ///////////////////////////////////////////////////////// - Cudd_Deref( bRes ); - } - else - { - assert(0); - } - - Cudd_Ref( bRes ); - RetValue = (int)( bRes == pR->G );//|| bRes == Cudd_Not(pR->G) ); - Cudd_RecursiveDeref( dd, bRes ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdTree.c b/src/bdd/dsd/dsdTree.c deleted file mode 100644 index 2855d68d..00000000 --- a/src/bdd/dsd/dsdTree.c +++ /dev/null @@ -1,1068 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdTree.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Managing the decomposition tree.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdTree.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Dsd_TreeUnmark_rec( Dsd_Node_t * pNode ); -static void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur ); -static int Dsd_TreeCountNonTerminalNodes_rec( Dsd_Node_t * pNode ); -static int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode ); -static int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars ); -static void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes ); -static void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fCcmp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames ); -static void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter ); - -//////////////////////////////////////////////////////////////////////// -/// STATIC VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -static int s_DepthMax; -static int s_GateSizeMax; - -static int s_CounterBlocks; -static int s_CounterPos; -static int s_CounterNeg; -static int s_CounterNo; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Create the DSD node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * Dsd_TreeNodeCreate( int Type, int nDecs, int BlockNum ) -{ - // allocate memory for this node - Dsd_Node_t * p = (Dsd_Node_t *) malloc( sizeof(Dsd_Node_t) ); - memset( p, 0, sizeof(Dsd_Node_t) ); - p->Type = Type; // the type of this block - p->nDecs = nDecs; // the number of decompositions - if ( p->nDecs ) - { - p->pDecs = (Dsd_Node_t **) malloc( p->nDecs * sizeof(Dsd_Node_t *) ); - p->pDecs[0] = NULL; - } - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the DSD node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode ) -{ - if ( pNode->G ) Cudd_RecursiveDeref( dd, pNode->G ); - if ( pNode->S ) Cudd_RecursiveDeref( dd, pNode->S ); - FREE( pNode->pDecs ); - FREE( pNode ); -} - -/**Function************************************************************* - - Synopsis [Unmarks the decomposition tree.] - - Description [This function assumes that originally pNode->nVisits are - set to zero!] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeUnmark( Dsd_Manager_t * pDsdMan ) -{ - int i; - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Dsd_TreeUnmark_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); -} - - -/**Function************************************************************* - - Synopsis [Recursive unmarking.] - - Description [This function should be called with a non-complemented - pointer.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeUnmark_rec( Dsd_Node_t * pNode ) -{ - int i; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits > 0 ); - - if ( --pNode->nVisits ) // if this is not the last visit, return - return; - - // upon the last visit, go through the list of successors and call recursively - if ( pNode->Type != DSD_NODE_BUF && pNode->Type != DSD_NODE_CONST1 ) - for ( i = 0; i < pNode->nDecs; i++ ) - Dsd_TreeUnmark_rec( Dsd_Regular(pNode->pDecs[i]) ); -} - -/**Function************************************************************* - - Synopsis [Getting information about the node.] - - Description [This function computes the max depth and the max gate size - of the tree rooted at the node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeNodeGetInfo( Dsd_Manager_t * pDsdMan, int * DepthMax, int * GateSizeMax ) -{ - int i; - s_DepthMax = 0; - s_GateSizeMax = 0; - - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Dsd_TreeGetInfo_rec( Dsd_Regular( pDsdMan->pRoots[i] ), 0 ); - - if ( DepthMax ) - *DepthMax = s_DepthMax; - if ( GateSizeMax ) - *GateSizeMax = s_GateSizeMax; -} - -/**Function************************************************************* - - Synopsis [Getting information about the node.] - - Description [This function computes the max depth and the max gate size - of the tree rooted at the node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax ) -{ - s_DepthMax = 0; - s_GateSizeMax = 0; - - Dsd_TreeGetInfo_rec( Dsd_Regular(pNode), 0 ); - - if ( DepthMax ) - *DepthMax = s_DepthMax; - if ( GateSizeMax ) - *GateSizeMax = s_GateSizeMax; -} - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Dsd_TreeNodeGetInfo().] - - Description [pNode is the node, for the tree rooted in which we are - determining info. RankCur is the current rank to assign to the node. - fSetRank is the flag saying whether the rank will be written in the - node. s_DepthMax is the maximum depths of the tree. s_GateSizeMax is - the maximum gate size.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur ) -{ - int i; - int GateSize; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits >= 0 ); - - // we don't want the two-input gates to count for non-decomposable blocks - if ( pNode->Type == DSD_NODE_OR || - pNode->Type == DSD_NODE_EXOR ) - GateSize = 2; - else - GateSize = pNode->nDecs; - - // update the max size of the node - if ( s_GateSizeMax < GateSize ) - s_GateSizeMax = GateSize; - - if ( pNode->nDecs < 2 ) - return; - - // update the max rank - if ( s_DepthMax < RankCur+1 ) - s_DepthMax = RankCur+1; - - // call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Dsd_TreeGetInfo_rec( Dsd_Regular(pNode->pDecs[i]), RankCur+1 ); -} - -/**Function************************************************************* - - Synopsis [Counts AIG nodes needed to implement this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeGetAigCost_rec( Dsd_Node_t * pNode ) -{ - int i, Counter = 0; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits >= 0 ); - - if ( pNode->nDecs < 2 ) - return 0; - - // we don't want the two-input gates to count for non-decomposable blocks - if ( pNode->Type == DSD_NODE_OR ) - Counter += pNode->nDecs - 1; - else if ( pNode->Type == DSD_NODE_EXOR ) - Counter += 3*(pNode->nDecs - 1); - else if ( pNode->Type == DSD_NODE_PRIME && pNode->nDecs == 3 ) - Counter += 3; - - // call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Counter += Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode->pDecs[i]) ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts AIG nodes needed to implement this node.] - - Description [Assumes that the only primes of the DSD tree are MUXes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeGetAigCost( Dsd_Node_t * pNode ) -{ - return Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode) ); -} - -/**Function************************************************************* - - Synopsis [Counts non-terminal nodes of the DSD tree.] - - Description [Nonterminal nodes include all the nodes with the - support more than 1. These are OR, EXOR, and PRIME nodes. They - do not include the elementary variable nodes and the constant 1 - node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * pDsdMan ) -{ - int Counter, i; - Counter = 0; - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Counter += Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); - Dsd_TreeUnmark( pDsdMan ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot ) -{ - int Counter = 0; - - // go through the list of successors and call recursively - Counter = Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular(pRoot) ); - - Dsd_TreeUnmark_rec( Dsd_Regular(pRoot) ); - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Counts non-terminal nodes for one root.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountNonTerminalNodes_rec( Dsd_Node_t * pNode ) -{ - int i; - int Counter = 0; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits >= 0 ); - - if ( pNode->nVisits++ ) // if this is not the first visit, return zero - return 0; - - if ( pNode->nDecs <= 1 ) - return 0; - - // upon the first visit, go through the list of successors and call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Counter += Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular(pNode->pDecs[i]) ); - - return Counter + 1; -} - - -/**Function************************************************************* - - Synopsis [Counts prime nodes of the DSD tree.] - - Description [Prime nodes are nodes with the support more than 2, - that is not an OR or EXOR gate.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan ) -{ - int Counter, i; - Counter = 0; - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Counter += Dsd_TreeCountPrimeNodes_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); - Dsd_TreeUnmark( pDsdMan ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts prime nodes for one root.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot ) -{ - int Counter = 0; - - // go through the list of successors and call recursively - Counter = Dsd_TreeCountPrimeNodes_rec( Dsd_Regular(pRoot) ); - - Dsd_TreeUnmark_rec( Dsd_Regular(pRoot) ); - return Counter; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode ) -{ - int i; - int Counter = 0; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits >= 0 ); - - if ( pNode->nVisits++ ) // if this is not the first visit, return zero - return 0; - - if ( pNode->nDecs <= 1 ) - return 0; - - // upon the first visit, go through the list of successors and call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Counter += Dsd_TreeCountPrimeNodes_rec( Dsd_Regular(pNode->pDecs[i]) ); - - if ( pNode->Type == DSD_NODE_PRIME ) - Counter++; - - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Collects the decomposable vars on the PI side.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * pDsdMan, int * pVars ) -{ - int nVars; - - // set the vars collected to 0 - nVars = 0; - Dsd_TreeCollectDecomposableVars_rec( pDsdMan->dd, Dsd_Regular(pDsdMan->pRoots[0]), pVars, &nVars ); - // return the number of collected vars - return nVars; -} - -/**Function************************************************************* - - Synopsis [Implements the recursive part of Dsd_TreeCollectDecomposableVars().] - - Description [Adds decomposable variables as they are found to pVars and increments - nVars. Returns 1 if a non-dec node with more than 4 inputs was encountered - in the processed subtree. Returns 0, otherwise. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars ) -{ - int fSkipThisNode, i; - Dsd_Node_t * pTemp; - int fVerbose = 0; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - - if ( pNode->nDecs <= 1 ) - return 0; - - // go through the list of successors and call recursively - fSkipThisNode = 0; - for ( i = 0; i < pNode->nDecs; i++ ) - if ( Dsd_TreeCollectDecomposableVars_rec(dd, Dsd_Regular(pNode->pDecs[i]), pVars, nVars) ) - fSkipThisNode = 1; - - if ( !fSkipThisNode && (pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR || pNode->nDecs <= 4) ) - { -if ( fVerbose ) -printf( "Node of type <%d> (OR=6,EXOR=8,RAND=1): ", pNode->Type ); - - for ( i = 0; i < pNode->nDecs; i++ ) - { - pTemp = Dsd_Regular(pNode->pDecs[i]); - if ( pTemp->Type == DSD_NODE_BUF ) - { - if ( pVars ) - pVars[ (*nVars)++ ] = pTemp->S->index; - else - (*nVars)++; - -if ( fVerbose ) -printf( "%d ", pTemp->S->index ); - } - } -if ( fVerbose ) -printf( "\n" ); - } - else - fSkipThisNode = 1; - - - return fSkipThisNode; -} - - -/**Function************************************************************* - - Synopsis [Creates the DFS ordered array of DSD nodes in the tree.] - - Description [The collected nodes do not include the terminal nodes - and the constant 1 node. The array of nodes is returned. The number - of entries in the array is returned in the variale pnNodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * pDsdMan, int * pnNodes ) -{ - Dsd_Node_t ** ppNodes; - int nNodes, nNodesAlloc; - int i; - - nNodesAlloc = Dsd_TreeCountNonTerminalNodes(pDsdMan); - nNodes = 0; - ppNodes = ALLOC( Dsd_Node_t *, nNodesAlloc ); - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pDsdMan->pRoots[i]), ppNodes, &nNodes ); - Dsd_TreeUnmark( pDsdMan ); - assert( nNodesAlloc == nNodes ); - *pnNodes = nNodes; - return ppNodes; -} - -/**Function************************************************************* - - Synopsis [Creates the DFS ordered array of DSD nodes in the tree.] - - Description [The collected nodes do not include the terminal nodes - and the constant 1 node. The array of nodes is returned. The number - of entries in the array is returned in the variale pnNodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes ) -{ - Dsd_Node_t ** ppNodes; - int nNodes, nNodesAlloc; - nNodesAlloc = Dsd_TreeCountNonTerminalNodesOne(pNode); - nNodes = 0; - ppNodes = ALLOC( Dsd_Node_t *, nNodesAlloc ); - Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pNode), ppNodes, &nNodes ); - Dsd_TreeUnmark_rec(Dsd_Regular(pNode)); - assert( nNodesAlloc == nNodes ); - *pnNodes = nNodes; - return ppNodes; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes ) -{ - int i; - assert( pNode ); - assert( !Dsd_IsComplement(pNode) ); - assert( pNode->nVisits >= 0 ); - - if ( pNode->nVisits++ ) // if this is not the first visit, return zero - return; - if ( pNode->nDecs <= 1 ) - return; - - // upon the first visit, go through the list of successors and call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pNode->pDecs[i]), ppNodes, pnNodes ); - - ppNodes[ (*pnNodes)++ ] = pNode; -} - -/**Function************************************************************* - - Synopsis [Prints the decompostion tree into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * pDsdMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output ) -{ - Dsd_Node_t * pNode; - int SigCounter; - int i; - SigCounter = 1; - - if ( Output == -1 ) - { - for ( i = 0; i < pDsdMan->nRoots; i++ ) - { - pNode = Dsd_Regular( pDsdMan->pRoots[i] ); - Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[i]), pInputNames, pOutputNames[i], 0, &SigCounter, fShortNames ); - } - } - else - { - assert( Output >= 0 && Output < pDsdMan->nRoots ); - pNode = Dsd_Regular( pDsdMan->pRoots[Output] ); - Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[Output]), pInputNames, pOutputNames[Output], 0, &SigCounter, fShortNames ); - } -} - -/**Function************************************************************* - - Synopsis [Prints the decompostion tree into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames ) -{ - char Buffer[100]; - Dsd_Node_t * pInput; - int * pInputNums; - int fCompNew, i; - - assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 || - pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); - - Extra_PrintSymbols( pFile, ' ', nOffset, 0 ); - if ( !fComp ) - fprintf( pFile, "%s = ", pOutputName ); - else - fprintf( pFile, "NOT(%s) = ", pOutputName ); - pInputNums = ALLOC( int, pNode->nDecs ); - if ( pNode->Type == DSD_NODE_CONST1 ) - { - fprintf( pFile, " Constant 1.\n" ); - } - else if ( pNode->Type == DSD_NODE_BUF ) - { - if ( fShortNames ) - fprintf( pFile, "%d", 'a' + pNode->S->index ); - else - fprintf( pFile, "%s", pInputNames[pNode->S->index] ); - fprintf( pFile, "\n" ); - } - else if ( pNode->Type == DSD_NODE_PRIME ) - { - // print the line - fprintf( pFile, "PRIME(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - if ( i ) - fprintf( pFile, "," ); - if ( fCompNew ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - if ( fShortNames ) - fprintf( pFile, "%d", pInput->S->index ); - else - fprintf( pFile, "%s", pInputNames[pInput->S->index] ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, "<%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, ")" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); - } - } - else if ( pNode->Type == DSD_NODE_OR ) - { - // print the line - fprintf( pFile, "OR(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - if ( i ) - fprintf( pFile, "," ); - if ( fCompNew ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - if ( fShortNames ) - fprintf( pFile, "%c", 'a' + pInput->S->index ); - else - fprintf( pFile, "%s", pInputNames[pInput->S->index] ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, "<%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, ")" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); - } - } - else if ( pNode->Type == DSD_NODE_EXOR ) - { - // print the line - fprintf( pFile, "EXOR(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - if ( i ) - fprintf( pFile, "," ); - if ( fCompNew ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - if ( fShortNames ) - fprintf( pFile, "%c", 'a' + pInput->S->index ); - else - fprintf( pFile, "%s", pInputNames[pInput->S->index] ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, "<%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, ")" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); - } - } - free( pInputNums ); -} - -/**Function************************************************************* - - Synopsis [Prints the decompostion tree into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode ) -{ - Dsd_Node_t * pNodeR; - int SigCounter = 1; - pNodeR = Dsd_Regular(pNode); - Dsd_NodePrint_rec( pFile, pNodeR, pNodeR != pNode, "F", 0, &SigCounter ); -} - -/**Function************************************************************* - - Synopsis [Prints one node of the decomposition tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter ) -{ - char Buffer[100]; - Dsd_Node_t * pInput; - int * pInputNums; - int fCompNew, i; - - assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 || - pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); - - Extra_PrintSymbols( pFile, ' ', nOffset, 0 ); - if ( !fComp ) - fprintf( pFile, "%s = ", pOutputName ); - else - fprintf( pFile, "NOT(%s) = ", pOutputName ); - pInputNums = ALLOC( int, pNode->nDecs ); - if ( pNode->Type == DSD_NODE_CONST1 ) - { - fprintf( pFile, " Constant 1.\n" ); - } - else if ( pNode->Type == DSD_NODE_BUF ) - { - fprintf( pFile, " " ); - fprintf( pFile, "%c", 'a' + pNode->S->index ); - fprintf( pFile, "\n" ); - } - else if ( pNode->Type == DSD_NODE_PRIME ) - { - // print the line - fprintf( pFile, "PRIME(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - assert( fCompNew == 0 ); - if ( i ) - fprintf( pFile, "," ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - fprintf( pFile, " %c", 'a' + pInput->S->index ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, " <%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, "\'" ); - } - fprintf( pFile, " )\n" ); -/* - fprintf( pFile, " ) " ); - { - DdNode * bLocal; - bLocal = Dsd_TreeGetPrimeFunction( dd, pNodeDsd ); Cudd_Ref( bLocal ); - Extra_bddPrint( dd, bLocal ); - Cudd_RecursiveDeref( dd, bLocal ); - } -*/ - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); - } - } - else if ( pNode->Type == DSD_NODE_OR ) - { - // print the line - fprintf( pFile, "OR(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - if ( i ) - fprintf( pFile, "," ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - fprintf( pFile, " %c", 'a' + pInput->S->index ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, " <%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, "\'" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); - } - } - else if ( pNode->Type == DSD_NODE_EXOR ) - { - // print the line - fprintf( pFile, "EXOR(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - assert( fCompNew == 0 ); - if ( i ) - fprintf( pFile, "," ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - fprintf( pFile, " %c", 'a' + pInput->S->index ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, " <%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, "\'" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); - } - } - free( pInputNums ); -} - - -/**Function************************************************************* - - Synopsis [Retuns the function of one node of the decomposition tree.] - - Description [This is the old procedure. It is now superceded by the - procedure Dsd_TreeGetPrimeFunction() found in "dsdLocal.c".] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) -{ - DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; - int i; - int fAllBuffs = 1; - static int Permute[MAXINPUTS]; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->Type == DSD_NODE_PRIME ); - - // transform the function of this block to depend on inputs - // corresponding to the formal inputs - - // first, substitute those inputs that have some blocks associated with them - // second, remap the inputs to the top of the manager (then, it is easy to output them) - - // start the function - bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); - // go over all primary inputs - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pNode->pDecs[i]->Type != DSD_NODE_BUF ) // remap only if it is not the buffer - { - bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); - bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); - Cudd_RecursiveDeref( dd, bCube0 ); - - bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); - bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); - Cudd_RecursiveDeref( dd, bCube1 ); - - Cudd_RecursiveDeref( dd, bNewFunc ); - - // use the variable in the i-th level of the manager -// bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); - // use the first variale in the support of the component - bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); - Cudd_RecursiveDeref( dd, bCof0 ); - Cudd_RecursiveDeref( dd, bCof1 ); - } - - if ( fRemap ) - { - // remap the function to the top of the manager - // remap the function to the first variables of the manager - for ( i = 0; i < pNode->nDecs; i++ ) - // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; - Permute[ pNode->pDecs[i]->S->index ] = i; - - bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - Cudd_Deref( bNewFunc ); - return bNewFunc; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/module.make b/src/bdd/dsd/module.make deleted file mode 100644 index f5e6673d..00000000 --- a/src/bdd/dsd/module.make +++ /dev/null @@ -1,6 +0,0 @@ -SRC += src/bdd/dsd/dsdApi.c \ - src/bdd/dsd/dsdCheck.c \ - src/bdd/dsd/dsdLocal.c \ - src/bdd/dsd/dsdMan.c \ - src/bdd/dsd/dsdProc.c \ - src/bdd/dsd/dsdTree.c |