blob: 94946390ac3519d021594f64dc60d6cf0fa693aa [file] [log] [blame]
/**CFile****************************************************************
FileName [ifLibLut.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [FPGA mapping based on priority cuts.]
Synopsis [LUT library.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 21, 2006.]
Revision [$Id: ifLibLut.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
***********************************************************************/
#include "if.h"
#include "base/main/mainInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Reads the description of LUTs from the LUT library file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
If_LibLut_t * If_LibLutReadString( char * pStr )
{
If_LibLut_t * p;
Vec_Ptr_t * vStrs;
char * pToken, * pBuffer, * pStrNew, * pStrMem;
int i, k, j;
if ( pStr == NULL || pStr[0] == 0 )
return NULL;
vStrs = Vec_PtrAlloc( 1000 );
pStrNew = pStrMem = Abc_UtilStrsav( pStr );
while ( *pStrNew )
{
Vec_PtrPush( vStrs, pStrNew );
while ( *pStrNew != '\n' )
pStrNew++;
while ( *pStrNew == '\n' )
*pStrNew++ = '\0';
}
p = ABC_ALLOC( If_LibLut_t, 1 );
memset( p, 0, sizeof(If_LibLut_t) );
i = 1;
//while ( fgets( pBuffer, 1000, pFile ) != NULL )
Vec_PtrForEachEntry( char *, vStrs, pBuffer, j )
{
if ( pBuffer[0] == 0 )
continue;
pToken = strtok( pBuffer, " \t\n" );
if ( pToken == NULL )
continue;
if ( pToken[0] == '#' )
continue;
if ( i != atoi(pToken) )
{
Abc_Print( 1, "Error in the LUT library string.\n" );
ABC_FREE( p->pName );
ABC_FREE( p );
ABC_FREE( pStrMem );
Vec_PtrFree( vStrs );
return NULL;
}
// read area
pToken = strtok( NULL, " \t\n" );
p->pLutAreas[i] = (float)atof(pToken);
// read delays
k = 0;
while ( (pToken = strtok( NULL, " \t\n" )) )
p->pLutDelays[i][k++] = (float)atof(pToken);
// check for out-of-bound
if ( k > i )
{
Abc_Print( 1, "LUT %d has too many pins (%d). Max allowed is %d.\n", i, k, i );
ABC_FREE( p->pName );
ABC_FREE( p );
ABC_FREE( pStrMem );
Vec_PtrFree( vStrs );
return NULL;
}
// check if var delays are specified
if ( k > 1 )
p->fVarPinDelays = 1;
if ( i == IF_MAX_LUTSIZE )
{
Abc_Print( 1, "Skipping LUTs of size more than %d.\n", i );
ABC_FREE( p->pName );
ABC_FREE( p );
ABC_FREE( pStrMem );
Vec_PtrFree( vStrs );
return NULL;
}
i++;
}
p->LutMax = i-1;
// check the library
if ( p->fVarPinDelays )
{
for ( i = 1; i <= p->LutMax; i++ )
for ( k = 0; k < i; k++ )
{
if ( p->pLutDelays[i][k] <= 0.0 )
Abc_Print( 0, "Pin %d of LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n",
k, i, p->pLutDelays[i][k] );
if ( k && p->pLutDelays[i][k-1] > p->pLutDelays[i][k] )
Abc_Print( 0, "Pin %d of LUT %d has delay %f. Pin %d of LUT %d has delay %f. Pin delays should be in non-decreasing order. Technology mapping may not work correctly.\n",
k-1, i, p->pLutDelays[i][k-1],
k, i, p->pLutDelays[i][k] );
}
}
else
{
for ( i = 1; i <= p->LutMax; i++ )
{
if ( p->pLutDelays[i][0] <= 0.0 )
Abc_Print( 0, "LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n",
i, p->pLutDelays[i][0] );
}
}
// cleanup
ABC_FREE( pStrMem );
Vec_PtrFree( vStrs );
return p;
}
/**Function*************************************************************
Synopsis [Sets the library associated with the string.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_FrameSetLutLibrary( Abc_Frame_t * pAbc, char * pLutLibString )
{
If_LibLut_t * pLib = If_LibLutReadString( pLutLibString );
if ( pLib == NULL )
{
fprintf( stdout, "Reading LUT library from string has failed.\n" );
return 0;
}
// replace the current library
If_LibLutFree( (If_LibLut_t *)Abc_FrameReadLibLut() );
Abc_FrameSetLibLut( pLib );
return 1;
}
int Abc_FrameSetLutLibraryTest( Abc_Frame_t * pAbc )
{
char * pStr = "1 1.00 1000\n2 1.00 1000 1200\n3 1.00 1000 1200 1400\n4 1.00 1000 1200 1400 1600\n5 1.00 1000 1200 1400 1600 1800\n6 1.00 1000 1200 1400 1600 1800 2000\n\n\n";
Abc_FrameSetLutLibrary( pAbc, pStr );
return 1;
}
/**Function*************************************************************
Synopsis [Reads the description of LUTs from the LUT library file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
If_LibLut_t * If_LibLutRead( char * FileName )
{
char pBuffer[1000], * pToken;
If_LibLut_t * p;
FILE * pFile;
int i, k;
pFile = fopen( FileName, "r" );
if ( pFile == NULL )
{
Abc_Print( -1, "Cannot open LUT library file \"%s\".\n", FileName );
return NULL;
}
p = ABC_ALLOC( If_LibLut_t, 1 );
memset( p, 0, sizeof(If_LibLut_t) );
p->pName = Abc_UtilStrsav( FileName );
i = 1;
while ( fgets( pBuffer, 1000, pFile ) != NULL )
{
pToken = strtok( pBuffer, " \t\n" );
if ( pToken == NULL )
continue;
if ( pToken[0] == '#' )
continue;
if ( i != atoi(pToken) )
{
Abc_Print( 1, "Error in the LUT library file \"%s\".\n", FileName );
ABC_FREE( p->pName );
ABC_FREE( p );
fclose( pFile );
return NULL;
}
// read area
pToken = strtok( NULL, " \t\n" );
p->pLutAreas[i] = (float)atof(pToken);
// read delays
k = 0;
while ( (pToken = strtok( NULL, " \t\n" )) )
p->pLutDelays[i][k++] = (float)atof(pToken);
// check for out-of-bound
if ( k > i )
{
ABC_FREE( p->pName );
ABC_FREE( p );
Abc_Print( 1, "LUT %d has too many pins (%d). Max allowed is %d.\n", i, k, i );
fclose( pFile );
return NULL;
}
// check if var delays are specified
if ( k > 1 )
p->fVarPinDelays = 1;
if ( i == IF_MAX_LUTSIZE )
{
ABC_FREE( p->pName );
ABC_FREE( p );
Abc_Print( 1, "Skipping LUTs of size more than %d.\n", i );
fclose( pFile );
return NULL;
}
i++;
}
p->LutMax = i-1;
// check the library
if ( p->fVarPinDelays )
{
for ( i = 1; i <= p->LutMax; i++ )
for ( k = 0; k < i; k++ )
{
if ( p->pLutDelays[i][k] <= 0.0 )
Abc_Print( 0, "Pin %d of LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n",
k, i, p->pLutDelays[i][k] );
if ( k && p->pLutDelays[i][k-1] > p->pLutDelays[i][k] )
Abc_Print( 0, "Pin %d of LUT %d has delay %f. Pin %d of LUT %d has delay %f. Pin delays should be in non-decreasing order. Technology mapping may not work correctly.\n",
k-1, i, p->pLutDelays[i][k-1],
k, i, p->pLutDelays[i][k] );
}
}
else
{
for ( i = 1; i <= p->LutMax; i++ )
{
if ( p->pLutDelays[i][0] <= 0.0 )
Abc_Print( 0, "LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n",
i, p->pLutDelays[i][0] );
}
}
fclose( pFile );
return p;
}
/**Function*************************************************************
Synopsis [Duplicates the LUT library.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
If_LibLut_t * If_LibLutDup( If_LibLut_t * p )
{
If_LibLut_t * pNew;
pNew = ABC_ALLOC( If_LibLut_t, 1 );
*pNew = *p;
pNew->pName = Abc_UtilStrsav( pNew->pName );
return pNew;
}
/**Function*************************************************************
Synopsis [Frees the LUT library.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_LibLutFree( If_LibLut_t * pLutLib )
{
if ( pLutLib == NULL )
return;
ABC_FREE( pLutLib->pName );
ABC_FREE( pLutLib );
}
/**Function*************************************************************
Synopsis [Prints the LUT library.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void If_LibLutPrint( If_LibLut_t * pLutLib )
{
int i, k;
Abc_Print( 1, "# The area/delay of k-variable LUTs:\n" );
Abc_Print( 1, "# k area delay\n" );
if ( pLutLib->fVarPinDelays )
{
for ( i = 1; i <= pLutLib->LutMax; i++ )
{
Abc_Print( 1, "%d %7.2f ", i, pLutLib->pLutAreas[i] );
for ( k = 0; k < i; k++ )
Abc_Print( 1, " %7.2f", pLutLib->pLutDelays[i][k] );
Abc_Print( 1, "\n" );
}
}
else
for ( i = 1; i <= pLutLib->LutMax; i++ )
Abc_Print( 1, "%d %7.2f %7.2f\n", i, pLutLib->pLutAreas[i], pLutLib->pLutDelays[i][0] );
}
/**Function*************************************************************
Synopsis [Returns 1 if the delays are discrete.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_LibLutDelaysAreDiscrete( If_LibLut_t * pLutLib )
{
float Delay;
int i;
for ( i = 1; i <= pLutLib->LutMax; i++ )
{
Delay = pLutLib->pLutDelays[i][0];
if ( ((float)((int)Delay)) != Delay )
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis [Returns 1 if the delays are discrete.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int If_LibLutDelaysAreDifferent( If_LibLut_t * pLutLib )
{
int i, k;
float Delay = pLutLib->pLutDelays[1][0];
if ( pLutLib->fVarPinDelays )
{
for ( i = 2; i <= pLutLib->LutMax; i++ )
for ( k = 0; k < i; k++ )
if ( pLutLib->pLutDelays[i][k] != Delay )
return 1;
}
else
{
for ( i = 2; i <= pLutLib->LutMax; i++ )
if ( pLutLib->pLutDelays[i][0] != Delay )
return 1;
}
return 0;
}
/**Function*************************************************************
Synopsis [Sets simple LUT library.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
If_LibLut_t * If_LibLutSetSimple( int nLutSize )
{
If_LibLut_t s_LutLib10= { "lutlib",10, 0, {0,1,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1},{1}} };
If_LibLut_t s_LutLib9 = { "lutlib", 9, 0, {0,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1}} };
If_LibLut_t s_LutLib8 = { "lutlib", 8, 0, {0,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1}} };
If_LibLut_t s_LutLib7 = { "lutlib", 7, 0, {0,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1}} };
If_LibLut_t s_LutLib6 = { "lutlib", 6, 0, {0,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1}} };
If_LibLut_t s_LutLib5 = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} };
If_LibLut_t s_LutLib4 = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} };
If_LibLut_t s_LutLib3 = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} };
If_LibLut_t * pLutLib;
assert( nLutSize >= 3 && nLutSize <= 10 );
switch ( nLutSize )
{
case 3: pLutLib = &s_LutLib3; break;
case 4: pLutLib = &s_LutLib4; break;
case 5: pLutLib = &s_LutLib5; break;
case 6: pLutLib = &s_LutLib6; break;
case 7: pLutLib = &s_LutLib7; break;
case 8: pLutLib = &s_LutLib8; break;
case 9: pLutLib = &s_LutLib9; break;
case 10: pLutLib = &s_LutLib10; break;
default: pLutLib = NULL; break;
}
if ( pLutLib == NULL )
return NULL;
return If_LibLutDup(pLutLib);
}
/**Function*************************************************************
Synopsis [Gets the delay of the fastest pin.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float If_LibLutFastestPinDelay( If_LibLut_t * p )
{
return !p? 1.0 : p->pLutDelays[p->LutMax][0];
}
/**Function*************************************************************
Synopsis [Gets the delay of the slowest pin.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float If_LibLutSlowestPinDelay( If_LibLut_t * p )
{
return !p? 1.0 : (p->fVarPinDelays? p->pLutDelays[p->LutMax][p->LutMax-1]: p->pLutDelays[p->LutMax][0]);
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END