cbaReadBlif.c 15.3 KB
Newer Older
1 2 3 4 5 6
/**CFile****************************************************************

  FileName    [cbaReadBlif.c]

  SystemName  [ABC: Logic synthesis and verification system.]

7
  PackageName [Hierarchical word-level netlist.]
8

9
  Synopsis    [BLIF parser.]
10 11 12 13 14 15 16 17 18 19 20

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - November 29, 2014.]

  Revision    [$Id: cbaReadBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]

***********************************************************************/

Alan Mishchenko committed
21
#include "cba.h"
22 23 24 25 26 27 28 29 30 31
#include "cbaPrs.h"

ABC_NAMESPACE_IMPL_START

////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

// BLIF keywords
typedef enum { 
32 33 34 35 36 37 38 39 40 41 42 43
    PRS_BLIF_NONE = 0, // 0:   unused
    PRS_BLIF_MODEL,    // 1:   .model
    PRS_BLIF_INOUTS,   // 2:   .inouts
    PRS_BLIF_INPUTS,   // 3:   .inputs
    PRS_BLIF_OUTPUTS,  // 4:   .outputs
    PRS_BLIF_NAMES,    // 5:   .names
    PRS_BLIF_SUBCKT,   // 6:   .subckt
    PRS_BLIF_GATE,     // 7:   .gate
    PRS_BLIF_LATCH,    // 8:   .latch
    PRS_BLIF_SHORT,    // 9:   .short
    PRS_BLIF_END,      // 10:  .end
    PRS_BLIF_UNKNOWN   // 11:  unknown
44 45
} Cba_BlifType_t;

46
const char * s_BlifTypes[PRS_BLIF_UNKNOWN+1] = {
Alan Mishchenko committed
47 48 49 50 51 52 53 54 55 56 57 58
    NULL,              // 0:   unused
    ".model",          // 1:   .model   
    ".inouts",         // 2:   .inputs
    ".inputs",         // 3:   .inputs
    ".outputs",        // 4:   .outputs
    ".names",          // 5:   .names
    ".subckt",         // 6:   .subckt
    ".gate",           // 7:   .gate
    ".latch",          // 8:   .latch
    ".short",          // 9:   .short
    ".end",            // 10:  .end
    NULL               // 11:  unknown
59 60
};

61
static inline void Prs_NtkAddBlifDirectives( Prs_Man_t * p )
62 63 64
{
    int i;
    for ( i = 1; s_BlifTypes[i]; i++ )
65 66
        Abc_NamStrFindOrAdd( p->pStrs, (char *)s_BlifTypes[i], NULL );
    assert( Abc_NamObjNumMax(p->pStrs) == i );
67 68 69 70 71 72 73 74 75
}


////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

Alan Mishchenko committed
76 77 78 79 80 81 82 83 84
  Synopsis    [Reading characters.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
85 86 87
static inline int  Prs_CharIsSpace( char c )                { return c == ' ' || c == '\t' || c == '\r';              }
static inline int  Prs_CharIsStop( char c )                 { return c == '#' || c == '\\' || c == '\n' || c == '=';  }
static inline int  Prs_CharIsLit( char c )                  { return c == '0' || c == '1'  || c == '-';               }
Alan Mishchenko committed
88

89 90 91
static inline int  Prs_ManIsSpace( Prs_Man_t * p )          { return Prs_CharIsSpace(*p->pCur);                       }
static inline int  Prs_ManIsStop( Prs_Man_t * p )           { return Prs_CharIsStop(*p->pCur);                        }
static inline int  Prs_ManIsLit( Prs_Man_t * p )            { return Prs_CharIsLit(*p->pCur);                         }
Alan Mishchenko committed
92

93 94
static inline int  Prs_ManIsChar( Prs_Man_t * p, char c )   { return *p->pCur == c;                                   }
static inline int  Prs_ManIsChar2( Prs_Man_t * p, char c )  { return *p->pCur++ == c;                                 }
Alan Mishchenko committed
95

96 97
static inline void Prs_ManSkip( Prs_Man_t * p )             { p->pCur++;                                              }
static inline char Prs_ManSkip2( Prs_Man_t * p )            { return *p->pCur++;                                      }
Alan Mishchenko committed
98 99 100 101


/**Function*************************************************************

102 103 104 105 106 107 108 109 110
  Synopsis    [Reading names.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
111
static inline void Prs_ManSkipToChar( Prs_Man_t * p, char c )  
Alan Mishchenko committed
112
{ 
113 114
    while ( !Prs_ManIsChar(p, c) ) 
        Prs_ManSkip(p);
Alan Mishchenko committed
115
}
116
static inline void Prs_ManSkipSpaces( Prs_Man_t * p )
117
{
Alan Mishchenko committed
118
    while ( 1 )
119
    {
120 121 122
        while ( Prs_ManIsSpace(p) )
            Prs_ManSkip(p);
        if ( Prs_ManIsChar(p, '\\') )
Alan Mishchenko committed
123
        {
124 125
            Prs_ManSkipToChar( p, '\n' );
            Prs_ManSkip(p);
Alan Mishchenko committed
126 127
            continue;
        }
128 129
        if ( Prs_ManIsChar(p, '#') )  
            Prs_ManSkipToChar( p, '\n' );
Alan Mishchenko committed
130 131
        break;
    }
132
    assert( !Prs_ManIsSpace(p) );
133
}
134
static inline int Prs_ManReadName( Prs_Man_t * p )
135
{
Alan Mishchenko committed
136
    char * pStart;
137 138
    Prs_ManSkipSpaces( p );
    if ( Prs_ManIsChar(p, '\n') )
Alan Mishchenko committed
139 140
        return 0;
    pStart = p->pCur;
141 142
    while ( !Prs_ManIsSpace(p) && !Prs_ManIsStop(p) )
        Prs_ManSkip(p);
143 144
    if ( pStart == p->pCur )
        return 0;
145
    return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL );
146
}
147
static inline int Prs_ManReadList( Prs_Man_t * p, Vec_Int_t * vOrder, int Type )
148
{
Alan Mishchenko committed
149 150
    int iToken;
    Vec_IntClear( &p->vTemp );
151
    while ( (iToken = Prs_ManReadName(p)) )
152
    {
Alan Mishchenko committed
153
        Vec_IntPush( &p->vTemp, iToken );
154 155
        Vec_IntPush( vOrder, Abc_Var2Lit2(iToken, Type) );
    }
156
    if ( Vec_IntSize(&p->vTemp) == 0 )                return Prs_ManErrorSet(p, "Signal list is empty.", 1);
Alan Mishchenko committed
157 158
    return 0;
}
159
static inline int Prs_ManReadList2( Prs_Man_t * p )
Alan Mishchenko committed
160 161
{
    int iToken;
162 163 164 165
    Vec_IntClear( &p->vTemp );
    while ( (iToken = Prs_ManReadName(p)) )
        Vec_IntPushTwo( &p->vTemp, 0, iToken );
    if ( Vec_IntSize(&p->vTemp) == 0 )                return Prs_ManErrorSet(p, "Signal list is empty.", 1);
Alan Mishchenko committed
166 167
    return 0;
}
168
static inline int Prs_ManReadList3( Prs_Man_t * p )
Alan Mishchenko committed
169 170
{
    Vec_IntClear( &p->vTemp );
171
    while ( !Prs_ManIsChar(p, '\n') )
Alan Mishchenko committed
172
    {
173 174
        int iToken = Prs_ManReadName(p);
        if ( iToken == 0 )              return Prs_ManErrorSet(p, "Cannot read formal name.", 1);
Alan Mishchenko committed
175
        Vec_IntPush( &p->vTemp, iToken );
176 177 178 179
        Prs_ManSkipSpaces( p );
        if ( !Prs_ManIsChar2(p, '=') )  return Prs_ManErrorSet(p, "Cannot find symbol \"=\".", 1);
        iToken = Prs_ManReadName(p);
        if ( iToken == 0 )              return Prs_ManErrorSet(p, "Cannot read actual name.", 1);
Alan Mishchenko committed
180
        Vec_IntPush( &p->vTemp, iToken );
181
        Prs_ManSkipSpaces( p );
Alan Mishchenko committed
182
    }
183 184
    if ( Vec_IntSize(&p->vTemp) == 0 )  return Prs_ManErrorSet(p, "Cannot read a list of formal/actual names.", 1);
    if ( Vec_IntSize(&p->vTemp) % 2  )  return Prs_ManErrorSet(p, "The number of formal/actual names is not even.", 1);
Alan Mishchenko committed
185
    return 0;
186 187 188 189 190 191 192 193 194 195 196 197 198
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
199
static inline int Prs_ManReadCube( Prs_Man_t * p )
200
{
201 202 203 204 205
    assert( Prs_ManIsLit(p) );
    while ( Prs_ManIsLit(p) )
        Vec_StrPush( &p->vCover, Prs_ManSkip2(p) );
    Prs_ManSkipSpaces( p );
    if ( Prs_ManIsChar(p, '\n') )
Alan Mishchenko committed
206
    {
207
        if ( Vec_StrSize(&p->vCover) != 1 )           return Prs_ManErrorSet(p, "Cannot read cube.", 1);
Alan Mishchenko committed
208 209 210 211 212 213
        // fix single literal cube by adding space
        Vec_StrPush( &p->vCover, Vec_StrEntry(&p->vCover,0) );
        Vec_StrWriteEntry( &p->vCover, 0, ' ' );
        Vec_StrPush( &p->vCover, '\n' );
        return 0;
    }
214
    if ( !Prs_ManIsLit(p) )                           return Prs_ManErrorSet(p, "Cannot read output literal.", 1);
Alan Mishchenko committed
215
    Vec_StrPush( &p->vCover, ' ' );
216
    Vec_StrPush( &p->vCover, Prs_ManSkip2(p) );
Alan Mishchenko committed
217
    Vec_StrPush( &p->vCover, '\n' );
218 219
    Prs_ManSkipSpaces( p );
    if ( !Prs_ManIsChar(p, '\n') )                    return Prs_ManErrorSet(p, "Cannot read end of cube.", 1);
Alan Mishchenko committed
220
    return 0;
221
}
222
static inline void Prs_ManSaveCover( Prs_Man_t * p )
223 224
{
    int iToken;
225 226 227 228 229 230 231 232 233 234
    if ( Vec_StrSize(&p->vCover) == 0 )
        p->pNtk->fHasC0s = 1;
    else if ( Vec_StrSize(&p->vCover) == 2 )
    {
        if ( Vec_StrEntryLast(&p->vCover) == '0' )
            p->pNtk->fHasC0s = 1;
        else if ( Vec_StrEntryLast(&p->vCover) == '1' )
            p->pNtk->fHasC1s = 1;
        else assert( 0 );
    }
Alan Mishchenko committed
235 236
    assert( Vec_StrSize(&p->vCover) > 0 );
    Vec_StrPush( &p->vCover, '\0' );
237 238
    //iToken = Abc_NamStrFindOrAdd( p->pStrs, Vec_StrArray(&p->vCover), NULL );
    iToken = Ptr_SopToType( Vec_StrArray(&p->vCover) );
Alan Mishchenko committed
239
    Vec_StrClear( &p->vCover );
240 241 242
    // set the cover to the module of this box
    assert( Prs_BoxNtk(p->pNtk, Prs_NtkBoxNum(p->pNtk)-1) == 1 ); // default const 0
    Prs_BoxSetNtk( p->pNtk, Prs_NtkBoxNum(p->pNtk)-1, iToken );
243 244 245 246 247 248 249 250 251 252 253 254 255
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
256
static inline int Prs_ManReadInouts( Prs_Man_t * p )
257
{
258
    if ( Prs_ManReadList(p, &p->pNtk->vOrder, 3) )    return 1;
259
    Vec_IntAppend( &p->pNtk->vInouts, &p->vTemp );
260 261
    return 0;
}
262
static inline int Prs_ManReadInputs( Prs_Man_t * p )
263
{
264
    if ( Prs_ManReadList(p, &p->pNtk->vOrder, 1) )    return 1;
265
    Vec_IntAppend( &p->pNtk->vInputs, &p->vTemp );
266 267
    return 0;
}
268
static inline int Prs_ManReadOutputs( Prs_Man_t * p )
269
{
270
    if ( Prs_ManReadList(p, &p->pNtk->vOrder, 2) )    return 1;
271
    Vec_IntAppend( &p->pNtk->vOutputs, &p->vTemp );
272 273
    return 0;
}
274
static inline int Prs_ManReadNode( Prs_Man_t * p )
275
{
276
    if ( Prs_ManReadList2(p) )   return 1;
277
    // save results
278
    Prs_NtkAddBox( p->pNtk, 1, 0, &p->vTemp ); // default const 0 function
279 280
    return 0;
}
281
static inline int Prs_ManReadBox( Prs_Man_t * p, int fGate )
282
{
283 284 285
    int iToken = Prs_ManReadName(p);
    if ( iToken == 0 )           return Prs_ManErrorSet(p, "Cannot read model name.", 1);
    if ( Prs_ManReadList3(p) )   return 1;
286
    // save results
287 288
    Prs_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
    if ( fGate ) p->pNtk->fMapped = 1;
289 290
    return 0;
}
291
static inline int Prs_ManReadLatch( Prs_Man_t * p )
292
{
293 294 295
    int iToken = Prs_ManReadName(p);
    Vec_IntClear( &p->vTemp );
    if ( iToken == 0 )                 return Prs_ManErrorSet(p, "Cannot read latch input.", 1);
Alan Mishchenko committed
296
    Vec_IntWriteEntry( &p->vTemp, 1, iToken );
297 298
    iToken = Prs_ManReadName(p);
    if ( iToken == 0 )                 return Prs_ManErrorSet(p, "Cannot read latch output.", 1);
Alan Mishchenko committed
299
    Vec_IntWriteEntry( &p->vTemp, 0, iToken );
300 301
    Prs_ManSkipSpaces( p );
    if ( Prs_ManIsChar(p, '0') )
Alan Mishchenko committed
302
        iToken = 0;
303
    else if ( Prs_ManIsChar(p, '1') )
Alan Mishchenko committed
304 305 306
        iToken = 1;
    else 
        iToken = 2;
307
    Prs_ManSkipToChar( p, '\n' );
308
    // save results
309
    Prs_NtkAddBox( p->pNtk, -1, iToken, &p->vTemp ); // -1 stands for latch
310 311
    return 0;
}
312
static inline int Prs_ManReadShort( Prs_Man_t * p )
313
{
314 315 316
    int iToken = Prs_ManReadName(p);
    Vec_IntClear( &p->vTemp );
    if ( iToken == 0 )                 return Prs_ManErrorSet(p, "Cannot read .short input.", 1);
Alan Mishchenko committed
317
    Vec_IntWriteEntry( &p->vTemp, 1, iToken );
318 319
    iToken = Prs_ManReadName(p);
    if ( iToken == 0 )                 return Prs_ManErrorSet(p, "Cannot read .short output.", 1);
Alan Mishchenko committed
320
    Vec_IntWriteEntry( &p->vTemp, 0, iToken );
321 322
    Prs_ManSkipSpaces( p );
    if ( !Prs_ManIsChar(p, '\n') )     return Prs_ManErrorSet(p, "Trailing symbols on .short line.", 1);
Alan Mishchenko committed
323
    // save results
324 325
    iToken = Abc_NamStrFindOrAdd( p->pStrs, "1 1\n", NULL );
    Prs_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
Alan Mishchenko committed
326 327
    return 0;
}
328
static inline int Prs_ManReadModel( Prs_Man_t * p )
Alan Mishchenko committed
329
{
330 331 332 333 334 335 336
    int iToken;
    if ( p->pNtk != NULL )                         return Prs_ManErrorSet(p, "Parsing previous model is unfinished.", 1);
    iToken = Prs_ManReadName(p);
    if ( iToken == 0 )                             return Prs_ManErrorSet(p, "Cannot read model name.", 1);
    Prs_ManInitializeNtk( p, iToken, 0 );
    Prs_ManSkipSpaces( p );
    if ( !Prs_ManIsChar(p, '\n') )                 return Prs_ManErrorSet(p, "Trailing symbols on .model line.", 1);
337 338
    return 0;
}
339
static inline int Prs_ManReadEnd( Prs_Man_t * p )
340
{
341 342 343 344 345
    if ( p->pNtk == 0 )                            return Prs_ManErrorSet(p, "Directive .end without .model.", 1);
    //printf( "Saving model \"%s\".\n", Abc_NamStr(p->pStrs, p->iModuleName) );
    Prs_ManFinalizeNtk( p );
    Prs_ManSkipSpaces( p );
    if ( !Prs_ManIsChar(p, '\n') )                 return Prs_ManErrorSet(p, "Trailing symbols on .end line.", 1);
346 347 348
    return 0;
}

349
static inline int Prs_ManReadDirective( Prs_Man_t * p )
350 351
{
    int iToken;
352 353
    if ( !Prs_ManIsChar(p, '.') )
        return Prs_ManReadCube( p );
Alan Mishchenko committed
354
    if ( Vec_StrSize(&p->vCover) > 0 ) // SOP was specified for the previous node
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
        Prs_ManSaveCover( p );
    iToken = Prs_ManReadName( p );  
    if ( iToken == PRS_BLIF_MODEL )
        return Prs_ManReadModel( p );
    if ( iToken == PRS_BLIF_INOUTS )
        return Prs_ManReadInouts( p );
    if ( iToken == PRS_BLIF_INPUTS )
        return Prs_ManReadInputs( p );
    if ( iToken == PRS_BLIF_OUTPUTS )
        return Prs_ManReadOutputs( p );
    if ( iToken == PRS_BLIF_NAMES )
        return Prs_ManReadNode( p );
    if ( iToken == PRS_BLIF_SUBCKT )
        return Prs_ManReadBox( p, 0 );
    if ( iToken == PRS_BLIF_GATE )
        return Prs_ManReadBox( p, 1 );
    if ( iToken == PRS_BLIF_LATCH )
        return Prs_ManReadLatch( p );
    if ( iToken == PRS_BLIF_SHORT )
        return Prs_ManReadShort( p );
    if ( iToken == PRS_BLIF_END )
        return Prs_ManReadEnd( p );
    printf( "Cannot read directive \"%s\".\n", Abc_NamStr(p->pStrs, iToken) );
378 379
    return 1;
}
380
static inline int Prs_ManReadLines( Prs_Man_t * p )
381
{
Alan Mishchenko committed
382
    while ( p->pCur[1] != '\0' )
383
    {
384 385 386 387
        assert( Prs_ManIsChar(p, '\n') );
        Prs_ManSkip(p);
        Prs_ManSkipSpaces( p );
        if ( Prs_ManIsChar(p, '\n') )
388
            continue;
389
        if ( Prs_ManReadDirective(p) )   
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
            return 1;
    }
    return 0;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
406
Vec_Ptr_t * Prs_ManReadBlif( char * pFileName )
407
{
408 409
    Vec_Ptr_t * vPrs = NULL;
    Prs_Man_t * p = Prs_ManAlloc( pFileName );
410 411
    if ( p == NULL )
        return NULL;
412 413 414 415 416 417
    Prs_NtkAddBlifDirectives( p );
    Prs_ManReadLines( p );
    if ( Prs_ManErrorPrint(p) )
        ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks );
    Prs_ManFree( p );
    return vPrs;
418 419
}

Alan Mishchenko committed
420 421 422 423 424 425 426 427 428 429 430
/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
431
void Prs_ManReadBlifTest()
Alan Mishchenko committed
432 433
{
    abctime clk = Abc_Clock();
434 435 436 437 438
    extern void Prs_ManWriteBlif( char * pFileName, Vec_Ptr_t * vPrs );
//    Vec_Ptr_t * vPrs = Prs_ManReadBlif( "aga/ray/ray_hie_oper.blif" );
    Vec_Ptr_t * vPrs = Prs_ManReadBlif( "c/hie/dump/1/netlist_1_out8.blif" );
    if ( !vPrs ) return;
    printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) );
Alan Mishchenko committed
439
    printf( "NameIDs = %d. ", Abc_NamObjNumMax(Prs_ManNameMan(vPrs)) );
440
    printf( "Memory = %.2f MB. ", 1.0*Prs_ManMemory(vPrs)/(1<<20) );
Alan Mishchenko committed
441
    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
442 443 444
//    Abc_NamPrint( p->pStrs );
    Prs_ManWriteBlif( "c/hie/dump/1/netlist_1_out8_out.blif", vPrs );
    Prs_ManVecFree( vPrs );
Alan Mishchenko committed
445 446
}

447 448 449 450 451 452 453
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END