blob: 1f0dbaeb35721ccf6ec92d1fa2023573100c8779 [file] [log] [blame]
/**CFile****************************************************************
FileName [bblif.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Binary BLIF representation for logic networks.]
Synopsis [Main implementation module.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - February 28, 2009.]
Revision [$Id: bblif.c,v 1.00 2009/02/28 00:00:00 alanmi Exp $]
***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "misc/util/abc_global.h"
#include "bblif.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// vector of integers
typedef struct Vec_Int_t_ Vec_Int_t;
struct Vec_Int_t_
{
int nCap;
int nSize;
int * pArray;
};
// vector of characters
typedef struct Vec_Str_t_ Vec_Str_t;
struct Vec_Str_t_
{
int nCap;
int nSize;
char * pArray;
};
// network object
struct Bbl_Obj_t_
{
int Id; // user ID
int Fnc; // functionality
unsigned fCi : 1; // combinational input
unsigned fCo : 1; // combinational output
unsigned fBox : 1; // subcircuit
unsigned fMark : 1; // temporary mark
unsigned nFanins : 28; // fanin number
int pFanins[0]; // fanin array
};
// object function
typedef struct Bbl_Fnc_t_ Bbl_Fnc_t;
struct Bbl_Fnc_t_
{
int nWords; // word number
int pWords[0]; // word array
};
// object function
typedef struct Bbl_Ent_t_ Bbl_Ent_t;
struct Bbl_Ent_t_
{
int iFunc; // function handle
int iNext; // next entry handle
};
// data manager
struct Bbl_Man_t_
{
// data pool
Vec_Str_t * pName; // design name
Vec_Str_t * pObjs; // vector of objects
Vec_Str_t * pFncs; // vector of functions
// construction
Vec_Int_t * vId2Obj; // mapping user IDs into objects
Vec_Int_t * vObj2Id; // mapping objects into user IDs
Vec_Int_t * vFaninNums; // mapping user IDs into fanin number
// file contents
int nFileSize; // file size
char * pFileData; // file contents
// other data
Vec_Str_t * pEnts; // vector of entries
int SopMap[17][17]; // mapping vars x cubes into entry handles
};
static inline int Bbl_ObjIsCi( Bbl_Obj_t * pObj ) { return pObj->fCi; }
static inline int Bbl_ObjIsCo( Bbl_Obj_t * pObj ) { return pObj->fCo; }
static inline int Bbl_ObjIsNode( Bbl_Obj_t * pObj ) { return!pObj->fCi && !pObj->fCo; }
static inline int Bbl_ObjFaninNum( Bbl_Obj_t * pObj ) { return pObj->nFanins; }
static inline Bbl_Obj_t * Bbl_ObjFanin( Bbl_Obj_t * pObj, int i ) { return (Bbl_Obj_t *)(((char *)pObj) - pObj->pFanins[i]); }
static inline int Bbl_ObjSize( Bbl_Obj_t * pObj ) { return sizeof(Bbl_Obj_t) + sizeof(int) * pObj->nFanins; }
static inline int Bbl_FncSize( Bbl_Fnc_t * pFnc ) { return sizeof(Bbl_Fnc_t) + sizeof(int) * pFnc->nWords; }
static inline Bbl_Obj_t * Bbl_VecObj( Vec_Str_t * p, int h ) { return (Bbl_Obj_t *)(p->pArray + h); }
static inline Bbl_Fnc_t * Bbl_VecFnc( Vec_Str_t * p, int h ) { return (Bbl_Fnc_t *)(p->pArray + h); }
static inline Bbl_Ent_t * Bbl_VecEnt( Vec_Str_t * p, int h ) { return (Bbl_Ent_t *)(p->pArray + h); }
static inline char * Bbl_ManSop( Bbl_Man_t * p, int h ) { return (char *)Bbl_VecFnc(p->pFncs, h)->pWords; }
static inline Bbl_Obj_t * Bbl_ManObj( Bbl_Man_t * p, int Id ) { return Bbl_VecObj(p->pObjs, p->vId2Obj->pArray[Id]); }
#define Bbl_ManForEachObj_int( p, pObj, h ) \
for ( h = 0; (h < p->nSize) && (pObj = Bbl_VecObj(p,h)); h += Bbl_ObjSize(pObj) )
#define Bbl_ManForEachFnc_int( p, pObj, h ) \
for ( h = 0; (h < p->nSize) && (pObj = Bbl_VecFnc(p,h)); h += Bbl_FncSize(pObj) )
#define Bbl_ObjForEachFanin_int( pObj, pFanin, i ) \
for ( i = 0; (i < (int)pObj->nFanins) && (pFanin = Bbl_ObjFanin(pObj,i)); i++ )
#define BBLIF_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
#define BBLIF_CALLOC(type, num) ((type *) calloc((num), sizeof(type)))
#define BBLIF_FALLOC(type, num) ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num)))
#define BBLIF_FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
#define BBLIF_REALLOC(type, obj, num) \
((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
((type *) malloc(sizeof(type) * (num))))
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Allocates a vector with the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Int_t * Vec_IntAlloc( int nCap )
{
Vec_Int_t * p;
p = BBLIF_ALLOC( Vec_Int_t, 1 );
if ( nCap > 0 && nCap < 16 )
nCap = 16;
p->nSize = 0;
p->nCap = nCap;
p->pArray = p->nCap? BBLIF_ALLOC( int, p->nCap ) : NULL;
return p;
}
/**Function*************************************************************
Synopsis [Allocates a vector with the given size and cleans it.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Int_t * Vec_IntStart( int nSize )
{
Vec_Int_t * p;
p = Vec_IntAlloc( nSize );
p->nSize = nSize;
memset( p->pArray, 0, sizeof(int) * nSize );
return p;
}
/**Function*************************************************************
Synopsis [Allocates a vector with the given size and cleans it.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Int_t * Vec_IntStartNatural( int nSize )
{
Vec_Int_t * p;
int i;
p = Vec_IntAlloc( nSize );
p->nSize = nSize;
for ( i = 0; i < nSize; i++ )
p->pArray[i] = i;
return p;
}
/**Function*************************************************************
Synopsis [Creates the vector from an integer array of the given size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Int_t * Vec_IntAllocArray( int * pArray, int nSize )
{
Vec_Int_t * p;
p = BBLIF_ALLOC( Vec_Int_t, 1 );
p->nSize = nSize;
p->nCap = nSize;
p->pArray = pArray;
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntFree( Vec_Int_t * p )
{
BBLIF_FREE( p->pArray );
BBLIF_FREE( p );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntSize( Vec_Int_t * p )
{
return p->nSize;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntEntry( Vec_Int_t * p, int i )
{
assert( i >= 0 && i < p->nSize );
return p->pArray[i];
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry )
{
assert( i >= 0 && i < p->nSize );
p->pArray[i] = Entry;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition )
{
assert( i >= 0 && i < p->nSize );
p->pArray[i] += Addition;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntEntryLast( Vec_Int_t * p )
{
assert( p->nSize > 0 );
return p->pArray[p->nSize-1];
}
/**Function*************************************************************
Synopsis [Resizes the vector to the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin )
{
if ( p->nCap >= nCapMin )
return;
p->pArray = BBLIF_REALLOC( int, p->pArray, nCapMin );
assert( p->pArray );
p->nCap = nCapMin;
}
/**Function*************************************************************
Synopsis [Fills the vector with given number of entries.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntFill( Vec_Int_t * p, int nSize, int Fill )
{
int i;
Vec_IntGrow( p, nSize );
for ( i = 0; i < nSize; i++ )
p->pArray[i] = Fill;
p->nSize = nSize;
}
/**Function*************************************************************
Synopsis [Fills the vector with given number of entries.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntFillExtra( Vec_Int_t * p, int nSize, int Fill )
{
int i;
if ( p->nSize >= nSize )
return;
if ( nSize > 2 * p->nCap )
Vec_IntGrow( p, nSize );
else if ( nSize > p->nCap )
Vec_IntGrow( p, 2 * p->nCap );
for ( i = p->nSize; i < nSize; i++ )
p->pArray[i] = Fill;
p->nSize = nSize;
}
/**Function*************************************************************
Synopsis [Returns the entry even if the place not exist.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntGetEntry( Vec_Int_t * p, int i )
{
Vec_IntFillExtra( p, i + 1, 0 );
return Vec_IntEntry( p, i );
}
/**Function*************************************************************
Synopsis [Inserts the entry even if the place does not exist.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntSetEntry( Vec_Int_t * p, int i, int Entry )
{
Vec_IntFillExtra( p, i + 1, 0 );
Vec_IntWriteEntry( p, i, Entry );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntShrink( Vec_Int_t * p, int nSizeNew )
{
assert( p->nSize >= nSizeNew );
p->nSize = nSizeNew;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntClear( Vec_Int_t * p )
{
p->nSize = 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntPush( Vec_Int_t * p, int Entry )
{
if ( p->nSize == p->nCap )
{
if ( p->nCap < 16 )
Vec_IntGrow( p, 16 );
else
Vec_IntGrow( p, 2 * p->nCap );
}
p->pArray[p->nSize++] = Entry;
}
/**Function*************************************************************
Synopsis [Allocates a vector with the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Str_t * Vec_StrAlloc( int nCap )
{
Vec_Str_t * p;
p = BBLIF_ALLOC( Vec_Str_t, 1 );
if ( nCap > 0 && nCap < 16 )
nCap = 16;
p->nSize = 0;
p->nCap = nCap;
p->pArray = p->nCap? BBLIF_ALLOC( char, p->nCap ) : NULL;
return p;
}
/**Function*************************************************************
Synopsis [Creates the vector from an array of the given size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize )
{
Vec_Str_t * p;
p = BBLIF_ALLOC( Vec_Str_t, 1 );
p->nSize = nSize;
p->nCap = nSize;
p->pArray = pArray;
return p;
}
/**Fnction*************************************************************
Synopsis [Returns a piece of memory.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
char * Vec_StrFetch( Vec_Str_t * p, int nBytes )
{
while ( p->nSize + nBytes > p->nCap )
{
p->pArray = BBLIF_REALLOC( char, p->pArray, 3 * p->nCap );
p->nCap *= 3;
}
p->nSize += nBytes;
return p->pArray + p->nSize - nBytes;
}
/**Fnction*************************************************************
Synopsis [Write vector into file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Vec_StrWrite( FILE * pFile, Vec_Str_t * p )
{
fwrite( &p->nSize, sizeof(int), 1, pFile );
fwrite( p->pArray, sizeof(char), p->nSize, pFile );
}
/**Fnction*************************************************************
Synopsis [Write vector into file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Str_t * Vec_StrRead( char ** ppStr )
{
Vec_Str_t * p;
char * pStr = *ppStr;
p = Vec_StrAlloc( 0 );
p->nSize = *(int *)pStr;
p->pArray = pStr + sizeof(int);
*ppStr = pStr + sizeof(int) + p->nSize * sizeof(char);
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_StrSize( Vec_Str_t * p )
{
return p->nSize;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_StrFree( Vec_Str_t * p )
{
BBLIF_FREE( p->pArray );
BBLIF_FREE( p );
}
/**Fnction*************************************************************
Synopsis [Returns the file size.]
Description [The file should be closed.]
SideEffects []
SeeAlso []
***********************************************************************/
int Bbl_ManFileSize( char * pFileName )
{
FILE * pFile;
int nFileSize;
pFile = fopen( pFileName, "r" );
if ( pFile == NULL )
{
printf( "Bbl_ManFileSize(): The file is unavailable (absent or open).\n" );
return 0;
}
fseek( pFile, 0, SEEK_END );
nFileSize = ftell( pFile );
fclose( pFile );
return nFileSize;
}
/**Fnction*************************************************************
Synopsis [Read data from file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
char * Bbl_ManFileRead( char * pFileName )
{
FILE * pFile;
char * pContents;
int nFileSize;
int RetValue;
nFileSize = Bbl_ManFileSize( pFileName );
pFile = fopen( pFileName, "rb" );
pContents = BBLIF_ALLOC( char, nFileSize );
RetValue = fread( pContents, nFileSize, 1, pFile );
fclose( pFile );
return pContents;
}
/**Fnction*************************************************************
Synopsis [Writes data into file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bbl_ManDumpBinaryBlif( Bbl_Man_t * p, char * pFileName )
{
FILE * pFile;
pFile = fopen( pFileName, "wb" );
Vec_StrWrite( pFile, p->pName );
Vec_StrWrite( pFile, p->pObjs );
Vec_StrWrite( pFile, p->pFncs );
fclose( pFile );
}
/**Fnction*************************************************************
Synopsis [Creates manager after reading.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Bbl_Man_t * Bbl_ManReadBinaryBlif( char * pFileName )
{
Bbl_Man_t * p;
Bbl_Obj_t * pObj;
char * pBuffer;
int h;
p = BBLIF_ALLOC( Bbl_Man_t, 1 );
memset( p, 0, sizeof(Bbl_Man_t) );
p->nFileSize = Bbl_ManFileSize( pFileName );
p->pFileData = Bbl_ManFileRead( pFileName );
// extract three managers
pBuffer = p->pFileData;
p->pName = Vec_StrRead( &pBuffer );
p->pObjs = Vec_StrRead( &pBuffer );
p->pFncs = Vec_StrRead( &pBuffer );
assert( pBuffer - p->pFileData == p->nFileSize );
// remember original IDs in the objects
p->vObj2Id = Vec_IntAlloc( 1000 );
Bbl_ManForEachObj_int( p->pObjs, pObj, h )
{
Vec_IntPush( p->vObj2Id, pObj->Id );
pObj->Id = Vec_IntSize(p->vObj2Id) - 1;
}
return p;
}
/**Fnction*************************************************************
Synopsis [Prints stats of the manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bbl_ManPrintStats( Bbl_Man_t * p )
{
Bbl_Obj_t * pObj;
Bbl_Fnc_t * pFnc;
int h, nFuncs = 0, nNodes = 0, nObjs = 0;
Bbl_ManForEachObj_int( p->pObjs, pObj, h )
nObjs++, nNodes += Bbl_ObjIsNode(pObj);
Bbl_ManForEachFnc_int( p->pFncs, pFnc, h )
nFuncs++;
printf( "Total objects = %7d. Total nodes = %7d. Unique functions = %7d.\n", nObjs, nNodes, nFuncs );
printf( "Name manager = %5.2f MB\n", 1.0*Vec_StrSize(p->pName)/(1 << 20) );
printf( "Objs manager = %5.2f MB\n", 1.0*Vec_StrSize(p->pObjs)/(1 << 20) );
printf( "Fncs manager = %5.2f MB\n", 1.0*Vec_StrSize(p->pFncs)/(1 << 20) );
}
/**Fnction*************************************************************
Synopsis [Deletes the manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bbl_ManStop( Bbl_Man_t * p )
{
if ( p->vId2Obj ) Vec_IntFree( p->vId2Obj );
if ( p->vObj2Id ) Vec_IntFree( p->vObj2Id );
if ( p->vFaninNums ) Vec_IntFree( p->vFaninNums );
if ( p->pFileData )
{
BBLIF_FREE( p->pFileData );
p->pName->pArray = NULL;
p->pObjs->pArray = NULL;
p->pFncs->pArray = NULL;
}
if ( p->pEnts )
Vec_StrFree( p->pEnts );
Vec_StrFree( p->pName );
Vec_StrFree( p->pObjs );
Vec_StrFree( p->pFncs );
BBLIF_FREE( p );
}
/**Fnction*************************************************************
Synopsis [Creates manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Bbl_Man_t * Bbl_ManStart( char * pName )
{
Bbl_Man_t * p;
int nLength;
p = BBLIF_ALLOC( Bbl_Man_t, 1 );
memset( p, 0, sizeof(Bbl_Man_t) );
nLength = pName? 4 * ((strlen(pName) + 1) / 4 + 1) : 0;
p->pName = Vec_StrAlloc( nLength );
p->pName->nSize = p->pName->nCap;
if ( pName )
strcpy( p->pName->pArray, pName );
p->pObjs = Vec_StrAlloc( 1 << 16 );
p->pFncs = Vec_StrAlloc( 1 << 16 );
p->pEnts = Vec_StrAlloc( 1 << 16 ); p->pEnts->nSize = 1;
p->vId2Obj = Vec_IntStart( 1 << 10 );
p->vFaninNums = Vec_IntStart( 1 << 10 );
return p;
}
/**Function*************************************************************
Synopsis [Performs selection sort on the array of cubes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bbl_ManSortCubes( char ** pCubes, int nCubes, int nVars )
{
char * pTemp;
int i, j, best_i;
for ( i = 0; i < nCubes-1; i++ )
{
best_i = i;
for (j = i+1; j < nCubes; j++)
if ( memcmp( pCubes[j], pCubes[best_i], nVars ) < 0 )
best_i = j;
pTemp = pCubes[i]; pCubes[i] = pCubes[best_i]; pCubes[best_i] = pTemp;
}
}
/**Function*************************************************************
Synopsis [Sorts the cubes in the SOP to uniqify them to some extent.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
char * Bbl_ManSortSop( char * pSop, int nVars )
{
char ** pCubes, * pSopNew;
int c, Length, nCubes;
Length = strlen(pSop);
assert( Length % (nVars + 3) == 0 );
nCubes = Length / (nVars + 3);
if ( nCubes < 2 )
{
pSopNew = BBLIF_ALLOC( char, Length + 1 );
memcpy( pSopNew, pSop, Length + 1 );
return pSopNew;
}
pCubes = BBLIF_ALLOC( char *, nCubes );
for ( c = 0; c < nCubes; c++ )
pCubes[c] = pSop + c * (nVars + 3);
if ( nCubes < 300 )
Bbl_ManSortCubes( pCubes, nCubes, nVars );
pSopNew = BBLIF_ALLOC( char, Length + 1 );
for ( c = 0; c < nCubes; c++ )
memcpy( pSopNew + c * (nVars + 3), pCubes[c], nVars + 3 );
BBLIF_FREE( pCubes );
pSopNew[nCubes * (nVars + 3)] = 0;
return pSopNew;
}
/**Fnction*************************************************************
Synopsis [Saves one entry.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bbl_ManCreateEntry( Bbl_Man_t * p, int iFunc, int iNext )
{
Bbl_Ent_t * pEnt;
pEnt = (Bbl_Ent_t *)Vec_StrFetch( p->pEnts, 2 * sizeof(int) );
pEnt->iFunc = iFunc;
pEnt->iNext = iNext;
return (char *)pEnt - p->pEnts->pArray;
}
/**Function*************************************************************
Synopsis [Sorts the cubes in the SOP to uniqify them to some extent.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bbl_ManSopCheckUnique( Bbl_Man_t * p, char * pSop, int nVars, int nCubes, int iFunc )
{
Bbl_Fnc_t * pFnc;
Bbl_Ent_t * pEnt;
int h, Length = strlen(pSop) + 1;
int nWords = (Length / 4 + (Length % 4 > 0));
if ( nVars > 16 ) nVars = 16;
if ( nCubes > 16 ) nCubes = 16;
// if ( nVars == 16 && nCubes == 16 )
// return iFunc;
for ( h = p->SopMap[nVars][nCubes]; h; h = pEnt->iNext )
{
pEnt = Bbl_VecEnt( p->pEnts, h );
pFnc = Bbl_VecFnc( p->pFncs, pEnt->iFunc );
assert( nVars == 16 || nCubes == 16 || pFnc->nWords == nWords );
if ( pFnc->nWords == nWords && memcmp( pFnc->pWords, pSop, Length ) == 0 )
return pEnt->iFunc;
}
p->SopMap[nVars][nCubes] = Bbl_ManCreateEntry( p, iFunc, p->SopMap[nVars][nCubes] );
return iFunc;
}
/**Fnction*************************************************************
Synopsis [Saves one SOP.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bbl_ManSaveSop( Bbl_Man_t * p, char * pSop, int nVars )
{
Bbl_Fnc_t * pFnc;
char * pSopNew;
int iFunc, Length = strlen(pSop) + 1;
int nWords = Length / 4 + (Length % 4 > 0);
// reorder cubes to semi-canicize SOPs
pSopNew = Bbl_ManSortSop( pSop, nVars );
// get the candidate location
iFunc = Bbl_ManSopCheckUnique( p, pSopNew, nVars, Length / (nVars + 3), Vec_StrSize(p->pFncs) );
// iFunc = Vec_StrSize(p->pFncs);
if ( iFunc == Vec_StrSize(p->pFncs) )
{ // store this SOP
pFnc = (Bbl_Fnc_t *)Vec_StrFetch( p->pFncs, sizeof(Bbl_Fnc_t) + nWords * sizeof(int) );
pFnc->pWords[nWords-1] = 0;
pFnc->nWords = nWords;
strcpy( (char *)pFnc->pWords, pSopNew );
assert( iFunc == (char *)pFnc - p->pFncs->pArray );
}
BBLIF_FREE( pSopNew );
return iFunc;
}
/**Fnction*************************************************************
Synopsis [Adds one object.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bbl_ManCreateObject( Bbl_Man_t * p, Bbl_Type_t Type, int ObjId, int nFanins, char * pSop )
{
Bbl_Obj_t * pObj;
if ( Type == BBL_OBJ_CI && nFanins != 0 )
{
printf( "Attempting to create a combinational input with %d fanins (should be 0).\n", nFanins );
return;
}
if ( Type == BBL_OBJ_CO && nFanins != 1 )
{
printf( "Attempting to create a combinational output with %d fanins (should be 1).\n", nFanins );
return;
}
pObj = (Bbl_Obj_t *)Vec_StrFetch( p->pObjs, sizeof(Bbl_Obj_t) + nFanins * sizeof(int) );
memset( pObj, 0, sizeof(Bbl_Obj_t) );
Vec_IntSetEntry( p->vId2Obj, ObjId, (char *)pObj - p->pObjs->pArray );
Vec_IntSetEntry( p->vFaninNums, ObjId, 0 );
pObj->fCi = (Type == BBL_OBJ_CI);
pObj->fCo = (Type == BBL_OBJ_CO);
pObj->Id = ObjId;
pObj->Fnc = pSop? Bbl_ManSaveSop(p, pSop, nFanins) : -1;
pObj->nFanins = nFanins;
}
/**Fnction*************************************************************
Synopsis [Creates fanin/fanout relationship between two objects.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bbl_ManAddFanin( Bbl_Man_t * p, int ObjId, int FaninId )
{
Bbl_Obj_t * pObj, * pFanin;
int iFanin;
pObj = Bbl_ManObj( p, ObjId );
if ( Bbl_ObjIsCi(pObj) )
{
printf( "Bbl_ManAddFanin(): Cannot add fanin of the combinational input (Id = %d).\n", ObjId );
return;
}
pFanin = Bbl_ManObj( p, FaninId );
if ( Bbl_ObjIsCo(pFanin) )
{
printf( "Bbl_ManAddFanin(): Cannot add fanout of the combinational output (Id = %d).\n", FaninId );
return;
}
iFanin = Vec_IntEntry( p->vFaninNums, ObjId );
if ( iFanin >= (int)pObj->nFanins )
{
printf( "Bbl_ManAddFanin(): Trying to add more fanins to object (Id = %d) than declared (%d).\n", ObjId, pObj->nFanins );
return;
}
assert( iFanin < (int)pObj->nFanins );
Vec_IntWriteEntry( p->vFaninNums, ObjId, iFanin+1 );
pObj->pFanins[iFanin] = (char *)pObj - (char *)pFanin;
}
/**Fnction*************************************************************
Synopsis [Returns 1 if the manager was created correctly.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bbl_ManCheck( Bbl_Man_t * p )
{
Bbl_Obj_t * pObj;
int h, RetValue = 1;
Bbl_ManForEachObj_int( p->pObjs, pObj, h )
{
if ( Bbl_ObjIsNode(pObj) && pObj->Fnc == -1 )
RetValue = 0, printf( "Bbl_ManCheck(): Node %d does not have function specified.\n", pObj->Id );
if ( Bbl_ObjIsCi(pObj) && pObj->Fnc != -1 )
RetValue = 0, printf( "Bbl_ManCheck(): CI with %d has function specified.\n", pObj->Id );
if ( Bbl_ObjIsCo(pObj) && pObj->Fnc != -1 )
RetValue = 0, printf( "Bbl_ManCheck(): CO with %d has function specified.\n", pObj->Id );
if ( Vec_IntEntry(p->vFaninNums, pObj->Id) != (int)pObj->nFanins )
RetValue = 0, printf( "Bbl_ManCheck(): Object %d has less fanins (%d) than declared (%d).\n",
pObj->Id, Vec_IntEntry(p->vFaninNums, pObj->Id), pObj->nFanins );
}
return RetValue;
}
/**Fnction*************************************************************
Synopsis [Misc APIs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bbl_ObjIsInput( Bbl_Obj_t * p ) { return Bbl_ObjIsCi(p); }
int Bbl_ObjIsOutput( Bbl_Obj_t * p ) { return Bbl_ObjIsCo(p); }
int Bbl_ObjIsLut( Bbl_Obj_t * p ) { return Bbl_ObjIsNode(p); }
int Bbl_ObjId( Bbl_Obj_t * p ) { return p->Id; }
int Bbl_ObjIdOriginal( Bbl_Man_t * pMan, Bbl_Obj_t * p ) { assert(0); return Vec_IntEntry(pMan->vObj2Id, p->Id); }
int Bbl_ObjFaninNumber( Bbl_Obj_t * p ) { return Bbl_ObjFaninNum(p); }
char * Bbl_ObjSop( Bbl_Man_t * pMan, Bbl_Obj_t * p ) { return Bbl_ManSop(pMan, p->Fnc); }
int Bbl_ObjIsMarked( Bbl_Obj_t * p ) { return p->fMark; }
void Bbl_ObjMark( Bbl_Obj_t * p ) { p->fMark = 1; }
int Bbl_ObjFncHandle( Bbl_Obj_t * p ) { return p->Fnc; }
/**Fnction*************************************************************
Synopsis [Returns the name of the design.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
char * Bbl_ManName( Bbl_Man_t * p )
{
return p->pName->pArray;
}
/**Fnction*************************************************************
Synopsis [Returns the maximum handle of the SOP.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bbl_ManFncSize( Bbl_Man_t * p )
{
return p->pFncs->nSize;
}
/**Fnction*************************************************************
Synopsis [Returns the first object.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Bbl_Obj_t * Bbl_ManObjFirst( Bbl_Man_t * p )
{
return Bbl_VecObj( p->pObjs, 0 );
}
/**Fnction*************************************************************
Synopsis [Returns the next object.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Bbl_Obj_t * Bbl_ManObjNext( Bbl_Man_t * p, Bbl_Obj_t * pObj )
{
char * pNext = (char *)pObj + Bbl_ObjSize(pObj);
char * pEdge = p->pObjs->pArray + p->pObjs->nSize;
return (Bbl_Obj_t *)(pNext < pEdge ? pNext : NULL);
}
/**Fnction*************************************************************
Synopsis [Returns the first fanin.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Bbl_Obj_t * Bbl_ObjFaninFirst( Bbl_Obj_t * p )
{
return Bbl_ObjFaninNum(p) ? Bbl_ObjFanin( p, 0 ) : NULL;
}
/**Fnction*************************************************************
Synopsis [Returns the next fanin.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Bbl_Obj_t * Bbl_ObjFaninNext( Bbl_Obj_t * p, Bbl_Obj_t * pPrev )
{
Bbl_Obj_t * pFanin;
int i;
Bbl_ObjForEachFanin_int( p, pFanin, i )
if ( pFanin == pPrev )
break;
return i < Bbl_ObjFaninNum(p) - 1 ? Bbl_ObjFanin( p, i+1 ) : NULL;
}
/**Fnction*************************************************************
Synopsis [Drives text BLIF file for debugging.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bbl_ManDumpBlif( Bbl_Man_t * p, char * pFileName )
{
FILE * pFile;
Bbl_Obj_t * pObj, * pFanin;
pFile = fopen( pFileName, "w" );
fprintf( pFile, "# Test file written by Bbl_ManDumpBlif() in ABC.\n" );
fprintf( pFile, ".model %s\n", Bbl_ManName(p) );
// write objects
Bbl_ManForEachObj( p, pObj )
{
if ( Bbl_ObjIsInput(pObj) )
fprintf( pFile, ".inputs %d\n", Bbl_ObjId(pObj) );
else if ( Bbl_ObjIsOutput(pObj) )
fprintf( pFile, ".outputs %d\n", Bbl_ObjId(pObj) );
else if ( Bbl_ObjIsLut(pObj) )
{
fprintf( pFile, ".names" );
Bbl_ObjForEachFanin( pObj, pFanin )
fprintf( pFile, " %d", Bbl_ObjId(pFanin) );
fprintf( pFile, " %d\n", Bbl_ObjId(pObj) );
fprintf( pFile, "%s", Bbl_ObjSop(p, pObj) );
}
else assert( 0 );
}
// write output drivers
Bbl_ManForEachObj( p, pObj )
{
if ( !Bbl_ObjIsOutput(pObj) )
continue;
fprintf( pFile, ".names" );
Bbl_ObjForEachFanin( pObj, pFanin )
fprintf( pFile, " %d", Bbl_ObjId(pFanin) );
fprintf( pFile, " %d\n", Bbl_ObjId(pObj) );
fprintf( pFile, "1 1\n" );
}
fprintf( pFile, ".end\n" );
fclose( pFile );
}
/**Fnction*************************************************************
Synopsis [Converting truth table into an SOP.]
Description [The truth table is given as a bit-string pTruth
composed of 2^nVars bits. The result is an SOP derived by
collecting minterms appearing in the truth table. The SOP is
represented as a C-string, as documented in file "bblif.h".
It is recommended to limit the use of this procedure to Boolean
functions up to 6 inputs.]
SideEffects []
SeeAlso []
***********************************************************************/
char * Bbl_ManTruthToSop( unsigned * pTruth, int nVars )
{
char * pResult, * pTemp;
int nMints, nOnes, b, v;
assert( nVars >= 0 && nVars <= 16 );
nMints = (1 << nVars);
// count the number of ones
nOnes = 0;
for ( b = 0; b < nMints; b++ )
nOnes += ((pTruth[b>>5] >> (b&31)) & 1);
// handle constants
if ( nOnes == 0 || nOnes == nMints )
{
pResult = pTemp = BBLIF_ALLOC( char, nVars + 4 );
for ( v = 0; v < nVars; v++ )
*pTemp++ = '-';
*pTemp++ = ' ';
*pTemp++ = nOnes? '1' : '0';
*pTemp++ = '\n';
*pTemp++ = 0;
assert( pTemp - pResult == nVars + 4 );
return pResult;
}
pResult = pTemp = BBLIF_ALLOC( char, nOnes * (nVars + 3) + 1 );
for ( b = 0; b < nMints; b++ )
{
if ( ((pTruth[b>>5] >> (b&31)) & 1) == 0 )
continue;
for ( v = 0; v < nVars; v++ )
*pTemp++ = ((b >> v) & 1)? '1' : '0';
*pTemp++ = ' ';
*pTemp++ = '1';
*pTemp++ = '\n';
}
*pTemp++ = 0;
assert( pTemp - pResult == nOnes * (nVars + 3) + 1 );
return pResult;
}
/**Function*************************************************************
Synopsis [Allocates the array of truth tables for the given number of vars.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Bbl_ManSopToTruthElem( int nVars, unsigned ** pVars )
{
unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
int i, k, nWords;
nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5)));
for ( i = 0; i < nVars; i++ )
{
if ( i < 5 )
{
for ( k = 0; k < nWords; k++ )
pVars[i][k] = Masks[i];
}
else
{
for ( k = 0; k < nWords; k++ )
if ( k & (1 << (i-5)) )
pVars[i][k] = ~(unsigned)0;
else
pVars[i][k] = 0;
}
}
}
/**Fnction*************************************************************
Synopsis [Converting SOP into a truth table.]
Description [The SOP is represented as a C-string, as documented in
file "bblif.h". The truth table is returned as a bit-string composed
of 2^nVars bits. For functions of less than 6 variables, the full
machine word is returned. (The truth table looks as if the function
had 5 variables.) The use of this procedure should be limited to
Boolean functions with no more than 16 inputs.]
SideEffects []
SeeAlso []
***********************************************************************/
unsigned * Bbl_ManSopToTruth( char * pSop, int nVars )
{
unsigned * pTruth, * pCube, * pVars[16];
int nWords = nVars <= 5 ? 1 : (1 << (nVars - 5));
int v, c, w, nCubes, fCompl = 0;
if ( pSop == NULL )
return NULL;
if ( strlen(pSop) % (nVars + 3) != 0 )
{
printf( "Bbl_ManSopToTruth(): SOP is represented incorrectly.\n" );
return NULL;
}
// create storage for TTs of the result, elementary variables and the temp cube
pTruth = BBLIF_ALLOC( unsigned, nWords );
pVars[0] = BBLIF_ALLOC( unsigned, nWords * (nVars+1) );
for ( v = 1; v < nVars; v++ )
pVars[v] = pVars[v-1] + nWords;
pCube = pVars[v-1] + nWords;
Bbl_ManSopToTruthElem( nVars, pVars );
// iterate through the cubes
memset( pTruth, 0, sizeof(unsigned) * nWords );
nCubes = strlen(pSop) / (nVars + 3);
for ( c = 0; c < nCubes; c++ )
{
fCompl = (pSop[nVars+1] == '0');
memset( pCube, 0xff, sizeof(unsigned) * nWords );
// iterate through the literals of the cube
for ( v = 0; v < nVars; v++ )
if ( pSop[v] == '1' )
for ( w = 0; w < nWords; w++ )
pCube[w] &= pVars[v][w];
else if ( pSop[v] == '0' )
for ( w = 0; w < nWords; w++ )
pCube[w] &= ~pVars[v][w];
// add cube to storage
for ( w = 0; w < nWords; w++ )
pTruth[w] |= pCube[w];
// go to the next cube
pSop += (nVars + 3);
}
BBLIF_FREE( pVars[0] );
if ( fCompl )
for ( w = 0; w < nWords; w++ )
pTruth[w] = ~pTruth[w];
return pTruth;
}
/**Fnction*************************************************************
Synopsis [Checks the truth table computation.]
Description [We construct the logic network for the half-adder represnted
using the BLIF file below]
SideEffects []
SeeAlso []
***********************************************************************/
void Bbl_ManTestTruth( char * pSop, int nVars )
{
unsigned * pTruth;
char * pSopNew;
pTruth = Bbl_ManSopToTruth( pSop, nVars );
pSopNew = Bbl_ManTruthToSop( pTruth, nVars );
printf( "Old SOP:\n%s\n", pSop );
printf( "New SOP:\n%s\n", pSopNew );
BBLIF_FREE( pSopNew );
BBLIF_FREE( pTruth );
}
/**Fnction*************************************************************
Synopsis [This demo shows using the internal to construct a half-adder.]
Description [We construct the logic network for the half-adder represnted
using the BLIF file below]
SideEffects []
SeeAlso []
***********************************************************************/
void Bbl_ManSimpleDemo()
{
/*
# There are contents of a BLIF file representing a half-adder:
.model hadder
.inputs a // ID = 1
.inputs b // ID = 2
.inputs cin // ID = 3
.outputs s // ID = 4
.outputs cout // ID = 5
.names a b cin s_driver // ID = 6
100 1
010 1
001 1
111 1
.names a b cin cout_driver // ID = 7
-11 1
1-1 1
11- 1
.names s_driver s
1 1
.names cout_driver cout
1 1
.end
*/
Bbl_Man_t * p;
// start the data manager
p = Bbl_ManStart( "hadder" );
// create CIs
Bbl_ManCreateObject( p, BBL_OBJ_CI, 1, 0, NULL ); // a
Bbl_ManCreateObject( p, BBL_OBJ_CI, 2, 0, NULL ); // b
Bbl_ManCreateObject( p, BBL_OBJ_CI, 3, 0, NULL ); // cin
// create COs
Bbl_ManCreateObject( p, BBL_OBJ_CO, 4, 1, NULL ); // s
Bbl_ManCreateObject( p, BBL_OBJ_CO, 5, 1, NULL ); // cout
// create internal nodes
Bbl_ManCreateObject( p, BBL_OBJ_NODE, 6, 3, "100 1\n010 1\n001 1\n111 1\n" ); // s_driver
Bbl_ManCreateObject( p, BBL_OBJ_NODE, 7, 3, "-11 1\n1-1 1\n11- 1\n" ); // cout_driver
// add fanins of node 6
Bbl_ManAddFanin( p, 6, 1 ); // s_driver <- a
Bbl_ManAddFanin( p, 6, 2 ); // s_driver <- b
Bbl_ManAddFanin( p, 6, 3 ); // s_driver <- cin
// add fanins of node 7
Bbl_ManAddFanin( p, 7, 1 ); // cout_driver <- a
Bbl_ManAddFanin( p, 7, 2 ); // cout_driver <- b
Bbl_ManAddFanin( p, 7, 3 ); // cout_driver <- cin
// add fanins of COs
Bbl_ManAddFanin( p, 4, 6 ); // s <- s_driver
Bbl_ManAddFanin( p, 5, 7 ); // cout <- cout_driver
// sanity check
Bbl_ManCheck( p );
// write BLIF file as a sanity check
Bbl_ManDumpBlif( p, "hadder.blif" );
// write binary BLIF file
Bbl_ManDumpBinaryBlif( p, "hadder.bblif" );
// remove the manager
Bbl_ManStop( p );
// Bbl_ManTestTruth( "100 1\n010 1\n001 1\n111 1\n", 3 );
// Bbl_ManTestTruth( "-11 0\n1-1 0\n11- 0\n", 3 );
// Bbl_ManTestTruth( "--- 1\n", 3 );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END