mirror of https://github.com/YosysHQ/abc.git
317 lines
9.4 KiB
C
317 lines
9.4 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [aigNode.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [And-Inverter Graph package.]
|
|
|
|
Synopsis []
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: aigNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "aig.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates the node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline Aig_Node_t * Aig_NodeCreate( Aig_Man_t * p )
|
|
{
|
|
Aig_Node_t * pNode;
|
|
// create the node
|
|
pNode = (Aig_Node_t *)Aig_MemFixedEntryFetch( p->mmNodes );
|
|
memset( pNode, 0, sizeof(Aig_Node_t) );
|
|
// assign the number and add to the array of nodes
|
|
pNode->pMan = p;
|
|
pNode->Id = p->vNodes->nSize;
|
|
Vec_PtrPush( p->vNodes, pNode );
|
|
return pNode;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates the constant 1 node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Node_t * Aig_NodeCreateConst( Aig_Man_t * p )
|
|
{
|
|
Aig_Node_t * pNode;
|
|
pNode = Aig_NodeCreate( p );
|
|
pNode->Type = AIG_NONE;
|
|
pNode->fPhase = 1; // sim value for 000... pattern
|
|
return pNode;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates a primary input node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Node_t * Aig_NodeCreatePi( Aig_Man_t * p )
|
|
{
|
|
Aig_Node_t * pNode;
|
|
pNode = Aig_NodeCreate( p );
|
|
Vec_PtrPush( p->vPis, pNode );
|
|
pNode->Type = AIG_PI;
|
|
pNode->fPhase = 0; // sim value for 000... pattern
|
|
return pNode;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates a primary output node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Node_t * Aig_NodeCreatePo( Aig_Man_t * p )
|
|
{
|
|
Aig_Node_t * pNode;
|
|
pNode = Aig_NodeCreate( p );
|
|
pNode->Type = AIG_PO;
|
|
Vec_PtrPush( p->vPos, pNode );
|
|
return pNode;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates a primary output node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Node_t * Aig_NodeConnectPo( Aig_Man_t * p, Aig_Node_t * pNode, Aig_Node_t * pFanin )
|
|
{
|
|
assert( Aig_NodeIsPo(pNode) );
|
|
assert( !Aig_IsComplement(pNode) );
|
|
// connect to the fanin
|
|
pNode->Fans[0].fComp = Aig_IsComplement(pFanin);
|
|
pNode->Fans[0].iNode = Aig_Regular(pFanin)->Id;
|
|
pNode->fPhase = pNode->Fans[0].fComp ^ Aig_Regular(pFanin)->fPhase; // sim value for 000... pattern
|
|
pNode->Level = Aig_Regular(pFanin)->Level;
|
|
Aig_Regular(pFanin)->nRefs++;
|
|
if ( pNode->pMan->vFanPivots ) Aig_NodeAddFaninFanout( pFanin, pNode );
|
|
// update global level if needed
|
|
if ( p->nLevelMax < (int)pNode->Level )
|
|
p->nLevelMax = pNode->Level;
|
|
return pNode;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates a new node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Node_t * Aig_NodeCreateAnd( Aig_Man_t * p, Aig_Node_t * pFanin0, Aig_Node_t * pFanin1 )
|
|
{
|
|
Aig_Node_t * pNode;
|
|
pNode = Aig_NodeCreate( p );
|
|
pNode->Type = AIG_AND;
|
|
Aig_NodeConnectAnd( pFanin0, pFanin1, pNode );
|
|
return pNode;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Connects the nodes to the AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Aig_NodeConnectAnd( Aig_Node_t * pFanin0, Aig_Node_t * pFanin1, Aig_Node_t * pNode )
|
|
{
|
|
assert( !Aig_IsComplement(pNode) );
|
|
assert( Aig_NodeIsAnd(pNode) );
|
|
// add the fanins
|
|
pNode->Fans[0].fComp = Aig_IsComplement(pFanin0);
|
|
pNode->Fans[0].iNode = Aig_Regular(pFanin0)->Id;
|
|
pNode->Fans[1].fComp = Aig_IsComplement(pFanin1);
|
|
pNode->Fans[1].iNode = Aig_Regular(pFanin1)->Id;
|
|
// compute the phase (sim value for 000... pattern)
|
|
pNode->fPhase = (pNode->Fans[0].fComp ^ Aig_Regular(pFanin0)->fPhase) &
|
|
(pNode->Fans[1].fComp ^ Aig_Regular(pFanin1)->fPhase);
|
|
pNode->Level = Aig_NodeGetLevelNew(pNode);
|
|
// reference the fanins
|
|
Aig_Regular(pFanin0)->nRefs++;
|
|
Aig_Regular(pFanin1)->nRefs++;
|
|
// add the fanouts
|
|
if ( pNode->pMan->vFanPivots ) Aig_NodeAddFaninFanout( pFanin0, pNode );
|
|
if ( pNode->pMan->vFanPivots ) Aig_NodeAddFaninFanout( pFanin1, pNode );
|
|
// add the node to the structural hash table
|
|
Aig_TableInsertNode( pNode->pMan, pFanin0, pFanin1, pNode );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Connects the nodes to the AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Aig_NodeDisconnectAnd( Aig_Node_t * pNode )
|
|
{
|
|
Aig_Node_t * pFanin0, * pFanin1;
|
|
assert( !Aig_IsComplement(pNode) );
|
|
assert( Aig_NodeIsAnd(pNode) );
|
|
// get the fanins
|
|
pFanin0 = Aig_NodeFanin0(pNode);
|
|
pFanin1 = Aig_NodeFanin1(pNode);
|
|
// dereference the fanins
|
|
pFanin0->nRefs--;
|
|
pFanin0->nRefs--;
|
|
// remove the fanouts
|
|
if ( pNode->pMan->vFanPivots ) Aig_NodeRemoveFaninFanout( pFanin0, pNode );
|
|
if ( pNode->pMan->vFanPivots ) Aig_NodeRemoveFaninFanout( pFanin1, pNode );
|
|
// remove the node from the structural hash table
|
|
Aig_TableDeleteNode( pNode->pMan, pNode );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs internal deletion step.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Aig_NodeDeleteAnd_rec( Aig_Man_t * pMan, Aig_Node_t * pRoot )
|
|
{
|
|
Aig_Node_t * pNode0, * pNode1;
|
|
// make sure the node is regular and dangling
|
|
assert( !Aig_IsComplement(pRoot) );
|
|
assert( pRoot->nRefs == 0 );
|
|
assert( Aig_NodeIsAnd(pRoot) );
|
|
// remember the children
|
|
pNode0 = Aig_NodeFanin0(pRoot);
|
|
pNode1 = Aig_NodeFanin1(pRoot);
|
|
// disconnect the node
|
|
Aig_NodeDisconnectAnd( pRoot );
|
|
// recycle the node
|
|
Vec_PtrWriteEntry( pMan->vNodes, pRoot->Id, NULL );
|
|
memset( pRoot, 0, sizeof(Aig_Node_t) ); // this is a temporary hack to skip dead children below!!!
|
|
Aig_MemFixedEntryRecycle( pMan->mmNodes, (char *)pRoot );
|
|
// call recursively
|
|
if ( Aig_NodeIsAnd(pNode0) && pNode0->nRefs == 0 )
|
|
Aig_NodeDeleteAnd_rec( pMan, pNode0 );
|
|
if ( Aig_NodeIsAnd(pNode1) && pNode1->nRefs == 0 )
|
|
Aig_NodeDeleteAnd_rec( pMan, pNode1 );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Prints the AIG node for debugging purposes.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Aig_NodePrint( Aig_Node_t * pNode )
|
|
{
|
|
Aig_Node_t * pNodeR = Aig_Regular(pNode);
|
|
if ( Aig_NodeIsPi(pNode) )
|
|
{
|
|
printf( "PI %4s%s.\n", Aig_NodeName(pNode), Aig_IsComplement(pNode)? "\'" : "" );
|
|
return;
|
|
}
|
|
if ( Aig_NodeIsConst(pNode) )
|
|
{
|
|
printf( "Constant 1 %s.\n", Aig_IsComplement(pNode)? "(complemented)" : "" );
|
|
return;
|
|
}
|
|
// print the node's function
|
|
printf( "%7s%s", Aig_NodeName(pNodeR), Aig_IsComplement(pNode)? "\'" : "" );
|
|
printf( " = " );
|
|
printf( "%7s%s", Aig_NodeName(Aig_NodeFanin0(pNodeR)), Aig_NodeFaninC0(pNodeR)? "\'" : "" );
|
|
printf( " * " );
|
|
printf( "%7s%s", Aig_NodeName(Aig_NodeFanin1(pNodeR)), Aig_NodeFaninC1(pNodeR)? "\'" : "" );
|
|
printf( "\n" );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the name of the node.]
|
|
|
|
Description [The name should be used before this procedure is called again.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
char * Aig_NodeName( Aig_Node_t * pNode )
|
|
{
|
|
static char Buffer[100];
|
|
sprintf( Buffer, "%d", Aig_Regular(pNode)->Id );
|
|
return Buffer;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|