mirror of https://github.com/YosysHQ/abc.git
558 lines
16 KiB
C
558 lines
16 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [abcHaig.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Network and node package.]
|
|
|
|
Synopsis [Implements history AIG for combinational rewriting.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: abcHaig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "base/abc/abc.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Collects the nodes in the classes.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Ptr_t * Abc_NtkHaigCollectMembers( Hop_Man_t * p )
|
|
{
|
|
Vec_Ptr_t * vObjs;
|
|
Hop_Obj_t * pObj;
|
|
int i;
|
|
vObjs = Vec_PtrAlloc( 4098 );
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
|
|
{
|
|
if ( pObj->pData == NULL )
|
|
continue;
|
|
pObj->pData = Hop_ObjRepr( pObj );
|
|
Vec_PtrPush( vObjs, pObj );
|
|
}
|
|
return vObjs;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates classes.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Ptr_t * Abc_NtkHaigCreateClasses( Vec_Ptr_t * vMembers )
|
|
{
|
|
Vec_Ptr_t * vClasses;
|
|
Hop_Obj_t * pObj, * pRepr;
|
|
int i;
|
|
|
|
// count classes
|
|
vClasses = Vec_PtrAlloc( 4098 );
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i )
|
|
{
|
|
pRepr = (Hop_Obj_t *)pObj->pData;
|
|
assert( pRepr->pData == NULL );
|
|
if ( pRepr->fMarkA == 0 ) // new
|
|
{
|
|
pRepr->fMarkA = 1;
|
|
Vec_PtrPush( vClasses, pRepr );
|
|
}
|
|
}
|
|
|
|
// set representatives as representatives
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, vClasses, pObj, i )
|
|
{
|
|
pObj->fMarkA = 0;
|
|
pObj->pData = pObj;
|
|
}
|
|
|
|
// go through the members and update
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i )
|
|
{
|
|
pRepr = (Hop_Obj_t *)pObj->pData;
|
|
if ( ((Hop_Obj_t *)pRepr->pData)->Id > pObj->Id )
|
|
pRepr->pData = pObj;
|
|
}
|
|
|
|
// change representatives of the class
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i )
|
|
{
|
|
pRepr = (Hop_Obj_t *)pObj->pData;
|
|
pObj->pData = pRepr->pData;
|
|
assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id );
|
|
}
|
|
|
|
// update classes
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, vClasses, pObj, i )
|
|
{
|
|
pRepr = (Hop_Obj_t *)pObj->pData;
|
|
assert( pRepr->pData == pRepr );
|
|
// pRepr->pData = NULL;
|
|
Vec_PtrWriteEntry( vClasses, i, pRepr );
|
|
Vec_PtrPush( vMembers, pObj );
|
|
}
|
|
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i )
|
|
if ( pObj->pData == pObj )
|
|
pObj->pData = NULL;
|
|
|
|
/*
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i )
|
|
{
|
|
printf( "ObjId = %4d : ", pObj->Id );
|
|
if ( pObj->pData == NULL )
|
|
{
|
|
printf( "NULL" );
|
|
}
|
|
else
|
|
{
|
|
printf( "%4d", ((Hop_Obj_t *)pObj->pData)->Id );
|
|
assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id );
|
|
}
|
|
printf( "\n" );
|
|
}
|
|
*/
|
|
return vClasses;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Counts how many data members have non-trivial fanout.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NtkHaigCountFans( Hop_Man_t * p )
|
|
{
|
|
Hop_Obj_t * pObj;
|
|
int i, Counter = 0;
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
|
|
{
|
|
if ( pObj->pData == NULL )
|
|
continue;
|
|
if ( Hop_ObjRefs(pObj) > 0 )
|
|
Counter++;
|
|
}
|
|
printf( "The number of class members with fanouts = %5d.\n", Counter );
|
|
return Counter;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline Hop_Obj_t * Hop_ObjReprHop( Hop_Obj_t * pObj )
|
|
{
|
|
Hop_Obj_t * pRepr;
|
|
assert( pObj->pNext != NULL );
|
|
if ( pObj->pData == NULL )
|
|
return pObj->pNext;
|
|
pRepr = (Hop_Obj_t *)pObj->pData;
|
|
assert( pRepr->pData == pRepr );
|
|
return Hop_NotCond( pRepr->pNext, pObj->fPhase ^ pRepr->fPhase );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline Hop_Obj_t * Hop_ObjChild0Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin0(pObj)), Hop_ObjFaninC0(pObj) ); }
|
|
static inline Hop_Obj_t * Hop_ObjChild1Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin1(pObj)), Hop_ObjFaninC1(pObj) ); }
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Stops history AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Hop_Man_t * Abc_NtkHaigReconstruct( Hop_Man_t * p )
|
|
{
|
|
Hop_Man_t * pNew;
|
|
Hop_Obj_t * pObj;
|
|
int i, Counter = 0;
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
|
|
pObj->pNext = NULL;
|
|
// start the HOP package
|
|
pNew = Hop_ManStart();
|
|
pNew->vObjs = Vec_PtrAlloc( p->nCreated );
|
|
Vec_PtrPush( pNew->vObjs, Hop_ManConst1(pNew) );
|
|
// map the constant node
|
|
Hop_ManConst1(p)->pNext = Hop_ManConst1(pNew);
|
|
// map the CIs
|
|
Hop_ManForEachPi( p, pObj, i )
|
|
pObj->pNext = Hop_ObjCreatePi(pNew);
|
|
// map the internal nodes
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
|
|
{
|
|
if ( !Hop_ObjIsNode(pObj) )
|
|
continue;
|
|
pObj->pNext = Hop_And( pNew, Hop_ObjChild0Hop(pObj), Hop_ObjChild1Hop(pObj) );
|
|
// assert( !Hop_IsComplement(pObj->pNext) );
|
|
if ( Hop_ManConst1(pNew) == Hop_Regular(pObj->pNext) )
|
|
Counter++;
|
|
if ( pObj->pData ) // member of the class
|
|
Hop_Regular(pObj->pNext)->pData = Hop_Regular(((Hop_Obj_t *)pObj->pData)->pNext);
|
|
}
|
|
// printf( " Counter = %d.\n", Counter );
|
|
// transfer the POs
|
|
Hop_ManForEachPo( p, pObj, i )
|
|
Hop_ObjCreatePo( pNew, Hop_ObjChild0Hop(pObj) );
|
|
// check the new manager
|
|
if ( !Hop_ManCheck(pNew) )
|
|
{
|
|
printf( "Abc_NtkHaigReconstruct: Check for History AIG has failed.\n" );
|
|
Hop_ManStop(pNew);
|
|
return NULL;
|
|
}
|
|
return pNew;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns 1 if pOld is in the TFI of pNew.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NtkHaigCheckTfi_rec( Abc_Obj_t * pNode, Abc_Obj_t * pOld )
|
|
{
|
|
if ( pNode == NULL )
|
|
return 0;
|
|
if ( pNode == pOld )
|
|
return 1;
|
|
// check the trivial cases
|
|
if ( Abc_ObjIsCi(pNode) )
|
|
return 0;
|
|
assert( Abc_ObjIsNode(pNode) );
|
|
// if this node is already visited, skip
|
|
if ( Abc_NodeIsTravIdCurrent( pNode ) )
|
|
return 0;
|
|
// mark the node as visited
|
|
Abc_NodeSetTravIdCurrent( pNode );
|
|
// check the children
|
|
if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin0(pNode), pOld ) )
|
|
return 1;
|
|
if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin1(pNode), pOld ) )
|
|
return 1;
|
|
// check equivalent nodes
|
|
return Abc_NtkHaigCheckTfi_rec( (Abc_Obj_t *)pNode->pData, pOld );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns 1 if pOld is in the TFI of pNew.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NtkHaigCheckTfi( Abc_Ntk_t * pNtk, Abc_Obj_t * pOld, Abc_Obj_t * pNew )
|
|
{
|
|
assert( !Abc_ObjIsComplement(pOld) );
|
|
assert( !Abc_ObjIsComplement(pNew) );
|
|
Abc_NtkIncrementTravId(pNtk);
|
|
return Abc_NtkHaigCheckTfi_rec( pNew, pOld );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline Abc_Obj_t * Hop_ObjChild0Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin0(pObj)->pNext, Hop_ObjFaninC0(pObj) ); }
|
|
static inline Abc_Obj_t * Hop_ObjChild1Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin1(pObj)->pNext, Hop_ObjFaninC1(pObj) ); }
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Stops history AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Abc_Ntk_t * Abc_NtkHaigRecreateAig( Abc_Ntk_t * pNtk, Hop_Man_t * p )
|
|
{
|
|
Abc_Ntk_t * pNtkAig;
|
|
Abc_Obj_t * pObjOld, * pObjAbcThis, * pObjAbcRepr;
|
|
Hop_Obj_t * pObj;
|
|
int i;
|
|
assert( p->nCreated == Vec_PtrSize(p->vObjs) );
|
|
|
|
// start the new network
|
|
pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
|
|
|
|
// transfer new nodes to the PIs of HOP
|
|
Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig );
|
|
Hop_ManForEachPi( p, pObj, i )
|
|
pObj->pNext = (Hop_Obj_t *)Abc_NtkCi( pNtkAig, i );
|
|
|
|
// construct new nodes
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
|
|
{
|
|
if ( !Hop_ObjIsNode(pObj) )
|
|
continue;
|
|
pObj->pNext = (Hop_Obj_t *)Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) );
|
|
assert( !Hop_IsComplement(pObj->pNext) );
|
|
}
|
|
|
|
// set the COs
|
|
Abc_NtkForEachCo( pNtk, pObjOld, i )
|
|
Abc_ObjAddFanin( pObjOld->pCopy, Hop_ObjChild0Next(Hop_ManPo(p,i)) );
|
|
|
|
// construct choice nodes
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
|
|
{
|
|
// skip the node without choices
|
|
if ( pObj->pData == NULL )
|
|
continue;
|
|
// skip the representative of the class
|
|
if ( pObj->pData == pObj )
|
|
continue;
|
|
// do not create choices for constant 1 and PIs
|
|
if ( !Hop_ObjIsNode((Hop_Obj_t *)pObj->pData) )
|
|
continue;
|
|
// get the corresponding new nodes
|
|
pObjAbcThis = (Abc_Obj_t *)pObj->pNext;
|
|
pObjAbcRepr = (Abc_Obj_t *)((Hop_Obj_t *)pObj->pData)->pNext;
|
|
// the new node cannot be already in the class
|
|
assert( pObjAbcThis->pData == NULL );
|
|
// the new node cannot have fanouts
|
|
assert( Abc_ObjFanoutNum(pObjAbcThis) == 0 );
|
|
// these should be different nodes
|
|
assert( pObjAbcRepr != pObjAbcThis );
|
|
// do not create choices if there is a path from pObjAbcThis to pObjAbcRepr
|
|
if ( !Abc_NtkHaigCheckTfi( pNtkAig, pObjAbcRepr, pObjAbcThis ) )
|
|
{
|
|
// find the last node in the class
|
|
while ( pObjAbcRepr->pData )
|
|
pObjAbcRepr = (Abc_Obj_t *)pObjAbcRepr->pData;
|
|
// add the new node at the end of the list
|
|
pObjAbcRepr->pData = pObjAbcThis;
|
|
}
|
|
}
|
|
|
|
// finish the new network
|
|
// Abc_NtkFinalize( pNtk, pNtkAig );
|
|
// Abc_AigCleanup( pNtkAig->pManFunc );
|
|
// check correctness of the network
|
|
if ( !Abc_NtkCheck( pNtkAig ) )
|
|
{
|
|
printf( "Abc_NtkHaigUse: The network check has failed.\n" );
|
|
Abc_NtkDelete( pNtkAig );
|
|
return NULL;
|
|
}
|
|
return pNtkAig;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Resets representatives.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_NtkHaigResetReprsOld( Hop_Man_t * pMan )
|
|
{
|
|
Vec_Ptr_t * vMembers, * vClasses;
|
|
|
|
// collect members of the classes and make them point to reprs
|
|
vMembers = Abc_NtkHaigCollectMembers( pMan );
|
|
printf( "Collected %6d class members.\n", Vec_PtrSize(vMembers) );
|
|
|
|
// create classes
|
|
vClasses = Abc_NtkHaigCreateClasses( vMembers );
|
|
printf( "Collected %6d classes. (Ave = %5.2f)\n", Vec_PtrSize(vClasses),
|
|
(float)(Vec_PtrSize(vMembers))/Vec_PtrSize(vClasses) );
|
|
|
|
Vec_PtrFree( vMembers );
|
|
Vec_PtrFree( vClasses );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Resets representatives.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NtkHaigResetReprs( Hop_Man_t * p )
|
|
{
|
|
Hop_Obj_t * pObj, * pRepr;
|
|
int i, nClasses, nMembers, nFanouts, nNormals;
|
|
// clear self-classes
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
|
|
{
|
|
// fix the strange situation of double-loop
|
|
pRepr = (Hop_Obj_t *)pObj->pData;
|
|
if ( pRepr && pRepr->pData == pObj )
|
|
pRepr->pData = pRepr;
|
|
// remove self-loops
|
|
if ( pObj->pData == pObj )
|
|
pObj->pData = NULL;
|
|
}
|
|
// set representatives
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
|
|
{
|
|
if ( pObj->pData == NULL )
|
|
continue;
|
|
// get representative of the node
|
|
pRepr = Hop_ObjRepr( pObj );
|
|
pRepr->pData = pRepr;
|
|
// set the representative
|
|
pObj->pData = pRepr;
|
|
}
|
|
// make each class point to the smallest topological order
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
|
|
{
|
|
if ( pObj->pData == NULL )
|
|
continue;
|
|
pRepr = Hop_ObjRepr( pObj );
|
|
if ( pRepr->Id > pObj->Id )
|
|
{
|
|
pRepr->pData = pObj;
|
|
pObj->pData = pObj;
|
|
}
|
|
else
|
|
pObj->pData = pRepr;
|
|
}
|
|
// count classes, members, and fanouts - and verify
|
|
nMembers = nClasses = nFanouts = nNormals = 0;
|
|
Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i )
|
|
{
|
|
if ( pObj->pData == NULL )
|
|
continue;
|
|
// count members
|
|
nMembers++;
|
|
// count the classes and fanouts
|
|
if ( pObj->pData == pObj )
|
|
nClasses++;
|
|
else if ( Hop_ObjRefs(pObj) > 0 )
|
|
nFanouts++;
|
|
else
|
|
nNormals++;
|
|
// compare representatives
|
|
pRepr = Hop_ObjRepr( pObj );
|
|
assert( pObj->pData == pRepr );
|
|
assert( pRepr->Id <= pObj->Id );
|
|
}
|
|
// printf( "Nodes = %7d. Member = %7d. Classes = %6d. Fanouts = %6d. Normals = %6d.\n",
|
|
// Hop_ManNodeNum(p), nMembers, nClasses, nFanouts, nNormals );
|
|
return nFanouts;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Transform HOP manager into the one without loops.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan )
|
|
{
|
|
Abc_Ntk_t * pNtkAig;
|
|
Hop_Man_t * pManTemp;
|
|
|
|
// iteratively reconstruct the HOP manager to create choice nodes
|
|
while ( Abc_NtkHaigResetReprs( pMan ) )
|
|
{
|
|
pMan = Abc_NtkHaigReconstruct( pManTemp = pMan );
|
|
Hop_ManStop( pManTemp );
|
|
}
|
|
|
|
// traverse in the topological order and create new AIG
|
|
pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan );
|
|
Hop_ManStop( pMan );
|
|
return pNtkAig;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|