mirror of https://github.com/YosysHQ/abc.git
395 lines
11 KiB
C
395 lines
11 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [darPrec.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [DAG-aware AIG rewriting.]
|
|
|
|
Synopsis [Truth table precomputation.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - April 28, 2007.]
|
|
|
|
Revision [$Id: darPrec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "darInt.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Allocated one-memory-chunk array.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
char ** Dar_ArrayAlloc( int nCols, int nRows, int Size )
|
|
{
|
|
char ** pRes;
|
|
char * pBuffer;
|
|
int i;
|
|
assert( nCols > 0 && nRows > 0 && Size > 0 );
|
|
pBuffer = ABC_ALLOC( char, nCols * (sizeof(void *) + nRows * Size) );
|
|
pRes = (char **)pBuffer;
|
|
pRes[0] = pBuffer + nCols * sizeof(void *);
|
|
for ( i = 1; i < nCols; i++ )
|
|
pRes[i] = pRes[0] + i * nRows * Size;
|
|
return pRes;
|
|
}
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the factorial.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
int Dar_Factorial( int n )
|
|
{
|
|
int i, Res = 1;
|
|
for ( i = 1; i <= n; i++ )
|
|
Res *= i;
|
|
return Res;
|
|
}
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Fills in the array of permutations.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
void Dar_Permutations_rec( char ** pRes, int nFact, int n, char Array[] )
|
|
{
|
|
char ** pNext;
|
|
int nFactNext;
|
|
int iTemp, iCur, iLast, k;
|
|
|
|
if ( n == 1 )
|
|
{
|
|
pRes[0][0] = Array[0];
|
|
return;
|
|
}
|
|
|
|
// get the next factorial
|
|
nFactNext = nFact / n;
|
|
// get the last entry
|
|
iLast = n - 1;
|
|
|
|
for ( iCur = 0; iCur < n; iCur++ )
|
|
{
|
|
// swap Cur and Last
|
|
iTemp = Array[iCur];
|
|
Array[iCur] = Array[iLast];
|
|
Array[iLast] = iTemp;
|
|
|
|
// get the pointer to the current section
|
|
pNext = pRes + (n - 1 - iCur) * nFactNext;
|
|
|
|
// set the last entry
|
|
for ( k = 0; k < nFactNext; k++ )
|
|
pNext[k][iLast] = Array[iLast];
|
|
|
|
// call recursively for this part
|
|
Dar_Permutations_rec( pNext, nFactNext, n - 1, Array );
|
|
|
|
// swap them back
|
|
iTemp = Array[iCur];
|
|
Array[iCur] = Array[iLast];
|
|
Array[iLast] = iTemp;
|
|
}
|
|
}
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the set of all permutations.]
|
|
|
|
Description [The number of permutations in the array is n!. The number of
|
|
entries in each permutation is n. Therefore, the resulting array is a
|
|
two-dimentional array of the size: n! x n. To free the resulting array,
|
|
call ABC_FREE() on the pointer returned by this procedure.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
char ** Dar_Permutations( int n )
|
|
{
|
|
char Array[50];
|
|
char ** pRes;
|
|
int nFact, i;
|
|
// allocate memory
|
|
nFact = Dar_Factorial( n );
|
|
pRes = Dar_ArrayAlloc( nFact, n, sizeof(char) );
|
|
// fill in the permutations
|
|
for ( i = 0; i < n; i++ )
|
|
Array[i] = i;
|
|
Dar_Permutations_rec( pRes, nFact, n, Array );
|
|
// print the permutations
|
|
/*
|
|
{
|
|
int i, k;
|
|
for ( i = 0; i < nFact; i++ )
|
|
{
|
|
printf( "{" );
|
|
for ( k = 0; k < n; k++ )
|
|
printf( " %d", pRes[i][k] );
|
|
printf( " }\n" );
|
|
}
|
|
}
|
|
*/
|
|
return pRes;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Permutes the given vector of minterms.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Dar_TruthPermute_int( int * pMints, int nMints, char * pPerm, int nVars, int * pMintsP )
|
|
{
|
|
int m, v;
|
|
// clean the storage for minterms
|
|
memset( pMintsP, 0, sizeof(int) * nMints );
|
|
// go through minterms and add the variables
|
|
for ( m = 0; m < nMints; m++ )
|
|
for ( v = 0; v < nVars; v++ )
|
|
if ( pMints[m] & (1 << v) )
|
|
pMintsP[m] |= (1 << pPerm[v]);
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Permutes the function.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
unsigned Dar_TruthPermute( unsigned Truth, char * pPerms, int nVars, int fReverse )
|
|
{
|
|
unsigned Result;
|
|
int * pMints;
|
|
int * pMintsP;
|
|
int nMints;
|
|
int i, m;
|
|
|
|
assert( nVars < 6 );
|
|
nMints = (1 << nVars);
|
|
pMints = ABC_ALLOC( int, nMints );
|
|
pMintsP = ABC_ALLOC( int, nMints );
|
|
for ( i = 0; i < nMints; i++ )
|
|
pMints[i] = i;
|
|
|
|
Dar_TruthPermute_int( pMints, nMints, pPerms, nVars, pMintsP );
|
|
|
|
Result = 0;
|
|
if ( fReverse )
|
|
{
|
|
for ( m = 0; m < nMints; m++ )
|
|
if ( Truth & (1 << pMintsP[m]) )
|
|
Result |= (1 << m);
|
|
}
|
|
else
|
|
{
|
|
for ( m = 0; m < nMints; m++ )
|
|
if ( Truth & (1 << m) )
|
|
Result |= (1 << pMintsP[m]);
|
|
}
|
|
|
|
ABC_FREE( pMints );
|
|
ABC_FREE( pMintsP );
|
|
|
|
return Result;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Changes the phase of the function.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
unsigned Dar_TruthPolarize( unsigned uTruth, int Polarity, int nVars )
|
|
{
|
|
// elementary truth tables
|
|
static unsigned Signs[5] = {
|
|
0xAAAAAAAA, // 1010 1010 1010 1010 1010 1010 1010 1010
|
|
0xCCCCCCCC, // 1010 1010 1010 1010 1010 1010 1010 1010
|
|
0xF0F0F0F0, // 1111 0000 1111 0000 1111 0000 1111 0000
|
|
0xFF00FF00, // 1111 1111 0000 0000 1111 1111 0000 0000
|
|
0xFFFF0000 // 1111 1111 1111 1111 0000 0000 0000 0000
|
|
};
|
|
unsigned uTruthRes, uCof0, uCof1;
|
|
int nMints, Shift, v;
|
|
assert( nVars < 6 );
|
|
nMints = (1 << nVars);
|
|
uTruthRes = uTruth;
|
|
for ( v = 0; v < nVars; v++ )
|
|
if ( Polarity & (1 << v) )
|
|
{
|
|
uCof0 = uTruth & ~Signs[v];
|
|
uCof1 = uTruth & Signs[v];
|
|
Shift = (1 << v);
|
|
uCof0 <<= Shift;
|
|
uCof1 >>= Shift;
|
|
uTruth = uCof0 | uCof1;
|
|
}
|
|
return uTruth;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes NPN canonical forms for 4-variable functions.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Dar_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap )
|
|
{
|
|
unsigned short * uCanons;
|
|
unsigned char * uMap;
|
|
unsigned uTruth, uPhase, uPerm;
|
|
char ** pPerms4, * uPhases, * uPerms;
|
|
int nFuncs, nClasses;
|
|
int i, k;
|
|
|
|
nFuncs = (1 << 16);
|
|
uCanons = ABC_CALLOC( unsigned short, nFuncs );
|
|
uPhases = ABC_CALLOC( char, nFuncs );
|
|
uPerms = ABC_CALLOC( char, nFuncs );
|
|
uMap = ABC_CALLOC( unsigned char, nFuncs );
|
|
pPerms4 = Dar_Permutations( 4 );
|
|
|
|
nClasses = 1;
|
|
nFuncs = (1 << 15);
|
|
for ( uTruth = 1; uTruth < (unsigned)nFuncs; uTruth++ )
|
|
{
|
|
// skip already assigned
|
|
if ( uCanons[uTruth] )
|
|
{
|
|
assert( uTruth > uCanons[uTruth] );
|
|
uMap[~uTruth & 0xFFFF] = uMap[uTruth] = uMap[uCanons[uTruth]];
|
|
continue;
|
|
}
|
|
uMap[uTruth] = nClasses++;
|
|
for ( i = 0; i < 16; i++ )
|
|
{
|
|
uPhase = Dar_TruthPolarize( uTruth, i, 4 );
|
|
for ( k = 0; k < 24; k++ )
|
|
{
|
|
uPerm = Dar_TruthPermute( uPhase, pPerms4[k], 4, 0 );
|
|
if ( uCanons[uPerm] == 0 )
|
|
{
|
|
uCanons[uPerm] = uTruth;
|
|
uPhases[uPerm] = i;
|
|
uPerms[uPerm] = k;
|
|
uMap[uPerm] = uMap[uTruth];
|
|
|
|
uPerm = ~uPerm & 0xFFFF;
|
|
uCanons[uPerm] = uTruth;
|
|
uPhases[uPerm] = i | 16;
|
|
uPerms[uPerm] = k;
|
|
uMap[uPerm] = uMap[uTruth];
|
|
}
|
|
else
|
|
assert( uCanons[uPerm] == uTruth );
|
|
}
|
|
uPhase = Dar_TruthPolarize( ~uTruth & 0xFFFF, i, 4 );
|
|
for ( k = 0; k < 24; k++ )
|
|
{
|
|
uPerm = Dar_TruthPermute( uPhase, pPerms4[k], 4, 0 );
|
|
if ( uCanons[uPerm] == 0 )
|
|
{
|
|
uCanons[uPerm] = uTruth;
|
|
uPhases[uPerm] = i;
|
|
uPerms[uPerm] = k;
|
|
uMap[uPerm] = uMap[uTruth];
|
|
|
|
uPerm = ~uPerm & 0xFFFF;
|
|
uCanons[uPerm] = uTruth;
|
|
uPhases[uPerm] = i | 16;
|
|
uPerms[uPerm] = k;
|
|
uMap[uPerm] = uMap[uTruth];
|
|
}
|
|
else
|
|
assert( uCanons[uPerm] == uTruth );
|
|
}
|
|
}
|
|
}
|
|
for ( uTruth = 1; uTruth < 0xffff; uTruth++ )
|
|
assert( uMap[uTruth] != 0 );
|
|
uPhases[(1<<16)-1] = 16;
|
|
assert( nClasses == 222 );
|
|
ABC_FREE( pPerms4 );
|
|
if ( puCanons )
|
|
*puCanons = uCanons;
|
|
else
|
|
ABC_FREE( uCanons );
|
|
if ( puPhases )
|
|
*puPhases = uPhases;
|
|
else
|
|
ABC_FREE( uPhases );
|
|
if ( puPerms )
|
|
*puPerms = uPerms;
|
|
else
|
|
ABC_FREE( uPerms );
|
|
if ( puMap )
|
|
*puMap = uMap;
|
|
else
|
|
ABC_FREE( uMap );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|