giaAiger.c 53.3 KB
Newer Older
Alan Mishchenko committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/**CFile****************************************************************

  FileName    [giaAiger.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Scalable AIG package.]

  Synopsis    [Procedures to read/write binary AIGER format developed by
  Armin Biere, Johannes Kepler University (http://fmv.jku.at/)]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - June 20, 2005.]

  Revision    [$Id: giaAiger.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]

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

#include "gia.h"
23
#include "misc/tim/tim.h"
24
#include "base/main/main.h"
Alan Mishchenko committed
25

26 27
ABC_NAMESPACE_IMPL_START

28
#define XAIG_VERBOSE 0
29

Alan Mishchenko committed
30 31 32 33 34 35 36 37 38 39
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

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

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

40
  Synopsis    []
Alan Mishchenko committed
41 42 43 44 45 46 47 48

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
49
void Gia_FileFixName( char * pFileName )
Alan Mishchenko committed
50 51 52 53 54 55
{
    char * pName;
    for ( pName = pFileName; *pName; pName++ )
        if ( *pName == '>' )
            *pName = '\\';
}
56 57 58 59 60 61 62 63
char * Gia_FileNameGeneric( char * FileName )
{
    char * pDot, * pRes;
    pRes = Abc_UtilStrsav( FileName );
    if ( (pDot = strrchr( pRes, '.' )) )
        *pDot = 0;
    return pRes;
}
Alan Mishchenko committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
int Gia_FileSize( char * pFileName )
{
    FILE * pFile;
    int nFileSize;
    pFile = fopen( pFileName, "r" );
    if ( pFile == NULL )
    {
        printf( "Gia_FileSize(): The file is unavailable (absent or open).\n" );
        return 0;
    }
    fseek( pFile, 0, SEEK_END );  
    nFileSize = ftell( pFile ); 
    fclose( pFile );
    return nFileSize;
}
79
void Gia_FileWriteBufferSize( FILE * pFile, int nSize )
Alan Mishchenko committed
80
{
81 82 83
    unsigned char Buffer[5];
    Gia_AigerWriteInt( Buffer, nSize );
    fwrite( Buffer, 1, 4, pFile );
Alan Mishchenko committed
84 85 86 87
}

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

88
  Synopsis    [Create the array of literals to be written.]
Alan Mishchenko committed
89 90 91 92 93 94 95 96

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
97
Vec_Int_t * Gia_AigerCollectLiterals( Gia_Man_t * p )
Alan Mishchenko committed
98
{
99 100 101 102 103 104 105 106 107
    Vec_Int_t * vLits;
    Gia_Obj_t * pObj;
    int i;
    vLits = Vec_IntAlloc( Gia_ManPoNum(p) );
    Gia_ManForEachRi( p, pObj, i )
        Vec_IntPush( vLits, Gia_ObjFaninLit0p(p, pObj) );
    Gia_ManForEachPo( p, pObj, i )
        Vec_IntPush( vLits, Gia_ObjFaninLit0p(p, pObj) );
    return vLits;
Alan Mishchenko committed
108
}
109
Vec_Int_t * Gia_AigerReadLiterals( unsigned char ** ppPos, int nEntries )
Alan Mishchenko committed
110
{
111 112 113 114 115 116
    Vec_Int_t * vLits;
    int Lit, LitPrev, Diff, i;
    vLits = Vec_IntAlloc( nEntries );
    LitPrev = Gia_AigerReadUnsigned( ppPos );
    Vec_IntPush( vLits, LitPrev );
    for ( i = 1; i < nEntries; i++ )
Alan Mishchenko committed
117
    {
118 119 120 121 122 123 124 125
//        Diff = Lit - LitPrev;
//        Diff = (Lit < LitPrev)? -Diff : Diff;
//        Diff = ((2 * Diff) << 1) | (int)(Lit < LitPrev);
        Diff = Gia_AigerReadUnsigned( ppPos );
        Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1;
        Lit  = Diff + LitPrev;
        Vec_IntPush( vLits, Lit );
        LitPrev = Lit;
Alan Mishchenko committed
126
    }
127
    return vLits;
Alan Mishchenko committed
128
}
129
Vec_Str_t * Gia_AigerWriteLiterals( Vec_Int_t * vLits )
Alan Mishchenko committed
130
{
131 132 133 134 135 136
    Vec_Str_t * vBinary;
    int Pos = 0, Lit, LitPrev, Diff, i;
    vBinary = Vec_StrAlloc( 2 * Vec_IntSize(vLits) );
    LitPrev = Vec_IntEntry( vLits, 0 );
    Pos = Gia_AigerWriteUnsignedBuffer( (unsigned char *)Vec_StrArray(vBinary), Pos, LitPrev ); 
    Vec_IntForEachEntryStart( vLits, Lit, i, 1 )
Alan Mishchenko committed
137
    {
138 139 140 141 142 143 144
        Diff = Lit - LitPrev;
        Diff = (Lit < LitPrev)? -Diff : Diff;
        Diff = (Diff << 1) | (int)(Lit < LitPrev);
        Pos = Gia_AigerWriteUnsignedBuffer( (unsigned char *)Vec_StrArray(vBinary), Pos, Diff );
        LitPrev = Lit;
        if ( Pos + 10 > vBinary->nCap )
            Vec_StrGrow( vBinary, vBinary->nCap+1 );
Alan Mishchenko committed
145
    }
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
    vBinary->nSize = Pos;
/*
    // verify
    {
        extern Vec_Int_t * Gia_AigerReadLiterals( char ** ppPos, int nEntries );
        char * pPos = Vec_StrArray( vBinary );
        Vec_Int_t * vTemp = Gia_AigerReadLiterals( &pPos, Vec_IntSize(vLits) );
        for ( i = 0; i < Vec_IntSize(vLits); i++ )
        {
            int Entry1 = Vec_IntEntry(vLits,i);
            int Entry2 = Vec_IntEntry(vTemp,i);
            assert( Entry1 == Entry2 );
        }
        Vec_IntFree( vTemp );
    }
*/
    return vBinary;
Alan Mishchenko committed
163 164 165 166
}

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

Alan Mishchenko committed
167 168 169 170 171 172 173 174 175
  Synopsis    [Reads the AIG in the binary AIGER format.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
176
Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSimple, int fSkipStrash, int fCheck )
Alan Mishchenko committed
177
{
178 179
    Gia_Man_t * pNew, * pTemp;
    Vec_Int_t * vLits = NULL, * vPoTypes = NULL;
180
    Vec_Int_t * vNodes, * vDrivers, * vInits = NULL;
181
    int iObj, iNode0, iNode1, fHieOnly = 0;
182
    int nTotal, nInputs, nOutputs, nLatches, nAnds, i;
183
    int nBad = 0, nConstr = 0, nJust = 0, nFair = 0;
184
    unsigned char * pDrivers, * pSymbols, * pCur;
Alan Mishchenko committed
185 186
    unsigned uLit0, uLit1, uLit;

187 188
    // read the parameters (M I L O A + B C J F)
    pCur = (unsigned char *)pContents;         while ( *pCur != ' ' ) pCur++; pCur++;
Alan Mishchenko committed
189
    // read the number of objects
190
    nTotal = atoi( (const char *)pCur );    while ( *pCur != ' ' ) pCur++; pCur++;
Alan Mishchenko committed
191
    // read the number of inputs
192
    nInputs = atoi( (const char *)pCur );   while ( *pCur != ' ' ) pCur++; pCur++;
Alan Mishchenko committed
193
    // read the number of latches
194
    nLatches = atoi( (const char *)pCur );  while ( *pCur != ' ' ) pCur++; pCur++;
Alan Mishchenko committed
195
    // read the number of outputs
196
    nOutputs = atoi( (const char *)pCur );  while ( *pCur != ' ' ) pCur++; pCur++;
Alan Mishchenko committed
197
    // read the number of nodes
198
    nAnds = atoi( (const char *)pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
199 200
    if ( *pCur == ' ' )
    {
201
//        assert( nOutputs == 0 );
202 203
        // read the number of properties
        pCur++;
204
        nBad = atoi( (const char *)pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
205 206 207 208 209 210
        nOutputs += nBad;
    }
    if ( *pCur == ' ' )
    {
        // read the number of properties
        pCur++;
211
        nConstr = atoi( (const char *)pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
212 213 214 215 216 217
        nOutputs += nConstr;
    }
    if ( *pCur == ' ' )
    {
        // read the number of properties
        pCur++;
218
        nJust = atoi( (const char *)pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
219 220 221 222 223 224
        nOutputs += nJust;
    }
    if ( *pCur == ' ' )
    {
        // read the number of properties
        pCur++;
225
        nFair = atoi( (const char *)pCur );     while ( *pCur != ' ' && *pCur != '\n' ) pCur++; 
226 227 228 229 230 231 232 233 234
        nOutputs += nFair;
    }
    if ( *pCur != '\n' )
    {
        fprintf( stdout, "The parameter line is in a wrong format.\n" );
        return NULL;
    }
    pCur++;

Alan Mishchenko committed
235 236 237
    // check the parameters
    if ( nTotal != nInputs + nLatches + nAnds )
    {
238
        fprintf( stdout, "The number of objects does not match.\n" );
Alan Mishchenko committed
239 240
        return NULL;
    }
241 242
    if ( nJust || nFair )
    {
243
        fprintf( stdout, "Reading AIGER files with liveness properties is currently not supported.\n" );
244 245 246 247 248 249 250 251 252 253
        return NULL;
    }

    if ( nConstr )
    {
        if ( nConstr == 1 )
            fprintf( stdout, "Warning: The last output is interpreted as a constraint.\n" );
        else
            fprintf( stdout, "Warning: The last %d outputs are interpreted as constraints.\n", nConstr );
    }
Alan Mishchenko committed
254 255 256

    // allocate the empty AIG
    pNew = Gia_ManStart( nTotal + nLatches + nOutputs + 1 );
257
    pNew->nConstrs = nConstr;
258
    pNew->fGiaSimple = fGiaSimple;
Alan Mishchenko committed
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281

    // prepare the array of nodes
    vNodes = Vec_IntAlloc( 1 + nTotal );
    Vec_IntPush( vNodes, 0 );

    // create the PIs
    for ( i = 0; i < nInputs + nLatches; i++ )
    {
        iObj = Gia_ManAppendCi(pNew);    
        Vec_IntPush( vNodes, iObj );
    }

    // remember the beginning of latch/PO literals
    pDrivers = pCur;
    if ( pContents[3] == ' ' ) // standard AIGER
    {
        // scroll to the beginning of the binary data
        for ( i = 0; i < nLatches + nOutputs; )
            if ( *pCur++ == '\n' )
                i++;
    }
    else // modified AIGER
    {
282
        vLits = Gia_AigerReadLiterals( &pCur, nLatches + nOutputs );
Alan Mishchenko committed
283 284 285
    }

    // create the AND gates
286
    if ( !fGiaSimple && !fSkipStrash )
287
        Gia_ManHashAlloc( pNew );
Alan Mishchenko committed
288 289 290
    for ( i = 0; i < nAnds; i++ )
    {
        uLit = ((i + 1 + nInputs + nLatches) << 1);
291 292
        uLit1 = uLit  - Gia_AigerReadUnsigned( &pCur );
        uLit0 = uLit1 - Gia_AigerReadUnsigned( &pCur );
Alan Mishchenko committed
293
//        assert( uLit1 > uLit0 );
294 295
        iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), uLit0 & 1 );
        iNode1 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit1 >> 1), uLit1 & 1 );
Alan Mishchenko committed
296
        assert( Vec_IntSize(vNodes) == i + 1 + nInputs + nLatches );
297
        if ( !fGiaSimple && fSkipStrash )
298 299 300 301 302 303
        {
            if ( iNode0 == iNode1 )
                Vec_IntPush( vNodes, Gia_ManAppendBuf(pNew, iNode0) );
            else
                Vec_IntPush( vNodes, Gia_ManAppendAnd(pNew, iNode0, iNode1) );
        }
304 305
        else
            Vec_IntPush( vNodes, Gia_ManHashAnd(pNew, iNode0, iNode1) );
Alan Mishchenko committed
306
    }
307
    if ( !fGiaSimple && !fSkipStrash )
308
        Gia_ManHashStop( pNew );
Alan Mishchenko committed
309 310 311 312 313 314 315 316

    // remember the place where symbols begin
    pSymbols = pCur;

    // read the latch driver literals
    vDrivers = Vec_IntAlloc( nLatches + nOutputs );
    if ( pContents[3] == ' ' ) // standard AIGER
    {
317
        vInits = Vec_IntAlloc( nLatches );
Alan Mishchenko committed
318 319 320
        pCur = pDrivers;
        for ( i = 0; i < nLatches; i++ )
        {
321 322 323 324 325 326 327 328 329 330 331 332 333 334
            uLit0 = atoi( (char *)pCur );   
            while ( *pCur != ' ' && *pCur != '\n' ) 
                pCur++;
            if ( *pCur == ' ' )
            {
                pCur++;
                Vec_IntPush( vInits, atoi( (char *)pCur ) );
                while ( *pCur++ != '\n' );
            }
            else
            {
                pCur++;
                Vec_IntPush( vInits, 0 );
            }
335
            iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );
Alan Mishchenko committed
336 337 338 339 340
            Vec_IntPush( vDrivers, iNode0 );
        }
        // read the PO driver literals
        for ( i = 0; i < nOutputs; i++ )
        {
341
            uLit0 = atoi( (char *)pCur );   while ( *pCur++ != '\n' );
342
            iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );
Alan Mishchenko committed
343 344 345 346 347 348 349 350 351 352
            Vec_IntPush( vDrivers, iNode0 );
        }

    }
    else
    {
        // read the latch driver literals
        for ( i = 0; i < nLatches; i++ )
        {
            uLit0 = Vec_IntEntry( vLits, i );
353
            iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );
Alan Mishchenko committed
354 355 356 357 358 359
            Vec_IntPush( vDrivers, iNode0 );
        }
        // read the PO driver literals
        for ( i = 0; i < nOutputs; i++ )
        {
            uLit0 = Vec_IntEntry( vLits, i+nLatches );
360
            iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );
Alan Mishchenko committed
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
            Vec_IntPush( vDrivers, iNode0 );
        }
        Vec_IntFree( vLits );
    }

    // create the POs
    for ( i = 0; i < nOutputs; i++ )
        Gia_ManAppendCo( pNew, Vec_IntEntry(vDrivers, nLatches + i) );
    for ( i = 0; i < nLatches; i++ )
        Gia_ManAppendCo( pNew, Vec_IntEntry(vDrivers, i) );
    Vec_IntFree( vDrivers );

    // create the latches
    Gia_ManSetRegNum( pNew, nLatches );

376
    // read signal names if they are of the special type
Alan Mishchenko committed
377
    pCur = pSymbols;
378
    if ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' )
Alan Mishchenko committed
379
    {
380 381 382 383 384 385
        int fBreakUsed = 0;
        unsigned char * pCurOld = pCur;
        pNew->vUserPiIds = Vec_IntStartFull( nInputs );
        pNew->vUserPoIds = Vec_IntStartFull( nOutputs );
        pNew->vUserFfIds = Vec_IntStartFull( nLatches );
        while ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' )
386 387
        {
            int iTerm;
388
            char * pType = (char *)pCur;
389 390 391
            // check terminal type
            if ( *pCur != 'i' && *pCur != 'o' && *pCur != 'l'  )
            {
392
//                fprintf( stdout, "Wrong terminal type.\n" );
393 394 395 396
                fBreakUsed = 1;
                break;
            }
            // get terminal number
397
            iTerm = atoi( (char *)++pCur );  while ( *pCur++ != ' ' );
398
            // skip spaces
399 400
            while ( *pCur == ' ' )
                pCur++;
401 402 403 404 405 406 407 408 409 410
            // decode the user numbers:
            // flops are named: @l<num>
            // PIs are named: @i<num>
            // POs are named: @o<num>
            if ( *pCur++ != '@' )
            {
                fBreakUsed = 1;
                break;
            }
            if ( *pCur == 'i' && *pType == 'i' )
411
                Vec_IntWriteEntry( pNew->vUserPiIds, iTerm, atoi((char *)pCur+1) );
412
            else if ( *pCur == 'o' && *pType == 'o' )
413
                Vec_IntWriteEntry( pNew->vUserPoIds, iTerm, atoi((char *)pCur+1) );
414
            else if ( *pCur == 'l' && *pType == 'l' )
415
                Vec_IntWriteEntry( pNew->vUserFfIds, iTerm, atoi((char *)pCur+1) );
416 417 418 419 420 421 422 423 424 425 426 427
            else
            {
                fprintf( stdout, "Wrong name format.\n" );
                fBreakUsed = 1;
                break;
            }
            // skip digits
            while ( *pCur++ != '\n' );
        }
        // in case of abnormal termination, remove the arrays
        if ( fBreakUsed )
        {
428
            unsigned char * pName;
429 430 431 432
            int Entry, nInvars, nConstr, iTerm;

            Vec_Int_t * vPoNames = Vec_IntStartFull( nOutputs );

433 434 435
            Vec_IntFreeP( &pNew->vUserPiIds );
            Vec_IntFreeP( &pNew->vUserPoIds );
            Vec_IntFreeP( &pNew->vUserFfIds );
436 437 438

            // try to figure out signal names
            fBreakUsed = 0;
439 440
            pCur = (unsigned char *)pCurOld;
            while ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' )
441 442 443
            {
                // get the terminal type
                if ( *pCur == 'i' || *pCur == 'l' )
444 445 446 447
                {
                    // skip till the end of the line
                    while ( *pCur++ != '\n' );
                    *(pCur-1) = 0;
448
                    continue;
449
                }
450 451
                if ( *pCur != 'o' )
                {
452
//                    fprintf( stdout, "Wrong terminal type.\n" );
453 454 455 456
                    fBreakUsed = 1;
                    break;
                }
                // get the terminal number
457
                iTerm = atoi( (char *)++pCur );  while ( *pCur++ != ' ' );
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
                // get the node
                if ( iTerm < 0 || iTerm >= nOutputs )
                {
                    fprintf( stdout, "The output number (%d) is out of range.\n", iTerm );
                    fBreakUsed = 1;
                    break;
                }
                if ( Vec_IntEntry(vPoNames, iTerm) != ~0 )
                {
                    fprintf( stdout, "The output number (%d) is listed twice.\n", iTerm );
                    fBreakUsed = 1;
                    break;
                }

                // get the name
                pName = pCur;          while ( *pCur++ != '\n' );
                *(pCur-1) = 0;
                // assign the name
476
                Vec_IntWriteEntry( vPoNames, iTerm, pName - (unsigned char *)pContents );
477 478 479 480 481 482
            } 

            // check that all names are assigned
            if ( !fBreakUsed )
            {
                nInvars = nConstr = 0;
483
                vPoTypes = Vec_IntStart( Gia_ManPoNum(pNew) );
484 485 486 487 488
                Vec_IntForEachEntry( vPoNames, Entry, i )
                {
                    if ( Entry == ~0 )
                        continue;
                    if ( strncmp( pContents+Entry, "constraint:", 11 ) == 0 )
489 490
                    {
                        Vec_IntWriteEntry( vPoTypes, i, 1 );
491
                        nConstr++;
492
                    }
493
                    if ( strncmp( pContents+Entry, "invariant:", 10 ) == 0 )
494 495
                    {
                        Vec_IntWriteEntry( vPoTypes, i, 2 );
496
                        nInvars++;
497
                    }
498 499 500 501 502
                }
                if ( nConstr )
                    fprintf( stdout, "Recognized and added %d constraints.\n", nConstr );
                if ( nInvars )
                    fprintf( stdout, "Recognized and skipped %d invariants.\n", nInvars );
503 504
                if ( nConstr == 0 && nInvars == 0 )
                    Vec_IntFreeP( &vPoTypes );
505 506
            }
            Vec_IntFree( vPoNames );
507 508 509
        }
    }

510 511 512 513

    // check if there are other types of information to read
    if ( pCur + 1 < (unsigned char *)pContents + nFileSize && *pCur == 'c' )
    {
514
        int fVerbose = XAIG_VERBOSE;
515
        Vec_Str_t * vStr;
516
        unsigned char * pCurTemp;
517
        pCur++;
518
        // skip new line if present
519 520
//        if ( *pCur == '\n' )
//            pCur++;
521
        while ( pCur < (unsigned char *)pContents + nFileSize )
522
        {
523 524 525 526
            // read extra AIG
            if ( *pCur == 'a' )
            {
                pCur++;
527
                vStr = Vec_StrStart( Gia_AigerReadInt(pCur) );             pCur += 4;
528
                memcpy( Vec_StrArray(vStr), pCur, (size_t)Vec_StrSize(vStr) );
529
                pCur += Vec_StrSize(vStr);
530
                pNew->pAigExtra = Gia_AigerReadFromMemory( Vec_StrArray(vStr), Vec_StrSize(vStr), 0, 0, 0 );
531
                Vec_StrFree( vStr );
532
                if ( fVerbose ) printf( "Finished reading extension \"a\".\n" );
533 534 535 536 537
            }
            // read number of constraints
            else if ( *pCur == 'c' )
            {
                pCur++;
538 539
                assert( Gia_AigerReadInt(pCur) == 4 );                     pCur += 4;
                pNew->nConstrs = Gia_AigerReadInt( pCur );                 pCur += 4;
540
                if ( fVerbose ) printf( "Finished reading extension \"c\".\n" );
541 542
            }
            // read delay information
543 544 545 546 547 548 549
            else if ( *pCur == 'd' )
            {
                pCur++;
                assert( Gia_AigerReadInt(pCur) == 4 );                     pCur += 4;
                pNew->nAnd2Delay = Gia_AigerReadInt(pCur);                 pCur += 4;
                if ( fVerbose ) printf( "Finished reading extension \"d\".\n" );
            }
550
            else if ( *pCur == 'i' )
551 552
            {
                pCur++;
553 554
                nInputs = Gia_AigerReadInt(pCur)/4;                        pCur += 4;
                pNew->vInArrs  = Vec_FltStart( nInputs );
555
                memcpy( Vec_FltArray(pNew->vInArrs),  pCur, (size_t)4*nInputs );   pCur += 4*nInputs;
556
                if ( fVerbose ) printf( "Finished reading extension \"i\".\n" );
557 558 559 560 561 562
            }
            else if ( *pCur == 'o' )
            {
                pCur++;
                nOutputs = Gia_AigerReadInt(pCur)/4;                       pCur += 4;
                pNew->vOutReqs  = Vec_FltStart( nOutputs );
563
                memcpy( Vec_FltArray(pNew->vOutReqs),  pCur, (size_t)4*nOutputs ); pCur += 4*nOutputs;
564
                if ( fVerbose ) printf( "Finished reading extension \"o\".\n" );
565
            }
566
            // read equivalence classes
567 568 569 570
            else if ( *pCur == 'e' )
            {
                extern Gia_Rpr_t * Gia_AigerReadEquivClasses( unsigned char ** ppPos, int nSize );
                pCur++;
571
                pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;              pCur += 4;
572 573
                pNew->pReprs = Gia_AigerReadEquivClasses( &pCur, Gia_ManObjNum(pNew) );
                pNew->pNexts = Gia_ManDeriveNexts( pNew );
574
                assert( pCur == pCurTemp );
575
                if ( fVerbose ) printf( "Finished reading extension \"e\".\n" );
576
            }
577
            // read flop classes
578 579 580
            else if ( *pCur == 'f' )
            {
                pCur++;
581 582
                assert( Gia_AigerReadInt(pCur) == 4*Gia_ManRegNum(pNew) );   pCur += 4;
                pNew->vFlopClasses  = Vec_IntStart( Gia_ManRegNum(pNew) );
583
                memcpy( Vec_IntArray(pNew->vFlopClasses),  pCur, (size_t)4*Gia_ManRegNum(pNew) );   pCur += 4*Gia_ManRegNum(pNew);
584
                if ( fVerbose ) printf( "Finished reading extension \"f\".\n" );
585
            }
586
            // read gate classes
587 588 589 590 591
            else if ( *pCur == 'g' )
            {
                pCur++;
                assert( Gia_AigerReadInt(pCur) == 4*Gia_ManObjNum(pNew) );   pCur += 4;
                pNew->vGateClasses  = Vec_IntStart( Gia_ManObjNum(pNew) );
592
                memcpy( Vec_IntArray(pNew->vGateClasses),  pCur, (size_t)4*Gia_ManObjNum(pNew) );   pCur += 4*Gia_ManObjNum(pNew);
593
                if ( fVerbose ) printf( "Finished reading extension \"g\".\n" );
594 595 596 597 598 599
            }
            // read hierarchy information
            else if ( *pCur == 'h' )
            {
                pCur++;
                vStr = Vec_StrStart( Gia_AigerReadInt(pCur) );          pCur += 4;
600
                memcpy( Vec_StrArray(vStr), pCur, (size_t)Vec_StrSize(vStr) );
601 602 603
                pCur += Vec_StrSize(vStr);
                pNew->pManTime = Tim_ManLoad( vStr, 1 );
                Vec_StrFree( vStr );
604
                fHieOnly = 1;
605
                if ( fVerbose ) printf( "Finished reading extension \"h\".\n" );
606 607 608 609 610
            }
            // read packing
            else if ( *pCur == 'k' )
            {
                extern Vec_Int_t * Gia_AigerReadPacking( unsigned char ** ppPos, int nSize );
611
                int nSize;
612
                pCur++;
613 614 615
                nSize = Gia_AigerReadInt(pCur);
                pCurTemp = pCur + nSize + 4;                            pCur += 4;
                pNew->vPacking = Gia_AigerReadPacking( &pCur, nSize ); 
616
                assert( pCur == pCurTemp );
617
                if ( fVerbose ) printf( "Finished reading extension \"k\".\n" );
618
            }
619
            // read mapping
620 621 622
            else if ( *pCur == 'm' )
            {
                extern int * Gia_AigerReadMapping( unsigned char ** ppPos, int nSize );
623
                extern int * Gia_AigerReadMappingSimple( unsigned char ** ppPos, int nSize );
624 625
                extern Vec_Int_t * Gia_AigerReadMappingDoc( unsigned char ** ppPos, int nObjs );
                int nSize;
626
                pCur++;
627 628
                nSize = Gia_AigerReadInt(pCur);
                pCurTemp = pCur + nSize + 4;           pCur += 4;
629
                pNew->vMapping = Gia_AigerReadMappingDoc( &pCur, Gia_ManObjNum(pNew) );
630
                assert( pCur == pCurTemp );
631
                if ( fVerbose ) printf( "Finished reading extension \"m\".\n" );
632 633 634 635 636 637 638 639 640 641 642
            }
            // read model name
            else if ( *pCur == 'n' )
            {
                pCur++;
                if ( (*pCur >= 'a' && *pCur <= 'z') || (*pCur >= 'A' && *pCur <= 'Z') || (*pCur >= '0' && *pCur <= '9') )
                {
                    pNew->pName = Abc_UtilStrsav( (char *)pCur );       pCur += strlen(pNew->pName) + 1;
                }
                else
                {
643
                    pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;       pCur += 4;
644 645 646 647 648
                    ABC_FREE( pNew->pName );
                    pNew->pName = Abc_UtilStrsav( (char *)pCur );       pCur += strlen(pNew->pName) + 1;
                    assert( pCur == pCurTemp );
                }
            }
649
            // read placement
650 651 652 653
            else if ( *pCur == 'p' )
            {
                Gia_Plc_t * pPlacement;
                pCur++;
654
                pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;           pCur += 4;
655
                pPlacement = ABC_ALLOC( Gia_Plc_t, Gia_ManObjNum(pNew) );
656
                memcpy( pPlacement, pCur, (size_t)4*Gia_ManObjNum(pNew) );      pCur += 4*Gia_ManObjNum(pNew);
657
                assert( pCur == pCurTemp );
658
                pNew->pPlacement = pPlacement;
659
                if ( fVerbose ) printf( "Finished reading extension \"p\".\n" );
660
            }
661 662 663
            // read register classes
            else if ( *pCur == 'r' )
            {
664
                int i, nRegs;
665
                pCur++;
666
                pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;           pCur += 4;
667 668
                nRegs = Gia_AigerReadInt(pCur);                         pCur += 4;
                //nRegs = (pCurTemp - pCur)/4;
669 670 671
                pNew->vRegClasses = Vec_IntAlloc( nRegs );
                for ( i = 0; i < nRegs; i++ )
                    Vec_IntPush( pNew->vRegClasses, Gia_AigerReadInt(pCur) ), pCur += 4;
672
                assert( pCur == pCurTemp );
673 674
                if ( fVerbose ) printf( "Finished reading extension \"r\".\n" );
            }
675 676 677 678 679 680 681 682 683 684 685 686 687
            // read register inits
            else if ( *pCur == 's' )
            {
                int i, nRegs;
                pCur++;
                pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;           pCur += 4;
                nRegs = Gia_AigerReadInt(pCur);                         pCur += 4;
                pNew->vRegInits = Vec_IntAlloc( nRegs );
                for ( i = 0; i < nRegs; i++ )
                    Vec_IntPush( pNew->vRegInits, Gia_AigerReadInt(pCur) ), pCur += 4;
                assert( pCur == pCurTemp );
                if ( fVerbose ) printf( "Finished reading extension \"s\".\n" );
            }
688 689 690 691 692 693 694
            // read configuration data
            else if ( *pCur == 'b' )
            {
                int nSize;
                pCur++;
                nSize = Gia_AigerReadInt(pCur);
                pCurTemp = pCur + nSize + 4;                            pCur += 4;
Alan Mishchenko committed
695
                pNew->pCellStr = Abc_UtilStrsav( (char*)pCur );         pCur += strlen((char*)pCur) + 1;
696 697
                nSize = nSize - strlen(pNew->pCellStr) - 1;
                assert( nSize % 4 == 0 );
698
                pNew->vConfigs = Vec_IntAlloc(nSize / 4);
699
//                memcpy(Vec_IntArray(pNew->vConfigs), pCur, (size_t)nSize);      pCur += nSize;
700 701
                for ( i = 0; i < nSize / 4; i++ )
                    Vec_IntPush( pNew->vConfigs, Gia_AigerReadInt(pCur) ), pCur += 4;
702 703 704
                assert( pCur == pCurTemp );
                if ( fVerbose ) printf( "Finished reading extension \"b\".\n" );
            }
705 706 707 708
            // read choices
            else if ( *pCur == 'q' )
            {
                int i, nPairs, iRepr, iNode;
709
                assert( !Gia_ManHasChoices(pNew) );
710 711 712 713 714 715 716 717 718 719 720 721 722 723
                pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(pNew) );
                pCur++;
                pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;           pCur += 4;
                nPairs = Gia_AigerReadInt(pCur);                        pCur += 4;
                for ( i = 0; i < nPairs; i++ )
                {
                    iRepr = Gia_AigerReadInt(pCur);                     pCur += 4;
                    iNode = Gia_AigerReadInt(pCur);                     pCur += 4;
                    pNew->pSibls[iRepr] = iNode;
                    assert( iRepr > iNode );
                }
                assert( pCur == pCurTemp );
                if ( fVerbose ) printf( "Finished reading extension \"q\".\n" );
            }
724
            // read switching activity
725
            else if ( *pCur == 'u' )
726 727 728
            { 
                unsigned char * pSwitching;
                pCur++;
729
                pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;           pCur += 4;
730
                pSwitching = ABC_ALLOC( unsigned char, Gia_ManObjNum(pNew) );
731
                memcpy( pSwitching, pCur, (size_t)Gia_ManObjNum(pNew) );        pCur += Gia_ManObjNum(pNew);
732
                assert( pCur == pCurTemp );
733
                if ( fVerbose ) printf( "Finished reading extension \"s\".\n" );
734
            }
735
            // read timing manager
736 737 738 739
            else if ( *pCur == 't' )
            {
                pCur++;
                vStr = Vec_StrStart( Gia_AigerReadInt(pCur) );          pCur += 4;
740
                memcpy( Vec_StrArray(vStr), pCur, (size_t)Vec_StrSize(vStr) );  pCur += Vec_StrSize(vStr);
741 742
                pNew->pManTime = Tim_ManLoad( vStr, 0 );
                Vec_StrFree( vStr );
743
                if ( fVerbose ) printf( "Finished reading extension \"t\".\n" );
744 745 746 747 748 749
            }
            // read object classes
            else if ( *pCur == 'v' )
            {
                pCur++;
                pNew->vObjClasses = Vec_IntStart( Gia_AigerReadInt(pCur)/4 ); pCur += 4;
750
                memcpy( Vec_IntArray(pNew->vObjClasses), pCur, (size_t)4*Vec_IntSize(pNew->vObjClasses) );
751
                pCur += 4*Vec_IntSize(pNew->vObjClasses);
752
                if ( fVerbose ) printf( "Finished reading extension \"v\".\n" );
753
            }
754 755 756 757 758 759 760 761 762 763 764 765
            // read edge information
            else if ( *pCur == 'w' )
            {
                Vec_Int_t * vPairs;
                int i, nPairs;
                pCur++;
                pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4;           pCur += 4;
                nPairs = Gia_AigerReadInt(pCur);                        pCur += 4;
                vPairs = Vec_IntAlloc( 2*nPairs );
                for ( i = 0; i < 2*nPairs; i++ )
                    Vec_IntPush( vPairs, Gia_AigerReadInt(pCur) ),      pCur += 4;
                assert( pCur == pCurTemp );
766 767 768 769 770 771 772
                if ( fSkipStrash )
                {
                    Gia_ManEdgeFromArray( pNew, vPairs );
                    if ( fVerbose ) printf( "Finished reading extension \"w\".\n" );
                }
                else
                    printf( "Cannot read extension \"w\" because AIG is rehashed. Use \"&r -s <file.aig>\".\n" );
773 774
                Vec_IntFree( vPairs );
            }
775
            else break;
776 777 778
        }
    }

779 780
    // skipping the comments
    Vec_IntFree( vNodes );
781 782 783 784 785

    // update polarity of the additional outputs
    if ( nBad || nConstr || nJust || nFair )
        Gia_ManInvertConstraints( pNew );

786 787 788 789 790 791 792
    // clean the PO drivers
    if ( vPoTypes )
    {
        pNew = Gia_ManDupWithConstraints( pTemp = pNew, vPoTypes );
        Gia_ManStop( pTemp );
        Vec_IntFreeP( &vPoTypes );
    }
793

794
    if ( !fGiaSimple && !fSkipStrash && Gia_ManHasDangling(pNew) )
795
    {
796
        Tim_Man_t * pManTime;
797
        Gia_Man_t * pAigExtra;
798 799 800 801 802 803 804
        Vec_Int_t * vFlopMap, * vGateMap, * vObjMap, * vRegClasses, * vRegInits;
        vRegClasses = pNew->vRegClasses;  pNew->vRegClasses    = NULL;
        vRegInits   = pNew->vRegInits;    pNew->vRegInits      = NULL;
        vFlopMap    = pNew->vFlopClasses; pNew->vFlopClasses   = NULL;
        vGateMap    = pNew->vGateClasses; pNew->vGateClasses   = NULL;
        vObjMap     = pNew->vObjClasses;  pNew->vObjClasses    = NULL;
        pManTime = (Tim_Man_t *)pNew->pManTime; pNew->pManTime = NULL;
805
        pAigExtra   = pNew->pAigExtra;    pNew->pAigExtra      = NULL;
806
        pNew = Gia_ManCleanup( pTemp = pNew );
807 808
        if ( (vGateMap || vObjMap) && (Gia_ManObjNum(pNew) < Gia_ManObjNum(pTemp)) )
            printf( "Cleanup removed objects after reading. Old gate/object abstraction maps are invalid!\n" );
809
        Gia_ManStop( pTemp );
810 811
        pNew->vRegClasses  = vRegClasses;
        pNew->vRegInits    = vRegInits;
812
        pNew->vFlopClasses = vFlopMap;
813
        pNew->vGateClasses = vGateMap;
814
        pNew->vObjClasses  = vObjMap;
815
        pNew->pManTime     = pManTime;
816
        pNew->pAigExtra    = pAigExtra;
817
    }
818 819 820

    if ( fHieOnly )
    {
821
//        Tim_ManPrint( (Tim_Man_t *)pNew->pManTime );
822
        if ( Abc_FrameReadLibBox() == NULL )
823 824
            printf( "Warning: Creating unit-delay box delay tables because box library is not available.\n" );
        Tim_ManCreate( (Tim_Man_t *)pNew->pManTime, Abc_FrameReadLibBox(), pNew->vInArrs, pNew->vOutReqs );
825
    }
826 827
    Vec_FltFreeP( &pNew->vInArrs );
    Vec_FltFreeP( &pNew->vOutReqs );
828 829 830 831 832 833 834 835 836
/*
    // check the result
    if ( fCheck && !Gia_ManCheck( pNew ) )
    {
        printf( "Gia_AigerRead: The network check has failed.\n" );
        Gia_ManStop( pNew );
        return NULL;
    }
*/
837

838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
    if ( vInits && Vec_IntSum(vInits) )
    {
        char * pInit = ABC_ALLOC( char, Vec_IntSize(vInits) + 1 );
        Gia_Obj_t * pObj;
        int i;
        assert( Vec_IntSize(vInits) == Gia_ManRegNum(pNew) );
        Gia_ManForEachRo( pNew, pObj, i )
        {
            if ( Vec_IntEntry(vInits, i) == 0 )
                pInit[i] = '0';
            else if ( Vec_IntEntry(vInits, i) == 1 )
                pInit[i] = '1';
            else 
            {
                assert( Vec_IntEntry(vInits, i) == Abc_Var2Lit(Gia_ObjId(pNew, pObj), 0) );
853
                // unitialized value of the latch is the latch literal according to http://fmv.jku.at/hwmcc11/beyond1.pdf
854 855 856 857
                pInit[i] = 'X';
            }
        }
        pInit[i] = 0;
858
        pNew = Gia_ManDupZeroUndc( pTemp = pNew, pInit, 0, fGiaSimple, 1 );
859 860 861 862 863
        pNew->nConstrs = pTemp->nConstrs; pTemp->nConstrs = 0;
        Gia_ManStop( pTemp );
        ABC_FREE( pInit );
    }
    Vec_IntFreeP( &vInits );
864
    if ( !fGiaSimple && !fSkipStrash && pNew->vMapping )
865 866 867 868
    {
        Abc_Print( 0, "Structural hashing enabled while reading AIGER invalidated the mapping.  Consider using \"&r -s\".\n" );
        Vec_IntFreeP( &pNew->vMapping );
    }
869 870 871 872 873 874 875 876 877 878 879 880 881 882
    return pNew;
}

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

  Synopsis    [Reads the AIG in the binary AIGER format.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
883
Gia_Man_t * Gia_AigerRead( char * pFileName, int fGiaSimple, int fSkipStrash, int fCheck )
884 885 886 887 888
{
    FILE * pFile;
    Gia_Man_t * pNew;
    char * pName, * pContents;
    int nFileSize;
889
    int RetValue;
890 891

    // read the file into the buffer
892
    Gia_FileFixName( pFileName );
893 894 895
    nFileSize = Gia_FileSize( pFileName );
    pFile = fopen( pFileName, "rb" );
    pContents = ABC_ALLOC( char, nFileSize );
896
    RetValue = fread( pContents, nFileSize, 1, pFile );
897 898
    fclose( pFile );

899
    pNew = Gia_AigerReadFromMemory( pContents, nFileSize, fGiaSimple, fSkipStrash, fCheck );
900 901 902
    ABC_FREE( pContents );
    if ( pNew )
    {
903
        ABC_FREE( pNew->pName );
904
        pName = Gia_FileNameGeneric( pFileName );
905
        pNew->pName = Abc_UtilStrsav( pName );
906
        ABC_FREE( pName );
907 908 909

        assert( pNew->pSpec == NULL );
        pNew->pSpec = Abc_UtilStrsav( pFileName );
910 911 912 913 914 915 916 917
    }
    return pNew;
}



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

918
  Synopsis    [Writes the AIG in into the memory buffer.]
Alan Mishchenko committed
919

920 921
  Description [The resulting buffer constains the AIG in AIGER format. 
  The resulting buffer should be deallocated by the user.]
Alan Mishchenko committed
922 923 924 925 926 927
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
928
Vec_Str_t * Gia_AigerWriteIntoMemoryStr( Gia_Man_t * p )
Alan Mishchenko committed
929
{
930
    Vec_Str_t * vBuffer;
Alan Mishchenko committed
931
    Gia_Obj_t * pObj;
932 933 934 935 936 937 938
    int nNodes = 0, i, uLit, uLit0, uLit1; 
    // set the node numbers to be used in the output file
    Gia_ManConst0(p)->Value = nNodes++;
    Gia_ManForEachCi( p, pObj, i )
        pObj->Value = nNodes++;
    Gia_ManForEachAnd( p, pObj, i )
        pObj->Value = nNodes++;
Alan Mishchenko committed
939

940 941 942 943 944 945 946 947 948 949 950 951 952
    // write the header "M I L O A" where M = I + L + A
    vBuffer = Vec_StrAlloc( 3*Gia_ManObjNum(p) );
    Vec_StrPrintStr( vBuffer, "aig " );
    Vec_StrPrintNum( vBuffer, Gia_ManCandNum(p) );
    Vec_StrPrintStr( vBuffer, " " );
    Vec_StrPrintNum( vBuffer, Gia_ManPiNum(p) );
    Vec_StrPrintStr( vBuffer, " " );
    Vec_StrPrintNum( vBuffer, Gia_ManRegNum(p) );
    Vec_StrPrintStr( vBuffer, " " );
    Vec_StrPrintNum( vBuffer, Gia_ManPoNum(p) );
    Vec_StrPrintStr( vBuffer, " " );
    Vec_StrPrintNum( vBuffer, Gia_ManAndNum(p) );
    Vec_StrPrintStr( vBuffer, "\n" );
Alan Mishchenko committed
953

954 955 956 957 958 959 960
    // write latch drivers
    Gia_ManForEachRi( p, pObj, i )
    {
        uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) );
        Vec_StrPrintNum( vBuffer, uLit );
        Vec_StrPrintStr( vBuffer, "\n" );
    }
Alan Mishchenko committed
961

962 963
    // write PO drivers
    Gia_ManForEachPo( p, pObj, i )
Alan Mishchenko committed
964
    {
965 966 967
        uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) );
        Vec_StrPrintNum( vBuffer, uLit );
        Vec_StrPrintStr( vBuffer, "\n" );
Alan Mishchenko committed
968
    }
969 970
    // write the nodes into the buffer
    Gia_ManForEachAnd( p, pObj, i )
Alan Mishchenko committed
971
    {
972 973 974 975 976
        uLit  = Abc_Var2Lit( Gia_ObjValue(pObj), 0 );
        uLit0 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) );
        uLit1 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj) );
        assert( uLit0 != uLit1 );
        if ( uLit0 > uLit1 )
Alan Mishchenko committed
977
        {
978 979 980
            int Temp = uLit0;
            uLit0 = uLit1;
            uLit1 = Temp;
Alan Mishchenko committed
981
        }
982 983
        Gia_AigerWriteUnsigned( vBuffer, uLit  - uLit1 );
        Gia_AigerWriteUnsigned( vBuffer, uLit1 - uLit0 );
Alan Mishchenko committed
984
    }
985 986
    Vec_StrPrintStr( vBuffer, "c" );
    return vBuffer;
Alan Mishchenko committed
987 988 989 990
}

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

991
  Synopsis    [Writes the AIG in into the memory buffer.]
Alan Mishchenko committed
992

993 994 995
  Description [The resulting buffer constains the AIG in AIGER format.
  The CI/CO/AND nodes are assumed to be ordered according to some rule.
  The resulting buffer should be deallocated by the user.]
Alan Mishchenko committed
996
  
997
  SideEffects [Note that in vCos, PIs are order first, followed by latches!]
Alan Mishchenko committed
998 999 1000 1001

  SeeAlso     []

***********************************************************************/
1002
Vec_Str_t * Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs )
Alan Mishchenko committed
1003
{
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
    Vec_Str_t * vBuffer;
    Gia_Obj_t * pObj;
    int nNodes = 0, i, uLit, uLit0, uLit1; 
    // set the node numbers to be used in the output file
    Gia_ManConst0(p)->Value = nNodes++;
    Gia_ManForEachObjVec( vCis, p, pObj, i )
    {
        assert( Gia_ObjIsCi(pObj) );
        pObj->Value = nNodes++;
    }
    Gia_ManForEachObjVec( vAnds, p, pObj, i )
    {
        assert( Gia_ObjIsAnd(pObj) );
        pObj->Value = nNodes++;
    }
Alan Mishchenko committed
1019

1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
    // write the header "M I L O A" where M = I + L + A
    vBuffer = Vec_StrAlloc( 3*Gia_ManObjNum(p) );
    Vec_StrPrintStr( vBuffer, "aig " );
    Vec_StrPrintNum( vBuffer, Vec_IntSize(vCis) + Vec_IntSize(vAnds) );
    Vec_StrPrintStr( vBuffer, " " );
    Vec_StrPrintNum( vBuffer, Vec_IntSize(vCis) - nRegs );
    Vec_StrPrintStr( vBuffer, " " );
    Vec_StrPrintNum( vBuffer, nRegs );
    Vec_StrPrintStr( vBuffer, " " );
    Vec_StrPrintNum( vBuffer, Vec_IntSize(vCos) - nRegs );
    Vec_StrPrintStr( vBuffer, " " );
    Vec_StrPrintNum( vBuffer, Vec_IntSize(vAnds) );
    Vec_StrPrintStr( vBuffer, "\n" );
Alan Mishchenko committed
1033

1034 1035
    // write latch drivers
    Gia_ManForEachObjVec( vCos, p, pObj, i )
Alan Mishchenko committed
1036
    {
1037 1038
        assert( Gia_ObjIsCo(pObj) );
        if ( i < Vec_IntSize(vCos) - nRegs )
Alan Mishchenko committed
1039
            continue;
1040 1041 1042
        uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) );
        Vec_StrPrintNum( vBuffer, uLit );
        Vec_StrPrintStr( vBuffer, "\n" );
Alan Mishchenko committed
1043
    }
1044 1045
    // write output drivers
    Gia_ManForEachObjVec( vCos, p, pObj, i )
Alan Mishchenko committed
1046
    {
1047 1048 1049 1050 1051 1052
        assert( Gia_ObjIsCo(pObj) );
        if ( i >= Vec_IntSize(vCos) - nRegs )
            continue;
        uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) );
        Vec_StrPrintNum( vBuffer, uLit );
        Vec_StrPrintStr( vBuffer, "\n" );
Alan Mishchenko committed
1053 1054
    }

1055 1056
    // write the nodes into the buffer
    Gia_ManForEachObjVec( vAnds, p, pObj, i )
Alan Mishchenko committed
1057
    {
1058 1059 1060 1061 1062
        uLit  = Abc_Var2Lit( Gia_ObjValue(pObj), 0 );
        uLit0 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) );
        uLit1 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj) );
        assert( uLit0 != uLit1 );
        if ( uLit0 > uLit1 )
Alan Mishchenko committed
1063
        {
1064 1065 1066
            int Temp = uLit0;
            uLit0 = uLit1;
            uLit1 = Temp;
Alan Mishchenko committed
1067
        }
1068 1069
        Gia_AigerWriteUnsigned( vBuffer, uLit  - uLit1 );
        Gia_AigerWriteUnsigned( vBuffer, uLit1 - uLit0 );
Alan Mishchenko committed
1070
    }
1071 1072
    Vec_StrPrintStr( vBuffer, "c" );
    return vBuffer;
Alan Mishchenko committed
1073 1074 1075 1076
}

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

Alan Mishchenko committed
1077 1078 1079 1080 1081 1082 1083 1084 1085
  Synopsis    [Writes the AIG in the binary AIGER format.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
1086
void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine )
Alan Mishchenko committed
1087
{
1088
    int fVerbose = XAIG_VERBOSE;
Alan Mishchenko committed
1089 1090 1091
    FILE * pFile;
    Gia_Man_t * p;
    Gia_Obj_t * pObj;
1092
    Vec_Str_t * vStrExt;
Alan Mishchenko committed
1093 1094 1095
    int i, nBufferSize, Pos;
    unsigned char * pBuffer;
    unsigned uLit0, uLit1, uLit;
1096
    assert( pInit->nXors == 0 && pInit->nMuxes == 0 );
Alan Mishchenko committed
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107

    if ( Gia_ManCoNum(pInit) == 0 )
    {
        printf( "AIG cannot be written because it has no POs.\n" );
        return;
    }

    // start the output stream
    pFile = fopen( pFileName, "wb" );
    if ( pFile == NULL )
    {
1108
        fprintf( stdout, "Gia_AigerWrite(): Cannot open the output file \"%s\".\n", pFileName );
Alan Mishchenko committed
1109 1110 1111 1112 1113
        return;
    }

    // create normalized AIG
    if ( !Gia_ManIsNormalized(pInit) )
Alan Mishchenko committed
1114
    {
1115
//        printf( "Gia_AigerWrite(): Normalizing AIG for writing.\n" );
1116
        p = Gia_ManDupNormalize( pInit, 0 );
1117 1118
        Gia_ManTransferMapping( p, pInit );
        Gia_ManTransferPacking( p, pInit );
1119
        Gia_ManTransferTiming( p, pInit );
1120
        p->nConstrs   = pInit->nConstrs;
Alan Mishchenko committed
1121
    }
Alan Mishchenko committed
1122 1123 1124 1125
    else
        p = pInit;

    // write the header "M I L O A" where M = I + L + A
1126
    fprintf( pFile, "aig%s %u %u %u %u %u", 
Alan Mishchenko committed
1127 1128 1129 1130
        fCompact? "2" : "",
        Gia_ManCiNum(p) + Gia_ManAndNum(p), 
        Gia_ManPiNum(p),
        Gia_ManRegNum(p),
1131
        Gia_ManConstrNum(p) ? 0 : Gia_ManPoNum(p),
Alan Mishchenko committed
1132
        Gia_ManAndNum(p) );
1133 1134 1135 1136
    // write the extended header "B C J F"
    if ( Gia_ManConstrNum(p) )
        fprintf( pFile, " %u %u", Gia_ManPoNum(p) - Gia_ManConstrNum(p), Gia_ManConstrNum(p) );
    fprintf( pFile, "\n" ); 
Alan Mishchenko committed
1137

1138
    Gia_ManInvertConstraints( p );
Alan Mishchenko committed
1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
    if ( !fCompact ) 
    {
        // write latch drivers
        Gia_ManForEachRi( p, pObj, i )
            fprintf( pFile, "%u\n", Gia_ObjFaninLit0p(p, pObj) );
        // write PO drivers
        Gia_ManForEachPo( p, pObj, i )
            fprintf( pFile, "%u\n", Gia_ObjFaninLit0p(p, pObj) );
    }
    else
    {
1150 1151
        Vec_Int_t * vLits = Gia_AigerCollectLiterals( p );
        Vec_Str_t * vBinary = Gia_AigerWriteLiterals( vLits );
Alan Mishchenko committed
1152 1153 1154 1155
        fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile );
        Vec_StrFree( vBinary );
        Vec_IntFree( vLits );
    }
1156
    Gia_ManInvertConstraints( p );
Alan Mishchenko committed
1157 1158 1159

    // write the nodes into the buffer
    Pos = 0;
1160
    nBufferSize = 8 * Gia_ManAndNum(p) + 100; // skeptically assuming 3 chars per one AIG edge
Alan Mishchenko committed
1161 1162 1163
    pBuffer = ABC_ALLOC( unsigned char, nBufferSize );
    Gia_ManForEachAnd( p, pObj, i )
    {
1164
        uLit  = Abc_Var2Lit( i, 0 );
Alan Mishchenko committed
1165 1166
        uLit0 = Gia_ObjFaninLit0( pObj, i );
        uLit1 = Gia_ObjFaninLit1( pObj, i );
1167
        assert( p->fGiaSimple || Gia_ManBufNum(p) || uLit0 < uLit1 );
1168 1169
        Pos = Gia_AigerWriteUnsignedBuffer( pBuffer, Pos, uLit  - uLit1 );
        Pos = Gia_AigerWriteUnsignedBuffer( pBuffer, Pos, uLit1 - uLit0 );
Alan Mishchenko committed
1170 1171
        if ( Pos > nBufferSize - 10 )
        {
1172
            printf( "Gia_AigerWrite(): AIGER generation has failed because the allocated buffer is too small.\n" );
Alan Mishchenko committed
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
            fclose( pFile );
            if ( p != pInit )
                Gia_ManStop( p );
            return;
        }
    }
    assert( Pos < nBufferSize );

    // write the buffer
    fwrite( pBuffer, 1, Pos, pFile );
    ABC_FREE( pBuffer );

1185 1186 1187 1188 1189 1190 1191
    // write the symbol table
    if ( p->vNamesIn && p->vNamesOut )
    {
        assert( Vec_PtrSize(p->vNamesIn)  == Gia_ManCiNum(p) );
        assert( Vec_PtrSize(p->vNamesOut) == Gia_ManCoNum(p) );
        // write PIs
        Gia_ManForEachPi( p, pObj, i )
1192
            fprintf( pFile, "i%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesIn, i) );
1193 1194
        // write latches
        Gia_ManForEachRo( p, pObj, i )
1195
            fprintf( pFile, "l%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesIn, Gia_ManPiNum(p) + i) );
1196 1197
        // write POs
        Gia_ManForEachPo( p, pObj, i )
1198
            fprintf( pFile, "o%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesOut, i) );
1199 1200
    }

Alan Mishchenko committed
1201
    // write the comment
1202 1203 1204 1205
    if ( fWriteNewLine ) 
        fprintf( pFile, "c\n" );
    else
        fprintf( pFile, "c" );
1206 1207 1208 1209 1210 1211 1212 1213 1214

    // write additional AIG
    if ( p->pAigExtra )
    {
        fprintf( pFile, "a" );
        vStrExt = Gia_AigerWriteIntoMemoryStr( p->pAigExtra );
        Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) );
        fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile );
        Vec_StrFree( vStrExt );
1215
        if ( fVerbose ) printf( "Finished writing extension \"a\".\n" );
1216 1217 1218 1219 1220 1221 1222 1223
    }
    // write constraints
    if ( p->nConstrs )
    {
        fprintf( pFile, "c" );
        Gia_FileWriteBufferSize( pFile, 4 );
        Gia_FileWriteBufferSize( pFile, p->nConstrs );
    }
1224 1225 1226 1227 1228 1229 1230
    // write timing information
    if ( p->nAnd2Delay )
    {
        fprintf( pFile, "d" );
        Gia_FileWriteBufferSize( pFile, 4 );
        Gia_FileWriteBufferSize( pFile, p->nAnd2Delay );
    }
1231
    if ( p->pManTime )
1232
    {
1233
        float * pTimes;
Alan Mishchenko committed
1234
        pTimes = Tim_ManGetArrTimes( (Tim_Man_t *)p->pManTime );
1235
        if ( pTimes )
1236 1237
        {
            fprintf( pFile, "i" );
1238
            Gia_FileWriteBufferSize( pFile, 4*Tim_ManPiNum((Tim_Man_t *)p->pManTime) );
1239 1240 1241 1242
            fwrite( pTimes, 1, 4*Tim_ManPiNum((Tim_Man_t *)p->pManTime), pFile );
            ABC_FREE( pTimes );
            if ( fVerbose ) printf( "Finished writing extension \"i\".\n" );
        }
Alan Mishchenko committed
1243
        pTimes = Tim_ManGetReqTimes( (Tim_Man_t *)p->pManTime );
1244 1245
        if ( pTimes )
        {
1246
            fprintf( pFile, "o" );
1247
            Gia_FileWriteBufferSize( pFile, 4*Tim_ManPoNum((Tim_Man_t *)p->pManTime) );
1248 1249
            fwrite( pTimes, 1, 4*Tim_ManPoNum((Tim_Man_t *)p->pManTime), pFile );
            ABC_FREE( pTimes );
1250
            if ( fVerbose ) printf( "Finished writing extension \"o\".\n" );
1251
        }
1252
    }
Alan Mishchenko committed
1253 1254 1255
    // write equivalences
    if ( p->pReprs && p->pNexts )
    {
1256
        extern Vec_Str_t * Gia_WriteEquivClasses( Gia_Man_t * p );
Alan Mishchenko committed
1257
        fprintf( pFile, "e" );
1258
        vStrExt = Gia_WriteEquivClasses( p );
1259
        Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) );
1260 1261
        fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile );
        Vec_StrFree( vStrExt );
Alan Mishchenko committed
1262
    }
Alan Mishchenko committed
1263 1264 1265 1266
    // write flop classes
    if ( p->vFlopClasses )
    {
        fprintf( pFile, "f" );
1267 1268 1269
        Gia_FileWriteBufferSize( pFile, 4*Gia_ManRegNum(p) );
        assert( Vec_IntSize(p->vFlopClasses) == Gia_ManRegNum(p) );
        fwrite( Vec_IntArray(p->vFlopClasses), 1, 4*Gia_ManRegNum(p), pFile );
Alan Mishchenko committed
1270
    }
1271 1272 1273 1274
    // write gate classes
    if ( p->vGateClasses )
    {
        fprintf( pFile, "g" );
1275 1276 1277
        Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) );
        assert( Vec_IntSize(p->vGateClasses) == Gia_ManObjNum(p) );
        fwrite( Vec_IntArray(p->vGateClasses), 1, 4*Gia_ManObjNum(p), pFile );
1278
    }
1279 1280
    // write hierarchy info
    if ( p->pManTime )
1281
    {
1282 1283 1284 1285 1286
        fprintf( pFile, "h" );
        vStrExt = Tim_ManSave( (Tim_Man_t *)p->pManTime, 1 );
        Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) );
        fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile );
        Vec_StrFree( vStrExt );
1287
        if ( fVerbose ) printf( "Finished writing extension \"h\".\n" );
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297
    }
    // write packing
    if ( p->vPacking )
    {
        extern Vec_Str_t * Gia_WritePacking( Vec_Int_t * vPacking );
        fprintf( pFile, "k" );
        vStrExt = Gia_WritePacking( p->vPacking );
        Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) );
        fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile );
        Vec_StrFree( vStrExt );
1298
        if ( fVerbose ) printf( "Finished writing extension \"k\".\n" );
1299
    }
1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
    // write edges
    if ( p->vEdge1 )
    {
        Vec_Int_t * vPairs = Gia_ManEdgeToArray( p );
        int i;
        fprintf( pFile, "w" );
        Gia_FileWriteBufferSize( pFile, 4*(Vec_IntSize(vPairs)+1) );
        Gia_FileWriteBufferSize( pFile, Vec_IntSize(vPairs)/2 );
        for ( i = 0; i < Vec_IntSize(vPairs); i++ )
            Gia_FileWriteBufferSize( pFile, Vec_IntEntry(vPairs, i) );
        Vec_IntFree( vPairs );
    }
Alan Mishchenko committed
1312
    // write mapping
1313
    if ( Gia_ManHasMapping(p) )
Alan Mishchenko committed
1314
    {
1315
        extern Vec_Str_t * Gia_AigerWriteMapping( Gia_Man_t * p );
1316
        extern Vec_Str_t * Gia_AigerWriteMappingSimple( Gia_Man_t * p );
1317
        extern Vec_Str_t * Gia_AigerWriteMappingDoc( Gia_Man_t * p );
Alan Mishchenko committed
1318
        fprintf( pFile, "m" );
1319
        vStrExt = Gia_AigerWriteMappingDoc( p );
1320 1321 1322
        Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) );
        fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile );
        Vec_StrFree( vStrExt );
1323
        if ( fVerbose ) printf( "Finished writing extension \"m\".\n" );
1324
    }
Alan Mishchenko committed
1325
    // write placement
Alan Mishchenko committed
1326 1327 1328
    if ( p->pPlacement )
    {
        fprintf( pFile, "p" );
1329 1330
        Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) );
        fwrite( p->pPlacement, 1, 4*Gia_ManObjNum(p), pFile );
Alan Mishchenko committed
1331
    }
1332 1333 1334
    // write register classes
    if ( p->vRegClasses )
    {
1335
        int i;
1336
        fprintf( pFile, "r" );
1337 1338
        Gia_FileWriteBufferSize( pFile, 4*(Vec_IntSize(p->vRegClasses)+1) );
        Gia_FileWriteBufferSize( pFile, Vec_IntSize(p->vRegClasses) );
1339 1340
        for ( i = 0; i < Vec_IntSize(p->vRegClasses); i++ )
            Gia_FileWriteBufferSize( pFile, Vec_IntEntry(p->vRegClasses, i) );
1341
    }
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351
    // write register inits
    if ( p->vRegInits )
    {
        int i;
        fprintf( pFile, "s" );
        Gia_FileWriteBufferSize( pFile, 4*(Vec_IntSize(p->vRegInits)+1) );
        Gia_FileWriteBufferSize( pFile, Vec_IntSize(p->vRegInits) );
        for ( i = 0; i < Vec_IntSize(p->vRegInits); i++ )
            Gia_FileWriteBufferSize( pFile, Vec_IntEntry(p->vRegInits, i) );
    }
1352 1353 1354 1355 1356 1357 1358
    // write configuration data
    if ( p->vConfigs )
    {
        fprintf( pFile, "b" );
        assert( p->pCellStr != NULL );
        Gia_FileWriteBufferSize( pFile, 4*Vec_IntSize(p->vConfigs) + strlen(p->pCellStr) + 1 );
        fwrite( p->pCellStr, 1, strlen(p->pCellStr) + 1, pFile );
1359 1360 1361
//        fwrite( Vec_IntArray(p->vConfigs), 1, 4*Vec_IntSize(p->vConfigs), pFile );
        for ( i = 0; i < Vec_IntSize(p->vConfigs); i++ )
            Gia_FileWriteBufferSize( pFile, Vec_IntEntry(p->vConfigs, i) );
1362
    }
1363
    // write choices
1364
    if ( Gia_ManHasChoices(p) )
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380
    {
        int i, nPairs = 0;
        fprintf( pFile, "q" );
        for ( i = 0; i < Gia_ManObjNum(p); i++ )
            nPairs += (Gia_ObjSibl(p, i) > 0);
        Gia_FileWriteBufferSize( pFile, 4*(nPairs * 2 + 1) );
        Gia_FileWriteBufferSize( pFile, nPairs );
        for ( i = 0; i < Gia_ManObjNum(p); i++ )
            if ( Gia_ObjSibl(p, i) )
            {
                assert( i > Gia_ObjSibl(p, i) );
                Gia_FileWriteBufferSize( pFile, i );
                Gia_FileWriteBufferSize( pFile, Gia_ObjSibl(p, i) );
            }
        if ( fVerbose ) printf( "Finished writing extension \"q\".\n" );
    }
1381
    // write switching activity
Alan Mishchenko committed
1382 1383
    if ( p->pSwitching )
    {
1384
        fprintf( pFile, "u" );
1385 1386
        Gia_FileWriteBufferSize( pFile, Gia_ManObjNum(p) );
        fwrite( p->pSwitching, 1, Gia_ManObjNum(p), pFile );
Alan Mishchenko committed
1387
    }
1388
/*
1389 1390 1391 1392
    // write timing information
    if ( p->pManTime )
    {
        fprintf( pFile, "t" );
1393 1394 1395 1396
        vStrExt = Tim_ManSave( (Tim_Man_t *)p->pManTime, 0 );
        Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) );
        fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile );
        Vec_StrFree( vStrExt );
1397
    }
1398
*/
1399 1400
    // write object classes
    if ( p->vObjClasses )
1401
    {
1402 1403 1404 1405
        fprintf( pFile, "v" );
        Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) );
        assert( Vec_IntSize(p->vObjClasses) == Gia_ManObjNum(p) );
        fwrite( Vec_IntArray(p->vObjClasses), 1, 4*Gia_ManObjNum(p), pFile );
1406
    }
1407 1408 1409 1410 1411 1412 1413 1414
    // write name
    if ( p->pName )
    {
        fprintf( pFile, "n" );
        Gia_FileWriteBufferSize( pFile, strlen(p->pName)+1 );
        fwrite( p->pName, 1, strlen(p->pName), pFile );
        fprintf( pFile, "%c", '\0' );
    }
1415
    // write comments
1416 1417
    if ( fWriteNewLine )
        fprintf( pFile, "c\n" );
Alan Mishchenko committed
1418
    fprintf( pFile, "\nThis file was produced by the GIA package in ABC on %s\n", Gia_TimeStamp() );
Alan Mishchenko committed
1419 1420 1421
    fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" );
    fclose( pFile );
    if ( p != pInit )
Alan Mishchenko committed
1422
    {
1423
        Gia_ManTransferTiming( pInit, p );
Alan Mishchenko committed
1424
        Gia_ManStop( p );
Alan Mishchenko committed
1425
    }
Alan Mishchenko committed
1426 1427
}

Alan Mishchenko committed
1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442
/**Function*************************************************************

  Synopsis    [Writes the AIG in the binary AIGER format.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Gia_DumpAiger( Gia_Man_t * p, char * pFilePrefix, int iFileNum, int nFileNumDigits )
{
    char Buffer[100];
    sprintf( Buffer, "%s%0*d.aig", pFilePrefix, nFileNumDigits, iFileNum );
1443
    Gia_AigerWrite( p, Buffer, 0, 0, 0 );
1444 1445
}

1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456
/**Function*************************************************************

  Synopsis    [Writes the AIG in the binary AIGER format.]

  Description []
  
  SideEffects []

  SeeAlso     []

***********************************************************************/
1457
void Gia_AigerWriteSimple( Gia_Man_t * pInit, char * pFileName )
1458 1459 1460 1461 1462
{
    FILE * pFile;
    Vec_Str_t * vStr;
    if ( Gia_ManPoNum(pInit) == 0 )
    {
1463
        printf( "Gia_AigerWriteSimple(): AIG cannot be written because it has no POs.\n" );
1464 1465 1466 1467 1468 1469
        return;
    }
    // start the output stream
    pFile = fopen( pFileName, "wb" );
    if ( pFile == NULL )
    {
1470
        fprintf( stdout, "Gia_AigerWriteSimple(): Cannot open the output file \"%s\".\n", pFileName );
1471 1472 1473
        return;
    }
    // write the buffer
1474
    vStr = Gia_AigerWriteIntoMemoryStr( pInit );
1475 1476 1477 1478 1479
    fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile );
    Vec_StrFree( vStr );
    fclose( pFile );
}

Alan Mishchenko committed
1480 1481 1482 1483 1484
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


1485 1486
ABC_NAMESPACE_IMPL_END