blob: fb5c6f06fcd6273aa6f962aeff54e6fba32693c0 [file] [log] [blame]
/**CFile****************************************************************
FileName [minilut.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Minimalistic representation of LUT mapped network.]
Synopsis [External declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - September 29, 2012.]
Revision [$Id: minilut.h,v 1.00 2012/09/29 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef MINI_LUT__mini_lut_h
#define MINI_LUT__mini_lut_h
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
ABC_NAMESPACE_HEADER_START
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
#define MINI_LUT_NULL (0x7FFFFFFF)
#define MINI_LUT_NULL2 (0x7FFFFFFE)
#define MINI_LUT_START_SIZE (0x000000FF)
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
typedef struct Mini_Lut_t_ Mini_Lut_t;
struct Mini_Lut_t_
{
int nCap;
int nSize;
int nRegs;
int LutSize;
int * pArray;
unsigned * pTruths;
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// memory management
#define MINI_LUT_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num)))
#define MINI_LUT_CALLOC(type, num) ((type *) calloc((num), sizeof(type)))
#define MINI_LUT_FALLOC(type, num) ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num)))
#define MINI_LUT_FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0)
#define MINI_LUT_REALLOC(type, obj, num) \
((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \
((type *) malloc(sizeof(type) * (num))))
// compute truth table size measured in unsigned's
static int Mini_LutWordNum( int LutSize )
{
return LutSize > 5 ? 1 << (LutSize-5) : 1;
}
// internal procedures
static void Mini_LutGrow( Mini_Lut_t * p, int nCapMin )
{
if ( p->nCap >= nCapMin )
return;
p->pArray = MINI_LUT_REALLOC( int, p->pArray, nCapMin * p->LutSize );
p->pTruths = MINI_LUT_REALLOC( unsigned, p->pTruths, nCapMin * Mini_LutWordNum(p->LutSize) );
p->nCap = nCapMin;
assert( p->pArray );
assert( p->pTruths );
}
static void Mini_LutPush( Mini_Lut_t * p, int nVars, int * pVars, unsigned * pTruth )
{
int i, nWords = Mini_LutWordNum(p->LutSize);
if ( p->nSize == p->nCap )
{
assert( p->LutSize*p->nSize < MINI_LUT_NULL/2 );
if ( p->nCap < MINI_LUT_START_SIZE )
Mini_LutGrow( p, MINI_LUT_START_SIZE );
else
Mini_LutGrow( p, 2 * p->nCap );
}
for ( i = 0; i < nVars; i++ )
p->pArray[p->LutSize * p->nSize + i] = pVars[i];
for ( ; i < p->LutSize; i++ )
p->pArray[p->LutSize * p->nSize + i] = MINI_LUT_NULL;
for ( i = 0; i < nWords; i++ )
p->pTruths[nWords * p->nSize + i] = pTruth? pTruth[i] : 0;
p->nSize++;
}
// accessing fanins
static int Mini_LutNodeFanin( Mini_Lut_t * p, int Id, int k )
{
assert( Id >= 0 && Id < p->nSize );
return p->pArray[p->LutSize*Id+k];
}
static unsigned * Mini_LutNodeTruth( Mini_Lut_t * p, int Id )
{
assert( Id >= 0 && Id < p->nSize );
return p->pTruths + Id * Mini_LutWordNum(p->LutSize);
}
// working with LUTs
static int Mini_LutNodeConst0() { return 0; }
static int Mini_LutNodeConst1() { return 1; }
static int Mini_LutNodeNum( Mini_Lut_t * p ) { return p->nSize; }
static int Mini_LutNodeIsConst( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id == 0 || Id == 1; }
static int Mini_LutNodeIsPi( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id > 1 && Mini_LutNodeFanin( p, Id, 0 ) == MINI_LUT_NULL; }
static int Mini_LutNodeIsPo( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id > 1 && Mini_LutNodeFanin( p, Id, 0 ) != MINI_LUT_NULL && Mini_LutNodeFanin( p, Id, 1 ) == MINI_LUT_NULL2; }
static int Mini_LutNodeIsNode( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id > 1 && Mini_LutNodeFanin( p, Id, 0 ) != MINI_LUT_NULL && Mini_LutNodeFanin( p, Id, 1 ) != MINI_LUT_NULL2; }
static int Mini_LutSize( Mini_Lut_t * p ) { return p->LutSize; }
// working with sequential AIGs
static int Mini_LutRegNum( Mini_Lut_t * p ) { return p->nRegs; }
static void Mini_LutSetRegNum( Mini_Lut_t * p, int n ) { p->nRegs = n; }
// iterators through objects
#define Mini_LutForEachPi( p, i ) for (i = 2; i < Mini_LutNodeNum(p); i++) if ( !Mini_LutNodeIsPi(p, i) ) {} else
#define Mini_LutForEachPo( p, i ) for (i = 2; i < Mini_LutNodeNum(p); i++) if ( !Mini_LutNodeIsPo(p, i) ) {} else
#define Mini_LutForEachNode( p, i ) for (i = 2; i < Mini_LutNodeNum(p); i++) if ( !Mini_LutNodeIsNode(p, i) ) {} else
// iterator through fanins
#define Mini_LutForEachFanin( p, i, Fan, k ) for (k = 0; (k < p->LutSize) && (Fan = Mini_LutNodeFanin(p, i, k)) < MINI_LUT_NULL2; k++)
// constructor/destructor
static Mini_Lut_t * Mini_LutStart( int LutSize )
{
Mini_Lut_t * p; int i;
assert( LutSize >= 2 && LutSize <= 16 );
p = MINI_LUT_CALLOC( Mini_Lut_t, 1 );
p->LutSize = LutSize;
p->nCap = MINI_LUT_START_SIZE;
p->pArray = MINI_LUT_ALLOC( int, p->nCap * p->LutSize );
p->pTruths = MINI_LUT_ALLOC( unsigned, p->nCap * Mini_LutWordNum(p->LutSize) );
Mini_LutPush( p, 0, NULL, NULL ); // const0
Mini_LutPush( p, 0, NULL, NULL ); // const1
for ( i = 0; i < Mini_LutWordNum(p->LutSize); i++ )
p->pTruths[i] = 0;
for ( i = 0; i < Mini_LutWordNum(p->LutSize); i++ )
p->pTruths[Mini_LutWordNum(p->LutSize) + i] = ~0;
return p;
}
static void Mini_LutStop( Mini_Lut_t * p )
{
MINI_LUT_FREE( p->pArray );
MINI_LUT_FREE( p->pTruths );
MINI_LUT_FREE( p );
}
static void Mini_LutPrintStats( Mini_Lut_t * p )
{
int i, nPis, nPos, nNodes;
nPis = 0;
Mini_LutForEachPi( p, i )
nPis++;
nPos = 0;
Mini_LutForEachPo( p, i )
nPos++;
nNodes = 0;
Mini_LutForEachNode( p, i )
nNodes++;
printf( "PI = %d. PO = %d. LUT = %d.\n", nPis, nPos, nNodes );
}
// serialization
static void Mini_LutDump( Mini_Lut_t * p, char * pFileName )
{
FILE * pFile;
int RetValue;
pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
{
printf( "Cannot open file for writing \"%s\".\n", pFileName );
return;
}
RetValue = (int)fwrite( &p->nSize, sizeof(int), 1, pFile );
RetValue = (int)fwrite( &p->nRegs, sizeof(int), 1, pFile );
RetValue = (int)fwrite( &p->LutSize, sizeof(int), 1, pFile );
RetValue = (int)fwrite( p->pArray, sizeof(int), p->nSize * p->LutSize, pFile );
RetValue = (int)fwrite( p->pTruths, sizeof(int), p->nSize * Mini_LutWordNum(p->LutSize), pFile );
fclose( pFile );
}
static Mini_Lut_t * Mini_LutLoad( char * pFileName )
{
Mini_Lut_t * p;
FILE * pFile;
int RetValue, nSize;
pFile = fopen( pFileName, "rb" );
if ( pFile == NULL )
{
printf( "Cannot open file for reading \"%s\".\n", pFileName );
return NULL;
}
RetValue = (int)fread( &nSize, sizeof(int), 1, pFile );
p = MINI_LUT_CALLOC( Mini_Lut_t, 1 );
p->nSize = p->nCap = nSize;
RetValue = (int)fread( &p->nRegs, sizeof(int), 1, pFile );
RetValue = (int)fread( &p->LutSize, sizeof(int), 1, pFile );
p->pArray = MINI_LUT_ALLOC( int, p->nCap * p->LutSize );
p->pTruths = MINI_LUT_ALLOC( unsigned, p->nCap * Mini_LutWordNum(p->LutSize) );
RetValue = (int)fread( p->pArray, sizeof(int), p->nCap * p->LutSize, pFile );
RetValue = (int)fread( p->pTruths, sizeof(int), p->nCap * Mini_LutWordNum(p->LutSize), pFile );
fclose( pFile );
return p;
}
// creating nodes
// (constant nodes are created when LUT manager is created)
static int Mini_LutCreatePi( Mini_Lut_t * p )
{
Mini_LutPush( p, 0, NULL, NULL );
return p->nSize - 1;
}
static int Mini_LutCreatePo( Mini_Lut_t * p, int Var0 )
{
assert( Var0 >= 0 && Var0 < p->nSize );
Mini_LutPush( p, 1, &Var0, NULL );
// mark PO by setting its 2nd fanin to the special number
p->pArray[p->LutSize*(p->nSize - 1)+1] = MINI_LUT_NULL2;
return p->nSize - 1;
}
// create LUT
static int Mini_LutCreateNode( Mini_Lut_t * p, int nVars, int * pVars, unsigned * pTruth )
{
assert( nVars >= 0 && nVars <= p->LutSize );
Mini_LutPush( p, nVars, pVars, pTruth );
return p->nSize - 1;
}
// procedure to check the topological order during AIG construction
static int Mini_LutCheck( Mini_Lut_t * p )
{
int status = 1;
int i, k, iFaninVar;
Mini_LutForEachNode( p, i )
{
for ( k = 0; k < p->LutSize; k++ )
{
iFaninVar = Mini_LutNodeFanin( p, i, k );
if ( iFaninVar == MINI_LUT_NULL )
continue;
if ( iFaninVar >= p->LutSize * i )
printf( "Fanin %d of LUT node %d is not in a topological order.\n", k, i ), status = 0;
}
}
Mini_LutForEachPo( p, i )
{
iFaninVar = Mini_LutNodeFanin( p, i, 0 );
if ( iFaninVar >= p->LutSize * i )
printf( "Fanin %d of PO node %d is not in a topological order.\n", k, i ), status = 0;
}
return status;
}
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_HEADER_END
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////