blob: 037e3202fb2c40dd11e24a0b39f8efad0629a36f [file] [log] [blame]
/**CFile****************************************************************
FileName [reoProfile.c]
PackageName [REO: A specialized DD reordering engine.]
Synopsis [Procudures that compute variables profiles (nodes, width, APL).]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - October 15, 2002.]
Revision [$Id: reoProfile.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]
***********************************************************************/
#include "reo.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function********************************************************************
Synopsis [Start the profile for the BDD nodes.]
Description [TopRef is the first level, on this the given node counts towards
the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)]
SideEffects []
SeeAlso []
******************************************************************************/
void reoProfileNodesStart( reo_man * p )
{
int Total, i;
Total = 0;
for ( i = 0; i <= p->nSupp; i++ )
{
p->pPlanes[i].statsCost = p->pPlanes[i].statsNodes;
Total += p->pPlanes[i].statsNodes;
}
assert( Total == p->nNodesCur );
p->nNodesBeg = p->nNodesCur;
}
/**Function*************************************************************
Synopsis [Start the profile for the APL.]
Description [Computes the total path length. The path length is normalized
by dividing it by 2^|supp(f)|. To get the "real" APL, multiply by 2^|supp(f)|.
This procedure assumes that Weight field of all nodes has been set to 0.0
before the call, except for the weight of the topmost node, which is set to 1.0
(1.0 is the probability of traversing the topmost node). This procedure
assigns the edge weights. Because of the equal probability of selecting 0 and 1
assignment at a node, the edge weights are the same for the node.
Instead of storing them, we store the weight of the node, which is the probability
of traversing the node (pUnit->Weight) during the top down evalation of the BDD. ]
SideEffects []
SeeAlso []
***********************************************************************/
void reoProfileAplStart( reo_man * p )
{
reo_unit * pER, * pTR;
reo_unit * pUnit;
double Res, Half;
int i;
// clean the weights of all nodes
for ( i = 0; i < p->nSupp; i++ )
for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next )
pUnit->Weight = 0.0;
// to assign the node weights (the probability of visiting each node)
// we visit the node after visiting its predecessors
// set the probability of visits to the top nodes
for ( i = 0; i < p->nTops; i++ )
Unit_Regular(p->pTops[i])->Weight += 1.0;
// to compute the path length (the sum of products of edge weight by edge length)
// we visit the nodes in any order (the above order will do)
Res = 0.0;
for ( i = 0; i < p->nSupp; i++ )
{
p->pPlanes[i].statsCost = 0.0;
for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next )
{
pER = Unit_Regular(pUnit->pE);
pTR = Unit_Regular(pUnit->pT);
Half = 0.5 * pUnit->Weight;
pER->Weight += Half;
pTR->Weight += Half;
// add to the path length
p->pPlanes[i].statsCost += pUnit->Weight;
}
Res += p->pPlanes[i].statsCost;
}
p->pPlanes[p->nSupp].statsCost = 0.0;
p->nAplBeg = p->nAplCur = Res;
}
/**Function********************************************************************
Synopsis [Start the profile for the BDD width. Complexity of the algorithm is O(N + n).]
Description [TopRef is the first level, on which the given node counts towards
the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)]
SideEffects []
SeeAlso []
******************************************************************************/
void reoProfileWidthStart( reo_man * p )
{
reo_unit * pUnit;
int * pWidthStart;
int * pWidthStop;
int v;
// allocate and clean the storage for starting and stopping levels
pWidthStart = ABC_ALLOC( int, p->nSupp + 1 );
pWidthStop = ABC_ALLOC( int, p->nSupp + 1 );
memset( pWidthStart, 0, sizeof(int) * (p->nSupp + 1) );
memset( pWidthStop, 0, sizeof(int) * (p->nSupp + 1) );
// go through the non-constant nodes and set the topmost level of their cofactors
for ( v = 0; v <= p->nSupp; v++ )
for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next )
{
pUnit->TopRef = REO_TOPREF_UNDEF;
pUnit->Sign = 0;
}
// add the topmost level of the width profile
for ( v = 0; v < p->nTops; v++ )
{
pUnit = Unit_Regular(p->pTops[v]);
if ( pUnit->TopRef == REO_TOPREF_UNDEF )
{
// set the starting level
pUnit->TopRef = 0;
pWidthStart[pUnit->TopRef]++;
// set the stopping level
if ( pUnit->lev != REO_CONST_LEVEL )
pWidthStop[pUnit->lev+1]++;
}
}
for ( v = 0; v < p->nSupp; v++ )
for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next )
{
if ( pUnit->pE->TopRef == REO_TOPREF_UNDEF )
{
// set the starting level
pUnit->pE->TopRef = pUnit->lev + 1;
pWidthStart[pUnit->pE->TopRef]++;
// set the stopping level
if ( pUnit->pE->lev != REO_CONST_LEVEL )
pWidthStop[pUnit->pE->lev+1]++;
}
if ( pUnit->pT->TopRef == REO_TOPREF_UNDEF )
{
// set the starting level
pUnit->pT->TopRef = pUnit->lev + 1;
pWidthStart[pUnit->pT->TopRef]++;
// set the stopping level
if ( pUnit->pT->lev != REO_CONST_LEVEL )
pWidthStop[pUnit->pT->lev+1]++;
}
}
// verify the top reference
for ( v = 0; v < p->nSupp; v++ )
reoProfileWidthVerifyLevel( p->pPlanes + v, v );
// derive the profile
p->nWidthCur = 0;
for ( v = 0; v <= p->nSupp; v++ )
{
if ( v == 0 )
p->pPlanes[v].statsWidth = pWidthStart[v] - pWidthStop[v];
else
p->pPlanes[v].statsWidth = p->pPlanes[v-1].statsWidth + pWidthStart[v] - pWidthStop[v];
p->pPlanes[v].statsCost = p->pPlanes[v].statsWidth;
p->nWidthCur += p->pPlanes[v].statsWidth;
printf( "Level %2d: Width = %5d.\n", v, p->pPlanes[v].statsWidth );
}
p->nWidthBeg = p->nWidthCur;
ABC_FREE( pWidthStart );
ABC_FREE( pWidthStop );
}
/**Function********************************************************************
Synopsis [Start the profile for the BDD width. Complexity of the algorithm is O(N * n).]
Description [TopRef is the first level, on which the given node counts towards
the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)]
SideEffects []
SeeAlso []
******************************************************************************/
void reoProfileWidthStart2( reo_man * p )
{
reo_unit * pUnit;
int i, v;
// clean the profile
for ( i = 0; i <= p->nSupp; i++ )
p->pPlanes[i].statsWidth = 0;
// clean the node structures
for ( v = 0; v <= p->nSupp; v++ )
for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next )
{
pUnit->TopRef = REO_TOPREF_UNDEF;
pUnit->Sign = 0;
}
// set the topref to the topmost nodes
for ( i = 0; i < p->nTops; i++ )
Unit_Regular(p->pTops[i])->TopRef = 0;
// go through the non-constant nodes and set the topmost level of their cofactors
for ( i = 0; i < p->nSupp; i++ )
for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next )
{
if ( pUnit->pE->TopRef > i+1 )
pUnit->pE->TopRef = i+1;
if ( pUnit->pT->TopRef > i+1 )
pUnit->pT->TopRef = i+1;
}
// verify the top reference
for ( i = 0; i < p->nSupp; i++ )
reoProfileWidthVerifyLevel( p->pPlanes + i, i );
// compute the profile for the internal nodes
for ( i = 0; i < p->nSupp; i++ )
for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next )
for ( v = pUnit->TopRef; v <= pUnit->lev; v++ )
p->pPlanes[v].statsWidth++;
// compute the profile for the constant nodes
for ( pUnit = p->pPlanes[p->nSupp].pHead; pUnit; pUnit = pUnit->Next )
for ( v = pUnit->TopRef; v <= p->nSupp; v++ )
p->pPlanes[v].statsWidth++;
// get the width cost
p->nWidthCur = 0;
for ( i = 0; i <= p->nSupp; i++ )
{
p->pPlanes[i].statsCost = p->pPlanes[i].statsWidth;
p->nWidthCur += p->pPlanes[i].statsWidth;
}
p->nWidthBeg = p->nWidthCur;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void reoProfileNodesPrint( reo_man * p )
{
printf( "NODES: Total = %6d. Average = %6.2f.\n", p->nNodesCur, p->nNodesCur / (float)p->nSupp );
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void reoProfileAplPrint( reo_man * p )
{
printf( "APL: Total = %8.2f. Average =%6.2f.\n", p->nAplCur, p->nAplCur / (float)p->nSupp );
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void reoProfileWidthPrint( reo_man * p )
{
int WidthMax;
int TotalWidth;
int i;
WidthMax = 0;
TotalWidth = 0;
for ( i = 0; i <= p->nSupp; i++ )
{
printf( "Level = %2d. Width = %3d.\n", i, p->pPlanes[i].statsWidth );
if ( WidthMax < p->pPlanes[i].statsWidth )
WidthMax = p->pPlanes[i].statsWidth;
TotalWidth += p->pPlanes[i].statsWidth;
}
assert( p->nWidthCur == TotalWidth );
printf( "WIDTH: " );
printf( "Maximum = %5d. ", WidthMax );
printf( "Total = %7d. ", p->nWidthCur );
printf( "Average = %6.2f.\n", TotalWidth / (float)p->nSupp );
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void reoProfileWidthVerifyLevel( reo_plane * pPlane, int Level )
{
reo_unit * pUnit;
for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next )
{
assert( pUnit->TopRef <= Level );
assert( pUnit->pE->TopRef <= Level + 1 );
assert( pUnit->pT->TopRef <= Level + 1 );
}
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END