mirror of https://github.com/YosysHQ/abc.git
353 lines
11 KiB
C
353 lines
11 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [abcSymm.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Network and node package.]
|
|
|
|
Synopsis [Computation of two-variable symmetries.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: abcSymm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "base/abc/abc.h"
|
|
#include "opt/sim/sim.h"
|
|
#include "opt/dau/dau.h"
|
|
#include "misc/util/utilTruth.h"
|
|
|
|
#ifdef ABC_USE_CUDD
|
|
#include "bdd/extrab/extraBdd.h"
|
|
#endif
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef ABC_USE_CUDD
|
|
|
|
static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose );
|
|
static void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose );
|
|
static void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose );
|
|
static void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms );
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [The top level procedure to compute symmetries.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose )
|
|
{
|
|
if ( fUseBdds || fNaive )
|
|
Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fReorder, fVerbose );
|
|
else
|
|
Abc_NtkSymmetriesUsingSandS( pNtk, fVerbose );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Symmetry computation using simulation and SAT.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose )
|
|
{
|
|
// extern int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose );
|
|
int nSymms = Sim_ComputeTwoVarSymms( pNtk, fVerbose );
|
|
printf( "The total number of symmetries is %d.\n", nSymms );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Symmetry computation using BDDs (both naive and smart).]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose )
|
|
{
|
|
DdManager * dd;
|
|
abctime clk, clkBdd, clkSym;
|
|
int fGarbCollect = 1;
|
|
|
|
// compute the global functions
|
|
clk = Abc_Clock();
|
|
dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, 0, fVerbose );
|
|
printf( "Shared BDD size = %d nodes.\n", Abc_NtkSizeOfGlobalBdds(pNtk) );
|
|
Cudd_AutodynDisable( dd );
|
|
if ( !fGarbCollect )
|
|
Cudd_DisableGarbageCollection( dd );
|
|
Cudd_zddVarsFromBddVars( dd, 2 );
|
|
clkBdd = Abc_Clock() - clk;
|
|
// create the collapsed network
|
|
clk = Abc_Clock();
|
|
Ntk_NetworkSymmsBdd( dd, pNtk, fNaive, fVerbose );
|
|
clkSym = Abc_Clock() - clk;
|
|
// undo the global functions
|
|
Abc_NtkFreeGlobalBdds( pNtk, 1 );
|
|
printf( "Statistics of BDD-based symmetry detection:\n" );
|
|
printf( "Algorithm = %s. Reordering = %s. Garbage collection = %s.\n",
|
|
fNaive? "naive" : "fast", fReorder? "yes" : "no", fGarbCollect? "yes" : "no" );
|
|
ABC_PRT( "Constructing BDDs", clkBdd );
|
|
ABC_PRT( "Computing symms ", clkSym );
|
|
ABC_PRT( "TOTAL ", clkBdd + clkSym );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Symmetry computation using BDDs (both naive and smart).]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose )
|
|
{
|
|
Extra_SymmInfo_t * pSymms;
|
|
Abc_Obj_t * pNode;
|
|
DdNode * bFunc;
|
|
int nSymms = 0;
|
|
int nSupps = 0;
|
|
int i;
|
|
|
|
// compute symmetry info for each PO
|
|
Abc_NtkForEachCo( pNtk, pNode, i )
|
|
{
|
|
// bFunc = pNtk->vFuncsGlob->pArray[i];
|
|
bFunc = (DdNode *)Abc_ObjGlobalBdd( pNode );
|
|
nSupps += Cudd_SupportSize( dd, bFunc );
|
|
if ( Cudd_IsConstant(bFunc) )
|
|
continue;
|
|
if ( fNaive )
|
|
pSymms = Extra_SymmPairsComputeNaive( dd, bFunc );
|
|
else
|
|
pSymms = Extra_SymmPairsCompute( dd, bFunc );
|
|
nSymms += pSymms->nSymms;
|
|
if ( fVerbose )
|
|
{
|
|
printf( "Output %6s (%d): ", Abc_ObjName(pNode), pSymms->nSymms );
|
|
Ntk_NetworkSymmsPrint( pNtk, pSymms );
|
|
}
|
|
//Extra_SymmPairsPrint( pSymms );
|
|
Extra_SymmPairsDissolve( pSymms );
|
|
}
|
|
printf( "Total number of vars in functional supports = %8d.\n", nSupps );
|
|
printf( "Total number of two-variable symmetries = %8d.\n", nSymms );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Printing symmetry groups from the symmetry data structure.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms )
|
|
{
|
|
char ** pInputNames;
|
|
int * pVarTaken;
|
|
int i, k, nVars, nSize, fStart;
|
|
|
|
// get variable names
|
|
nVars = Abc_NtkCiNum(pNtk);
|
|
pInputNames = Abc_NtkCollectCioNames( pNtk, 0 );
|
|
|
|
// alloc the array of marks
|
|
pVarTaken = ABC_ALLOC( int, nVars );
|
|
memset( pVarTaken, 0, sizeof(int) * nVars );
|
|
|
|
// print the groups
|
|
fStart = 1;
|
|
nSize = pSymms->nVars;
|
|
for ( i = 0; i < nSize; i++ )
|
|
{
|
|
// skip the variable already considered
|
|
if ( pVarTaken[i] )
|
|
continue;
|
|
// find all the vars symmetric with this one
|
|
for ( k = 0; k < nSize; k++ )
|
|
{
|
|
if ( k == i )
|
|
continue;
|
|
if ( pSymms->pSymms[i][k] == 0 )
|
|
continue;
|
|
// vars i and k are symmetric
|
|
assert( pVarTaken[k] == 0 );
|
|
// there is a new symmetry pair
|
|
if ( fStart == 1 )
|
|
{ // start a new symmetry class
|
|
fStart = 0;
|
|
printf( " { %s", pInputNames[ pSymms->pVars[i] ] );
|
|
// mark the var as taken
|
|
pVarTaken[i] = 1;
|
|
}
|
|
printf( " %s", pInputNames[ pSymms->pVars[k] ] );
|
|
// mark the var as taken
|
|
pVarTaken[k] = 1;
|
|
}
|
|
if ( fStart == 0 )
|
|
{
|
|
printf( " }" );
|
|
fStart = 1;
|
|
}
|
|
}
|
|
printf( "\n" );
|
|
|
|
ABC_FREE( pInputNames );
|
|
ABC_FREE( pVarTaken );
|
|
}
|
|
|
|
#else
|
|
|
|
void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose ) {}
|
|
|
|
#endif
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Try different permutations.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ntk_SymTryRandomFlips( word * pFun, word * pNpn, int nVars )
|
|
{
|
|
int Rand[16] = { 17290, 20203, 19027, 12035, 14687, 10920, 10413, 261, 2072, 16899, 4480, 6192, 3978, 8343, 745, 1370 };
|
|
int i, nWords = Abc_TtWordNum(nVars);
|
|
word * pFunT = ABC_CALLOC( word, nWords );
|
|
Abc_TtCopy( pFunT, pFun, nWords, 0 );
|
|
for ( i = 0; i < 16; i++ )
|
|
Abc_TtFlip( pFunT, nWords, Rand[i] % (nVars-1) );
|
|
assert( Abc_TtCompareRev(pNpn, pFunT, nWords) != 1 );
|
|
ABC_FREE( pFunT );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Find canonical form of symmetric function.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ntk_SymFunDeriveNpn( word * pFun, int nVars, int * pComp )
|
|
{
|
|
int i, nWords = Abc_TtWordNum(nVars);
|
|
word * pFunB = ABC_CALLOC( word, nWords );
|
|
Abc_TtCopy( pFunB, pFun, nWords, 1 );
|
|
if ( Abc_TtCompareRev(pFunB, pFun, nWords) == 1 )
|
|
Abc_TtCopy( pFunB, pFun, nWords, 0 );
|
|
for ( i = 0; i < (1 << nVars); i++ )
|
|
{
|
|
Abc_TtFlip( pFun, nWords, pComp[i] );
|
|
if ( Abc_TtCompareRev(pFunB, pFun, nWords) == 1 )
|
|
Abc_TtCopy( pFunB, pFun, nWords, 0 );
|
|
Abc_TtNot( pFun, nWords );
|
|
if ( Abc_TtCompareRev(pFunB, pFun, nWords) == 1 )
|
|
Abc_TtCopy( pFunB, pFun, nWords, 0 );
|
|
}
|
|
//Ntk_SymTryRandomFlips( pFun, pFunB, nVars );
|
|
Abc_TtCopy( pFun, pFunB, nWords, 0 );
|
|
ABC_FREE( pFunB );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Generating NPN classes of all symmetric function of N variables.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ntk_SymFunGenerate( int nVars, int fVerbose )
|
|
{
|
|
int k, m, Class;
|
|
int * pComp = Extra_GreyCodeSchedule( nVars );
|
|
Vec_Mem_t * vTtMem = Vec_MemAlloc( Abc_Truth6WordNum(nVars), 12 );
|
|
Vec_MemHashAlloc( vTtMem, 10000 );
|
|
assert( !(nVars < 1 || nVars > 16) );
|
|
printf( "Generating truth tables of all symmetric functions of %d variables.\n", nVars );
|
|
for ( m = 0; m < (1 << (nVars+1)); m++ )
|
|
{
|
|
word * pFun;
|
|
char Ones[100] = {0};
|
|
for ( k = 0; k <= nVars; k++ )
|
|
Ones[k] = '0' + ((m >> k) & 1);
|
|
if ( fVerbose )
|
|
printf( "%s : ", Ones );
|
|
pFun = Abc_TtSymFunGenerate( Ones, nVars );
|
|
if ( nVars < 6 )
|
|
pFun[0] = Abc_Tt6Stretch( pFun[0], nVars );
|
|
if ( fVerbose )
|
|
Extra_PrintHex( stdout, (unsigned *)pFun, nVars );
|
|
Ntk_SymFunDeriveNpn( pFun, nVars, pComp );
|
|
Class = Vec_MemHashInsert( vTtMem, pFun );
|
|
if ( fVerbose )
|
|
{
|
|
printf( " : NPN " );
|
|
Extra_PrintHex( stdout, (unsigned *)pFun, nVars );
|
|
printf( " Class %3d", Class );
|
|
printf( "\n" );
|
|
}
|
|
ABC_FREE( pFun );
|
|
}
|
|
printf( "The number of different NPN classes is %d.\n", Vec_MemEntryNum(vTtMem) );
|
|
Vec_MemHashFree( vTtMem );
|
|
Vec_MemFreeP( &vTtMem );
|
|
ABC_FREE( pComp );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|