abcBridge-0.14: abc-build/src/base/abc/abcHie.c
/**CFile****************************************************************
FileName [abcHie.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
Synopsis [Procedures to handle hierarchy.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: abcHie.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "abc.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Recursively flattens logic hierarchy of the netlist.]
Description [When this procedure is called, the PI/PO nets of the old
netlist point to the corresponding nets of the flattened netlist.]
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkFlattenLogicHierarchy2_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter )
{
char Suffix[2000] = {0};
Abc_Ntk_t * pNtkModel;
Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin;
int i, k;
// process the blackbox
if ( Abc_NtkHasBlackbox(pNtk) )
{
// duplicate the blackbox
assert( Abc_NtkBoxNum(pNtk) == 1 );
pObj = Abc_NtkBox( pNtk, 0 );
Abc_NtkDupBox( pNtkNew, pObj, 1 );
pObj->pCopy->pData = pNtk;
// connect blackbox fanins to the PI nets
assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) );
Abc_NtkForEachPi( pNtk, pTerm, i )
Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy );
// connect blackbox fanouts to the PO nets
assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) );
Abc_NtkForEachPo( pNtk, pTerm, i )
Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) );
return;
}
(*pCounter)++;
// create the suffix, which will be appended to the internal names
if ( *pCounter )
sprintf( Suffix, "_%s_%d", Abc_NtkName(pNtk), *pCounter );
// duplicate nets of all boxes, including latches
Abc_NtkForEachBox( pNtk, pObj, i )
{
Abc_ObjForEachFanin( pObj, pTerm, k )
{
pNet = Abc_ObjFanin0(pTerm);
if ( pNet->pCopy )
continue;
pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) );
}
Abc_ObjForEachFanout( pObj, pTerm, k )
{
pNet = Abc_ObjFanout0(pTerm);
if ( pNet->pCopy )
continue;
pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) );
}
}
// mark objects that will not be used
Abc_NtkIncrementTravId( pNtk );
Abc_NtkForEachPi( pNtk, pTerm, i )
Abc_NodeSetTravIdCurrent( pTerm );
Abc_NtkForEachPo( pNtk, pTerm, i )
{
Abc_NodeSetTravIdCurrent( pTerm );
// if the netlist has net names beginning with "abc_property_"
// these names will be addes as primary outputs of the network
pNet = Abc_ObjFanin0(pTerm);
if ( strncmp( Abc_ObjName(pNet), "abc_property", 12 ) )
continue;
Abc_ObjAddFanin( Abc_NtkCreatePo(pNet->pCopy->pNtk), pNet->pCopy );
if ( Nm_ManFindNameById(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id) )
Nm_ManDeleteIdName(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id);
Abc_ObjAssignName( pNet->pCopy, Abc_ObjName(pNet), Suffix );
}
Abc_NtkForEachBox( pNtk, pObj, i )
{
if ( Abc_ObjIsLatch(pObj) )
continue;
Abc_NodeSetTravIdCurrent( pObj );
Abc_ObjForEachFanin( pObj, pTerm, k )
Abc_NodeSetTravIdCurrent( pTerm );
Abc_ObjForEachFanout( pObj, pTerm, k )
Abc_NodeSetTravIdCurrent( pTerm );
}
// duplicate objects that do not have prototypes yet
Abc_NtkForEachObj( pNtk, pObj, i )
{
if ( Abc_NodeIsTravIdCurrent(pObj) )
continue;
if ( pObj->pCopy )
continue;
Abc_NtkDupObj( pNtkNew, pObj, 0 );
}
// connect objects
Abc_NtkForEachObj( pNtk, pObj, i )
if ( !Abc_NodeIsTravIdCurrent(pObj) )
Abc_ObjForEachFanin( pObj, pFanin, k )
if ( !Abc_NodeIsTravIdCurrent(pFanin) )
Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
// call recursively
Abc_NtkForEachBox( pNtk, pObj, i )
{
if ( Abc_ObjIsLatch(pObj) )
continue;
pNtkModel = (Abc_Ntk_t *)pObj->pData;
// check the match between the number of actual and formal parameters
assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) );
assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) );
// clean the node copy fields
Abc_NtkCleanCopy( pNtkModel );
// map PIs/POs
Abc_ObjForEachFanin( pObj, pTerm, k )
Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy;
Abc_ObjForEachFanout( pObj, pTerm, k )
Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy;
// call recursively
Abc_NtkFlattenLogicHierarchy2_rec( pNtkNew, pNtkModel, pCounter );
}
// if it is a BLIF-MV netlist transfer the values of all nets
if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
{
if ( Abc_NtkMvVar( pNtkNew ) == NULL )
Abc_NtkStartMvVars( pNtkNew );
Abc_NtkForEachNet( pNtk, pObj, i )
Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
}
}
/**Function*************************************************************
Synopsis [Flattens the logic hierarchy of the netlist.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy2( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pTerm, * pNet;
int i, Counter;
extern Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave );
assert( Abc_NtkIsNetlist(pNtk) );
// start the network
pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
// duplicate the name and the spec
pNtkNew->pName = Abc_UtilStrsav(pNtk->pName);
pNtkNew->pSpec = Abc_UtilStrsav(pNtk->pSpec);
// clean the node copy fields
Abc_NtkCleanCopy( pNtk );
// duplicate PIs/POs and their nets
Abc_NtkForEachPi( pNtk, pTerm, i )
{
Abc_NtkDupObj( pNtkNew, pTerm, 0 );
pNet = Abc_ObjFanout0( pTerm );
pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy );
}
Abc_NtkForEachPo( pNtk, pTerm, i )
{
Abc_NtkDupObj( pNtkNew, pTerm, 0 );
pNet = Abc_ObjFanin0( pTerm );
pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy );
}
// recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes
Counter = -1;
Abc_NtkFlattenLogicHierarchy2_rec( pNtkNew, pNtk, &Counter );
printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n",
Counter, Abc_NtkBlackboxNum(pNtkNew) );
if ( pNtk->pDesign )
{
// pass on the design
assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk );
pNtkNew->pDesign = Abc_DesDupBlackboxes( pNtk->pDesign, pNtkNew );
// update the pointers
Abc_NtkForEachBlackbox( pNtkNew, pTerm, i )
pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy;
}
// we may have added property outputs
Abc_NtkOrderCisCos( pNtkNew );
// copy the timing information
// Abc_ManTimeDup( pNtk, pNtkNew );
// duplicate EXDC
if ( pNtk->pExdc )
printf( "EXDC is not transformed.\n" );
if ( !Abc_NtkCheck( pNtkNew ) )
{
fprintf( stdout, "Abc_NtkFlattenLogicHierarchy2(): Network check has failed.\n" );
Abc_NtkDelete( pNtkNew );
return NULL;
}
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Recursively flattens logic hierarchy of the netlist.]
Description [When this procedure is called, the PI/PO nets of the old
netlist point to the corresponding nets of the flattened netlist.]
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkFlattenLogicHierarchy_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter, Vec_Str_t * vPref )
{
Abc_Ntk_t * pNtkModel;
Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin;
int i, k, Length;
// process the blackbox
if ( Abc_NtkHasBlackbox(pNtk) )
{
printf( "Flatting black box \"%s\".\n", pNtk->pName );
// duplicate the blackbox
assert( Abc_NtkBoxNum(pNtk) == 1 );
pObj = Abc_NtkBox( pNtk, 0 );
Abc_NtkDupBox( pNtkNew, pObj, 1 );
pObj->pCopy->pData = pNtk;
// connect blackbox fanins to the PI nets
assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) );
Abc_NtkForEachPi( pNtk, pTerm, i )
Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy );
// connect blackbox fanouts to the PO nets
assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) );
Abc_NtkForEachPo( pNtk, pTerm, i )
Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) );
return;
}
(*pCounter)++;
// create the suffix, which will be appended to the internal names
if ( *pCounter )
{
char Buffer[20];
sprintf( Buffer, "(%d)", *pCounter );
Vec_StrPrintStr( vPref, Buffer );
}
Vec_StrPush( vPref, '|' );
Vec_StrPush( vPref, 0 );
// duplicate nets of all boxes, including latches
Abc_NtkForEachBox( pNtk, pObj, i )
{
Abc_ObjForEachFanin( pObj, pTerm, k )
{
pNet = Abc_ObjFanin0(pTerm);
if ( pNet->pCopy )
continue;
pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNamePrefix(pNet, Vec_StrArray(vPref)) );
}
Abc_ObjForEachFanout( pObj, pTerm, k )
{
pNet = Abc_ObjFanout0(pTerm);
if ( pNet->pCopy )
continue;
pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNamePrefix(pNet, Vec_StrArray(vPref)) );
}
}
// mark objects that will not be used
Abc_NtkIncrementTravId( pNtk );
Abc_NtkForEachPi( pNtk, pTerm, i )
Abc_NodeSetTravIdCurrent( pTerm );
Abc_NtkForEachPo( pNtk, pTerm, i )
{
Abc_NodeSetTravIdCurrent( pTerm );
// if the netlist has net names beginning with "abc_property_"
// these names will be addes as primary outputs of the network
pNet = Abc_ObjFanin0(pTerm);
if ( strncmp( Abc_ObjName(pNet), "abc_property", 12 ) )
continue;
Abc_ObjAddFanin( Abc_NtkCreatePo(pNet->pCopy->pNtk), pNet->pCopy );
if ( Nm_ManFindNameById(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id) )
Nm_ManDeleteIdName(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id);
Abc_ObjAssignName( pNet->pCopy, Vec_StrArray(vPref), Abc_ObjName(pNet) );
}
Abc_NtkForEachBox( pNtk, pObj, i )
{
if ( Abc_ObjIsLatch(pObj) )
continue;
Abc_NodeSetTravIdCurrent( pObj );
Abc_ObjForEachFanin( pObj, pTerm, k )
Abc_NodeSetTravIdCurrent( pTerm );
Abc_ObjForEachFanout( pObj, pTerm, k )
Abc_NodeSetTravIdCurrent( pTerm );
}
// duplicate objects that do not have prototypes yet
Abc_NtkForEachObj( pNtk, pObj, i )
{
if ( Abc_NodeIsTravIdCurrent(pObj) )
continue;
if ( pObj->pCopy )
continue;
Abc_NtkDupObj( pNtkNew, pObj, 0 );
}
// connect objects
Abc_NtkForEachObj( pNtk, pObj, i )
if ( !Abc_NodeIsTravIdCurrent(pObj) )
Abc_ObjForEachFanin( pObj, pFanin, k )
if ( !Abc_NodeIsTravIdCurrent(pFanin) )
Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
// call recursively
Vec_StrPop( vPref );
Length = Vec_StrSize( vPref );
Abc_NtkForEachBox( pNtk, pObj, i )
{
if ( Abc_ObjIsLatch(pObj) )
continue;
pNtkModel = (Abc_Ntk_t *)pObj->pData;
// check the match between the number of actual and formal parameters
assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) );
assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) );
// clean the node copy fields
Abc_NtkCleanCopy( pNtkModel );
// map PIs/POs
Abc_ObjForEachFanin( pObj, pTerm, k )
Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy;
Abc_ObjForEachFanout( pObj, pTerm, k )
Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy;
// create name
Vec_StrShrink( vPref, Length );
Vec_StrPrintStr( vPref, Abc_NtkName(pNtkModel) );
// call recursively
Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtkModel, pCounter, vPref );
}
// if it is a BLIF-MV netlist transfer the values of all nets
if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
{
if ( Abc_NtkMvVar( pNtkNew ) == NULL )
Abc_NtkStartMvVars( pNtkNew );
Abc_NtkForEachNet( pNtk, pObj, i )
Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
}
}
/**Function*************************************************************
Synopsis [Returns 0 if CI names are repeated.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCompareNames( Abc_Ntk_t ** p1, Abc_Ntk_t ** p2 )
{
return strcmp( Abc_NtkName(*p1), Abc_NtkName(*p2) );
}
/**Function*************************************************************
Synopsis [Prints information about boxes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkPrintBoxInfo( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vMods;
Abc_Ntk_t * pModel, * pBoxModel;
Abc_Obj_t * pObj;
Vec_Int_t * vCounts;
int i, k, Num;
if ( pNtk->pDesign == NULL || pNtk->pDesign->vModules == NULL )
{
// printf( "There is no hierarchy information.\n" );
return;
}
// sort models by name
vMods = pNtk->pDesign->vModules;
Vec_PtrSort( vMods, (int(*)())Abc_NtkCompareNames );
// Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
// printf( "%s\n", Abc_NtkName(pModel) );
// swap the first model
Num = Vec_PtrFind( vMods, pNtk );
assert( Num >= 0 && Num < Vec_PtrSize(vMods) );
pBoxModel = (Abc_Ntk_t *)Vec_PtrEntry(vMods, 0);
Vec_PtrWriteEntry(vMods, 0, (Abc_Ntk_t *)Vec_PtrEntry(vMods, Num) );
Vec_PtrWriteEntry(vMods, Num, pBoxModel );
// print models
vCounts = Vec_IntStart( Vec_PtrSize(vMods) );
Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
{
if ( Abc_NtkBoxNum(pModel) == 0 )
continue;
Vec_IntFill( vCounts, Vec_IntSize(vCounts), 0 );
Abc_NtkForEachBox( pModel, pObj, k )
{
pBoxModel = (Abc_Ntk_t *)pObj->pData;
if ( pBoxModel == NULL )
continue;
Num = Vec_PtrFind( vMods, pBoxModel );
assert( Num >= 0 && Num < Vec_PtrSize(vMods) );
Vec_IntAddToEntry( vCounts, Num, 1 );
}
// Abc_NtkPrintStats( pModel, 0, 0, 0, 0, 0, 0, 0, 0 );
printf( "MODULE " );
printf( "%-30s : ", Abc_NtkName(pModel) );
printf( "PI=%6d ", Abc_NtkPiNum(pModel) );
printf( "PO=%6d ", Abc_NtkPoNum(pModel) );
printf( "BB=%6d ", Abc_NtkBoxNum(pModel) );
printf( "ND=%6d ", Abc_NtkNodeNum(pModel) ); // sans constants
printf( "Lev=%5d ", Abc_NtkLevel(pModel) );
printf( "\n" );
Vec_IntForEachEntry( vCounts, Num, k )
if ( Num )
printf( "%15d : %s\n", Num, Abc_NtkName((Abc_Ntk_t *)Vec_PtrEntry(vMods, k)) );
}
Vec_IntFree( vCounts );
Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
{
if ( Abc_NtkBoxNum(pModel) != 0 )
continue;
printf( "MODULE " );
printf( "%-30s : ", Abc_NtkName(pModel) );
printf( "PI=%6d ", Abc_NtkPiNum(pModel) );
printf( "PO=%6d ", Abc_NtkPoNum(pModel) );
printf( "BB=%6d ", Abc_NtkBoxNum(pModel) );
printf( "ND=%6d ", Abc_NtkNodeNum(pModel) );
printf( "Lev=%5d ", Abc_NtkLevel(pModel) );
printf( "\n" );
}
}
/**Function*************************************************************
Synopsis [Flattens the logic hierarchy of the netlist.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk )
{
extern Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave );
Vec_Str_t * vPref;
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pTerm, * pNet;
int i, Counter = -1;
assert( Abc_NtkIsNetlist(pNtk) );
// Abc_NtkPrintBoxInfo( pNtk );
// start the network
pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
// duplicate the name and the spec
pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
// clean the node copy fields
Abc_NtkCleanCopy( pNtk );
// duplicate PIs/POs and their nets
Abc_NtkForEachPi( pNtk, pTerm, i )
{
Abc_NtkDupObj( pNtkNew, pTerm, 0 );
pNet = Abc_ObjFanout0( pTerm );
pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy );
}
Abc_NtkForEachPo( pNtk, pTerm, i )
{
Abc_NtkDupObj( pNtkNew, pTerm, 0 );
pNet = Abc_ObjFanin0( pTerm );
pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy );
}
// recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes
vPref = Vec_StrAlloc( 1000 );
Vec_StrPrintStr( vPref, Abc_NtkName(pNtk) );
Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtk, &Counter, vPref );
printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n",
Counter, Abc_NtkBlackboxNum(pNtkNew) );
Vec_StrFree( vPref );
if ( pNtk->pDesign )
{
// pass on the design
assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk );
pNtkNew->pDesign = Abc_DesDupBlackboxes( pNtk->pDesign, pNtkNew );
// update the pointers
Abc_NtkForEachBlackbox( pNtkNew, pTerm, i )
pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy;
}
// we may have added property outputs
Abc_NtkOrderCisCos( pNtkNew );
// copy the timing information
// Abc_ManTimeDup( pNtk, pNtkNew );
// duplicate EXDC
if ( pNtk->pExdc )
printf( "EXDC is not transformed.\n" );
if ( !Abc_NtkCheck( pNtkNew ) )
{
fprintf( stdout, "Abc_NtkFlattenLogicHierarchy(): Network check has failed.\n" );
Abc_NtkDelete( pNtkNew );
return NULL;
}
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Extracts blackboxes by making them into additional PIs/POs.]
Description [The input netlist has not logic hierarchy. The resulting
netlist has additional PIs/POs for each blackbox input/output.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pNet, * pFanin, * pTerm;
int i, k;
assert( Abc_NtkIsNetlist(pNtk) );
assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
// start the network
pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
// duplicate the name and the spec
pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec );
// clean the node copy fields
Abc_NtkCleanCopy( pNtk );
// mark the nodes that should not be connected
Abc_NtkIncrementTravId( pNtk );
Abc_NtkForEachBlackbox( pNtk, pObj, i )
Abc_NodeSetTravIdCurrent( pObj );
Abc_NtkForEachCi( pNtk, pTerm, i )
Abc_NodeSetTravIdCurrent( pTerm );
Abc_NtkForEachCo( pNtk, pTerm, i )
Abc_NodeSetTravIdCurrent( pTerm );
// unmark PIs and LIs/LOs
Abc_NtkForEachPi( pNtk, pTerm, i )
Abc_NodeSetTravIdPrevious( pTerm );
Abc_NtkForEachLatchInput( pNtk, pTerm, i )
Abc_NodeSetTravIdPrevious( pTerm );
Abc_NtkForEachLatchOutput( pNtk, pTerm, i )
Abc_NodeSetTravIdPrevious( pTerm );
// copy the box outputs
Abc_NtkForEachBlackbox( pNtk, pObj, i )
Abc_ObjForEachFanout( pObj, pTerm, k )
pTerm->pCopy = Abc_NtkCreatePi( pNtkNew );
// duplicate other objects
Abc_NtkForEachObj( pNtk, pObj, i )
if ( !Abc_NodeIsTravIdCurrent(pObj) )
Abc_NtkDupObj( pNtkNew, pObj, Abc_ObjIsNet(pObj) );
// connect all objects
Abc_NtkForEachObj( pNtk, pObj, i )
if ( !Abc_NodeIsTravIdCurrent(pObj) )
Abc_ObjForEachFanin( pObj, pFanin, k )
Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
// create unique PO for each net feeding into blackboxes or POs
Abc_NtkIncrementTravId( pNtk );
Abc_NtkForEachCo( pNtk, pTerm, i )
{
// skip latch inputs
assert( Abc_ObjFanoutNum(pTerm) <= 1 );
if ( Abc_ObjFanoutNum(pTerm) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pTerm)) )
continue;
// check if the net is visited
pNet = Abc_ObjFanin0(pTerm);
if ( Abc_NodeIsTravIdCurrent(pNet) )
continue;
// create PO
Abc_NodeSetTravIdCurrent( pNet );
Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNet->pCopy );
}
// check integrity
if ( !Abc_NtkCheck( pNtkNew ) )
{
fprintf( stdout, "Abc_NtkConvertBlackboxes(): Network check has failed.\n" );
Abc_NtkDelete( pNtkNew );
return NULL;
}
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Inserts blackboxes into the netlist.]
Description [The first arg is the netlist with blackboxes without logic hierarchy.
The second arg is a non-hierarchical netlist derived from the above netlist after processing.
This procedure create a new netlist, which is comparable to the original netlist with
blackboxes, except that it contains logic nodes from the netlist after processing.]
SideEffects [This procedure silently assumes that blackboxes appear
only in the top-level model. If they appear in other models as well,
the name of the model and its number were appended to the names of
blackbox inputs/outputs.]
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL )
{
Abc_Des_t * pDesign;
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObjH, * pObjL, * pNetH, * pNetL, * pTermH;
int i, k;
assert( Abc_NtkIsNetlist(pNtkH) );
assert( Abc_NtkWhiteboxNum(pNtkH) == 0 );
assert( Abc_NtkBlackboxNum(pNtkH) > 0 );
assert( Abc_NtkIsNetlist(pNtkL) );
assert( Abc_NtkWhiteboxNum(pNtkL) == 0 );
assert( Abc_NtkBlackboxNum(pNtkL) == 0 );
// prepare the logic network for copying
Abc_NtkCleanCopy( pNtkL );
// start the network
pNtkNew = Abc_NtkAlloc( pNtkL->ntkType, pNtkL->ntkFunc, 1 );
// duplicate the name and the spec
pNtkNew->pName = Extra_UtilStrsav( pNtkH->pName );
pNtkNew->pSpec = Extra_UtilStrsav( pNtkH->pSpec );
// make sure every PI/PO has a PI/PO in the processed network
Abc_NtkForEachPi( pNtkH, pObjH, i )
{
pNetH = Abc_ObjFanout0(pObjH);
pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) )
{
printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the PI %s.\n", Abc_ObjName(pNetH) );
Abc_NtkDelete( pNtkNew );
return NULL;
}
if ( pNetL->pCopy )
{
printf( "Error in Abc_NtkInsertNewLogic(): Primary input %s is repeated twice.\n", Abc_ObjName(pNetH) );
Abc_NtkDelete( pNtkNew );
return NULL;
}
// create the new net
pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
Abc_NtkDupObj( pNtkNew, Abc_ObjFanin0(pNetL), 0 );
}
// make sure every BB has a PI/PO in the processed network
Abc_NtkForEachBlackbox( pNtkH, pObjH, i )
{
// duplicate the box
Abc_NtkDupBox( pNtkNew, pObjH, 0 );
pObjH->pCopy->pData = pObjH->pData;
// create PIs
Abc_ObjForEachFanout( pObjH, pTermH, k )
{
pNetH = Abc_ObjFanout0( pTermH );
pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) )
{
printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the inpout %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) );
Abc_NtkDelete( pNtkNew );
return NULL;
}
if ( pNetL->pCopy )
{
printf( "Error in Abc_NtkInsertNewLogic(): Box output %s is repeated twice.\n", Abc_ObjName(pNetH) );
Abc_NtkDelete( pNtkNew );
return NULL;
}
// create net and map the PI
pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
Abc_ObjFanin0(pNetL)->pCopy = pTermH->pCopy;
}
}
Abc_NtkForEachPo( pNtkH, pObjH, i )
{
pNetH = Abc_ObjFanin0(pObjH);
pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) )
{
printf( "Error in Abc_NtkInsertNewLogic(): There is no PO corresponding to the PO %s.\n", Abc_ObjName(pNetH) );
Abc_NtkDelete( pNtkNew );
return NULL;
}
if ( pNetL->pCopy )
continue;
// create the new net
pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
Abc_NtkDupObj( pNtkNew, Abc_ObjFanout0(pNetL), 0 );
}
Abc_NtkForEachBlackbox( pNtkH, pObjH, i )
{
Abc_ObjForEachFanin( pObjH, pTermH, k )
{
char * pName;
pNetH = Abc_ObjFanin0( pTermH );
pName = Abc_ObjName(pNetH);
pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) )
{
printf( "There is no PO corresponding to the input %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) );
Abc_NtkDelete( pNtkNew );
return NULL;
}
// create net and map the PO
if ( pNetL->pCopy )
{
if ( Abc_ObjFanout0(pNetL)->pCopy == NULL )
Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy;
else
Abc_ObjAddFanin( pTermH->pCopy, pNetL->pCopy );
continue;
}
pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy;
}
}
// duplicate other objects of the logic network
Abc_NtkForEachObj( pNtkL, pObjL, i )
if ( pObjL->pCopy == NULL && !Abc_ObjIsPo(pObjL) ) // skip POs feeding into PIs
Abc_NtkDupObj( pNtkNew, pObjL, Abc_ObjIsNet(pObjL) );
// connect objects
Abc_NtkForEachObj( pNtkL, pObjL, i )
Abc_ObjForEachFanin( pObjL, pNetL, k )
if ( pObjL->pCopy )
Abc_ObjAddFanin( pObjL->pCopy, pNetL->pCopy );
// transfer the design
pDesign = pNtkH->pDesign; pNtkH->pDesign = NULL;
assert( Vec_PtrEntry( pDesign->vModules, 0 ) == pNtkH );
Vec_PtrWriteEntry( pDesign->vModules, 0, pNtkNew );
pNtkNew->pDesign = pDesign;
// check integrity
if ( !Abc_NtkCheck( pNtkNew ) )
{
fprintf( stdout, "Abc_NtkInsertNewLogic(): Network check has failed.\n" );
Abc_NtkDelete( pNtkNew );
return NULL;
}
return pNtkNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END