/**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" #include "misc/tim/tim.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START #define XAIG_VERBOSE 0 //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_FileFixName( char * pFileName ) { char * pName; for ( pName = pFileName; *pName; pName++ ) if ( *pName == '>' ) *pName = '\\'; } char * Gia_FileNameGeneric( char * FileName ) { char * pDot, * pRes; pRes = Abc_UtilStrsav( FileName ); if ( (pDot = strrchr( pRes, '.' )) ) *pDot = 0; return pRes; } 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; } void Gia_FileWriteBufferSize( FILE * pFile, int nSize ) { unsigned char Buffer[5]; Gia_AigerWriteInt( Buffer, nSize ); fwrite( Buffer, 1, 4, pFile ); } /**Function************************************************************* Synopsis [Create the array of literals to be written.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_AigerCollectLiterals( Gia_Man_t * p ) { 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; } Vec_Int_t * Gia_AigerReadLiterals( unsigned char ** ppPos, int nEntries ) { 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++ ) { // 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; } return vLits; } Vec_Str_t * Gia_AigerWriteLiterals( Vec_Int_t * vLits ) { 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 ) { 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 ); } 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; } /**Function************************************************************* Synopsis [Reads the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fSkipStrash, int fCheck ) { Gia_Man_t * pNew, * pTemp; Vec_Int_t * vLits = NULL, * vPoTypes = NULL; Vec_Int_t * vNodes, * vDrivers, * vInits = NULL; int iObj, iNode0, iNode1, fHieOnly = 0; int nTotal, nInputs, nOutputs, nLatches, nAnds, i; int nBad = 0, nConstr = 0, nJust = 0, nFair = 0; unsigned char * pDrivers, * pSymbols, * pCur; unsigned uLit0, uLit1, uLit; // read the parameters (M I L O A + B C J F) pCur = (unsigned char *)pContents; while ( *pCur != ' ' ) pCur++; pCur++; // read the number of objects nTotal = atoi( (const char *)pCur ); while ( *pCur != ' ' ) pCur++; pCur++; // read the number of inputs nInputs = atoi( (const char *)pCur ); while ( *pCur != ' ' ) pCur++; pCur++; // read the number of latches nLatches = atoi( (const char *)pCur ); while ( *pCur != ' ' ) pCur++; pCur++; // read the number of outputs nOutputs = atoi( (const char *)pCur ); while ( *pCur != ' ' ) pCur++; pCur++; // read the number of nodes nAnds = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; if ( *pCur == ' ' ) { // assert( nOutputs == 0 ); // read the number of properties pCur++; nBad = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; nOutputs += nBad; } if ( *pCur == ' ' ) { // read the number of properties pCur++; nConstr = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; nOutputs += nConstr; } if ( *pCur == ' ' ) { // read the number of properties pCur++; nJust = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; nOutputs += nJust; } if ( *pCur == ' ' ) { // read the number of properties pCur++; nFair = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; nOutputs += nFair; } if ( *pCur != '\n' ) { fprintf( stdout, "The parameter line is in a wrong format.\n" ); return NULL; } pCur++; // check the parameters if ( nTotal != nInputs + nLatches + nAnds ) { fprintf( stdout, "The number of objects does not match.\n" ); return NULL; } if ( nJust || nFair ) { fprintf( stdout, "Reading AIGER files with liveness properties is currently not supported.\n" ); 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 ); } // allocate the empty AIG pNew = Gia_ManStart( nTotal + nLatches + nOutputs + 1 ); pNew->nConstrs = nConstr; // 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 { vLits = Gia_AigerReadLiterals( &pCur, nLatches + nOutputs ); } // create the AND gates if ( !fSkipStrash ) Gia_ManHashAlloc( pNew ); for ( i = 0; i < nAnds; i++ ) { uLit = ((i + 1 + nInputs + nLatches) << 1); uLit1 = uLit - Gia_AigerReadUnsigned( &pCur ); uLit0 = uLit1 - Gia_AigerReadUnsigned( &pCur ); // assert( uLit1 > uLit0 ); iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); iNode1 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); assert( Vec_IntSize(vNodes) == i + 1 + nInputs + nLatches ); if ( fSkipStrash ) { if ( iNode0 == iNode1 ) Vec_IntPush( vNodes, Gia_ManAppendBuf(pNew, iNode0) ); else Vec_IntPush( vNodes, Gia_ManAppendAnd(pNew, iNode0, iNode1) ); } else Vec_IntPush( vNodes, Gia_ManHashAnd(pNew, iNode0, iNode1) ); } if ( !fSkipStrash ) Gia_ManHashStop( pNew ); // remember the place where symbols begin pSymbols = pCur; // read the latch driver literals vDrivers = Vec_IntAlloc( nLatches + nOutputs ); if ( pContents[3] == ' ' ) // standard AIGER { vInits = Vec_IntAlloc( nLatches ); pCur = pDrivers; for ( i = 0; i < nLatches; i++ ) { 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 ); } iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } // read the PO driver literals for ( i = 0; i < nOutputs; i++ ) { uLit0 = atoi( (char *)pCur ); while ( *pCur++ != '\n' ); iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } } else { // read the latch driver literals for ( i = 0; i < nLatches; i++ ) { uLit0 = Vec_IntEntry( vLits, i ); iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } // read the PO driver literals for ( i = 0; i < nOutputs; i++ ) { uLit0 = Vec_IntEntry( vLits, i+nLatches ); iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); 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 ); // read signal names if they are of the special type pCur = pSymbols; if ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' ) { 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' ) { int iTerm; char * pType = (char *)pCur; // check terminal type if ( *pCur != 'i' && *pCur != 'o' && *pCur != 'l' ) { // fprintf( stdout, "Wrong terminal type.\n" ); fBreakUsed = 1; break; } // get terminal number iTerm = atoi( (char *)++pCur ); while ( *pCur++ != ' ' ); // skip spaces while ( *pCur == ' ' ) pCur++; // decode the user numbers: // flops are named: @l // PIs are named: @i // POs are named: @o if ( *pCur++ != '@' ) { fBreakUsed = 1; break; } if ( *pCur == 'i' && *pType == 'i' ) Vec_IntWriteEntry( pNew->vUserPiIds, iTerm, atoi((char *)pCur+1) ); else if ( *pCur == 'o' && *pType == 'o' ) Vec_IntWriteEntry( pNew->vUserPoIds, iTerm, atoi((char *)pCur+1) ); else if ( *pCur == 'l' && *pType == 'l' ) Vec_IntWriteEntry( pNew->vUserFfIds, iTerm, atoi((char *)pCur+1) ); 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 ) { unsigned char * pName; int Entry, nInvars, nConstr, iTerm; Vec_Int_t * vPoNames = Vec_IntStartFull( nOutputs ); Vec_IntFreeP( &pNew->vUserPiIds ); Vec_IntFreeP( &pNew->vUserPoIds ); Vec_IntFreeP( &pNew->vUserFfIds ); // try to figure out signal names fBreakUsed = 0; pCur = (unsigned char *)pCurOld; while ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' ) { // get the terminal type if ( *pCur == 'i' || *pCur == 'l' ) { // skip till the end of the line while ( *pCur++ != '\n' ); *(pCur-1) = 0; continue; } if ( *pCur != 'o' ) { // fprintf( stdout, "Wrong terminal type.\n" ); fBreakUsed = 1; break; } // get the terminal number iTerm = atoi( (char *)++pCur ); while ( *pCur++ != ' ' ); // 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 Vec_IntWriteEntry( vPoNames, iTerm, pName - (unsigned char *)pContents ); } // check that all names are assigned if ( !fBreakUsed ) { nInvars = nConstr = 0; vPoTypes = Vec_IntStart( Gia_ManPoNum(pNew) ); Vec_IntForEachEntry( vPoNames, Entry, i ) { if ( Entry == ~0 ) continue; if ( strncmp( pContents+Entry, "constraint:", 11 ) == 0 ) { Vec_IntWriteEntry( vPoTypes, i, 1 ); nConstr++; } if ( strncmp( pContents+Entry, "invariant:", 10 ) == 0 ) { Vec_IntWriteEntry( vPoTypes, i, 2 ); nInvars++; } } if ( nConstr ) fprintf( stdout, "Recognized and added %d constraints.\n", nConstr ); if ( nInvars ) fprintf( stdout, "Recognized and skipped %d invariants.\n", nInvars ); if ( nConstr == 0 && nInvars == 0 ) Vec_IntFreeP( &vPoTypes ); } Vec_IntFree( vPoNames ); } } // check if there are other types of information to read if ( pCur + 1 < (unsigned char *)pContents + nFileSize && *pCur == 'c' ) { int fVerbose = XAIG_VERBOSE; Vec_Str_t * vStr; unsigned char * pCurTemp; pCur++; // skip new line if present // if ( *pCur == '\n' ) // pCur++; while ( pCur < (unsigned char *)pContents + nFileSize ) { // read extra AIG if ( *pCur == 'a' ) { pCur++; vStr = Vec_StrStart( Gia_AigerReadInt(pCur) ); pCur += 4; memcpy( Vec_StrArray(vStr), pCur, Vec_StrSize(vStr) ); pCur += Vec_StrSize(vStr); pNew->pAigExtra = Gia_AigerReadFromMemory( Vec_StrArray(vStr), Vec_StrSize(vStr), 0, 0 ); Vec_StrFree( vStr ); if ( fVerbose ) printf( "Finished reading extension \"a\".\n" ); } // read number of constraints else if ( *pCur == 'c' ) { pCur++; assert( Gia_AigerReadInt(pCur) == 4 ); pCur += 4; pNew->nConstrs = Gia_AigerReadInt( pCur ); pCur += 4; if ( fVerbose ) printf( "Finished reading extension \"c\".\n" ); } // read delay information 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" ); } else if ( *pCur == 'i' ) { pCur++; nInputs = Gia_AigerReadInt(pCur)/4; pCur += 4; pNew->vInArrs = Vec_FltStart( nInputs ); memcpy( Vec_FltArray(pNew->vInArrs), pCur, 4*nInputs ); pCur += 4*nInputs; if ( fVerbose ) printf( "Finished reading extension \"i\".\n" ); } else if ( *pCur == 'o' ) { pCur++; nOutputs = Gia_AigerReadInt(pCur)/4; pCur += 4; pNew->vOutReqs = Vec_FltStart( nOutputs ); memcpy( Vec_FltArray(pNew->vOutReqs), pCur, 4*nOutputs ); pCur += 4*nOutputs; if ( fVerbose ) printf( "Finished reading extension \"o\".\n" ); } // read equivalence classes else if ( *pCur == 'e' ) { extern Gia_Rpr_t * Gia_AigerReadEquivClasses( unsigned char ** ppPos, int nSize ); pCur++; pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; pNew->pReprs = Gia_AigerReadEquivClasses( &pCur, Gia_ManObjNum(pNew) ); pNew->pNexts = Gia_ManDeriveNexts( pNew ); assert( pCur == pCurTemp ); if ( fVerbose ) printf( "Finished reading extension \"e\".\n" ); } // read flop classes else if ( *pCur == 'f' ) { pCur++; assert( Gia_AigerReadInt(pCur) == 4*Gia_ManRegNum(pNew) ); pCur += 4; pNew->vFlopClasses = Vec_IntStart( Gia_ManRegNum(pNew) ); memcpy( Vec_IntArray(pNew->vFlopClasses), pCur, 4*Gia_ManRegNum(pNew) ); pCur += 4*Gia_ManRegNum(pNew); if ( fVerbose ) printf( "Finished reading extension \"f\".\n" ); } // read gate classes else if ( *pCur == 'g' ) { pCur++; assert( Gia_AigerReadInt(pCur) == 4*Gia_ManObjNum(pNew) ); pCur += 4; pNew->vGateClasses = Vec_IntStart( Gia_ManObjNum(pNew) ); memcpy( Vec_IntArray(pNew->vGateClasses), pCur, 4*Gia_ManObjNum(pNew) ); pCur += 4*Gia_ManObjNum(pNew); if ( fVerbose ) printf( "Finished reading extension \"g\".\n" ); } // read hierarchy information else if ( *pCur == 'h' ) { pCur++; vStr = Vec_StrStart( Gia_AigerReadInt(pCur) ); pCur += 4; memcpy( Vec_StrArray(vStr), pCur, Vec_StrSize(vStr) ); pCur += Vec_StrSize(vStr); pNew->pManTime = Tim_ManLoad( vStr, 1 ); Vec_StrFree( vStr ); fHieOnly = 1; if ( fVerbose ) printf( "Finished reading extension \"h\".\n" ); } // read packing else if ( *pCur == 'k' ) { extern Vec_Int_t * Gia_AigerReadPacking( unsigned char ** ppPos, int nSize ); int nSize; pCur++; nSize = Gia_AigerReadInt(pCur); pCurTemp = pCur + nSize + 4; pCur += 4; pNew->vPacking = Gia_AigerReadPacking( &pCur, nSize ); assert( pCur == pCurTemp ); if ( fVerbose ) printf( "Finished reading extension \"k\".\n" ); } // read mapping else if ( *pCur == 'm' ) { extern int * Gia_AigerReadMapping( unsigned char ** ppPos, int nSize ); extern int * Gia_AigerReadMappingSimple( unsigned char ** ppPos, int nSize ); extern Vec_Int_t * Gia_AigerReadMappingDoc( unsigned char ** ppPos, int nObjs ); int nSize; pCur++; nSize = Gia_AigerReadInt(pCur); pCurTemp = pCur + nSize + 4; pCur += 4; pNew->vMapping = Gia_AigerReadMappingDoc( &pCur, Gia_ManObjNum(pNew) ); assert( pCur == pCurTemp ); if ( fVerbose ) printf( "Finished reading extension \"m\".\n" ); } // 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 { pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; ABC_FREE( pNew->pName ); pNew->pName = Abc_UtilStrsav( (char *)pCur ); pCur += strlen(pNew->pName) + 1; assert( pCur == pCurTemp ); } } // read placement else if ( *pCur == 'p' ) { Gia_Plc_t * pPlacement; pCur++; pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; pPlacement = ABC_ALLOC( Gia_Plc_t, Gia_ManObjNum(pNew) ); memcpy( pPlacement, pCur, 4*Gia_ManObjNum(pNew) ); pCur += 4*Gia_ManObjNum(pNew); assert( pCur == pCurTemp ); pNew->pPlacement = pPlacement; if ( fVerbose ) printf( "Finished reading extension \"p\".\n" ); } // read register classes else if ( *pCur == 'r' ) { int i, nRegs; pCur++; nRegs = Gia_AigerReadInt(pCur)/4; pCur += 4; pNew->vRegClasses = Vec_IntAlloc( nRegs ); for ( i = 0; i < nRegs; i++ ) Vec_IntPush( pNew->vRegClasses, Gia_AigerReadInt(pCur) ), pCur += 4; if ( fVerbose ) printf( "Finished reading extension \"r\".\n" ); } // read choices else if ( *pCur == 'q' ) { int i, nPairs, iRepr, iNode; assert( !Gia_ManHasChoices(pNew) ); 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" ); } // read switching activity else if ( *pCur == 'u' ) { unsigned char * pSwitching; pCur++; pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; pSwitching = ABC_ALLOC( unsigned char, Gia_ManObjNum(pNew) ); memcpy( pSwitching, pCur, Gia_ManObjNum(pNew) ); pCur += Gia_ManObjNum(pNew); assert( pCur == pCurTemp ); if ( fVerbose ) printf( "Finished reading extension \"s\".\n" ); } // read timing manager else if ( *pCur == 't' ) { pCur++; vStr = Vec_StrStart( Gia_AigerReadInt(pCur) ); pCur += 4; memcpy( Vec_StrArray(vStr), pCur, Vec_StrSize(vStr) ); pCur += Vec_StrSize(vStr); pNew->pManTime = Tim_ManLoad( vStr, 0 ); Vec_StrFree( vStr ); if ( fVerbose ) printf( "Finished reading extension \"t\".\n" ); } // read object classes else if ( *pCur == 'v' ) { pCur++; pNew->vObjClasses = Vec_IntStart( Gia_AigerReadInt(pCur)/4 ); pCur += 4; memcpy( Vec_IntArray(pNew->vObjClasses), pCur, 4*Vec_IntSize(pNew->vObjClasses) ); pCur += 4*Vec_IntSize(pNew->vObjClasses); if ( fVerbose ) printf( "Finished reading extension \"v\".\n" ); } else break; } } // skipping the comments Vec_IntFree( vNodes ); // update polarity of the additional outputs if ( nBad || nConstr || nJust || nFair ) Gia_ManInvertConstraints( pNew ); // clean the PO drivers if ( vPoTypes ) { pNew = Gia_ManDupWithConstraints( pTemp = pNew, vPoTypes ); Gia_ManStop( pTemp ); Vec_IntFreeP( &vPoTypes ); } if ( !fSkipStrash && Gia_ManHasDangling(pNew) ) { Tim_Man_t * pManTime; Vec_Int_t * vFlopMap, * vGateMap, * vObjMap; 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; pNew = Gia_ManCleanup( pTemp = pNew ); if ( (vGateMap || vObjMap) && (Gia_ManObjNum(pNew) < Gia_ManObjNum(pTemp)) ) printf( "Cleanup removed objects after reading. Old gate/object abstraction maps are invalid!\n" ); Gia_ManStop( pTemp ); pNew->vFlopClasses = vFlopMap; pNew->vGateClasses = vGateMap; pNew->vObjClasses = vObjMap; pNew->pManTime = pManTime; } if ( fHieOnly ) { // Tim_ManPrint( (Tim_Man_t *)pNew->pManTime ); if ( Abc_FrameReadLibBox() == NULL ) 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 ); } Vec_FltFreeP( &pNew->vInArrs ); Vec_FltFreeP( &pNew->vOutReqs ); /* // check the result if ( fCheck && !Gia_ManCheck( pNew ) ) { printf( "Gia_AigerRead: The network check has failed.\n" ); Gia_ManStop( pNew ); return NULL; } */ 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) ); // unitialized value of the latch is the latch literal according to http://fmv.jku.at/hwmcc11/beyond1.pdf pInit[i] = 'X'; } } pInit[i] = 0; pNew = Gia_ManDupZeroUndc( pTemp = pNew, pInit, 1 ); pNew->nConstrs = pTemp->nConstrs; pTemp->nConstrs = 0; Gia_ManStop( pTemp ); ABC_FREE( pInit ); } Vec_IntFreeP( &vInits ); if ( !fSkipStrash && pNew->vMapping ) { Abc_Print( 0, "Structural hashing enabled while reading AIGER invalidated the mapping. Consider using \"&r -s\".\n" ); Vec_IntFreeP( &pNew->vMapping ); } return pNew; } /**Function************************************************************* Synopsis [Reads the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_AigerRead( char * pFileName, int fSkipStrash, int fCheck ) { FILE * pFile; Gia_Man_t * pNew; char * pName, * pContents; int nFileSize; int RetValue; // read the file into the buffer Gia_FileFixName( pFileName ); nFileSize = Gia_FileSize( pFileName ); pFile = fopen( pFileName, "rb" ); pContents = ABC_ALLOC( char, nFileSize ); RetValue = fread( pContents, nFileSize, 1, pFile ); fclose( pFile ); pNew = Gia_AigerReadFromMemory( pContents, nFileSize, fSkipStrash, fCheck ); ABC_FREE( pContents ); if ( pNew ) { ABC_FREE( pNew->pName ); pName = Gia_FileNameGeneric( pFileName ); pNew->pName = Abc_UtilStrsav( pName ); ABC_FREE( pName ); assert( pNew->pSpec == NULL ); pNew->pSpec = Abc_UtilStrsav( pFileName ); } return pNew; } /**Function************************************************************* Synopsis [Writes the AIG in into the memory buffer.] Description [The resulting buffer constains the AIG in AIGER format. The resulting buffer should be deallocated by the user.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Gia_AigerWriteIntoMemoryStr( Gia_Man_t * p ) { 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_ManForEachCi( p, pObj, i ) pObj->Value = nNodes++; Gia_ManForEachAnd( p, pObj, i ) pObj->Value = nNodes++; // 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" ); // 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" ); } // write PO drivers Gia_ManForEachPo( p, pObj, i ) { uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); Vec_StrPrintNum( vBuffer, uLit ); Vec_StrPrintStr( vBuffer, "\n" ); } // write the nodes into the buffer Gia_ManForEachAnd( p, pObj, i ) { 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 ) { int Temp = uLit0; uLit0 = uLit1; uLit1 = Temp; } Gia_AigerWriteUnsigned( vBuffer, uLit - uLit1 ); Gia_AigerWriteUnsigned( vBuffer, uLit1 - uLit0 ); } Vec_StrPrintStr( vBuffer, "c" ); return vBuffer; } /**Function************************************************************* Synopsis [Writes the AIG in into the memory buffer.] 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.] SideEffects [Note that in vCos, PIs are order first, followed by latches!] SeeAlso [] ***********************************************************************/ Vec_Str_t * Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs ) { 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++; } // 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" ); // write latch drivers Gia_ManForEachObjVec( vCos, p, pObj, i ) { 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" ); } // write output drivers Gia_ManForEachObjVec( vCos, p, pObj, i ) { 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" ); } // write the nodes into the buffer Gia_ManForEachObjVec( vAnds, p, pObj, i ) { 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 ) { int Temp = uLit0; uLit0 = uLit1; uLit1 = Temp; } Gia_AigerWriteUnsigned( vBuffer, uLit - uLit1 ); Gia_AigerWriteUnsigned( vBuffer, uLit1 - uLit0 ); } Vec_StrPrintStr( vBuffer, "c" ); return vBuffer; } /**Function************************************************************* Synopsis [Writes the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact ) { int fVerbose = XAIG_VERBOSE; FILE * pFile; Gia_Man_t * p; Gia_Obj_t * pObj; Vec_Str_t * vStrExt; int i, nBufferSize, Pos; unsigned char * pBuffer; unsigned uLit0, uLit1, uLit; assert( pInit->nXors == 0 && pInit->nMuxes == 0 ); 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 ) { fprintf( stdout, "Gia_AigerWrite(): Cannot open the output file \"%s\".\n", pFileName ); return; } // create normalized AIG if ( !Gia_ManIsNormalized(pInit) ) { // printf( "Gia_AigerWrite(): Normalizing AIG for writing.\n" ); p = Gia_ManDupNormalize( pInit ); Gia_ManTransferMapping( p, pInit ); Gia_ManTransferPacking( p, pInit ); Gia_ManTransferTiming( p, pInit ); p->vNamesIn = pInit->vNamesIn; pInit->vNamesIn = NULL; p->vNamesOut = pInit->vNamesOut; pInit->vNamesOut = NULL; p->nConstrs = pInit->nConstrs; pInit->nConstrs = 0; } else p = pInit; // write the header "M I L O A" where M = I + L + A fprintf( pFile, "aig%s %u %u %u %u %u", fCompact? "2" : "", Gia_ManCiNum(p) + Gia_ManAndNum(p), Gia_ManPiNum(p), Gia_ManRegNum(p), Gia_ManConstrNum(p) ? 0 : Gia_ManPoNum(p), Gia_ManAndNum(p) ); // 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" ); Gia_ManInvertConstraints( p ); 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 { Vec_Int_t * vLits = Gia_AigerCollectLiterals( p ); Vec_Str_t * vBinary = Gia_AigerWriteLiterals( vLits ); fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile ); Vec_StrFree( vBinary ); Vec_IntFree( vLits ); } Gia_ManInvertConstraints( p ); // write the nodes into the buffer Pos = 0; nBufferSize = 8 * Gia_ManAndNum(p) + 100; // skeptically assuming 3 chars per one AIG edge pBuffer = ABC_ALLOC( unsigned char, nBufferSize ); Gia_ManForEachAnd( p, pObj, i ) { uLit = Abc_Var2Lit( i, 0 ); uLit0 = Gia_ObjFaninLit0( pObj, i ); uLit1 = Gia_ObjFaninLit1( pObj, i ); assert( Gia_ManBufNum(p) || uLit0 < uLit1 ); Pos = Gia_AigerWriteUnsignedBuffer( pBuffer, Pos, uLit - uLit1 ); Pos = Gia_AigerWriteUnsignedBuffer( pBuffer, Pos, uLit1 - uLit0 ); if ( Pos > nBufferSize - 10 ) { printf( "Gia_AigerWrite(): AIGER generation has failed because the allocated buffer is too small.\n" ); fclose( pFile ); if ( p != pInit ) Gia_ManStop( p ); return; } } assert( Pos < nBufferSize ); // write the buffer fwrite( pBuffer, 1, Pos, pFile ); ABC_FREE( pBuffer ); // 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 ) fprintf( pFile, "i%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesIn, i) ); // write latches Gia_ManForEachRo( p, pObj, i ) fprintf( pFile, "l%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesIn, Gia_ManPiNum(p) + i) ); // write POs Gia_ManForEachPo( p, pObj, i ) fprintf( pFile, "o%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesOut, i) ); } // write the comment // fprintf( pFile, "c\n" ); fprintf( pFile, "c" ); // 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 ); if ( fVerbose ) printf( "Finished writing extension \"a\".\n" ); } // write constraints if ( p->nConstrs ) { fprintf( pFile, "c" ); Gia_FileWriteBufferSize( pFile, 4 ); Gia_FileWriteBufferSize( pFile, p->nConstrs ); } // write timing information if ( p->nAnd2Delay ) { fprintf( pFile, "d" ); Gia_FileWriteBufferSize( pFile, 4 ); Gia_FileWriteBufferSize( pFile, p->nAnd2Delay ); } if ( p->pManTime ) { float * pTimes; pTimes = Tim_ManGetArrTimes( (Tim_Man_t *)p->pManTime ); if ( pTimes ) { fprintf( pFile, "i" ); Gia_FileWriteBufferSize( pFile, 4*Tim_ManPiNum((Tim_Man_t *)p->pManTime) ); fwrite( pTimes, 1, 4*Tim_ManPiNum((Tim_Man_t *)p->pManTime), pFile ); ABC_FREE( pTimes ); if ( fVerbose ) printf( "Finished writing extension \"i\".\n" ); } pTimes = Tim_ManGetReqTimes( (Tim_Man_t *)p->pManTime ); if ( pTimes ) { fprintf( pFile, "o" ); Gia_FileWriteBufferSize( pFile, 4*Tim_ManPoNum((Tim_Man_t *)p->pManTime) ); fwrite( pTimes, 1, 4*Tim_ManPoNum((Tim_Man_t *)p->pManTime), pFile ); ABC_FREE( pTimes ); if ( fVerbose ) printf( "Finished writing extension \"o\".\n" ); } } // write equivalences if ( p->pReprs && p->pNexts ) { extern Vec_Str_t * Gia_WriteEquivClasses( Gia_Man_t * p ); fprintf( pFile, "e" ); vStrExt = Gia_WriteEquivClasses( p ); Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); Vec_StrFree( vStrExt ); } // write flop classes if ( p->vFlopClasses ) { fprintf( pFile, "f" ); 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 ); } // write gate classes if ( p->vGateClasses ) { fprintf( pFile, "g" ); 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 ); } // write hierarchy info if ( p->pManTime ) { 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 ); if ( fVerbose ) printf( "Finished writing extension \"h\".\n" ); } // 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 ); if ( fVerbose ) printf( "Finished writing extension \"k\".\n" ); } // write mapping if ( Gia_ManHasMapping(p) ) { extern Vec_Str_t * Gia_AigerWriteMapping( Gia_Man_t * p ); extern Vec_Str_t * Gia_AigerWriteMappingSimple( Gia_Man_t * p ); extern Vec_Str_t * Gia_AigerWriteMappingDoc( Gia_Man_t * p ); fprintf( pFile, "m" ); vStrExt = Gia_AigerWriteMappingDoc( p ); Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); Vec_StrFree( vStrExt ); if ( fVerbose ) printf( "Finished writing extension \"m\".\n" ); } // write placement if ( p->pPlacement ) { fprintf( pFile, "p" ); Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) ); fwrite( p->pPlacement, 1, 4*Gia_ManObjNum(p), pFile ); } // write register classes if ( p->vRegClasses ) { int i; fprintf( pFile, "r" ); Gia_FileWriteBufferSize( pFile, 4*Vec_IntSize(p->vRegClasses) ); for ( i = 0; i < Vec_IntSize(p->vRegClasses); i++ ) Gia_FileWriteBufferSize( pFile, Vec_IntEntry(p->vRegClasses, i) ); } // write choices if ( Gia_ManHasChoices(p) ) { 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" ); } // write switching activity if ( p->pSwitching ) { fprintf( pFile, "u" ); Gia_FileWriteBufferSize( pFile, Gia_ManObjNum(p) ); fwrite( p->pSwitching, 1, Gia_ManObjNum(p), pFile ); } /* // write timing information if ( p->pManTime ) { fprintf( pFile, "t" ); 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 ); } */ // write object classes if ( p->vObjClasses ) { 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 ); } // 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' ); } // write comments fprintf( pFile, "\nThis file was produced by the GIA package in ABC on %s\n", Gia_TimeStamp() ); fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); fclose( pFile ); if ( p != pInit ) { pInit->pManTime = p->pManTime; p->pManTime = NULL; pInit->vNamesIn = p->vNamesIn; p->vNamesIn = NULL; pInit->vNamesOut = p->vNamesOut; p->vNamesOut = NULL; Gia_ManStop( p ); } } /**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 ); Gia_AigerWrite( p, Buffer, 0, 0 ); } /**Function************************************************************* Synopsis [Writes the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_AigerWriteSimple( Gia_Man_t * pInit, char * pFileName ) { FILE * pFile; Vec_Str_t * vStr; if ( Gia_ManPoNum(pInit) == 0 ) { printf( "Gia_AigerWriteSimple(): AIG cannot be written because it has no POs.\n" ); return; } // start the output stream pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { fprintf( stdout, "Gia_AigerWriteSimple(): Cannot open the output file \"%s\".\n", pFileName ); return; } // write the buffer vStr = Gia_AigerWriteIntoMemoryStr( pInit ); fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile ); Vec_StrFree( vStr ); fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END