1 /**CFile****************************************************************
2
3 FileName [amapRead.c]
4
5 SystemName [ABC: Logic synthesis and verification system.]
6
7 PackageName [Technology mapper for standard cells.]
8
9 Synopsis []
10
11 Author [Alan Mishchenko]
12
13 Affiliation [UC Berkeley]
14
15 Date [Ver. 1.0. Started - June 20, 2005.]
16
17 Revision [$Id: amapRead.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
18
19 ***********************************************************************/
20
21 #include "amapInt.h"
22 #include "base/io/ioAbc.h"
23
24 ABC_NAMESPACE_IMPL_START
25
26
27 ////////////////////////////////////////////////////////////////////////
28 /// DECLARATIONS ///
29 ////////////////////////////////////////////////////////////////////////
30
31 #define AMAP_STRING_GATE "GATE"
32 #define AMAP_STRING_PIN "PIN"
33 #define AMAP_STRING_NONINV "NONINV"
34 #define AMAP_STRING_INV "INV"
35 #define AMAP_STRING_UNKNOWN "UNKNOWN"
36
37 // these symbols (and no other) can appear in the formulas
38 #define AMAP_SYMB_AND '*'
39 #define AMAP_SYMB_AND2 '&'
40 #define AMAP_SYMB_OR1 '+'
41 #define AMAP_SYMB_OR2 '|'
42 #define AMAP_SYMB_XOR '^'
43 #define AMAP_SYMB_NOT '!'
44 #define AMAP_SYMB_AFTNOT '\''
45 #define AMAP_SYMB_OPEN '('
46 #define AMAP_SYMB_CLOSE ')'
47
48 typedef enum {
49 AMAP_PHASE_UNKNOWN,
50 AMAP_PHASE_INV,
51 AMAP_PHASE_NONINV
52 } Amap_PinPhase_t;
53
Amap_ParseGateAlloc(Aig_MmFlex_t * p,int nPins)54 static inline Amap_Gat_t * Amap_ParseGateAlloc( Aig_MmFlex_t * p, int nPins )
55 { return (Amap_Gat_t *)Aig_MmFlexEntryFetch( p, sizeof(Amap_Gat_t)+sizeof(Amap_Pin_t)*nPins ); }
Amap_ParseStrsav(Aig_MmFlex_t * p,char * pStr)56 static inline char * Amap_ParseStrsav( Aig_MmFlex_t * p, char * pStr )
57 { return pStr ? strcpy(Aig_MmFlexEntryFetch(p, strlen(pStr)+1), pStr) : NULL; }
58
59 ////////////////////////////////////////////////////////////////////////
60 /// FUNCTION DEFINITIONS ///
61 ////////////////////////////////////////////////////////////////////////
62
63 /**Function*************************************************************
64
65 Synopsis [Loads the file into temporary buffer.]
66
67 Description []
68
69 SideEffects []
70
71 SeeAlso []
72
73 ***********************************************************************/
Amap_LoadFile(char * pFileName)74 char * Amap_LoadFile( char * pFileName )
75 {
76 // extern FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose );
77 FILE * pFile;
78 char * pBuffer;
79 int nFileSize;
80 int RetValue;
81 // open the BLIF file for binary reading
82 pFile = Io_FileOpen( pFileName, "open_path", "rb", 1 );
83 // pFile = fopen( FileName, "rb" );
84 // if we got this far, file should be okay otherwise would
85 // have been detected by caller
86 if ( pFile == NULL )
87 {
88 printf( "Cannot open file \"%s\".\n", pFileName );
89 return NULL;
90 }
91 assert ( pFile != NULL );
92 // get the file size, in bytes
93 fseek( pFile, 0, SEEK_END );
94 nFileSize = ftell( pFile );
95 // move the file current reading position to the beginning
96 rewind( pFile );
97 // load the contents of the file into memory
98 pBuffer = ABC_ALLOC( char, nFileSize + 10 );
99 RetValue = fread( pBuffer, nFileSize, 1, pFile );
100 // terminate the string with '\0'
101 pBuffer[ nFileSize ] = '\0';
102 strcat( pBuffer, "\n.end\n" );
103 // close file
104 fclose( pFile );
105 return pBuffer;
106 }
107
108 /**Function*************************************************************
109
110 Synopsis [Eliminates comments from the input file.]
111
112 Description [As a byproduct, this procedure also counts the number
113 lines and dot-statements in the input file. This also joins non-comment
114 lines that are joined with a backspace '\']
115
116 SideEffects []
117
118 SeeAlso []
119
120 ***********************************************************************/
Amap_RemoveComments(char * pBuffer,int * pnDots,int * pnLines)121 void Amap_RemoveComments( char * pBuffer, int * pnDots, int * pnLines )
122 {
123 char * pCur;
124 int nDots, nLines;
125 // scan through the buffer and eliminate comments
126 // (in the BLIF file, comments are lines starting with "#")
127 nDots = nLines = 0;
128 for ( pCur = pBuffer; *pCur; pCur++ )
129 {
130 // if this is the beginning of comment
131 // clean it with spaces until the new line statement
132 if ( *pCur == '#' )
133 while ( *pCur != '\n' )
134 *pCur++ = ' ';
135
136 // count the number of new lines and dots
137 if ( *pCur == '\n' ) {
138 if (*(pCur-1)=='\r') {
139 // DOS(R) file support
140 if (*(pCur-2)!='\\') nLines++;
141 else {
142 // rewind to backslash and overwrite with a space
143 *(pCur-2) = ' ';
144 *(pCur-1) = ' ';
145 *pCur = ' ';
146 }
147 } else {
148 // UNIX(TM) file support
149 if (*(pCur-1)!='\\') nLines++;
150 else {
151 // rewind to backslash and overwrite with a space
152 *(pCur-1) = ' ';
153 *pCur = ' ';
154 }
155 }
156 }
157 else if ( *pCur == '.' )
158 nDots++;
159 }
160 if ( pnDots )
161 *pnDots = nDots;
162 if ( pnLines )
163 *pnLines = nLines;
164 }
165
166 /**Function*************************************************************
167
168 Synopsis [Splits the stream into tokens.]
169
170 Description []
171
172 SideEffects []
173
174 SeeAlso []
175
176 ***********************************************************************/
Amap_DeriveTokens(char * pBuffer)177 Vec_Ptr_t * Amap_DeriveTokens( char * pBuffer )
178 {
179 Vec_Ptr_t * vTokens;
180 char * pToken;
181 vTokens = Vec_PtrAlloc( 1000 );
182 pToken = strtok( pBuffer, " =\t\r\n" );
183 while ( pToken )
184 {
185 Vec_PtrPush( vTokens, pToken );
186 pToken = strtok( NULL, " =\t\r\n" );
187 // skip latches
188 if ( pToken && strcmp( pToken, "LATCH" ) == 0 )
189 while ( pToken && strcmp( pToken, "GATE" ) != 0 )
190 pToken = strtok( NULL, " =\t\r\n" );
191 }
192 return vTokens;
193 }
194
195 /**Function*************************************************************
196
197 Synopsis [Finds the number of pins.]
198
199 Description []
200
201 SideEffects []
202
203 SeeAlso []
204
205 ***********************************************************************/
Amap_ParseCountPins(Vec_Ptr_t * vTokens,int iPos)206 int Amap_ParseCountPins( Vec_Ptr_t * vTokens, int iPos )
207 {
208 char * pToken;
209 int i, Counter = 0;
210 Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, iPos )
211 if ( !strcmp( pToken, AMAP_STRING_PIN ) )
212 Counter++;
213 else if ( !strcmp( pToken, AMAP_STRING_GATE ) )
214 return Counter;
215 return Counter;
216 }
217
218 /**Function*************************************************************
219
220 Synopsis [Collect the pin names used in the formula.]
221
222 Description []
223
224 SideEffects []
225
226 SeeAlso []
227
228 ***********************************************************************/
Amap_GateCollectNames(Aig_MmFlex_t * pMem,char * pForm,char * pPinNames[])229 int Amap_GateCollectNames( Aig_MmFlex_t * pMem, char * pForm, char * pPinNames[] )
230 {
231 char Buffer[1000];
232 char * pTemp;
233 int nPins, i;
234 // save the formula as it was
235 strcpy( Buffer, pForm );
236 // remove the non-name symbols
237 for ( pTemp = Buffer; *pTemp; pTemp++ )
238 if ( *pTemp == AMAP_SYMB_AND || *pTemp == AMAP_SYMB_OR1 || *pTemp == AMAP_SYMB_OR2
239 || *pTemp == AMAP_SYMB_XOR || *pTemp == AMAP_SYMB_NOT || *pTemp == AMAP_SYMB_OPEN
240 || *pTemp == AMAP_SYMB_CLOSE || *pTemp == AMAP_SYMB_AFTNOT || *pTemp == AMAP_SYMB_AND2 )
241 *pTemp = ' ';
242 // save the names
243 nPins = 0;
244 pTemp = strtok( Buffer, " " );
245 while ( pTemp )
246 {
247 for ( i = 0; i < nPins; i++ )
248 if ( strcmp( pTemp, pPinNames[i] ) == 0 )
249 break;
250 if ( i == nPins )
251 { // cannot find this name; save it
252 pPinNames[nPins++] = Amap_ParseStrsav( pMem, pTemp );
253 }
254 // get the next name
255 pTemp = strtok( NULL, " " );
256 }
257 return nPins;
258 }
259
260 /**Function*************************************************************
261
262 Synopsis [Creates a duplicate gate with pins specified.]
263
264 Description []
265
266 SideEffects []
267
268 SeeAlso []
269
270 ***********************************************************************/
Amap_ParseGateWithSamePins(Amap_Gat_t * p)271 Amap_Gat_t * Amap_ParseGateWithSamePins( Amap_Gat_t * p )
272 {
273 Amap_Gat_t * pGate;
274 Amap_Pin_t * pPin;
275 char * pPinNames[128];
276 int nPinNames;
277 assert( p->nPins == 1 && !strcmp( p->Pins->pName, "*" ) );
278 nPinNames = Amap_GateCollectNames( p->pLib->pMemGates, p->pForm, pPinNames );
279 pGate = Amap_ParseGateAlloc( p->pLib->pMemGates, nPinNames );
280 *pGate = *p;
281 pGate->nPins = nPinNames;
282 Amap_GateForEachPin( pGate, pPin )
283 {
284 *pPin = *p->Pins;
285 pPin->pName = pPinNames[pPin - pGate->Pins];
286 }
287 return pGate;
288 }
289
290 /**Function*************************************************************
291
292 Synopsis []
293
294 Description []
295
296 SideEffects []
297
298 SeeAlso []
299
300 ***********************************************************************/
Amap_CollectFormulaTokens(Vec_Ptr_t * vTokens,char * pToken,int iPos)301 int Amap_CollectFormulaTokens( Vec_Ptr_t * vTokens, char * pToken, int iPos )
302 {
303 char * pNext, * pPrev;
304 pPrev = pToken + strlen(pToken);
305 while ( *(pPrev-1) != ';' )
306 {
307 *pPrev++ = ' ';
308 pNext = (char *)Vec_PtrEntry(vTokens, iPos++);
309 while ( *pNext )
310 *pPrev++ = *pNext++;
311 }
312 *(pPrev-1) = 0;
313 return iPos;
314 }
315
316 /**Function*************************************************************
317
318 Synopsis []
319
320 Description []
321
322 SideEffects []
323
324 SeeAlso []
325
326 ***********************************************************************/
Amap_ParseTokens(Vec_Ptr_t * vTokens,int fVerbose)327 Amap_Lib_t * Amap_ParseTokens( Vec_Ptr_t * vTokens, int fVerbose )
328 {
329 Amap_Lib_t * p;
330 Amap_Gat_t * pGate, * pPrev;
331 Amap_Pin_t * pPin;
332 char * pToken, * pMoGate = NULL;
333 int i, nPins, iPos = 0, Count = 0;
334 p = Amap_LibAlloc();
335 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
336 do
337 {
338 if ( strcmp( pToken, AMAP_STRING_GATE ) )
339 {
340 Amap_LibFree( p );
341 printf( "The first line should begin with %s.\n", AMAP_STRING_GATE );
342 return NULL;
343 }
344 // start gate
345 nPins = Amap_ParseCountPins( vTokens, iPos );
346 pGate = Amap_ParseGateAlloc( p->pMemGates, nPins );
347 memset( pGate, 0, sizeof(Amap_Gat_t) );
348 pGate->Id = Vec_PtrSize( p->vGates );
349 Vec_PtrPush( p->vGates, pGate );
350 pGate->pLib = p;
351 pGate->nPins = nPins;
352 // read gate
353 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
354 pGate->pName = Amap_ParseStrsav( p->pMemGates, pToken );
355 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
356 pGate->dArea = atof( pToken );
357 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
358 pGate->pOutName = Amap_ParseStrsav( p->pMemGates, pToken );
359 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
360 iPos = Amap_CollectFormulaTokens( vTokens, pToken, iPos );
361 pGate->pForm = Amap_ParseStrsav( p->pMemGates, pToken );
362 // read pins
363 Amap_GateForEachPin( pGate, pPin )
364 {
365 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
366 if ( strcmp( pToken, AMAP_STRING_PIN ) )
367 {
368 Amap_LibFree( p );
369 printf( "Cannot parse gate %s.\n", pGate->pName );
370 return NULL;
371 }
372 // read pin
373 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
374 pPin->pName = Amap_ParseStrsav( p->pMemGates, pToken );
375 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
376 if ( strcmp( pToken, AMAP_STRING_UNKNOWN ) == 0 )
377 pPin->Phase = AMAP_PHASE_UNKNOWN;
378 else if ( strcmp( pToken, AMAP_STRING_INV ) == 0 )
379 pPin->Phase = AMAP_PHASE_INV;
380 else if ( strcmp( pToken, AMAP_STRING_NONINV ) == 0 )
381 pPin->Phase = AMAP_PHASE_NONINV;
382 else
383 {
384 Amap_LibFree( p );
385 printf( "Cannot read phase of pin %s of gate %s\n", pPin->pName, pGate->pName );
386 return NULL;
387 }
388 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
389 pPin->dLoadInput = atof( pToken );
390 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
391 pPin->dLoadMax = atof( pToken );
392 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
393 pPin->dDelayBlockRise = atof( pToken );
394 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
395 pPin->dDelayFanoutRise = atof( pToken );
396 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
397 pPin->dDelayBlockFall = atof( pToken );
398 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
399 pPin->dDelayFanoutFall = atof( pToken );
400 if ( pPin->dDelayBlockRise > pPin->dDelayBlockFall )
401 pPin->dDelayBlockMax = pPin->dDelayBlockRise;
402 else
403 pPin->dDelayBlockMax = pPin->dDelayBlockFall;
404 }
405 // fix the situation when all pins are represented as one
406 if ( pGate->nPins == 1 && !strcmp( pGate->Pins->pName, "*" ) )
407 {
408 pGate = Amap_ParseGateWithSamePins( pGate );
409 Vec_PtrPop( p->vGates );
410 Vec_PtrPush( p->vGates, pGate );
411 }
412 pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
413 //printf( "Finished reading gate %s (%s)\n", pGate->pName, pGate->pOutName );
414 }
415 while ( strcmp( pToken, ".end" ) );
416
417 // check if there are gates with identical names
418 pPrev = NULL;
419 Amap_LibForEachGate( p, pGate, i )
420 {
421 if ( pPrev && !strcmp(pPrev->pName, pGate->pName) )
422 {
423 pPrev->pTwin = pGate, pGate->pTwin = pPrev;
424 // printf( "Warning: Detected multi-output gate \"%s\".\n", pGate->pName );
425 if ( pMoGate == NULL )
426 pMoGate = pGate->pName;
427 Count++;
428 }
429 pPrev = pGate;
430 }
431 if ( Count )
432 printf( "Warning: Detected %d multi-output gates (for example, \"%s\").\n", Count, pMoGate );
433 return p;
434 }
435
436 /**Function*************************************************************
437
438 Synopsis [Reads the library from the input file.]
439
440 Description []
441
442 SideEffects []
443
444 SeeAlso []
445
446 ***********************************************************************/
Amap_LibReadBuffer(char * pBuffer,int fVerbose)447 Amap_Lib_t * Amap_LibReadBuffer( char * pBuffer, int fVerbose )
448 {
449 Amap_Lib_t * pLib;
450 Vec_Ptr_t * vTokens;
451 Amap_RemoveComments( pBuffer, NULL, NULL );
452 vTokens = Amap_DeriveTokens( pBuffer );
453 pLib = Amap_ParseTokens( vTokens, fVerbose );
454 if ( pLib == NULL )
455 {
456 Vec_PtrFree( vTokens );
457 return NULL;
458 }
459 Vec_PtrFree( vTokens );
460 return pLib;
461 }
462
463 /**Function*************************************************************
464
465 Synopsis [Reads the library from the input file.]
466
467 Description []
468
469 SideEffects []
470
471 SeeAlso []
472
473 ***********************************************************************/
Amap_LibReadFile(char * pFileName,int fVerbose)474 Amap_Lib_t * Amap_LibReadFile( char * pFileName, int fVerbose )
475 {
476 Amap_Lib_t * pLib;
477 char * pBuffer;
478 pBuffer = Amap_LoadFile( pFileName );
479 if ( pBuffer == NULL )
480 return NULL;
481 pLib = Amap_LibReadBuffer( pBuffer, fVerbose );
482 if ( pLib )
483 pLib->pName = Abc_UtilStrsav( pFileName );
484 ABC_FREE( pBuffer );
485 return pLib;
486 }
487
488 ////////////////////////////////////////////////////////////////////////
489 /// END OF FILE ///
490 ////////////////////////////////////////////////////////////////////////
491
492
493 ABC_NAMESPACE_IMPL_END
494
495