blob: 97f40aea4497dcb3ea2ea7e97cd14fc92fb80b87 [file] [log] [blame]
/**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 fGiaSimple, 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;
pNew->fGiaSimple = fGiaSimple;
// 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 ( !fGiaSimple && !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 ( !fGiaSimple && 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 ( !fGiaSimple && !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<num>
// PIs are named: @i<num>
// POs are named: @o<num>
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, 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++;
pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4;
nRegs = Gia_AigerReadInt(pCur); pCur += 4;
//nRegs = (pCurTemp - pCur)/4;
pNew->vRegClasses = Vec_IntAlloc( nRegs );
for ( i = 0; i < nRegs; i++ )
Vec_IntPush( pNew->vRegClasses, Gia_AigerReadInt(pCur) ), pCur += 4;
assert( pCur == pCurTemp );
if ( fVerbose ) printf( "Finished reading extension \"r\".\n" );
}
// 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" );
}
// read configuration data
else if ( *pCur == 'b' )
{
int nSize;
pCur++;
nSize = Gia_AigerReadInt(pCur);
pCurTemp = pCur + nSize + 4; pCur += 4;
pNew->pCellStr = Abc_UtilStrsav( (char*)pCur ); pCur += strlen((char*)pCur) + 1;
nSize = nSize - strlen(pNew->pCellStr) - 1;
assert( nSize % 4 == 0 );
pNew->vConfigs = Vec_IntAlloc(nSize / 4);
// memcpy(Vec_IntArray(pNew->vConfigs), pCur, nSize); pCur += nSize;
for ( i = 0; i < nSize / 4; i++ )
Vec_IntPush( pNew->vConfigs, Gia_AigerReadInt(pCur) ), pCur += 4;
assert( pCur == pCurTemp );
if ( fVerbose ) printf( "Finished reading extension \"b\".\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" );
}
// 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 );
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" );
Vec_IntFree( vPairs );
}
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 ( !fGiaSimple && !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, fGiaSimple, 1 );
pNew->nConstrs = pTemp->nConstrs; pTemp->nConstrs = 0;
Gia_ManStop( pTemp );
ABC_FREE( pInit );
}
Vec_IntFreeP( &vInits );
if ( !fGiaSimple && !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 fGiaSimple, 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, fGiaSimple, 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, 0 );
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( p->fGiaSimple || 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 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 );
}
// 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)+1) );
Gia_FileWriteBufferSize( pFile, Vec_IntSize(p->vRegClasses) );
for ( i = 0; i < Vec_IntSize(p->vRegClasses); i++ )
Gia_FileWriteBufferSize( pFile, Vec_IntEntry(p->vRegClasses, i) );
}
// 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) );
}
// 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 );
// 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) );
}
// 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