| /**CFile**************************************************************** |
| |
| FileName [superGate.c] |
| |
| PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] |
| |
| Synopsis [Pre-computation of supergates.] |
| |
| Author [MVSIS Group] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - September 8, 2003.] |
| |
| Revision [$Id: superGate.c,v 1.7 2004/08/03 00:11:40 satrajit Exp $] |
| |
| ***********************************************************************/ |
| |
| #include <math.h> |
| #include "superInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| // the bit masks |
| #define SUPER_MASK(n) ((~((unsigned)0)) >> (32-(n))) |
| #define SUPER_FULL (~((unsigned)0)) |
| #define SUPER_NO_VAR (-9999.0) |
| #define SUPER_EPSILON (0.001) |
| |
| // data structure for supergate precomputation |
| typedef struct Super_ManStruct_t_ Super_Man_t; // manager |
| typedef struct Super_GateStruct_t_ Super_Gate_t; // supergate |
| |
| struct Super_ManStruct_t_ |
| { |
| // parameters |
| char * pName; // the original genlib file name |
| int nVarsMax; // the number of inputs |
| int nMints; // the number of minterms |
| int nLevels; // the number of logic levels |
| int nGatesMax; // the number of gates computed |
| float tDelayMax; // the max delay of the supergates in the library |
| float tAreaMax; // the max area of the supergates in the library |
| int fSkipInv; // the flag says about skipping inverters |
| int fWriteOldFormat; // in addition, writes the file in the old format |
| int fVerbose; |
| |
| // supergates |
| Super_Gate_t * pInputs[10]; // the input supergates |
| int nGates; // the number of gates in the library |
| Super_Gate_t ** pGates; // the gates themselves |
| stmm_table * tTable; // mapping of truth tables into gates |
| |
| // memory managers |
| Extra_MmFixed_t * pMem; // memory manager for the supergates |
| Extra_MmFlex_t * pMemFlex; // memory manager for the fanin arrays |
| |
| // statistics |
| int nTried; // the total number of tried |
| int nAdded; // the number of entries added |
| int nRemoved; // the number of entries removed |
| int nClasses; // the number of gate classes |
| int nUnique; // the number of unique gates |
| int nLookups; // the number of hash table lookups |
| int nAliases; // the number of hash table lookups thrown away due to aliasing |
| |
| // runtime |
| abctime Time; // the runtime of the generation procedure |
| int TimeLimit; // the runtime limit (in seconds) |
| int TimeSec; // the time passed (in seconds) |
| abctime TimeStop; // the time to stop computation (in miliseconds) |
| abctime TimePrint; // the time to print message |
| }; |
| |
| struct Super_GateStruct_t_ |
| { |
| Mio_Gate_t * pRoot; // the root gate for this supergate |
| unsigned fVar : 1; // the flag signaling the elementary variable |
| unsigned fSuper : 1; // the flag signaling the elementary variable |
| unsigned nFanins : 6; // the number of fanin gates |
| unsigned Number : 24; // the number assigned in the process |
| unsigned uTruth[2]; // the truth table of this supergate |
| Super_Gate_t * pFanins[6]; // the fanins of the gate |
| float Area; // the area of this gate |
| float ptDelays[6]; // the pin-to-pin delays for all inputs |
| float tDelayMax; // the maximum delay |
| Super_Gate_t * pNext; // the next gate in the table |
| }; |
| |
| |
| // iterating through the gates in the library |
| #define Super_ManForEachGate( GateArray, Limit, Index, Gate ) \ |
| for ( Index = 0; \ |
| Index < Limit && (Gate = GateArray[Index]); \ |
| Index++ ) |
| |
| // static functions |
| static Super_Man_t * Super_ManStart(); |
| static void Super_ManStop( Super_Man_t * pMan ); |
| |
| static void Super_AddGateToTable( Super_Man_t * pMan, Super_Gate_t * pGate ); |
| static void Super_First( Super_Man_t * pMan, int nVarsMax ); |
| static Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGates, int nGatesMax, int fSkipInv ); |
| static Super_Gate_t * Super_CreateGateNew( Super_Man_t * pMan, Mio_Gate_t * pRoot, Super_Gate_t ** pSupers, int nSupers, unsigned uTruth[], float Area, float tPinDelaysRes[], float tDelayMax, int nPins ); |
| static int Super_CompareGates( Super_Man_t * pMan, unsigned uTruth[], float Area, float tPinDelaysRes[], int nPins ); |
| static int Super_DelayCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ); |
| static int Super_AreaCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ); |
| static void Super_TranferGatesToArray( Super_Man_t * pMan ); |
| static int Super_CheckTimeout( ProgressBar * pPro, Super_Man_t * pMan ); |
| |
| static Vec_Str_t * Super_Write( Super_Man_t * pMan ); |
| static int Super_WriteCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ); |
| static void Super_WriteFileHeader( Super_Man_t * pMan, FILE * pFile ); |
| |
| static void Super_WriteLibrary( Super_Man_t * pMan ); |
| |
| static void Super_WriteLibraryTreeFile( Super_Man_t * pMan ); |
| static Vec_Str_t * Super_WriteLibraryTreeStr( Super_Man_t * pMan ); |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Precomputes the library of supergates.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Super_Precompute( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, int nGatesMax, float tDelayMax, float tAreaMax, int TimeLimit, int fSkipInv, int fVerbose, char * pFileName ) |
| { |
| Vec_Str_t * vStr; |
| FILE * pFile = fopen( pFileName, "wb" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Cannot open output file \"%s\".\n", pFileName ); |
| return; |
| } |
| vStr = Super_PrecomputeStr( pLibGen, nVarsMax, nLevels, nGatesMax, tDelayMax, tAreaMax, TimeLimit, fSkipInv, fVerbose ); |
| fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile ); |
| fclose( pFile ); |
| Vec_StrFree( vStr ); |
| // report the result of writing |
| if ( fVerbose ) |
| { |
| printf( "The supergates are written using new format \"%s\" ", pFileName ); |
| printf( "(%0.3f MB).\n", ((double)Extra_FileSize(pFileName))/(1<<20) ); |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Precomputes the library of supergates.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Str_t * Super_PrecomputeStr( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, int nGatesMax, float tDelayMax, float tAreaMax, int TimeLimit, int fSkipInv, int fVerbose ) |
| { |
| Vec_Str_t * vStr; |
| Super_Man_t * pMan; |
| Mio_Gate_t ** ppGates; |
| int nGates, Level; |
| abctime clk, clockStart; |
| |
| assert( nVarsMax < 7 ); |
| if ( nGatesMax && nGatesMax < nVarsMax ) |
| { |
| fprintf( stderr, "Erro! The number of supergates requested (%d) in less than the number of variables (%d).\n", nGatesMax, nVarsMax ); |
| fprintf( stderr, "The library cannot be computed.\n" ); |
| return NULL; |
| } |
| |
| // get the root gates |
| ppGates = Mio_CollectRoots( pLibGen, nVarsMax, tDelayMax, 0, &nGates, fVerbose ); |
| if ( nGatesMax && nGates >= nGatesMax ) |
| { |
| fprintf( stdout, "Warning! Genlib library contains more gates than can be computed.\n"); |
| fprintf( stdout, "Only one-gate supergates are included in the supergate library.\n" ); |
| } |
| |
| // start the manager |
| pMan = Super_ManStart(); |
| pMan->pName = Mio_LibraryReadName(pLibGen); |
| pMan->nGatesMax = nGatesMax; |
| pMan->fSkipInv = fSkipInv; |
| pMan->tDelayMax = tDelayMax; |
| pMan->tAreaMax = tAreaMax; |
| pMan->TimeLimit = TimeLimit; // in seconds |
| pMan->TimeStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + Abc_Clock() : 0; // in CPU ticks |
| pMan->fVerbose = fVerbose; |
| |
| if ( nGates == 0 ) |
| { |
| fprintf( stderr, "Error: No genlib gates satisfy the limits criteria. Stop.\n"); |
| fprintf( stderr, "Limits: max delay = %.2f, max area = %.2f, time limit = %d sec.\n", |
| pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit ); |
| |
| // stop the manager |
| Super_ManStop( pMan ); |
| ABC_FREE( ppGates ); |
| |
| return NULL; |
| } |
| |
| // get the starting supergates |
| Super_First( pMan, nVarsMax ); |
| |
| // perform the computation of supergates |
| clockStart = Abc_Clock(); |
| if ( fVerbose ) |
| { |
| printf( "Computing supergates with %d inputs, %d levels, and %d max gates.\n", |
| pMan->nVarsMax, nLevels, nGatesMax ); |
| printf( "Limits: max delay = %.2f, max area = %.2f, time limit = %d sec.\n", |
| pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit ); |
| } |
| |
| for ( Level = 1; Level <= nLevels; Level++ ) |
| { |
| if ( pMan->TimeStop && Abc_Clock() > pMan->TimeStop ) |
| break; |
| clk = Abc_Clock(); |
| Super_Compute( pMan, ppGates, nGates, nGatesMax, fSkipInv ); |
| pMan->nLevels = Level; |
| if ( fVerbose ) |
| { |
| printf( "Lev %d: Try =%12d. Add =%6d. Rem =%5d. Save =%6d. Lookups =%12d. Aliases =%12d. ", |
| Level, pMan->nTried, pMan->nAdded, pMan->nRemoved, pMan->nAdded - pMan->nRemoved, pMan->nLookups, pMan->nAliases ); |
| ABC_PRT( "Time", Abc_Clock() - clk ); |
| fflush( stdout ); |
| } |
| } |
| pMan->Time = Abc_Clock() - clockStart; |
| |
| if ( fVerbose ) |
| { |
| printf( "Writing the output file...\n" ); |
| fflush( stdout ); |
| } |
| // write them into a file |
| vStr = Super_Write( pMan ); |
| |
| // stop the manager |
| Super_ManStop( pMan ); |
| ABC_FREE( ppGates ); |
| return vStr; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives the starting supergates.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Super_First( Super_Man_t * pMan, int nVarsMax ) |
| { |
| Super_Gate_t * pSuper; |
| int nMintLimit, nVarLimit; |
| int v, m; |
| // set the parameters |
| pMan->nVarsMax = nVarsMax; |
| pMan->nMints = (1 << nVarsMax); |
| pMan->nLevels = 0; |
| // allocate room for the gates |
| pMan->nGates = nVarsMax; |
| pMan->pGates = ABC_ALLOC( Super_Gate_t *, nVarsMax + 2 ); |
| // create the gates corresponding to the elementary variables |
| for ( v = 0; v < nVarsMax; v++ ) |
| { |
| // get a new gate |
| pSuper = (Super_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); |
| memset( pSuper, 0, sizeof(Super_Gate_t) ); |
| // assign the elementary variable, the truth table, and the delays |
| pSuper->fVar = 1; |
| pSuper->Number = v; |
| for ( m = 0; m < nVarsMax; m++ ) |
| pSuper->ptDelays[m] = SUPER_NO_VAR; |
| pSuper->ptDelays[v] = 0.0; |
| // set the gate |
| pMan->pGates[v] = pSuper; |
| Super_AddGateToTable( pMan, pSuper ); |
| pMan->pInputs[v] = pSuper; |
| } |
| // set up their truth tables |
| nVarLimit = (nVarsMax >= 5)? 5 : nVarsMax; |
| nMintLimit = (1 << nVarLimit); |
| for ( m = 0; m < nMintLimit; m++ ) |
| for ( v = 0; v < nVarLimit; v++ ) |
| if ( m & (1 << v) ) |
| pMan->pGates[v]->uTruth[0] |= (1 << m); |
| // make adjustments for the case of 6 variables |
| if ( nVarsMax == 6 ) |
| { |
| for ( v = 0; v < 5; v++ ) |
| pMan->pGates[v]->uTruth[1] = pMan->pGates[v]->uTruth[0]; |
| pMan->pGates[5]->uTruth[0] = 0; |
| pMan->pGates[5]->uTruth[1] = ~((unsigned)0); |
| } |
| else |
| { |
| for ( v = 0; v < nVarsMax; v++ ) |
| pMan->pGates[v]->uTruth[1] = 0; |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Precomputes one level of supergates.] |
| |
| Description [This procedure computes the set of supergates that can be |
| derived from the given set of root gates (from genlib library) by composing |
| the root gates with the currently available supergates. This procedure is |
| smart in the sense that it tries to avoid useless emuration by imposing |
| tight bounds by area and delay. Only the supergates and are guaranteed to |
| have smaller area and delay are enumereated. See comments below for details.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGates, int nGatesMax, int fSkipInv ) |
| { |
| Super_Gate_t * pSupers[6], * pGate0, * pGate1, * pGate2, * pGate3, * pGate4, * pGate5, * pGateNew; |
| float tPinDelaysRes[6], * ptPinDelays[6], tPinDelayMax, tDelayMio; |
| float Area = 0.0; // Suppress "might be used uninitialized" |
| float Area0, Area1, Area2, Area3, Area4, AreaMio; |
| unsigned uTruth[2], uTruths[6][2]; |
| int i0, i1, i2, i3, i4, i5; |
| Super_Gate_t ** ppGatesLimit; |
| int nFanins, nGatesLimit, k, s, t; |
| ProgressBar * pProgress; |
| int fTimeOut; |
| int fPrune = 1; // Shall we prune? |
| int iPruneLimit = 3; // Each of the gates plugged into the root gate will have |
| // less than these many fanins |
| int iPruneLimitRoot = 4; // The root gate may have only less than these many fanins |
| |
| // put the gates from the unique table into the array |
| // the gates from the array will be used to compose other gates |
| // the gates in tbe table are used to check uniqueness of collected gates |
| Super_TranferGatesToArray( pMan ); |
| |
| // sort the gates in the increasing order of maximum delay |
| if ( pMan->nGates > 10000 ) |
| { |
| printf( "Sorting array of %d supergates...\r", pMan->nGates ); |
| fflush( stdout ); |
| } |
| qsort( (void *)pMan->pGates, pMan->nGates, sizeof(Super_Gate_t *), |
| (int (*)(const void *, const void *)) Super_DelayCompare ); |
| assert( Super_DelayCompare( pMan->pGates, pMan->pGates + pMan->nGates - 1 ) <= 0 ); |
| if ( pMan->nGates > 10000 ) |
| { |
| printf( " \r" ); |
| } |
| |
| pProgress = Extra_ProgressBarStart( stdout, pMan->TimeLimit ); |
| pMan->TimePrint = Abc_Clock() + CLOCKS_PER_SEC; |
| ppGatesLimit = ABC_ALLOC( Super_Gate_t *, pMan->nGates ); |
| // go through the root gates |
| // the root gates are sorted in the increasing gelay |
| fTimeOut = 0; |
| for ( k = 0; k < nGates; k++ ) |
| { |
| if ( fTimeOut ) break; |
| |
| if ( fPrune ) |
| { |
| if ( pMan->nLevels >= 1 ) // First level gates have been computed |
| { |
| if ( Mio_GateReadPinNum(ppGates[k]) >= iPruneLimitRoot ) |
| continue; |
| } |
| } |
| /* |
| if ( strcmp(Mio_GateReadName(ppGates[k]), "MUX2IX0") == 0 ) |
| { |
| int s = 0; |
| } |
| */ |
| // select the subset of gates to be considered with this root gate |
| // all the gates past this point will lead to delay larger than the limit |
| tDelayMio = (float)Mio_GateReadDelayMax(ppGates[k]); |
| for ( s = 0, t = 0; s < pMan->nGates; s++ ) |
| { |
| if ( fPrune && ( pMan->nLevels >= 1 ) && ( ((int)pMan->pGates[s]->nFanins) >= iPruneLimit )) |
| continue; |
| |
| ppGatesLimit[t] = pMan->pGates[s]; |
| if ( ppGatesLimit[t++]->tDelayMax + tDelayMio > pMan->tDelayMax && pMan->tDelayMax > 0.0 ) |
| break; |
| } |
| nGatesLimit = t; |
| |
| if ( pMan->fVerbose ) |
| { |
| printf ("Trying %d choices for %d inputs\r", t, Mio_GateReadPinNum(ppGates[k]) ); |
| } |
| |
| // resort part of this range by area |
| // now we can prune the search by going up in the list until we reach the limit on area |
| // all the gates beyond this point can be skipped because their area can be only larger |
| if ( nGatesLimit > 10000 ) |
| printf( "Sorting array of %d supergates...\r", nGatesLimit ); |
| qsort( (void *)ppGatesLimit, nGatesLimit, sizeof(Super_Gate_t *), |
| (int (*)(const void *, const void *)) Super_AreaCompare ); |
| assert( Super_AreaCompare( ppGatesLimit, ppGatesLimit + nGatesLimit - 1 ) <= 0 ); |
| if ( nGatesLimit > 10000 ) |
| printf( " \r" ); |
| |
| // consider the combinations of gates with the root gate on top |
| AreaMio = (float)Mio_GateReadArea(ppGates[k]); |
| nFanins = Mio_GateReadPinNum(ppGates[k]); |
| switch ( nFanins ) |
| { |
| case 0: // should not happen |
| assert( 0 ); |
| break; |
| case 1: // interter root |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) |
| { |
| if ( fTimeOut ) break; |
| fTimeOut = Super_CheckTimeout( pProgress, pMan ); |
| // skip the inverter as the root gate before the elementary variable |
| // as a result, the supergates will not have inverters on the input side |
| // but inverters still may occur at the output of or inside complex supergates |
| if ( fSkipInv && pGate0->tDelayMax == 0 ) |
| continue; |
| // compute area |
| Area = AreaMio + pGate0->Area; |
| if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) |
| break; |
| |
| pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; |
| Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); |
| Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); |
| if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) |
| continue; |
| // create a new gate |
| pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); |
| Super_AddGateToTable( pMan, pGateNew ); |
| if ( nGatesMax && pMan->nClasses > nGatesMax ) |
| goto done; |
| } |
| break; |
| case 2: // two-input root gate |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) |
| { |
| Area0 = AreaMio + pGate0->Area; |
| if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax ) |
| break; |
| pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) |
| if ( i1 != i0 ) |
| { |
| if ( fTimeOut ) goto done; |
| fTimeOut = Super_CheckTimeout( pProgress, pMan ); |
| // compute area |
| Area = Area0 + pGate1->Area; |
| if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) |
| break; |
| |
| pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; |
| Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); |
| Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); |
| if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) |
| continue; |
| // create a new gate |
| pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); |
| Super_AddGateToTable( pMan, pGateNew ); |
| if ( nGatesMax && pMan->nClasses > nGatesMax ) |
| goto done; |
| } |
| } |
| break; |
| case 3: // three-input root gate |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) |
| { |
| Area0 = AreaMio + pGate0->Area; |
| if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax ) |
| break; |
| pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) |
| if ( i1 != i0 ) |
| { |
| Area1 = Area0 + pGate1->Area; |
| if ( pMan->tAreaMax > 0.0 && Area1 > pMan->tAreaMax ) |
| break; |
| pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) |
| if ( i2 != i0 && i2 != i1 ) |
| { |
| if ( fTimeOut ) goto done; |
| fTimeOut = Super_CheckTimeout( pProgress, pMan ); |
| // compute area |
| Area = Area1 + pGate2->Area; |
| if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) |
| break; |
| pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; |
| |
| Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); |
| Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); |
| if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) |
| continue; |
| // create a new gate |
| pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); |
| Super_AddGateToTable( pMan, pGateNew ); |
| if ( nGatesMax && pMan->nClasses > nGatesMax ) |
| goto done; |
| } |
| } |
| } |
| break; |
| case 4: // four-input root gate |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) |
| { |
| Area0 = AreaMio + pGate0->Area; |
| if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax ) |
| break; |
| pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) |
| if ( i1 != i0 ) |
| { |
| Area1 = Area0 + pGate1->Area; |
| if ( pMan->tAreaMax > 0.0 && Area1 > pMan->tAreaMax ) |
| break; |
| pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) |
| if ( i2 != i0 && i2 != i1 ) |
| { |
| Area2 = Area1 + pGate2->Area; |
| if ( pMan->tAreaMax > 0.0 && Area2 > pMan->tAreaMax ) |
| break; |
| pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 ) |
| if ( i3 != i0 && i3 != i1 && i3 != i2 ) |
| { |
| if ( fTimeOut ) goto done; |
| fTimeOut = Super_CheckTimeout( pProgress, pMan ); |
| // compute area |
| Area = Area2 + pGate3->Area; |
| if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) |
| break; |
| pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays; |
| |
| Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); |
| Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); |
| if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) |
| continue; |
| // create a new gate |
| pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); |
| Super_AddGateToTable( pMan, pGateNew ); |
| if ( nGatesMax && pMan->nClasses > nGatesMax ) |
| goto done; |
| } |
| } |
| } |
| } |
| break; |
| case 5: // five-input root gate |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) |
| { |
| Area0 = AreaMio + pGate0->Area; |
| if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax ) |
| break; |
| pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) |
| if ( i1 != i0 ) |
| { |
| Area1 = Area0 + pGate1->Area; |
| if ( pMan->tAreaMax > 0.0 && Area1 > pMan->tAreaMax ) |
| break; |
| pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) |
| if ( i2 != i0 && i2 != i1 ) |
| { |
| Area2 = Area1 + pGate2->Area; |
| if ( pMan->tAreaMax > 0.0 && Area2 > pMan->tAreaMax ) |
| break; |
| pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 ) |
| if ( i3 != i0 && i3 != i1 && i3 != i2 ) |
| { |
| Area3 = Area2 + pGate3->Area; |
| if ( pMan->tAreaMax > 0.0 && Area3 > pMan->tAreaMax ) |
| break; |
| pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i4, pGate4 ) |
| if ( i4 != i0 && i4 != i1 && i4 != i2 && i4 != i3 ) |
| { |
| if ( fTimeOut ) goto done; |
| fTimeOut = Super_CheckTimeout( pProgress, pMan ); |
| // compute area |
| Area = Area3 + pGate4->Area; |
| if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) |
| break; |
| pSupers[4] = pGate4; uTruths[4][0] = pGate4->uTruth[0]; uTruths[4][1] = pGate4->uTruth[1]; ptPinDelays[4] = pGate4->ptDelays; |
| |
| Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); |
| Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); |
| if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) |
| continue; |
| // create a new gate |
| pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); |
| Super_AddGateToTable( pMan, pGateNew ); |
| if ( nGatesMax && pMan->nClasses > nGatesMax ) |
| goto done; |
| } |
| } |
| } |
| } |
| } |
| break; |
| case 6: // six-input root gate |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) |
| { |
| Area0 = AreaMio + pGate0->Area; |
| if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax ) |
| break; |
| pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) |
| if ( i1 != i0 ) |
| { |
| Area1 = Area0 + pGate1->Area; |
| if ( pMan->tAreaMax > 0.0 && Area1 > pMan->tAreaMax ) |
| break; |
| pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) |
| if ( i2 != i0 && i2 != i1 ) |
| { |
| Area2 = Area1 + pGate2->Area; |
| if ( pMan->tAreaMax > 0.0 && Area2 > pMan->tAreaMax ) |
| break; |
| pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 ) |
| if ( i3 != i0 && i3 != i1 && i3 != i2 ) |
| { |
| Area3 = Area2 + pGate3->Area; |
| if ( pMan->tAreaMax > 0.0 && Area3 > pMan->tAreaMax ) |
| break; |
| pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i4, pGate4 ) |
| if ( i4 != i0 && i4 != i1 && i4 != i2 && i4 != i3 ) |
| { |
| if ( fTimeOut ) break; |
| fTimeOut = Super_CheckTimeout( pProgress, pMan ); |
| // compute area |
| Area4 = Area3 + pGate4->Area; |
| if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) |
| break; |
| pSupers[4] = pGate4; uTruths[4][0] = pGate4->uTruth[0]; uTruths[4][1] = pGate4->uTruth[1]; ptPinDelays[4] = pGate4->ptDelays; |
| |
| Super_ManForEachGate( ppGatesLimit, nGatesLimit, i5, pGate5 ) |
| if ( i5 != i0 && i5 != i1 && i5 != i2 && i5 != i3 && i5 != i4 ) |
| { |
| if ( fTimeOut ) goto done; |
| fTimeOut = Super_CheckTimeout( pProgress, pMan ); |
| // compute area |
| Area = Area4 + pGate5->Area; |
| if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) |
| break; |
| pSupers[5] = pGate5; uTruths[5][0] = pGate5->uTruth[0]; uTruths[5][1] = pGate5->uTruth[1]; ptPinDelays[5] = pGate5->ptDelays; |
| |
| Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); |
| Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); |
| if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) |
| continue; |
| // create a new gate |
| pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); |
| Super_AddGateToTable( pMan, pGateNew ); |
| if ( nGatesMax && pMan->nClasses > nGatesMax ) |
| goto done; |
| } |
| } |
| } |
| } |
| } |
| } |
| break; |
| default : |
| assert( 0 ); |
| break; |
| } |
| } |
| done: |
| Extra_ProgressBarStop( pProgress ); |
| ABC_FREE( ppGatesLimit ); |
| return pMan; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Transfers gates from table into the array.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Super_CheckTimeout( ProgressBar * pPro, Super_Man_t * pMan ) |
| { |
| abctime TimeNow = Abc_Clock(); |
| if ( TimeNow > pMan->TimePrint ) |
| { |
| Extra_ProgressBarUpdate( pPro, ++pMan->TimeSec, NULL ); |
| pMan->TimePrint = Abc_Clock() + CLOCKS_PER_SEC; |
| } |
| if ( pMan->TimeStop && TimeNow > pMan->TimeStop ) |
| { |
| printf ("Timeout!\n"); |
| return 1; |
| } |
| pMan->nTried++; |
| return 0; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Transfers gates from table into the array.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Super_TranferGatesToArray( Super_Man_t * pMan ) |
| { |
| stmm_generator * gen; |
| Super_Gate_t * pGate, * pList; |
| ABC_PTRUINT_T Key; |
| |
| // put the gates fron the table into the array |
| ABC_FREE( pMan->pGates ); |
| pMan->pGates = ABC_ALLOC( Super_Gate_t *, pMan->nAdded ); |
| pMan->nGates = 0; |
| stmm_foreach_item( pMan->tTable, gen, (char **)&Key, (char **)&pList ) |
| { |
| for ( pGate = pList; pGate; pGate = pGate->pNext ) |
| pMan->pGates[ pMan->nGates++ ] = pGate; |
| } |
| // assert( pMan->nGates == pMan->nAdded - pMan->nRemoved ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds one supergate into the unique table.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Super_AddGateToTable( Super_Man_t * pMan, Super_Gate_t * pGate ) |
| { |
| Super_Gate_t ** ppList; |
| ABC_PTRUINT_T Key; |
| // Key = pGate->uTruth[0] + 2003 * pGate->uTruth[1]; |
| Key = pGate->uTruth[0] ^ pGate->uTruth[1]; |
| if ( !stmm_find_or_add( pMan->tTable, (char *)Key, (char ***)&ppList ) ) |
| { |
| *ppList = NULL; |
| pMan->nClasses++; |
| } |
| pGate->pNext = *ppList; |
| *ppList = pGate; |
| pMan->nAdded++; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Check the manager's unique table for comparable gates.] |
| |
| Description [Returns 0 if the gate is dominated by others. Returns 1 |
| if the gate is new or is better than the available ones. In this case, |
| cleans the table by removing the gates that are worse than the given one.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Super_CompareGates( Super_Man_t * pMan, unsigned uTruth[], float Area, float tPinDelaysRes[], int nPins ) |
| { |
| Super_Gate_t ** ppList, * pPrev, * pGate, * pGate2; |
| int i, fNewIsBetter, fGateIsBetter; |
| ABC_PTRUINT_T Key; |
| |
| // skip constant functions |
| if ( pMan->nVarsMax < 6 ) |
| { |
| if ( uTruth[0] == 0 || ~uTruth[0] == 0 ) |
| return 0; |
| } |
| else |
| { |
| if ( ( uTruth[0] == 0 && uTruth[1] == 0 ) || ( ~uTruth[0] == 0 && ~uTruth[1] == 0 ) ) |
| return 0; |
| } |
| |
| // get hold of the place where the entry is stored |
| // Key = uTruth[0] + 2003 * uTruth[1]; |
| Key = uTruth[0] ^ uTruth[1]; |
| if ( !stmm_find( pMan->tTable, (char *)Key, (char ***)&ppList ) ) |
| return 1; |
| // the entry with this truth table is found |
| pPrev = NULL; |
| for ( pGate = *ppList, pGate2 = pGate? pGate->pNext: NULL; pGate; |
| pGate = pGate2, pGate2 = pGate? pGate->pNext: NULL ) |
| { |
| pMan->nLookups++; |
| if ( pGate->uTruth[0] != uTruth[0] || pGate->uTruth[1] != uTruth[1] ) |
| { |
| pMan->nAliases++; |
| continue; |
| } |
| fGateIsBetter = 0; |
| fNewIsBetter = 0; |
| if ( pGate->Area + SUPER_EPSILON < Area ) |
| fGateIsBetter = 1; |
| else if ( pGate->Area > Area + SUPER_EPSILON ) |
| fNewIsBetter = 1; |
| for ( i = 0; i < nPins; i++ ) |
| { |
| if ( pGate->ptDelays[i] == SUPER_NO_VAR || tPinDelaysRes[i] == SUPER_NO_VAR ) |
| continue; |
| if ( pGate->ptDelays[i] + SUPER_EPSILON < tPinDelaysRes[i] ) |
| fGateIsBetter = 1; |
| else if ( pGate->ptDelays[i] > tPinDelaysRes[i] + SUPER_EPSILON ) |
| fNewIsBetter = 1; |
| if ( fGateIsBetter && fNewIsBetter ) |
| break; |
| } |
| // consider 4 cases |
| if ( fGateIsBetter && fNewIsBetter ) // Pareto points; save both |
| pPrev = pGate; |
| else if ( fNewIsBetter ) // gate is worse; remove the gate |
| { |
| if ( pPrev == NULL ) |
| *ppList = pGate->pNext; |
| else |
| pPrev->pNext = pGate->pNext; |
| Extra_MmFixedEntryRecycle( pMan->pMem, (char *)pGate ); |
| pMan->nRemoved++; |
| } |
| else if ( fGateIsBetter ) // new is worse, already dominated no need to see others |
| return 0; |
| else // if ( !fGateIsBetter && !fNewIsBetter ) // they are identical, no need to see others |
| return 0; |
| } |
| return 1; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Create a new supergate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Super_Gate_t * Super_CreateGateNew( Super_Man_t * pMan, Mio_Gate_t * pRoot, Super_Gate_t ** pSupers, int nSupers, |
| unsigned uTruth[], float Area, float tPinDelaysRes[], float tDelayMax, int nPins ) |
| { |
| Super_Gate_t * pSuper; |
| pSuper = (Super_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); |
| memset( pSuper, 0, sizeof(Super_Gate_t) ); |
| pSuper->pRoot = pRoot; |
| pSuper->uTruth[0] = uTruth[0]; |
| pSuper->uTruth[1] = uTruth[1]; |
| memcpy( pSuper->ptDelays, tPinDelaysRes, sizeof(float) * nPins ); |
| pSuper->Area = Area; |
| pSuper->nFanins = nSupers; |
| memcpy( pSuper->pFanins, pSupers, sizeof(Super_Gate_t *) * nSupers ); |
| pSuper->pNext = NULL; |
| pSuper->tDelayMax = tDelayMax; |
| return pSuper; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Starts the manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Super_Man_t * Super_ManStart() |
| { |
| Super_Man_t * pMan; |
| pMan = ABC_CALLOC( Super_Man_t, 1 ); |
| pMan->pMem = Extra_MmFixedStart( sizeof(Super_Gate_t) ); |
| pMan->tTable = stmm_init_table( st__ptrcmp, st__ptrhash ); |
| return pMan; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Stops the manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Super_ManStop( Super_Man_t * pMan ) |
| { |
| Extra_MmFixedStop( pMan->pMem ); |
| if ( pMan->tTable ) stmm_free_table( pMan->tTable ); |
| ABC_FREE( pMan->pGates ); |
| ABC_FREE( pMan ); |
| } |
| |
| |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Writes the supergate library into the file.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Str_t * Super_Write( Super_Man_t * pMan ) |
| { |
| Vec_Str_t * vStr; |
| Super_Gate_t * pGateRoot, * pGate; |
| stmm_generator * gen; |
| int fZeroFound, v; |
| abctime clk; |
| ABC_PTRUINT_T Key; |
| |
| if ( pMan->nGates < 1 ) |
| { |
| printf( "The generated library is empty. No output file written.\n" ); |
| return NULL; |
| } |
| |
| // Filters the supergates by removing those that have fewer inputs than |
| // the given limit, provided that the inputs are not consequtive. |
| // For example, NAND2(a,c) is removed, but NAND2(a,b) is left, |
| // because a and b are consequtive. |
| ABC_FREE( pMan->pGates ); |
| pMan->pGates = ABC_ALLOC( Super_Gate_t *, pMan->nAdded ); |
| pMan->nGates = 0; |
| stmm_foreach_item( pMan->tTable, gen, (char **)&Key, (char **)&pGateRoot ) |
| { |
| for ( pGate = pGateRoot; pGate; pGate = pGate->pNext ) |
| { |
| // skip the elementary variables |
| if ( pGate->pRoot == NULL ) |
| continue; |
| // skip the non-consequtive gates |
| fZeroFound = 0; |
| for ( v = 0; v < pMan->nVarsMax; v++ ) |
| if ( pGate->ptDelays[v] < SUPER_NO_VAR + SUPER_EPSILON ) |
| fZeroFound = 1; |
| else if ( fZeroFound ) |
| break; |
| if ( v < pMan->nVarsMax ) |
| continue; |
| // save the unique gate |
| pMan->pGates[ pMan->nGates++ ] = pGate; |
| } |
| } |
| |
| clk = Abc_Clock(); |
| // sort the supergates by truth table |
| qsort( (void *)pMan->pGates, pMan->nGates, sizeof(Super_Gate_t *), |
| (int (*)(const void *, const void *)) Super_WriteCompare ); |
| assert( Super_WriteCompare( pMan->pGates, pMan->pGates + pMan->nGates - 1 ) <= 0 ); |
| if ( pMan->fVerbose ) |
| { |
| ABC_PRT( "Sorting", Abc_Clock() - clk ); |
| } |
| |
| |
| // write library in the old format |
| clk = Abc_Clock(); |
| if ( pMan->fWriteOldFormat ) |
| Super_WriteLibrary( pMan ); |
| if ( pMan->fVerbose ) |
| { |
| ABC_PRT( "Writing old format", Abc_Clock() - clk ); |
| } |
| |
| // write the tree-like structure of supergates |
| clk = Abc_Clock(); |
| vStr = Super_WriteLibraryTreeStr( pMan ); |
| if ( pMan->fVerbose ) |
| { |
| ABC_PRT( "Writing new format", Abc_Clock() - clk ); |
| } |
| return vStr; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Writes the file header.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Super_WriteFileHeader( Super_Man_t * pMan, FILE * pFile ) |
| { |
| fprintf( pFile, "#\n" ); |
| fprintf( pFile, "# Supergate library derived for \"%s\" on %s.\n", pMan->pName, Extra_TimeStamp() ); |
| fprintf( pFile, "#\n" ); |
| fprintf( pFile, "# Command line: \"super -I %d -L %d -N %d -T %d -D %.2f -A %.2f %s %s\".\n", |
| pMan->nVarsMax, pMan->nLevels, pMan->nGatesMax, pMan->TimeLimit, pMan->tDelayMax, pMan->tAreaMax, (pMan->fSkipInv? "" : "-s"), pMan->pName ); |
| fprintf( pFile, "#\n" ); |
| fprintf( pFile, "# The number of inputs = %10d.\n", pMan->nVarsMax ); |
| fprintf( pFile, "# The number of levels = %10d.\n", pMan->nLevels ); |
| fprintf( pFile, "# The maximum delay = %10.2f.\n", pMan->tDelayMax ); |
| fprintf( pFile, "# The maximum area = %10.2f.\n", pMan->tAreaMax ); |
| fprintf( pFile, "# The maximum runtime (sec) = %10d.\n", pMan->TimeLimit ); |
| fprintf( pFile, "#\n" ); |
| fprintf( pFile, "# The number of attempts = %10d.\n", pMan->nTried ); |
| fprintf( pFile, "# The number of supergates = %10d.\n", pMan->nGates ); |
| fprintf( pFile, "# The number of functions = %10d.\n", pMan->nUnique ); |
| fprintf( pFile, "# The total functions = %.0f (2^%d).\n", pow((double)2,pMan->nMints), pMan->nMints ); |
| fprintf( pFile, "#\n" ); |
| fprintf( pFile, "# Generation time = %10.2f sec.\n", (float)(pMan->Time)/(float)(CLOCKS_PER_SEC) ); |
| fprintf( pFile, "#\n" ); |
| fprintf( pFile, "%s\n", pMan->pName ); |
| fprintf( pFile, "%d\n", pMan->nVarsMax ); |
| fprintf( pFile, "%d\n", pMan->nGates ); |
| } |
| void Super_WriteFileHeaderStr( Super_Man_t * pMan, Vec_Str_t * vStr ) |
| { |
| char pBuffer[1000]; |
| sprintf( pBuffer, "#\n" ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "# Supergate library derived for \"%s\" on %s.\n", pMan->pName, Extra_TimeStamp() ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "#\n" ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "# Command line: \"super -I %d -L %d -N %d -T %d -D %.2f -A %.2f %s %s\".\n", |
| pMan->nVarsMax, pMan->nLevels, pMan->nGatesMax, pMan->TimeLimit, pMan->tDelayMax, pMan->tAreaMax, (pMan->fSkipInv? "" : "-s"), pMan->pName ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "#\n" ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "# The number of inputs = %10d.\n", pMan->nVarsMax ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "# The number of levels = %10d.\n", pMan->nLevels ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "# The maximum delay = %10.2f.\n", pMan->tDelayMax ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "# The maximum area = %10.2f.\n", pMan->tAreaMax ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "# The maximum runtime (sec) = %10d.\n", pMan->TimeLimit ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "#\n" ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "# The number of attempts = %10d.\n", pMan->nTried ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "# The number of supergates = %10d.\n", pMan->nGates ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "# The number of functions = %10d.\n", pMan->nUnique ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "# The total functions = %.0f (2^%d).\n", pow((double)2,pMan->nMints), pMan->nMints ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "#\n" ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "# Generation time = %10.2f sec.\n", (float)(pMan->Time)/(float)(CLOCKS_PER_SEC) ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "#\n" ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "%s\n", pMan->pName ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "%d\n", pMan->nVarsMax ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| sprintf( pBuffer, "%d\n", pMan->nGates ); |
| Vec_StrPrintStr( vStr, pBuffer ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compares two gates.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Super_WriteCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ) |
| { |
| unsigned * pTruth1 = (*ppG1)->uTruth; |
| unsigned * pTruth2 = (*ppG2)->uTruth; |
| if ( pTruth1[1] < pTruth2[1] ) |
| return -1; |
| if ( pTruth1[1] > pTruth2[1] ) |
| return 1; |
| if ( pTruth1[0] < pTruth2[0] ) |
| return -1; |
| if ( pTruth1[0] > pTruth2[0] ) |
| return 1; |
| return 0; |
| } |
| int Super_DelayCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ) |
| { |
| if ( (*ppG1)->tDelayMax < (*ppG2)->tDelayMax ) |
| return -1; |
| if ( (*ppG1)->tDelayMax > (*ppG2)->tDelayMax ) |
| return 1; |
| return 0; |
| } |
| int Super_AreaCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ) |
| { |
| if ( (*ppG1)->Area < (*ppG2)->Area ) |
| return -1; |
| if ( (*ppG1)->Area > (*ppG2)->Area ) |
| return 1; |
| return 0; |
| } |
| |
| |
| |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Writes the gates into the file.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Super_WriteLibraryGateName_rec( Super_Gate_t * pGate, char * pBuffer ) |
| { |
| char Buffer[10]; |
| int i; |
| |
| if ( pGate->pRoot == NULL ) |
| { |
| sprintf( Buffer, "%c", 'a' + pGate->Number ); |
| strcat( pBuffer, Buffer ); |
| return; |
| } |
| strcat( pBuffer, Mio_GateReadName(pGate->pRoot) ); |
| strcat( pBuffer, "(" ); |
| for ( i = 0; i < (int)pGate->nFanins; i++ ) |
| { |
| if ( i ) |
| strcat( pBuffer, "," ); |
| Super_WriteLibraryGateName_rec( pGate->pFanins[i], pBuffer ); |
| } |
| strcat( pBuffer, ")" ); |
| } |
| char * Super_WriteLibraryGateName( Super_Gate_t * pGate ) |
| { |
| static char Buffer[2000]; |
| Buffer[0] = 0; |
| Super_WriteLibraryGateName_rec( pGate, Buffer ); |
| return Buffer; |
| } |
| void Super_WriteLibraryGate( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pGate, int Num ) |
| { |
| int i; |
| fprintf( pFile, "%04d ", Num ); // the number |
| Extra_PrintBinary( pFile, pGate->uTruth, pMan->nMints ); // the truth table |
| fprintf( pFile, " %5.2f", pGate->tDelayMax ); // the max delay |
| fprintf( pFile, " " ); |
| for ( i = 0; i < pMan->nVarsMax; i++ ) // the pin-to-pin delays |
| fprintf( pFile, " %5.2f", pGate->ptDelays[i]==SUPER_NO_VAR? 0.0 : pGate->ptDelays[i] ); |
| fprintf( pFile, " %5.2f", pGate->Area ); // the area |
| fprintf( pFile, " " ); |
| fprintf( pFile, "%s", Super_WriteLibraryGateName(pGate) ); // the symbolic expression |
| fprintf( pFile, "\n" ); |
| } |
| void Super_WriteLibrary( Super_Man_t * pMan ) |
| { |
| Super_Gate_t * pGate, * pGateNext; |
| FILE * pFile; |
| char * FileName; |
| char * pNameGeneric; |
| int i, Counter; |
| |
| FileName = ABC_ALLOC( char, 10000 ); |
| |
| // get the file name |
| pNameGeneric = Extra_FileNameGeneric( pMan->pName ); |
| sprintf( FileName, "%s.super_old", pNameGeneric ); |
| ABC_FREE( pNameGeneric ); |
| |
| // count the number of unique functions |
| pMan->nUnique = 1; |
| Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pGate ) |
| { |
| if ( i == pMan->nGates - 1 ) |
| break; |
| // print the newline if this gate is different from the following one |
| pGateNext = pMan->pGates[i+1]; |
| if ( pGateNext->uTruth[0] != pGate->uTruth[0] || pGateNext->uTruth[1] != pGate->uTruth[1] ) |
| pMan->nUnique++; |
| } |
| |
| // start the file |
| pFile = fopen( FileName, "w" ); |
| Super_WriteFileHeader( pMan, pFile ); |
| |
| // print the gates |
| Counter = 0; |
| Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pGate ) |
| { |
| Super_WriteLibraryGate( pFile, pMan, pGate, ++Counter ); |
| if ( i == pMan->nGates - 1 ) |
| break; |
| // print the newline if this gate is different from the following one |
| pGateNext = pMan->pGates[i+1]; |
| if ( pGateNext->uTruth[0] != pGate->uTruth[0] || pGateNext->uTruth[1] != pGate->uTruth[1] ) |
| fprintf( pFile, "\n" ); |
| } |
| assert( Counter == pMan->nGates ); |
| fclose( pFile ); |
| |
| if ( pMan->fVerbose ) |
| { |
| printf( "The supergates are written using old format \"%s\" ", FileName ); |
| printf( "(%0.3f MB).\n", ((double)Extra_FileSize(FileName))/(1<<20) ); |
| } |
| |
| ABC_FREE( FileName ); |
| } |
| |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Recursively writes the gates.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Super_WriteLibraryTreeFile_rec( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter ) |
| { |
| int nFanins, i; |
| // skip an elementary variable and a gate that was already written |
| if ( pSuper->fVar || pSuper->Number > 0 ) |
| return; |
| // write the fanins |
| nFanins = Mio_GateReadPinNum(pSuper->pRoot); |
| for ( i = 0; i < nFanins; i++ ) |
| Super_WriteLibraryTreeFile_rec( pFile, pMan, pSuper->pFanins[i], pCounter ); |
| // finally write the gate |
| pSuper->Number = (*pCounter)++; |
| fprintf( pFile, "%s", pSuper->fSuper? "* " : "" ); |
| fprintf( pFile, "%s", Mio_GateReadName(pSuper->pRoot) ); |
| for ( i = 0; i < nFanins; i++ ) |
| fprintf( pFile, " %d", pSuper->pFanins[i]->Number ); |
| // write the formula |
| // this step is optional, the resulting library will work in any case |
| // however, it may be helpful to for debugging to compare the same library |
| // written in the old format and written in the new format with formulas |
| // fprintf( pFile, " # %s", Super_WriteLibraryGateName( pSuper ) ); |
| fprintf( pFile, "\n" ); |
| } |
| void Super_WriteLibraryTreeFile( Super_Man_t * pMan ) |
| { |
| Super_Gate_t * pSuper; |
| FILE * pFile; |
| char * FileName; |
| char * pNameGeneric; |
| int i, Counter; |
| int posStart; |
| |
| FileName = ABC_ALLOC( char, 10000 ); |
| |
| // get the file name |
| pNameGeneric = Extra_FileNameGeneric( pMan->pName ); |
| sprintf( FileName, "%s.super", pNameGeneric ); |
| ABC_FREE( pNameGeneric ); |
| |
| // write the elementary variables |
| pFile = fopen( FileName, "wb" ); |
| Super_WriteFileHeader( pMan, pFile ); |
| // write the place holder for the number of lines |
| posStart = ftell( pFile ); |
| fprintf( pFile, " \n" ); |
| // mark the real supergates |
| Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper ) |
| pSuper->fSuper = 1; |
| // write the supergates |
| Counter = pMan->nVarsMax; |
| Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper ) |
| Super_WriteLibraryTreeFile_rec( pFile, pMan, pSuper, &Counter ); |
| fclose( pFile ); |
| // write the number of lines |
| pFile = fopen( FileName, "rb+" ); |
| fseek( pFile, posStart, SEEK_SET ); |
| fprintf( pFile, "%d", Counter ); |
| fclose( pFile ); |
| |
| if ( pMan->fVerbose ) |
| { |
| printf( "The supergates are written using new format \"%s\" ", FileName ); |
| printf( "(%0.3f MB).\n", ((double)Extra_FileSize(FileName))/(1<<20) ); |
| } |
| |
| ABC_FREE( FileName ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Recursively writes the gates.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Super_WriteLibraryTreeStr_rec( Vec_Str_t * vStr, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter ) |
| { |
| int nFanins, i; |
| // skip an elementary variable and a gate that was already written |
| if ( pSuper->fVar || pSuper->Number > 0 ) |
| return; |
| // write the fanins |
| nFanins = Mio_GateReadPinNum(pSuper->pRoot); |
| for ( i = 0; i < nFanins; i++ ) |
| Super_WriteLibraryTreeStr_rec( vStr, pMan, pSuper->pFanins[i], pCounter ); |
| // finally write the gate |
| pSuper->Number = (*pCounter)++; |
| // fprintf( pFile, "%s", pSuper->fSuper? "* " : "" ); |
| // fprintf( pFile, "%s", Mio_GateReadName(pSuper->pRoot) ); |
| // for ( i = 0; i < nFanins; i++ ) |
| // fprintf( pFile, " %d", pSuper->pFanins[i]->Number ); |
| Vec_StrPrintStr( vStr, pSuper->fSuper? "* " : "" ); |
| Vec_StrPrintStr( vStr, Mio_GateReadName(pSuper->pRoot) ); |
| for ( i = 0; i < nFanins; i++ ) |
| { |
| Vec_StrPrintStr( vStr, " " ); |
| Vec_StrPrintNum( vStr, pSuper->pFanins[i]->Number ); |
| } |
| // write the formula |
| // this step is optional, the resulting library will work in any case |
| // however, it may be helpful to for debugging to compare the same library |
| // written in the old format and written in the new format with formulas |
| // fprintf( pFile, " # %s", Super_WriteLibraryGateName( pSuper ) ); |
| // fprintf( pFile, "\n" ); |
| Vec_StrPrintStr( vStr, "\n" ); |
| } |
| Vec_Str_t * Super_WriteLibraryTreeStr( Super_Man_t * pMan ) |
| { |
| char pInsert[16]; |
| Vec_Str_t * vStr; |
| Super_Gate_t * pSuper; |
| int i, Counter; |
| int posStart; |
| // write the elementary variables |
| vStr = Vec_StrAlloc( 1000 ); |
| Super_WriteFileHeaderStr( pMan, vStr ); |
| // write the place holder for the number of lines |
| posStart = Vec_StrSize( vStr ); |
| for ( i = 0; i < 9; i++ ) |
| Vec_StrPush( vStr, ' ' ); |
| Vec_StrPush( vStr, '\n' ); |
| // mark the real supergates |
| Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper ) |
| pSuper->fSuper = 1; |
| // write the supergates |
| Counter = pMan->nVarsMax; |
| Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper ) |
| Super_WriteLibraryTreeStr_rec( vStr, pMan, pSuper, &Counter ); |
| Vec_StrPush( vStr, 0 ); |
| // write the number of lines |
| sprintf( pInsert, "%d", Counter ); |
| for ( i = 0; i < (int)strlen(pInsert); i++ ) |
| Vec_StrWriteEntry( vStr, posStart + i, pInsert[i] ); |
| return vStr; |
| } |
| void Super_WriteLibraryTree( Super_Man_t * pMan ) |
| { |
| Vec_Str_t * vStr; |
| char * pFileName = Extra_FileNameGenericAppend( pMan->pName, ".super" ); |
| FILE * pFile = fopen( pFileName, "wb" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Cannot open output file \"%s\".\n", pFileName ); |
| return; |
| } |
| vStr = Super_WriteLibraryTreeStr( pMan ); |
| fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile ); |
| fclose( pFile ); |
| Vec_StrFree( vStr ); |
| // report the result of writing |
| if ( pMan->fVerbose ) |
| { |
| printf( "The supergates are written using new format \"%s\" ", pFileName ); |
| printf( "(%0.3f MB).\n", ((double)Extra_FileSize(pFileName))/(1<<20) ); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| ABC_NAMESPACE_IMPL_END |
| |