00001
00021 #include "abc.h"
00022 #include "extra.h"
00023 #include "vecPtr.h"
00024 #include "io.h"
00025
00029
00030 #define IO_BLIFMV_MAXVALUES 256
00031
00032 typedef struct Io_MvVar_t_ Io_MvVar_t;
00033 typedef struct Io_MvMod_t_ Io_MvMod_t;
00034 typedef struct Io_MvMan_t_ Io_MvMan_t;
00035
00036 struct Io_MvVar_t_
00037 {
00038 int nValues;
00039 char ** pNames;
00040 };
00041
00042 struct Io_MvMod_t_
00043 {
00044
00045 char * pName;
00046 Vec_Ptr_t * vInputs;
00047 Vec_Ptr_t * vOutputs;
00048 Vec_Ptr_t * vLatches;
00049 Vec_Ptr_t * vResets;
00050 Vec_Ptr_t * vNames;
00051 Vec_Ptr_t * vSubckts;
00052 Vec_Ptr_t * vMvs;
00053 int fBlackBox;
00054
00055 Abc_Ntk_t * pNtk;
00056 Abc_Obj_t * pResetLatch;
00057
00058 Io_MvMan_t * pMan;
00059 };
00060
00061 struct Io_MvMan_t_
00062 {
00063
00064 int fBlifMv;
00065 int fUseReset;
00066 char * pFileName;
00067 char * pBuffer;
00068 Vec_Ptr_t * vLines;
00069
00070 Abc_Lib_t * pDesign;
00071 int nNDnodes;
00072
00073 Vec_Ptr_t * vModels;
00074 Io_MvMod_t * pLatest;
00075
00076 Vec_Ptr_t * vTokens;
00077 Vec_Ptr_t * vTokens2;
00078 Vec_Str_t * vFunc;
00079
00080 char sError[512];
00081
00082 int nTablesRead;
00083 int nTablesLeft;
00084 };
00085
00086
00087 static Io_MvMan_t * Io_MvAlloc();
00088 static void Io_MvFree( Io_MvMan_t * p );
00089 static Io_MvMod_t * Io_MvModAlloc();
00090 static void Io_MvModFree( Io_MvMod_t * p );
00091 static char * Io_MvLoadFile( char * pFileName );
00092 static void Io_MvReadPreparse( Io_MvMan_t * p );
00093 static void Io_MvReadInterfaces( Io_MvMan_t * p );
00094 static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p );
00095 static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine );
00096 static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine );
00097 static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine );
00098 static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine );
00099 static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine );
00100 static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine );
00101 static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset );
00102 static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine );
00103 static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens );
00104 static Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar );
00105
00106 static int Io_MvCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; }
00107 static int Io_MvCharIsMvSymb( char s ) { return s == '(' || s == ')' || s == '{' || s == '}' || s == '-' || s == ',' || s == '!'; }
00108
00109 extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk );
00110
00114
00126 Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck )
00127 {
00128 FILE * pFile;
00129 Io_MvMan_t * p;
00130 Abc_Ntk_t * pNtk;
00131 Abc_Lib_t * pDesign;
00132 char * pDesignName;
00133 int RetValue, i;
00134
00135
00136 pFile = fopen( pFileName, "rb" );
00137 if ( pFile == NULL )
00138 {
00139 printf( "Io_ReadBlifMv(): The file is unavailable (absent or open).\n" );
00140 return 0;
00141 }
00142 fclose( pFile );
00143
00144
00145 p = Io_MvAlloc();
00146 p->fBlifMv = fBlifMv;
00147 p->fUseReset = 0;
00148 p->pFileName = pFileName;
00149 p->pBuffer = Io_MvLoadFile( pFileName );
00150 if ( p->pBuffer == NULL )
00151 {
00152 Io_MvFree( p );
00153 return NULL;
00154 }
00155
00156 pDesignName = Extra_FileNameGeneric( pFileName );
00157 p->pDesign = Abc_LibCreate( pDesignName );
00158 free( pDesignName );
00159
00160 Hop_ManStop( p->pDesign->pManFunc );
00161 p->pDesign->pManFunc = NULL;
00162
00163 Io_MvReadPreparse( p );
00164
00165 Io_MvReadInterfaces( p );
00166
00167 pDesign = Io_MvParse( p );
00168 if ( p->sError[0] )
00169 fprintf( stdout, "%s\n", p->sError );
00170 if ( pDesign == NULL )
00171 return NULL;
00172 Io_MvFree( p );
00173
00174
00175
00176 if ( fCheck )
00177 {
00178 Vec_PtrForEachEntry( pDesign->vModules, pNtk, i )
00179 {
00180 if ( !Abc_NtkCheckRead( pNtk ) )
00181 {
00182 printf( "Io_ReadBlifMv: The network check has failed for network %s.\n", pNtk->pName );
00183 Abc_LibFree( pDesign, NULL );
00184 return NULL;
00185 }
00186 }
00187 }
00188
00189
00190
00191
00192 RetValue = Abc_LibFindTopLevelModels( pDesign );
00193 pNtk = Vec_PtrEntry( pDesign->vTops, 0 );
00194 if ( RetValue > 1 )
00195 printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n",
00196 Vec_PtrSize(pDesign->vTops), pNtk->pName );
00197
00198
00199 pNtk->pDesign = pDesign;
00200 pDesign->pManFunc = NULL;
00201
00202
00203 assert( Vec_PtrSize(pDesign->vModules) > 0 );
00204 if ( Vec_PtrSize(pDesign->vModules) == 1 )
00205 {
00206
00207 Abc_LibFree( pDesign, pNtk );
00208 pNtk->pDesign = NULL;
00209 pNtk->pSpec = Extra_UtilStrsav( pFileName );
00210 }
00211 else
00212 Abc_NtkIsAcyclicHierarchy( pNtk );
00213
00214
00215 if ( pNtk->pSpec == NULL )
00216 pNtk->pSpec = Extra_UtilStrsav( pFileName );
00217 return pNtk;
00218 }
00219
00231 static Io_MvMan_t * Io_MvAlloc()
00232 {
00233 Io_MvMan_t * p;
00234 p = ALLOC( Io_MvMan_t, 1 );
00235 memset( p, 0, sizeof(Io_MvMan_t) );
00236 p->vLines = Vec_PtrAlloc( 512 );
00237 p->vModels = Vec_PtrAlloc( 512 );
00238 p->vTokens = Vec_PtrAlloc( 512 );
00239 p->vTokens2 = Vec_PtrAlloc( 512 );
00240 p->vFunc = Vec_StrAlloc( 512 );
00241 return p;
00242 }
00243
00255 static void Io_MvFree( Io_MvMan_t * p )
00256 {
00257 Io_MvMod_t * pMod;
00258 int i;
00259 if ( p->pDesign )
00260 Abc_LibFree( p->pDesign, NULL );
00261 if ( p->pBuffer )
00262 free( p->pBuffer );
00263 if ( p->vLines )
00264 Vec_PtrFree( p->vLines );
00265 if ( p->vModels )
00266 {
00267 Vec_PtrForEachEntry( p->vModels, pMod, i )
00268 Io_MvModFree( pMod );
00269 Vec_PtrFree( p->vModels );
00270 }
00271 Vec_PtrFree( p->vTokens );
00272 Vec_PtrFree( p->vTokens2 );
00273 Vec_StrFree( p->vFunc );
00274 free( p );
00275 }
00276
00288 static Io_MvMod_t * Io_MvModAlloc()
00289 {
00290 Io_MvMod_t * p;
00291 p = ALLOC( Io_MvMod_t, 1 );
00292 memset( p, 0, sizeof(Io_MvMod_t) );
00293 p->vInputs = Vec_PtrAlloc( 512 );
00294 p->vOutputs = Vec_PtrAlloc( 512 );
00295 p->vLatches = Vec_PtrAlloc( 512 );
00296 p->vResets = Vec_PtrAlloc( 512 );
00297 p->vNames = Vec_PtrAlloc( 512 );
00298 p->vSubckts = Vec_PtrAlloc( 512 );
00299 p->vMvs = Vec_PtrAlloc( 512 );
00300 return p;
00301 }
00302
00314 static void Io_MvModFree( Io_MvMod_t * p )
00315 {
00316
00317
00318 Vec_PtrFree( p->vInputs );
00319 Vec_PtrFree( p->vOutputs );
00320 Vec_PtrFree( p->vLatches );
00321 Vec_PtrFree( p->vResets );
00322 Vec_PtrFree( p->vNames );
00323 Vec_PtrFree( p->vSubckts );
00324 Vec_PtrFree( p->vMvs );
00325 free( p );
00326 }
00327
00328
00329
00341 static int Io_MvCountChars( char * pLine, char Char )
00342 {
00343 char * pCur;
00344 int Counter = 0;
00345 for ( pCur = pLine; *pCur; pCur++ )
00346 if ( *pCur == Char )
00347 Counter++;
00348 return Counter;
00349 }
00350
00362 static char * Io_MvFindArrow( char * pLine )
00363 {
00364 char * pCur;
00365 for ( pCur = pLine; *(pCur+1); pCur++ )
00366 if ( *pCur == '-' && *(pCur+1) == '>' )
00367 {
00368 *pCur = ' ';
00369 *(pCur+1) = ' ';
00370 return pCur;
00371 }
00372 return NULL;
00373 }
00374
00386 static void Io_MvCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput )
00387 {
00388 char * pCur;
00389 Vec_PtrClear( vTokens );
00390 for ( pCur = pInput; pCur < pOutput; pCur++ )
00391 {
00392 if ( *pCur == 0 )
00393 continue;
00394 Vec_PtrPush( vTokens, pCur );
00395 while ( *++pCur );
00396 }
00397 }
00398
00410 static void Io_MvSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop )
00411 {
00412 char * pCur;
00413
00414 for ( pCur = pLine; *pCur != Stop; pCur++ )
00415 if ( Io_MvCharIsSpace(*pCur) )
00416 *pCur = 0;
00417
00418 Io_MvCollectTokens( vTokens, pLine, pCur );
00419 }
00420
00432 static void Io_MvSplitIntoTokensMv( Vec_Ptr_t * vTokens, char * pLine )
00433 {
00434 char * pCur;
00435
00436 for ( pCur = pLine; *pCur != '.' || *(pCur+1) == 'd'; pCur++ )
00437 if ( Io_MvCharIsSpace(*pCur) )
00438 *pCur = 0;
00439
00440 Io_MvCollectTokens( vTokens, pLine, pCur );
00441 }
00442
00454 static void Io_MvSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char )
00455 {
00456 char * pCur;
00457
00458 for ( pCur = pLine; *pCur != Stop; pCur++ )
00459 if ( Io_MvCharIsSpace(*pCur) || *pCur == Char )
00460 *pCur = 0;
00461
00462 Io_MvCollectTokens( vTokens, pLine, pCur );
00463 }
00464
00476 static int Io_MvGetLine( Io_MvMan_t * p, char * pToken )
00477 {
00478 char * pLine;
00479 int i;
00480 Vec_PtrForEachEntry( p->vLines, pLine, i )
00481 if ( pToken < pLine )
00482 return i;
00483 return -1;
00484 }
00485
00497 static char * Io_MvLoadFile( char * pFileName )
00498 {
00499 FILE * pFile;
00500 int nFileSize;
00501 char * pContents;
00502 pFile = fopen( pFileName, "rb" );
00503 if ( pFile == NULL )
00504 {
00505 printf( "Io_MvLoadFile(): The file is unavailable (absent or open).\n" );
00506 return NULL;
00507 }
00508 fseek( pFile, 0, SEEK_END );
00509 nFileSize = ftell( pFile );
00510 if ( nFileSize == 0 )
00511 {
00512 printf( "Io_MvLoadFile(): The file is empty.\n" );
00513 return NULL;
00514 }
00515 pContents = ALLOC( char, nFileSize + 10 );
00516 rewind( pFile );
00517 fread( pContents, nFileSize, 1, pFile );
00518 fclose( pFile );
00519
00520
00521 strcpy( pContents + nFileSize, "\n.end\n" );
00522 return pContents;
00523 }
00524
00542 static void Io_MvReadPreparse( Io_MvMan_t * p )
00543 {
00544 char * pCur, * pPrev;
00545 int i, fComment = 0;
00546
00547 Vec_PtrPush( p->vLines, p->pBuffer );
00548 for ( pCur = p->pBuffer; *pCur; pCur++ )
00549 {
00550 if ( *pCur == '\n' )
00551 {
00552 *pCur = 0;
00553
00554
00555 fComment = 0;
00556 Vec_PtrPush( p->vLines, pCur + 1 );
00557 }
00558 else if ( *pCur == '#' )
00559 fComment = 1;
00560
00561 if ( fComment )
00562 *pCur = 0;
00563 }
00564
00565
00566 Vec_PtrForEachEntry( p->vLines, pCur, i )
00567 {
00568 if ( *pCur == 0 )
00569 continue;
00570
00571 for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- )
00572 if ( !Io_MvCharIsSpace(*pPrev) )
00573 break;
00574
00575 if ( *pPrev == '\\' )
00576 {
00577 for ( ; *pPrev; pPrev++ )
00578 *pPrev = ' ';
00579 *pPrev = ' ';
00580 continue;
00581 }
00582
00583 while ( Io_MvCharIsSpace(*pCur++) );
00584
00585 if ( *(pCur-1) != '.' )
00586 continue;
00587 if ( !strncmp(pCur, "names", 5) || !strncmp(pCur, "table", 5) || !strncmp(pCur, "gate", 4) )
00588 Vec_PtrPush( p->pLatest->vNames, pCur );
00589 else if ( p->fBlifMv && (!strncmp(pCur, "def ", 4) || !strncmp(pCur, "default ", 8)) )
00590 continue;
00591 else if ( !strncmp(pCur, "latch", 5) )
00592 Vec_PtrPush( p->pLatest->vLatches, pCur );
00593 else if ( !strncmp(pCur, "r ", 2) || !strncmp(pCur, "reset ", 6) )
00594 Vec_PtrPush( p->pLatest->vResets, pCur );
00595 else if ( !strncmp(pCur, "inputs", 6) )
00596 Vec_PtrPush( p->pLatest->vInputs, pCur );
00597 else if ( !strncmp(pCur, "outputs", 7) )
00598 Vec_PtrPush( p->pLatest->vOutputs, pCur );
00599 else if ( !strncmp(pCur, "subckt", 6) )
00600 Vec_PtrPush( p->pLatest->vSubckts, pCur );
00601 else if ( p->fBlifMv && !strncmp(pCur, "mv", 2) )
00602 Vec_PtrPush( p->pLatest->vMvs, pCur );
00603 else if ( !strncmp(pCur, "blackbox", 8) )
00604 p->pLatest->fBlackBox = 1;
00605 else if ( !strncmp(pCur, "model", 5) )
00606 {
00607 p->pLatest = Io_MvModAlloc();
00608 p->pLatest->pName = pCur;
00609 p->pLatest->pMan = p;
00610 }
00611 else if ( !strncmp(pCur, "end", 3) )
00612 {
00613 if ( p->pLatest )
00614 Vec_PtrPush( p->vModels, p->pLatest );
00615 p->pLatest = NULL;
00616 }
00617 else if ( !strncmp(pCur, "exdc", 4) )
00618 {
00619 fprintf( stdout, "Line %d: Skipping EXDC network.\n", Io_MvGetLine(p, pCur) );
00620 break;
00621 }
00622 else
00623 {
00624 pCur--;
00625 if ( pCur[strlen(pCur)-1] == '\r' )
00626 pCur[strlen(pCur)-1] = 0;
00627 fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_MvGetLine(p, pCur), pCur );
00628 }
00629 }
00630 }
00631
00643 static void Io_MvReadInterfaces( Io_MvMan_t * p )
00644 {
00645 Io_MvMod_t * pMod;
00646 char * pLine;
00647 int i, k;
00648
00649 Vec_PtrForEachEntry( p->vModels, pMod, i )
00650 {
00651
00652 if ( !Io_MvParseLineModel( pMod, pMod->pName ) )
00653 return;
00654
00655 if ( !Abc_LibAddModel( p->pDesign, pMod->pNtk ) )
00656 {
00657 sprintf( p->sError, "Line %d: Model %s is defined twice.", Io_MvGetLine(p, pMod->pName), pMod->pName );
00658 return;
00659 }
00660
00661 Vec_PtrForEachEntry( pMod->vInputs, pLine, k )
00662 if ( !Io_MvParseLineInputs( pMod, pLine ) )
00663 return;
00664
00665 Vec_PtrForEachEntry( pMod->vOutputs, pLine, k )
00666 if ( !Io_MvParseLineOutputs( pMod, pLine ) )
00667 return;
00668 }
00669 }
00670
00671
00683 static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p )
00684 {
00685 Abc_Lib_t * pDesign;
00686 Io_MvMod_t * pMod;
00687 char * pLine;
00688 int i, k;
00689
00690 Vec_PtrForEachEntry( p->vModels, pMod, i )
00691 {
00692
00693 if ( Vec_PtrSize(pMod->vMvs) > 0 )
00694 Abc_NtkStartMvVars( pMod->pNtk );
00695
00696 Vec_PtrForEachEntry( pMod->vMvs, pLine, k )
00697 if ( !Io_MvParseLineMv( pMod, pLine ) )
00698 return NULL;
00699
00700 if ( Vec_PtrSize(pMod->vResets) > 0 )
00701 {
00702 if ( Vec_PtrSize(pMod->vLatches) != Vec_PtrSize(pMod->vResets) )
00703 {
00704 sprintf( p->sError, "Line %d: Model %s has different number of latches (%d) and reset nodes (%d).",
00705 Io_MvGetLine(p, pMod->pName), Abc_NtkName(pMod->pNtk), Vec_PtrSize(pMod->vLatches), Vec_PtrSize(pMod->vResets) );
00706 return NULL;
00707 }
00708
00709 if ( p->fUseReset )
00710 pMod->pResetLatch = Io_ReadCreateResetLatch( pMod->pNtk, p->fBlifMv );
00711 }
00712
00713 Vec_PtrForEachEntry( pMod->vLatches, pLine, k )
00714 if ( !Io_MvParseLineLatch( pMod, pLine ) )
00715 return NULL;
00716
00717 if ( p->fUseReset )
00718 Vec_PtrForEachEntry( pMod->vResets, pLine, k )
00719 if ( !Io_MvParseLineNamesMv( pMod, pLine, 1 ) )
00720 return NULL;
00721
00722 if ( p->fBlifMv )
00723 {
00724 Vec_PtrForEachEntry( pMod->vNames, pLine, k )
00725 if ( !Io_MvParseLineNamesMv( pMod, pLine, 0 ) )
00726 return NULL;
00727 }
00728 else
00729 {
00730 Vec_PtrForEachEntry( pMod->vNames, pLine, k )
00731 if ( !Io_MvParseLineNamesBlif( pMod, pLine ) )
00732 return NULL;
00733 }
00734
00735 Vec_PtrForEachEntry( pMod->vSubckts, pLine, k )
00736 if ( !Io_MvParseLineSubckt( pMod, pLine ) )
00737 return NULL;
00738
00739 Abc_NtkFinalizeRead( pMod->pNtk );
00740 }
00741 if ( p->nNDnodes )
00742
00743 printf( "Warning: The parser added %d constant 0 nodes to replace non-deterministic nodes.\n", p->nNDnodes );
00744
00745 pDesign = p->pDesign;
00746 p->pDesign = NULL;
00747 return pDesign;
00748 }
00749
00761 static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine )
00762 {
00763 Vec_Ptr_t * vTokens = p->pMan->vTokens;
00764 char * pToken;
00765 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
00766 pToken = Vec_PtrEntry( vTokens, 0 );
00767 assert( !strcmp(pToken, "model") );
00768 if ( Vec_PtrSize(vTokens) != 2 )
00769 {
00770 sprintf( p->pMan->sError, "Line %d: Model line has %d entries while it should have 2.", Io_MvGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) );
00771 return 0;
00772 }
00773 if ( p->fBlackBox )
00774 p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, 1 );
00775 else if ( p->pMan->fBlifMv )
00776 p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLIFMV, 1 );
00777 else
00778 p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 );
00779 p->pNtk->pName = Extra_UtilStrsav( Vec_PtrEntry(vTokens, 1) );
00780 return 1;
00781 }
00782
00794 static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine )
00795 {
00796 Vec_Ptr_t * vTokens = p->pMan->vTokens;
00797 char * pToken;
00798 int i;
00799 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
00800 pToken = Vec_PtrEntry(vTokens, 0);
00801 assert( !strcmp(pToken, "inputs") );
00802 Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 )
00803 Io_ReadCreatePi( p->pNtk, pToken );
00804 return 1;
00805 }
00806
00818 static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine )
00819 {
00820 Vec_Ptr_t * vTokens = p->pMan->vTokens;
00821 char * pToken;
00822 int i;
00823 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
00824 pToken = Vec_PtrEntry(vTokens, 0);
00825 assert( !strcmp(pToken, "outputs") );
00826 Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 )
00827 Io_ReadCreatePo( p->pNtk, pToken );
00828 return 1;
00829 }
00830
00842 static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine )
00843 {
00844 Vec_Ptr_t * vTokens = p->pMan->vTokens;
00845 Abc_Obj_t * pObj, * pNet;
00846 char * pToken;
00847 int Init;
00848 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
00849 pToken = Vec_PtrEntry(vTokens,0);
00850 assert( !strcmp(pToken, "latch") );
00851 if ( Vec_PtrSize(vTokens) < 3 )
00852 {
00853 sprintf( p->pMan->sError, "Line %d: Latch does not have input name and output name.", Io_MvGetLine(p->pMan, pToken) );
00854 return 0;
00855 }
00856
00857 if ( p->pResetLatch == NULL )
00858 {
00859 pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Vec_PtrEntry(vTokens,2) );
00860
00861 if ( p->pMan->fBlifMv )
00862 Abc_LatchSetInit0( pObj );
00863 else
00864 {
00865 if ( Vec_PtrSize(vTokens) > 3 )
00866 Init = atoi( Vec_PtrEntry(vTokens,3) );
00867 else
00868 Init = 2;
00869 if ( Init < 0 || Init > 2 )
00870 {
00871 sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,3) );
00872 return 0;
00873 }
00874 if ( Init == 0 )
00875 Abc_LatchSetInit0( pObj );
00876 else if ( Init == 1 )
00877 Abc_LatchSetInit1( pObj );
00878 else
00879 Abc_LatchSetInitDc( pObj );
00880 }
00881 }
00882 else
00883 {
00884
00885 pNet = Abc_NtkFindOrCreateNet( p->pNtk, Vec_PtrEntry(vTokens,2) );
00886
00887 pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") );
00888
00889 pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) );
00890 Abc_LatchSetInit0( pObj );
00891 }
00892 return 1;
00893 }
00894
00906 static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine )
00907 {
00908 Vec_Ptr_t * vTokens = p->pMan->vTokens;
00909 Abc_Ntk_t * pModel;
00910 Abc_Obj_t * pBox, * pNet, * pTerm;
00911 char * pToken, * pName, ** ppNames;
00912 int nEquals, i, k;
00913
00914
00915 nEquals = Io_MvCountChars( pLine, '=' );
00916 Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' );
00917 pToken = Vec_PtrEntry(vTokens,0);
00918 assert( !strcmp(pToken, "subckt") );
00919
00920
00921 pName = Vec_PtrEntry(vTokens,1);
00922 pModel = Abc_LibFindModelByName( p->pMan->pDesign, pName );
00923 if ( pModel == NULL )
00924 {
00925 sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Io_MvGetLine(p->pMan, pToken), pName );
00926 return 0;
00927 }
00928
00929
00930 if ( nEquals != Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) )
00931 {
00932 sprintf( p->pMan->sError, "Line %d: The number of ports (%d) in .subckt differs from the sum of PIs and POs of the model (%d).",
00933 Io_MvGetLine(p->pMan, pToken), nEquals, Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) );
00934 return 0;
00935 }
00936
00937
00938 ppNames = (char **)Vec_PtrArray(vTokens) + 2 + p->pMan->fBlifMv;
00939
00940
00941 if ( Abc_NtkHasBlackbox(pModel) )
00942 pBox = Abc_NtkCreateBlackbox( p->pNtk );
00943 else
00944 pBox = Abc_NtkCreateWhitebox( p->pNtk );
00945 pBox->pData = pModel;
00946 if ( p->pMan->fBlifMv )
00947 Abc_ObjAssignName( pBox, Vec_PtrEntry(vTokens,2), NULL );
00948 Abc_NtkForEachPi( pModel, pTerm, i )
00949 {
00950
00951 pName = Abc_ObjName(Abc_ObjFanout0(pTerm));
00952 for ( k = 0; k < nEquals; k++ )
00953 if ( !strcmp( ppNames[2*k], pName ) )
00954 break;
00955 if ( k == nEquals )
00956 {
00957 sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.",
00958 Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) );
00959 return 0;
00960 }
00961
00962 pNet = Abc_NtkFindOrCreateNet( p->pNtk, ppNames[2*k+1] );
00963 pTerm = Abc_NtkCreateBi( p->pNtk );
00964 Abc_ObjAddFanin( pBox, pTerm );
00965 Abc_ObjAddFanin( pTerm, pNet );
00966 }
00967 Abc_NtkForEachPo( pModel, pTerm, i )
00968 {
00969
00970 pName = Abc_ObjName(Abc_ObjFanin0(pTerm));
00971 for ( k = 0; k < nEquals; k++ )
00972 if ( !strcmp( ppNames[2*k], pName ) )
00973 break;
00974 if ( k == nEquals )
00975 {
00976 sprintf( p->pMan->sError, "Line %d: Cannot find PO \"%s\" of the modell \"%s\" as a formal output of the subcircuit.",
00977 Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) );
00978 return 0;
00979 }
00980
00981 pNet = Abc_NtkFindOrCreateNet( p->pNtk, ppNames[2*k+1] );
00982 pTerm = Abc_NtkCreateBo( p->pNtk );
00983 Abc_ObjAddFanin( pNet, pTerm );
00984 Abc_ObjAddFanin( pTerm, pBox );
00985 }
00986 return 1;
00987 }
00988
00989
01001 static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine )
01002 {
01003 Vec_Ptr_t * vTokens = p->pMan->vTokens;
01004 Abc_Obj_t * pObj;
01005 Io_MvVar_t * pVar;
01006 Extra_MmFlex_t * pFlex;
01007 char * pName;
01008 int nCommas, nValues, i, k;
01009
01010 nCommas = Io_MvCountChars( pLine, ',' );
01011 Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', ',' );
01012 pName = Vec_PtrEntry(vTokens,0);
01013 assert( !strcmp(pName, "mv") );
01014
01015 if ( Vec_PtrSize(vTokens) <= nCommas + 2 )
01016 {
01017 sprintf( p->pMan->sError, "Line %d: The number of values in not specified in .mv line.", Io_MvGetLine(p->pMan, pName), pName );
01018 return 0;
01019 }
01020 nValues = atoi( Vec_PtrEntry(vTokens,nCommas+2) );
01021 if ( nValues < 2 || nValues > IO_BLIFMV_MAXVALUES )
01022 {
01023 sprintf( p->pMan->sError, "Line %d: The number of values (%d) is incorrect (should be >= 2 and <= %d).",
01024 Io_MvGetLine(p->pMan, pName), nValues, IO_BLIFMV_MAXVALUES );
01025 return 0;
01026 }
01027
01028 if ( nValues == 2 && Vec_PtrSize(vTokens) == nCommas + 3 )
01029 return 1;
01030 if ( Vec_PtrSize(vTokens) > nCommas + 3 && Vec_PtrSize(vTokens) - (nCommas + 3) != nValues )
01031 {
01032 sprintf( p->pMan->sError, "Line %d: Wrong number (%d) of symbolic value names (should be %d).",
01033 Io_MvGetLine(p->pMan, pName), Vec_PtrSize(vTokens) - (nCommas + 3), nValues );
01034 return 0;
01035 }
01036
01037 pFlex = Abc_NtkMvVarMan( p->pNtk );
01038 for ( i = 0; i <= nCommas; i++ )
01039 {
01040 pName = Vec_PtrEntry( vTokens, i+1 );
01041 pObj = Abc_NtkFindOrCreateNet( p->pNtk, pName );
01042
01043 pVar = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) );
01044 pVar->nValues = nValues;
01045 pVar->pNames = NULL;
01046
01047 if ( Vec_PtrSize(vTokens) > nCommas + 3 )
01048 {
01049 pVar->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * nValues );
01050 Vec_PtrForEachEntryStart( vTokens, pName, k, nCommas + 3 )
01051 {
01052 pVar->pNames[k-(nCommas + 3)] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pName) + 1 );
01053 strcpy( pVar->pNames[k-(nCommas + 3)], pName );
01054 }
01055 }
01056
01057 Abc_ObjSetMvVar( pObj, pVar );
01058 }
01059
01060 if ( pVar->pNames )
01061 {
01062 for ( i = 0; i < nValues; i++ )
01063 for ( k = i+1; k < nValues; k++ )
01064 if ( !strcmp(pVar->pNames[i], pVar->pNames[k]) )
01065 {
01066 pName = Vec_PtrEntry(vTokens,0);
01067 sprintf( p->pMan->sError, "Line %d: Symbolic value name \"%s\" is repeated in .mv line.",
01068 Io_MvGetLine(p->pMan, pName), pVar->pNames[i] );
01069 return 0;
01070 }
01071 }
01072 return 1;
01073 }
01074
01086 static int Io_MvWriteValues( Abc_Obj_t * pNode, Vec_Str_t * vFunc )
01087 {
01088 char Buffer[10];
01089 Abc_Obj_t * pFanin;
01090 int i;
01091
01092 Abc_ObjForEachFanin( pNode, pFanin, i )
01093 {
01094 sprintf( Buffer, "%d", Abc_ObjMvVarNum(pFanin) );
01095 Vec_StrAppend( vFunc, Buffer );
01096 Vec_StrPush( vFunc, ' ' );
01097 }
01098
01099 sprintf( Buffer, "%d", Abc_ObjMvVarNum(Abc_ObjFanout0(pNode)) );
01100 Vec_StrAppend( vFunc, Buffer );
01101 Vec_StrPush( vFunc, '\n' );
01102 return 1;
01103 }
01104
01116 static int Io_MvParseLiteralMv( Io_MvMod_t * p, Abc_Obj_t * pNode, char * pToken, Vec_Str_t * vFunc, int iLit )
01117 {
01118 char Buffer[10];
01119 Io_MvVar_t * pVar;
01120 Abc_Obj_t * pFanin, * pNet;
01121 char * pCur, * pNext;
01122 int i;
01123
01124 if ( pToken[0] == '=' )
01125 {
01126
01127 Abc_ObjForEachFanin( pNode, pFanin, i )
01128 if ( !strcmp( Abc_ObjName(pFanin), pToken + 1 ) )
01129 break;
01130 if ( i == Abc_ObjFaninNum(pNode) )
01131 {
01132 sprintf( p->pMan->sError, "Line %d: Node name in the table \"%s\" cannot be found on .names line.",
01133 Io_MvGetLine(p->pMan, pToken), pToken + 1 );
01134 return 0;
01135 }
01136 Vec_StrPush( vFunc, '=' );
01137 sprintf( Buffer, "%d", i );
01138 Vec_StrAppend( vFunc, Buffer );
01139 Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') );
01140 return 1;
01141 }
01142
01143 assert( iLit < Abc_ObjFaninNum(pNode) );
01144 pNet = iLit >= 0 ? Abc_ObjFanin(pNode, iLit) : Abc_ObjFanout0(pNode);
01145 pVar = Abc_ObjMvVar( pNet );
01146
01147 if ( pVar == NULL || pVar->pNames == NULL )
01148 {
01149 Vec_StrAppend( vFunc, pToken );
01150 Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') );
01151 return 1;
01152 }
01153
01154 for ( pCur = pToken; *pCur; pCur++ )
01155 {
01156 if ( Io_MvCharIsMvSymb(*pCur) )
01157 {
01158 Vec_StrPush( vFunc, *pCur );
01159 continue;
01160 }
01161
01162 for ( pNext = pCur+1; *pNext; pNext++ )
01163 if ( Io_MvCharIsMvSymb(*pNext) )
01164 break;
01165
01166 for ( i = 0; i < pVar->nValues; i++ )
01167 if ( !strncmp( pVar->pNames[i], pCur, pNext-pCur ) )
01168 break;
01169 if ( i == pVar->nValues )
01170 {
01171 *pNext = 0;
01172 sprintf( p->pMan->sError, "Line %d: Cannot find value name \"%s\" among the value names of variable \"%s\".",
01173 Io_MvGetLine(p->pMan, pToken), pCur, Abc_ObjName(pNet) );
01174 return 0;
01175 }
01176
01177 sprintf( Buffer, "%d", i );
01178 Vec_StrAppend( vFunc, Buffer );
01179
01180 pCur = pNext - 1;
01181 }
01182 Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') );
01183 return 1;
01184 }
01185
01197 static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut )
01198 {
01199 Vec_Str_t * vFunc = p->pMan->vFunc;
01200 char * pFirst, * pToken;
01201 int iStart, i;
01202
01203 Vec_StrClear( vFunc );
01204
01205
01206
01207 pFirst = Vec_PtrEntry( vTokens2, 0 );
01208 if ( pFirst[0] == '.' )
01209 {
01210
01211 Vec_StrPush( vFunc, 'd' );
01212 pToken = Vec_PtrEntry(vTokens2, 1 + iOut);
01213 if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) )
01214 return NULL;
01215 iStart = 1 + nOutputs;
01216 }
01217 else
01218 iStart = 0;
01219
01220 while ( iStart < Vec_PtrSize(vTokens2) )
01221 {
01222
01223 for ( i = 0; i < nInputs; i++ )
01224 {
01225 pToken = Vec_PtrEntry( vTokens2, iStart + i );
01226 if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, i ) )
01227 return NULL;
01228 }
01229
01230 pToken = Vec_PtrEntry( vTokens2, iStart + nInputs + iOut );
01231 if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) )
01232 return NULL;
01233
01234 iStart += nInputs + nOutputs;
01235 }
01236 Vec_StrPush( vFunc, '\0' );
01237 return Vec_StrArray( vFunc );
01238 }
01239
01251 static Abc_Obj_t * Io_MvParseAddResetCircuit( Io_MvMod_t * p, char * pName )
01252 {
01253 char Buffer[50];
01254 Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pOutNet;
01255 Io_MvVar_t * pVar;
01256
01257 assert( p->pResetLatch != NULL );
01258
01259 pResetLONet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch));
01260
01261 pOutNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
01262
01263 pData0Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_reset") );
01264 pData1Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_out") );
01265
01266 if ( Abc_NtkMvVar(p->pNtk) )
01267 {
01268 pVar = Abc_ObjMvVar( pOutNet );
01269 Abc_ObjSetMvVar( pData0Net, Abc_NtkMvVarDup(p->pNtk, pVar) );
01270 Abc_ObjSetMvVar( pData1Net, Abc_NtkMvVarDup(p->pNtk, pVar) );
01271 }
01272
01273 pNode = Abc_NtkCreateNode( p->pNtk );
01274
01275 Abc_ObjAddFanin( pOutNet, pNode );
01276
01277 if ( p->pMan->fBlifMv )
01278 {
01279
01280 int nValues = Abc_ObjMvVarNum(pOutNet);
01281
01282 sprintf( Buffer, "1 - - =1\n0 - - =2\n" );
01283 pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, Buffer );
01284 }
01285 else
01286 pNode->pData = Abc_SopCreateMux( p->pNtk->pManFunc );
01287
01288 Abc_ObjAddFanin( pNode, pResetLONet );
01289 Abc_ObjAddFanin( pNode, pData1Net );
01290 Abc_ObjAddFanin( pNode, pData0Net );
01291 return pData0Net;
01292 }
01293
01305 static int Io_MvParseLineNamesMvOne( Io_MvMod_t * p, Vec_Ptr_t * vTokens, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut, int fReset )
01306 {
01307 Abc_Obj_t * pNet, * pNode;
01308 char * pName;
01309
01310 pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + iOut );
01311
01312 if ( fReset )
01313 {
01314 pNet = Abc_NtkFindNet( p->pNtk, pName );
01315 if ( pNet == NULL )
01316 {
01317 sprintf( p->pMan->sError, "Line %d: Latch with output signal \"%s\" does not exist.", Io_MvGetLine(p->pMan, pName), pName );
01318 return 0;
01319 }
01320
01321
01322
01323
01324
01325
01326
01327
01328 pNet = Io_MvParseAddResetCircuit( p, pName );
01329
01330 pNode = Io_ReadCreateNode( p->pNtk, Abc_ObjName(pNet), (char **)(vTokens->pArray + 1), nInputs );
01331 assert( nInputs == Vec_PtrSize(vTokens) - 2 );
01332 }
01333 else
01334 {
01335 pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
01336 if ( Abc_ObjFaninNum(pNet) > 0 )
01337 {
01338 sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName );
01339 return 0;
01340 }
01341 pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), nInputs );
01342 }
01343
01344 pNode->pData = Io_MvParseTableMv( p, pNode, vTokens2, nInputs, nOutputs, iOut );
01345 if ( pNode->pData == NULL )
01346 return 0;
01347 pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, pNode->pData );
01348
01349 return 1;
01350 }
01351
01363 static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset )
01364 {
01365 Vec_Ptr_t * vTokens = p->pMan->vTokens;
01366 Vec_Ptr_t * vTokens2 = p->pMan->vTokens2;
01367 Abc_Obj_t * pNet;
01368 char * pName, * pFirst, * pArrow;
01369 int nInputs, nOutputs, nLiterals, nLines, i;
01370 assert( p->pMan->fBlifMv );
01371
01372 pArrow = Io_MvFindArrow( pLine );
01373 if ( !p->pMan->fBlifMv && pArrow )
01374 {
01375 sprintf( p->pMan->sError, "Line %d: Multi-output node symbol (->) in binary BLIF file.", Io_MvGetLine(p->pMan, pLine) );
01376 return 0;
01377 }
01378
01379 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
01380 if ( fReset )
01381 assert( !strcmp(Vec_PtrEntry(vTokens,0), "r") || !strcmp(Vec_PtrEntry(vTokens,0), "reset") );
01382 else
01383 assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") || !strcmp(Vec_PtrEntry(vTokens,0), "table") );
01384
01385 nInputs = Vec_PtrSize(vTokens) - 2;
01386 nOutputs = 1;
01387 if ( pArrow != NULL )
01388 {
01389 for ( i = Vec_PtrSize(vTokens) - 2; i >= 1; i-- )
01390 if ( pArrow < (char*)Vec_PtrEntry(vTokens,i) )
01391 {
01392 nInputs--;
01393 nOutputs++;
01394 }
01395 }
01396
01397 pName = Vec_PtrEntryLast( vTokens );
01398 Io_MvSplitIntoTokensMv( vTokens2, pName + strlen(pName) );
01399 pFirst = Vec_PtrEntry( vTokens2, 0 );
01400 if ( pFirst[0] == '.' )
01401 {
01402 assert( pFirst[1] == 'd' );
01403 nLiterals = Vec_PtrSize(vTokens2) - 1 - nOutputs;
01404 }
01405 else
01406 nLiterals = Vec_PtrSize(vTokens2);
01407
01408 if ( nLiterals % (nInputs + nOutputs) != 0 )
01409 {
01410 sprintf( p->pMan->sError, "Line %d: Wrong number of literals in the table of node \"%s\". (Spaces inside literals are not allowed.)", Io_MvGetLine(p->pMan, pFirst), pName );
01411 return 0;
01412 }
01413
01414 nLines = nLiterals / (nInputs + nOutputs);
01415 if ( nInputs == 0 && nLines > 1 )
01416 {
01417
01418 for ( i = 0; i < nOutputs; i++ )
01419 {
01420 pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + i );
01421
01422 pNet = Abc_NtkFindOrCreateNet(p->pNtk, pName);
01423 if ( fReset )
01424 {
01425 assert( p->pResetLatch != NULL );
01426
01427 pNet = Io_MvParseAddResetCircuit( p, pName );
01428 }
01429
01430
01431
01432 p->pMan->nNDnodes++;
01433 Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(p->pNtk) );
01434 }
01435 return 1;
01436 }
01437
01438 for ( i = 0; i < nOutputs; i++ )
01439 {
01440 if ( !Io_MvParseLineNamesMvOne( p, vTokens, vTokens2, nInputs, nOutputs, i, fReset ) )
01441 return 0;
01442 }
01443 return 1;
01444 }
01445
01446
01458 static char * Io_MvParseTableBlif( Io_MvMod_t * p, char * pTable, int nFanins )
01459 {
01460 Vec_Ptr_t * vTokens = p->pMan->vTokens;
01461 Vec_Str_t * vFunc = p->pMan->vFunc;
01462 char * pProduct, * pOutput;
01463 int i, Polarity = -1;
01464
01465 p->pMan->nTablesRead++;
01466
01467 Io_MvSplitIntoTokens( vTokens, pTable, '.' );
01468 if ( Vec_PtrSize(vTokens) == 0 )
01469 return Abc_SopCreateConst0( p->pNtk->pManFunc );
01470 if ( Vec_PtrSize(vTokens) == 1 )
01471 {
01472 pOutput = Vec_PtrEntry( vTokens, 0 );
01473 if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
01474 {
01475 sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Io_MvGetLine(p->pMan, pOutput), pOutput );
01476 return NULL;
01477 }
01478 return pOutput[0] == '0' ? Abc_SopCreateConst0(p->pNtk->pManFunc) : Abc_SopCreateConst1(p->pNtk->pManFunc);
01479 }
01480 pProduct = Vec_PtrEntry( vTokens, 0 );
01481 if ( Vec_PtrSize(vTokens) % 2 == 1 )
01482 {
01483 sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Io_MvGetLine(p->pMan, pProduct), Vec_PtrSize(vTokens) );
01484 return NULL;
01485 }
01486
01487 Vec_StrClear( vFunc );
01488 for ( i = 0; i < Vec_PtrSize(vTokens)/2; i++ )
01489 {
01490 pProduct = Vec_PtrEntry( vTokens, 2*i + 0 );
01491 pOutput = Vec_PtrEntry( vTokens, 2*i + 1 );
01492 if ( strlen(pProduct) != (unsigned)nFanins )
01493 {
01494 sprintf( p->pMan->sError, "Line %d: Cube \"%s\" has size different from the fanin count (%d).", Io_MvGetLine(p->pMan, pProduct), pProduct, nFanins );
01495 return NULL;
01496 }
01497 if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
01498 {
01499 sprintf( p->pMan->sError, "Line %d: Output value \"%s\" is incorrect.", Io_MvGetLine(p->pMan, pProduct), pOutput );
01500 return NULL;
01501 }
01502 if ( Polarity == -1 )
01503 Polarity = pOutput[0] - '0';
01504 else if ( Polarity != pOutput[0] - '0' )
01505 {
01506 sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Io_MvGetLine(p->pMan, pProduct), pOutput, Polarity );
01507 return NULL;
01508 }
01509
01510 Vec_StrAppend( vFunc, pProduct );
01511 Vec_StrPush( vFunc, ' ' );
01512 Vec_StrPush( vFunc, pOutput[0] );
01513 Vec_StrPush( vFunc, '\n' );
01514 }
01515 Vec_StrPush( vFunc, '\0' );
01516 return Vec_StrArray( vFunc );
01517 }
01518
01530 static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine )
01531 {
01532 Vec_Ptr_t * vTokens = p->pMan->vTokens;
01533 Abc_Obj_t * pNet, * pNode;
01534 char * pName;
01535 assert( !p->pMan->fBlifMv );
01536 Io_MvSplitIntoTokens( vTokens, pLine, '\0' );
01537
01538 if ( !strcmp(Vec_PtrEntry(vTokens,0), "gate") )
01539 return Io_MvParseLineGateBlif( p, vTokens );
01540
01541 assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") );
01542 pName = Vec_PtrEntryLast( vTokens );
01543 pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName );
01544 if ( Abc_ObjFaninNum(pNet) > 0 )
01545 {
01546 sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName );
01547 return 0;
01548 }
01549
01550 pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), Vec_PtrSize(vTokens) - 2 );
01551
01552 pNode->pData = Io_MvParseTableBlif( p, pName + strlen(pName), Abc_ObjFaninNum(pNode) );
01553 if ( pNode->pData == NULL )
01554 return 0;
01555 pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, pNode->pData );
01556 return 1;
01557 }
01558
01570 Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar )
01571 {
01572 Extra_MmFlex_t * pFlex;
01573 Io_MvVar_t * pVarDup;
01574 int i;
01575 if ( pVar == NULL )
01576 return NULL;
01577 pFlex = Abc_NtkMvVarMan( pNtk );
01578 assert( pFlex != NULL );
01579 pVarDup = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) );
01580 pVarDup->nValues = pVar->nValues;
01581 pVarDup->pNames = NULL;
01582 if ( pVar->pNames == NULL )
01583 return pVarDup;
01584 pVarDup->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * pVar->nValues );
01585 for ( i = 0; i < pVar->nValues; i++ )
01586 {
01587 pVarDup->pNames[i] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pVar->pNames[i]) + 1 );
01588 strcpy( pVarDup->pNames[i], pVar->pNames[i] );
01589 }
01590 return pVarDup;
01591 }
01592
01593
01594 #include "mio.h"
01595 #include "main.h"
01596
01608 static char * Io_ReadBlifCleanName( char * pName )
01609 {
01610 int i, Length;
01611 Length = strlen(pName);
01612 for ( i = 0; i < Length; i++ )
01613 if ( pName[i] == '=' )
01614 return pName + i + 1;
01615 return NULL;
01616 }
01617
01629 static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens )
01630 {
01631 Mio_Library_t * pGenlib;
01632 Mio_Gate_t * pGate;
01633 Abc_Obj_t * pNode;
01634 char ** ppNames, * pName;
01635 int i, nNames;
01636
01637 pName = vTokens->pArray[0];
01638
01639
01640 pGenlib = Abc_FrameReadLibGen();
01641 if ( pGenlib == NULL )
01642 {
01643 sprintf( p->pMan->sError, "Line %d: The current library is not available.", Io_MvGetLine(p->pMan, pName) );
01644 return 0;
01645 }
01646
01647
01648 if ( vTokens->nSize < 2 )
01649 {
01650 sprintf( p->pMan->sError, "Line %d: The .gate line has less than two tokens.", Io_MvGetLine(p->pMan, pName) );
01651 return 0;
01652 }
01653
01654
01655 pGate = Mio_LibraryReadGateByName( pGenlib, vTokens->pArray[1] );
01656 if ( pGate == NULL )
01657 {
01658 sprintf( p->pMan->sError, "Line %d: Cannot find gate \"%s\" in the library.", Io_MvGetLine(p->pMan, pName), vTokens->pArray[1] );
01659 return 0;
01660 }
01661
01662
01663 if ( Abc_NtkNodeNum(p->pNtk) == 0 )
01664 {
01665 assert( p->pNtk->ntkFunc == ABC_FUNC_SOP );
01666 p->pNtk->ntkFunc = ABC_FUNC_MAP;
01667 Extra_MmFlexStop( p->pNtk->pManFunc );
01668 p->pNtk->pManFunc = pGenlib;
01669 }
01670
01671
01672 for ( i = 2; i < vTokens->nSize; i++ )
01673 {
01674 vTokens->pArray[i] = Io_ReadBlifCleanName( vTokens->pArray[i] );
01675 if ( vTokens->pArray[i] == NULL )
01676 {
01677 sprintf( p->pMan->sError, "Line %d: Invalid gate input assignment.", Io_MvGetLine(p->pMan, pName) );
01678 return 0;
01679 }
01680 }
01681
01682
01683 ppNames = (char **)vTokens->pArray + 2;
01684 nNames = vTokens->nSize - 3;
01685 pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames );
01686
01687
01688 Abc_ObjSetData( pNode, pGate );
01689 return 1;
01690 }
01691
01695
01696