blob: ed4e4643aee4862190b0d7300675222151938f7d [file] [log] [blame]
/**CFile****************************************************************
FileName [ioReadBlifAig.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Command processing package.]
Synopsis [Procedures to read BLIF file into AIG.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - December 23, 2006.]
Revision [$Id: ioReadBlifAig.c,v 1.00 2006/12/23 00:00:00 alanmi Exp $]
***********************************************************************/
#include "base/abc/abc.h"
#include "misc/vec/vecPtr.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// latch initial values
typedef enum {
IO_BLIF_INIT_NONE = 0, // 0: unknown
IO_BLIF_INIT_ZERO, // 1: zero
IO_BLIF_INIT_ONE, // 2: one
IO_BLIF_INIT_DC // 3: don't-care
} Io_BlifInit_t;
typedef struct Io_BlifObj_t_ Io_BlifObj_t; // parsing object
struct Io_BlifObj_t_
{
unsigned fPi : 1; // the object is a primary input
unsigned fPo : 1; // the object is a primary output
unsigned fLi : 1; // the object is a latch input
unsigned fLo : 1; // the object is a latch output
unsigned fDef : 1; // the object is defined as a table (node, PO, LI)
unsigned fLoop : 1; // flag for loop detection
unsigned Init : 2; // the latch initial state
unsigned Offset : 24; // temporary number
char * pName; // the name of this object
void * pEquiv; // the AIG node representing this line
Io_BlifObj_t * pNext; // the next obj in the hash table
};
typedef struct Io_BlifMan_t_ Io_BlifMan_t; // parsing manager
struct Io_BlifMan_t_
{
// general info about file
char * pFileName; // the name of the file
char * pBuffer; // the begining of the file buffer
Vec_Ptr_t * vLines; // the line beginnings
// temporary objects
Io_BlifObj_t * pObjects; // the storage for objects
int nObjects; // the number of objects allocated
int iObjNext; // the next free object
// file lines
char * pModel; // .model line
Vec_Ptr_t * vInputs; // .inputs lines
Vec_Ptr_t * vOutputs; // .outputs lines
Vec_Ptr_t * vLatches; // .latches lines
Vec_Ptr_t * vNames; // .names lines
// network objects
Vec_Ptr_t * vPis; // the PI structures
Vec_Ptr_t * vPos; // the PO structures
Vec_Ptr_t * vLis; // the LI structures
Vec_Ptr_t * vLos; // the LO structures
// mapping of names into objects
Io_BlifObj_t ** pTable; // the hash table
int nTableSize; // the hash table size
// current processing info
Abc_Ntk_t * pAig; // the network under construction
Vec_Ptr_t * vTokens; // the current tokens
char sError[512]; // the error string generated during parsing
// statistics
int nTablesRead; // the number of processed tables
int nTablesLeft; // the number of dangling tables
};
// static functions
static Io_BlifMan_t * Io_BlifAlloc();
static void Io_BlifFree( Io_BlifMan_t * p );
static char * Io_BlifLoadFile( char * pFileName );
static void Io_BlifReadPreparse( Io_BlifMan_t * p );
static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p );
static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine );
static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine );
static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine );
static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine );
static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine );
static int Io_BlifParseConstruct( Io_BlifMan_t * p );
static int Io_BlifCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Reads the network from the BLIF file as an AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck )
{
FILE * pFile;
Io_BlifMan_t * p;
Abc_Ntk_t * pAig;
// check that the file is available
pFile = fopen( pFileName, "rb" );
if ( pFile == NULL )
{
printf( "Io_Blif(): The file is unavailable (absent or open).\n" );
return 0;
}
fclose( pFile );
// start the file reader
p = Io_BlifAlloc();
p->pFileName = pFileName;
p->pBuffer = Io_BlifLoadFile( pFileName );
if ( p->pBuffer == NULL )
{
Io_BlifFree( p );
return NULL;
}
// prepare the file for parsing
Io_BlifReadPreparse( p );
// construct the network
pAig = Io_BlifParse( p );
if ( p->sError[0] )
fprintf( stdout, "%s\n", p->sError );
if ( pAig == NULL )
return NULL;
Io_BlifFree( p );
// make sure that everything is okay with the network structure
if ( fCheck && !Abc_NtkCheckRead( pAig ) )
{
printf( "Io_Blif: The network check has failed.\n" );
Abc_NtkDelete( pAig );
return NULL;
}
return pAig;
}
/**Function*************************************************************
Synopsis [Allocates the BLIF parsing structure.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static Io_BlifMan_t * Io_BlifAlloc()
{
Io_BlifMan_t * p;
p = ABC_ALLOC( Io_BlifMan_t, 1 );
memset( p, 0, sizeof(Io_BlifMan_t) );
p->vLines = Vec_PtrAlloc( 512 );
p->vInputs = Vec_PtrAlloc( 512 );
p->vOutputs = Vec_PtrAlloc( 512 );
p->vLatches = Vec_PtrAlloc( 512 );
p->vNames = Vec_PtrAlloc( 512 );
p->vTokens = Vec_PtrAlloc( 512 );
p->vPis = Vec_PtrAlloc( 512 );
p->vPos = Vec_PtrAlloc( 512 );
p->vLis = Vec_PtrAlloc( 512 );
p->vLos = Vec_PtrAlloc( 512 );
return p;
}
/**Function*************************************************************
Synopsis [Frees the BLIF parsing structure.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static void Io_BlifFree( Io_BlifMan_t * p )
{
if ( p->pAig )
Abc_NtkDelete( p->pAig );
if ( p->pBuffer ) ABC_FREE( p->pBuffer );
if ( p->pObjects ) ABC_FREE( p->pObjects );
if ( p->pTable ) ABC_FREE( p->pTable );
Vec_PtrFree( p->vLines );
Vec_PtrFree( p->vInputs );
Vec_PtrFree( p->vOutputs );
Vec_PtrFree( p->vLatches );
Vec_PtrFree( p->vNames );
Vec_PtrFree( p->vTokens );
Vec_PtrFree( p->vPis );
Vec_PtrFree( p->vPos );
Vec_PtrFree( p->vLis );
Vec_PtrFree( p->vLos );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Hashing for character strings.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static unsigned Io_BlifHashString( char * pName, int TableSize )
{
static int s_Primes[10] = {
1291, 1699, 2357, 4177, 5147,
5647, 6343, 7103, 7873, 8147
};
unsigned i, Key = 0;
for ( i = 0; pName[i] != '\0'; i++ )
Key ^= s_Primes[i%10]*pName[i]*pName[i];
return Key % TableSize;
}
/**Function*************************************************************
Synopsis [Checks if the given name exists in the table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static Io_BlifObj_t ** Io_BlifHashLookup( Io_BlifMan_t * p, char * pName )
{
Io_BlifObj_t ** ppEntry;
for ( ppEntry = p->pTable + Io_BlifHashString(pName, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext )
if ( !strcmp((*ppEntry)->pName, pName) )
return ppEntry;
return ppEntry;
}
/**Function*************************************************************
Synopsis [Finds or add the given name to the table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static Io_BlifObj_t * Io_BlifHashFindOrAdd( Io_BlifMan_t * p, char * pName )
{
Io_BlifObj_t ** ppEntry;
ppEntry = Io_BlifHashLookup( p, pName );
if ( *ppEntry == NULL )
{
assert( p->iObjNext < p->nObjects );
*ppEntry = p->pObjects + p->iObjNext++;
(*ppEntry)->pName = pName;
}
return *ppEntry;
}
/**Function*************************************************************
Synopsis [Collects the already split tokens.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static void Io_BlifCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput )
{
char * pCur;
Vec_PtrClear( vTokens );
for ( pCur = pInput; pCur < pOutput; pCur++ )
{
if ( *pCur == 0 )
continue;
Vec_PtrPush( vTokens, pCur );
while ( *++pCur );
}
}
/**Function*************************************************************
Synopsis [Splits the line into tokens.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static void Io_BlifSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop )
{
char * pCur;
// clear spaces
for ( pCur = pLine; *pCur != Stop; pCur++ )
if ( Io_BlifCharIsSpace(*pCur) )
*pCur = 0;
// collect tokens
Io_BlifCollectTokens( vTokens, pLine, pCur );
}
/**Function*************************************************************
Synopsis [Returns the 1-based number of the line in which the token occurs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static int Io_BlifGetLine( Io_BlifMan_t * p, char * pToken )
{
char * pLine;
int i;
Vec_PtrForEachEntry( char *, p->vLines, pLine, i )
if ( pToken < pLine )
return i;
return -1;
}
/**Function*************************************************************
Synopsis [Conservatively estimates the number of primary inputs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static int Io_BlifEstimatePiNum( Io_BlifMan_t * p )
{
char * pCur;
int i, fSpaces;
int Counter = 0;
Vec_PtrForEachEntry( char *, p->vInputs, pCur, i )
for ( fSpaces = 0; *pCur; pCur++ )
{
if ( Io_BlifCharIsSpace(*pCur) )
{
if ( !fSpaces )
Counter++;
fSpaces = 1;
}
else
fSpaces = 0;
}
return Counter;
}
/**Function*************************************************************
Synopsis [Conservatively estimates the number of AIG nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static int Io_BlifEstimateAndNum( Io_BlifMan_t * p )
{
Io_BlifObj_t * pObj;
char * pCur;
int i, CounterOne, Counter = 0;
for ( i = 0; i < p->iObjNext; i++ )
{
pObj = p->pObjects + i;
if ( !pObj->fDef )
continue;
CounterOne = 0;
for ( pCur = pObj->pName + strlen(pObj->pName); *pCur != '.'; pCur++ )
if ( *pCur == '0' || *pCur == '1' )
CounterOne++;
if ( CounterOne )
Counter += CounterOne - 1;
}
return Counter;
}
/**Function*************************************************************
Synopsis [Reads the file into a character buffer.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static char * Io_BlifLoadFile( char * pFileName )
{
FILE * pFile;
int nFileSize;
char * pContents;
int RetValue;
pFile = fopen( pFileName, "rb" );
if ( pFile == NULL )
{
printf( "Io_BlifLoadFile(): The file is unavailable (absent or open).\n" );
return NULL;
}
fseek( pFile, 0, SEEK_END );
nFileSize = ftell( pFile );
if ( nFileSize == 0 )
{
fclose( pFile );
printf( "Io_BlifLoadFile(): The file is empty.\n" );
return NULL;
}
pContents = ABC_ALLOC( char, nFileSize + 10 );
rewind( pFile );
RetValue = fread( pContents, nFileSize, 1, pFile );
fclose( pFile );
// finish off the file with the spare .end line
// some benchmarks suddenly break off without this line
strcpy( pContents + nFileSize, "\n.end\n" );
return pContents;
}
/**Function*************************************************************
Synopsis [Prepares the parsing.]
Description [Performs several preliminary operations:
- Cuts the file buffer into separate lines.
- Removes comments and line extenders.
- Sorts lines by directives.
- Estimates the number of objects.
- Allocates room for the objects.
- Allocates room for the hash table.]
SideEffects []
SeeAlso []
***********************************************************************/
static void Io_BlifReadPreparse( Io_BlifMan_t * p )
{
char * pCur, * pPrev;
int i, fComment = 0;
// parse the buffer into lines and remove comments
Vec_PtrPush( p->vLines, p->pBuffer );
for ( pCur = p->pBuffer; *pCur; pCur++ )
{
if ( *pCur == '\n' )
{
*pCur = 0;
fComment = 0;
Vec_PtrPush( p->vLines, pCur + 1 );
}
else if ( *pCur == '#' )
fComment = 1;
// remove comments
if ( fComment )
*pCur = 0;
}
// unfold the line extensions and sort lines by directive
Vec_PtrForEachEntry( char *, p->vLines, pCur, i )
{
if ( *pCur == 0 )
continue;
// find previous non-space character
for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- )
if ( !Io_BlifCharIsSpace(*pPrev) )
break;
// if it is the line extender, overwrite it with spaces
if ( *pPrev == '\\' )
{
for ( ; *pPrev; pPrev++ )
*pPrev = ' ';
*pPrev = ' ';
continue;
}
// skip spaces at the beginning of the line
while ( Io_BlifCharIsSpace(*pCur++) );
// parse directives
if ( *(pCur-1) != '.' )
continue;
if ( !strncmp(pCur, "names", 5) )
Vec_PtrPush( p->vNames, pCur );
else if ( !strncmp(pCur, "latch", 5) )
Vec_PtrPush( p->vLatches, pCur );
else if ( !strncmp(pCur, "inputs", 6) )
Vec_PtrPush( p->vInputs, pCur );
else if ( !strncmp(pCur, "outputs", 7) )
Vec_PtrPush( p->vOutputs, pCur );
else if ( !strncmp(pCur, "model", 5) )
p->pModel = pCur;
else if ( !strncmp(pCur, "end", 3) || !strncmp(pCur, "exdc", 4) )
break;
else
{
pCur--;
if ( pCur[strlen(pCur)-1] == '\r' )
pCur[strlen(pCur)-1] = 0;
fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_BlifGetLine(p, pCur), pCur );
}
}
// count the number of objects
p->nObjects = Io_BlifEstimatePiNum(p) + Vec_PtrSize(p->vLatches) + Vec_PtrSize(p->vNames) + 512;
// allocate memory for objects
p->pObjects = ABC_ALLOC( Io_BlifObj_t, p->nObjects );
memset( p->pObjects, 0, p->nObjects * sizeof(Io_BlifObj_t) );
// allocate memory for the hash table
p->nTableSize = p->nObjects/2 + 1;
p->pTable = ABC_ALLOC( Io_BlifObj_t *, p->nTableSize );
memset( p->pTable, 0, p->nTableSize * sizeof(Io_BlifObj_t *) );
}
/**Function*************************************************************
Synopsis [Reads the AIG in the binary AIGER format.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p )
{
Abc_Ntk_t * pAig;
char * pLine;
int i;
// parse the model
if ( !Io_BlifParseModel( p, p->pModel ) )
return NULL;
// parse the inputs
Vec_PtrForEachEntry( char *, p->vInputs, pLine, i )
if ( !Io_BlifParseInputs( p, pLine ) )
return NULL;
// parse the outputs
Vec_PtrForEachEntry( char *, p->vOutputs, pLine, i )
if ( !Io_BlifParseOutputs( p, pLine ) )
return NULL;
// parse the latches
Vec_PtrForEachEntry( char *, p->vLatches, pLine, i )
if ( !Io_BlifParseLatch( p, pLine ) )
return NULL;
// parse the nodes
Vec_PtrForEachEntry( char *, p->vNames, pLine, i )
if ( !Io_BlifParseNames( p, pLine ) )
return NULL;
// reconstruct the network from the parsed data
if ( !Io_BlifParseConstruct( p ) )
return NULL;
// return the network
pAig = p->pAig;
p->pAig = NULL;
return pAig;
}
/**Function*************************************************************
Synopsis [Parses the model line.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine )
{
char * pToken;
Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
pToken = (char *)Vec_PtrEntry( p->vTokens, 0 );
assert( !strcmp(pToken, "model") );
if ( Vec_PtrSize(p->vTokens) != 2 )
{
sprintf( p->sError, "Line %d: Model line has %d entries while it should have 2.", Io_BlifGetLine(p, pToken), Vec_PtrSize(p->vTokens) );
return 0;
}
p->pModel = (char *)Vec_PtrEntry( p->vTokens, 1 );
return 1;
}
/**Function*************************************************************
Synopsis [Parses the inputs line.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine )
{
Io_BlifObj_t * pObj;
char * pToken;
int i;
Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
pToken = (char *)Vec_PtrEntry(p->vTokens, 0);
assert( !strcmp(pToken, "inputs") );
Vec_PtrForEachEntryStart( char *, p->vTokens, pToken, i, 1 )
{
pObj = Io_BlifHashFindOrAdd( p, pToken );
if ( pObj->fPi )
{
sprintf( p->sError, "Line %d: Primary input (%s) is defined more than once.", Io_BlifGetLine(p, pToken), pToken );
return 0;
}
pObj->fPi = 1;
Vec_PtrPush( p->vPis, pObj );
}
return 1;
}
/**Function*************************************************************
Synopsis [Parses the outputs line.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine )
{
Io_BlifObj_t * pObj;
char * pToken;
int i;
Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
pToken = (char *)Vec_PtrEntry(p->vTokens, 0);
assert( !strcmp(pToken, "outputs") );
Vec_PtrForEachEntryStart( char *, p->vTokens, pToken, i, 1 )
{
pObj = Io_BlifHashFindOrAdd( p, pToken );
if ( pObj->fPo )
fprintf( stdout, "Line %d: Primary output (%s) is defined more than once (warning only).\n", Io_BlifGetLine(p, pToken), pToken );
pObj->fPo = 1;
Vec_PtrPush( p->vPos, pObj );
}
return 1;
}
/**Function*************************************************************
Synopsis [Parses the latches line.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine )
{
Io_BlifObj_t * pObj;
char * pToken;
int Init;
Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
pToken = (char *)Vec_PtrEntry(p->vTokens,0);
assert( !strcmp(pToken, "latch") );
if ( Vec_PtrSize(p->vTokens) < 3 )
{
sprintf( p->sError, "Line %d: Latch does not have input name and output name.", Io_BlifGetLine(p, pToken) );
return 0;
}
// get initial value
if ( Vec_PtrSize(p->vTokens) > 3 )
Init = atoi( (char *)Vec_PtrEntry(p->vTokens,3) );
else
Init = 2;
if ( Init < 0 || Init > 2 )
{
sprintf( p->sError, "Line %d: Initial state of the latch is incorrect (%s).", Io_BlifGetLine(p, pToken), (char*)Vec_PtrEntry(p->vTokens,3) );
return 0;
}
if ( Init == 0 )
Init = IO_BLIF_INIT_ZERO;
else if ( Init == 1 )
Init = IO_BLIF_INIT_ONE;
else // if ( Init == 2 )
Init = IO_BLIF_INIT_DC;
// get latch input
pObj = Io_BlifHashFindOrAdd( p, (char *)Vec_PtrEntry(p->vTokens,1) );
pObj->fLi = 1;
Vec_PtrPush( p->vLis, pObj );
pObj->Init = Init;
// get latch output
pObj = Io_BlifHashFindOrAdd( p, (char *)Vec_PtrEntry(p->vTokens,2) );
if ( pObj->fPi )
{
sprintf( p->sError, "Line %d: Primary input (%s) is also defined latch output.", Io_BlifGetLine(p, pToken), (char*)Vec_PtrEntry(p->vTokens,2) );
return 0;
}
if ( pObj->fLo )
{
sprintf( p->sError, "Line %d: Latch output (%s) is defined as the output of another latch.", Io_BlifGetLine(p, pToken), (char*)Vec_PtrEntry(p->vTokens,2) );
return 0;
}
pObj->fLo = 1;
Vec_PtrPush( p->vLos, pObj );
pObj->Init = Init;
return 1;
}
/**Function*************************************************************
Synopsis [Parses the nodes line.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine )
{
Io_BlifObj_t * pObj;
char * pName;
Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' );
assert( !strcmp((char *)Vec_PtrEntry(p->vTokens,0), "names") );
pName = (char *)Vec_PtrEntryLast( p->vTokens );
pObj = Io_BlifHashFindOrAdd( p, pName );
if ( pObj->fPi )
{
sprintf( p->sError, "Line %d: Primary input (%s) has a table.", Io_BlifGetLine(p, pName), pName );
return 0;
}
if ( pObj->fLo )
{
sprintf( p->sError, "Line %d: Latch output (%s) has a table.", Io_BlifGetLine(p, pName), pName );
return 0;
}
if ( pObj->fDef )
{
sprintf( p->sError, "Line %d: Signal (%s) is defined more than once.", Io_BlifGetLine(p, pName), pName );
return 0;
}
pObj->fDef = 1;
// remember offset to the first fanin name
pObj->pName = pName;
pObj->Offset = pObj->pName - (char *)Vec_PtrEntry(p->vTokens,1);
return 1;
}
/**Function*************************************************************
Synopsis [Constructs the AIG from the file parsing info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static Abc_Obj_t * Io_BlifParseTable( Io_BlifMan_t * p, char * pTable, Vec_Ptr_t * vFanins )
{
char * pProduct, * pOutput;
Abc_Obj_t * pRes, * pCube;
int i, k, Polarity = -1;
p->nTablesRead++;
// get the tokens
Io_BlifSplitIntoTokens( p->vTokens, pTable, '.' );
if ( Vec_PtrSize(p->vTokens) == 0 )
return Abc_ObjNot( Abc_AigConst1(p->pAig) );
if ( Vec_PtrSize(p->vTokens) == 1 )
{
pOutput = (char *)Vec_PtrEntry( p->vTokens, 0 );
if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
{
sprintf( p->sError, "Line %d: Constant table has wrong output value (%s).", Io_BlifGetLine(p, pOutput), pOutput );
return NULL;
}
return Abc_ObjNotCond( Abc_AigConst1(p->pAig), pOutput[0] == '0' );
}
pProduct = (char *)Vec_PtrEntry( p->vTokens, 0 );
if ( Vec_PtrSize(p->vTokens) % 2 == 1 )
{
sprintf( p->sError, "Line %d: Table has odd number of tokens (%d).", Io_BlifGetLine(p, pProduct), Vec_PtrSize(p->vTokens) );
return NULL;
}
// parse the table
pRes = Abc_ObjNot( Abc_AigConst1(p->pAig) );
for ( i = 0; i < Vec_PtrSize(p->vTokens)/2; i++ )
{
pProduct = (char *)Vec_PtrEntry( p->vTokens, 2*i + 0 );
pOutput = (char *)Vec_PtrEntry( p->vTokens, 2*i + 1 );
if ( strlen(pProduct) != (unsigned)Vec_PtrSize(vFanins) )
{
sprintf( p->sError, "Line %d: Cube (%s) has size different from the fanin count (%d).", Io_BlifGetLine(p, pProduct), pProduct, Vec_PtrSize(vFanins) );
return NULL;
}
if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] )
{
sprintf( p->sError, "Line %d: Output value (%s) is incorrect.", Io_BlifGetLine(p, pProduct), pOutput );
return NULL;
}
if ( Polarity == -1 )
Polarity = pOutput[0] - '0';
else if ( Polarity != pOutput[0] - '0' )
{
sprintf( p->sError, "Line %d: Output value (%s) differs from the value in the first line of the table (%d).", Io_BlifGetLine(p, pProduct), pOutput, Polarity );
return NULL;
}
// parse one product product
pCube = Abc_AigConst1(p->pAig);
for ( k = 0; pProduct[k]; k++ )
{
if ( pProduct[k] == '0' )
pCube = Abc_AigAnd( (Abc_Aig_t *)p->pAig->pManFunc, pCube, Abc_ObjNot((Abc_Obj_t *)Vec_PtrEntry(vFanins,k)) );
else if ( pProduct[k] == '1' )
pCube = Abc_AigAnd( (Abc_Aig_t *)p->pAig->pManFunc, pCube, (Abc_Obj_t *)Vec_PtrEntry(vFanins,k) );
else if ( pProduct[k] != '-' )
{
sprintf( p->sError, "Line %d: Product term (%s) contains character (%c).", Io_BlifGetLine(p, pProduct), pProduct, pProduct[k] );
return NULL;
}
}
pRes = Abc_AigOr( (Abc_Aig_t *)p->pAig->pManFunc, pRes, pCube );
}
pRes = Abc_ObjNotCond( pRes, Polarity == 0 );
return pRes;
}
/**Function*************************************************************
Synopsis [Constructs the AIG from the file parsing info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static Abc_Obj_t * Io_BlifParseConstruct_rec( Io_BlifMan_t * p, char * pName )
{
Vec_Ptr_t * vFanins;
Abc_Obj_t * pFaninAbc;
Io_BlifObj_t * pObjIo;
char * pNameFanin;
int i;
// get the IO object with this name
pObjIo = *Io_BlifHashLookup( p, pName );
if ( pObjIo == NULL )
{
sprintf( p->sError, "Line %d: Signal (%s) is not defined as a table.", Io_BlifGetLine(p, pName), pName );
return NULL;
}
// loop detection
if ( pObjIo->fLoop )
{
sprintf( p->sError, "Line %d: Signal (%s) appears twice on a combinational path.", Io_BlifGetLine(p, pName), pName );
return NULL;
}
// check if the AIG is already constructed
if ( pObjIo->pEquiv )
return (Abc_Obj_t *)pObjIo->pEquiv;
// mark this node on the path
pObjIo->fLoop = 1;
// construct the AIGs for the fanins
vFanins = Vec_PtrAlloc( 8 );
Io_BlifCollectTokens( vFanins, pObjIo->pName - pObjIo->Offset, pObjIo->pName );
Vec_PtrForEachEntry( char *, vFanins, pNameFanin, i )
{
pFaninAbc = Io_BlifParseConstruct_rec( p, pNameFanin );
if ( pFaninAbc == NULL )
{
Vec_PtrFree( vFanins );
return NULL;
}
Vec_PtrWriteEntry( vFanins, i, pFaninAbc );
}
// construct the node
pObjIo->pEquiv = Io_BlifParseTable( p, pObjIo->pName + strlen(pObjIo->pName), vFanins );
Vec_PtrFree( vFanins );
// unmark this node on the path
pObjIo->fLoop = 0;
// remember the new node
return (Abc_Obj_t *)pObjIo->pEquiv;
}
/**Function*************************************************************
Synopsis [Constructs the AIG from the file parsing info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static int Io_BlifParseConstruct( Io_BlifMan_t * p )
{
Abc_Ntk_t * pAig;
Io_BlifObj_t * pObjIo, * pObjIoInput;
Abc_Obj_t * pObj, * pLatch;
int i;
// allocate the empty AIG
pAig = p->pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
pAig->pName = Extra_UtilStrsav( p->pModel );
pAig->pSpec = Extra_UtilStrsav( p->pFileName );
// create PIs
Vec_PtrForEachEntry( Io_BlifObj_t *, p->vPis, pObjIo, i )
{
pObj = Abc_NtkCreatePi( pAig );
Abc_ObjAssignName( pObj, pObjIo->pName, NULL );
pObjIo->pEquiv = pObj;
}
// create POs
Vec_PtrForEachEntry( Io_BlifObj_t *, p->vPos, pObjIo, i )
{
pObj = Abc_NtkCreatePo( pAig );
Abc_ObjAssignName( pObj, pObjIo->pName, NULL );
}
// create latches
Vec_PtrForEachEntry( Io_BlifObj_t *, p->vLos, pObjIo, i )
{
// add the latch input terminal
pObj = Abc_NtkCreateBi( pAig );
pObjIoInput = (Io_BlifObj_t *)Vec_PtrEntry( p->vLis, i );
Abc_ObjAssignName( pObj, pObjIoInput->pName, NULL );
// add the latch box
pLatch = Abc_NtkCreateLatch( pAig );
pLatch->pData = (void *)(ABC_PTRUINT_T)pObjIo->Init;
Abc_ObjAssignName( pLatch, pObjIo->pName, "L" );
Abc_ObjAddFanin( pLatch, pObj );
// add the latch output terminal
pObj = Abc_NtkCreateBo( pAig );
Abc_ObjAssignName( pObj, pObjIo->pName, NULL );
Abc_ObjAddFanin( pObj, pLatch );
// set the value of the latch output
// pObjIo->pEquiv = Abc_ObjNotCond( pObj, pObjIo->Init );
pObjIo->pEquiv = pObj;
}
// traverse the nodes from the POs
Vec_PtrForEachEntry( Io_BlifObj_t *, p->vPos, pObjIo, i )
{
pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName );
if ( pObj == NULL )
return 0;
Abc_ObjAddFanin( Abc_NtkPo(p->pAig, i), pObj );
}
// traverse the nodes from the latch inputs
Vec_PtrForEachEntry( Io_BlifObj_t *, p->vLis, pObjIo, i )
{
pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName );
if ( pObj == NULL )
return 0;
// pObj = Abc_ObjNotCond( pObj, pObjIo->Init );
Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(p->pAig, i)), pObj );
}
p->nTablesLeft = Vec_PtrSize(p->vNames) - p->nTablesRead;
if ( p->nTablesLeft )
printf( "The number of dangling tables = %d.\n", p->nTablesLeft );
printf( "AND nodes = %6d. Estimate = %6d.\n", Abc_NtkNodeNum(p->pAig), Io_BlifEstimateAndNum(p) );
return 1;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END