/**CFile**************************************************************** FileName [ioReadBlif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to read BLIF files.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioReadBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "base/main/main.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Io_ReadBlif_t_ Io_ReadBlif_t; // all reading info struct Io_ReadBlif_t_ { // general info about file char * pFileName; // the name of the file Extra_FileReader_t * pReader; // the input file reader // current processing info Abc_Ntk_t * pNtkMaster; // the primary network Abc_Ntk_t * pNtkCur; // the primary network int LineCur; // the line currently parsed // temporary storage for tokens Vec_Ptr_t * vTokens; // the current tokens Vec_Ptr_t * vNewTokens; // the temporary storage for the tokens Vec_Str_t * vCubes; // the temporary storage for the tokens // the error message FILE * Output; // the output stream char sError[1000]; // the error string generated during parsing int fError; // set to 1 when error occurs }; static Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ); static void Io_ReadBlifFree( Io_ReadBlif_t * p ); static void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ); static Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ); static char * Io_ReadBlifCleanName( char * pName ); static Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ); static Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ); static int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ); static int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkDefaultOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkInputDrive( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkOutputLoad( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkDefaultInputDrive( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkDefaultOutputLoad( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkAndGateDelay( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the (hierarchical) network from the BLIF file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ) { Io_ReadBlif_t * p; Abc_Ntk_t * pNtk; // start the file p = Io_ReadBlifFile( pFileName ); if ( p == NULL ) return NULL; // read the hierarchical network pNtk = Io_ReadBlifNetwork( p ); if ( pNtk == NULL ) { Io_ReadBlifFree( p ); return NULL; } pNtk->pSpec = Extra_UtilStrsav( pFileName ); Abc_NtkTimeInitialize( pNtk, NULL ); Io_ReadBlifFree( p ); // make sure that everything is okay with the network structure if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) { printf( "Io_ReadBlif: The network check has failed.\n" ); Abc_NtkDelete( pNtk ); return NULL; } return pNtk; } /**Function************************************************************* Synopsis [Iteratively reads several networks in the hierarchical design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ) { Abc_Ntk_t * pNtk, * pNtkMaster; // read the name of the master network p->vTokens = Io_ReadBlifGetTokens(p); if ( p->vTokens == NULL || strcmp( (char *)p->vTokens->pArray[0], ".model" ) ) { p->LineCur = 0; sprintf( p->sError, "Wrong input file format." ); Io_ReadBlifPrintErrorMessage( p ); return NULL; } // read networks (with EXDC) pNtkMaster = NULL; while ( p->vTokens ) { // read the network and its EXDC if present pNtk = Io_ReadBlifNetworkOne( p ); if ( pNtk == NULL ) break; if ( p->vTokens && strcmp((char *)p->vTokens->pArray[0], ".exdc") == 0 ) { pNtk->pExdc = Io_ReadBlifNetworkOne( p ); if ( pNtk->pExdc == NULL ) break; Abc_NtkFinalizeRead( pNtk->pExdc ); } // add this network as part of the hierarchy if ( pNtkMaster == NULL ) // no master network so far { p->pNtkMaster = pNtkMaster = pNtk; continue; } /* // make sure hierarchy does not have the network with this name if ( pNtkMaster->tName2Model && stmm_is_member( pNtkMaster->tName2Model, pNtk->pName ) ) { p->LineCur = 0; sprintf( p->sError, "Model %s is multiply defined in the file.", pNtk->pName ); Io_ReadBlifPrintErrorMessage( p ); Abc_NtkDelete( pNtk ); Abc_NtkDelete( pNtkMaster ); pNtkMaster = NULL; return NULL; } // add the network to the hierarchy if ( pNtkMaster->tName2Model == NULL ) pNtkMaster->tName2Model = stmm_init_table((int (*)(void))strcmp, (int (*)(void))stmm_strhash); stmm_insert( pNtkMaster->tName2Model, pNtk->pName, (char *)pNtk ); */ } /* // if there is a hierarchy, connect the boxes if ( pNtkMaster && pNtkMaster->tName2Model ) { if ( Io_ReadBlifNetworkConnectBoxes( p, pNtkMaster ) ) { Abc_NtkDelete( pNtkMaster ); return NULL; } } else */ if ( !p->fError ) Abc_NtkFinalizeRead( pNtkMaster ); // return the master network return pNtkMaster; } /**Function************************************************************* Synopsis [Reads one (main or exdc) network from the BLIF file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ) { ProgressBar * pProgress = NULL; Abc_Ntk_t * pNtk; char * pDirective; int iLine, fTokensReady, fStatus; // make sure the tokens are present assert( p->vTokens != NULL ); // create the new network p->pNtkCur = pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); // read the model name if ( strcmp( (char *)p->vTokens->pArray[0], ".model" ) == 0 ) { char * pToken, * pPivot; if ( Vec_PtrSize(p->vTokens) != 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .model line does not have exactly two entries." ); Io_ReadBlifPrintErrorMessage( p ); return NULL; } for ( pPivot = pToken = (char *)Vec_PtrEntry(p->vTokens, 1); *pToken; pToken++ ) if ( *pToken == '/' || *pToken == '\\' ) pPivot = pToken+1; pNtk->pName = Extra_UtilStrsav( pPivot ); } else if ( strcmp( (char *)p->vTokens->pArray[0], ".exdc" ) != 0 ) { printf( "%s: File parsing skipped after line %d (\"%s\").\n", p->pFileName, Extra_FileReaderGetLineNumber(p->pReader, 0), (char*)p->vTokens->pArray[0] ); Abc_NtkDelete(pNtk); p->pNtkCur = NULL; return NULL; } // read the inputs/outputs if ( p->pNtkMaster == NULL ) pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p->pReader) ); fTokensReady = fStatus = 0; for ( iLine = 0; fTokensReady || (p->vTokens = Io_ReadBlifGetTokens(p)); iLine++ ) { if ( p->pNtkMaster == NULL && iLine % 1000 == 0 ) Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p->pReader), NULL ); // consider different line types fTokensReady = 0; pDirective = (char *)p->vTokens->pArray[0]; if ( !strcmp( pDirective, ".names" ) ) { fStatus = Io_ReadBlifNetworkNames( p, &p->vTokens ); fTokensReady = 1; } else if ( !strcmp( pDirective, ".gate" ) ) fStatus = Io_ReadBlifNetworkGate( p, p->vTokens ); else if ( !strcmp( pDirective, ".latch" ) ) fStatus = Io_ReadBlifNetworkLatch( p, p->vTokens ); else if ( !strcmp( pDirective, ".inputs" ) ) fStatus = Io_ReadBlifNetworkInputs( p, p->vTokens ); else if ( !strcmp( pDirective, ".outputs" ) ) fStatus = Io_ReadBlifNetworkOutputs( p, p->vTokens ); else if ( !strcmp( pDirective, ".input_arrival" ) ) fStatus = Io_ReadBlifNetworkInputArrival( p, p->vTokens ); else if ( !strcmp( pDirective, ".output_required" ) ) fStatus = Io_ReadBlifNetworkOutputRequired( p, p->vTokens ); else if ( !strcmp( pDirective, ".default_input_arrival" ) ) fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, p->vTokens ); else if ( !strcmp( pDirective, ".default_output_required" ) ) fStatus = Io_ReadBlifNetworkDefaultOutputRequired( p, p->vTokens ); else if ( !strcmp( pDirective, ".input_drive" ) ) fStatus = Io_ReadBlifNetworkInputDrive( p, p->vTokens ); else if ( !strcmp( pDirective, ".output_load" ) ) fStatus = Io_ReadBlifNetworkOutputLoad( p, p->vTokens ); else if ( !strcmp( pDirective, ".default_input_drive" ) ) fStatus = Io_ReadBlifNetworkDefaultInputDrive( p, p->vTokens ); else if ( !strcmp( pDirective, ".default_output_load" ) ) fStatus = Io_ReadBlifNetworkDefaultOutputLoad( p, p->vTokens ); else if ( !strcmp( pDirective, ".and_gate_delay" ) ) fStatus = Io_ReadBlifNetworkAndGateDelay( p, p->vTokens ); // else if ( !strcmp( pDirective, ".subckt" ) ) // fStatus = Io_ReadBlifNetworkSubcircuit( p, p->vTokens ); else if ( !strcmp( pDirective, ".exdc" ) ) break; else if ( !strcmp( pDirective, ".end" ) ) { p->vTokens = Io_ReadBlifGetTokens(p); break; } else if ( !strcmp( pDirective, ".blackbox" ) ) { pNtk->ntkType = ABC_NTK_NETLIST; pNtk->ntkFunc = ABC_FUNC_BLACKBOX; Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 ); pNtk->pManFunc = NULL; } else printf( "%s (line %d): Skipping directive \"%s\".\n", p->pFileName, Extra_FileReaderGetLineNumber(p->pReader, 0), pDirective ); if ( p->vTokens == NULL ) // some files do not have ".end" in the end break; if ( fStatus == 1 ) { Extra_ProgressBarStop( pProgress ); Abc_NtkDelete( pNtk ); return NULL; } } if ( p->pNtkMaster == NULL ) Extra_ProgressBarStop( pProgress ); return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { int i; for ( i = 1; i < vTokens->nSize; i++ ) Io_ReadCreatePi( p->pNtkCur, (char *)vTokens->pArray[i] ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { int i; for ( i = 1; i < vTokens->nSize; i++ ) Io_ReadCreatePo( p->pNtkCur, (char *)vTokens->pArray[i] ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Ntk_t * pNtk = p->pNtkCur; Abc_Obj_t * pLatch; int ResetValue; if ( vTokens->nSize < 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .latch line does not have enough tokens." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the latch pLatch = Io_ReadCreateLatch( pNtk, (char *)vTokens->pArray[1], (char *)vTokens->pArray[2] ); // get the latch reset value if ( vTokens->nSize == 3 ) Abc_LatchSetInitDc( pLatch ); else { ResetValue = atoi((char *)vTokens->pArray[vTokens->nSize-1]); if ( ResetValue != 0 && ResetValue != 1 && ResetValue != 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .latch line has an unknown reset value (%s).", (char*)vTokens->pArray[3] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } if ( ResetValue == 0 ) Abc_LatchSetInit0( pLatch ); else if ( ResetValue == 1 ) Abc_LatchSetInit1( pLatch ); else if ( ResetValue == 2 ) Abc_LatchSetInitDc( pLatch ); } return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ) { Vec_Ptr_t * vTokens = *pvTokens; Abc_Ntk_t * pNtk = p->pNtkCur; Abc_Obj_t * pNode; char * pToken, Char, ** ppNames; int nFanins, nNames; // create a new node and add it to the network if ( vTokens->nSize < 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .names line has less than two tokens." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the node ppNames = (char **)vTokens->pArray + 1; nNames = vTokens->nSize - 2; pNode = Io_ReadCreateNode( pNtk, ppNames[nNames], ppNames, nNames ); // derive the functionality of the node p->vCubes->nSize = 0; nFanins = vTokens->nSize - 2; if ( nFanins == 0 ) { while ( (vTokens = Io_ReadBlifGetTokens(p)) ) { pToken = (char *)vTokens->pArray[0]; if ( pToken[0] == '.' ) break; // read the cube if ( vTokens->nSize != 1 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The number of tokens in the constant cube is wrong." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the cube Char = ((char *)vTokens->pArray[0])[0]; Vec_StrPush( p->vCubes, ' ' ); Vec_StrPush( p->vCubes, Char ); Vec_StrPush( p->vCubes, '\n' ); } } else { while ( (vTokens = Io_ReadBlifGetTokens(p)) ) { pToken = (char *)vTokens->pArray[0]; if ( pToken[0] == '.' ) break; // read the cube if ( vTokens->nSize != 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The number of tokens in the cube is wrong." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the cube Vec_StrPrintStr( p->vCubes, (char *)vTokens->pArray[0] ); // check the char Char = ((char *)vTokens->pArray[1])[0]; if ( Char != '0' && Char != '1' && Char != 'x' && Char != 'n' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The output character in the constant cube is wrong." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } Vec_StrPush( p->vCubes, ' ' ); Vec_StrPush( p->vCubes, Char ); Vec_StrPush( p->vCubes, '\n' ); } } // if there is nothing there if ( p->vCubes->nSize == 0 ) { // create an empty cube Vec_StrPush( p->vCubes, ' ' ); Vec_StrPush( p->vCubes, '0' ); Vec_StrPush( p->vCubes, '\n' ); } Vec_StrPush( p->vCubes, 0 ); // set the pointer to the functionality of the node Abc_ObjSetData( pNode, Abc_SopRegister((Mem_Flex_t *)pNtk->pManFunc, p->vCubes->pArray) ); // check the size if ( Abc_ObjFaninNum(pNode) != Abc_SopGetVarNum((char *)Abc_ObjData(pNode)) ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The number of fanins (%d) of node %s is different from SOP size (%d).", Abc_ObjFaninNum(pNode), Abc_ObjName(Abc_ObjFanout(pNode,0)), Abc_SopGetVarNum((char *)Abc_ObjData(pNode)) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // return the last array of tokens *pvTokens = vTokens; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifReorderFormalNames( Vec_Ptr_t * vTokens, Mio_Gate_t * pGate, Mio_Gate_t * pTwin ) { Mio_Pin_t * pGatePin; char * pName, * pNamePin; int i, k, nSize, Length; nSize = Vec_PtrSize(vTokens); if ( pTwin == NULL ) { if ( nSize - 3 != Mio_GateReadPinNum(pGate) ) return 0; } else { if ( nSize - 3 != Mio_GateReadPinNum(pGate) && nSize - 4 != Mio_GateReadPinNum(pGate) ) return 0; } // check if the names are in order for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) { pNamePin = Mio_PinReadName(pGatePin); Length = strlen(pNamePin); pName = (char *)Vec_PtrEntry(vTokens, i+2); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) continue; break; } if ( pTwin == NULL ) { if ( i == Mio_GateReadPinNum(pGate) ) return 1; // reorder the pins for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) { pNamePin = Mio_PinReadName(pGatePin); Length = strlen(pNamePin); for ( k = 2; k < nSize; k++ ) { pName = (char *)Vec_PtrEntry(vTokens, k); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) { Vec_PtrPush( vTokens, pName ); break; } } } pNamePin = Mio_GateReadOutName(pGate); Length = strlen(pNamePin); for ( k = 2; k < nSize; k++ ) { pName = (char *)Vec_PtrEntry(vTokens, k); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) { Vec_PtrPush( vTokens, pName ); break; } } if ( Vec_PtrSize(vTokens) - nSize != nSize - 2 ) return 0; Vec_PtrForEachEntryStart( char *, vTokens, pName, k, nSize ) Vec_PtrWriteEntry( vTokens, k - nSize + 2, pName ); Vec_PtrShrink( vTokens, nSize ); } else { if ( i != Mio_GateReadPinNum(pGate) ) // expect the correct order of input pins in the network with twin gates return 0; // check the last two entries if ( nSize - 3 == Mio_GateReadPinNum(pGate) ) // only one output is available { pNamePin = Mio_GateReadOutName(pGate); Length = strlen(pNamePin); pName = (char *)Vec_PtrEntry(vTokens, nSize - 1); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) // the last entry is pGate { Vec_PtrPush( vTokens, NULL ); return 1; } pNamePin = Mio_GateReadOutName(pTwin); Length = strlen(pNamePin); pName = (char *)Vec_PtrEntry(vTokens, nSize - 1); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) // the last entry is pTwin { pName = (char *)Vec_PtrPop( vTokens ); Vec_PtrPush( vTokens, NULL ); Vec_PtrPush( vTokens, pName ); return 1; } return 0; } if ( nSize - 4 == Mio_GateReadPinNum(pGate) ) // two outputs are available { pNamePin = Mio_GateReadOutName(pGate); Length = strlen(pNamePin); pName = (char *)Vec_PtrEntry(vTokens, nSize - 2); if ( !(!strncmp( pNamePin, pName, Length ) && pName[Length] == '=') ) return 0; pNamePin = Mio_GateReadOutName(pTwin); Length = strlen(pNamePin); pName = (char *)Vec_PtrEntry(vTokens, nSize - 1); if ( !(!strncmp( pNamePin, pName, Length ) && pName[Length] == '=') ) return 0; return 1; } assert( 0 ); } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Mio_Library_t * pGenlib; Mio_Gate_t * pGate; Abc_Obj_t * pNode; char ** ppNames; int i, nNames; // check that the library is available pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen(); if ( pGenlib == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The current library is not available." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create a new node and add it to the network if ( vTokens->nSize < 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .gate line has less than two tokens." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // get the gate pGate = Mio_LibraryReadGateByName( pGenlib, (char *)vTokens->pArray[1], NULL ); if ( pGate == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Cannot find gate \"%s\" in the library.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // if this is the first line with gate, update the network type if ( Abc_NtkNodeNum(p->pNtkCur) == 0 ) { assert( p->pNtkCur->ntkFunc == ABC_FUNC_SOP ); p->pNtkCur->ntkFunc = ABC_FUNC_MAP; Mem_FlexStop( (Mem_Flex_t *)p->pNtkCur->pManFunc, 0 ); p->pNtkCur->pManFunc = pGenlib; } // reorder the formal inputs to be in the same order as in the gate if ( !Io_ReadBlifReorderFormalNames( vTokens, pGate, Mio_GateReadTwin(pGate) ) ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Mismatch in the fanins of gate \"%s\".", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // remove the formal parameter names for ( i = 2; i < vTokens->nSize; i++ ) { vTokens->pArray[i] = Io_ReadBlifCleanName( (char *)vTokens->pArray[i] ); if ( vTokens->pArray[i] == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Invalid gate input assignment." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } } // create the node if ( Mio_GateReadTwin(pGate) == NULL ) { nNames = vTokens->nSize - 3; ppNames = (char **)vTokens->pArray + 2; pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames ); Abc_ObjSetData( pNode, pGate ); } else { nNames = vTokens->nSize - 4; ppNames = (char **)vTokens->pArray + 2; assert( ppNames[nNames] != NULL || ppNames[nNames+1] != NULL ); if ( ppNames[nNames] ) { pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames ); Abc_ObjSetData( pNode, pGate ); } if ( ppNames[nNames+1] ) { pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames+1], ppNames, nNames ); Abc_ObjSetData( pNode, Mio_GateReadTwin(pGate) ); } } return 0; } /**Function************************************************************* Synopsis [Creates a multi-input multi-output box in the hierarchical design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Obj_t * pBox; Vec_Ptr_t * vNames; char * pName; int i; // create a new node and add it to the network if ( vTokens->nSize < 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .subcircuit line has less than three tokens." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // store the names of formal/actual inputs/outputs of the box vNames = Vec_PtrAlloc( 10 ); Vec_PtrForEachEntryStart( char *, vTokens, pName, i, 1 ) // Vec_PtrPush( vNames, Abc_NtkRegisterName(p->pNtkCur, pName) ); Vec_PtrPush( vNames, Extra_UtilStrsav(pName) ); // memory leak!!! // create a new box and add it to the network pBox = Abc_NtkCreateBlackbox( p->pNtkCur ); // set the pointer to the node names Abc_ObjSetData( pBox, vNames ); // remember the line of the file pBox->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Extra_FileReaderGetLineNumber(p->pReader, 0); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Io_ReadBlifCleanName( char * pName ) { int i, Length; Length = strlen(pName); for ( i = 0; i < Length; i++ ) if ( pName[i] == '=' ) return pName + i + 1; return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Obj_t * pNet; char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".input_arrival", 14 ) == 0 ); if ( vTokens->nSize != 4 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .input_arrival line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] ); if ( pNet == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Cannot find object corresponding to %s on .input_arrival line.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .input_arrival line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set the arrival time Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Obj_t * pNet; char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".output_required", 16 ) == 0 ); if ( vTokens->nSize != 4 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .output_required line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] ); if ( pNet == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Cannot find object corresponding to %s on .output_required line.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .output_required line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set the arrival time Abc_NtkTimeSetRequired( p->pNtkCur, Abc_ObjFanout0(pNet)->Id, (float)TimeRise, (float)TimeFall ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".default_input_arrival", 23 ) == 0 ); if ( vTokens->nSize != 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .default_input_arrival line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[1], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[2], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_input_arrival line.", (char*)vTokens->pArray[1], (char*)vTokens->pArray[2] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set the arrival time Abc_NtkTimeSetDefaultArrival( p->pNtkCur, (float)TimeRise, (float)TimeFall ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkDefaultOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".default_output_required", 25 ) == 0 ); if ( vTokens->nSize != 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .default_output_required line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[1], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[2], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_output_required line.", (char*)vTokens->pArray[1], (char*)vTokens->pArray[2] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set the arrival time Abc_NtkTimeSetDefaultRequired( p->pNtkCur, (float)TimeRise, (float)TimeFall ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadFindCiId( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) { Abc_Obj_t * pTemp; int i; Abc_NtkForEachCi( pNtk, pTemp, i ) if ( pTemp == pObj ) return i; return -1; } int Io_ReadBlifNetworkInputDrive( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Obj_t * pNet; char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".input_drive", 12 ) == 0 ); if ( vTokens->nSize != 4 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .input_drive line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] ); if ( pNet == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Cannot find object corresponding to %s on .input_drive line.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .input_drive line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set the arrival time Abc_NtkTimeSetInputDrive( p->pNtkCur, Io_ReadFindCiId(p->pNtkCur, Abc_NtkObj(p->pNtkCur, Abc_ObjFanin0(pNet)->Id)), (float)TimeRise, (float)TimeFall ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadFindCoId( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) { Abc_Obj_t * pTemp; int i; Abc_NtkForEachPo( pNtk, pTemp, i ) if ( pTemp == pObj ) return i; return -1; } int Io_ReadBlifNetworkOutputLoad( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Obj_t * pNet; char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".output_load", 12 ) == 0 ); if ( vTokens->nSize != 4 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .output_load line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] ); if ( pNet == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Cannot find object corresponding to %s on .output_load line.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .output_load line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set the arrival time Abc_NtkTimeSetOutputLoad( p->pNtkCur, Io_ReadFindCoId(p->pNtkCur, Abc_NtkObj(p->pNtkCur, Abc_ObjFanout0(pNet)->Id)), (float)TimeRise, (float)TimeFall ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkDefaultInputDrive( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".default_input_drive", 21 ) == 0 ); if ( vTokens->nSize != 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .default_input_drive line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[1], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[2], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_input_drive line.", (char*)vTokens->pArray[1], (char*)vTokens->pArray[2] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set the arrival time Abc_NtkTimeSetDefaultInputDrive( p->pNtkCur, (float)TimeRise, (float)TimeFall ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkDefaultOutputLoad( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".default_output_load", 21 ) == 0 ); if ( vTokens->nSize != 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .default_output_load line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[1], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[2], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_output_load line.", (char*)vTokens->pArray[1], (char*)vTokens->pArray[2] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set the arrival time Abc_NtkTimeSetDefaultOutputLoad( p->pNtkCur, (float)TimeRise, (float)TimeFall ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkAndGateDelay( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { char * pFoo1; double AndGateDelay; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".and_gate_delay", 25 ) == 0 ); if ( vTokens->nSize != 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments (%d) on .and_gate_delay line (should be 1).", vTokens->nSize-1 ); Io_ReadBlifPrintErrorMessage( p ); return 1; } AndGateDelay = strtod( (char *)vTokens->pArray[1], &pFoo1 ); if ( *pFoo1 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s) for AND gate delay in on .and_gate_delay line line.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set the arrival time p->pNtkCur->AndGateDelay = (float)AndGateDelay; return 0; } /**Function************************************************************* Synopsis [Prints the error message including the file name and line number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ) { p->fError = 1; if ( p->LineCur == 0 ) // the line number is not given fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); else // print the error message with the line number fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, p->LineCur, p->sError ); } /**Function************************************************************* Synopsis [Gets the tokens taking into account the line breaks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ) { Vec_Ptr_t * vTokens; char * pLastToken; int i; // get rid of the old tokens if ( p->vNewTokens->nSize > 0 ) { for ( i = 0; i < p->vNewTokens->nSize; i++ ) ABC_FREE( p->vNewTokens->pArray[i] ); p->vNewTokens->nSize = 0; } // get the new tokens vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p->pReader); if ( vTokens == NULL ) return vTokens; // check if there is a transfer to another line pLastToken = (char *)vTokens->pArray[vTokens->nSize - 1]; if ( pLastToken[ strlen(pLastToken)-1 ] != '\\' ) return vTokens; // remove the slash pLastToken[ strlen(pLastToken)-1 ] = 0; if ( pLastToken[0] == 0 ) vTokens->nSize--; // load them into the new array for ( i = 0; i < vTokens->nSize; i++ ) Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav((char *)vTokens->pArray[i]) ); // load as long as there is the line break while ( 1 ) { // get the new tokens vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p->pReader); if ( vTokens->nSize == 0 ) return p->vNewTokens; // check if there is a transfer to another line pLastToken = (char *)vTokens->pArray[vTokens->nSize - 1]; if ( pLastToken[ strlen(pLastToken)-1 ] == '\\' ) { // remove the slash pLastToken[ strlen(pLastToken)-1 ] = 0; if ( pLastToken[0] == 0 ) vTokens->nSize--; // load them into the new array for ( i = 0; i < vTokens->nSize; i++ ) Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav((char *)vTokens->pArray[i]) ); continue; } // otherwise, load them and break for ( i = 0; i < vTokens->nSize; i++ ) Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav((char *)vTokens->pArray[i]) ); break; } return p->vNewTokens; } /**Function************************************************************* Synopsis [Starts the reading data structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ) { Extra_FileReader_t * pReader; Io_ReadBlif_t * p; // start the reader pReader = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t" ); if ( pReader == NULL ) return NULL; // start the reading data structure p = ABC_ALLOC( Io_ReadBlif_t, 1 ); memset( p, 0, sizeof(Io_ReadBlif_t) ); p->pFileName = pFileName; p->pReader = pReader; p->Output = stdout; p->vNewTokens = Vec_PtrAlloc( 100 ); p->vCubes = Vec_StrAlloc( 100 ); return p; } /**Function************************************************************* Synopsis [Frees the data structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_ReadBlifFree( Io_ReadBlif_t * p ) { Extra_FileReaderFree( p->pReader ); Vec_PtrFree( p->vNewTokens ); Vec_StrFree( p->vCubes ); ABC_FREE( p ); } /**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 ); } Abc_NtkForEachPi( pNtkModel, pObj, i ) pObj->pCopy = NULL; // create the fanouts of the box Abc_NtkForEachPo( pNtkModel, pObj, i ) pObj->pCopy = NULL; Vec_PtrForEachEntryStart( char *, pNames, pName, i, Start ) { 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 PO 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 output \"%s\" as an PO of model \"%s\".", pName, (char*)Vec_PtrEntry(pNames, 0) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // get the PO pObj = Abc_ObjFanout0(pObj); if ( pObj->pCopy != NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Formal output \"%s\" is used more than once.", pName ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pObj->pCopy = (Abc_Obj_t *)pActual; } // 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 ); } Abc_NtkForEachPo( pNtkModel, pObj, i ) pObj->pCopy = NULL; // remove the array of names, assign the pointer to the model Vec_PtrForEachEntry( char *, (Vec_Ptr_t *)pBox->pData, pName, i ) ABC_FREE( pName ); Vec_PtrFree( (Vec_Ptr_t *)pBox->pData ); pBox->pData = pNtkModel; return 0; } /**Function************************************************************* Synopsis [Connect the boxes in the hierarchy of networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkConnectBoxesOne( Io_ReadBlif_t * p, Abc_Ntk_t * pNtk, stmm_table * tName2Model ) { Abc_Obj_t * pBox; int i; // go through the boxes Abc_NtkForEachBlackbox( pNtk, pBox, i ) if ( Io_ReadBlifNetworkConnectBoxesOneBox( p, pBox, tName2Model ) ) return 1; Abc_NtkFinalizeRead( pNtk ); return 0; } #if 0 /**Function************************************************************* Synopsis [Connect the boxes in the hierarchy of networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ) { stmm_generator * gen; Abc_Ntk_t * pNtk; char * pName; // connect the master network if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtkMaster, pNtkMaster->tName2Model ) ) return 1; // connect other networks stmm_foreach_item( pNtkMaster->tName2Model, gen, &pName, (char **)&pNtk ) if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtk, pNtkMaster->tName2Model ) ) return 1; return 0; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END