1 /**CFile****************************************************************
2 
3   FileName    [ioReadBlifAig.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Command processing package.]
8 
9   Synopsis    [Procedures to read BLIF file into AIG.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - December 23, 2006.]
16 
17   Revision    [$Id: ioReadBlifAig.c,v 1.00 2006/12/23 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "base/abc/abc.h"
22 #include "misc/vec/vecPtr.h"
23 
24 ABC_NAMESPACE_IMPL_START
25 
26 
27 ////////////////////////////////////////////////////////////////////////
28 ///                        DECLARATIONS                              ///
29 ////////////////////////////////////////////////////////////////////////
30 
31 // latch initial values
32 typedef enum {
33     IO_BLIF_INIT_NONE = 0,  // 0:  unknown
34     IO_BLIF_INIT_ZERO,      // 1:  zero
35     IO_BLIF_INIT_ONE,       // 2:  one
36     IO_BLIF_INIT_DC         // 3:  don't-care
37 } Io_BlifInit_t;
38 
39 typedef struct Io_BlifObj_t_ Io_BlifObj_t;  // parsing object
40 struct Io_BlifObj_t_
41 {
42     unsigned             fPi    :  1;  // the object is a primary input
43     unsigned             fPo    :  1;  // the object is a primary output
44     unsigned             fLi    :  1;  // the object is a latch input
45     unsigned             fLo    :  1;  // the object is a latch output
46     unsigned             fDef   :  1;  // the object is defined as a table (node, PO, LI)
47     unsigned             fLoop  :  1;  // flag for loop detection
48     unsigned             Init   :  2;  // the latch initial state
49     unsigned             Offset : 24;  // temporary number
50     char *               pName;        // the name of this object
51     void *               pEquiv;       // the AIG node representing this line
52     Io_BlifObj_t *       pNext;        // the next obj in the hash table
53 };
54 
55 typedef struct Io_BlifMan_t_ Io_BlifMan_t;  // parsing manager
56 struct Io_BlifMan_t_
57 {
58     // general info about file
59     char *               pFileName;    // the name of the file
60     char *               pBuffer;      // the begining of the file buffer
61     Vec_Ptr_t *          vLines;       // the line beginnings
62     // temporary objects
63     Io_BlifObj_t *       pObjects;     // the storage for objects
64     int                  nObjects;     // the number of objects allocated
65     int                  iObjNext;     // the next free object
66     // file lines
67     char *               pModel;       // .model line
68     Vec_Ptr_t *          vInputs;      // .inputs lines
69     Vec_Ptr_t *          vOutputs;     // .outputs lines
70     Vec_Ptr_t *          vLatches;     // .latches lines
71     Vec_Ptr_t *          vNames;       // .names lines
72     // network objects
73     Vec_Ptr_t *          vPis;         // the PI structures
74     Vec_Ptr_t *          vPos;         // the PO structures
75     Vec_Ptr_t *          vLis;         // the LI structures
76     Vec_Ptr_t *          vLos;         // the LO structures
77     // mapping of names into objects
78     Io_BlifObj_t **      pTable;       // the hash table
79     int                  nTableSize;   // the hash table size
80     // current processing info
81     Abc_Ntk_t *          pAig;         // the network under construction
82     Vec_Ptr_t *          vTokens;      // the current tokens
83     char                 sError[512];  // the error string generated during parsing
84     // statistics
85     int                  nTablesRead;  // the number of processed tables
86     int                  nTablesLeft;  // the number of dangling tables
87 };
88 
89 // static functions
90 static Io_BlifMan_t *    Io_BlifAlloc();
91 static void              Io_BlifFree( Io_BlifMan_t * p );
92 static char *            Io_BlifLoadFile( char * pFileName );
93 static void              Io_BlifReadPreparse( Io_BlifMan_t * p );
94 static Abc_Ntk_t *       Io_BlifParse( Io_BlifMan_t * p );
95 static int               Io_BlifParseModel( Io_BlifMan_t * p, char * pLine );
96 static int               Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine );
97 static int               Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine );
98 static int               Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine );
99 static int               Io_BlifParseNames( Io_BlifMan_t * p, char * pLine );
100 static int               Io_BlifParseConstruct( Io_BlifMan_t * p );
Io_BlifCharIsSpace(char s)101 static int               Io_BlifCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n';  }
102 
103 ////////////////////////////////////////////////////////////////////////
104 ///                     FUNCTION DEFINITIONS                         ///
105 ////////////////////////////////////////////////////////////////////////
106 
107 /**Function*************************************************************
108 
109   Synopsis    [Reads the network from the BLIF file as an AIG.]
110 
111   Description []
112 
113   SideEffects []
114 
115   SeeAlso     []
116 
117 ***********************************************************************/
Io_ReadBlifAsAig(char * pFileName,int fCheck)118 Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck )
119 {
120     FILE * pFile;
121     Io_BlifMan_t * p;
122     Abc_Ntk_t * pAig;
123 
124     // check that the file is available
125     pFile = fopen( pFileName, "rb" );
126     if ( pFile == NULL )
127     {
128         printf( "Io_Blif(): The file is unavailable (absent or open).\n" );
129         return 0;
130     }
131     fclose( pFile );
132 
133     // start the file reader
134     p = Io_BlifAlloc();
135     p->pFileName = pFileName;
136     p->pBuffer   = Io_BlifLoadFile( pFileName );
137     if ( p->pBuffer == NULL )
138     {
139         Io_BlifFree( p );
140         return NULL;
141     }
142     // prepare the file for parsing
143     Io_BlifReadPreparse( p );
144     // construct the network
145     pAig = Io_BlifParse( p );
146     if ( p->sError[0] )
147         fprintf( stdout, "%s\n", p->sError );
148     if ( pAig == NULL )
149         return NULL;
150     Io_BlifFree( p );
151 
152     // make sure that everything is okay with the network structure
153     if ( fCheck && !Abc_NtkCheckRead( pAig ) )
154     {
155         printf( "Io_Blif: The network check has failed.\n" );
156         Abc_NtkDelete( pAig );
157         return NULL;
158     }
159     return pAig;
160 }
161 
162 /**Function*************************************************************
163 
164   Synopsis    [Allocates the BLIF parsing structure.]
165 
166   Description []
167 
168   SideEffects []
169 
170   SeeAlso     []
171 
172 ***********************************************************************/
Io_BlifAlloc()173 static Io_BlifMan_t * Io_BlifAlloc()
174 {
175     Io_BlifMan_t * p;
176     p = ABC_ALLOC( Io_BlifMan_t, 1 );
177     memset( p, 0, sizeof(Io_BlifMan_t) );
178     p->vLines   = Vec_PtrAlloc( 512 );
179     p->vInputs  = Vec_PtrAlloc( 512 );
180     p->vOutputs = Vec_PtrAlloc( 512 );
181     p->vLatches = Vec_PtrAlloc( 512 );
182     p->vNames   = Vec_PtrAlloc( 512 );
183     p->vTokens  = Vec_PtrAlloc( 512 );
184     p->vPis     = Vec_PtrAlloc( 512 );
185     p->vPos     = Vec_PtrAlloc( 512 );
186     p->vLis     = Vec_PtrAlloc( 512 );
187     p->vLos     = Vec_PtrAlloc( 512 );
188     return p;
189 }
190 
191 /**Function*************************************************************
192 
193   Synopsis    [Frees the BLIF parsing structure.]
194 
195   Description []
196 
197   SideEffects []
198 
199   SeeAlso     []
200 
201 ***********************************************************************/
Io_BlifFree(Io_BlifMan_t * p)202 static void Io_BlifFree( Io_BlifMan_t * p )
203 {
204     if ( p->pAig )
205         Abc_NtkDelete( p->pAig );
206     if ( p->pBuffer )  ABC_FREE( p->pBuffer );
207     if ( p->pObjects ) ABC_FREE( p->pObjects );
208     if ( p->pTable )   ABC_FREE( p->pTable );
209     Vec_PtrFree( p->vLines );
210     Vec_PtrFree( p->vInputs );
211     Vec_PtrFree( p->vOutputs );
212     Vec_PtrFree( p->vLatches );
213     Vec_PtrFree( p->vNames );
214     Vec_PtrFree( p->vTokens );
215     Vec_PtrFree( p->vPis );
216     Vec_PtrFree( p->vPos );
217     Vec_PtrFree( p->vLis );
218     Vec_PtrFree( p->vLos );
219     ABC_FREE( p );
220 }
221 
222 
223 /**Function*************************************************************
224 
225   Synopsis    [Hashing for character strings.]
226 
227   Description []
228 
229   SideEffects []
230 
231   SeeAlso     []
232 
233 ***********************************************************************/
Io_BlifHashString(char * pName,int TableSize)234 static unsigned Io_BlifHashString( char * pName, int TableSize )
235 {
236     static int s_Primes[10] = {
237         1291, 1699, 2357, 4177, 5147,
238         5647, 6343, 7103, 7873, 8147
239     };
240     unsigned i, Key = 0;
241     for ( i = 0; pName[i] != '\0'; i++ )
242         Key ^= s_Primes[i%10]*pName[i]*pName[i];
243     return Key % TableSize;
244 }
245 
246 /**Function*************************************************************
247 
248   Synopsis    [Checks if the given name exists in the table.]
249 
250   Description []
251 
252   SideEffects []
253 
254   SeeAlso     []
255 
256 ***********************************************************************/
Io_BlifHashLookup(Io_BlifMan_t * p,char * pName)257 static Io_BlifObj_t ** Io_BlifHashLookup( Io_BlifMan_t * p, char * pName )
258 {
259     Io_BlifObj_t ** ppEntry;
260     for ( ppEntry = p->pTable + Io_BlifHashString(pName, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext )
261         if ( !strcmp((*ppEntry)->pName, pName) )
262             return ppEntry;
263     return ppEntry;
264 }
265 
266 /**Function*************************************************************
267 
268   Synopsis    [Finds or add the given name to the table.]
269 
270   Description []
271 
272   SideEffects []
273 
274   SeeAlso     []
275 
276 ***********************************************************************/
Io_BlifHashFindOrAdd(Io_BlifMan_t * p,char * pName)277 static Io_BlifObj_t * Io_BlifHashFindOrAdd( Io_BlifMan_t * p, char * pName )
278 {
279     Io_BlifObj_t ** ppEntry;
280     ppEntry = Io_BlifHashLookup( p, pName );
281     if ( *ppEntry == NULL )
282     {
283         assert( p->iObjNext < p->nObjects );
284         *ppEntry = p->pObjects + p->iObjNext++;
285         (*ppEntry)->pName = pName;
286     }
287     return *ppEntry;
288 }
289 
290 
291 /**Function*************************************************************
292 
293   Synopsis    [Collects the already split tokens.]
294 
295   Description []
296 
297   SideEffects []
298 
299   SeeAlso     []
300 
301 ***********************************************************************/
Io_BlifCollectTokens(Vec_Ptr_t * vTokens,char * pInput,char * pOutput)302 static void Io_BlifCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput )
303 {
304     char * pCur;
305     Vec_PtrClear( vTokens );
306     for ( pCur = pInput; pCur < pOutput; pCur++ )
307     {
308         if ( *pCur == 0 )
309             continue;
310         Vec_PtrPush( vTokens, pCur );
311         while ( *++pCur );
312     }
313 }
314 
315 /**Function*************************************************************
316 
317   Synopsis    [Splits the line into tokens.]
318 
319   Description []
320 
321   SideEffects []
322 
323   SeeAlso     []
324 
325 ***********************************************************************/
Io_BlifSplitIntoTokens(Vec_Ptr_t * vTokens,char * pLine,char Stop)326 static void Io_BlifSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop )
327 {
328     char * pCur;
329     // clear spaces
330     for ( pCur = pLine; *pCur != Stop; pCur++ )
331         if ( Io_BlifCharIsSpace(*pCur) )
332             *pCur = 0;
333     // collect tokens
334     Io_BlifCollectTokens( vTokens, pLine, pCur );
335 }
336 
337 /**Function*************************************************************
338 
339   Synopsis    [Returns the 1-based number of the line in which the token occurs.]
340 
341   Description []
342 
343   SideEffects []
344 
345   SeeAlso     []
346 
347 ***********************************************************************/
Io_BlifGetLine(Io_BlifMan_t * p,char * pToken)348 static int Io_BlifGetLine( Io_BlifMan_t * p, char * pToken )
349 {
350     char * pLine;
351     int i;
352     Vec_PtrForEachEntry( char *, p->vLines, pLine, i )
353         if ( pToken < pLine )
354             return i;
355     return -1;
356 }
357 
358 /**Function*************************************************************
359 
360   Synopsis    [Conservatively estimates the number of primary inputs.]
361 
362   Description []
363 
364   SideEffects []
365 
366   SeeAlso     []
367 
368 ***********************************************************************/
Io_BlifEstimatePiNum(Io_BlifMan_t * p)369 static int Io_BlifEstimatePiNum( Io_BlifMan_t * p )
370 {
371     char * pCur;
372     int i, fSpaces;
373     int Counter = 0;
374     Vec_PtrForEachEntry( char *, p->vInputs, pCur, i )
375         for ( fSpaces = 0; *pCur; pCur++ )
376         {
377             if ( Io_BlifCharIsSpace(*pCur) )
378             {
379                 if ( !fSpaces )
380                     Counter++;
381                 fSpaces = 1;
382             }
383             else
384                 fSpaces = 0;
385         }
386     return Counter;
387 }
388 
389 /**Function*************************************************************
390 
391   Synopsis    [Conservatively estimates the number of AIG nodes.]
392 
393   Description []
394 
395   SideEffects []
396 
397   SeeAlso     []
398 
399 ***********************************************************************/
Io_BlifEstimateAndNum(Io_BlifMan_t * p)400 static int Io_BlifEstimateAndNum( Io_BlifMan_t * p )
401 {
402     Io_BlifObj_t * pObj;
403     char * pCur;
404     int i, CounterOne, Counter = 0;
405     for ( i = 0; i < p->iObjNext; i++ )
406     {
407         pObj = p->pObjects + i;
408         if ( !pObj->fDef )
409             continue;
410         CounterOne = 0;
411         for ( pCur = pObj->pName + strlen(pObj->pName); *pCur != '.'; pCur++ )
412             if ( *pCur == '0' || *pCur == '1' )
413                 CounterOne++;
414         if ( CounterOne )
415             Counter += CounterOne - 1;
416     }
417     return Counter;
418 }
419 
420 /**Function*************************************************************
421 
422   Synopsis    [Reads the file into a character buffer.]
423 
424   Description []
425 
426   SideEffects []
427 
428   SeeAlso     []
429 
430 ***********************************************************************/
Io_BlifLoadFile(char * pFileName)431 static char * Io_BlifLoadFile( char * pFileName )
432 {
433     FILE * pFile;
434     int nFileSize;
435     char * pContents;
436     int RetValue;
437     pFile = fopen( pFileName, "rb" );
438     if ( pFile == NULL )
439     {
440         printf( "Io_BlifLoadFile(): The file is unavailable (absent or open).\n" );
441         return NULL;
442     }
443     fseek( pFile, 0, SEEK_END );
444     nFileSize = ftell( pFile );
445     if ( nFileSize == 0 )
446     {
447         fclose( pFile );
448         printf( "Io_BlifLoadFile(): The file is empty.\n" );
449         return NULL;
450     }
451     pContents = ABC_ALLOC( char, nFileSize + 10 );
452     rewind( pFile );
453     RetValue = fread( pContents, nFileSize, 1, pFile );
454     fclose( pFile );
455     // finish off the file with the spare .end line
456     // some benchmarks suddenly break off without this line
457     strcpy( pContents + nFileSize, "\n.end\n" );
458     return pContents;
459 }
460 
461 /**Function*************************************************************
462 
463   Synopsis    [Prepares the parsing.]
464 
465   Description [Performs several preliminary operations:
466   - Cuts the file buffer into separate lines.
467   - Removes comments and line extenders.
468   - Sorts lines by directives.
469   - Estimates the number of objects.
470   - Allocates room for the objects.
471   - Allocates room for the hash table.]
472 
473   SideEffects []
474 
475   SeeAlso     []
476 
477 ***********************************************************************/
Io_BlifReadPreparse(Io_BlifMan_t * p)478 static void Io_BlifReadPreparse( Io_BlifMan_t * p )
479 {
480     char * pCur, * pPrev;
481     int i, fComment = 0;
482     // parse the buffer into lines and remove comments
483     Vec_PtrPush( p->vLines, p->pBuffer );
484     for ( pCur = p->pBuffer; *pCur; pCur++ )
485     {
486         if ( *pCur == '\n' )
487         {
488             *pCur = 0;
489             fComment = 0;
490             Vec_PtrPush( p->vLines, pCur + 1 );
491         }
492         else if ( *pCur == '#' )
493             fComment = 1;
494         // remove comments
495         if ( fComment )
496             *pCur = 0;
497     }
498 
499     // unfold the line extensions and sort lines by directive
500     Vec_PtrForEachEntry( char *, p->vLines, pCur, i )
501     {
502         if ( *pCur == 0 )
503             continue;
504         // find previous non-space character
505         for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- )
506             if ( !Io_BlifCharIsSpace(*pPrev) )
507                 break;
508         // if it is the line extender, overwrite it with spaces
509         if ( *pPrev == '\\' )
510         {
511             for ( ; *pPrev; pPrev++ )
512                 *pPrev = ' ';
513             *pPrev = ' ';
514             continue;
515         }
516         // skip spaces at the beginning of the line
517         while ( Io_BlifCharIsSpace(*pCur++) );
518         // parse directives
519         if ( *(pCur-1) != '.' )
520             continue;
521         if ( !strncmp(pCur, "names", 5) )
522             Vec_PtrPush( p->vNames, pCur );
523         else if ( !strncmp(pCur, "latch", 5) )
524             Vec_PtrPush( p->vLatches, pCur );
525         else if ( !strncmp(pCur, "inputs", 6) )
526             Vec_PtrPush( p->vInputs, pCur );
527         else if ( !strncmp(pCur, "outputs", 7) )
528             Vec_PtrPush( p->vOutputs, pCur );
529         else if ( !strncmp(pCur, "model", 5) )
530             p->pModel = pCur;
531         else if ( !strncmp(pCur, "end", 3) || !strncmp(pCur, "exdc", 4) )
532             break;
533         else
534         {
535             pCur--;
536             if ( pCur[strlen(pCur)-1] == '\r' )
537                 pCur[strlen(pCur)-1] = 0;
538             fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_BlifGetLine(p, pCur), pCur );
539         }
540     }
541 
542     // count the number of objects
543     p->nObjects = Io_BlifEstimatePiNum(p) + Vec_PtrSize(p->vLatches) + Vec_PtrSize(p->vNames) + 512;
544 
545     // allocate memory for objects
546     p->pObjects = ABC_ALLOC( Io_BlifObj_t, p->nObjects );
547     memset( p->pObjects, 0, p->nObjects * sizeof(Io_BlifObj_t) );
548 
549     // allocate memory for the hash table
550     p->nTableSize = p->nObjects/2 + 1;
551     p->pTable = ABC_ALLOC( Io_BlifObj_t *, p->nTableSize );
552     memset( p->pTable, 0, p->nTableSize * sizeof(Io_BlifObj_t *) );
553 }
554 
555 
556 /**Function*************************************************************
557 
558   Synopsis    [Reads the AIG in the binary AIGER format.]
559 
560   Description []
561 
562   SideEffects []
563 
564   SeeAlso     []
565 
566 ***********************************************************************/
Io_BlifParse(Io_BlifMan_t * p)567 static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p )
568 {
569     Abc_Ntk_t * pAig;
570     char * pLine;
571     int i;
572     // parse the model
573     if ( !Io_BlifParseModel( p, p->pModel ) )
574         return NULL;
575     // parse the inputs
576     Vec_PtrForEachEntry( char *, p->vInputs, pLine, i )
577         if ( !Io_BlifParseInputs( p, pLine ) )
578             return NULL;
579     // parse the outputs
580     Vec_PtrForEachEntry( char *, p->vOutputs, pLine, i )
581         if ( !Io_BlifParseOutputs( p, pLine ) )
582             return NULL;
583     // parse the latches
584     Vec_PtrForEachEntry( char *, p->vLatches, pLine, i )
585         if ( !Io_BlifParseLatch( p, pLine ) )
586             return NULL;
587     // parse the nodes
588     Vec_PtrForEachEntry( char *, p->vNames, pLine, i )
589         if ( !Io_BlifParseNames( p, pLine ) )
590             return NULL;
591     // reconstruct the network from the parsed data
592     if ( !Io_BlifParseConstruct( p ) )
593         return NULL;
594     // return the network
595     pAig = p->pAig;
596     p->pAig = NULL;
597     return pAig;
598 }
599 
600 /**Function*************************************************************
601 
602   Synopsis    [Parses the model line.]
603 
604   Description []
605 
606   SideEffects []
607 
608   SeeAlso     []
609 
610 ***********************************************************************/
Io_BlifParseModel(Io_BlifMan_t * p,char * pLine)611 static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine )
612 {
613     char * pToken;
614     Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
615     pToken = (char *)Vec_PtrEntry( p->vTokens, 0 );
616     assert( !strcmp(pToken, "model") );
617     if ( Vec_PtrSize(p->vTokens) != 2 )
618     {
619         sprintf( p->sError, "Line %d: Model line has %d entries while it should have 2.", Io_BlifGetLine(p, pToken), Vec_PtrSize(p->vTokens) );
620         return 0;
621     }
622     p->pModel = (char *)Vec_PtrEntry( p->vTokens, 1 );
623     return 1;
624 }
625 
626 /**Function*************************************************************
627 
628   Synopsis    [Parses the inputs line.]
629 
630   Description []
631 
632   SideEffects []
633 
634   SeeAlso     []
635 
636 ***********************************************************************/
Io_BlifParseInputs(Io_BlifMan_t * p,char * pLine)637 static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine )
638 {
639     Io_BlifObj_t * pObj;
640     char * pToken;
641     int i;
642     Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
643     pToken = (char *)Vec_PtrEntry(p->vTokens, 0);
644     assert( !strcmp(pToken, "inputs") );
645     Vec_PtrForEachEntryStart( char *, p->vTokens, pToken, i, 1 )
646     {
647         pObj = Io_BlifHashFindOrAdd( p, pToken );
648         if ( pObj->fPi )
649         {
650             sprintf( p->sError, "Line %d: Primary input (%s) is defined more than once.", Io_BlifGetLine(p, pToken), pToken );
651             return 0;
652         }
653         pObj->fPi = 1;
654         Vec_PtrPush( p->vPis, pObj );
655     }
656     return 1;
657 }
658 
659 /**Function*************************************************************
660 
661   Synopsis    [Parses the outputs line.]
662 
663   Description []
664 
665   SideEffects []
666 
667   SeeAlso     []
668 
669 ***********************************************************************/
Io_BlifParseOutputs(Io_BlifMan_t * p,char * pLine)670 static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine )
671 {
672     Io_BlifObj_t * pObj;
673     char * pToken;
674     int i;
675     Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
676     pToken = (char *)Vec_PtrEntry(p->vTokens, 0);
677     assert( !strcmp(pToken, "outputs") );
678     Vec_PtrForEachEntryStart( char *, p->vTokens, pToken, i, 1 )
679     {
680         pObj = Io_BlifHashFindOrAdd( p, pToken );
681         if ( pObj->fPo )
682             fprintf( stdout, "Line %d: Primary output (%s) is defined more than once (warning only).\n", Io_BlifGetLine(p, pToken), pToken );
683         pObj->fPo = 1;
684         Vec_PtrPush( p->vPos, pObj );
685     }
686     return 1;
687 }
688 
689 /**Function*************************************************************
690 
691   Synopsis    [Parses the latches line.]
692 
693   Description []
694 
695   SideEffects []
696 
697   SeeAlso     []
698 
699 ***********************************************************************/
Io_BlifParseLatch(Io_BlifMan_t * p,char * pLine)700 static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine )
701 {
702     Io_BlifObj_t * pObj;
703     char * pToken;
704     int Init;
705     Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
706     pToken = (char *)Vec_PtrEntry(p->vTokens,0);
707     assert( !strcmp(pToken, "latch") );
708     if ( Vec_PtrSize(p->vTokens) < 3 )
709     {
710         sprintf( p->sError, "Line %d: Latch does not have input name and output name.", Io_BlifGetLine(p, pToken) );
711         return 0;
712     }
713     // get initial value
714     if ( Vec_PtrSize(p->vTokens) > 3 )
715         Init = atoi( (char *)Vec_PtrEntry(p->vTokens,3) );
716     else
717         Init = 2;
718     if ( Init < 0 || Init > 2 )
719     {
720         sprintf( p->sError, "Line %d: Initial state of the latch is incorrect (%s).", Io_BlifGetLine(p, pToken), (char*)Vec_PtrEntry(p->vTokens,3) );
721         return 0;
722     }
723     if ( Init == 0 )
724         Init = IO_BLIF_INIT_ZERO;
725     else if ( Init == 1 )
726         Init = IO_BLIF_INIT_ONE;
727     else // if ( Init == 2 )
728         Init = IO_BLIF_INIT_DC;
729     // get latch input
730     pObj = Io_BlifHashFindOrAdd( p, (char *)Vec_PtrEntry(p->vTokens,1) );
731     pObj->fLi = 1;
732     Vec_PtrPush( p->vLis, pObj );
733     pObj->Init = Init;
734     // get latch output
735     pObj = Io_BlifHashFindOrAdd( p, (char *)Vec_PtrEntry(p->vTokens,2) );
736     if ( pObj->fPi )
737     {
738         sprintf( p->sError, "Line %d: Primary input (%s) is also defined latch output.", Io_BlifGetLine(p, pToken), (char*)Vec_PtrEntry(p->vTokens,2) );
739         return 0;
740     }
741     if ( pObj->fLo )
742     {
743         sprintf( p->sError, "Line %d: Latch output (%s) is defined as the output of another latch.", Io_BlifGetLine(p, pToken), (char*)Vec_PtrEntry(p->vTokens,2) );
744         return 0;
745     }
746     pObj->fLo = 1;
747     Vec_PtrPush( p->vLos, pObj );
748     pObj->Init = Init;
749     return 1;
750 }
751 
752 /**Function*************************************************************
753 
754   Synopsis    [Parses the nodes line.]
755 
756   Description []
757 
758   SideEffects []
759 
760   SeeAlso     []
761 
762 ***********************************************************************/
Io_BlifParseNames(Io_BlifMan_t * p,char * pLine)763 static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine )
764 {
765     Io_BlifObj_t * pObj;
766     char * pName;
767     Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
768     assert( !strcmp((char *)Vec_PtrEntry(p->vTokens,0), "names") );
769     pName = (char *)Vec_PtrEntryLast( p->vTokens );
770     pObj = Io_BlifHashFindOrAdd( p, pName );
771     if ( pObj->fPi )
772     {
773         sprintf( p->sError, "Line %d: Primary input (%s) has a table.", Io_BlifGetLine(p, pName), pName );
774         return 0;
775     }
776     if ( pObj->fLo )
777     {
778         sprintf( p->sError, "Line %d: Latch output (%s) has a table.", Io_BlifGetLine(p, pName), pName );
779         return 0;
780     }
781     if ( pObj->fDef )
782     {
783         sprintf( p->sError, "Line %d: Signal (%s) is defined more than once.", Io_BlifGetLine(p, pName), pName );
784         return 0;
785     }
786     pObj->fDef = 1;
787     // remember offset to the first fanin name
788     pObj->pName = pName;
789     pObj->Offset = pObj->pName - (char *)Vec_PtrEntry(p->vTokens,1);
790     return 1;
791 }
792 
793 
794 /**Function*************************************************************
795 
796   Synopsis    [Constructs the AIG from the file parsing info.]
797 
798   Description []
799 
800   SideEffects []
801 
802   SeeAlso     []
803 
804 ***********************************************************************/
Io_BlifParseTable(Io_BlifMan_t * p,char * pTable,Vec_Ptr_t * vFanins)805 static Abc_Obj_t * Io_BlifParseTable( Io_BlifMan_t * p, char * pTable, Vec_Ptr_t * vFanins )
806 {
807     char * pProduct, * pOutput;
808     Abc_Obj_t * pRes, * pCube;
809     int i, k, Polarity = -1;
810 
811     p->nTablesRead++;
812     // get the tokens
813     Io_BlifSplitIntoTokens( p->vTokens, pTable, '.' );
814     if ( Vec_PtrSize(p->vTokens) == 0 )
815         return Abc_ObjNot( Abc_AigConst1(p->pAig) );
816     if ( Vec_PtrSize(p->vTokens) == 1 )
817     {
818         pOutput = (char *)Vec_PtrEntry( p->vTokens, 0 );
819         if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
820         {
821             sprintf( p->sError, "Line %d: Constant table has wrong output value (%s).", Io_BlifGetLine(p, pOutput), pOutput );
822             return NULL;
823         }
824         return Abc_ObjNotCond( Abc_AigConst1(p->pAig), pOutput[0] == '0' );
825     }
826     pProduct = (char *)Vec_PtrEntry( p->vTokens, 0 );
827     if ( Vec_PtrSize(p->vTokens) % 2 == 1 )
828     {
829         sprintf( p->sError, "Line %d: Table has odd number of tokens (%d).", Io_BlifGetLine(p, pProduct), Vec_PtrSize(p->vTokens) );
830         return NULL;
831     }
832     // parse the table
833     pRes = Abc_ObjNot( Abc_AigConst1(p->pAig) );
834     for ( i = 0; i < Vec_PtrSize(p->vTokens)/2; i++ )
835     {
836         pProduct = (char *)Vec_PtrEntry( p->vTokens, 2*i + 0 );
837         pOutput  = (char *)Vec_PtrEntry( p->vTokens, 2*i + 1 );
838         if ( strlen(pProduct) != (unsigned)Vec_PtrSize(vFanins) )
839         {
840             sprintf( p->sError, "Line %d: Cube (%s) has size different from the fanin count (%d).", Io_BlifGetLine(p, pProduct), pProduct, Vec_PtrSize(vFanins) );
841             return NULL;
842         }
843         if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
844         {
845             sprintf( p->sError, "Line %d: Output value (%s) is incorrect.", Io_BlifGetLine(p, pProduct), pOutput );
846             return NULL;
847         }
848         if ( Polarity == -1 )
849             Polarity = pOutput[0] - '0';
850         else if ( Polarity != pOutput[0] - '0' )
851         {
852             sprintf( p->sError, "Line %d: Output value (%s) differs from the value in the first line of the table (%d).", Io_BlifGetLine(p, pProduct), pOutput, Polarity );
853             return NULL;
854         }
855         // parse one product product
856         pCube = Abc_AigConst1(p->pAig);
857         for ( k = 0; pProduct[k]; k++ )
858         {
859             if ( pProduct[k] == '0' )
860                 pCube = Abc_AigAnd( (Abc_Aig_t *)p->pAig->pManFunc, pCube, Abc_ObjNot((Abc_Obj_t *)Vec_PtrEntry(vFanins,k)) );
861             else if ( pProduct[k] == '1' )
862                 pCube = Abc_AigAnd( (Abc_Aig_t *)p->pAig->pManFunc, pCube, (Abc_Obj_t *)Vec_PtrEntry(vFanins,k) );
863             else if ( pProduct[k] != '-' )
864             {
865                 sprintf( p->sError, "Line %d: Product term (%s) contains character (%c).", Io_BlifGetLine(p, pProduct), pProduct, pProduct[k] );
866                 return NULL;
867             }
868         }
869         pRes = Abc_AigOr( (Abc_Aig_t *)p->pAig->pManFunc, pRes, pCube );
870     }
871     pRes = Abc_ObjNotCond( pRes, Polarity == 0 );
872     return pRes;
873 }
874 
875 /**Function*************************************************************
876 
877   Synopsis    [Constructs the AIG from the file parsing info.]
878 
879   Description []
880 
881   SideEffects []
882 
883   SeeAlso     []
884 
885 ***********************************************************************/
Io_BlifParseConstruct_rec(Io_BlifMan_t * p,char * pName)886 static Abc_Obj_t * Io_BlifParseConstruct_rec( Io_BlifMan_t * p, char * pName )
887 {
888     Vec_Ptr_t * vFanins;
889     Abc_Obj_t * pFaninAbc;
890     Io_BlifObj_t * pObjIo;
891     char * pNameFanin;
892     int i;
893     // get the IO object with this name
894     pObjIo = *Io_BlifHashLookup( p, pName );
895     if ( pObjIo == NULL )
896     {
897         sprintf( p->sError, "Line %d: Signal (%s) is not defined as a table.", Io_BlifGetLine(p, pName), pName );
898         return NULL;
899     }
900     // loop detection
901     if ( pObjIo->fLoop )
902     {
903         sprintf( p->sError, "Line %d: Signal (%s) appears twice on a combinational path.", Io_BlifGetLine(p, pName), pName );
904         return NULL;
905     }
906     // check if the AIG is already constructed
907     if ( pObjIo->pEquiv )
908         return (Abc_Obj_t *)pObjIo->pEquiv;
909     // mark this node on the path
910     pObjIo->fLoop = 1;
911     // construct the AIGs for the fanins
912     vFanins = Vec_PtrAlloc( 8 );
913     Io_BlifCollectTokens( vFanins, pObjIo->pName - pObjIo->Offset, pObjIo->pName );
914     Vec_PtrForEachEntry( char *, vFanins, pNameFanin, i )
915     {
916         pFaninAbc = Io_BlifParseConstruct_rec( p, pNameFanin );
917         if ( pFaninAbc == NULL )
918         {
919             Vec_PtrFree( vFanins );
920             return NULL;
921         }
922         Vec_PtrWriteEntry( vFanins, i, pFaninAbc );
923     }
924     // construct the node
925     pObjIo->pEquiv = Io_BlifParseTable( p, pObjIo->pName + strlen(pObjIo->pName), vFanins );
926     Vec_PtrFree( vFanins );
927     // unmark this node on the path
928     pObjIo->fLoop = 0;
929     // remember the new node
930     return (Abc_Obj_t *)pObjIo->pEquiv;
931 }
932 
933 /**Function*************************************************************
934 
935   Synopsis    [Constructs the AIG from the file parsing info.]
936 
937   Description []
938 
939   SideEffects []
940 
941   SeeAlso     []
942 
943 ***********************************************************************/
Io_BlifParseConstruct(Io_BlifMan_t * p)944 static int Io_BlifParseConstruct( Io_BlifMan_t * p )
945 {
946     Abc_Ntk_t * pAig;
947     Io_BlifObj_t * pObjIo, * pObjIoInput;
948     Abc_Obj_t * pObj, * pLatch;
949     int i;
950     // allocate the empty AIG
951     pAig = p->pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
952     pAig->pName = Extra_UtilStrsav( p->pModel );
953     pAig->pSpec = Extra_UtilStrsav( p->pFileName );
954     // create PIs
955     Vec_PtrForEachEntry( Io_BlifObj_t *, p->vPis, pObjIo, i )
956     {
957         pObj = Abc_NtkCreatePi( pAig );
958         Abc_ObjAssignName( pObj, pObjIo->pName, NULL );
959         pObjIo->pEquiv = pObj;
960     }
961     // create POs
962     Vec_PtrForEachEntry( Io_BlifObj_t *, p->vPos, pObjIo, i )
963     {
964         pObj = Abc_NtkCreatePo( pAig );
965         Abc_ObjAssignName( pObj, pObjIo->pName, NULL );
966     }
967     // create latches
968     Vec_PtrForEachEntry( Io_BlifObj_t *, p->vLos, pObjIo, i )
969     {
970         // add the latch input terminal
971         pObj = Abc_NtkCreateBi( pAig );
972         pObjIoInput = (Io_BlifObj_t *)Vec_PtrEntry( p->vLis, i );
973         Abc_ObjAssignName( pObj, pObjIoInput->pName, NULL );
974 
975         // add the latch box
976         pLatch = Abc_NtkCreateLatch( pAig );
977         pLatch->pData = (void *)(ABC_PTRUINT_T)pObjIo->Init;
978         Abc_ObjAssignName( pLatch, pObjIo->pName, "L" );
979         Abc_ObjAddFanin( pLatch, pObj  );
980 
981         // add the latch output terminal
982         pObj = Abc_NtkCreateBo( pAig );
983         Abc_ObjAssignName( pObj, pObjIo->pName, NULL );
984         Abc_ObjAddFanin( pObj, pLatch );
985         // set the value of the latch output
986 //        pObjIo->pEquiv = Abc_ObjNotCond( pObj, pObjIo->Init );
987         pObjIo->pEquiv = pObj;
988     }
989     // traverse the nodes from the POs
990     Vec_PtrForEachEntry( Io_BlifObj_t *, p->vPos, pObjIo, i )
991     {
992         pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName );
993         if ( pObj == NULL )
994             return 0;
995         Abc_ObjAddFanin( Abc_NtkPo(p->pAig, i), pObj );
996     }
997     // traverse the nodes from the latch inputs
998     Vec_PtrForEachEntry( Io_BlifObj_t *, p->vLis, pObjIo, i )
999     {
1000         pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName );
1001         if ( pObj == NULL )
1002             return 0;
1003 //        pObj = Abc_ObjNotCond( pObj, pObjIo->Init );
1004         Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(p->pAig, i)), pObj );
1005     }
1006     p->nTablesLeft = Vec_PtrSize(p->vNames) - p->nTablesRead;
1007     if ( p->nTablesLeft )
1008         printf( "The number of dangling tables = %d.\n", p->nTablesLeft );
1009     printf( "AND nodes = %6d.  Estimate = %6d.\n", Abc_NtkNodeNum(p->pAig), Io_BlifEstimateAndNum(p) );
1010     return 1;
1011 }
1012 
1013 ////////////////////////////////////////////////////////////////////////
1014 ///                       END OF FILE                                ///
1015 ////////////////////////////////////////////////////////////////////////
1016 
1017 
1018 ABC_NAMESPACE_IMPL_END
1019 
1020