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