1 /**CFile****************************************************************
2 
3   FileName    [bacReadBlif.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Hierarchical word-level netlist.]
8 
9   Synopsis    [BLIF parser.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - November 29, 2014.]
16 
17   Revision    [$Id: bacReadBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "bac.h"
22 #include "bacPrs.h"
23 
24 ABC_NAMESPACE_IMPL_START
25 
26 ////////////////////////////////////////////////////////////////////////
27 ///                        DECLARATIONS                              ///
28 ////////////////////////////////////////////////////////////////////////
29 
30 // BLIF keywords
31 typedef enum {
32     PRS_BLIF_NONE = 0, // 0:   unused
33     PRS_BLIF_MODEL,    // 1:   .model
34     PRS_BLIF_INOUTS,   // 2:   .inouts
35     PRS_BLIF_INPUTS,   // 3:   .inputs
36     PRS_BLIF_OUTPUTS,  // 4:   .outputs
37     PRS_BLIF_NAMES,    // 5:   .names
38     PRS_BLIF_SUBCKT,   // 6:   .subckt
39     PRS_BLIF_GATE,     // 7:   .gate
40     PRS_BLIF_LATCH,    // 8:   .latch
41     PRS_BLIF_SHORT,    // 9:   .short
42     PRS_BLIF_END,      // 10:  .end
43     PRS_BLIF_UNKNOWN   // 11:  unknown
44 } Bac_BlifType_t;
45 
46 static const char * s_BlifTypes[PRS_BLIF_UNKNOWN+1] = {
47     NULL,              // 0:   unused
48     ".model",          // 1:   .model
49     ".inouts",         // 2:   .inputs
50     ".inputs",         // 3:   .inputs
51     ".outputs",        // 4:   .outputs
52     ".names",          // 5:   .names
53     ".subckt",         // 6:   .subckt
54     ".gate",           // 7:   .gate
55     ".latch",          // 8:   .latch
56     ".short",          // 9:   .short
57     ".end",            // 10:  .end
58     NULL               // 11:  unknown
59 };
60 
Psr_NtkAddBlifDirectives(Psr_Man_t * p)61 static inline void Psr_NtkAddBlifDirectives( Psr_Man_t * p )
62 {
63     int i;
64     for ( i = 1; s_BlifTypes[i]; i++ )
65         Abc_NamStrFindOrAdd( p->pStrs, (char *)s_BlifTypes[i], NULL );
66     assert( Abc_NamObjNumMax(p->pStrs) == i );
67 }
68 
69 
70 ////////////////////////////////////////////////////////////////////////
71 ///                     FUNCTION DEFINITIONS                         ///
72 ////////////////////////////////////////////////////////////////////////
73 
74 /**Function*************************************************************
75 
76   Synopsis    [Reading characters.]
77 
78   Description []
79 
80   SideEffects []
81 
82   SeeAlso     []
83 
84 ***********************************************************************/
Psr_CharIsSpace(char c)85 static inline int  Psr_CharIsSpace( char c )                { return c == ' ' || c == '\t' || c == '\r';              }
Psr_CharIsStop(char c)86 static inline int  Psr_CharIsStop( char c )                 { return c == '#' || c == '\\' || c == '\n' || c == '=';  }
Psr_CharIsLit(char c)87 static inline int  Psr_CharIsLit( char c )                  { return c == '0' || c == '1'  || c == '-';               }
88 
Psr_ManIsSpace(Psr_Man_t * p)89 static inline int  Psr_ManIsSpace( Psr_Man_t * p )          { return Psr_CharIsSpace(*p->pCur);                       }
Psr_ManIsStop(Psr_Man_t * p)90 static inline int  Psr_ManIsStop( Psr_Man_t * p )           { return Psr_CharIsStop(*p->pCur);                        }
Psr_ManIsLit(Psr_Man_t * p)91 static inline int  Psr_ManIsLit( Psr_Man_t * p )            { return Psr_CharIsLit(*p->pCur);                         }
92 
Psr_ManIsChar(Psr_Man_t * p,char c)93 static inline int  Psr_ManIsChar( Psr_Man_t * p, char c )   { return *p->pCur == c;                                   }
Psr_ManIsChar2(Psr_Man_t * p,char c)94 static inline int  Psr_ManIsChar2( Psr_Man_t * p, char c )  { return *p->pCur++ == c;                                 }
95 
Psr_ManSkip(Psr_Man_t * p)96 static inline void Psr_ManSkip( Psr_Man_t * p )             { p->pCur++;                                              }
Psr_ManSkip2(Psr_Man_t * p)97 static inline char Psr_ManSkip2( Psr_Man_t * p )            { return *p->pCur++;                                      }
98 
99 
100 /**Function*************************************************************
101 
102   Synopsis    [Reading names.]
103 
104   Description []
105 
106   SideEffects []
107 
108   SeeAlso     []
109 
110 ***********************************************************************/
Psr_ManSkipToChar(Psr_Man_t * p,char c)111 static inline void Psr_ManSkipToChar( Psr_Man_t * p, char c )
112 {
113     while ( !Psr_ManIsChar(p, c) )
114         Psr_ManSkip(p);
115 }
Psr_ManSkipSpaces(Psr_Man_t * p)116 static inline void Psr_ManSkipSpaces( Psr_Man_t * p )
117 {
118     while ( 1 )
119     {
120         while ( Psr_ManIsSpace(p) )
121             Psr_ManSkip(p);
122         if ( Psr_ManIsChar(p, '\\') )
123         {
124             Psr_ManSkipToChar( p, '\n' );
125             Psr_ManSkip(p);
126             continue;
127         }
128         if ( Psr_ManIsChar(p, '#') )
129             Psr_ManSkipToChar( p, '\n' );
130         break;
131     }
132     assert( !Psr_ManIsSpace(p) );
133 }
Psr_ManReadName(Psr_Man_t * p)134 static inline int Psr_ManReadName( Psr_Man_t * p )
135 {
136     char * pStart;
137     Psr_ManSkipSpaces( p );
138     if ( Psr_ManIsChar(p, '\n') )
139         return 0;
140     pStart = p->pCur;
141     while ( !Psr_ManIsSpace(p) && !Psr_ManIsStop(p) )
142         Psr_ManSkip(p);
143     if ( pStart == p->pCur )
144         return 0;
145     return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL );
146 }
Psr_ManReadList(Psr_Man_t * p,Vec_Int_t * vOrder,int Type)147 static inline int Psr_ManReadList( Psr_Man_t * p, Vec_Int_t * vOrder, int Type )
148 {
149     int iToken;
150     Vec_IntClear( &p->vTemp );
151     while ( (iToken = Psr_ManReadName(p)) )
152     {
153         Vec_IntPush( &p->vTemp, iToken );
154         Vec_IntPush( vOrder, Abc_Var2Lit2(iToken, Type) );
155     }
156     if ( Vec_IntSize(&p->vTemp) == 0 )                return Psr_ManErrorSet(p, "Signal list is empty.", 1);
157     return 0;
158 }
Psr_ManReadList2(Psr_Man_t * p)159 static inline int Psr_ManReadList2( Psr_Man_t * p )
160 {
161     int iToken;
162     Vec_IntClear( &p->vTemp );
163     while ( (iToken = Psr_ManReadName(p)) )
164         Vec_IntPushTwo( &p->vTemp, 0, iToken );
165     if ( Vec_IntSize(&p->vTemp) == 0 )                return Psr_ManErrorSet(p, "Signal list is empty.", 1);
166     return 0;
167 }
Psr_ManReadList3(Psr_Man_t * p)168 static inline int Psr_ManReadList3( Psr_Man_t * p )
169 {
170     Vec_IntClear( &p->vTemp );
171     while ( !Psr_ManIsChar(p, '\n') )
172     {
173         int iToken = Psr_ManReadName(p);
174         if ( iToken == 0 )              return Psr_ManErrorSet(p, "Cannot read formal name.", 1);
175         Vec_IntPush( &p->vTemp, iToken );
176         Psr_ManSkipSpaces( p );
177         if ( !Psr_ManIsChar2(p, '=') )  return Psr_ManErrorSet(p, "Cannot find symbol \"=\".", 1);
178         iToken = Psr_ManReadName(p);
179         if ( iToken == 0 )              return Psr_ManErrorSet(p, "Cannot read actual name.", 1);
180         Vec_IntPush( &p->vTemp, iToken );
181         Psr_ManSkipSpaces( p );
182     }
183     if ( Vec_IntSize(&p->vTemp) == 0 )  return Psr_ManErrorSet(p, "Cannot read a list of formal/actual names.", 1);
184     if ( Vec_IntSize(&p->vTemp) % 2  )  return Psr_ManErrorSet(p, "The number of formal/actual names is not even.", 1);
185     return 0;
186 }
187 
188 /**Function*************************************************************
189 
190   Synopsis    []
191 
192   Description []
193 
194   SideEffects []
195 
196   SeeAlso     []
197 
198 ***********************************************************************/
Psr_ManReadCube(Psr_Man_t * p)199 static inline int Psr_ManReadCube( Psr_Man_t * p )
200 {
201     assert( Psr_ManIsLit(p) );
202     while ( Psr_ManIsLit(p) )
203         Vec_StrPush( &p->vCover, Psr_ManSkip2(p) );
204     Psr_ManSkipSpaces( p );
205     if ( Psr_ManIsChar(p, '\n') )
206     {
207         if ( Vec_StrSize(&p->vCover) != 1 )           return Psr_ManErrorSet(p, "Cannot read cube.", 1);
208         // fix single literal cube by adding space
209         Vec_StrPush( &p->vCover, Vec_StrEntry(&p->vCover,0) );
210         Vec_StrWriteEntry( &p->vCover, 0, ' ' );
211         Vec_StrPush( &p->vCover, '\n' );
212         return 0;
213     }
214     if ( !Psr_ManIsLit(p) )                           return Psr_ManErrorSet(p, "Cannot read output literal.", 1);
215     Vec_StrPush( &p->vCover, ' ' );
216     Vec_StrPush( &p->vCover, Psr_ManSkip2(p) );
217     Vec_StrPush( &p->vCover, '\n' );
218     Psr_ManSkipSpaces( p );
219     if ( !Psr_ManIsChar(p, '\n') )                    return Psr_ManErrorSet(p, "Cannot read end of cube.", 1);
220     return 0;
221 }
Psr_ManSaveCover(Psr_Man_t * p)222 static inline void Psr_ManSaveCover( Psr_Man_t * p )
223 {
224     int iToken;
225     if ( Vec_StrSize(&p->vCover) == 0 )
226         p->pNtk->fHasC0s = 1;
227     else if ( Vec_StrSize(&p->vCover) == 2 )
228     {
229         if ( Vec_StrEntryLast(&p->vCover) == '0' )
230             p->pNtk->fHasC0s = 1;
231         else if ( Vec_StrEntryLast(&p->vCover) == '1' )
232             p->pNtk->fHasC1s = 1;
233         else assert( 0 );
234     }
235     assert( Vec_StrSize(&p->vCover) > 0 );
236     Vec_StrPush( &p->vCover, '\0' );
237     //iToken = Abc_NamStrFindOrAdd( p->pStrs, Vec_StrArray(&p->vCover), NULL );
238     iToken = Ptr_SopToType( Vec_StrArray(&p->vCover) );
239     Vec_StrClear( &p->vCover );
240     // set the cover to the module of this box
241     assert( Psr_BoxNtk(p->pNtk, Psr_NtkBoxNum(p->pNtk)-1) == 1 ); // default const 0
242     Psr_BoxSetNtk( p->pNtk, Psr_NtkBoxNum(p->pNtk)-1, iToken );
243 }
244 
245 /**Function*************************************************************
246 
247   Synopsis    []
248 
249   Description []
250 
251   SideEffects []
252 
253   SeeAlso     []
254 
255 ***********************************************************************/
Psr_ManReadInouts(Psr_Man_t * p)256 static inline int Psr_ManReadInouts( Psr_Man_t * p )
257 {
258     if ( Psr_ManReadList(p, &p->pNtk->vOrder, 3) )    return 1;
259     Vec_IntAppend( &p->pNtk->vInouts, &p->vTemp );
260     return 0;
261 }
Psr_ManReadInputs(Psr_Man_t * p)262 static inline int Psr_ManReadInputs( Psr_Man_t * p )
263 {
264     if ( Psr_ManReadList(p, &p->pNtk->vOrder, 1) )    return 1;
265     Vec_IntAppend( &p->pNtk->vInputs, &p->vTemp );
266     return 0;
267 }
Psr_ManReadOutputs(Psr_Man_t * p)268 static inline int Psr_ManReadOutputs( Psr_Man_t * p )
269 {
270     if ( Psr_ManReadList(p, &p->pNtk->vOrder, 2) )    return 1;
271     Vec_IntAppend( &p->pNtk->vOutputs, &p->vTemp );
272     return 0;
273 }
Psr_ManReadNode(Psr_Man_t * p)274 static inline int Psr_ManReadNode( Psr_Man_t * p )
275 {
276     if ( Psr_ManReadList2(p) )   return 1;
277     // save results
278     Psr_NtkAddBox( p->pNtk, 1, 0, &p->vTemp ); // default const 0 function
279     return 0;
280 }
Psr_ManReadBox(Psr_Man_t * p,int fGate)281 static inline int Psr_ManReadBox( Psr_Man_t * p, int fGate )
282 {
283     int iToken = Psr_ManReadName(p);
284     if ( iToken == 0 )           return Psr_ManErrorSet(p, "Cannot read model name.", 1);
285     if ( Psr_ManReadList3(p) )   return 1;
286     // save results
287     Psr_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
288     if ( fGate ) p->pNtk->fMapped = 1;
289     return 0;
290 }
Psr_ManReadLatch(Psr_Man_t * p)291 static inline int Psr_ManReadLatch( Psr_Man_t * p )
292 {
293     int iToken = Psr_ManReadName(p);
294     Vec_IntClear( &p->vTemp );
295     if ( iToken == 0 )                 return Psr_ManErrorSet(p, "Cannot read latch input.", 1);
296     Vec_IntWriteEntry( &p->vTemp, 1, iToken );
297     iToken = Psr_ManReadName(p);
298     if ( iToken == 0 )                 return Psr_ManErrorSet(p, "Cannot read latch output.", 1);
299     Vec_IntWriteEntry( &p->vTemp, 0, iToken );
300     Psr_ManSkipSpaces( p );
301     if ( Psr_ManIsChar(p, '0') )
302         iToken = 0;
303     else if ( Psr_ManIsChar(p, '1') )
304         iToken = 1;
305     else
306         iToken = 2;
307     Psr_ManSkipToChar( p, '\n' );
308     // save results
309     Psr_NtkAddBox( p->pNtk, -1, iToken, &p->vTemp ); // -1 stands for latch
310     return 0;
311 }
Psr_ManReadShort(Psr_Man_t * p)312 static inline int Psr_ManReadShort( Psr_Man_t * p )
313 {
314     int iToken = Psr_ManReadName(p);
315     Vec_IntClear( &p->vTemp );
316     if ( iToken == 0 )                 return Psr_ManErrorSet(p, "Cannot read .short input.", 1);
317     Vec_IntWriteEntry( &p->vTemp, 1, iToken );
318     iToken = Psr_ManReadName(p);
319     if ( iToken == 0 )                 return Psr_ManErrorSet(p, "Cannot read .short output.", 1);
320     Vec_IntWriteEntry( &p->vTemp, 0, iToken );
321     Psr_ManSkipSpaces( p );
322     if ( !Psr_ManIsChar(p, '\n') )     return Psr_ManErrorSet(p, "Trailing symbols on .short line.", 1);
323     // save results
324     iToken = Abc_NamStrFindOrAdd( p->pStrs, "1 1\n", NULL );
325     Psr_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
326     return 0;
327 }
Psr_ManReadModel(Psr_Man_t * p)328 static inline int Psr_ManReadModel( Psr_Man_t * p )
329 {
330     int iToken;
331     if ( p->pNtk != NULL )                         return Psr_ManErrorSet(p, "Parsing previous model is unfinished.", 1);
332     iToken = Psr_ManReadName(p);
333     if ( iToken == 0 )                             return Psr_ManErrorSet(p, "Cannot read model name.", 1);
334     Psr_ManInitializeNtk( p, iToken, 0 );
335     Psr_ManSkipSpaces( p );
336     if ( !Psr_ManIsChar(p, '\n') )                 return Psr_ManErrorSet(p, "Trailing symbols on .model line.", 1);
337     return 0;
338 }
Psr_ManReadEnd(Psr_Man_t * p)339 static inline int Psr_ManReadEnd( Psr_Man_t * p )
340 {
341     if ( p->pNtk == 0 )                            return Psr_ManErrorSet(p, "Directive .end without .model.", 1);
342     //printf( "Saving model \"%s\".\n", Abc_NamStr(p->pStrs, p->iModuleName) );
343     Psr_ManFinalizeNtk( p );
344     Psr_ManSkipSpaces( p );
345     if ( !Psr_ManIsChar(p, '\n') )                 return Psr_ManErrorSet(p, "Trailing symbols on .end line.", 1);
346     return 0;
347 }
348 
Psr_ManReadDirective(Psr_Man_t * p)349 static inline int Psr_ManReadDirective( Psr_Man_t * p )
350 {
351     int iToken;
352     if ( !Psr_ManIsChar(p, '.') )
353         return Psr_ManReadCube( p );
354     if ( Vec_StrSize(&p->vCover) > 0 ) // SOP was specified for the previous node
355         Psr_ManSaveCover( p );
356     iToken = Psr_ManReadName( p );
357     if ( iToken == PRS_BLIF_MODEL )
358         return Psr_ManReadModel( p );
359     if ( iToken == PRS_BLIF_INOUTS )
360         return Psr_ManReadInouts( p );
361     if ( iToken == PRS_BLIF_INPUTS )
362         return Psr_ManReadInputs( p );
363     if ( iToken == PRS_BLIF_OUTPUTS )
364         return Psr_ManReadOutputs( p );
365     if ( iToken == PRS_BLIF_NAMES )
366         return Psr_ManReadNode( p );
367     if ( iToken == PRS_BLIF_SUBCKT )
368         return Psr_ManReadBox( p, 0 );
369     if ( iToken == PRS_BLIF_GATE )
370         return Psr_ManReadBox( p, 1 );
371     if ( iToken == PRS_BLIF_LATCH )
372         return Psr_ManReadLatch( p );
373     if ( iToken == PRS_BLIF_SHORT )
374         return Psr_ManReadShort( p );
375     if ( iToken == PRS_BLIF_END )
376         return Psr_ManReadEnd( p );
377     printf( "Cannot read directive \"%s\".\n", Abc_NamStr(p->pStrs, iToken) );
378     return 1;
379 }
Psr_ManReadLines(Psr_Man_t * p)380 static inline int Psr_ManReadLines( Psr_Man_t * p )
381 {
382     while ( p->pCur[1] != '\0' )
383     {
384         assert( Psr_ManIsChar(p, '\n') );
385         Psr_ManSkip(p);
386         Psr_ManSkipSpaces( p );
387         if ( Psr_ManIsChar(p, '\n') )
388             continue;
389         if ( Psr_ManReadDirective(p) )
390             return 1;
391     }
392     return 0;
393 }
394 
395 /**Function*************************************************************
396 
397   Synopsis    []
398 
399   Description []
400 
401   SideEffects []
402 
403   SeeAlso     []
404 
405 ***********************************************************************/
Psr_ManReadBlif(char * pFileName)406 Vec_Ptr_t * Psr_ManReadBlif( char * pFileName )
407 {
408     Vec_Ptr_t * vPrs = NULL;
409     Psr_Man_t * p = Psr_ManAlloc( pFileName );
410     if ( p == NULL )
411         return NULL;
412     Psr_NtkAddBlifDirectives( p );
413     Psr_ManReadLines( p );
414     if ( Psr_ManErrorPrint(p) )
415         ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks );
416     Psr_ManFree( p );
417     return vPrs;
418 }
419 
420 /**Function*************************************************************
421 
422   Synopsis    []
423 
424   Description []
425 
426   SideEffects []
427 
428   SeeAlso     []
429 
430 ***********************************************************************/
Psr_ManReadBlifTest()431 void Psr_ManReadBlifTest()
432 {
433     abctime clk = Abc_Clock();
434     extern void Psr_ManWriteBlif( char * pFileName, Vec_Ptr_t * vPrs );
435 //    Vec_Ptr_t * vPrs = Psr_ManReadBlif( "aga/ray/ray_hie_oper.blif" );
436     Vec_Ptr_t * vPrs = Psr_ManReadBlif( "c/hie/dump/1/netlist_1_out8.blif" );
437     if ( !vPrs ) return;
438     printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) );
439     printf( "NameIDs = %d. ", Abc_NamObjNumMax(Psr_ManNameMan(vPrs)) );
440     printf( "Memory = %.2f MB. ", 1.0*Psr_ManMemory(vPrs)/(1<<20) );
441     Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
442 //    Abc_NamPrint( p->pStrs );
443     Psr_ManWriteBlif( "c/hie/dump/1/netlist_1_out8_out.blif", vPrs );
444     Psr_ManVecFree( vPrs );
445 }
446 
447 ////////////////////////////////////////////////////////////////////////
448 ///                       END OF FILE                                ///
449 ////////////////////////////////////////////////////////////////////////
450 
451 
452 ABC_NAMESPACE_IMPL_END
453 
454