ntlReadBlif.c 47.7 KB
Newer Older
Alan Mishchenko committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/**CFile****************************************************************

  FileName    [ntlReadBlif.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Command processing package.]

  Synopsis    [Procedures to read BLIF file.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - January 8, 2007.]

Alan Mishchenko committed
17
  Revision    [$Id: ntlReadBlif.c,v 1.1 2008/10/10 14:09:30 mjarvin Exp $]
Alan Mishchenko committed
18 19 20

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

Alan Mishchenko committed
21 22
// The code in this file is developed in collaboration with Mark Jarvin of Toronto.

Alan Mishchenko committed
23
#include "ntl.h"
Alan Mishchenko committed
24
#include "bzlib.h"
Alan Mishchenko committed
25
#include "zlib.h"
Alan Mishchenko committed
26

27 28 29
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
30 31 32 33
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

34 35
typedef struct Ntl_ReadMod_t_ Ntl_ReadMod_t;   // parsing model
typedef struct Ntl_ReadMan_t_ Ntl_ReadMan_t;   // parsing manager
Alan Mishchenko committed
36

37
struct Ntl_ReadMod_t_
Alan Mishchenko committed
38 39 40
{
    // file lines
    char *               pFirst;       // .model line
Alan Mishchenko committed
41
    char *               pAttrib;      // .attrib line
Alan Mishchenko committed
42 43 44 45 46 47
    Vec_Ptr_t *          vInputs;      // .inputs lines
    Vec_Ptr_t *          vOutputs;     // .outputs lines
    Vec_Ptr_t *          vLatches;     // .latch lines
    Vec_Ptr_t *          vNames;       // .names lines
    Vec_Ptr_t *          vSubckts;     // .subckt lines
    Vec_Ptr_t *          vDelays;      // .delay lines
Alan Mishchenko committed
48 49
    Vec_Ptr_t *          vTimeInputs;  // .input_arrival/required lines
    Vec_Ptr_t *          vTimeOutputs; // .output_required/arrival lines
Alan Mishchenko committed
50
    int                  fBlackBox;    // indicates blackbox model
Alan Mishchenko committed
51 52 53 54 55
    int                  fNoMerge;     // indicates no-merge model
    char                 fInArr;     
    char                 fInReq;     
    char                 fOutArr;     
    char                 fOutReq;     
Alan Mishchenko committed
56 57 58
    // the resulting network
    Ntl_Mod_t *          pNtk;   
    // the parent manager
59
    Ntl_ReadMan_t *      pMan;         
Alan Mishchenko committed
60 61
};

62
struct Ntl_ReadMan_t_
Alan Mishchenko committed
63 64 65 66 67 68 69 70 71
{
    // general info about file
    char *               pFileName;    // the name of the file
    char *               pBuffer;      // the contents of the file
    Vec_Ptr_t *          vLines;       // the line beginnings
    // the results of reading
    Ntl_Man_t *          pDesign;      // the design under construction
    // intermediate storage for models
    Vec_Ptr_t *          vModels;      // vector of models
72
    Ntl_ReadMod_t *      pLatest;      // the current model
Alan Mishchenko committed
73 74 75 76 77 78 79 80 81 82 83 84
    // current processing info
    Vec_Ptr_t *          vTokens;      // the current tokens
    Vec_Ptr_t *          vTokens2;     // the current tokens
    Vec_Str_t *          vFunc;        // the local function
    // error reporting
    char                 sError[512];  // the error string generated during parsing
    // statistics 
    int                  nTablesRead;  // the number of processed tables
    int                  nTablesLeft;  // the number of dangling tables
};

// static functions
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
static Ntl_ReadMan_t *   Ntl_ReadAlloc();
static void              Ntl_ReadFree( Ntl_ReadMan_t * p );
static Ntl_ReadMod_t *   Ntl_ReadModAlloc();
static void              Ntl_ReadModFree( Ntl_ReadMod_t * p );
static char *            Ntl_ReadLoadFile( char * pFileName );
static char *            Ntl_ReadLoadFileBz2( char * pFileName );
static char *            Ntl_ReadLoadFileGz( char * pFileName );
static void              Ntl_ReadReadPreparse( Ntl_ReadMan_t * p );
static int               Ntl_ReadReadInterfaces( Ntl_ReadMan_t * p );
static Ntl_Man_t *       Ntl_ReadParse( Ntl_ReadMan_t * p );
static int               Ntl_ReadParseLineModel( Ntl_ReadMod_t * p, char * pLine );
static int               Ntl_ReadParseLineAttrib( Ntl_ReadMod_t * p, char * pLine );
static int               Ntl_ReadParseLineInputs( Ntl_ReadMod_t * p, char * pLine );
static int               Ntl_ReadParseLineOutputs( Ntl_ReadMod_t * p, char * pLine );
static int               Ntl_ReadParseLineLatch( Ntl_ReadMod_t * p, char * pLine );
static int               Ntl_ReadParseLineSubckt( Ntl_ReadMod_t * p, char * pLine );
static int               Ntl_ReadParseLineDelay( Ntl_ReadMod_t * p, char * pLine );
static int               Ntl_ReadParseLineTimes( Ntl_ReadMod_t * p, char * pLine, int fOutput );
static int               Ntl_ReadParseLineNamesBlif( Ntl_ReadMod_t * p, char * pLine );

static int               Ntl_ReadCharIsSpace( char s )   { return s == ' ' || s == '\t' || s == '\r' || s == '\n';             }
static int               Ntl_ReadCharIsSopSymb( char s ) { return s == '0' || s == '1' || s == '-' || s == '\r' || s == '\n';  }
Alan Mishchenko committed
107

Alan Mishchenko committed
108

Alan Mishchenko committed
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

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

  Synopsis    [Reads the network from the BLIF file.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
124
Ntl_Man_t * Ntl_ManReadBlif( char * pFileName, int fCheck )
Alan Mishchenko committed
125 126
{
    FILE * pFile;
127
    Ntl_ReadMan_t * p;
Alan Mishchenko committed
128
    Ntl_Man_t * pDesign;
129 130 131 132 133
    if ( !Ntl_FileIsType(pFileName, ".blif", ".blif.gz", ".blif.bz2") )
    {     
        printf( "Wrong file format\n" );
        return NULL;
    }
Alan Mishchenko committed
134 135 136 137
    // check that the file is available
    pFile = fopen( pFileName, "rb" );
    if ( pFile == NULL )
    {
138
        printf( "Ntl_ManReadBlif(): The file is unavailable (absent or open).\n" );
Alan Mishchenko committed
139 140 141 142 143
        return 0;
    }
    fclose( pFile );

    // start the file reader
144
    p = Ntl_ReadAlloc();
Alan Mishchenko committed
145
    p->pFileName = pFileName;
Alan Mishchenko committed
146
    if ( !strncmp(pFileName+strlen(pFileName)-4,".bz2",4) )
147
        p->pBuffer = Ntl_ReadLoadFileBz2( pFileName );
Alan Mishchenko committed
148
    else if ( !strncmp(pFileName+strlen(pFileName)-3,".gz",3) )
149
        p->pBuffer = Ntl_ReadLoadFileGz( pFileName );
Alan Mishchenko committed
150
    else
151
        p->pBuffer = Ntl_ReadLoadFile( pFileName );
Alan Mishchenko committed
152 153
    if ( p->pBuffer == NULL )
    {
154
        Ntl_ReadFree( p );
Alan Mishchenko committed
155 156 157
        return NULL;
    }
    // set the design name
158
    p->pDesign = Ntl_ManAlloc();
Alan Mishchenko committed
159 160
    p->pDesign->pName = Ntl_ManStoreFileName( p->pDesign, pFileName );
    p->pDesign->pSpec = Ntl_ManStoreName( p->pDesign, pFileName );
Alan Mishchenko committed
161
    // prepare the file for parsing
162
    Ntl_ReadReadPreparse( p );
Alan Mishchenko committed
163
    // parse interfaces of each network
164
    if ( !Ntl_ReadReadInterfaces( p ) )
Alan Mishchenko committed
165 166 167
    {
        if ( p->sError[0] )
            fprintf( stdout, "%s\n", p->sError );
168
        Ntl_ReadFree( p );
Alan Mishchenko committed
169 170 171
        return NULL;
    }
    // construct the network
172
    pDesign = Ntl_ReadParse( p );
Alan Mishchenko committed
173 174 175 176
    if ( p->sError[0] )
        fprintf( stdout, "%s\n", p->sError );
    if ( pDesign == NULL )
    {
177
        Ntl_ReadFree( p );
Alan Mishchenko committed
178 179 180
        return NULL;
    }
    p->pDesign = NULL;
181
    Ntl_ReadFree( p );
Alan Mishchenko committed
182 183 184 185 186 187 188
// pDesign should be linked to all models of the design

    // make sure that everything is okay with the network structure
    if ( fCheck )
    {
        if ( !Ntl_ManCheck( pDesign ) )
        {
189
            printf( "Ntl_ReadBlif: The check has failed for design %s.\n", pDesign->pName );
Alan Mishchenko committed
190 191 192 193 194
            Ntl_ManFree( pDesign );
            return NULL;
        }

    }
Alan Mishchenko committed
195
    // transform the design by removing the CO drivers
Alan Mishchenko committed
196 197
//    if ( (nNodes = Ntl_ManReconnectCoDrivers(pDesign)) )
//        printf( "The design was transformed by removing %d buf/inv CO drivers.\n", nNodes );
198
//Ntl_ManWriteBlif( pDesign, "_temp_.blif" );
Alan Mishchenko committed
199 200 201 202 203 204
/*
    {   
        Aig_Man_t * p = Ntl_ManCollapseSeq( pDesign );
        Aig_ManStop( p );
    }
*/
Alan Mishchenko committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218
    return pDesign;
}

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

  Synopsis    [Allocates the BLIF parsing structure.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
219
static Ntl_ReadMan_t * Ntl_ReadAlloc()
Alan Mishchenko committed
220
{
221 222 223
    Ntl_ReadMan_t * p;
    p = ABC_ALLOC( Ntl_ReadMan_t, 1 );
    memset( p, 0, sizeof(Ntl_ReadMan_t) );
Alan Mishchenko committed
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
    p->vLines   = Vec_PtrAlloc( 512 );
    p->vModels  = Vec_PtrAlloc( 512 );
    p->vTokens  = Vec_PtrAlloc( 512 );
    p->vTokens2 = Vec_PtrAlloc( 512 );
    p->vFunc    = Vec_StrAlloc( 512 );
    return p;
}

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

  Synopsis    [Frees the BLIF parsing structure.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
243
static void Ntl_ReadFree( Ntl_ReadMan_t * p )
Alan Mishchenko committed
244
{
245
    Ntl_ReadMod_t * pMod;
Alan Mishchenko committed
246 247 248 249
    int i;
    if ( p->pDesign )
        Ntl_ManFree( p->pDesign );
    if ( p->pBuffer )  
Alan Mishchenko committed
250
        ABC_FREE( p->pBuffer );
Alan Mishchenko committed
251 252 253 254
    if ( p->vLines )
        Vec_PtrFree( p->vLines );
    if ( p->vModels )
    {
255 256
        Vec_PtrForEachEntry( Ntl_ReadMod_t *, p->vModels, pMod, i )
            Ntl_ReadModFree( pMod );
Alan Mishchenko committed
257 258 259 260 261
        Vec_PtrFree( p->vModels );
    }
    Vec_PtrFree( p->vTokens );
    Vec_PtrFree( p->vTokens2 );
    Vec_StrFree( p->vFunc );
Alan Mishchenko committed
262
    ABC_FREE( p );
Alan Mishchenko committed
263 264 265 266 267 268 269 270 271 272 273 274 275
}

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

  Synopsis    [Allocates the BLIF parsing structure for one model.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
276
static Ntl_ReadMod_t * Ntl_ReadModAlloc()
Alan Mishchenko committed
277
{
278 279 280
    Ntl_ReadMod_t * p;
    p = ABC_ALLOC( Ntl_ReadMod_t, 1 );
    memset( p, 0, sizeof(Ntl_ReadMod_t) );
Alan Mishchenko committed
281 282 283 284 285 286
    p->vInputs      = Vec_PtrAlloc( 8 );
    p->vOutputs     = Vec_PtrAlloc( 8 );
    p->vLatches     = Vec_PtrAlloc( 8 );
    p->vNames       = Vec_PtrAlloc( 8 );
    p->vSubckts     = Vec_PtrAlloc( 8 );
    p->vDelays      = Vec_PtrAlloc( 8 );
Alan Mishchenko committed
287 288
    p->vTimeInputs  = Vec_PtrAlloc( 8 );
    p->vTimeOutputs = Vec_PtrAlloc( 8 );
Alan Mishchenko committed
289 290 291 292 293 294 295 296 297 298 299 300 301 302
    return p;
}

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

  Synopsis    [Deallocates the BLIF parsing structure for one model.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
303
static void Ntl_ReadModFree( Ntl_ReadMod_t * p )
Alan Mishchenko committed
304 305 306 307 308 309 310
{
    Vec_PtrFree( p->vInputs );
    Vec_PtrFree( p->vOutputs );
    Vec_PtrFree( p->vLatches );
    Vec_PtrFree( p->vNames );
    Vec_PtrFree( p->vSubckts );
    Vec_PtrFree( p->vDelays );
Alan Mishchenko committed
311 312
    Vec_PtrFree( p->vTimeInputs );
    Vec_PtrFree( p->vTimeOutputs );
Alan Mishchenko committed
313
    ABC_FREE( p );
Alan Mishchenko committed
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
}



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

  Synopsis    [Counts the number of given chars.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
329
static int Ntl_ReadCountChars( char * pLine, char Char )
Alan Mishchenko committed
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
{
    char * pCur;
    int Counter = 0;
    for ( pCur = pLine; *pCur; pCur++ )
        if ( *pCur == Char )
            Counter++;
    return Counter;
}

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

  Synopsis    [Collects the already split tokens.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
350
static void Ntl_ReadCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput )
Alan Mishchenko committed
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
{
    char * pCur;
    Vec_PtrClear( vTokens );
    for ( pCur = pInput; pCur < pOutput; pCur++ )
    {
        if ( *pCur == 0 )
            continue;
        Vec_PtrPush( vTokens, pCur );
        while ( *++pCur );
    }
}

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

  Synopsis    [Splits the line into tokens.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
374
static void Ntl_ReadSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop )
Alan Mishchenko committed
375 376 377 378
{
    char * pCur;
    // clear spaces
    for ( pCur = pLine; *pCur != Stop; pCur++ )
379
        if ( Ntl_ReadCharIsSpace(*pCur) )
Alan Mishchenko committed
380 381
            *pCur = 0;
    // collect tokens
382
    Ntl_ReadCollectTokens( vTokens, pLine, pCur );
Alan Mishchenko committed
383 384 385 386 387 388 389 390 391 392 393 394 395
}

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

  Synopsis    [Splits the line into tokens.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
396
static void Ntl_ReadSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char )
Alan Mishchenko committed
397 398 399 400
{
    char * pCur;
    // clear spaces
    for ( pCur = pLine; *pCur != Stop; pCur++ )
401
        if ( Ntl_ReadCharIsSpace(*pCur) || *pCur == Char )
Alan Mishchenko committed
402 403
            *pCur = 0;
    // collect tokens
404
    Ntl_ReadCollectTokens( vTokens, pLine, pCur );
Alan Mishchenko committed
405 406 407 408 409 410 411 412 413 414 415 416 417
}

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

  Synopsis    [Returns the 1-based number of the line in which the token occurs.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
418
static int Ntl_ReadGetLine( Ntl_ReadMan_t * p, char * pToken )
Alan Mishchenko committed
419 420 421
{
    char * pLine;
    int i;
422
    Vec_PtrForEachEntry( char *, p->vLines, pLine, i )
Alan Mishchenko committed
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
        if ( pToken < pLine )
            return i;
    return -1;
}

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

  Synopsis    [Reads the file into a character buffer.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
439
static char * Ntl_ReadLoadFile( char * pFileName )
Alan Mishchenko committed
440 441 442 443 444 445 446
{
    FILE * pFile;
    int nFileSize;
    char * pContents;
    pFile = fopen( pFileName, "rb" );
    if ( pFile == NULL )
    {
447
        fclose( pFile );
448
        printf( "Ntl_ReadLoadFile(): The file is unavailable (absent or open).\n" );
Alan Mishchenko committed
449 450 451 452 453 454
        return NULL;
    }
    fseek( pFile, 0, SEEK_END );  
    nFileSize = ftell( pFile ); 
    if ( nFileSize == 0 )
    {
455
        fclose( pFile );
456
        printf( "Ntl_ReadLoadFile(): The file is empty.\n" );
Alan Mishchenko committed
457 458
        return NULL;
    }
Alan Mishchenko committed
459
    pContents = ABC_ALLOC( char, nFileSize + 10 );
Alan Mishchenko committed
460 461 462 463 464 465 466 467 468 469 470
    rewind( pFile );
    fread( pContents, nFileSize, 1, pFile );
    fclose( pFile );
    // finish off the file with the spare .end line
    // some benchmarks suddenly break off without this line
    strcpy( pContents + nFileSize, "\n.end\n" );
    return pContents;
}

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

Alan Mishchenko committed
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
  Synopsis    [Reads the file into a character buffer.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
typedef struct buflist {
  char buf[1<<20];
  int nBuf;
  struct buflist * next;
} buflist;

486
static char * Ntl_ReadLoadFileBz2( char * pFileName )
Alan Mishchenko committed
487 488 489 490 491 492 493 494 495 496 497 498
{
    FILE    * pFile;
    int       nFileSize = 0;
    char    * pContents;
    BZFILE  * b;
    int       bzError;
    struct buflist * pNext;
    buflist * bufHead = NULL, * buf = NULL;

    pFile = fopen( pFileName, "rb" );
    if ( pFile == NULL )
    {
499
        printf( "Ntl_ReadLoadFileBz2(): The file is unavailable (absent or open).\n" );
Alan Mishchenko committed
500 501 502 503
        return NULL;
    }
    b = BZ2_bzReadOpen(&bzError,pFile,0,0,NULL,0);
    if (bzError != BZ_OK) {
504
        printf( "Ntl_ReadLoadFileBz2(): BZ2_bzReadOpen() failed with error %d.\n",bzError );
Alan Mishchenko committed
505 506 507 508
        return NULL;
    }
    do {
        if (!bufHead)
Alan Mishchenko committed
509
            buf = bufHead = ABC_ALLOC( buflist, 1 );
Alan Mishchenko committed
510
        else
Alan Mishchenko committed
511
            buf = buf->next = ABC_ALLOC( buflist, 1 );
Alan Mishchenko committed
512 513 514 515 516 517 518 519
        nFileSize += buf->nBuf = BZ2_bzRead(&bzError,b,buf->buf,1<<20);
        buf->next = NULL;
    } while (bzError == BZ_OK);
    if (bzError == BZ_STREAM_END) {
        // we're okay
        char * p;
        int nBytes = 0;
        BZ2_bzReadClose(&bzError,b);
Alan Mishchenko committed
520
        p = pContents = ABC_ALLOC( char, nFileSize + 10 );
Alan Mishchenko committed
521 522 523 524 525 526
        buf = bufHead;
        do {
            memcpy(p+nBytes,buf->buf,buf->nBuf);
            nBytes += buf->nBuf;
//        } while((buf = buf->next));
            pNext = buf->next;
Alan Mishchenko committed
527
            ABC_FREE( buf );
Alan Mishchenko committed
528 529 530 531 532 533 534 535
        } while((buf = pNext));
    } else if (bzError == BZ_DATA_ERROR_MAGIC) {
        // not a BZIP2 file
        BZ2_bzReadClose(&bzError,b);
        fseek( pFile, 0, SEEK_END );
        nFileSize = ftell( pFile );
        if ( nFileSize == 0 )
        {
536
            printf( "Ntl_ReadLoadFileBz2(): The file is empty.\n" );
Alan Mishchenko committed
537 538
            return NULL;
        }
Alan Mishchenko committed
539
        pContents = ABC_ALLOC( char, nFileSize + 10 );
Alan Mishchenko committed
540 541 542 543
        rewind( pFile );
        fread( pContents, nFileSize, 1, pFile );
    } else { 
        // Some other error.
544
        printf( "Ntl_ReadLoadFileBz2(): Unable to read the compressed BLIF.\n" );
Alan Mishchenko committed
545 546 547 548 549 550 551 552 553 554 555
        return NULL;
    }
    fclose( pFile );
    // finish off the file with the spare .end line
    // some benchmarks suddenly break off without this line
    strcpy( pContents + nFileSize, "\n.end\n" );
    return pContents;
}

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

Alan Mishchenko committed
556 557 558 559 560 561 562 563 564
  Synopsis    [Reads the file into a character buffer.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
565
static char * Ntl_ReadLoadFileGz( char * pFileName )
Alan Mishchenko committed
566 567 568 569 570
{
    const int READ_BLOCK_SIZE = 100000;
    FILE * pFile;
    char * pContents;
    int amtRead, readBlock, nFileSize = READ_BLOCK_SIZE;
571
    pFile = (FILE *)gzopen( pFileName, "rb" ); // if pFileName doesn't end in ".gz" then this acts as a passthrough to fopen
Alan Mishchenko committed
572
    pContents = ABC_ALLOC( char, nFileSize );        
Alan Mishchenko committed
573 574 575 576
    readBlock = 0;
    while ((amtRead = gzread(pFile, pContents + readBlock * READ_BLOCK_SIZE, READ_BLOCK_SIZE)) == READ_BLOCK_SIZE) {
        //printf("%d: read %d bytes\n", readBlock, amtRead);
        nFileSize += READ_BLOCK_SIZE;
Alan Mishchenko committed
577
        pContents = ABC_REALLOC(char, pContents, nFileSize);
Alan Mishchenko committed
578 579 580 581 582 583 584 585 586 587 588
        ++readBlock;
    }
    //printf("%d: read %d bytes\n", readBlock, amtRead);
    assert( amtRead != -1 ); // indicates a zlib error
    nFileSize -= (READ_BLOCK_SIZE - amtRead);
    gzclose(pFile);
    return pContents;
}

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

Alan Mishchenko committed
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
  Synopsis    [Prepares the parsing.]

  Description [Performs several preliminary operations:
  - Cuts the file buffer into separate lines.
  - Removes comments and line extenders.
  - Sorts lines by directives.
  - Estimates the number of objects.
  - Allocates room for the objects.
  - Allocates room for the hash table.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
604
static void Ntl_ReadReadPreparse( Ntl_ReadMan_t * p )
Alan Mishchenko committed
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
{
    char * pCur, * pPrev;
    int i, fComment = 0;
    // parse the buffer into lines and remove comments
    Vec_PtrPush( p->vLines, p->pBuffer );
    for ( pCur = p->pBuffer; *pCur; pCur++ )
    {
        if ( *pCur == '\n' )
        {
            *pCur = 0;
//            if ( *(pCur-1) == '\r' )
//                *(pCur-1) = 0;
            fComment = 0;
            Vec_PtrPush( p->vLines, pCur + 1 );
        }
        else if ( *pCur == '#' )
            fComment = 1;
        // remove comments
        if ( fComment )
            *pCur = 0;
    }

    // unfold the line extensions and sort lines by directive
628
    Vec_PtrForEachEntry( char *, p->vLines, pCur, i )
Alan Mishchenko committed
629 630 631 632 633
    {
        if ( *pCur == 0 )
            continue;
        // find previous non-space character
        for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- )
634
            if ( !Ntl_ReadCharIsSpace(*pPrev) )
Alan Mishchenko committed
635 636
                break;
        // if it is the line extender, overwrite it with spaces
Alan Mishchenko committed
637
        if ( pPrev >= p->pBuffer && *pPrev == '\\' )
Alan Mishchenko committed
638 639 640 641 642 643 644
        {
            for ( ; *pPrev; pPrev++ )
                *pPrev = ' ';
            *pPrev = ' ';
            continue;
        }
        // skip spaces at the beginning of the line
645
        while ( Ntl_ReadCharIsSpace(*pCur++) );
Alan Mishchenko committed
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
        // parse directives
        if ( *(pCur-1) != '.' )
            continue;
        if ( !strncmp(pCur, "names", 5) )
            Vec_PtrPush( p->pLatest->vNames, pCur );
        else if ( !strncmp(pCur, "latch", 5) )
            Vec_PtrPush( p->pLatest->vLatches, pCur );
        else if ( !strncmp(pCur, "inputs", 6) )
            Vec_PtrPush( p->pLatest->vInputs, pCur );
        else if ( !strncmp(pCur, "outputs", 7) )
            Vec_PtrPush( p->pLatest->vOutputs, pCur );
        else if ( !strncmp(pCur, "subckt", 6) )
            Vec_PtrPush( p->pLatest->vSubckts, pCur );
        else if ( !strncmp(pCur, "delay", 5) )
            Vec_PtrPush( p->pLatest->vDelays, pCur );
Alan Mishchenko committed
661 662
        else if ( !strncmp(pCur, "input_arrival", 13) ||
                  !strncmp(pCur, "input_required", 14) )
Alan Mishchenko committed
663 664 665 666 667
        {
            if ( !strncmp(pCur, "input_arrival", 13) )
                p->pLatest->fInArr = 1;
            if ( !strncmp(pCur, "input_required", 14) )
                p->pLatest->fInReq = 1;
Alan Mishchenko committed
668
            Vec_PtrPush( p->pLatest->vTimeInputs, pCur );
Alan Mishchenko committed
669 670 671 672 673 674 675 676
        }
        else if ( !strncmp(pCur, "output_required", 15) ||
                  !strncmp(pCur, "output_arrival", 14) )
        {
            if ( !strncmp(pCur, "output_required", 15) )
                p->pLatest->fOutReq = 1;
            if ( !strncmp(pCur, "output_arrival", 14) )
                p->pLatest->fOutArr = 1;
Alan Mishchenko committed
677
            Vec_PtrPush( p->pLatest->vTimeOutputs, pCur );
Alan Mishchenko committed
678
        }
Alan Mishchenko committed
679 680 681 682
        else if ( !strncmp(pCur, "blackbox", 8) )
            p->pLatest->fBlackBox = 1;
        else if ( !strncmp(pCur, "model", 5) ) 
        {
683
            p->pLatest = Ntl_ReadModAlloc();
Alan Mishchenko committed
684 685 686
            p->pLatest->pFirst = pCur;
            p->pLatest->pMan = p;
        }
Alan Mishchenko committed
687
        else if ( !strncmp(pCur, "attrib", 6) ) 
Alan Mishchenko committed
688 689
        {
            if ( p->pLatest->pAttrib != NULL )
690
                fprintf( stdout, "Line %d: Skipping second .attrib line for this model.\n", Ntl_ReadGetLine(p, pCur) );
Alan Mishchenko committed
691 692 693
            else
                p->pLatest->pAttrib = pCur;
        }
Alan Mishchenko committed
694 695 696 697 698 699 700 701
        else if ( !strncmp(pCur, "end", 3) )
        {
            if ( p->pLatest )
                Vec_PtrPush( p->vModels, p->pLatest );
            p->pLatest = NULL;
        }
        else if ( !strncmp(pCur, "exdc", 4) )
        {
702
            fprintf( stdout, "Line %d: Skipping EXDC network.\n", Ntl_ReadGetLine(p, pCur) );
Alan Mishchenko committed
703 704
            break;
        }
Alan Mishchenko committed
705 706
        else if ( !strncmp(pCur, "no_merge", 8) ) 
        {
Alan Mishchenko committed
707
            p->pLatest->fNoMerge = 1;
Alan Mishchenko committed
708
        }
Alan Mishchenko committed
709 710 711 712 713
        else
        {
            pCur--;
            if ( pCur[strlen(pCur)-1] == '\r' )
                pCur[strlen(pCur)-1] = 0;
714
            fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Ntl_ReadGetLine(p, pCur), pCur );
Alan Mishchenko committed
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
        }
    }
}

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

  Synopsis    [Parses interfaces of the models.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
730
static int Ntl_ReadReadInterfaces( Ntl_ReadMan_t * p )
Alan Mishchenko committed
731
{
732
    Ntl_ReadMod_t * pMod;
Alan Mishchenko committed
733 734 735
    char * pLine;
    int i, k;
    // iterate through the models
736
    Vec_PtrForEachEntry( Ntl_ReadMod_t *, p->vModels, pMod, i )
Alan Mishchenko committed
737 738
    {
        // parse the model
739
        if ( !Ntl_ReadParseLineModel( pMod, pMod->pFirst ) )
Alan Mishchenko committed
740
            return 0;
Alan Mishchenko committed
741
        // parse the model attributes
742
        if ( pMod->pAttrib && !Ntl_ReadParseLineAttrib( pMod, pMod->pAttrib ) )
Alan Mishchenko committed
743
            return 0;
Alan Mishchenko committed
744 745 746
        // parse no-merge
        if ( pMod->fNoMerge )
            pMod->pNtk->attrNoMerge = 1;
Alan Mishchenko committed
747
        // parse the inputs
748 749
        Vec_PtrForEachEntry( char *, pMod->vInputs, pLine, k )
            if ( !Ntl_ReadParseLineInputs( pMod, pLine ) )
Alan Mishchenko committed
750 751
                return 0;
        // parse the outputs
752 753
        Vec_PtrForEachEntry( char *, pMod->vOutputs, pLine, k )
            if ( !Ntl_ReadParseLineOutputs( pMod, pLine ) )
Alan Mishchenko committed
754 755
                return 0;
        // parse the delay info
Alan Mishchenko committed
756
        Ntl_ModelSetPioNumbers( pMod->pNtk );
757 758
        Vec_PtrForEachEntry( char *, pMod->vDelays, pLine, k )
            if ( !Ntl_ReadParseLineDelay( pMod, pLine ) )
Alan Mishchenko committed
759
                return 0;
760 761
        Vec_PtrForEachEntry( char *, pMod->vTimeInputs, pLine, k )
            if ( !Ntl_ReadParseLineTimes( pMod, pLine, 0 ) )
Alan Mishchenko committed
762
                return 0;
763 764
        Vec_PtrForEachEntry( char *, pMod->vTimeOutputs, pLine, k )
            if ( !Ntl_ReadParseLineTimes( pMod, pLine, 1 ) )
Alan Mishchenko committed
765
                return 0;
Alan Mishchenko committed
766 767 768 769 770 771 772 773 774
        // report timing line stats
        if ( pMod->fInArr && pMod->fInReq )
            printf( "Model %s has both .input_arrival and .input_required.\n", pMod->pNtk->pName );
        if ( pMod->fOutArr && pMod->fOutReq )
            printf( "Model %s has both .output_arrival and .output_required.\n", pMod->pNtk->pName );
        if ( !pMod->vDelays && !pMod->fInArr && !pMod->fInReq )
            printf( "Model %s has neither .input_arrival nor .input_required.\n", pMod->pNtk->pName );
        if ( !pMod->vDelays && !pMod->fOutArr && !pMod->fOutReq )
            printf( "Model %s has neither .output_arrival nor .output_required.\n", pMod->pNtk->pName );
Alan Mishchenko committed
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
    }
    return 1;
}


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

  Synopsis    []

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
791
static Ntl_Man_t * Ntl_ReadParse( Ntl_ReadMan_t * p )
Alan Mishchenko committed
792 793
{
    Ntl_Man_t * pDesign;
794
    Ntl_ReadMod_t * pMod;
Alan Mishchenko committed
795 796 797
    char * pLine;
    int i, k;
    // iterate through the models
798
    Vec_PtrForEachEntry( Ntl_ReadMod_t *, p->vModels, pMod, i )
Alan Mishchenko committed
799 800
    {
        // parse the latches
801 802
        Vec_PtrForEachEntry( char *, pMod->vLatches, pLine, k )
            if ( !Ntl_ReadParseLineLatch( pMod, pLine ) )
Alan Mishchenko committed
803 804
                return NULL;
        // parse the nodes
805 806
        Vec_PtrForEachEntry( char *, pMod->vNames, pLine, k )
            if ( !Ntl_ReadParseLineNamesBlif( pMod, pLine ) )
Alan Mishchenko committed
807 808
                return NULL;
        // parse the subcircuits
809 810
        Vec_PtrForEachEntry( char *, pMod->vSubckts, pLine, k )
            if ( !Ntl_ReadParseLineSubckt( pMod, pLine ) )
Alan Mishchenko committed
811 812 813 814
                return NULL;
        // finalize the network
        Ntl_ModelFixNonDrivenNets( pMod->pNtk );
    }
Alan Mishchenko committed
815 816 817
    if ( i == 0 )
        return NULL;
    // update the design name
818
    pMod = (Ntl_ReadMod_t *)Vec_PtrEntry( p->vModels, 0 );
Alan Mishchenko committed
819 820
    if ( Ntl_ModelLatchNum(pMod->pNtk) > 0 )
        Ntl_ModelTransformLatches( pMod->pNtk );
Alan Mishchenko committed
821
    p->pDesign->pName = Ntl_ManStoreName( p->pDesign, pMod->pNtk->pName );
Alan Mishchenko committed
822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838
    // return the network
    pDesign = p->pDesign;
    p->pDesign = NULL;
    return pDesign;
}

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

  Synopsis    [Parses the model line.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
839
static int Ntl_ReadParseLineModel( Ntl_ReadMod_t * p, char * pLine )
Alan Mishchenko committed
840 841 842
{
    Vec_Ptr_t * vTokens = p->pMan->vTokens;
    char * pToken;
843 844
    Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' );
    pToken = (char *)Vec_PtrEntry( vTokens, 0 );
Alan Mishchenko committed
845 846 847
    assert( !strcmp(pToken, "model") );
    if ( Vec_PtrSize(vTokens) != 2 )
    {
848
        sprintf( p->pMan->sError, "Line %d: The number of entries (%d) in .model line is different from two.", Ntl_ReadGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) );
Alan Mishchenko committed
849 850
        return 0;
    }
851
    p->pNtk = Ntl_ModelAlloc( p->pMan->pDesign, (char *)Vec_PtrEntry(vTokens, 1) );
Alan Mishchenko committed
852 853
    if ( p->pNtk == NULL )
    {
854
        sprintf( p->pMan->sError, "Line %d: Model %s already exists.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens, 1) );
Alan Mishchenko committed
855 856
        return 0;
    }
Alan Mishchenko committed
857 858 859 860 861
    return 1;
}

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

Alan Mishchenko committed
862 863 864 865 866 867 868 869 870
  Synopsis    [Parses the model line.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
871
static int Ntl_ReadParseLineAttrib( Ntl_ReadMod_t * p, char * pLine )
Alan Mishchenko committed
872 873 874
{
    Vec_Ptr_t * vTokens = p->pMan->vTokens;
    char * pToken;
Alan Mishchenko committed
875
    int i;
876 877
    Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' );
    pToken = (char *)Vec_PtrEntry( vTokens, 0 );
Alan Mishchenko committed
878
    assert( !strncmp(pToken, "attrib", 6) );
879
    Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 )
Alan Mishchenko committed
880
    {
881
        pToken = (char *)Vec_PtrEntry( vTokens, i );
Alan Mishchenko committed
882 883 884 885 886 887
        if ( strcmp( pToken, "white" ) == 0 )
            p->pNtk->attrWhite = 1;
        else if ( strcmp( pToken, "black" ) == 0 )
            p->pNtk->attrWhite = 0;
        else if ( strcmp( pToken, "box" ) == 0 )
            p->pNtk->attrBox = 1;
Alan Mishchenko committed
888 889
        else if ( strcmp( pToken, "logic" ) == 0 )
            p->pNtk->attrBox = 0;
Alan Mishchenko committed
890 891 892 893 894 895
        else if ( strcmp( pToken, "comb" ) == 0 )
            p->pNtk->attrComb = 1;
        else if ( strcmp( pToken, "seq" ) == 0 )
            p->pNtk->attrComb = 0;
        else if ( strcmp( pToken, "keep" ) == 0 )
            p->pNtk->attrKeep = 1;
Alan Mishchenko committed
896 897
        else if ( strcmp( pToken, "sweep" ) == 0 )
            p->pNtk->attrKeep = 0;
Alan Mishchenko committed
898 899
        else 
        {
900
            sprintf( p->pMan->sError, "Line %d: Unknown attribute (%s) in the .attrib line of model %s.", Ntl_ReadGetLine(p->pMan, pToken), pToken, p->pNtk->pName );
Alan Mishchenko committed
901 902
            return 0;
        }
Alan Mishchenko committed
903 904 905 906 907 908
    }
    return 1;
}

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

Alan Mishchenko committed
909 910 911 912 913 914 915 916 917
  Synopsis    [Parses the inputs line.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
918
static int Ntl_ReadParseLineInputs( Ntl_ReadMod_t * p, char * pLine )
Alan Mishchenko committed
919 920 921 922 923 924
{
    Ntl_Net_t * pNet;
    Ntl_Obj_t * pObj;
    Vec_Ptr_t * vTokens = p->pMan->vTokens;
    char * pToken;
    int i;
925 926
    Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' );
    pToken = (char *)Vec_PtrEntry(vTokens, 0);
Alan Mishchenko committed
927
    assert( !strcmp(pToken, "inputs") );
928
    Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 )
Alan Mishchenko committed
929 930 931 932 933
    {
        pObj = Ntl_ModelCreatePi( p->pNtk );
        pNet = Ntl_ModelFindOrCreateNet( p->pNtk, pToken );
        if ( !Ntl_ModelSetNetDriver( pObj, pNet ) )
        {
934
            sprintf( p->pMan->sError, "Line %d: Net %s already has a driver.", Ntl_ReadGetLine(p->pMan, pToken), pNet->pName );
Alan Mishchenko committed
935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951
            return 0;
        }
    }
    return 1;
}

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

  Synopsis    [Parses the outputs line.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
952
static int Ntl_ReadParseLineOutputs( Ntl_ReadMod_t * p, char * pLine )
Alan Mishchenko committed
953 954 955 956 957 958
{
    Ntl_Net_t * pNet;
    Ntl_Obj_t * pObj;
    Vec_Ptr_t * vTokens = p->pMan->vTokens;
    char * pToken;
    int i;
959 960
    Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' );
    pToken = (char *)Vec_PtrEntry(vTokens, 0);
Alan Mishchenko committed
961
    assert( !strcmp(pToken, "outputs") );
962
    Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 )
Alan Mishchenko committed
963 964 965
    {
        pNet = Ntl_ModelFindOrCreateNet( p->pNtk, pToken );
        pObj = Ntl_ModelCreatePo( p->pNtk, pNet );
Alan Mishchenko committed
966
        pNet->pCopy = pObj;
Alan Mishchenko committed
967 968 969 970 971 972 973 974 975 976 977 978 979 980 981
    }
    return 1;
}

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

  Synopsis    [Parses the latches line.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
982
static int Ntl_ReadParseLineLatch( Ntl_ReadMod_t * p, char * pLine )
Alan Mishchenko committed
983 984 985 986 987
{
    Vec_Ptr_t * vTokens = p->pMan->vTokens;
    Ntl_Net_t * pNetLi, * pNetLo;
    Ntl_Obj_t * pObj;
    char * pToken, * pNameLi, * pNameLo;
988 989
    Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' );
    pToken = (char *)Vec_PtrEntry(vTokens,0);
Alan Mishchenko committed
990 991 992
    assert( !strcmp(pToken, "latch") );
    if ( Vec_PtrSize(vTokens) < 3 )
    {
993
        sprintf( p->pMan->sError, "Line %d: Latch does not have input name and output name.", Ntl_ReadGetLine(p->pMan, pToken) );
Alan Mishchenko committed
994 995 996
        return 0;
    }
    // create latch
997 998
    pNameLi = (char *)Vec_PtrEntry( vTokens, 1 );
    pNameLo = (char *)Vec_PtrEntry( vTokens, 2 );
Alan Mishchenko committed
999 1000 1001 1002 1003 1004
    pNetLi  = Ntl_ModelFindOrCreateNet( p->pNtk, pNameLi );
    pNetLo  = Ntl_ModelFindOrCreateNet( p->pNtk, pNameLo );
    pObj    = Ntl_ModelCreateLatch( p->pNtk );
    pObj->pFanio[0] = pNetLi;
    if ( !Ntl_ModelSetNetDriver( pObj, pNetLo ) )
    {
1005
        sprintf( p->pMan->sError, "Line %d: Net %s already has a driver.", Ntl_ReadGetLine(p->pMan, pToken), pNetLo->pName );
Alan Mishchenko committed
1006 1007 1008 1009
        return 0;
    }
    // get initial value
    if ( Vec_PtrSize(vTokens) > 3 )
1010
        pObj->LatchId.regInit = atoi( (char *)Vec_PtrEntry(vTokens,Vec_PtrSize(vTokens)-1) );
Alan Mishchenko committed
1011
    else
Alan Mishchenko committed
1012 1013
        pObj->LatchId.regInit = 2;
    if ( pObj->LatchId.regInit < 0 || pObj->LatchId.regInit > 2 )
Alan Mishchenko committed
1014
    {
1015
        sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens,3) );
Alan Mishchenko committed
1016 1017 1018
        return 0;
    }
    // get the register class
1019 1020
//    if ( Vec_PtrSize(vTokens) == 6 )
    if ( Vec_PtrSize(vTokens) == 5 || Vec_PtrSize(vTokens) == 6 )
Alan Mishchenko committed
1021
    {
1022
        pToken = (char *)Vec_PtrEntry(vTokens,3);
Alan Mishchenko committed
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
        if ( strcmp( pToken, "fe" ) == 0 )
            pObj->LatchId.regType = 1;
        else if ( strcmp( pToken, "re" ) == 0 )
            pObj->LatchId.regType = 2;
        else if ( strcmp( pToken, "ah" ) == 0 )
            pObj->LatchId.regType = 3;
        else if ( strcmp( pToken, "al" ) == 0 )
            pObj->LatchId.regType = 4;
        else if ( strcmp( pToken, "as" ) == 0 )
            pObj->LatchId.regType = 5;
        else if ( pToken[0] >= '0' && pToken[0] <= '9' )
            pObj->LatchId.regClass = atoi(pToken);
        else
        {
1037
            sprintf( p->pMan->sError, "Line %d: Type/class of the latch is incorrect \"%s\".", Ntl_ReadGetLine(p->pMan, pToken), pToken );
Alan Mishchenko committed
1038 1039 1040 1041 1042
            return 0;
        }
    }
    if ( pObj->LatchId.regClass < 0 || pObj->LatchId.regClass > (1<<24) )
    {
1043
        sprintf( p->pMan->sError, "Line %d: Class of the latch is incorrect \"%s\".", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens,3) );
Alan Mishchenko committed
1044 1045 1046
        return 0;
    }
    // get the clock
1047 1048
//    if ( Vec_PtrSize(vTokens) == 5 || Vec_PtrSize(vTokens) == 6 )
    if ( Vec_PtrSize(vTokens) == 6 )
Alan Mishchenko committed
1049
    {
1050
        pToken = (char *)Vec_PtrEntry(vTokens,Vec_PtrSize(vTokens)-2);
Alan Mishchenko committed
1051
        pNetLi = Ntl_ModelFindOrCreateNet( p->pNtk, pToken );
Alan Mishchenko committed
1052
        pObj->pClock = pNetLi;
Alan Mishchenko committed
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
    }
    return 1;
}

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

  Synopsis    [Parses the subckt line.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
1068
static int Ntl_ReadParseLineSubckt( Ntl_ReadMod_t * p, char * pLine )
Alan Mishchenko committed
1069 1070 1071 1072 1073 1074 1075 1076 1077
{
    Vec_Ptr_t * vTokens = p->pMan->vTokens;
    Ntl_Mod_t * pModel;
    Ntl_Obj_t * pBox, * pTerm;
    Ntl_Net_t * pNet;
    char * pToken, * pName, ** ppNames;
    int nEquals, i, k;

    // split the line into tokens
1078 1079 1080
    nEquals = Ntl_ReadCountChars( pLine, '=' );
    Ntl_ReadSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' );
    pToken = (char *)Vec_PtrEntry(vTokens,0);
Alan Mishchenko committed
1081 1082 1083
    assert( !strcmp(pToken, "subckt") );

    // get the model for this box
1084
    pName = (char *)Vec_PtrEntry(vTokens,1);
Alan Mishchenko committed
1085 1086 1087
    pModel = Ntl_ManFindModel( p->pMan->pDesign, pName );
    if ( pModel == NULL )
    {
1088
        sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Ntl_ReadGetLine(p->pMan, pToken), pName );
Alan Mishchenko committed
1089 1090
        return 0;
    }
Alan Mishchenko committed
1091 1092 1093 1094 1095 1096 1097 1098 1099
/*
    // temporary fix for splitting the .subckt line
    if ( nEquals < Ntl_ModelPiNum(pModel) + Ntl_ModelPoNum(pModel) )
    { 
        Vec_Ptr_t * vTokens2 = Vec_PtrAlloc( 10 );
        // get one additional token
        pToken = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - 1 );
        for ( ; *pToken; pToken++ );
        for ( ; *pToken == 0; pToken++ );
1100
        Ntl_ReadSplitIntoTokensAndClear( vTokens2, pToken, '\0', '=' );
Alan Mishchenko committed
1101
//        assert( Vec_PtrSize( vTokens2 ) == 2 );
1102
        Vec_PtrForEachEntry( char *, vTokens2, pToken, i )
Alan Mishchenko committed
1103 1104 1105 1106 1107
            Vec_PtrPush( vTokens, pToken );
        nEquals += Vec_PtrSize(vTokens2)/2;
        Vec_PtrFree( vTokens2 );
    }
*/    
Alan Mishchenko committed
1108 1109 1110
    // check if the number of tokens is correct
    if ( nEquals != Ntl_ModelPiNum(pModel) + Ntl_ModelPoNum(pModel) )
    {
Alan Mishchenko committed
1111
        sprintf( p->pMan->sError, "Line %d: The number of ports (%d) in .subckt %s differs from the sum of PIs and POs of the model (%d).", 
1112
            Ntl_ReadGetLine(p->pMan, pToken), nEquals, pName, Ntl_ModelPiNum(pModel) + Ntl_ModelPoNum(pModel) );
Alan Mishchenko committed
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
        return 0;
    }

    // get the names
    ppNames = (char **)Vec_PtrArray(vTokens) + 2;

    // create the box with these terminals
    pBox = Ntl_ModelCreateBox( p->pNtk, Ntl_ModelPiNum(pModel), Ntl_ModelPoNum(pModel) );
    pBox->pImplem = pModel;
    Ntl_ModelForEachPi( pModel, pTerm, i )
    {
        // find this terminal among the formal inputs of the subcircuit
        pName = Ntl_ObjFanout0(pTerm)->pName;
        for ( k = 0; k < nEquals; k++ )
            if ( !strcmp( ppNames[2*k], pName ) )
                break;
        if ( k == nEquals )
        {
            sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.", 
1132
                Ntl_ReadGetLine(p->pMan, pToken), pName, pModel->pName );
Alan Mishchenko committed
1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
            return 0;
        }
        // create the BI with the actual name
        pNet = Ntl_ModelFindOrCreateNet( p->pNtk, ppNames[2*k+1] );
        Ntl_ObjSetFanin( pBox, pNet, i );
    }
    Ntl_ModelForEachPo( pModel, pTerm, i )
    {
        // find this terminal among the formal outputs of the subcircuit
        pName = Ntl_ObjFanin0(pTerm)->pName;
        for ( k = 0; k < nEquals; k++ )
            if ( !strcmp( ppNames[2*k], pName ) )
                break;
        if ( k == nEquals )
        {
            sprintf( p->pMan->sError, "Line %d: Cannot find PO \"%s\" of the model \"%s\" as a formal output of the subcircuit.", 
1149
                Ntl_ReadGetLine(p->pMan, pToken), pName, pModel->pName );
Alan Mishchenko committed
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
            return 0;
        }
        // create the BI with the actual name
        pNet = Ntl_ModelFindOrCreateNet( p->pNtk, ppNames[2*k+1] );
        Ntl_ObjSetFanout( pBox, pNet, i );
    }
    return 1;
}

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

  Synopsis    [Parses the subckt line.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
1170
static int Ntl_ReadParseLineDelay( Ntl_ReadMod_t * p, char * pLine )
Alan Mishchenko committed
1171 1172 1173 1174 1175 1176
{
    Vec_Ptr_t * vTokens = p->pMan->vTokens;
    int RetValue1, RetValue2, Number1, Number2, Temp;
    char * pToken, * pTokenNum;
    float Delay;
    assert( sizeof(float) == sizeof(int) );
1177 1178
    Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' );
    pToken = (char *)Vec_PtrEntry(vTokens,0);
Alan Mishchenko committed
1179 1180 1181
    assert( !strcmp(pToken, "delay") );
    if ( Vec_PtrSize(vTokens) < 2 && Vec_PtrSize(vTokens) > 4 )
    {
1182
        sprintf( p->pMan->sError, "Line %d: Delay line does not have a valid number of parameters (1, 2, or 3).", Ntl_ReadGetLine(p->pMan, pToken) );
Alan Mishchenko committed
1183 1184 1185
        return 0;
    }
    // find the delay number
1186
    pTokenNum = (char *)Vec_PtrEntryLast(vTokens);
Alan Mishchenko committed
1187 1188 1189
    Delay = atof( pTokenNum );
    if ( Delay == 0.0 && pTokenNum[0] != '0' )
    {
1190
        sprintf( p->pMan->sError, "Line %d: Delay value (%s) appears to be invalid.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntryLast(vTokens) );
Alan Mishchenko committed
1191 1192 1193 1194 1195 1196
        return 0;
    }
    // find the PI/PO numbers
    RetValue1 = 0; Number1 = -1;
    if ( Vec_PtrSize(vTokens) > 2 )
    {
1197
        RetValue1 = Ntl_ModelFindPioNumber( p->pNtk, 0, 0, (char *)Vec_PtrEntry(vTokens, 1), &Number1 );
Alan Mishchenko committed
1198 1199
        if ( RetValue1 == 0 )
        {
1200
            sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs/POs.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens, 1) );
Alan Mishchenko committed
1201 1202 1203 1204 1205 1206
            return 0;
        }
    }
    RetValue2 = 0; Number2 = -1;
    if ( Vec_PtrSize(vTokens) > 3 )
    {
1207
        RetValue2 = Ntl_ModelFindPioNumber( p->pNtk, 0, 0, (char *)Vec_PtrEntry(vTokens, 2), &Number2 );
Alan Mishchenko committed
1208 1209
        if ( RetValue2 == 0 )
        {
1210
            sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs/POs.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens, 2) );
Alan Mishchenko committed
1211 1212 1213 1214 1215 1216
            return 0;
        }
    }
    if ( RetValue1 == RetValue2 && RetValue1 )
    {
        sprintf( p->pMan->sError, "Line %d: Both signals \"%s\" and \"%s\" listed appear to be PIs or POs.", 
1217
            Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens, 1), (char*)Vec_PtrEntry(vTokens, 2) );
Alan Mishchenko committed
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246
        return 0;
    }
    if ( RetValue2 < RetValue1 )
    {
        Temp = RetValue2; RetValue2 = RetValue1; RetValue1 = Temp;
        Temp = Number2;   Number2 = Number1;     Number1 = Temp;
    }
    assert( RetValue1 == 0 || RetValue1 == -1 );
    assert( RetValue2 == 0 || RetValue2 ==  1 );
    // store the values
    if ( p->pNtk->vDelays == NULL )
        p->pNtk->vDelays = Vec_IntAlloc( 100 );
    Vec_IntPush( p->pNtk->vDelays, Number1 );
    Vec_IntPush( p->pNtk->vDelays, Number2 );
    Vec_IntPush( p->pNtk->vDelays, Aig_Float2Int(Delay) );        
    return 1;
}

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

  Synopsis    [Parses the subckt line.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
1247
static int Ntl_ReadParseLineTimes( Ntl_ReadMod_t * p, char * pLine, int fOutput )
Alan Mishchenko committed
1248 1249
{
    Vec_Ptr_t * vTokens = p->pMan->vTokens;
Alan Mishchenko committed
1250
    int RetValue, Number = -1;
Alan Mishchenko committed
1251 1252 1253
    char * pToken, * pTokenNum;
    float Delay;
    assert( sizeof(float) == sizeof(int) );
1254 1255
    Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' );
    pToken = (char *)Vec_PtrEntry(vTokens,0);
Alan Mishchenko committed
1256
    if ( fOutput )
Alan Mishchenko committed
1257
        assert( !strncmp(pToken, "output_", 7) );
Alan Mishchenko committed
1258
    else
Alan Mishchenko committed
1259 1260
        assert( !strncmp(pToken, "input_", 6) );
    if ( Vec_PtrSize(vTokens) != 2 && Vec_PtrSize(vTokens) != 3 )
Alan Mishchenko committed
1261
    {
1262
        sprintf( p->pMan->sError, "Line %d: Delay line does not have a valid number of parameters (2 or 3).", Ntl_ReadGetLine(p->pMan, pToken) );
Alan Mishchenko committed
1263 1264 1265
        return 0;
    }
    // find the delay number
1266
    pTokenNum = (char *)Vec_PtrEntryLast(vTokens);
Alan Mishchenko committed
1267
    if ( !strcmp( pTokenNum, "-inf" ) )
Alan Mishchenko committed
1268
        Delay = -TIM_ETERNITY;
Alan Mishchenko committed
1269
    else if ( !strcmp( pTokenNum, "inf" ) ) 
Alan Mishchenko committed
1270
        Delay = TIM_ETERNITY;
Alan Mishchenko committed
1271 1272 1273 1274
    else
        Delay = atof( pTokenNum );
    if ( Delay == 0.0 && pTokenNum[0] != '0' )
    {
1275
        sprintf( p->pMan->sError, "Line %d: Delay value (%s) appears to be invalid.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntryLast(vTokens) );
Alan Mishchenko committed
1276 1277 1278 1279 1280
        return 0;
    }
    // find the PI/PO numbers
    if ( fOutput )
    {
Alan Mishchenko committed
1281
        if ( Vec_PtrSize(vTokens) == 3 )
Alan Mishchenko committed
1282
        {
1283
            RetValue = Ntl_ModelFindPioNumber( p->pNtk, 0, 1, (char *)Vec_PtrEntry(vTokens, 1), &Number );
Alan Mishchenko committed
1284 1285
            if ( RetValue == 0 )
            {
1286
                sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among POs.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens, 1) );
Alan Mishchenko committed
1287 1288
                return 0;
            }
Alan Mishchenko committed
1289 1290
        }
        // store the values
Alan Mishchenko committed
1291 1292 1293 1294
        if ( p->pNtk->vTimeOutputs == NULL )
            p->pNtk->vTimeOutputs = Vec_IntAlloc( 100 );
        Vec_IntPush( p->pNtk->vTimeOutputs, Number );
        Vec_IntPush( p->pNtk->vTimeOutputs, Aig_Float2Int(Delay) );        
Alan Mishchenko committed
1295 1296 1297
    }
    else
    {
Alan Mishchenko committed
1298
        if ( Vec_PtrSize(vTokens) == 3 )
Alan Mishchenko committed
1299
        {
1300
            RetValue = Ntl_ModelFindPioNumber( p->pNtk, 1, 0, (char *)Vec_PtrEntry(vTokens, 1), &Number );
Alan Mishchenko committed
1301 1302
            if ( RetValue == 0 )
            {
1303
                sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs.", Ntl_ReadGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens, 1) );
Alan Mishchenko committed
1304 1305
                return 0;
            }
Alan Mishchenko committed
1306 1307
        }
        // store the values
Alan Mishchenko committed
1308 1309 1310 1311
        if ( p->pNtk->vTimeInputs == NULL )
            p->pNtk->vTimeInputs = Vec_IntAlloc( 100 );
        Vec_IntPush( p->pNtk->vTimeInputs, Number );
        Vec_IntPush( p->pNtk->vTimeInputs, Aig_Float2Int(Delay) );        
Alan Mishchenko committed
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
    }
    return 1;
}


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

  Synopsis    [Constructs the SOP cover from the file parsing info.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
1328
static char * Ntl_ReadParseTableBlif( Ntl_ReadMod_t * p, char * pTable, int nFanins )
Alan Mishchenko committed
1329 1330 1331 1332 1333 1334
{
    Vec_Ptr_t * vTokens = p->pMan->vTokens;
    Vec_Str_t * vFunc = p->pMan->vFunc;
    char * pProduct, * pOutput;
    int i, Polarity = -1;

Alan Mishchenko committed
1335

Alan Mishchenko committed
1336 1337
    p->pMan->nTablesRead++;
    // get the tokens
1338
    Ntl_ReadSplitIntoTokens( vTokens, pTable, '.' );
Alan Mishchenko committed
1339
    if ( Vec_PtrSize(vTokens) == 0 )
Alan Mishchenko committed
1340
        return Ntl_ManStoreSop( p->pMan->pDesign->pMemSops, " 0\n" );
Alan Mishchenko committed
1341 1342
    if ( Vec_PtrSize(vTokens) == 1 )
    {
1343
        pOutput = (char *)Vec_PtrEntry( vTokens, 0 );
Alan Mishchenko committed
1344 1345
        if ( *pOutput == '\"' )
            return Ntl_ManStoreSop( p->pMan->pDesign->pMemSops, pOutput );
Alan Mishchenko committed
1346 1347
        if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
        {
1348
            sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Ntl_ReadGetLine(p->pMan, pOutput), pOutput );
Alan Mishchenko committed
1349 1350
            return NULL;
        }
Alan Mishchenko committed
1351
        return Ntl_ManStoreSop( p->pMan->pDesign->pMemSops, (pOutput[0] == '0') ? " 0\n" : " 1\n" );
Alan Mishchenko committed
1352
    }
1353
    pProduct = (char *)Vec_PtrEntry( vTokens, 0 );
Alan Mishchenko committed
1354 1355
    if ( Vec_PtrSize(vTokens) % 2 == 1 )
    {
1356
        sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Ntl_ReadGetLine(p->pMan, pProduct), Vec_PtrSize(vTokens) );
Alan Mishchenko committed
1357 1358 1359 1360 1361 1362
        return NULL;
    }
    // parse the table
    Vec_StrClear( vFunc );
    for ( i = 0; i < Vec_PtrSize(vTokens)/2; i++ )
    {
1363 1364
        pProduct = (char *)Vec_PtrEntry( vTokens, 2*i + 0 );
        pOutput  = (char *)Vec_PtrEntry( vTokens, 2*i + 1 );
Alan Mishchenko committed
1365 1366
        if ( strlen(pProduct) != (unsigned)nFanins )
        {
1367
            sprintf( p->pMan->sError, "Line %d: Cube \"%s\" has size different from the fanin count (%d).", Ntl_ReadGetLine(p->pMan, pProduct), pProduct, nFanins );
Alan Mishchenko committed
1368 1369 1370 1371
            return NULL;
        }
        if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
        {
1372
            sprintf( p->pMan->sError, "Line %d: Output value \"%s\" is incorrect.", Ntl_ReadGetLine(p->pMan, pProduct), pOutput );
Alan Mishchenko committed
1373 1374 1375 1376 1377 1378
            return NULL;
        }
        if ( Polarity == -1 )
            Polarity = pOutput[0] - '0';
        else if ( Polarity != pOutput[0] - '0' )
        {
1379
            sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Ntl_ReadGetLine(p->pMan, pProduct), pOutput, Polarity );
Alan Mishchenko committed
1380 1381 1382
            return NULL;
        }
        // parse one product 
1383
        Vec_StrPrintStr( vFunc, pProduct );
Alan Mishchenko committed
1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402
        Vec_StrPush( vFunc, ' ' );
        Vec_StrPush( vFunc, pOutput[0] );
        Vec_StrPush( vFunc, '\n' );
    }
    Vec_StrPush( vFunc, '\0' );
    return Vec_StrArray( vFunc );
}

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

  Synopsis    [Parses the nodes line.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
1403
static int Ntl_ReadParseLineNamesBlif( Ntl_ReadMod_t * p, char * pLine )
Alan Mishchenko committed
1404 1405 1406 1407 1408 1409
{
    Vec_Ptr_t * vTokens = p->pMan->vTokens;
    Ntl_Obj_t * pNode;
    Ntl_Net_t * pNetOut, * pNetIn;
    char * pNameOut, * pNameIn;
    int i;
1410
    Ntl_ReadSplitIntoTokens( vTokens, pLine, '\0' );
Alan Mishchenko committed
1411 1412
    // parse the mapped node
//    if ( !strcmp(Vec_PtrEntry(vTokens,0), "gate") )
1413
//        return Ntl_ReadParseLineGateBlif( p, vTokens );
Alan Mishchenko committed
1414
    // parse the regular name line
1415 1416
    assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "names") );
    pNameOut = (char *)Vec_PtrEntryLast( vTokens );
Alan Mishchenko committed
1417 1418 1419 1420 1421
    pNetOut = Ntl_ModelFindOrCreateNet( p->pNtk, pNameOut );
    // create fanins
    pNode = Ntl_ModelCreateNode( p->pNtk, Vec_PtrSize(vTokens) - 2 );
    for ( i = 0; i < Vec_PtrSize(vTokens) - 2; i++ )
    {
1422
        pNameIn = (char *)Vec_PtrEntry(vTokens, i+1);
Alan Mishchenko committed
1423 1424 1425 1426 1427
        pNetIn = Ntl_ModelFindOrCreateNet( p->pNtk, pNameIn );
        Ntl_ObjSetFanin( pNode, pNetIn, i );
    }
    if ( !Ntl_ModelSetNetDriver( pNode, pNetOut ) )
    {
1428
        sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Ntl_ReadGetLine(p->pMan, pNameOut), pNameOut );
Alan Mishchenko committed
1429 1430 1431
        return 0;
    }
    // parse the table of this node
1432
    pNode->pSop = Ntl_ReadParseTableBlif( p, pNameOut + strlen(pNameOut), pNode->nFanins );
Alan Mishchenko committed
1433 1434
    if ( pNode->pSop == NULL )
        return 0;
Alan Mishchenko committed
1435
    pNode->pSop = Ntl_ManStoreSop( p->pNtk->pMan->pMemSops, pNode->pSop );
Alan Mishchenko committed
1436 1437 1438 1439 1440 1441 1442 1443 1444
    return 1;
}


////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


1445 1446
ABC_NAMESPACE_IMPL_END