| /**CFile**************************************************************** |
| |
| FileName [mapperTree.c] |
| |
| PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] |
| |
| Synopsis [Generic technology mapping engine.] |
| |
| Author [MVSIS Group] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 2.0. Started - June 1, 2004.] |
| |
| Revision [$Id: mapperTree.c,v 1.9 2005/01/23 06:59:45 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #ifdef __linux__ |
| #include <libgen.h> |
| #endif |
| |
| #include "mapperInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| static void Map_LibraryAddFaninDelays( Map_SuperLib_t * pLib, Map_Super_t * pGate, Map_Super_t * pFanin, Mio_Pin_t * pPin ); |
| static int Map_LibraryGetMaxSuperPi_rec( Map_Super_t * pGate ); |
| static unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate ); |
| |
| // fanout limits |
| static const int s_MapFanoutLimits[10] = { 1/*0*/, 10/*1*/, 5/*2*/, 2/*3*/, 1/*4*/, 1/*5*/, 1/*6*/ }; |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Reads one gate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Map_Super_t * Map_LibraryReadGateTree( Map_SuperLib_t * pLib, char * pBuffer, int Number, int nVarsMax ) |
| { |
| Map_Super_t * pGate; |
| char * pTemp; |
| int i, Num; |
| |
| // start and clean the gate |
| pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); |
| memset( pGate, 0, sizeof(Map_Super_t) ); |
| |
| // set the gate number |
| pGate->Num = Number; |
| |
| // read the mark |
| pTemp = strtok( pBuffer, " " ); |
| if ( pTemp[0] == '*' ) |
| { |
| pGate->fSuper = 1; |
| pTemp = strtok( NULL, " " ); |
| } |
| |
| // read the root gate |
| pGate->pRoot = Mio_LibraryReadGateByName( pLib->pGenlib, pTemp, NULL ); |
| if ( pGate->pRoot == NULL ) |
| { |
| printf( "Cannot read the root gate names %s.\n", pTemp ); |
| return NULL; |
| } |
| // set the max number of fanouts |
| pGate->nFanLimit = s_MapFanoutLimits[ Mio_GateReadPinNum(pGate->pRoot) ]; |
| |
| // read the pin-to-pin delay |
| for ( i = 0; ( pTemp = strtok( NULL, " \n\0" ) ); i++ ) |
| { |
| if ( pTemp[0] == '#' ) |
| break; |
| if ( i == nVarsMax ) |
| { |
| printf( "There are too many entries on the line.\n" ); |
| return NULL; |
| } |
| Num = atoi(pTemp); |
| if ( Num < 0 ) |
| { |
| printf( "The number of a child supergate is negative.\n" ); |
| return NULL; |
| } |
| if ( Num > pLib->nLines ) |
| { |
| printf( "The number of a child supergate (%d) exceeded the number of lines (%d).\n", |
| Num, pLib->nLines ); |
| return NULL; |
| } |
| pGate->pFanins[i] = pLib->ppSupers[Num]; |
| } |
| pGate->nFanins = i; |
| if ( pGate->nFanins != (unsigned)Mio_GateReadPinNum(pGate->pRoot) ) |
| { |
| printf( "The number of fanins of a root gate is wrong.\n" ); |
| return NULL; |
| } |
| |
| // save the gate name, just in case |
| if ( pTemp && pTemp[0] == '#' ) |
| { |
| if ( pTemp[1] == 0 ) |
| pTemp = strtok( NULL, " \n\0" ); |
| else // skip spaces |
| for ( pTemp++; *pTemp == ' '; pTemp++ ); |
| // save the formula |
| pGate->pFormula = Extra_MmFlexEntryFetch( pLib->mmForms, strlen(pTemp)+1 ); |
| strcpy( pGate->pFormula, pTemp ); |
| } |
| // check the rest of the string |
| pTemp = strtok( NULL, " \n\0" ); |
| if ( pTemp != NULL ) |
| printf( "The following trailing symbols found \"%s\".\n", pTemp ); |
| return pGate; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Reads the supergate library from file.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| /* |
| int Map_LibraryReadFileTree( Map_SuperLib_t * pLib, FILE * pFile, char *pFileName ) |
| { |
| ProgressBar * pProgress; |
| char pBuffer[5000]; |
| Map_Super_t * pGate; |
| char * pTemp = 0, * pLibName; |
| int nCounter, k, i; |
| int RetValue; |
| |
| // skip empty and comment lines |
| while ( fgets( pBuffer, 5000, pFile ) != NULL ) |
| { |
| // skip leading spaces |
| for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); |
| // skip comment lines and empty lines |
| if ( *pTemp != 0 && *pTemp != '#' ) |
| break; |
| } |
| |
| pLibName = strtok( pTemp, " \t\r\n" ); |
| pLib->pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen(); |
| if ( pLib->pGenlib == NULL || strcmp( Mio_LibraryReadName(pLib->pGenlib), pLibName ) ) |
| { |
| printf( "Supergate library \"%s\" requires the use of genlib library \"%s\".\n", pFileName, pLibName ); |
| return 0; |
| } |
| |
| // read the number of variables |
| RetValue = fscanf( pFile, "%d\n", &pLib->nVarsMax ); |
| if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 ) |
| { |
| printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax ); |
| return 0; |
| } |
| |
| // read the number of gates |
| RetValue = fscanf( pFile, "%d\n", &pLib->nSupersReal ); |
| if ( pLib->nSupersReal < 1 || pLib->nSupersReal > 10000000 ) |
| { |
| printf( "Suspicious number of gates (%d).\n", pLib->nSupersReal ); |
| return 0; |
| } |
| |
| // read the number of lines |
| RetValue = fscanf( pFile, "%d\n", &pLib->nLines ); |
| if ( pLib->nLines < 1 || pLib->nLines > 10000000 ) |
| { |
| printf( "Suspicious number of lines (%d).\n", pLib->nLines ); |
| return 0; |
| } |
| |
| // allocate room for supergate pointers |
| pLib->ppSupers = ABC_ALLOC( Map_Super_t *, pLib->nLines + 10000 ); |
| |
| // create the elementary supergates |
| for ( i = 0; i < pLib->nVarsMax; i++ ) |
| { |
| // get a new gate |
| pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); |
| memset( pGate, 0, sizeof(Map_Super_t) ); |
| // assign the elementary variable, the truth table, and the delays |
| pGate->Num = i; |
| // set the truth table |
| pGate->uTruth[0] = pLib->uTruths[i][0]; |
| pGate->uTruth[1] = pLib->uTruths[i][1]; |
| // set the arrival times of all input to non-existent delay |
| for ( k = 0; k < pLib->nVarsMax; k++ ) |
| { |
| pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR; |
| pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR; |
| } |
| // set an existent arrival time for rise and fall |
| pGate->tDelaysR[i].Rise = 0.0; |
| pGate->tDelaysF[i].Fall = 0.0; |
| // set the gate |
| pLib->ppSupers[i] = pGate; |
| } |
| |
| // read the lines |
| nCounter = pLib->nVarsMax; |
| pProgress = Extra_ProgressBarStart( stdout, pLib->nLines ); |
| while ( fgets( pBuffer, 5000, pFile ) != NULL ) |
| { |
| for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); |
| if ( pTemp[0] == '\0' ) |
| continue; |
| // if ( pTemp[0] == 'a' || pTemp[2] == 'a' ) |
| // { |
| // pLib->nLines--; |
| // continue; |
| // } |
| |
| // get the gate |
| pGate = Map_LibraryReadGateTree( pLib, pTemp, nCounter, pLib->nVarsMax ); |
| if ( pGate == NULL ) |
| { |
| Extra_ProgressBarStop( pProgress ); |
| return 0; |
| } |
| pLib->ppSupers[nCounter++] = pGate; |
| // later we will derive: truth table, delays, area, number of component gates, etc |
| |
| // update the progress bar |
| Extra_ProgressBarUpdate( pProgress, nCounter, NULL ); |
| } |
| Extra_ProgressBarStop( pProgress ); |
| if ( nCounter != pLib->nLines ) |
| printf( "The number of lines read (%d) is different what the file says (%d).\n", nCounter, pLib->nLines ); |
| pLib->nSupersAll = nCounter; |
| // count the number of real supergates |
| nCounter = 0; |
| for ( k = 0; k < pLib->nLines; k++ ) |
| nCounter += pLib->ppSupers[k]->fSuper; |
| if ( nCounter != pLib->nSupersReal ) |
| printf( "The number of gates read (%d) is different what the file says (%d).\n", nCounter, pLib->nSupersReal ); |
| pLib->nSupersReal = nCounter; |
| return 1; |
| } |
| int Map_LibraryReadTree2( Map_SuperLib_t * pLib, char * pFileName, char * pExcludeFile ) |
| { |
| FILE * pFile; |
| int Status, num; |
| Abc_Frame_t * pAbc; |
| st__table * tExcludeGate = 0; |
| |
| // read the beginning of the file |
| assert( pLib->pGenlib == NULL ); |
| pFile = Io_FileOpen( pFileName, "open_path", "r", 1 ); |
| // pFile = fopen( pFileName, "r" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Cannot open input file \"%s\".\n", pFileName ); |
| return 0; |
| } |
| |
| if ( pExcludeFile ) |
| { |
| pAbc = Abc_FrameGetGlobalFrame(); |
| |
| tExcludeGate = st__init_table(strcmp, st__strhash); |
| if ( (num = Mio_LibraryReadExclude( pExcludeFile, tExcludeGate )) == -1 ) |
| { |
| st__free_table( tExcludeGate ); |
| tExcludeGate = 0; |
| return 0; |
| } |
| |
| fprintf ( Abc_FrameReadOut( pAbc ), "Read %d gates from exclude file\n", num ); |
| } |
| |
| Status = Map_LibraryReadFileTree( pLib, pFile, pFileName ); |
| fclose( pFile ); |
| if ( Status == 0 ) |
| return 0; |
| // prepare the info about the library |
| return Map_LibraryDeriveGateInfo( pLib, tExcludeGate ); |
| } |
| */ |
| |
| /**Function************************************************************* |
| |
| Synopsis [Similar to fgets.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Vec_StrGets( char * pBuffer, int nBufferSize, Vec_Str_t * vStr, int * pPos ) |
| { |
| char * pCur; |
| char * pBeg = Vec_StrArray(vStr) + *pPos; |
| char * pEnd = Vec_StrArray(vStr) + Vec_StrSize(vStr); |
| assert( nBufferSize > 1 ); |
| if ( pBeg == pEnd ) |
| { |
| *pBuffer = 0; |
| return 0; |
| } |
| assert( pBeg < pEnd ); |
| for ( pCur = pBeg; pCur < pEnd; pCur++ ) |
| { |
| *pBuffer++ = *pCur; |
| if ( *pCur == 0 ) |
| { |
| *pPos += pCur - pBeg; |
| return 0; |
| } |
| if ( *pCur == '\n' ) |
| { |
| *pPos += pCur - pBeg + 1; |
| *pBuffer = 0; |
| return 1; |
| } |
| if ( pCur - pBeg == nBufferSize-1 ) |
| { |
| *pPos += pCur - pBeg + 1; |
| *pBuffer = 0; |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Map_LibraryCompareLibNames( char * pName1, char * pName2 ) |
| { |
| char * p1 = Abc_UtilStrsav( pName1 ); |
| char * p2 = Abc_UtilStrsav( pName2 ); |
| int i, RetValue; |
| for ( i = 0; p1[i]; i++ ) |
| if ( p1[i] == '>' || p1[i] == '\\' || p1[i] == '/' ) |
| p1[i] = '/'; |
| for ( i = 0; p2[i]; i++ ) |
| if ( p2[i] == '>' || p2[i] == '\\' || p2[i] == '/' ) |
| p2[i] = '/'; |
| RetValue = strcmp( p1, p2 ); |
| ABC_FREE( p1 ); |
| ABC_FREE( p2 ); |
| return RetValue; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Reads the supergate library from file.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Map_LibraryReadFileTreeStr( Map_SuperLib_t * pLib, Mio_Library_t * pGenlib, Vec_Str_t * vStr, char * pFileName ) |
| { |
| ProgressBar * pProgress; |
| char pBuffer[5000]; |
| Map_Super_t * pGate; |
| char * pTemp = 0, * pLibName; |
| int nCounter, k, i; |
| int RetValue, nPos = 0; |
| |
| // skip empty and comment lines |
| // while ( fgets( pBuffer, 5000, pFile ) != NULL ) |
| while ( 1 ) |
| { |
| RetValue = Vec_StrGets( pBuffer, 5000, vStr, &nPos ); |
| if ( RetValue == 0 ) |
| return 0; |
| // skip leading spaces |
| for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); |
| // skip comment lines and empty lines |
| if ( *pTemp != 0 && *pTemp != '#' ) |
| break; |
| } |
| |
| pLibName = strtok( pTemp, " \t\r\n" ); |
| // pLib->pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen(); |
| pLib->pGenlib = pGenlib; |
| // if ( pLib->pGenlib == NULL || strcmp( , pLibName ) ) |
| if ( pLib->pGenlib == NULL || Map_LibraryCompareLibNames(Mio_LibraryReadName(pLib->pGenlib), pLibName) ) |
| { |
| printf( "Supergate library \"%s\" requires the use of genlib library \"%s\".\n", pFileName, pLibName ); |
| return 0; |
| } |
| |
| // read the number of variables |
| RetValue = Vec_StrGets( pBuffer, 5000, vStr, &nPos ); |
| if ( RetValue == 0 ) |
| return 0; |
| RetValue = sscanf( pBuffer, "%d\n", &pLib->nVarsMax ); |
| if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 ) |
| { |
| printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax ); |
| return 0; |
| } |
| |
| // read the number of gates |
| RetValue = Vec_StrGets( pBuffer, 5000, vStr, &nPos ); |
| if ( RetValue == 0 ) |
| return 0; |
| RetValue = sscanf( pBuffer, "%d\n", &pLib->nSupersReal ); |
| if ( pLib->nSupersReal < 1 || pLib->nSupersReal > 10000000 ) |
| { |
| printf( "Suspicious number of gates (%d).\n", pLib->nSupersReal ); |
| return 0; |
| } |
| |
| // read the number of lines |
| RetValue = Vec_StrGets( pBuffer, 5000, vStr, &nPos ); |
| if ( RetValue == 0 ) |
| return 0; |
| RetValue = sscanf( pBuffer, "%d\n", &pLib->nLines ); |
| if ( pLib->nLines < 1 || pLib->nLines > 10000000 ) |
| { |
| printf( "Suspicious number of lines (%d).\n", pLib->nLines ); |
| return 0; |
| } |
| |
| // allocate room for supergate pointers |
| pLib->ppSupers = ABC_ALLOC( Map_Super_t *, pLib->nLines + 10000 ); |
| |
| // create the elementary supergates |
| for ( i = 0; i < pLib->nVarsMax; i++ ) |
| { |
| // get a new gate |
| pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); |
| memset( pGate, 0, sizeof(Map_Super_t) ); |
| // assign the elementary variable, the truth table, and the delays |
| pGate->Num = i; |
| // set the truth table |
| pGate->uTruth[0] = pLib->uTruths[i][0]; |
| pGate->uTruth[1] = pLib->uTruths[i][1]; |
| // set the arrival times of all input to non-existent delay |
| for ( k = 0; k < pLib->nVarsMax; k++ ) |
| { |
| pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR; |
| pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR; |
| } |
| // set an existent arrival time for rise and fall |
| pGate->tDelaysR[i].Rise = 0.0; |
| pGate->tDelaysF[i].Fall = 0.0; |
| // set the gate |
| pLib->ppSupers[i] = pGate; |
| } |
| |
| // read the lines |
| nCounter = pLib->nVarsMax; |
| pProgress = Extra_ProgressBarStart( stdout, pLib->nLines ); |
| // while ( fgets( pBuffer, 5000, pFile ) != NULL ) |
| while ( Vec_StrGets( pBuffer, 5000, vStr, &nPos ) ) |
| { |
| for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); |
| if ( pTemp[0] == '\0' ) |
| continue; |
| // if ( pTemp[0] == 'a' || pTemp[2] == 'a' ) |
| // { |
| // pLib->nLines--; |
| // continue; |
| // } |
| |
| // get the gate |
| pGate = Map_LibraryReadGateTree( pLib, pTemp, nCounter, pLib->nVarsMax ); |
| if ( pGate == NULL ) |
| { |
| Extra_ProgressBarStop( pProgress ); |
| return 0; |
| } |
| pLib->ppSupers[nCounter++] = pGate; |
| // later we will derive: truth table, delays, area, number of component gates, etc |
| |
| // update the progress bar |
| Extra_ProgressBarUpdate( pProgress, nCounter, NULL ); |
| } |
| Extra_ProgressBarStop( pProgress ); |
| if ( nCounter != pLib->nLines ) |
| printf( "The number of lines read (%d) is different from what the file says (%d).\n", nCounter, pLib->nLines ); |
| pLib->nSupersAll = nCounter; |
| // count the number of real supergates |
| nCounter = 0; |
| for ( k = 0; k < pLib->nLines; k++ ) |
| nCounter += pLib->ppSupers[k]->fSuper; |
| if ( nCounter != pLib->nSupersReal ) |
| printf( "The number of gates read (%d) is different what the file says (%d).\n", nCounter, pLib->nSupersReal ); |
| pLib->nSupersReal = nCounter; |
| return 1; |
| } |
| int Map_LibraryReadTree( Map_SuperLib_t * pLib, Mio_Library_t * pGenlib, char * pFileName, char * pExcludeFile ) |
| { |
| char * pBuffer; |
| Vec_Str_t * vStr; |
| int Status, num; |
| Abc_Frame_t * pAbc; |
| st__table * tExcludeGate = 0; |
| |
| // read the beginning of the file |
| assert( pLib->pGenlib == NULL ); |
| // pFile = Io_FileOpen( pFileName, "open_path", "r", 1 ); |
| pBuffer = Mio_ReadFile( pFileName, 0 ); |
| if ( pBuffer == NULL ) |
| { |
| printf( "Cannot open input file \"%s\".\n", pFileName ); |
| return 0; |
| } |
| vStr = Vec_StrAllocArray( pBuffer, strlen(pBuffer) ); |
| |
| if ( pExcludeFile ) |
| { |
| pAbc = Abc_FrameGetGlobalFrame(); |
| |
| tExcludeGate = st__init_table(strcmp, st__strhash); |
| if ( (num = Mio_LibraryReadExclude( pExcludeFile, tExcludeGate )) == -1 ) |
| { |
| st__free_table( tExcludeGate ); |
| tExcludeGate = 0; |
| Vec_StrFree( vStr ); |
| return 0; |
| } |
| |
| fprintf ( Abc_FrameReadOut( pAbc ), "Read %d gates from exclude file\n", num ); |
| } |
| |
| Status = Map_LibraryReadFileTreeStr( pLib, pGenlib, vStr, pFileName ); |
| Vec_StrFree( vStr ); |
| if ( Status == 0 ) |
| return 0; |
| // prepare the info about the library |
| return Map_LibraryDeriveGateInfo( pLib, tExcludeGate ); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives information about the library.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st__table * tExcludeGate ) |
| { |
| Map_Super_t * pGate, * pFanin; |
| Mio_Pin_t * pPin; |
| unsigned uCanon[2]; |
| unsigned uTruths[6][2]; |
| int i, k, nRealVars; |
| |
| // set all the derivable info related to the supergates |
| for ( i = pLib->nVarsMax; i < (int)pLib->nLines; i++ ) |
| { |
| pGate = pLib->ppSupers[i]; |
| |
| if ( tExcludeGate ) |
| { |
| if ( st__is_member( tExcludeGate, Mio_GateReadName( pGate->pRoot ) ) ) |
| pGate->fExclude = 1; |
| for ( k = 0; k < (int)pGate->nFanins; k++ ) |
| { |
| pFanin = pGate->pFanins[k]; |
| if ( pFanin->fExclude ) |
| { |
| pGate->fExclude = 1; |
| continue; |
| } |
| } |
| } |
| |
| // collect the truth tables of the fanins |
| for ( k = 0; k < (int)pGate->nFanins; k++ ) |
| { |
| pFanin = pGate->pFanins[k]; |
| uTruths[k][0] = pFanin->uTruth[0]; |
| uTruths[k][1] = pFanin->uTruth[1]; |
| } |
| // derive the new truth table |
| Mio_DeriveTruthTable( pGate->pRoot, uTruths, pGate->nFanins, 6, pGate->uTruth ); |
| |
| // set the initial delays of the supergate |
| for ( k = 0; k < pLib->nVarsMax; k++ ) |
| { |
| pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR; |
| pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR; |
| } |
| // get the linked list of pins for the given root gate |
| pPin = Mio_GateReadPins( pGate->pRoot ); |
| // update the initial delay of the supergate using info from the corresponding pin |
| for ( k = 0; k < (int)pGate->nFanins; k++, pPin = Mio_PinReadNext(pPin) ) |
| { |
| // if there is no corresponding pin, this is a bug, return fail |
| if ( pPin == NULL ) |
| { |
| printf( "There are less pins than gate inputs.\n" ); |
| return 0; |
| } |
| // update the delay information of k-th fanins info from the corresponding pin |
| Map_LibraryAddFaninDelays( pLib, pGate, pGate->pFanins[k], pPin ); |
| } |
| // if there are some pins left, this is a bug, return fail |
| if ( pPin != NULL ) |
| { |
| printf( "There are more pins than gate inputs.\n" ); |
| return 0; |
| } |
| // find the max delay |
| pGate->tDelayMax.Rise = pGate->tDelayMax.Fall = MAP_NO_VAR; |
| for ( k = 0; k < pLib->nVarsMax; k++ ) |
| { |
| // the rise of the output depends on the rise and fall of the output |
| if ( pGate->tDelayMax.Rise < pGate->tDelaysR[k].Rise ) |
| pGate->tDelayMax.Rise = pGate->tDelaysR[k].Rise; |
| if ( pGate->tDelayMax.Rise < pGate->tDelaysR[k].Fall ) |
| pGate->tDelayMax.Rise = pGate->tDelaysR[k].Fall; |
| // the fall of the output depends on the rise and fall of the output |
| if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Rise ) |
| pGate->tDelayMax.Fall = pGate->tDelaysF[k].Rise; |
| if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Fall ) |
| pGate->tDelayMax.Fall = pGate->tDelaysF[k].Fall; |
| |
| pGate->tDelaysF[k].Worst = MAP_MAX( pGate->tDelaysF[k].Fall, pGate->tDelaysF[k].Rise ); |
| pGate->tDelaysR[k].Worst = MAP_MAX( pGate->tDelaysR[k].Fall, pGate->tDelaysR[k].Rise ); |
| } |
| |
| // count gates and area of the supergate |
| pGate->nGates = 1; |
| pGate->Area = (float)Mio_GateReadArea(pGate->pRoot); |
| for ( k = 0; k < (int)pGate->nFanins; k++ ) |
| { |
| pGate->nGates += pGate->pFanins[k]->nGates; |
| pGate->Area += pGate->pFanins[k]->Area; |
| } |
| // do not add the gate to the table, if this gate is an internal gate |
| // of some supegate and does not correspond to a supergate output |
| if ( ( !pGate->fSuper ) || pGate->fExclude ) |
| continue; |
| |
| // find the maximum index of a variable in the support of the supergates |
| // this is important for two reasons: |
| // (1) to limit the number of permutations considered for canonicization |
| // (2) to get rid of equivalence phases to speed-up matching |
| nRealVars = Map_LibraryGetMaxSuperPi_rec( pGate ) + 1; |
| assert( nRealVars > 0 && nRealVars <= pLib->nVarsMax ); |
| // if there are some problems with this code, try this instead |
| // nRealVars = pLib->nVarsMax; |
| |
| // find the N-canonical form of this supergate |
| pGate->nPhases = Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, nRealVars, pGate->uTruth, pGate->uPhases, uCanon ); |
| // add the supergate into the table by its N-canonical table |
| Map_SuperTableInsertC( pLib->tTableC, uCanon, pGate ); |
| /* |
| { |
| int uCanon1, uCanon2; |
| uCanon1 = uCanon[0]; |
| pGate->uTruth[0] = ~pGate->uTruth[0]; |
| pGate->uTruth[1] = ~pGate->uTruth[1]; |
| Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, nRealVars, pGate->uTruth, pGate->uPhases, uCanon ); |
| uCanon2 = uCanon[0]; |
| Rwt_Man5ExploreCount( uCanon1 < uCanon2 ? uCanon1 : uCanon2 ); |
| } |
| */ |
| } |
| // sort the gates in each line |
| Map_SuperTableSortSupergatesByDelay( pLib->tTableC, pLib->nSupersAll ); |
| |
| // let the glory be manifest |
| // Map_LibraryPrintTree( pLib ); |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Finds the largest PI number in the support of the supergate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Map_LibraryGetMaxSuperPi_rec( Map_Super_t * pGate ) |
| { |
| int i, VarCur, VarMax = 0; |
| if ( pGate->pRoot == NULL ) |
| return pGate->Num; |
| for ( i = 0; i < (int)pGate->nFanins; i++ ) |
| { |
| VarCur = Map_LibraryGetMaxSuperPi_rec( pGate->pFanins[i] ); |
| if ( VarMax < VarCur ) |
| VarMax = VarCur; |
| } |
| return VarMax; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Finds the largest PI number in the support of the supergate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate ) |
| { |
| unsigned uSupport; |
| int i; |
| if ( pGate->pRoot == NULL ) |
| return (unsigned)(1 << (pGate->Num)); |
| uSupport = 0; |
| for ( i = 0; i < (int)pGate->nFanins; i++ ) |
| uSupport |= Map_LibraryGetGateSupp_rec( pGate->pFanins[i] ); |
| return uSupport; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives the pin-to-pin delay constraints for the supergate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Map_LibraryAddFaninDelays( Map_SuperLib_t * pLib, Map_Super_t * pGate, Map_Super_t * pFanin, Mio_Pin_t * pPin ) |
| { |
| Mio_PinPhase_t PinPhase; |
| float tDelayBlockRise, tDelayBlockFall, tDelayPin; |
| int fMaxDelay = 0; |
| int i; |
| |
| // use this node to enable max-delay model |
| if ( fMaxDelay ) |
| { |
| float tDelayBlockMax; |
| // get the maximum delay |
| tDelayBlockMax = (float)Mio_PinReadDelayBlockMax(pPin); |
| // go through the supergate inputs |
| for ( i = 0; i < pLib->nVarsMax; i++ ) |
| { |
| if ( pFanin->tDelaysR[i].Rise < 0 ) |
| continue; |
| tDelayPin = pFanin->tDelaysR[i].Rise + tDelayBlockMax; |
| if ( pGate->tDelaysR[i].Rise < tDelayPin ) |
| pGate->tDelaysR[i].Rise = tDelayPin; |
| } |
| // go through the supergate inputs |
| for ( i = 0; i < pLib->nVarsMax; i++ ) |
| { |
| if ( pFanin->tDelaysF[i].Fall < 0 ) |
| continue; |
| tDelayPin = pFanin->tDelaysF[i].Fall + tDelayBlockMax; |
| if ( pGate->tDelaysF[i].Fall < tDelayPin ) |
| pGate->tDelaysF[i].Fall = tDelayPin; |
| } |
| return; |
| } |
| |
| // get the interesting parameters of this pin |
| PinPhase = Mio_PinReadPhase(pPin); |
| tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); |
| tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); |
| |
| // update the rise and fall of the output depending on the phase of the pin |
| if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present |
| { |
| // the rise of the gate is determined by the rise of the fanin |
| // the fall of the gate is determined by the fall of the fanin |
| for ( i = 0; i < pLib->nVarsMax; i++ ) |
| { |
| //////////////////////////////////////////////////////// |
| // consider the rise of the gate |
| //////////////////////////////////////////////////////// |
| // check two types of constraints on the rise of the fanin: |
| // (1) the constraints related to the rise of the PIs |
| // (2) the constraints related to the fall of the PIs |
| if ( pFanin->tDelaysR[i].Rise >= 0 ) // case (1) |
| { // fanin's rise depends on the rise of i-th PI |
| // update the rise of the gate's output |
| if ( pGate->tDelaysR[i].Rise < pFanin->tDelaysR[i].Rise + tDelayBlockRise ) |
| pGate->tDelaysR[i].Rise = pFanin->tDelaysR[i].Rise + tDelayBlockRise; |
| } |
| if ( pFanin->tDelaysR[i].Fall >= 0 ) // case (2) |
| { // fanin's rise depends on the fall of i-th PI |
| // update the rise of the gate's output |
| if ( pGate->tDelaysR[i].Fall < pFanin->tDelaysR[i].Fall + tDelayBlockRise ) |
| pGate->tDelaysR[i].Fall = pFanin->tDelaysR[i].Fall + tDelayBlockRise; |
| } |
| //////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////// |
| // consider the fall of the gate (similar) |
| //////////////////////////////////////////////////////// |
| // check two types of constraints on the fall of the fanin: |
| // (1) the constraints related to the rise of the PIs |
| // (2) the constraints related to the fall of the PIs |
| if ( pFanin->tDelaysF[i].Rise >= 0 ) // case (1) |
| { |
| if ( pGate->tDelaysF[i].Rise < pFanin->tDelaysF[i].Rise + tDelayBlockFall ) |
| pGate->tDelaysF[i].Rise = pFanin->tDelaysF[i].Rise + tDelayBlockFall; |
| } |
| if ( pFanin->tDelaysF[i].Fall >= 0 ) // case (2) |
| { |
| if ( pGate->tDelaysF[i].Fall < pFanin->tDelaysF[i].Fall + tDelayBlockFall ) |
| pGate->tDelaysF[i].Fall = pFanin->tDelaysF[i].Fall + tDelayBlockFall; |
| } |
| //////////////////////////////////////////////////////// |
| } |
| } |
| if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present |
| { |
| // the rise of the gate is determined by the fall of the fanin |
| // the fall of the gate is determined by the rise of the fanin |
| for ( i = 0; i < pLib->nVarsMax; i++ ) |
| { |
| //////////////////////////////////////////////////////// |
| // consider the rise of the gate's output |
| //////////////////////////////////////////////////////// |
| // check two types of constraints on the fall of the fanin: |
| // (1) the constraints related to the rise of the PIs |
| // (2) the constraints related to the fall of the PIs |
| if ( pFanin->tDelaysF[i].Rise >= 0 ) // case (1) |
| { // fanin's rise depends on the rise of i-th PI |
| // update the rise of the gate |
| if ( pGate->tDelaysR[i].Rise < pFanin->tDelaysF[i].Rise + tDelayBlockRise ) |
| pGate->tDelaysR[i].Rise = pFanin->tDelaysF[i].Rise + tDelayBlockRise; |
| } |
| if ( pFanin->tDelaysF[i].Fall >= 0 ) // case (2) |
| { // fanin's rise depends on the fall of i-th PI |
| // update the rise of the gate |
| if ( pGate->tDelaysR[i].Fall < pFanin->tDelaysF[i].Fall + tDelayBlockRise ) |
| pGate->tDelaysR[i].Fall = pFanin->tDelaysF[i].Fall + tDelayBlockRise; |
| } |
| //////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////// |
| // consider the fall of the gate (similar) |
| //////////////////////////////////////////////////////// |
| // check two types of constraints on the rise of the fanin: |
| // (1) the constraints related to the rise of the PIs |
| // (2) the constraints related to the fall of the PIs |
| if ( pFanin->tDelaysR[i].Rise >= 0 ) // case (1) |
| { |
| if ( pGate->tDelaysF[i].Rise < pFanin->tDelaysR[i].Rise + tDelayBlockFall ) |
| pGate->tDelaysF[i].Rise = pFanin->tDelaysR[i].Rise + tDelayBlockFall; |
| } |
| if ( pFanin->tDelaysR[i].Fall >= 0 ) // case (2) |
| { |
| if ( pGate->tDelaysF[i].Fall < pFanin->tDelaysR[i].Fall + tDelayBlockFall ) |
| pGate->tDelaysF[i].Fall = pFanin->tDelaysR[i].Fall + tDelayBlockFall; |
| } |
| //////////////////////////////////////////////////////// |
| } |
| } |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs phase transformation for one function.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| unsigned Map_CalculatePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase ) |
| { |
| int v, Shift; |
| for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) |
| if ( uPhase & Shift ) |
| uTruth = (((uTruth & ~uTruths[v][0]) << Shift) | ((uTruth & uTruths[v][0]) >> Shift)); |
| return uTruth; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs phase transformation for one function.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Map_CalculatePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] ) |
| { |
| unsigned uTemp; |
| int v, Shift; |
| |
| // initialize the result |
| uTruthRes[0] = uTruth[0]; |
| uTruthRes[1] = uTruth[1]; |
| if ( uPhase == 0 ) |
| return; |
| // compute the phase |
| for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) |
| if ( uPhase & Shift ) |
| { |
| if ( Shift < 32 ) |
| { |
| uTruthRes[0] = (((uTruthRes[0] & ~uTruths[v][0]) << Shift) | ((uTruthRes[0] & uTruths[v][0]) >> Shift)); |
| uTruthRes[1] = (((uTruthRes[1] & ~uTruths[v][1]) << Shift) | ((uTruthRes[1] & uTruths[v][1]) >> Shift)); |
| } |
| else |
| { |
| uTemp = uTruthRes[0]; |
| uTruthRes[0] = uTruthRes[1]; |
| uTruthRes[1] = uTemp; |
| } |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints the supergate library after deriving parameters.] |
| |
| Description [This procedure is very useful to see the library after |
| it has been read into the mapper by "read_super" and all the information |
| about the supergates derived.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Map_LibraryPrintTree( Map_SuperLib_t * pLib ) |
| { |
| Map_Super_t * pGate; |
| int i, k; |
| |
| // print all the info related to the supergates |
| // for ( i = pLib->nVarsMax; i < (int)pLib->nLines; i++ ) |
| for ( i = pLib->nVarsMax; i < 20; i++ ) |
| { |
| pGate = pLib->ppSupers[i]; |
| |
| // write the gate's fanin info and formula |
| printf( "%6d ", pGate->Num ); |
| printf( "%c ", pGate->fSuper? '*' : ' ' ); |
| printf( "%6s", Mio_GateReadName(pGate->pRoot) ); |
| for ( k = 0; k < (int)pGate->nFanins; k++ ) |
| printf( " %6d", pGate->pFanins[k]->Num ); |
| printf( " %s", pGate->pFormula ); |
| printf( "\n" ); |
| |
| // write the gate's derived info |
| Extra_PrintBinary( stdout, pGate->uTruth, 64 ); |
| printf( " %3d", pGate->nGates ); |
| printf( " %6.2f", pGate->Area ); |
| printf( " (%4.2f, %4.2f)", pGate->tDelayMax.Rise, pGate->tDelayMax.Fall ); |
| printf( "\n" ); |
| for ( k = 0; k < pLib->nVarsMax; k++ ) |
| { |
| // print the constraint on the rise of the gate in the form (D1, D2), |
| // where D1 is the constraint related to the rise of the k-th PI |
| // where D2 is the constraint related to the fall of the k-th PI |
| if ( pGate->tDelaysR[k].Rise < 0 && pGate->tDelaysR[k].Fall < 0 ) |
| printf( " (----, ----)" ); |
| else if ( pGate->tDelaysR[k].Fall < 0 ) |
| printf( " (%4.2f, ----)", pGate->tDelaysR[k].Rise ); |
| else if ( pGate->tDelaysR[k].Rise < 0 ) |
| printf( " (----, %4.2f)", pGate->tDelaysR[k].Fall ); |
| else |
| printf( " (%4.2f, %4.2f)", pGate->tDelaysR[k].Rise, pGate->tDelaysR[k].Fall ); |
| |
| // print the constraint on the fall of the gate in the form (D1, D2), |
| // where D1 is the constraint related to the rise of the k-th PI |
| // where D2 is the constraint related to the fall of the k-th PI |
| if ( pGate->tDelaysF[k].Rise < 0 && pGate->tDelaysF[k].Fall < 0 ) |
| printf( " (----, ----)" ); |
| else if ( pGate->tDelaysF[k].Fall < 0 ) |
| printf( " (%4.2f, ----)", pGate->tDelaysF[k].Rise ); |
| else if ( pGate->tDelaysF[k].Rise < 0 ) |
| printf( " (----, %4.2f)", pGate->tDelaysF[k].Fall ); |
| else |
| printf( " (%4.2f, %4.2f)", pGate->tDelaysF[k].Rise, pGate->tDelaysF[k].Fall ); |
| printf( "\n" ); |
| } |
| printf( "\n" ); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |