/**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) ) { // 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