/**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