blob: 7e325597f6bcec9bee318c67b4482d9193fc3d9e [file] [log] [blame]
/**CFile****************************************************************
FileName [llb2Cluster.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [BDD based reachability.]
Synopsis [Non-linear quantification scheduling.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: llb2Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "llbInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Find good static variable ordering.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Llb_Nonlin4FindOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter )
{
Aig_Obj_t * pFanin0, * pFanin1;
if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
return;
Aig_ObjSetTravIdCurrent( pAig, pObj );
assert( Llb_ObjBddVar(vOrder, pObj) < 0 );
if ( Aig_ObjIsCi(pObj) )
{
Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
return;
}
// try fanins with higher level first
pFanin0 = Aig_ObjFanin0(pObj);
pFanin1 = Aig_ObjFanin1(pObj);
// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) )
if ( pFanin0->Level > pFanin1->Level )
{
Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter );
Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter );
}
else
{
Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter );
Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter );
}
if ( pObj->fMarkA )
Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
}
/**Function*************************************************************
Synopsis [Find good static variable ordering.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Llb_Nonlin4FindOrder( Aig_Man_t * pAig, int * pCounter )
{
Vec_Int_t * vNodes = NULL;
Vec_Int_t * vOrder;
Aig_Obj_t * pObj;
int i, Counter = 0;
// mark nodes to exclude: AND with low level and CO drivers
Aig_ManCleanMarkA( pAig );
Aig_ManForEachNode( pAig, pObj, i )
if ( Aig_ObjLevel(pObj) > 3 )
pObj->fMarkA = 1;
Aig_ManForEachCo( pAig, pObj, i )
Aig_ObjFanin0(pObj)->fMarkA = 0;
// collect nodes in the order
vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
Aig_ManIncrementTravId( pAig );
Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
// Aig_ManForEachCo( pAig, pObj, i )
Saig_ManForEachLi( pAig, pObj, i )
{
Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
Llb_Nonlin4FindOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter );
}
Aig_ManForEachCi( pAig, pObj, i )
if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
Aig_ManCleanMarkA( pAig );
Vec_IntFreeP( &vNodes );
// assert( Counter == Aig_ManObjNum(pAig) - 1 );
/*
Saig_ManForEachPi( pAig, pObj, i )
printf( "pi%d ", Llb_ObjBddVar(vOrder, pObj) );
printf( "\n" );
Saig_ManForEachLo( pAig, pObj, i )
printf( "lo%d ", Llb_ObjBddVar(vOrder, pObj) );
printf( "\n" );
Saig_ManForEachPo( pAig, pObj, i )
printf( "po%d ", Llb_ObjBddVar(vOrder, pObj) );
printf( "\n" );
Saig_ManForEachLi( pAig, pObj, i )
printf( "li%d ", Llb_ObjBddVar(vOrder, pObj) );
printf( "\n" );
Aig_ManForEachNode( pAig, pObj, i )
printf( "n%d ", Llb_ObjBddVar(vOrder, pObj) );
printf( "\n" );
*/
if ( pCounter )
*pCounter = Counter;
return vOrder;
}
/**Function*************************************************************
Synopsis [Derives BDDs for the partitions.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
DdNode * Llb_Nonlin4FindPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots )
{
DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar;
if ( Aig_ObjIsConst1(pObj) )
return Cudd_ReadOne(dd);
if ( Aig_ObjIsCi(pObj) )
return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
if ( pObj->pData )
return (DdNode *)pObj->pData;
if ( Aig_ObjIsCo(pObj) )
{
bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart );
Vec_PtrPush( vRoots, bPart );
return NULL;
}
bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
bBdd1 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) );
bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd );
if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
{
vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart );
Vec_PtrPush( vRoots, bPart );
Cudd_RecursiveDeref( dd, bBdd );
bBdd = vVar; Cudd_Ref( vVar );
}
pObj->pData = bBdd;
return bBdd;
}
/**Function*************************************************************
Synopsis [Derives BDDs for the partitions.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Llb_Nonlin4FindPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fOutputs )
{
Vec_Ptr_t * vRoots;
Aig_Obj_t * pObj;
int i;
Aig_ManCleanData( pAig );
vRoots = Vec_PtrAlloc( 100 );
if ( fOutputs )
{
Saig_ManForEachPo( pAig, pObj, i )
Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots );
}
else
{
Saig_ManForEachLi( pAig, pObj, i )
Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots );
}
Aig_ManForEachNode( pAig, pObj, i )
if ( pObj->pData )
Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
return vRoots;
}
/**Function*************************************************************
Synopsis [Creates quantifiable variables for both types of traversal.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Llb_Nonlin4FindVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
{
Vec_Int_t * vVars2Q;
Aig_Obj_t * pObj;
int i;
vVars2Q = Vec_IntAlloc( 0 );
Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 );
Saig_ManForEachLo( pAig, pObj, i )
Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
// Aig_ManForEachCo( pAig, pObj, i )
Saig_ManForEachLi( pAig, pObj, i )
Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
return vVars2Q;
}
/**Function*************************************************************
Synopsis [Creates quantifiable variables for both types of traversal.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Llb_Nonlin4CountTerms( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, DdNode * bFunc, int fCo, int fFlop )
{
DdNode * bSupp;
Aig_Obj_t * pObj;
int i, Counter = 0;
bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp );
if ( !fCo && !fFlop )
{
Saig_ManForEachPi( pAig, pObj, i )
if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
}
else if ( fCo && !fFlop )
{
Saig_ManForEachPo( pAig, pObj, i )
if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
}
else if ( !fCo && fFlop )
{
Saig_ManForEachLo( pAig, pObj, i )
if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
}
else if ( fCo && fFlop )
{
Saig_ManForEachLi( pAig, pObj, i )
if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
}
Cudd_RecursiveDeref( dd, bSupp );
return Counter;
}
/**Function*************************************************************
Synopsis [Creates quantifiable variables for both types of traversal.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Llb_Nonlin4PrintGroups( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups )
{
DdNode * bTemp;
int i, nSuppAll, nSuppPi, nSuppPo, nSuppLi, nSuppLo, nSuppAnd;
Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i )
{
//Extra_bddPrintSupport(dd, bTemp); printf("\n" );
nSuppAll = Cudd_SupportSize(dd,bTemp);
nSuppPi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 0);
nSuppPo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 0);
nSuppLi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 1);
nSuppLo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 1);
nSuppAnd = nSuppAll - (nSuppPi+nSuppPo+nSuppLi+nSuppLo);
if ( Cudd_DagSize(bTemp) <= 10 )
continue;
printf( "%4d : bdd =%6d supp =%3d ", i, Cudd_DagSize(bTemp), nSuppAll );
printf( "pi =%3d ", nSuppPi );
printf( "po =%3d ", nSuppPo );
printf( "lo =%3d ", nSuppLo );
printf( "li =%3d ", nSuppLi );
printf( "and =%3d", nSuppAnd );
printf( "\n" );
}
}
/**Function*************************************************************
Synopsis [Creates quantifiable variables for both types of traversal.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Llb_Nonlin4PrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups )
{
Aig_Obj_t * pObj;
int i, * pSupp;
int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0;
pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) );
Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp );
Aig_ManForEachObj( pAig, pObj, i )
{
if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
continue;
// remove variables that do not participate
if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 )
{
if ( Aig_ObjIsNode(pObj) )
Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 );
continue;
}
nSuppAll++;
if ( Saig_ObjIsPi(pAig, pObj) )
nSuppPi++;
else if ( Saig_ObjIsLo(pAig, pObj) )
nSuppLo++;
else if ( Saig_ObjIsPo(pAig, pObj) )
nSuppPo++;
else if ( Saig_ObjIsLi(pAig, pObj) )
nSuppLi++;
else
nSuppAnd++;
}
ABC_FREE( pSupp );
printf( "Groups =%3d ", Vec_PtrSize(vGroups) );
printf( "Variables: all =%4d ", nSuppAll );
printf( "pi =%4d ", nSuppPi );
printf( "po =%4d ", nSuppPo );
printf( "lo =%4d ", nSuppLo );
printf( "li =%4d ", nSuppLi );
printf( "and =%4d", nSuppAnd );
printf( "\n" );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose )
{
DdManager * dd;
Vec_Int_t * vOrder, * vVars2Q;
Vec_Ptr_t * vParts, * vGroups;
DdNode * bTemp;
int i, nVarNum;
// create the BDD manager
vOrder = Llb_Nonlin4FindOrder( pAig, &nVarNum );
dd = Cudd_Init( nVarNum, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
vVars2Q = Llb_Nonlin4FindVars2Q( dd, pAig, vOrder );
vParts = Llb_Nonlin4FindPartitions( dd, pAig, vOrder, 0 );
vGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddMax );
Vec_IntFree( vVars2Q );
Vec_PtrForEachEntry( DdNode *, vParts, bTemp, i )
Cudd_RecursiveDeref( dd, bTemp );
Vec_PtrFree( vParts );
// if ( fVerbose )
Llb_Nonlin4PrintSuppProfile( dd, pAig, vOrder, vGroups );
if ( fVerbose )
printf( "Before reordering\n" );
if ( fVerbose )
Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups );
// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
// printf( "After reordering\n" );
// Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups );
if ( pvOrder )
*pvOrder = vOrder;
else
Vec_IntFree( vOrder );
if ( pvGroups )
*pvGroups = vGroups;
else
{
Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i )
Cudd_RecursiveDeref( dd, bTemp );
Vec_PtrFree( vGroups );
}
if ( pdd )
*pdd = dd;
else
Extra_StopManager( dd );
// Cudd_Quit( dd );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END