mirror of https://github.com/YosysHQ/abc.git
1045 lines
32 KiB
C
1045 lines
32 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [mioUtils.c]
|
|
|
|
PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
|
|
|
|
Synopsis [File reading/writing for technology mapping.]
|
|
|
|
Author [MVSIS Group]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - September 8, 2003.]
|
|
|
|
Revision [$Id: mioUtils.c,v 1.6 2004/09/03 18:02:20 satrajit Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include <math.h>
|
|
#include "mioInt.h"
|
|
#include "base/main/main.h"
|
|
#include "exp.h"
|
|
#include "misc/util/utilTruth.h"
|
|
#include "opt/dau/dau.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_LibraryDelete( Mio_Library_t * pLib )
|
|
{
|
|
Mio_Gate_t * pGate, * pGate2;
|
|
if ( pLib == NULL )
|
|
return;
|
|
// free the bindings of nodes to gates from this library for all networks
|
|
Abc_FrameUnmapAllNetworks( Abc_FrameGetGlobalFrame() );
|
|
// free the library
|
|
ABC_FREE( pLib->pName );
|
|
Mio_LibraryForEachGateSafe( pLib, pGate, pGate2 )
|
|
Mio_GateDelete( pGate );
|
|
Mem_FlexStop( pLib->pMmFlex, 0 );
|
|
Vec_StrFree( pLib->vCube );
|
|
if ( pLib->tName2Gate )
|
|
st__free_table( pLib->tName2Gate );
|
|
// if ( pLib->dd )
|
|
// Cudd_Quit( pLib->dd );
|
|
ABC_FREE( pLib->ppGates0 );
|
|
ABC_FREE( pLib->ppGatesName );
|
|
ABC_FREE( pLib );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_GateDelete( Mio_Gate_t * pGate )
|
|
{
|
|
Mio_Pin_t * pPin, * pPin2;
|
|
if ( pGate->nInputs > 6 )
|
|
ABC_FREE( pGate->pTruth );
|
|
Vec_IntFreeP( &pGate->vExpr );
|
|
ABC_FREE( pGate->pOutName );
|
|
ABC_FREE( pGate->pName );
|
|
ABC_FREE( pGate->pForm );
|
|
// if ( pGate->bFunc )
|
|
// Cudd_RecursiveDeref( pGate->pLib->dd, pGate->bFunc );
|
|
Mio_GateForEachPinSafe( pGate, pPin, pPin2 )
|
|
Mio_PinDelete( pPin );
|
|
ABC_FREE( pGate );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_PinDelete( Mio_Pin_t * pPin )
|
|
{
|
|
ABC_FREE( pPin->pName );
|
|
ABC_FREE( pPin );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin )
|
|
{
|
|
Mio_Pin_t * pPinNew;
|
|
|
|
pPinNew = ABC_ALLOC( Mio_Pin_t, 1 );
|
|
*pPinNew = *pPin;
|
|
pPinNew->pName = (pPinNew->pName ? Abc_UtilStrsav(pPinNew->pName) : NULL);
|
|
pPinNew->pNext = NULL;
|
|
|
|
return pPinNew;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Check if pin characteristics are the same.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Mio_CheckPins( Mio_Pin_t * pPin1, Mio_Pin_t * pPin2 )
|
|
{
|
|
if ( pPin1 == NULL || pPin2 == NULL )
|
|
return 1;
|
|
if ( pPin1->dLoadInput != pPin2->dLoadInput )
|
|
return 0;
|
|
if ( pPin1->dLoadMax != pPin2->dLoadMax )
|
|
return 0;
|
|
if ( pPin1->dDelayBlockRise != pPin2->dDelayBlockRise )
|
|
return 0;
|
|
if ( pPin1->dDelayFanoutRise != pPin2->dDelayFanoutRise )
|
|
return 0;
|
|
if ( pPin1->dDelayBlockFall != pPin2->dDelayBlockFall )
|
|
return 0;
|
|
if ( pPin1->dDelayFanoutFall != pPin2->dDelayFanoutFall )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
int Mio_CheckGates( Mio_Library_t * pLib )
|
|
{
|
|
Mio_Gate_t * pGate;
|
|
Mio_Pin_t * pPin0 = NULL, * pPin = NULL;
|
|
Mio_LibraryForEachGate( pLib, pGate )
|
|
Mio_GateForEachPin( pGate, pPin )
|
|
if ( Mio_CheckPins( pPin0, pPin ) )
|
|
pPin0 = pPin;
|
|
else
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_WritePin( FILE * pFile, Mio_Pin_t * pPin, int NameLen, int fAllPins )
|
|
{
|
|
char * pPhaseNames[10] = { "UNKNOWN", "INV", "NONINV" };
|
|
if ( fAllPins )
|
|
fprintf( pFile, "PIN * " );
|
|
else
|
|
fprintf( pFile, "\n PIN %*s ", NameLen, pPin->pName );
|
|
fprintf( pFile, "%7s ", pPhaseNames[pPin->Phase] );
|
|
fprintf( pFile, "%3d ", (int)pPin->dLoadInput );
|
|
fprintf( pFile, "%3d ", (int)pPin->dLoadMax );
|
|
fprintf( pFile, "%6.2f ", pPin->dDelayBlockRise );
|
|
fprintf( pFile, "%6.2f ", pPin->dDelayFanoutRise );
|
|
fprintf( pFile, "%6.2f ", pPin->dDelayBlockFall );
|
|
fprintf( pFile, "%6.2f", pPin->dDelayFanoutFall );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_WriteGate( FILE * pFile, Mio_Gate_t * pGate, int GateLen, int NameLen, int FormLen, int fPrintSops, int fAllPins )
|
|
{
|
|
char Buffer[5000];
|
|
Mio_Pin_t * pPin;
|
|
assert( NameLen+FormLen+2 < 5000 );
|
|
sprintf( Buffer, "%s=%s;", pGate->pOutName, pGate->pForm );
|
|
fprintf( pFile, "GATE %-*s ", GateLen, pGate->pName );
|
|
fprintf( pFile, "%8.2f ", pGate->dArea );
|
|
fprintf( pFile, "%-*s ", Abc_MinInt(NameLen+FormLen+2, 30), Buffer );
|
|
// print the pins
|
|
if ( fPrintSops )
|
|
fprintf( pFile, "%s", pGate->pSop? pGate->pSop : "unspecified\n" );
|
|
if ( fAllPins && pGate->pPins ) // equal pins
|
|
Mio_WritePin( pFile, pGate->pPins, NameLen, 1 );
|
|
else // different pins
|
|
Mio_GateForEachPin( pGate, pPin )
|
|
Mio_WritePin( pFile, pPin, NameLen, 0 );
|
|
fprintf( pFile, "\n" );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops )
|
|
{
|
|
Mio_Gate_t * pGate;
|
|
Mio_Pin_t * pPin;
|
|
int i, GateLen = 0, NameLen = 0, FormLen = 0;
|
|
int fAllPins = Mio_CheckGates( pLib );
|
|
Mio_LibraryForEachGate( pLib, pGate )
|
|
{
|
|
GateLen = Abc_MaxInt( GateLen, strlen(pGate->pName) );
|
|
NameLen = Abc_MaxInt( NameLen, strlen(pGate->pOutName) );
|
|
FormLen = Abc_MaxInt( FormLen, strlen(pGate->pForm) );
|
|
Mio_GateForEachPin( pGate, pPin )
|
|
NameLen = Abc_MaxInt( NameLen, strlen(pPin->pName) );
|
|
}
|
|
fprintf( pFile, "# The genlib library \"%s\" written by ABC on %s\n\n", pLib->pName, Extra_TimeStamp() );
|
|
for ( i = 0; i < pLib->nGates; i++ )
|
|
Mio_WriteGate( pFile, pLib->ppGates0[i], GateLen, NameLen, FormLen, fPrintSops, fAllPins );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Compares the max delay of two gates.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Mio_DelayCompare( Mio_Gate_t ** ppG1, Mio_Gate_t ** ppG2 )
|
|
{
|
|
if ( (*ppG1)->dDelayMax < (*ppG2)->dDelayMax )
|
|
return -1;
|
|
if ( (*ppG1)->dDelayMax > (*ppG2)->dDelayMax )
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Collects the set of root gates.]
|
|
|
|
Description [Only collects the gates with unique functionality,
|
|
which have fewer inputs and shorter delay than the given limits.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Mio_Gate_t ** Mio_CollectRoots( Mio_Library_t * pLib, int nInputs, float tDelay, int fSkipInv, int * pnGates, int fVerbose )
|
|
{
|
|
Mio_Gate_t * pGate;
|
|
Mio_Gate_t ** ppGates;
|
|
int i, nGates, iGate;
|
|
nGates = Mio_LibraryReadGateNum( pLib );
|
|
ppGates = ABC_ALLOC( Mio_Gate_t *, nGates );
|
|
iGate = 0;
|
|
// for each functionality, select gate with the smallest area
|
|
// if equal areas, select gate with lexicographically smaller name
|
|
Mio_LibraryForEachGate( pLib, pGate )
|
|
{
|
|
if ( pGate->nInputs > nInputs )
|
|
continue;
|
|
if ( tDelay > 0.0 && pGate->dDelayMax > (double)tDelay )
|
|
continue;
|
|
if ( pGate->uTruth == 0 || pGate->uTruth == ~(word)0 )
|
|
continue;
|
|
if ( pGate->uTruth == ABC_CONST(0xAAAAAAAAAAAAAAAA) )
|
|
continue;
|
|
if ( pGate->uTruth == ~ABC_CONST(0xAAAAAAAAAAAAAAAA) && fSkipInv )
|
|
continue;
|
|
if ( pGate->pTwin ) // skip multi-output gates for now
|
|
continue;
|
|
// check if the gate with this functionality already exists
|
|
for ( i = 0; i < iGate; i++ )
|
|
if ( ppGates[i]->uTruth == pGate->uTruth )
|
|
{
|
|
if ( ppGates[i]->dArea > pGate->dArea ||
|
|
(ppGates[i]->dArea == pGate->dArea && strcmp(ppGates[i]->pName, pGate->pName) > 0) )
|
|
ppGates[i] = pGate;
|
|
break;
|
|
}
|
|
if ( i < iGate )
|
|
continue;
|
|
assert( iGate < nGates );
|
|
ppGates[ iGate++ ] = pGate;
|
|
if ( fVerbose )
|
|
printf( "Selected gate %3d: %-20s A = %7.2f D = %7.2f %3s = %-s\n",
|
|
iGate+1, pGate->pName, pGate->dArea, pGate->dDelayMax, pGate->pOutName, pGate->pForm );
|
|
}
|
|
// sort by delay
|
|
if ( iGate > 0 )
|
|
{
|
|
qsort( (void *)ppGates, iGate, sizeof(Mio_Gate_t *),
|
|
(int (*)(const void *, const void *)) Mio_DelayCompare );
|
|
assert( Mio_DelayCompare( ppGates, ppGates + iGate - 1 ) <= 0 );
|
|
}
|
|
if ( pnGates )
|
|
*pnGates = iGate;
|
|
return ppGates;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Compares the max delay of two gates.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Mio_DelayCompareNew( Mio_Cell_t * pG1, Mio_Cell_t * pG2 )
|
|
{
|
|
if ( (pG1)->nFanins < (pG2)->nFanins )
|
|
return -1;
|
|
if ( (pG1)->nFanins > (pG2)->nFanins )
|
|
return 1;
|
|
if ( (pG1)->Area < (pG2)->Area )
|
|
return -1;
|
|
if ( (pG1)->Area > (pG2)->Area )
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Collects the set of root gates.]
|
|
|
|
Description [Only collects the gates with unique functionality,
|
|
which have fewer inputs and shorter delay than the given limits.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_CollectCopy( Mio_Cell_t * pCell, Mio_Gate_t * pGate )
|
|
{
|
|
Mio_Pin_t * pPin;
|
|
int k;
|
|
pCell->pName = pGate->pName;
|
|
pCell->uTruth = pGate->uTruth;
|
|
pCell->Area = (float)pGate->dArea;
|
|
pCell->nFanins = pGate->nInputs;
|
|
for ( k = 0, pPin = pGate->pPins; pPin; pPin = pPin->pNext, k++ )
|
|
pCell->Delays[k] = (float)(0.5 * pPin->dDelayBlockRise + 0.5 * pPin->dDelayBlockFall);
|
|
}
|
|
|
|
Mio_Cell_t * Mio_CollectRootsNew( Mio_Library_t * pLib, int nInputs, int * pnGates, int fVerbose )
|
|
{
|
|
Mio_Gate_t * pGate;
|
|
Mio_Cell_t * ppCells;
|
|
int i, nGates, iCell = 4;
|
|
nGates = Mio_LibraryReadGateNum( pLib );
|
|
ppCells = ABC_CALLOC( Mio_Cell_t, nGates + 4 );
|
|
// for each functionality, select gate with the smallest area
|
|
// if equal areas, select gate with lexicographically smaller name
|
|
Mio_LibraryForEachGate( pLib, pGate )
|
|
{
|
|
if ( pGate->nInputs > nInputs || pGate->pTwin ) // skip large and multi-output
|
|
continue;
|
|
// check if the gate with this functionality already exists
|
|
for ( i = 0; i < iCell; i++ )
|
|
if ( ppCells[i].pName && ppCells[i].uTruth == pGate->uTruth )
|
|
{
|
|
if ( ppCells[i].Area > pGate->dArea ||
|
|
(ppCells[i].Area == pGate->dArea && strcmp(ppCells[i].pName, pGate->pName) > 0) )
|
|
{
|
|
Mio_CollectCopy( ppCells + i, pGate );
|
|
}
|
|
break;
|
|
}
|
|
if ( i < iCell )
|
|
continue;
|
|
if ( pGate->uTruth == 0 || pGate->uTruth == ~(word)0 )
|
|
{
|
|
int Idx = (int)(pGate->uTruth == ~(word)0);
|
|
assert( pGate->nInputs == 0 );
|
|
Mio_CollectCopy( ppCells + Idx, pGate );
|
|
continue;
|
|
}
|
|
if ( pGate->uTruth == ABC_CONST(0xAAAAAAAAAAAAAAAA) || pGate->uTruth == ~ABC_CONST(0xAAAAAAAAAAAAAAAA) )
|
|
{
|
|
int Idx = 2 + (int)(pGate->uTruth == ~ABC_CONST(0xAAAAAAAAAAAAAAAA));
|
|
assert( pGate->nInputs == 1 );
|
|
Mio_CollectCopy( ppCells + Idx, pGate );
|
|
continue;
|
|
}
|
|
Mio_CollectCopy( ppCells + iCell++, pGate );
|
|
}
|
|
// sort by delay
|
|
if ( iCell > 1 )
|
|
{
|
|
qsort( (void *)(ppCells + 4), iCell - 4, sizeof(Mio_Cell_t),
|
|
(int (*)(const void *, const void *)) Mio_DelayCompareNew );
|
|
assert( Mio_DelayCompareNew( ppCells + 4, ppCells + iCell - 1 ) <= 0 );
|
|
}
|
|
// assign IDs
|
|
for ( i = 0; i < iCell; i++ )
|
|
ppCells[i].Id = ppCells[i].pName ? i : -1;
|
|
|
|
// report
|
|
if ( fVerbose )
|
|
{
|
|
// count gates
|
|
int * pCounts = ABC_CALLOC( int, nGates + 4 );
|
|
Mio_LibraryForEachGate( pLib, pGate )
|
|
{
|
|
if ( pGate->nInputs > nInputs || pGate->pTwin ) // skip large and multi-output
|
|
continue;
|
|
for ( i = 0; i < iCell; i++ )
|
|
if ( ppCells[i].pName && ppCells[i].uTruth == pGate->uTruth )
|
|
{
|
|
pCounts[i]++;
|
|
break;
|
|
}
|
|
assert( i < iCell );
|
|
}
|
|
for ( i = 0; i < iCell; i++ )
|
|
{
|
|
Mio_Cell_t * pCell = ppCells + i;
|
|
printf( "%4d : ", i );
|
|
if ( pCell->pName == NULL )
|
|
printf( "None\n" );
|
|
else
|
|
printf( "%-20s In = %d N = %3d A = %7.2f D = %7.2f\n",
|
|
pCell->pName, pCell->nFanins, pCounts[i], pCell->Area, pCell->Delays[0] );
|
|
}
|
|
ABC_FREE( pCounts );
|
|
}
|
|
if ( pnGates )
|
|
*pnGates = iCell;
|
|
return ppCells;
|
|
}
|
|
Mio_Cell_t * Mio_CollectRootsNewDefault( int nInputs, int * pnGates, int fVerbose )
|
|
{
|
|
return Mio_CollectRootsNew( (Mio_Library_t *)Abc_FrameReadLibGen(), nInputs, pnGates, fVerbose );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derives the truth table of the gate.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
word Mio_DeriveTruthTable6( Mio_Gate_t * pGate )
|
|
{
|
|
static unsigned uTruths6[6][2] = {
|
|
{ 0xAAAAAAAA, 0xAAAAAAAA },
|
|
{ 0xCCCCCCCC, 0xCCCCCCCC },
|
|
{ 0xF0F0F0F0, 0xF0F0F0F0 },
|
|
{ 0xFF00FF00, 0xFF00FF00 },
|
|
{ 0xFFFF0000, 0xFFFF0000 },
|
|
{ 0x00000000, 0xFFFFFFFF }
|
|
};
|
|
union {
|
|
unsigned u[2];
|
|
word w;
|
|
} uTruthRes;
|
|
assert( pGate->nInputs <= 6 );
|
|
Mio_DeriveTruthTable( pGate, uTruths6, pGate->nInputs, 6, uTruthRes.u );
|
|
return uTruthRes.w;
|
|
}
|
|
|
|
#if 0
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Recursively derives the truth table of the gate.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_DeriveTruthTable_rec( DdNode * bFunc, unsigned uTruthsIn[][2], unsigned uTruthRes[] )
|
|
{
|
|
unsigned uTruthsCof0[2];
|
|
unsigned uTruthsCof1[2];
|
|
|
|
// complement the resulting truth table, if the function is complemented
|
|
if ( Cudd_IsComplement(bFunc) )
|
|
{
|
|
Mio_DeriveTruthTable_rec( Cudd_Not(bFunc), uTruthsIn, uTruthRes );
|
|
uTruthRes[0] = ~uTruthRes[0];
|
|
uTruthRes[1] = ~uTruthRes[1];
|
|
return;
|
|
}
|
|
|
|
// if the function is constant 1, return the constant 1 truth table
|
|
if ( bFunc->index == CUDD_CONST_INDEX )
|
|
{
|
|
uTruthRes[0] = MIO_FULL;
|
|
uTruthRes[1] = MIO_FULL;
|
|
return;
|
|
}
|
|
|
|
// solve the problem for both cofactors
|
|
Mio_DeriveTruthTable_rec( cuddE(bFunc), uTruthsIn, uTruthsCof0 );
|
|
Mio_DeriveTruthTable_rec( cuddT(bFunc), uTruthsIn, uTruthsCof1 );
|
|
|
|
// derive the resulting truth table using the input truth tables
|
|
uTruthRes[0] = (uTruthsCof0[0] & ~uTruthsIn[bFunc->index][0]) |
|
|
(uTruthsCof1[0] & uTruthsIn[bFunc->index][0]);
|
|
uTruthRes[1] = (uTruthsCof0[1] & ~uTruthsIn[bFunc->index][1]) |
|
|
(uTruthsCof1[1] & uTruthsIn[bFunc->index][1]);
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derives the truth table of the gate.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] )
|
|
{
|
|
Mio_DeriveTruthTable_rec( pGate->bFunc, uTruthsIn, uTruthRes );
|
|
}
|
|
|
|
#endif
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derives the truth table of the gate.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] )
|
|
{
|
|
word uRes, uFanins[6];
|
|
int i;
|
|
assert( pGate->nInputs == nSigns );
|
|
for ( i = 0; i < nSigns; i++ )
|
|
uFanins[i] = (((word)uTruthsIn[i][1]) << 32) | (word)uTruthsIn[i][0];
|
|
uRes = Exp_Truth6( nSigns, pGate->vExpr, (word *)uFanins );
|
|
uTruthRes[0] = uRes & 0xFFFFFFFF;
|
|
uTruthRes[1] = uRes >> 32;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Reads the number of variables in the cover.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Mio_SopGetVarNum( char * pSop )
|
|
{
|
|
char * pCur;
|
|
for ( pCur = pSop; *pCur != '\n'; pCur++ )
|
|
if ( *pCur == 0 )
|
|
return -1;
|
|
return pCur - pSop - 2;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derives the truth table of the root of the gate.]
|
|
|
|
Description [Given the truth tables of the leaves of the gate,
|
|
this procedure derives the truth table of the root.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_DeriveTruthTable2( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nTruths, int nInputs, unsigned uTruthRes[] )
|
|
{
|
|
unsigned uSignCube[2];
|
|
int i, nFanins;
|
|
char * pCube;
|
|
|
|
// make sure that the number of input truth tables in equal to the number of gate inputs
|
|
assert( pGate->nInputs == nTruths );
|
|
assert( nInputs < 7 );
|
|
|
|
nFanins = Mio_SopGetVarNum( pGate->pSop );
|
|
assert( nFanins == nInputs );
|
|
|
|
// clean the resulting truth table
|
|
uTruthRes[0] = 0;
|
|
uTruthRes[1] = 0;
|
|
if ( nInputs < 6 )
|
|
{
|
|
// Abc_SopForEachCube( pGate->pSop, nFanins, pCube )
|
|
for ( pCube = pGate->pSop; *pCube; pCube += (nFanins) + 3 )
|
|
{
|
|
// add the clause
|
|
uSignCube[0] = MIO_FULL;
|
|
for ( i = 0; i < nFanins; i++ )
|
|
{
|
|
if ( pCube[i] == '0' )
|
|
uSignCube[0] &= ~uTruthsIn[i][0];
|
|
else if ( pCube[i] == '1' )
|
|
uSignCube[0] &= uTruthsIn[i][0];
|
|
}
|
|
}
|
|
if ( nInputs < 5 )
|
|
uTruthRes[0] &= MIO_MASK(1<<nInputs);
|
|
}
|
|
else
|
|
{
|
|
// consider the case when two unsigneds should be used
|
|
// Abc_SopForEachCube( pGate->pSop, nFanins, pCube )
|
|
for ( pCube = pGate->pSop; *pCube; pCube += (nFanins) + 3 )
|
|
{
|
|
uSignCube[0] = MIO_FULL;
|
|
uSignCube[1] = MIO_FULL;
|
|
for ( i = 0; i < nFanins; i++ )
|
|
{
|
|
if ( pCube[i] == '0' )
|
|
{
|
|
uSignCube[0] &= ~uTruthsIn[i][0];
|
|
uSignCube[1] &= ~uTruthsIn[i][1];
|
|
}
|
|
else if ( pCube[i] == '1' )
|
|
{
|
|
uSignCube[0] &= uTruthsIn[i][0];
|
|
uSignCube[1] &= uTruthsIn[i][1];
|
|
}
|
|
}
|
|
uTruthRes[0] |= uSignCube[0];
|
|
uTruthRes[1] |= uSignCube[1];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derives the area and delay of the root of the gate.]
|
|
|
|
Description [Array of the resulting delays should be initialized
|
|
to the (negative) SUPER_NO_VAR value.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_DeriveGateDelays( Mio_Gate_t * pGate,
|
|
float ** ptPinDelays, int nPins, int nInputs, float tDelayZero,
|
|
float * ptDelaysRes, float * ptPinDelayMax )
|
|
{
|
|
Mio_Pin_t * pPin;
|
|
float Delay, DelayMax;
|
|
int i, k;
|
|
assert( pGate->nInputs == nPins );
|
|
// set all the delays to the unused delay
|
|
for ( i = 0; i < nInputs; i++ )
|
|
ptDelaysRes[i] = tDelayZero;
|
|
// compute the delays for each input and the max delay at the same time
|
|
DelayMax = 0;
|
|
for ( i = 0; i < nInputs; i++ )
|
|
{
|
|
for ( k = 0, pPin = pGate->pPins; pPin; pPin = pPin->pNext, k++ )
|
|
{
|
|
if ( ptPinDelays[k][i] < 0 )
|
|
continue;
|
|
Delay = ptPinDelays[k][i] + (float)pPin->dDelayBlockMax;
|
|
if ( ptDelaysRes[i] < Delay )
|
|
ptDelaysRes[i] = Delay;
|
|
}
|
|
if ( k != nPins )
|
|
{
|
|
printf ("DEBUG: problem gate is %s\n", Mio_GateReadName( pGate ));
|
|
}
|
|
assert( k == nPins );
|
|
if ( DelayMax < ptDelaysRes[i] )
|
|
DelayMax = ptDelaysRes[i];
|
|
}
|
|
*ptPinDelayMax = DelayMax;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Creates a pseudo-gate.]
|
|
|
|
Description [The pseudo-gate is a N-input gate with all info set to 0.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Mio_Gate_t * Mio_GateCreatePseudo( int nInputs )
|
|
{
|
|
Mio_Gate_t * pGate;
|
|
Mio_Pin_t * pPin;
|
|
int i;
|
|
// allocate the gate structure
|
|
pGate = ABC_ALLOC( Mio_Gate_t, 1 );
|
|
memset( pGate, 0, sizeof(Mio_Gate_t) );
|
|
pGate->nInputs = nInputs;
|
|
// create pins
|
|
for ( i = 0; i < nInputs; i++ )
|
|
{
|
|
pPin = ABC_ALLOC( Mio_Pin_t, 1 );
|
|
memset( pPin, 0, sizeof(Mio_Pin_t) );
|
|
pPin->pNext = pGate->pPins;
|
|
pGate->pPins = pPin;
|
|
}
|
|
return pGate;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Adds constant value to all delay values.]
|
|
|
|
Description [The pseudo-gate is a N-input gate with all info set to 0.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_LibraryShiftDelay( Mio_Library_t * pLib, double Shift )
|
|
{
|
|
Mio_Gate_t * pGate;
|
|
Mio_Pin_t * pPin;
|
|
Mio_LibraryForEachGate( pLib, pGate )
|
|
{
|
|
pGate->dDelayMax += Shift;
|
|
Mio_GateForEachPin( pGate, pPin )
|
|
{
|
|
pPin->dDelayBlockRise += Shift;
|
|
pPin->dDelayBlockFall += Shift;
|
|
pPin->dDelayBlockMax += Shift;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Multiply areas/delays by values proportional to fanin count.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_LibraryMultiArea( Mio_Library_t * pLib, double Multi )
|
|
{
|
|
Mio_Gate_t * pGate;
|
|
Mio_LibraryForEachGate( pLib, pGate )
|
|
{
|
|
if ( pGate->nInputs < 2 )
|
|
continue;
|
|
// printf( "Before %8.3f ", pGate->dArea );
|
|
pGate->dArea *= pow( pGate->nInputs, Multi );
|
|
// printf( "After %8.3f Inputs = %d. Factor = %8.3f\n", pGate->dArea, pGate->nInputs, pow( pGate->nInputs, Multi ) );
|
|
}
|
|
}
|
|
void Mio_LibraryMultiDelay( Mio_Library_t * pLib, double Multi )
|
|
{
|
|
Mio_Gate_t * pGate;
|
|
Mio_Pin_t * pPin;
|
|
Mio_LibraryForEachGate( pLib, pGate )
|
|
{
|
|
if ( pGate->nInputs < 2 )
|
|
continue;
|
|
// printf( "Before %8.3f ", pGate->dDelayMax );
|
|
pGate->dDelayMax *= pow( pGate->nInputs, Multi );
|
|
// printf( "After %8.3f Inputs = %d. Factor = %8.3f\n", pGate->dDelayMax, pGate->nInputs, pow( pGate->nInputs, Multi ) );
|
|
Mio_GateForEachPin( pGate, pPin )
|
|
{
|
|
pPin->dDelayBlockRise *= pow( pGate->nInputs, Multi );
|
|
pPin->dDelayBlockFall *= pow( pGate->nInputs, Multi );
|
|
pPin->dDelayBlockMax *= pow( pGate->nInputs, Multi );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Transfers delays from the second to the first.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Mio_LibraryTransferDelays( Mio_Library_t * pLibD, Mio_Library_t * pLibS )
|
|
{
|
|
Mio_Gate_t * pGateD, * pGateS;
|
|
Mio_Pin_t * pPinD, * pPinS;
|
|
Mio_LibraryForEachGate( pLibS, pGateS )
|
|
{
|
|
Mio_LibraryForEachGate( pLibD, pGateD )
|
|
{
|
|
if ( pGateD->uTruth != pGateS->uTruth )
|
|
continue;
|
|
pPinS = Mio_GateReadPins( pGateS );
|
|
Mio_GateForEachPin( pGateD, pPinD )
|
|
{
|
|
if (pPinS)
|
|
{
|
|
pPinD->dDelayBlockRise = pPinS->dDelayBlockRise;
|
|
pPinD->dDelayBlockFall = pPinS->dDelayBlockFall;
|
|
pPinD->dDelayBlockMax = pPinS->dDelayBlockMax;
|
|
pPinS = Mio_PinReadNext(pPinS);
|
|
}
|
|
else
|
|
{
|
|
pPinD->dDelayBlockRise = 0;
|
|
pPinD->dDelayBlockFall = 0;
|
|
pPinD->dDelayBlockMax = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Nf_ManPrepareGate( int nVars, word uTruth, int * pComp, int * pPerm, Vec_Wrd_t * vResult )
|
|
{
|
|
int nPerms = Extra_Factorial( nVars );
|
|
int nMints = (1 << nVars);
|
|
word tCur, tTemp1, tTemp2;
|
|
int i, p, c;
|
|
Vec_WrdClear( vResult );
|
|
for ( i = 0; i < 2; i++ )
|
|
{
|
|
tCur = i ? ~uTruth : uTruth;
|
|
tTemp1 = tCur;
|
|
for ( p = 0; p < nPerms; p++ )
|
|
{
|
|
tTemp2 = tCur;
|
|
for ( c = 0; c < nMints; c++ )
|
|
{
|
|
Vec_WrdPush( vResult, tCur );
|
|
tCur = Abc_Tt6Flip( tCur, pComp[c] );
|
|
}
|
|
assert( tTemp2 == tCur );
|
|
tCur = Abc_Tt6SwapAdjacent( tCur, pPerm[p] );
|
|
}
|
|
assert( tTemp1 == tCur );
|
|
}
|
|
}
|
|
void Nf_ManPreparePrint( int nVars, int * pComp, int * pPerm, char Line[2*720*64][8] )
|
|
{
|
|
int nPerms = Extra_Factorial( nVars );
|
|
int nMints = (1 << nVars);
|
|
char * pChar, * pChar2;
|
|
int i, p, c, n = 0;
|
|
for ( i = 0; i < nVars; i++ )
|
|
Line[0][i] = 'A' + nVars - 1 - i;
|
|
Line[0][nVars] = '+';
|
|
Line[0][nVars+1] = 0;
|
|
for ( i = 0; i < 2; i++ )
|
|
{
|
|
Line[n][nVars] = i ? '-' : '+';
|
|
for ( p = 0; p < nPerms; p++ )
|
|
{
|
|
for ( c = 0; c < nMints; c++ )
|
|
{
|
|
strcpy( Line[n+1], Line[n] ); n++;
|
|
pChar = &Line[n][pComp[c]];
|
|
if ( *pChar >= 'A' && *pChar <= 'Z' )
|
|
*pChar += 'a' - 'A';
|
|
else if ( *pChar >= 'a' && *pChar <= 'z' )
|
|
*pChar -= 'a' - 'A';
|
|
}
|
|
pChar = &Line[n][pPerm[p]];
|
|
pChar2 = pChar + 1;
|
|
ABC_SWAP( char, *pChar, *pChar2 );
|
|
}
|
|
}
|
|
assert( n == 2*nPerms*nMints );
|
|
n = 0;
|
|
for ( i = 0; i < 2; i++ )
|
|
for ( p = 0; p < nPerms; p++ )
|
|
for ( c = 0; c < nMints; c++ )
|
|
printf("%8d : %d %3d %2d : %s\n", n, i, p, c, Line[n]), n++;
|
|
}
|
|
|
|
void Nf_ManPrepareLibrary( Mio_Library_t * pLib )
|
|
{
|
|
// char Lines[2*720*64][8];
|
|
// Nf_ManPreparePrint( 6, pComp, pPerm, Lines );
|
|
int * pComp[7];
|
|
int * pPerm[7];
|
|
Mio_Gate_t ** ppGates;
|
|
Vec_Wrd_t * vResult;
|
|
word * pTruths;
|
|
int * pSizes;
|
|
int nGates, i, nClasses = 0, nTotal;
|
|
abctime clk = Abc_Clock();
|
|
|
|
for ( i = 2; i <= 6; i++ )
|
|
pComp[i] = Extra_GreyCodeSchedule( i );
|
|
for ( i = 2; i <= 6; i++ )
|
|
pPerm[i] = Extra_PermSchedule( i );
|
|
|
|
// collect truth tables
|
|
ppGates = Mio_CollectRoots( pLib, 6, (float)1.0e+20, 1, &nGates, 0 );
|
|
pSizes = ABC_CALLOC( int, nGates );
|
|
pTruths = ABC_CALLOC( word, nGates );
|
|
vResult = Vec_WrdAlloc( 2 * 720 * 64 );
|
|
for ( i = 0; i < nGates; i++ )
|
|
{
|
|
pSizes[i] = Mio_GateReadPinNum( ppGates[i] );
|
|
assert( pSizes[i] > 1 && pSizes[i] <= 6 );
|
|
pTruths[i] = Mio_GateReadTruth( ppGates[i] );
|
|
|
|
Nf_ManPrepareGate( pSizes[i], pTruths[i], pComp[pSizes[i]], pPerm[pSizes[i]], vResult );
|
|
Vec_WrdUniqify(vResult);
|
|
nClasses += Vec_WrdSize(vResult);
|
|
nTotal = (1 << (pSizes[i]+1)) * Extra_Factorial(pSizes[i]);
|
|
|
|
printf( "%6d : ", i );
|
|
printf( "%16s : ", Mio_GateReadName( ppGates[i] ) );
|
|
printf( "%48s : ", Mio_GateReadForm( ppGates[i] ) );
|
|
printf( "Inputs = %2d ", pSizes[i] );
|
|
printf( "Total = %6d ", nTotal );
|
|
printf( "Classes = %6d ", Vec_WrdSize(vResult) );
|
|
printf( "Configs = %8.2f ", 1.0*nTotal/Vec_WrdSize(vResult) );
|
|
printf( "%6.2f %% ", 100.0*Vec_WrdSize(vResult)/nTotal );
|
|
Dau_DsdPrintFromTruth( &pTruths[i], pSizes[i] );
|
|
// printf( "\n" );
|
|
}
|
|
Vec_WrdFree( vResult );
|
|
ABC_FREE( ppGates );
|
|
ABC_FREE( pSizes );
|
|
ABC_FREE( pTruths );
|
|
|
|
for ( i = 2; i <= 6; i++ )
|
|
ABC_FREE( pComp[i] );
|
|
for ( i = 2; i <= 6; i++ )
|
|
ABC_FREE( pPerm[i] );
|
|
|
|
printf( "Classes = %d. ", nClasses );
|
|
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
|
}
|
|
|
|
void Nf_ManPrepareLibraryTest2()
|
|
{
|
|
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
|
|
if ( pLib != NULL )
|
|
Nf_ManPrepareLibrary( pLib );
|
|
else
|
|
printf( "Standard cell library is not available.\n" );
|
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|