mirror of https://github.com/YosysHQ/abc.git
1068 lines
26 KiB
C
1068 lines
26 KiB
C
/**CFile***********************************************************************
|
|
|
|
FileName [zMaxMin.c]
|
|
|
|
PackageName [extra]
|
|
|
|
Synopsis [Experimental version of some ZDD operators.]
|
|
|
|
Description [External procedures included in this module:
|
|
<ul>
|
|
<li> Extra_zddMaximal();
|
|
<li> Extra_zddMinimal();
|
|
<li> Extra_zddMaxUnion();
|
|
<li> Extra_zddMinUnion();
|
|
<li> Extra_zddDotProduct();
|
|
<li> Extra_zddCrossProduct();
|
|
<li> Extra_zddMaxDotProduct();
|
|
</ul>
|
|
Internal procedures included in this module:
|
|
<ul>
|
|
<li> extraZddMaximal();
|
|
<li> extraZddMinimal();
|
|
<li> extraZddMaxUnion();
|
|
<li> extraZddMinUnion();
|
|
<li> extraZddDotProduct();
|
|
<li> extraZddCrossProduct();
|
|
<li> extraZddMaxDotProduct();
|
|
</ul>
|
|
StaTc procedures included in this module:
|
|
<ul>
|
|
</ul>
|
|
|
|
DotProduct and MaxDotProduct were introduced
|
|
by O.Coudert to solve problems arising in two-level planar routing
|
|
See O. Coudert, C.-J. R. Shi. Exact Multi-Layer Topological Planar
|
|
Routing. Proc. of IEEE Custom Integrated Circuit Conference '96,
|
|
pp. 179-182.
|
|
]
|
|
|
|
SeeAlso []
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Copyright []
|
|
|
|
ReviSon [$zMaxMin.c, v.1.2, November 26, 2000, alanmi $]
|
|
|
|
******************************************************************************/
|
|
|
|
#include "extraBdd.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Constant declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Stucture declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Type declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Variable declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Macro declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/**AutomaTcStart*************************************************************/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* StaTc Function prototypes */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/**AutomaTcEnd***************************************************************/
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of exported Functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the maximal of a set represented by its ZDD.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso [Extra_zddMinimal]
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
Extra_zddMaximal(
|
|
DdManager * dd,
|
|
DdNode * S)
|
|
{
|
|
DdNode *res;
|
|
do {
|
|
dd->reordered = 0;
|
|
res = extraZddMaximal(dd, S);
|
|
} while (dd->reordered == 1);
|
|
return(res);
|
|
|
|
} /* end of Extra_zddMaximal */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the minimal of a set represented by its ZDD.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso [Extra_zddMaximal]
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
Extra_zddMinimal(
|
|
DdManager * dd,
|
|
DdNode * S)
|
|
{
|
|
DdNode *res;
|
|
do {
|
|
dd->reordered = 0;
|
|
res = extraZddMinimal(dd, S);
|
|
} while (dd->reordered == 1);
|
|
return(res);
|
|
|
|
} /* end of Extra_zddMinimal */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the maximal of the union of two sets represented by ZDDs.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso [Extra_zddMaximal Extra_zddMimimal Extra_zddMinUnion]
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
Extra_zddMaxUnion(
|
|
DdManager * dd,
|
|
DdNode * S,
|
|
DdNode * T)
|
|
{
|
|
DdNode *res;
|
|
do {
|
|
dd->reordered = 0;
|
|
res = extraZddMaxUnion(dd, S, T);
|
|
} while (dd->reordered == 1);
|
|
return(res);
|
|
|
|
} /* end of Extra_zddMaxUnion */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the minimal of the union of two sets represented by ZDDs.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso [Extra_zddMaximal Extra_zddMimimal Extra_zddMaxUnion]
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
Extra_zddMinUnion(
|
|
DdManager * dd,
|
|
DdNode * S,
|
|
DdNode * T)
|
|
{
|
|
DdNode *res;
|
|
do {
|
|
dd->reordered = 0;
|
|
res = extraZddMinUnion(dd, S, T);
|
|
} while (dd->reordered == 1);
|
|
return(res);
|
|
|
|
} /* end of Extra_zddMinUnion */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the dot product of two sets of subsets represented by ZDDs.]
|
|
|
|
Description [The dot product is defined as a set of pair-wise unions of subsets
|
|
belonging to the arguments.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso [Extra_zddCrossProduct]
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
Extra_zddDotProduct(
|
|
DdManager * dd,
|
|
DdNode * S,
|
|
DdNode * T)
|
|
{
|
|
DdNode *res;
|
|
do {
|
|
dd->reordered = 0;
|
|
res = extraZddDotProduct(dd, S, T);
|
|
} while (dd->reordered == 1);
|
|
return(res);
|
|
|
|
} /* end of Extra_zddDotProduct */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the cross product of two sets of subsets represented by ZDDs.]
|
|
|
|
Description [The cross product is defined as a set of pair-wise intersections of subsets
|
|
belonging to the arguments.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso [Extra_zddDotProduct]
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
Extra_zddCrossProduct(
|
|
DdManager * dd,
|
|
DdNode * S,
|
|
DdNode * T)
|
|
{
|
|
DdNode *res;
|
|
do {
|
|
dd->reordered = 0;
|
|
res = extraZddCrossProduct(dd, S, T);
|
|
} while (dd->reordered == 1);
|
|
return(res);
|
|
|
|
} /* end of Extra_zddCrossProduct */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the maximal of the DotProduct of the union of two sets represented by ZDDs.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso [Extra_zddDotProduct Extra_zddMaximal Extra_zddMinCrossProduct]
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
Extra_zddMaxDotProduct(
|
|
DdManager * dd,
|
|
DdNode * S,
|
|
DdNode * T)
|
|
{
|
|
DdNode *res;
|
|
do {
|
|
dd->reordered = 0;
|
|
res = extraZddMaxDotProduct(dd, S, T);
|
|
} while (dd->reordered == 1);
|
|
return(res);
|
|
|
|
} /* end of Extra_zddMaxDotProduct */
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of internal Functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Performs the recursive step of Extra_zddMaximal.]
|
|
|
|
Description []
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
extraZddMaximal(
|
|
DdManager * dd,
|
|
DdNode * zSet)
|
|
{
|
|
DdNode *zRes;
|
|
statLine(dd);
|
|
|
|
/* consider terminal cases */
|
|
if ( zSet == z0 || zSet == z1 )
|
|
return zSet;
|
|
|
|
/* check cache */
|
|
zRes = cuddCacheLookup1Zdd(dd, extraZddMaximal, zSet);
|
|
if (zRes)
|
|
return(zRes);
|
|
else
|
|
{
|
|
DdNode *zSet0, *zSet1, *zRes0, *zRes1;
|
|
|
|
/* compute maximal for subsets without the top-most element */
|
|
zSet0 = extraZddMaximal(dd, cuddE(zSet));
|
|
if ( zSet0 == NULL )
|
|
return NULL;
|
|
cuddRef( zSet0 );
|
|
|
|
/* compute maximal for subsets with the top-most element */
|
|
zSet1 = extraZddMaximal(dd, cuddT(zSet));
|
|
if ( zSet1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
return NULL;
|
|
}
|
|
cuddRef( zSet1 );
|
|
|
|
/* remove subsets without this element covered by subsets with this element */
|
|
zRes0 = extraZddNotSubSet(dd, zSet0, zSet1);
|
|
if ( zRes0 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes0 );
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
|
|
/* subset with this element remains unchanged */
|
|
zRes1 = zSet1;
|
|
|
|
/* create the new node */
|
|
zRes = cuddZddGetNode( dd, zSet->index, zRes1, zRes0 );
|
|
if ( zRes == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd( dd, zRes0 );
|
|
Cudd_RecursiveDerefZdd( dd, zRes1 );
|
|
return NULL;
|
|
}
|
|
cuddDeref( zRes0 );
|
|
cuddDeref( zRes1 );
|
|
|
|
/* insert the result into cache */
|
|
cuddCacheInsert1(dd, extraZddMaximal, zSet, zRes);
|
|
return zRes;
|
|
}
|
|
} /* end of extraZddMaximal */
|
|
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Performs the recursive step of Extra_zddMinimal.]
|
|
|
|
Description []
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
extraZddMinimal(
|
|
DdManager * dd,
|
|
DdNode * zSet)
|
|
{
|
|
DdNode *zRes;
|
|
statLine(dd);
|
|
|
|
/* consider terminal cases */
|
|
if ( zSet == z0 )
|
|
return zSet;
|
|
/* the empty combinaTon, if present, is the only minimal combinaTon */
|
|
if ( Extra_zddEmptyBelongs(dd, zSet) )
|
|
return z1;
|
|
|
|
/* check cache */
|
|
zRes = cuddCacheLookup1Zdd(dd, extraZddMinimal, zSet);
|
|
if (zRes)
|
|
return(zRes);
|
|
else
|
|
{
|
|
DdNode *zSet0, *zSet1, *zRes0, *zRes1;
|
|
|
|
/* compute minimal for subsets without the top-most element */
|
|
zSet0 = extraZddMinimal(dd, cuddE(zSet));
|
|
if ( zSet0 == NULL )
|
|
return NULL;
|
|
cuddRef( zSet0 );
|
|
|
|
/* compute minimal for subsets with the top-most element */
|
|
zSet1 = extraZddMinimal(dd, cuddT(zSet));
|
|
if ( zSet1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
return NULL;
|
|
}
|
|
cuddRef( zSet1 );
|
|
|
|
/* subset without this element remains unchanged */
|
|
zRes0 = zSet0;
|
|
|
|
/* remove subsets with this element that contain subsets without this element */
|
|
zRes1 = extraZddNotSupSet(dd, zSet1, zSet0);
|
|
if ( zRes1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes1 );
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
|
|
/* create the new node */
|
|
zRes = cuddZddGetNode( dd, zSet->index, zRes1, zRes0 );
|
|
if ( zRes == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd( dd, zRes0 );
|
|
Cudd_RecursiveDerefZdd( dd, zRes1 );
|
|
return NULL;
|
|
}
|
|
cuddDeref( zRes0 );
|
|
cuddDeref( zRes1 );
|
|
|
|
/* insert the result into cache */
|
|
cuddCacheInsert1(dd, extraZddMinimal, zSet, zRes);
|
|
return zRes;
|
|
}
|
|
} /* end of extraZddMinimal */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Performs the recursive step of Extra_zddMaxUnion.]
|
|
|
|
Description []
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
extraZddMaxUnion(
|
|
DdManager * dd,
|
|
DdNode * S,
|
|
DdNode * T)
|
|
{
|
|
DdNode *zRes;
|
|
int TopS, TopT;
|
|
statLine(dd);
|
|
|
|
/* consider terminal cases */
|
|
if ( S == z0 )
|
|
return T;
|
|
if ( T == z0 )
|
|
return S;
|
|
if ( S == T )
|
|
return S;
|
|
if ( S == z1 )
|
|
return T;
|
|
if ( T == z1 )
|
|
return S;
|
|
|
|
/* the operation is commutative - normalize the problem */
|
|
TopS = dd->permZ[S->index];
|
|
TopT = dd->permZ[T->index];
|
|
|
|
if ( TopS > TopT || (TopS == TopT && (unsigned)S > (unsigned)T) )
|
|
return extraZddMaxUnion(dd, T, S);
|
|
|
|
/* check cache */
|
|
zRes = cuddCacheLookup2Zdd(dd, extraZddMaxUnion, S, T);
|
|
if (zRes)
|
|
return zRes;
|
|
else
|
|
{
|
|
DdNode *zSet0, *zSet1, *zRes0, *zRes1;
|
|
|
|
if ( TopS == TopT )
|
|
{
|
|
/* compute maximal for subsets without the top-most element */
|
|
zSet0 = extraZddMaxUnion(dd, cuddE(S), cuddE(T) );
|
|
if ( zSet0 == NULL )
|
|
return NULL;
|
|
cuddRef( zSet0 );
|
|
|
|
/* compute maximal for subsets with the top-most element */
|
|
zSet1 = extraZddMaxUnion(dd, cuddT(S), cuddT(T) );
|
|
if ( zSet1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
return NULL;
|
|
}
|
|
cuddRef( zSet1 );
|
|
}
|
|
else /* if ( TopS < TopT ) */
|
|
{
|
|
/* compute maximal for subsets without the top-most element */
|
|
zSet0 = extraZddMaxUnion(dd, cuddE(S), T );
|
|
if ( zSet0 == NULL )
|
|
return NULL;
|
|
cuddRef( zSet0 );
|
|
|
|
/* subset with this element is just the cofactor of S */
|
|
zSet1 = cuddT(S);
|
|
cuddRef( zSet1 );
|
|
}
|
|
|
|
/* remove subsets without this element covered by subsets with this element */
|
|
zRes0 = extraZddNotSubSet(dd, zSet0, zSet1);
|
|
if ( zRes0 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes0 );
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
|
|
/* subset with this element remains unchanged */
|
|
zRes1 = zSet1;
|
|
|
|
/* create the new node */
|
|
zRes = cuddZddGetNode( dd, S->index, zRes1, zRes0 );
|
|
if ( zRes == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd( dd, zRes0 );
|
|
Cudd_RecursiveDerefZdd( dd, zRes1 );
|
|
return NULL;
|
|
}
|
|
cuddDeref( zRes0 );
|
|
cuddDeref( zRes1 );
|
|
|
|
/* insert the result into cache */
|
|
cuddCacheInsert2(dd, extraZddMaxUnion, S, T, zRes);
|
|
return zRes;
|
|
}
|
|
} /* end of extraZddMaxUnion */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Performs the recursive step of Extra_zddMinUnion.]
|
|
|
|
Description []
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
extraZddMinUnion(
|
|
DdManager * dd,
|
|
DdNode * S,
|
|
DdNode * T)
|
|
{
|
|
DdNode *zRes;
|
|
int TopS, TopT;
|
|
statLine(dd);
|
|
|
|
/* consider terminal cases */
|
|
if ( S == z0 )
|
|
return T;
|
|
if ( T == z0 )
|
|
return S;
|
|
if ( S == T )
|
|
return S;
|
|
/* the empty combination, if present, is the only minimal combination */
|
|
if ( Extra_zddEmptyBelongs(dd, S) || Extra_zddEmptyBelongs(dd, T) )
|
|
return z1;
|
|
|
|
/* the operation is commutative - normalize the problem */
|
|
TopS = dd->permZ[S->index];
|
|
TopT = dd->permZ[T->index];
|
|
|
|
if ( TopS > TopT || (TopS == TopT && (unsigned)S > (unsigned)T) )
|
|
return extraZddMinUnion(dd, T, S);
|
|
|
|
/* check cache */
|
|
zRes = cuddCacheLookup2Zdd(dd, extraZddMinUnion, S, T);
|
|
if (zRes)
|
|
return(zRes);
|
|
else
|
|
{
|
|
DdNode *zSet0, *zSet1, *zRes0, *zRes1;
|
|
if ( TopS == TopT )
|
|
{
|
|
/* compute maximal for subsets without the top-most element */
|
|
zSet0 = extraZddMinUnion(dd, cuddE(S), cuddE(T) );
|
|
if ( zSet0 == NULL )
|
|
return NULL;
|
|
cuddRef( zSet0 );
|
|
|
|
/* compute maximal for subsets with the top-most element */
|
|
zSet1 = extraZddMinUnion(dd, cuddT(S), cuddT(T) );
|
|
if ( zSet1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
return NULL;
|
|
}
|
|
cuddRef( zSet1 );
|
|
}
|
|
else /* if ( TopS < TopT ) */
|
|
{
|
|
/* compute maximal for subsets without the top-most element */
|
|
zSet0 = extraZddMinUnion(dd, cuddE(S), T );
|
|
if ( zSet0 == NULL )
|
|
return NULL;
|
|
cuddRef( zSet0 );
|
|
|
|
/* subset with this element is just the cofactor of S */
|
|
zSet1 = cuddT(S);
|
|
cuddRef( zSet1 );
|
|
}
|
|
|
|
/* subset without this element remains unchanged */
|
|
zRes0 = zSet0;
|
|
|
|
/* remove subsets with this element that contain subsets without this element */
|
|
zRes1 = extraZddNotSupSet(dd, zSet1, zSet0);
|
|
if ( zRes1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes1 );
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
|
|
/* create the new node */
|
|
zRes = cuddZddGetNode( dd, S->index, zRes1, zRes0 );
|
|
if ( zRes == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd( dd, zRes0 );
|
|
Cudd_RecursiveDerefZdd( dd, zRes1 );
|
|
return NULL;
|
|
}
|
|
cuddDeref( zRes0 );
|
|
cuddDeref( zRes1 );
|
|
|
|
/* insert the result into cache */
|
|
cuddCacheInsert2(dd, extraZddMinUnion, S, T, zRes);
|
|
return zRes;
|
|
}
|
|
} /* end of extraZddMinUnion */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Performs the recursive step of Extra_zddDotProduct.]
|
|
|
|
Description []
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
extraZddDotProduct(
|
|
DdManager * dd,
|
|
DdNode * S,
|
|
DdNode * T)
|
|
{
|
|
DdNode *zRes;
|
|
int TopS, TopT;
|
|
statLine(dd);
|
|
|
|
/* consider terminal cases */
|
|
if ( S == z0 || T == z0 )
|
|
return z0;
|
|
if ( S == z1 )
|
|
return T;
|
|
if ( T == z1 )
|
|
return S;
|
|
|
|
/* the operation is commutative - normalize the problem */
|
|
TopS = dd->permZ[S->index];
|
|
TopT = dd->permZ[T->index];
|
|
|
|
if ( TopS > TopT || (TopS == TopT && (unsigned)S > (unsigned)T) )
|
|
return extraZddDotProduct(dd, T, S);
|
|
|
|
/* check cache */
|
|
zRes = cuddCacheLookup2Zdd(dd, extraZddDotProduct, S, T);
|
|
if (zRes)
|
|
return zRes;
|
|
else
|
|
{
|
|
DdNode *zSet0, *zSet1, *zRes0, *zRes1, *zTemp;
|
|
if ( TopS == TopT )
|
|
{
|
|
/* compute the union of two cofactors of T (T0+T1) */
|
|
zTemp = cuddZddUnion(dd, cuddE(T), cuddT(T) );
|
|
if ( zTemp == NULL )
|
|
return NULL;
|
|
cuddRef( zTemp );
|
|
|
|
/* compute DotProduct with the top element for subsets (S1, T0+T1) */
|
|
zSet0 = extraZddDotProduct(dd, cuddT(S), zTemp );
|
|
if ( zSet0 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zTemp);
|
|
return NULL;
|
|
}
|
|
cuddRef( zSet0 );
|
|
Cudd_RecursiveDerefZdd(dd, zTemp);
|
|
|
|
/* compute DotProduct with the top element for subsets (S0, T1) */
|
|
zSet1 = extraZddDotProduct(dd, cuddE(S), cuddT(T) );
|
|
if ( zSet1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
return NULL;
|
|
}
|
|
cuddRef( zSet1 );
|
|
|
|
/* compute the union of these two partial results (zSet0 + zSet1) */
|
|
zRes1 = cuddZddUnion(dd, zSet0, zSet1 );
|
|
if ( zRes1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes1 );
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
|
|
/* compute DotProduct for subsets without the top-most element */
|
|
zRes0 = extraZddDotProduct(dd, cuddE(S), cuddE(T) );
|
|
if ( zRes0 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zRes1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes0 );
|
|
}
|
|
else /* if ( TopS < TopT ) */
|
|
{
|
|
/* compute DotProduct with the top element for subsets (S1, T) */
|
|
zRes1 = extraZddDotProduct(dd, cuddT(S), T );
|
|
if ( zRes1 == NULL )
|
|
return NULL;
|
|
cuddRef( zRes1 );
|
|
|
|
/* compute DotProduct for subsets without the top-most element */
|
|
zRes0 = extraZddDotProduct(dd, cuddE(S), T );
|
|
if ( zRes0 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zRes1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes0 );
|
|
}
|
|
|
|
/* create the new node */
|
|
zRes = cuddZddGetNode( dd, S->index, zRes1, zRes0 );
|
|
if ( zRes == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd( dd, zRes0 );
|
|
Cudd_RecursiveDerefZdd( dd, zRes1 );
|
|
return NULL;
|
|
}
|
|
cuddDeref( zRes0 );
|
|
cuddDeref( zRes1 );
|
|
|
|
/* insert the result into cache */
|
|
cuddCacheInsert2(dd, extraZddDotProduct, S, T, zRes);
|
|
return zRes;
|
|
}
|
|
} /* end of extraZddDotProduct */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Performs the recursive step of Extra_zddCrossProduct.]
|
|
|
|
Description []
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
extraZddCrossProduct(
|
|
DdManager * dd,
|
|
DdNode * S,
|
|
DdNode * T)
|
|
{
|
|
DdNode *zRes;
|
|
int TopS, TopT;
|
|
statLine(dd);
|
|
|
|
/* consider terminal cases */
|
|
if ( S == z0 || T == z0 )
|
|
return z0;
|
|
if ( S == z1 || T == z1 )
|
|
return z1;
|
|
|
|
/* the operation is commutative - normalize the problem */
|
|
TopS = dd->permZ[S->index];
|
|
TopT = dd->permZ[T->index];
|
|
|
|
if ( TopS > TopT || (TopS == TopT && (unsigned)S > (unsigned)T) )
|
|
return extraZddCrossProduct(dd, T, S);
|
|
|
|
/* check cache */
|
|
zRes = cuddCacheLookup2Zdd(dd, extraZddCrossProduct, S, T);
|
|
if (zRes)
|
|
return zRes;
|
|
else
|
|
{
|
|
DdNode *zSet0, *zSet1, *zRes0, *zRes1, *zTemp;
|
|
|
|
if ( TopS == TopT )
|
|
{
|
|
/* compute the union of two cofactors of T (T0+T1) */
|
|
zTemp = cuddZddUnion(dd, cuddE(T), cuddT(T) );
|
|
if ( zTemp == NULL )
|
|
return NULL;
|
|
cuddRef( zTemp );
|
|
|
|
/* compute CrossProduct without the top element for subsets (S0, T0+T1) */
|
|
zSet0 = extraZddCrossProduct(dd, cuddE(S), zTemp );
|
|
if ( zSet0 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zTemp);
|
|
return NULL;
|
|
}
|
|
cuddRef( zSet0 );
|
|
Cudd_RecursiveDerefZdd(dd, zTemp);
|
|
|
|
/* compute CrossProduct without the top element for subsets (S1, T0) */
|
|
zSet1 = extraZddCrossProduct(dd, cuddT(S), cuddE(T) );
|
|
if ( zSet1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
return NULL;
|
|
}
|
|
cuddRef( zSet1 );
|
|
|
|
/* compute the union of these two partial results (zSet0 + zSet1) */
|
|
zRes0 = cuddZddUnion(dd, zSet0, zSet1 );
|
|
if ( zRes0 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes0 );
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
|
|
/* compute CrossProduct for subsets with the top-most element */
|
|
zRes1 = extraZddCrossProduct(dd, cuddT(S), cuddT(T) );
|
|
if ( zRes1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zRes0);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes1 );
|
|
|
|
/* create the new node */
|
|
zRes = cuddZddGetNode( dd, S->index, zRes1, zRes0 );
|
|
if ( zRes == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd( dd, zRes0 );
|
|
Cudd_RecursiveDerefZdd( dd, zRes1 );
|
|
return NULL;
|
|
}
|
|
cuddDeref( zRes0 );
|
|
cuddDeref( zRes1 );
|
|
}
|
|
else /* if ( TopS < TopT ) */
|
|
{
|
|
/* compute CrossProduct without the top element (S0, T) */
|
|
zSet0 = extraZddCrossProduct(dd, cuddE(S), T );
|
|
if ( zSet0 == NULL )
|
|
return NULL;
|
|
cuddRef( zSet0 );
|
|
|
|
/* compute CrossProduct without the top element (S1, T) */
|
|
zSet1 = extraZddCrossProduct(dd, cuddT(S), T );
|
|
if ( zSet1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
return NULL;
|
|
}
|
|
cuddRef( zSet1 );
|
|
|
|
/* compute the union of these two partial results (zSet0 + zSet1) */
|
|
zRes = cuddZddUnion(dd, zSet0, zSet1 );
|
|
if ( zRes == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes );
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
cuddDeref( zRes );
|
|
}
|
|
|
|
/* insert the result into cache */
|
|
cuddCacheInsert2(dd, extraZddCrossProduct, S, T, zRes);
|
|
return zRes;
|
|
}
|
|
} /* end of extraZddCrossProduct */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Performs the recursive step of Extra_zddMaxDotProduct.]
|
|
|
|
Description []
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
DdNode *
|
|
extraZddMaxDotProduct(
|
|
DdManager * dd,
|
|
DdNode * S,
|
|
DdNode * T)
|
|
{
|
|
DdNode *zRes;
|
|
int TopS, TopT;
|
|
statLine(dd);
|
|
|
|
/* consider terminal cases */
|
|
if ( S == z0 || T == z0 )
|
|
return z0;
|
|
if ( S == z1 )
|
|
return T;
|
|
if ( T == z1 )
|
|
return S;
|
|
|
|
/* the operation is commutative - normalize the problem */
|
|
TopS = dd->permZ[S->index];
|
|
TopT = dd->permZ[T->index];
|
|
|
|
if ( TopS > TopT || (TopS == TopT && (unsigned)S > (unsigned)T) )
|
|
return extraZddMaxDotProduct(dd, T, S);
|
|
|
|
/* check cache */
|
|
zRes = cuddCacheLookup2Zdd(dd, extraZddMaxDotProduct, S, T);
|
|
if (zRes)
|
|
return zRes;
|
|
else
|
|
{
|
|
DdNode *zSet0, *zSet1, *zRes0, *zRes1, *zTemp;
|
|
if ( TopS == TopT )
|
|
{
|
|
/* compute the union of two cofactors of T (T0+T1) */
|
|
zTemp = extraZddMaxUnion(dd, cuddE(T), cuddT(T) );
|
|
if ( zTemp == NULL )
|
|
return NULL;
|
|
cuddRef( zTemp );
|
|
|
|
/* compute MaxDotProduct with the top element for subsets (S1, T0+T1) */
|
|
zSet0 = extraZddMaxDotProduct(dd, cuddT(S), zTemp );
|
|
if ( zSet0 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zTemp);
|
|
return NULL;
|
|
}
|
|
cuddRef( zSet0 );
|
|
Cudd_RecursiveDerefZdd(dd, zTemp);
|
|
|
|
/* compute MaxDotProduct with the top element for subsets (S0, T1) */
|
|
zSet1 = extraZddMaxDotProduct(dd, cuddE(S), cuddT(T) );
|
|
if ( zSet1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
return NULL;
|
|
}
|
|
cuddRef( zSet1 );
|
|
|
|
/* compute the union of these two partial results (zSet0 + zSet1) */
|
|
zRes1 = extraZddMaxUnion(dd, zSet0, zSet1 );
|
|
if ( zRes1 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes1 );
|
|
Cudd_RecursiveDerefZdd(dd, zSet0);
|
|
Cudd_RecursiveDerefZdd(dd, zSet1);
|
|
|
|
/* compute MaxDotProduct for subsets without the top-most element */
|
|
zRes0 = extraZddMaxDotProduct(dd, cuddE(S), cuddE(T) );
|
|
if ( zRes0 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zRes1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes0 );
|
|
}
|
|
else /* if ( TopS < TopT ) */
|
|
{
|
|
/* compute MaxDotProduct with the top element for subsets (S1, T) */
|
|
zRes1 = extraZddMaxDotProduct(dd, cuddT(S), T );
|
|
if ( zRes1 == NULL )
|
|
return NULL;
|
|
cuddRef( zRes1 );
|
|
|
|
/* compute MaxDotProduct for subsets without the top-most element */
|
|
zRes0 = extraZddMaxDotProduct(dd, cuddE(S), T );
|
|
if ( zRes0 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zRes1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes0 );
|
|
}
|
|
|
|
/* remove subsets without this element covered by subsets with this element */
|
|
zRes0 = extraZddNotSubSet(dd, zTemp = zRes0, zRes1);
|
|
if ( zRes0 == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd(dd, zTemp);
|
|
Cudd_RecursiveDerefZdd(dd, zRes1);
|
|
return NULL;
|
|
}
|
|
cuddRef( zRes0 );
|
|
Cudd_RecursiveDerefZdd(dd, zTemp);
|
|
|
|
/* create the new node */
|
|
zRes = cuddZddGetNode( dd, S->index, zRes1, zRes0 );
|
|
if ( zRes == NULL )
|
|
{
|
|
Cudd_RecursiveDerefZdd( dd, zRes0 );
|
|
Cudd_RecursiveDerefZdd( dd, zRes1 );
|
|
return NULL;
|
|
}
|
|
cuddDeref( zRes0 );
|
|
cuddDeref( zRes1 );
|
|
|
|
/* insert the result into cache */
|
|
cuddCacheInsert2(dd, extraZddMaxDotProduct, S, T, zRes);
|
|
return zRes;
|
|
}
|
|
} /* end of extraZddMaxDotProduct */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of staTc Functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
ABC_NAMESPACE_IMPL_END
|