mirror of https://github.com/YosysHQ/abc.git
371 lines
12 KiB
C
371 lines
12 KiB
C
/**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
|
|
|