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