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