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