mirror of https://github.com/YosysHQ/abc.git
1006 lines
33 KiB
C
1006 lines
33 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [abcRr.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Network and node package.]
|
|
|
|
Synopsis [Redundancy removal.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: abcRr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "base/abc/abc.h"
|
|
#include "proof/fraig/fraig.h"
|
|
#include "opt/sim/sim.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef struct Abc_RRMan_t_ Abc_RRMan_t;
|
|
struct Abc_RRMan_t_
|
|
{
|
|
// the parameters
|
|
Abc_Ntk_t * pNtk; // the network
|
|
int nFaninLevels; // the number of fanin levels
|
|
int nFanoutLevels; // the number of fanout levels
|
|
// the node/fanin/fanout
|
|
Abc_Obj_t * pNode; // the node
|
|
Abc_Obj_t * pFanin; // the fanin
|
|
Abc_Obj_t * pFanout; // the fanout
|
|
// the intermediate cones
|
|
Vec_Ptr_t * vFaninLeaves; // the leaves of the fanin cone
|
|
Vec_Ptr_t * vFanoutRoots; // the roots of the fanout cone
|
|
// the window
|
|
Vec_Ptr_t * vLeaves; // the leaves of the window
|
|
Vec_Ptr_t * vCone; // the internal nodes of the window
|
|
Vec_Ptr_t * vRoots; // the roots of the window
|
|
Abc_Ntk_t * pWnd; // the window derived for the edge
|
|
// the miter
|
|
Abc_Ntk_t * pMiter; // the miter derived from the window
|
|
Prove_Params_t * pParams; // the miter proving parameters
|
|
// statistical variables
|
|
int nNodesOld; // the old number of nodes
|
|
int nLevelsOld; // the old number of levels
|
|
int nEdgesTried; // the number of nodes tried
|
|
int nEdgesRemoved; // the number of nodes proved
|
|
abctime timeWindow; // the time to construct the window
|
|
abctime timeMiter; // the time to construct the miter
|
|
abctime timeProve; // the time to prove the miter
|
|
abctime timeUpdate; // the network update time
|
|
abctime timeTotal; // the total runtime
|
|
};
|
|
|
|
static Abc_RRMan_t * Abc_RRManStart();
|
|
static void Abc_RRManStop( Abc_RRMan_t * p );
|
|
static void Abc_RRManPrintStats( Abc_RRMan_t * p );
|
|
static void Abc_RRManClean( Abc_RRMan_t * p );
|
|
static int Abc_NtkRRProve( Abc_RRMan_t * p );
|
|
static int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout );
|
|
static int Abc_NtkRRWindow( Abc_RRMan_t * p );
|
|
|
|
static int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit );
|
|
static int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout );
|
|
static int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit );
|
|
static void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit );
|
|
static Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots );
|
|
|
|
static void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk );
|
|
static void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk );
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Removes stuck-at redundancies.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose )
|
|
{
|
|
ProgressBar * pProgress;
|
|
Abc_RRMan_t * p;
|
|
Abc_Obj_t * pNode, * pFanin, * pFanout;
|
|
int i, k, m, nNodes, RetValue;
|
|
abctime clk, clkTotal = Abc_Clock();
|
|
// start the manager
|
|
p = Abc_RRManStart();
|
|
p->pNtk = pNtk;
|
|
p->nFaninLevels = nFaninLevels;
|
|
p->nFanoutLevels = nFanoutLevels;
|
|
p->nNodesOld = Abc_NtkNodeNum(pNtk);
|
|
p->nLevelsOld = Abc_AigLevel(pNtk);
|
|
// remember latch values
|
|
// Abc_NtkForEachLatch( pNtk, pNode, i )
|
|
// pNode->pNext = pNode->pData;
|
|
// go through the nodes
|
|
Abc_NtkCleanCopy(pNtk);
|
|
nNodes = Abc_NtkObjNumMax(pNtk);
|
|
Abc_NtkRRSimulateStart(pNtk);
|
|
pProgress = Extra_ProgressBarStart( stdout, nNodes );
|
|
Abc_NtkForEachNode( pNtk, pNode, i )
|
|
{
|
|
Extra_ProgressBarUpdate( pProgress, i, NULL );
|
|
// stop if all nodes have been tried once
|
|
if ( i >= nNodes )
|
|
break;
|
|
// skip the constant node
|
|
// if ( Abc_NodeIsConst(pNode) )
|
|
// continue;
|
|
// skip persistant nodes
|
|
if ( Abc_NodeIsPersistant(pNode) )
|
|
continue;
|
|
// skip the nodes with many fanouts
|
|
if ( Abc_ObjFanoutNum(pNode) > 1000 )
|
|
continue;
|
|
// construct the window
|
|
if ( !fUseFanouts )
|
|
{
|
|
Abc_ObjForEachFanin( pNode, pFanin, k )
|
|
{
|
|
// skip the nodes with only one fanout (tree nodes)
|
|
if ( Abc_ObjFanoutNum(pFanin) == 1 )
|
|
continue;
|
|
/*
|
|
if ( pFanin->Id == 228 && pNode->Id == 2649 )
|
|
{
|
|
int k = 0;
|
|
}
|
|
*/
|
|
p->nEdgesTried++;
|
|
Abc_RRManClean( p );
|
|
p->pNode = pNode;
|
|
p->pFanin = pFanin;
|
|
p->pFanout = NULL;
|
|
|
|
clk = Abc_Clock();
|
|
RetValue = Abc_NtkRRWindow( p );
|
|
p->timeWindow += Abc_Clock() - clk;
|
|
if ( !RetValue )
|
|
continue;
|
|
/*
|
|
if ( pFanin->Id == 228 && pNode->Id == 2649 )
|
|
{
|
|
Abc_NtkShowAig( p->pWnd, 0 );
|
|
}
|
|
*/
|
|
clk = Abc_Clock();
|
|
RetValue = Abc_NtkRRProve( p );
|
|
p->timeMiter += Abc_Clock() - clk;
|
|
if ( !RetValue )
|
|
continue;
|
|
//printf( "%d -> %d (%d)\n", pFanin->Id, pNode->Id, k );
|
|
|
|
clk = Abc_Clock();
|
|
Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout );
|
|
p->timeUpdate += Abc_Clock() - clk;
|
|
|
|
p->nEdgesRemoved++;
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
// use the fanouts
|
|
Abc_ObjForEachFanin( pNode, pFanin, k )
|
|
Abc_ObjForEachFanout( pNode, pFanout, m )
|
|
{
|
|
// skip the nodes with only one fanout (tree nodes)
|
|
// if ( Abc_ObjFanoutNum(pFanin) == 1 && Abc_ObjFanoutNum(pNode) == 1 )
|
|
// continue;
|
|
|
|
p->nEdgesTried++;
|
|
Abc_RRManClean( p );
|
|
p->pNode = pNode;
|
|
p->pFanin = pFanin;
|
|
p->pFanout = pFanout;
|
|
|
|
clk = Abc_Clock();
|
|
RetValue = Abc_NtkRRWindow( p );
|
|
p->timeWindow += Abc_Clock() - clk;
|
|
if ( !RetValue )
|
|
continue;
|
|
|
|
clk = Abc_Clock();
|
|
RetValue = Abc_NtkRRProve( p );
|
|
p->timeMiter += Abc_Clock() - clk;
|
|
if ( !RetValue )
|
|
continue;
|
|
|
|
clk = Abc_Clock();
|
|
Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout );
|
|
p->timeUpdate += Abc_Clock() - clk;
|
|
|
|
p->nEdgesRemoved++;
|
|
break;
|
|
}
|
|
}
|
|
Abc_NtkRRSimulateStop(pNtk);
|
|
Extra_ProgressBarStop( pProgress );
|
|
p->timeTotal = Abc_Clock() - clkTotal;
|
|
if ( fVerbose )
|
|
Abc_RRManPrintStats( p );
|
|
Abc_RRManStop( p );
|
|
// restore latch values
|
|
// Abc_NtkForEachLatch( pNtk, pNode, i )
|
|
// pNode->pData = pNode->pNext, pNode->pNext = NULL;
|
|
// put the nodes into the DFS order and reassign their IDs
|
|
Abc_NtkReassignIds( pNtk );
|
|
Abc_NtkLevel( pNtk );
|
|
// check
|
|
if ( !Abc_NtkCheck( pNtk ) )
|
|
{
|
|
printf( "Abc_NtkRR: The network check has failed.\n" );
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Start the manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Abc_RRMan_t * Abc_RRManStart()
|
|
{
|
|
Abc_RRMan_t * p;
|
|
p = ABC_ALLOC( Abc_RRMan_t, 1 );
|
|
memset( p, 0, sizeof(Abc_RRMan_t) );
|
|
p->vFaninLeaves = Vec_PtrAlloc( 100 ); // the leaves of the fanin cone
|
|
p->vFanoutRoots = Vec_PtrAlloc( 100 ); // the roots of the fanout cone
|
|
p->vLeaves = Vec_PtrAlloc( 100 ); // the leaves of the window
|
|
p->vCone = Vec_PtrAlloc( 100 ); // the internal nodes of the window
|
|
p->vRoots = Vec_PtrAlloc( 100 ); // the roots of the window
|
|
p->pParams = ABC_ALLOC( Prove_Params_t, 1 );
|
|
memset( p->pParams, 0, sizeof(Prove_Params_t) );
|
|
Prove_ParamsSetDefault( p->pParams );
|
|
return p;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Stop the manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_RRManStop( Abc_RRMan_t * p )
|
|
{
|
|
Abc_RRManClean( p );
|
|
Vec_PtrFree( p->vFaninLeaves );
|
|
Vec_PtrFree( p->vFanoutRoots );
|
|
Vec_PtrFree( p->vLeaves );
|
|
Vec_PtrFree( p->vCone );
|
|
Vec_PtrFree( p->vRoots );
|
|
ABC_FREE( p->pParams );
|
|
ABC_FREE( p );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Stop the manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_RRManPrintStats( Abc_RRMan_t * p )
|
|
{
|
|
double Ratio = 100.0*(p->nNodesOld - Abc_NtkNodeNum(p->pNtk))/p->nNodesOld;
|
|
printf( "Redundancy removal statistics:\n" );
|
|
printf( "Edges tried = %6d.\n", p->nEdgesTried );
|
|
printf( "Edges removed = %6d. (%5.2f %%)\n", p->nEdgesRemoved, 100.0*p->nEdgesRemoved/p->nEdgesTried );
|
|
printf( "Node gain = %6d. (%5.2f %%)\n", p->nNodesOld - Abc_NtkNodeNum(p->pNtk), Ratio );
|
|
printf( "Level gain = %6d.\n", p->nLevelsOld - Abc_AigLevel(p->pNtk) );
|
|
ABC_PRT( "Windowing ", p->timeWindow );
|
|
ABC_PRT( "Miter ", p->timeMiter );
|
|
ABC_PRT( " Construct ", p->timeMiter - p->timeProve );
|
|
ABC_PRT( " Prove ", p->timeProve );
|
|
ABC_PRT( "Update ", p->timeUpdate );
|
|
ABC_PRT( "TOTAL ", p->timeTotal );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Clean the manager.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_RRManClean( Abc_RRMan_t * p )
|
|
{
|
|
p->pNode = NULL;
|
|
p->pFanin = NULL;
|
|
p->pFanout = NULL;
|
|
Vec_PtrClear( p->vFaninLeaves );
|
|
Vec_PtrClear( p->vFanoutRoots );
|
|
Vec_PtrClear( p->vLeaves );
|
|
Vec_PtrClear( p->vCone );
|
|
Vec_PtrClear( p->vRoots );
|
|
if ( p->pWnd ) Abc_NtkDelete( p->pWnd );
|
|
if ( p->pMiter ) Abc_NtkDelete( p->pMiter );
|
|
p->pWnd = NULL;
|
|
p->pMiter = NULL;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns 1 if the miter is constant 0.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NtkRRProve( Abc_RRMan_t * p )
|
|
{
|
|
Abc_Ntk_t * pWndCopy;
|
|
int RetValue;
|
|
abctime clk;
|
|
// Abc_NtkShowAig( p->pWnd, 0 );
|
|
pWndCopy = Abc_NtkDup( p->pWnd );
|
|
Abc_NtkRRUpdate( pWndCopy, p->pNode->pCopy->pCopy, p->pFanin->pCopy->pCopy, p->pFanout? p->pFanout->pCopy->pCopy : NULL );
|
|
if ( !Abc_NtkIsDfsOrdered(pWndCopy) )
|
|
Abc_NtkReassignIds(pWndCopy);
|
|
p->pMiter = Abc_NtkMiter( p->pWnd, pWndCopy, 1, 0, 0, 0 );
|
|
Abc_NtkDelete( pWndCopy );
|
|
clk = Abc_Clock();
|
|
RetValue = Abc_NtkMiterProve( &p->pMiter, p->pParams );
|
|
p->timeProve += Abc_Clock() - clk;
|
|
if ( RetValue == 1 )
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Updates the network after redundancy removal.]
|
|
|
|
Description [This procedure assumes that non-control value of the fanin
|
|
was proved redundant. It is okay to concentrate on non-control values
|
|
because the control values can be seen as redundancy of the fanout edge.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout )
|
|
{
|
|
Abc_Obj_t * pNodeNew = NULL, * pFanoutNew = NULL;
|
|
assert( pFanout == NULL );
|
|
assert( !Abc_ObjIsComplement(pNode) );
|
|
assert( !Abc_ObjIsComplement(pFanin) );
|
|
assert( !Abc_ObjIsComplement(pFanout) );
|
|
// find the node after redundancy removal
|
|
if ( pFanin == Abc_ObjFanin0(pNode) )
|
|
pNodeNew = Abc_ObjChild1(pNode);
|
|
else if ( pFanin == Abc_ObjFanin1(pNode) )
|
|
pNodeNew = Abc_ObjChild0(pNode);
|
|
else assert( 0 );
|
|
// replace
|
|
if ( pFanout == NULL )
|
|
{
|
|
Abc_AigReplace( (Abc_Aig_t *)pNtk->pManFunc, pNode, pNodeNew, 1 );
|
|
return 1;
|
|
}
|
|
// find the fanout after redundancy removal
|
|
if ( pNode == Abc_ObjFanin0(pFanout) )
|
|
pFanoutNew = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC0(pFanout)), Abc_ObjChild1(pFanout) );
|
|
else if ( pNode == Abc_ObjFanin1(pFanout) )
|
|
pFanoutNew = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC1(pFanout)), Abc_ObjChild0(pFanout) );
|
|
else assert( 0 );
|
|
// replace
|
|
Abc_AigReplace( (Abc_Aig_t *)pNtk->pManFunc, pFanout, pFanoutNew, 1 );
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Constructs window for checking RR.]
|
|
|
|
Description [If the window (p->pWnd) with the given scope (p->nFaninLevels,
|
|
p->nFanoutLevels) cannot be constructed, returns 0. Otherwise, returns 1.
|
|
The levels are measured from the fanin node (pFanin) and the fanout node
|
|
(pEdgeFanout), respectively.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NtkRRWindow( Abc_RRMan_t * p )
|
|
{
|
|
Abc_Obj_t * pObj, * pEdgeFanin, * pEdgeFanout;
|
|
int i, LevelMin, LevelMax, RetValue;
|
|
|
|
// get the edge
|
|
pEdgeFanout = p->pFanout? p->pFanout : p->pNode;
|
|
pEdgeFanin = p->pFanout? p->pNode : p->pFanin;
|
|
// get the minimum and maximum levels of the window
|
|
LevelMin = Abc_MaxInt( 0, ((int)p->pFanin->Level) - p->nFaninLevels );
|
|
LevelMax = (int)pEdgeFanout->Level + p->nFanoutLevels;
|
|
|
|
// start the TFI leaves with the fanin
|
|
Abc_NtkIncrementTravId( p->pNtk );
|
|
Abc_NodeSetTravIdCurrent( p->pFanin );
|
|
Vec_PtrPush( p->vFaninLeaves, p->pFanin );
|
|
// mark the TFI cone and collect the leaves down to the given level
|
|
while ( Abc_NtkRRTfi_int(p->vFaninLeaves, LevelMin) );
|
|
|
|
// mark the leaves with the new TravId
|
|
Abc_NtkIncrementTravId( p->pNtk );
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninLeaves, pObj, i )
|
|
Abc_NodeSetTravIdCurrent( pObj );
|
|
// traverse the TFO cone of the leaves (while skipping the edge)
|
|
// (a) mark the nodes in the cone using the current TravId
|
|
// (b) collect the nodes that have external fanouts into p->vFanoutRoots
|
|
while ( Abc_NtkRRTfo_int(p->vFaninLeaves, p->vFanoutRoots, LevelMax, pEdgeFanin, pEdgeFanout) );
|
|
|
|
// mark the fanout roots
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanoutRoots, pObj, i )
|
|
pObj->fMarkA = 1;
|
|
// collect roots reachable from the fanout (p->vRoots)
|
|
RetValue = Abc_NtkRRTfo_rec( pEdgeFanout, p->vRoots, LevelMax + 1 );
|
|
// unmark the fanout roots
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanoutRoots, pObj, i )
|
|
pObj->fMarkA = 0;
|
|
|
|
// return if the window is infeasible
|
|
if ( RetValue == 0 )
|
|
return 0;
|
|
|
|
// collect the DFS-ordered new cone (p->vCone) and new leaves (p->vLeaves)
|
|
// using the previous marks coming from the TFO cone
|
|
Abc_NtkIncrementTravId( p->pNtk );
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i )
|
|
Abc_NtkRRTfi_rec( pObj, p->vLeaves, p->vCone, LevelMin );
|
|
|
|
// create a new network
|
|
p->pWnd = Abc_NtkWindow( p->pNtk, p->vLeaves, p->vCone, p->vRoots );
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Marks the nodes in the TFI and collects their leaves.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit )
|
|
{
|
|
Abc_Obj_t * pObj, * pNext;
|
|
int i, k, LevelMax, nSize;
|
|
assert( LevelLimit >= 0 );
|
|
// find the maximum level of leaves
|
|
LevelMax = 0;
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
|
|
if ( LevelMax < (int)pObj->Level )
|
|
LevelMax = pObj->Level;
|
|
// if the nodes are all PIs, LevelMax == 0
|
|
if ( LevelMax <= LevelLimit )
|
|
return 0;
|
|
// expand the nodes with the minimum level
|
|
nSize = Vec_PtrSize(vLeaves);
|
|
Vec_PtrForEachEntryStop( Abc_Obj_t *, vLeaves, pObj, i, nSize )
|
|
{
|
|
if ( LevelMax != (int)pObj->Level )
|
|
continue;
|
|
Abc_ObjForEachFanin( pObj, pNext, k )
|
|
{
|
|
if ( Abc_NodeIsTravIdCurrent(pNext) )
|
|
continue;
|
|
Abc_NodeSetTravIdCurrent( pNext );
|
|
Vec_PtrPush( vLeaves, pNext );
|
|
}
|
|
}
|
|
// remove old nodes (cannot remove a PI)
|
|
k = 0;
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
|
|
{
|
|
if ( LevelMax == (int)pObj->Level )
|
|
continue;
|
|
Vec_PtrWriteEntry( vLeaves, k++, pObj );
|
|
}
|
|
Vec_PtrShrink( vLeaves, k );
|
|
if ( Vec_PtrSize(vLeaves) > 2000 )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Marks the nodes in the TFO and collects their roots.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout )
|
|
{
|
|
Abc_Obj_t * pObj, * pNext;
|
|
int i, k, LevelMin, nSize, fObjIsRoot;
|
|
// find the minimum level of leaves
|
|
LevelMin = ABC_INFINITY;
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
|
|
if ( LevelMin > (int)pObj->Level )
|
|
LevelMin = pObj->Level;
|
|
// if the minimum level exceed the limit, we are done
|
|
if ( LevelMin > LevelLimit )
|
|
return 0;
|
|
// expand the nodes with the minimum level
|
|
nSize = Vec_PtrSize(vLeaves);
|
|
Vec_PtrForEachEntryStop( Abc_Obj_t *, vLeaves, pObj, i, nSize )
|
|
{
|
|
if ( LevelMin != (int)pObj->Level )
|
|
continue;
|
|
fObjIsRoot = 0;
|
|
Abc_ObjForEachFanout( pObj, pNext, k )
|
|
{
|
|
// check if the fanout is outside of the cone
|
|
if ( Abc_ObjIsCo(pNext) || pNext->Level > (unsigned)LevelLimit )
|
|
{
|
|
fObjIsRoot = 1;
|
|
continue;
|
|
}
|
|
// skip the edge under check
|
|
if ( pObj == pEdgeFanin && pNext == pEdgeFanout )
|
|
continue;
|
|
// skip the visited fanouts
|
|
if ( Abc_NodeIsTravIdCurrent(pNext) )
|
|
continue;
|
|
Abc_NodeSetTravIdCurrent( pNext );
|
|
Vec_PtrPush( vLeaves, pNext );
|
|
}
|
|
if ( fObjIsRoot )
|
|
Vec_PtrPush( vRoots, pObj );
|
|
}
|
|
// remove old nodes
|
|
k = 0;
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
|
|
{
|
|
if ( LevelMin == (int)pObj->Level )
|
|
continue;
|
|
Vec_PtrWriteEntry( vLeaves, k++, pObj );
|
|
}
|
|
Vec_PtrShrink( vLeaves, k );
|
|
if ( Vec_PtrSize(vLeaves) > 2000 )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Collects the roots in the TFO of the node.]
|
|
|
|
Description [Note that this procedure can be improved by
|
|
marking and skipping the visited nodes.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit )
|
|
{
|
|
Abc_Obj_t * pFanout;
|
|
int i;
|
|
// if we encountered a node outside of the TFO cone of the fanins, quit
|
|
if ( Abc_ObjIsCo(pNode) || pNode->Level > (unsigned)LevelLimit )
|
|
return 0;
|
|
// if we encountered a node on the boundary, add it to the roots
|
|
if ( pNode->fMarkA )
|
|
{
|
|
Vec_PtrPushUnique( vRoots, pNode );
|
|
return 1;
|
|
}
|
|
// mark the node with the current TravId (needed to have all internal nodes marked)
|
|
Abc_NodeSetTravIdCurrent( pNode );
|
|
// traverse the fanouts
|
|
Abc_ObjForEachFanout( pNode, pFanout, i )
|
|
if ( !Abc_NtkRRTfo_rec( pFanout, vRoots, LevelLimit ) )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Collects the leaves and cone of the roots.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit )
|
|
{
|
|
Abc_Obj_t * pFanin;
|
|
int i;
|
|
// skip visited nodes
|
|
if ( Abc_NodeIsTravIdCurrent(pNode) )
|
|
return;
|
|
// add node to leaves if it is not in TFI cone of the leaves (marked before) or below the limit
|
|
if ( !Abc_NodeIsTravIdPrevious(pNode) || (int)pNode->Level <= LevelLimit )
|
|
{
|
|
Abc_NodeSetTravIdCurrent( pNode );
|
|
Vec_PtrPush( vLeaves, pNode );
|
|
return;
|
|
}
|
|
// mark the node as visited
|
|
Abc_NodeSetTravIdCurrent( pNode );
|
|
// call for the node's fanins
|
|
Abc_ObjForEachFanin( pNode, pFanin, i )
|
|
Abc_NtkRRTfi_rec( pFanin, vLeaves, vCone, LevelLimit );
|
|
// add the node to the cone in topological order
|
|
Vec_PtrPush( vCone, pNode );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots )
|
|
{
|
|
Abc_Ntk_t * pNtkNew;
|
|
Abc_Obj_t * pObj;
|
|
int fCheck = 1;
|
|
int i;
|
|
assert( Abc_NtkIsStrash(pNtk) );
|
|
// start the network
|
|
pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
|
|
// duplicate the name and the spec
|
|
pNtkNew->pName = Extra_UtilStrsav( "temp" );
|
|
// map the constant nodes
|
|
Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
|
|
// create and map the PIs
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
|
|
pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
|
|
// copy the AND gates
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i )
|
|
pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
|
|
// compare the number of nodes before and after
|
|
if ( Vec_PtrSize(vCone) != Abc_NtkNodeNum(pNtkNew) )
|
|
printf( "Warning: Structural hashing during windowing reduced %d nodes (this is a bug).\n",
|
|
Vec_PtrSize(vCone) - Abc_NtkNodeNum(pNtkNew) );
|
|
// create the POs
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i )
|
|
{
|
|
assert( !Abc_ObjIsComplement(pObj->pCopy) );
|
|
Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObj->pCopy );
|
|
}
|
|
// add the PI/PO names
|
|
Abc_NtkAddDummyPiNames( pNtkNew );
|
|
Abc_NtkAddDummyPoNames( pNtkNew );
|
|
// check
|
|
if ( fCheck && !Abc_NtkCheck( pNtkNew ) )
|
|
{
|
|
printf( "Abc_NtkWindow: The network check has failed.\n" );
|
|
return NULL;
|
|
}
|
|
return pNtkNew;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Starts simulation to detect non-redundant edges.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk )
|
|
{
|
|
Abc_Obj_t * pObj;
|
|
unsigned uData, uData0, uData1;
|
|
int i;
|
|
Abc_AigConst1(pNtk)->pData = (void *)~((unsigned)0);
|
|
Abc_NtkForEachCi( pNtk, pObj, i )
|
|
pObj->pData = (void *)(ABC_PTRUINT_T)SIM_RANDOM_UNSIGNED;
|
|
Abc_NtkForEachNode( pNtk, pObj, i )
|
|
{
|
|
if ( i == 0 ) continue;
|
|
uData0 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData;
|
|
uData1 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pData;
|
|
uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0;
|
|
uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1;
|
|
assert( pObj->pData == NULL );
|
|
pObj->pData = (void *)(ABC_PTRUINT_T)uData;
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Stops simulation to detect non-redundant edges.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk )
|
|
{
|
|
Abc_Obj_t * pObj;
|
|
int i;
|
|
Abc_NtkForEachObj( pNtk, pObj, i )
|
|
pObj->pData = NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes );
|
|
static void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField );
|
|
static void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField );
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Simulation to detect non-redundant edges.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Str_t * Abc_NtkRRSimulate( Abc_Ntk_t * pNtk )
|
|
{
|
|
Vec_Ptr_t * vNodes, * vField;
|
|
Vec_Str_t * vTargets;
|
|
Abc_Obj_t * pObj;
|
|
unsigned uData, uData0, uData1;
|
|
int PrevCi, Phase, i, k;
|
|
|
|
// start the candidates
|
|
vTargets = Vec_StrStart( Abc_NtkObjNumMax(pNtk) + 1 );
|
|
Abc_NtkForEachNode( pNtk, pObj, i )
|
|
{
|
|
Phase = ((Abc_ObjFanoutNum(Abc_ObjFanin1(pObj)) > 1) << 1);
|
|
Phase |= (Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) > 1);
|
|
Vec_StrWriteEntry( vTargets, pObj->Id, (char)Phase );
|
|
}
|
|
|
|
// simulate patters and store them in copy
|
|
Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)~((unsigned)0);
|
|
Abc_NtkForEachCi( pNtk, pObj, i )
|
|
pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)SIM_RANDOM_UNSIGNED;
|
|
Abc_NtkForEachNode( pNtk, pObj, i )
|
|
{
|
|
if ( i == 0 ) continue;
|
|
uData0 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData;
|
|
uData1 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pData;
|
|
uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0;
|
|
uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1;
|
|
pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)uData;
|
|
}
|
|
// store the result in data
|
|
Abc_NtkForEachCo( pNtk, pObj, i )
|
|
{
|
|
uData0 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData;
|
|
if ( Abc_ObjFaninC0(pObj) )
|
|
pObj->pData = (void *)(ABC_PTRUINT_T)~uData0;
|
|
else
|
|
pObj->pData = (void *)(ABC_PTRUINT_T)uData0;
|
|
}
|
|
|
|
// refine the candidates
|
|
for ( PrevCi = 0; PrevCi < Abc_NtkCiNum(pNtk); PrevCi = i )
|
|
{
|
|
vNodes = Vec_PtrAlloc( 10 );
|
|
Abc_NtkIncrementTravId( pNtk );
|
|
for ( i = PrevCi; i < Abc_NtkCiNum(pNtk); i++ )
|
|
{
|
|
Sim_TraverseNodes_rec( Abc_NtkCi(pNtk, i), vTargets, vNodes );
|
|
if ( Vec_PtrSize(vNodes) > 128 )
|
|
break;
|
|
}
|
|
// collect the marked nodes in the topological order
|
|
vField = Vec_PtrAlloc( 10 );
|
|
Abc_NtkIncrementTravId( pNtk );
|
|
Abc_NtkForEachCo( pNtk, pObj, k )
|
|
Sim_CollectNodes_rec( pObj, vField );
|
|
|
|
// simulate these nodes
|
|
Sim_SimulateCollected( vTargets, vNodes, vField );
|
|
// prepare for the next loop
|
|
Vec_PtrFree( vNodes );
|
|
}
|
|
|
|
// clean
|
|
Abc_NtkForEachObj( pNtk, pObj, i )
|
|
pObj->pData = NULL;
|
|
return vTargets;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Collects nodes starting from the given node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes )
|
|
{
|
|
Abc_Obj_t * pFanout;
|
|
char Entry;
|
|
int k;
|
|
if ( Abc_NodeIsTravIdCurrent(pRoot) )
|
|
return;
|
|
Abc_NodeSetTravIdCurrent( pRoot );
|
|
// save the reached targets
|
|
Entry = Vec_StrEntry(vTargets, pRoot->Id);
|
|
if ( Entry & 1 )
|
|
Vec_PtrPush( vNodes, Abc_ObjNot(pRoot) );
|
|
if ( Entry & 2 )
|
|
Vec_PtrPush( vNodes, pRoot );
|
|
// explore the fanouts
|
|
Abc_ObjForEachFanout( pRoot, pFanout, k )
|
|
Sim_TraverseNodes_rec( pFanout, vTargets, vNodes );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Collects nodes starting from the given node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField )
|
|
{
|
|
Abc_Obj_t * pFanin;
|
|
int i;
|
|
if ( Abc_NodeIsTravIdCurrent(pRoot) )
|
|
return;
|
|
if ( !Abc_NodeIsTravIdPrevious(pRoot) )
|
|
return;
|
|
Abc_NodeSetTravIdCurrent( pRoot );
|
|
Abc_ObjForEachFanin( pRoot, pFanin, i )
|
|
Sim_CollectNodes_rec( pFanin, vField );
|
|
if ( !Abc_ObjIsCo(pRoot) )
|
|
pRoot->pData = (void *)(ABC_PTRUINT_T)Vec_PtrSize(vField);
|
|
Vec_PtrPush( vField, pRoot );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Simulate the given nodes.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField )
|
|
{
|
|
Abc_Obj_t * pObj, * pFanin0, * pFanin1, * pDisproved;
|
|
Vec_Ptr_t * vSims;
|
|
unsigned * pUnsigned, * pUnsignedF;
|
|
int i, k, Phase, fCompl;
|
|
// get simulation info
|
|
vSims = Sim_UtilInfoAlloc( Vec_PtrSize(vField), Vec_PtrSize(vNodes), 0 );
|
|
// simulate the nodes
|
|
Vec_PtrForEachEntry( Abc_Obj_t *, vField, pObj, i )
|
|
{
|
|
if ( Abc_ObjIsCi(pObj) )
|
|
{
|
|
pUnsigned = (unsigned *)Vec_PtrEntry( vSims, i );
|
|
for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
|
|
pUnsigned[k] = (unsigned)(ABC_PTRUINT_T)pObj->pCopy;
|
|
continue;
|
|
}
|
|
if ( Abc_ObjIsCo(pObj) )
|
|
{
|
|
pUnsigned = (unsigned *)Vec_PtrEntry( vSims, i );
|
|
pUnsignedF = (unsigned *)Vec_PtrEntry( vSims, (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData );
|
|
if ( Abc_ObjFaninC0(pObj) )
|
|
for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
|
|
pUnsigned[k] = ~pUnsignedF[k];
|
|
else
|
|
for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
|
|
pUnsigned[k] = pUnsignedF[k];
|
|
// update targets
|
|
for ( k = 0; k < Vec_PtrSize(vNodes); k++ )
|
|
{
|
|
if ( pUnsigned[k] == (unsigned)(ABC_PTRUINT_T)pObj->pData )
|
|
continue;
|
|
pDisproved = (Abc_Obj_t *)Vec_PtrEntry( vNodes, k );
|
|
fCompl = Abc_ObjIsComplement(pDisproved);
|
|
pDisproved = Abc_ObjRegular(pDisproved);
|
|
Phase = Vec_StrEntry( vTargets, pDisproved->Id );
|
|
if ( fCompl )
|
|
Phase = (Phase & 2);
|
|
else
|
|
Phase = (Phase & 1);
|
|
Vec_StrWriteEntry( vTargets, pDisproved->Id, (char)Phase );
|
|
}
|
|
continue;
|
|
}
|
|
// simulate the node
|
|
pFanin0 = Abc_ObjFanin0(pObj);
|
|
pFanin1 = Abc_ObjFanin1(pObj);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
{
|
|
unsigned uData;
|
|
if ( pFanin == Abc_ObjFanin0(pNode) )
|
|
{
|
|
uData = (unsigned)Abc_ObjFanin1(pNode)->pData;
|
|
uData = Abc_ObjFaninC1(pNode)? ~uData : uData;
|
|
}
|
|
else if ( pFanin == Abc_ObjFanin1(pNode) )
|
|
{
|
|
uData = (unsigned)Abc_ObjFanin0(pNode)->pData;
|
|
uData = Abc_ObjFaninC0(pNode)? ~uData : uData;
|
|
}
|
|
uData ^= (unsigned)pNode->pData;
|
|
// Extra_PrintBinary( stdout, &uData, 32 ); printf( "\n" );
|
|
if ( Extra_WordCountOnes(uData) > 8 )
|
|
continue;
|
|
}
|
|
*/
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|