/**Function************************************************************* Synopsis [Transform the logic network into a netlist.] Description [The logic network given to this procedure should have exactly the same structure as the resulting netlist. The COs can only point to CIs if they have identical names. Otherwise, they should have a node between them, even if this node is inverter or buffer.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pNet, * pDriver, * pFanin; int i, k; assert( Abc_NtkIsLogic(pNtk) ); // remove dangling nodes Abc_NtkCleanup( pNtk, 0 ); // make sure the CO names are unique Abc_NtkCheckUniqueCiNames( pNtk ); Abc_NtkCheckUniqueCoNames( pNtk ); Abc_NtkCheckUniqueCioNames( pNtk ); // assert( Abc_NtkLogicHasSimpleCos(pNtk) ); if ( !Abc_NtkLogicHasSimpleCos(pNtk) ) { printf( "Abc_NtkLogicToNetlist() warning: The network is converted to have simple COs.\n" ); Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); } // start the netlist by creating PI/PO/Latch objects pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc ); // create the CI nets and remember them in the new CI nodes Abc_NtkForEachCi( pNtk, pObj, i ) { pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); Abc_ObjAddFanin( pNet, pObj->pCopy ); pObj->pCopy->pCopy = pNet; }
// first add the nets to the CO drivers Abc_NtkForEachCo( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0(pObj); if ( Abc_ObjIsCi(pDriver) ) { assert( !strcmp( Abc_ObjName(pDriver), Abc_ObjName(pObj) ) ); Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); continue; } assert( Abc_ObjIsNode(pDriver) ); // if the CO driver has no net, create it if ( pDriver->pCopy->pCopy == NULL ) { // create the CO net and connect it to CO pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); Abc_ObjAddFanin( pObj->pCopy, pNet ); // connect the CO net to the new driver and remember it in the new driver Abc_ObjAddFanin( pNet, pDriver->pCopy ); pDriver->pCopy->pCopy = pNet; } else { assert( !strcmp( Abc_ObjName(pDriver->pCopy->pCopy), Abc_ObjName(pObj) ) ); Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); } }
/**Function************************************************************* Synopsis [Create node and the net driven by it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs ) { Abc_Obj_t * pNet, * pNode; int i; // create a new node pNode = Abc_NtkCreateNode( pNtk ); // add the fanin nets for ( i = 0; i < nInputs; i++ ) { pNet = Abc_NtkFindOrCreateNet( pNtk, pNamesIn[i] ); Abc_ObjAddFanin( pNode, pNet ); } // add the fanout net pNet = Abc_NtkFindOrCreateNet( pNtk, pNameOut ); Abc_ObjAddFanin( pNet, pNode ); return pNode; }
// create the missing nets Abc_NtkForEachNode( pNtk, pObj, i ) { if ( pObj->pCopy->pCopy ) // the net of the new object is already created continue; // create the new net pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); // here we create ridiculous names net line "n48", where 48 is the ID of the node Abc_ObjAddFanin( pNet, pObj->pCopy ); pObj->pCopy->pCopy = pNet; }
/**Function************************************************************* Synopsis [Create a latch with the given input/output.] Description [By default, the latch value is unknown (ABC_INIT_NONE).] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ) { Abc_Obj_t * pLatch, * pTerm, * pNet; // get the LI net pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLI ); // add the BO terminal pTerm = Abc_NtkCreateBi( pNtk ); Abc_ObjAddFanin( pTerm, pNet ); // add the latch box pLatch = Abc_NtkCreateLatch( pNtk ); Abc_ObjAddFanin( pLatch, pTerm ); // add the BI terminal pTerm = Abc_NtkCreateBo( pNtk ); Abc_ObjAddFanin( pTerm, pLatch ); // get the LO net pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLO ); Abc_ObjAddFanin( pNet, pTerm ); // set latch name Abc_ObjAssignName( pLatch, pNetLO, "L" ); return pLatch; }
// create the fanouts of the box Abc_NtkForEachPo( pNtkModel, pObj, i ) { pActual = (char *)pObj->pCopy; if ( pActual == NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Formal output \"%s\" of model %s is not driven.", pName, (char*)Vec_PtrEntry(pNames, 0) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); Abc_ObjAddFanin( pNet, pBox ); }
/**Function************************************************************* Synopsis [Creates PO terminal and net.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreateAssert( Abc_Ntk_t * pNtk, char * pName ) { Abc_Obj_t * pNet, * pTerm; // get the PO net pNet = Abc_NtkFindNet( pNtk, pName ); if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) printf( "Warning: Assert \"%s\" appears twice in the list.\n", pName ); pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); // add the PO node pTerm = Abc_NtkCreateAssert( pNtk ); Abc_ObjAddFanin( pTerm, pNet ); return pTerm; }
/**Function************************************************************* Synopsis [Creates PI terminal and net.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName ) { Abc_Obj_t * pNet, * pTerm; // get the PI net pNet = Abc_NtkFindNet( pNtk, pName ); if ( pNet ) printf( "Warning: PI \"%s\" appears twice in the list.\n", pName ); pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); // add the PI node pTerm = Abc_NtkCreatePi( pNtk ); Abc_ObjAddFanin( pNet, pTerm ); return pTerm; }
/**Function************************************************************* Synopsis [Connect one box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkConnectBoxesOneBox( Io_ReadBlif_t * p, Abc_Obj_t * pBox, stmm_table * tName2Model ) { Vec_Ptr_t * pNames; Abc_Ntk_t * pNtkModel; Abc_Obj_t * pObj, * pNet; char * pName = NULL, * pActual; int i, Length, Start = -1; // get the model for this box pNames = (Vec_Ptr_t *)pBox->pData; if ( !stmm_lookup( tName2Model, (char *)Vec_PtrEntry(pNames, 0), (char **)&pNtkModel ) ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Cannot find the model for subcircuit %s.", (char*)Vec_PtrEntry(pNames, 0) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the fanins of the box Abc_NtkForEachPi( pNtkModel, pObj, i ) pObj->pCopy = NULL; if ( Abc_NtkPiNum(pNtkModel) == 0 ) Start = 1; else { Vec_PtrForEachEntryStart( char *, pNames, pName, i, 1 ) { pActual = Io_ReadBlifCleanName(pName); if ( pActual == NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); Io_ReadBlifPrintErrorMessage( p ); return 1; } Length = pActual - pName - 1; pName[Length] = 0; // find the PI net with this name pObj = Abc_NtkFindNet( pNtkModel, pName ); if ( pObj == NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Cannot find formal input \"%s\" as an PI of model \"%s\".", pName, (char*)Vec_PtrEntry(pNames, 0) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // get the PI pObj = Abc_ObjFanin0(pObj); // quit if this is not a PI net if ( !Abc_ObjIsPi(pObj) ) { pName[Length] = '='; Start = i; break; } // remember the actual name in the net if ( pObj->pCopy != NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Formal input \"%s\" is used more than once.", pName ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pObj->pCopy = (Abc_Obj_t *)pActual; // quit if we processed all PIs if ( i == Abc_NtkPiNum(pNtkModel) ) { Start = i+1; break; } } } // create the fanins of the box Abc_NtkForEachPi( pNtkModel, pObj, i ) { pActual = (char *)pObj->pCopy; if ( pActual == NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Formal input \"%s\" of model %s is not driven.", pName, (char*)Vec_PtrEntry(pNames, 0) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); Abc_ObjAddFanin( pBox, pNet ); }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ) { ProgressBar * pProgress; Vec_Ptr_t * vTokens; Abc_Ntk_t * pNtk; Abc_Obj_t * pNet, * pObj, * pFanout; char * pGateName, * pNetName; int fTokensReady, iLine, i; // read the first line vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); if ( strcmp( (char *)vTokens->pArray[0], "edif" ) != 0 ) { printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); return NULL; } // allocate the empty network pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); // go through the lines of the file fTokensReady = 0; pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); for ( iLine = 1; fTokensReady || (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p)); iLine++ ) { Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); // get the type of the line fTokensReady = 0; if ( strcmp( (char *)vTokens->pArray[0], "instance" ) == 0 ) { pNetName = (char *)vTokens->pArray[1]; pNet = Abc_NtkFindOrCreateNet( pNtk, pNetName ); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); pGateName = (char *)vTokens->pArray[1]; if ( strncmp( pGateName, "Flip", 4 ) == 0 ) { pObj = Abc_NtkCreateLatch( pNtk ); Abc_LatchSetInit0( pObj ); } else { pObj = Abc_NtkCreateNode( pNtk ); // pObj->pData = Abc_NtkRegisterName( pNtk, pGateName ); pObj->pData = Extra_UtilStrsav( pGateName ); // memory leak!!! } Abc_ObjAddFanin( pNet, pObj ); } else if ( strcmp( (char *)vTokens->pArray[0], "net" ) == 0 ) { pNetName = (char *)vTokens->pArray[1]; if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 ) continue; if ( strcmp( pNetName + strlen(pNetName) - 4, "_out" ) == 0 ) pNetName[strlen(pNetName) - 4] = 0; pNet = Abc_NtkFindNet( pNtk, pNetName ); assert( pNet ); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); while ( strcmp( (char *)vTokens->pArray[0], "portRef" ) == 0 ) { if ( strcmp( pNetName, (char *)vTokens->pArray[3] ) != 0 ) { pFanout = Abc_NtkFindNet( pNtk, (char *)vTokens->pArray[3] ); Abc_ObjAddFanin( Abc_ObjFanin0(pFanout), pNet ); } vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); } fTokensReady = 1; } else if ( strcmp( (char *)vTokens->pArray[0], "library" ) == 0 ) { vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); while ( strcmp( (char *)vTokens->pArray[0], "port" ) == 0 ) { pNetName = (char *)vTokens->pArray[1]; if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 ) { vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); continue; } if ( strcmp( pNetName + strlen(pNetName) - 3, "_PO" ) == 0 ) pNetName[strlen(pNetName) - 3] = 0; if ( strcmp( (char *)vTokens->pArray[3], "INPUT" ) == 0 ) Io_ReadCreatePi( pNtk, (char *)vTokens->pArray[1] ); else if ( strcmp( (char *)vTokens->pArray[3], "OUTPUT" ) == 0 ) Io_ReadCreatePo( pNtk, (char *)vTokens->pArray[1] ); else { printf( "%s (line %d): Wrong interface specification.\n", Extra_FileReaderGetFileName(p), iLine ); Abc_NtkDelete( pNtk ); return NULL; } vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); } } else if ( strcmp( (char *)vTokens->pArray[0], "design" ) == 0 ) { ABC_FREE( pNtk->pName ); pNtk->pName = (char *)Extra_UtilStrsav( (char *)vTokens->pArray[3] ); break; } } Extra_ProgressBarStop( pProgress ); // assign logic functions Abc_NtkForEachNode( pNtk, pObj, i ) { if ( strncmp( (char *)pObj->pData, "And", 3 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateAnd((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); else if ( strncmp( (char *)pObj->pData, "Or", 2 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateOr((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); else if ( strncmp( (char *)pObj->pData, "Nand", 4 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateNand((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); else if ( strncmp( (char *)pObj->pData, "Nor", 3 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateNor((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); else if ( strncmp( (char *)pObj->pData, "Exor", 4 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateXor((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); else if ( strncmp( (char *)pObj->pData, "Exnor", 5 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateNxor((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); else if ( strncmp( (char *)pObj->pData, "Inv", 3 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateInv((Mem_Flex_t *)pNtk->pManFunc) ); else if ( strncmp( (char *)pObj->pData, "Buf", 3 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateBuf((Mem_Flex_t *)pNtk->pManFunc) ); else { printf( "%s: Unknown gate type \"%s\".\n", Extra_FileReaderGetFileName(p), (char*)pObj->pData ); Abc_NtkDelete( pNtk ); return NULL; } } // check if constants have been added // if ( pNet = Abc_NtkFindNet( pNtk, "VDD" ) ) // Io_ReadCreateConst( pNtk, "VDD", 1 ); // if ( pNet = Abc_NtkFindNet( pNtk, "GND" ) ) // Io_ReadCreateConst( pNtk, "GND", 0 ); Abc_NtkFinalizeRead( pNtk ); return pNtk; }