blob: df8b5cf0a202af3aff5cb4b1fd2e7ad0dcc0abf0 [file] [log] [blame]
/**CFile****************************************************************
FileName [reoTransfer.c]
PackageName [REO: A specialized DD reordering engine.]
Synopsis [Transfering a DD from the CUDD manager into REO"s internal data structures and back.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - October 15, 2002.]
Revision [$Id: reoTransfer.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
***********************************************************************/
#include "reo.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Transfers the DD into the internal reordering data structure.]
Description [It is important that the hash table is lossless.]
SideEffects []
SeeAlso []
***********************************************************************/
reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F )
{
DdManager * dd = p->dd;
reo_unit * pUnit;
int HKey = -1; // Suppress "might be used uninitialized"
int fComp;
fComp = Cudd_IsComplement(F);
F = Cudd_Regular(F);
// check the hash-table
if ( F->ref != 1 )
{
// search cache - use linear probing
for ( HKey = hashKey2(p->Signature,F,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize )
if ( p->HTable[HKey].Arg1 == (reo_unit *)F )
{
pUnit = p->HTable[HKey].Arg2;
assert( pUnit );
// increment the edge counter
pUnit->n++;
return Unit_NotCond( pUnit, fComp );
}
}
// the entry in not found in the cache
// create a new entry
pUnit = reoUnitsGetNextUnit( p );
pUnit->n = 1;
if ( cuddIsConstant(F) )
{
pUnit->lev = REO_CONST_LEVEL;
pUnit->pE = (reo_unit*)(ABC_PTRUINT_T)(cuddV(F));
pUnit->pT = NULL;
// check if the diagram that is being reordering has complement edges
if ( F != dd->one )
p->fThisIsAdd = 1;
// insert the unit into the corresponding plane
reoUnitsAddUnitToPlane( &(p->pPlanes[p->nSupp]), pUnit ); // increments the unit counter
}
else
{
pUnit->lev = p->pMapToPlanes[F->index];
pUnit->pE = reoTransferNodesToUnits_rec( p, cuddE(F) );
pUnit->pT = reoTransferNodesToUnits_rec( p, cuddT(F) );
// insert the unit into the corresponding plane
reoUnitsAddUnitToPlane( &(p->pPlanes[pUnit->lev]), pUnit ); // increments the unit counter
}
// add to the hash table
if ( F->ref != 1 )
{
// the next free entry is already found - it is pointed to by HKey
// while we traversed the diagram, the hash entry to which HKey points,
// might have been used. Make sure that its signature is different.
for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize );
p->HTable[HKey].Sign = p->Signature;
p->HTable[HKey].Arg1 = (reo_unit *)F;
p->HTable[HKey].Arg2 = pUnit;
}
// increment the counter of nodes
p->nNodesCur++;
return Unit_NotCond( pUnit, fComp );
}
/**Function*************************************************************
Synopsis [Creates the DD from the internal reordering data structure.]
Description [It is important that the hash table is lossless.]
SideEffects []
SeeAlso []
***********************************************************************/
DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit )
{
DdManager * dd = p->dd;
DdNode * bRes, * E, * T;
int HKey = -1; // Suppress "might be used uninitialized"
int fComp;
fComp = Cudd_IsComplement(pUnit);
pUnit = Unit_Regular(pUnit);
// check the hash-table
if ( pUnit->n != 1 )
{
for ( HKey = hashKey2(p->Signature,pUnit,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize )
if ( p->HTable[HKey].Arg1 == pUnit )
{
bRes = (DdNode*) p->HTable[HKey].Arg2;
assert( bRes );
return Cudd_NotCond( bRes, fComp );
}
}
// treat the case of constants
if ( Unit_IsConstant(pUnit) )
{
bRes = cuddUniqueConst( dd, ((double)((int)(ABC_PTRUINT_T)(pUnit->pE))) );
cuddRef( bRes );
}
else
{
// split and recur on children of this node
E = reoTransferUnitsToNodes_rec( p, pUnit->pE );
if ( E == NULL )
return NULL;
cuddRef(E);
T = reoTransferUnitsToNodes_rec( p, pUnit->pT );
if ( T == NULL )
{
Cudd_RecursiveDeref(dd, E);
return NULL;
}
cuddRef(T);
// consider the case when Res0 and Res1 are the same node
assert( E != T );
assert( !Cudd_IsComplement(T) );
bRes = cuddUniqueInter( dd, p->pMapToDdVarsFinal[pUnit->lev], T, E );
if ( bRes == NULL )
{
Cudd_RecursiveDeref(dd,E);
Cudd_RecursiveDeref(dd,T);
return NULL;
}
cuddRef( bRes );
cuddDeref( E );
cuddDeref( T );
}
// do not keep the result if the ref count is only 1, since it will not be visited again
if ( pUnit->n != 1 )
{
// while we traversed the diagram, the hash entry to which HKey points,
// might have been used. Make sure that its signature is different.
for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize );
p->HTable[HKey].Sign = p->Signature;
p->HTable[HKey].Arg1 = pUnit;
p->HTable[HKey].Arg2 = (reo_unit *)bRes;
// add the DD to the referenced DD list in order to be able to store it in cache
p->pRefNodes[p->nRefNodes++] = bRes; Cudd_Ref( bRes );
// no need to do this, because the garbage collection will not take bRes away
// it is held by the diagram in the making
}
// increment the counter of nodes
p->nNodesCur++;
cuddDeref( bRes );
return Cudd_NotCond( bRes, fComp );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END