blob: 66db8e97718e233dedf748ebf07d5c95e1c4433a [file] [log] [blame]
/**CFile****************************************************************
FileName [abcLut.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
Synopsis [Superchoicing for K-LUTs.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: abcLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "base/abc/abc.h"
#include "opt/cut/cut.h"
ABC_NAMESPACE_IMPL_START
#define LARGE_LEVEL 1000000
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define SCL_LUT_MAX 6 // the maximum LUT size
#define SCL_VARS_MAX 15 // the maximum number of variables
#define SCL_NODE_MAX 1000 // the maximum number of nodes
typedef struct Abc_ManScl_t_ Abc_ManScl_t;
struct Abc_ManScl_t_
{
// paramers
int nLutSize; // the LUT size
int nCutSizeMax; // the max number of leaves of the cone
int nNodesMax; // the max number of divisors in the cone
int nWords; // the number of machine words in sim info
// structural representation of the cone
Vec_Ptr_t * vLeaves; // leaves of the cut
Vec_Ptr_t * vVolume; // volume of the cut
int pBSet[SCL_VARS_MAX]; // bound set
// functional representation of the cone
unsigned * uTruth; // truth table of the cone
// representation of truth tables
unsigned ** uVars; // elementary truth tables
unsigned ** uSims; // truth tables of the nodes
unsigned ** uCofs; // truth tables of the cofactors
};
static Vec_Ptr_t * s_pLeaves = NULL;
static Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize );
static Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax );
static void Abc_ManSclStop( Abc_ManScl_t * p );
static void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj );
static Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * pManScl, Abc_Obj_t * pObj );
static int Abc_NodeDecomposeStep( Abc_ManScl_t * pManScl );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Performs superchoicing for K-LUTs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose )
{
ProgressBar * pProgress;
Abc_ManCut_t * pManCut;
Abc_ManScl_t * pManScl;
Cut_Man_t * pManCuts;
Abc_Obj_t * pObj, * pFanin, * pObjTop;
int i, LevelMax, nNodes;
int nNodesTried, nNodesDec, nNodesExist, nNodesUsed;
assert( Abc_NtkIsSopLogic(pNtk) );
if ( nLutSize < 3 || nLutSize > SCL_LUT_MAX )
{
printf( "LUT size (%d) does not belong to the interval: 3 <= LUT size <= %d\n", nLutSize, SCL_LUT_MAX );
return 0;
}
if ( nCutSizeMax <= nLutSize || nCutSizeMax > SCL_VARS_MAX )
{
printf( "Cut size (%d) does not belong to the interval: LUT size (%d) < Cut size <= %d\n", nCutSizeMax, nLutSize, SCL_VARS_MAX );
return 0;
}
assert( nLutSize <= SCL_LUT_MAX );
assert( nCutSizeMax <= SCL_VARS_MAX );
nNodesTried = nNodesDec = nNodesExist = nNodesUsed = 0;
// set the delays of the CIs
Abc_NtkForEachCi( pNtk, pObj, i )
pObj->Level = 0;
//Abc_NtkLevel( pNtk );
// start the managers
pManScl = Abc_ManSclStart( nLutSize, nCutSizeMax, 1000 );
pManCuts = Abc_NtkStartCutManForScl( pNtk, nLutSize );
pManCut = Abc_NtkManCutStart( nCutSizeMax, 100000, 100000, 100000 );
s_pLeaves = Abc_NtkManCutReadCutSmall( pManCut );
pManScl->vVolume = Abc_NtkManCutReadVisited( pManCut );
// process each internal node (assuming topological order of nodes!!!)
nNodes = Abc_NtkObjNumMax(pNtk);
pProgress = Extra_ProgressBarStart( stdout, nNodes );
Abc_NtkForEachObj( pNtk, pObj, i )
{
// if ( i != nNodes-1 )
// continue;
Extra_ProgressBarUpdate( pProgress, i, NULL );
if ( i >= nNodes )
break;
if ( Abc_ObjFaninNum(pObj) != 2 )
continue;
nNodesTried++;
// map this node using regular cuts
// pObj->Level = 0;
Abc_NodeLutMap( pManCuts, pObj );
// compute the cut
pManScl->vLeaves = Abc_NodeFindCut( pManCut, pObj, 0 );
if ( Vec_PtrSize(pManScl->vLeaves) <= nLutSize )
continue;
// get the volume of the cut
if ( Vec_PtrSize(pManScl->vVolume) > SCL_NODE_MAX )
continue;
nNodesDec++;
// decompose the cut
pObjTop = Abc_NodeSuperChoiceLut( pManScl, pObj );
if ( pObjTop == NULL )
continue;
nNodesExist++;
// if there is no delay improvement, skip; otherwise, update level
if ( pObjTop->Level >= pObj->Level )
{
Abc_NtkDeleteObj_rec( pObjTop, 1 );
continue;
}
pObj->Level = pObjTop->Level;
nNodesUsed++;
}
Extra_ProgressBarStop( pProgress );
// delete the managers
Abc_ManSclStop( pManScl );
Abc_NtkManCutStop( pManCut );
Cut_ManStop( pManCuts );
// get the largest arrival time
LevelMax = 0;
Abc_NtkForEachCo( pNtk, pObj, i )
{
pFanin = Abc_ObjFanin0( pObj );
// skip inv/buf
if ( Abc_ObjFaninNum(pFanin) == 1 )
pFanin = Abc_ObjFanin0( pFanin );
// get the new level
LevelMax = Abc_MaxInt( LevelMax, (int)pFanin->Level );
}
if ( fVerbose )
printf( "Try = %d. Dec = %d. Exist = %d. Use = %d. SUPER = %d levels of %d-LUTs.\n",
nNodesTried, nNodesDec, nNodesExist, nNodesUsed, LevelMax, nLutSize );
// if ( fVerbose )
// printf( "The network is superchoiced for %d levels of %d-LUTs.\n", LevelMax, nLutSize );
// clean the data field
Abc_NtkForEachObj( pNtk, pObj, i )
pObj->pNext = NULL;
// check
if ( !Abc_NtkCheck( pNtk ) )
{
printf( "Abc_NtkSuperChoiceLut: The network check has failed.\n" );
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis [Performs LUT mapping of the node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj )
{
Cut_Cut_t * pCut;
Abc_Obj_t * pFanin;
int i, DelayMax;
pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCuts, pObj, 0, 0 );
assert( pCut != NULL );
assert( pObj->Level == 0 );
// go through the cuts
pObj->Level = LARGE_LEVEL;
for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext )
{
DelayMax = 0;
for ( i = 0; i < (int)pCut->nLeaves; i++ )
{
pFanin = Abc_NtkObj( pObj->pNtk, pCut->pLeaves[i] );
// assert( Abc_ObjIsCi(pFanin) || pFanin->Level > 0 ); // should hold if node ordering is topological
if ( DelayMax < (int)pFanin->Level )
DelayMax = pFanin->Level;
}
if ( (int)pObj->Level > DelayMax )
pObj->Level = DelayMax;
}
assert( pObj->Level < LARGE_LEVEL );
pObj->Level++;
// printf( "%d(%d) ", pObj->Id, pObj->Level );
}
/**Function*************************************************************
Synopsis [Starts the cut manager for rewriting.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize )
{
static Cut_Params_t Params, * pParams = &Params;
Cut_Man_t * pManCut;
Abc_Obj_t * pObj;
int i;
// start the cut manager
memset( pParams, 0, sizeof(Cut_Params_t) );
pParams->nVarsMax = nLutSize; // the max cut size ("k" of the k-feasible cuts)
pParams->nKeepMax = 500; // the max number of cuts kept at a node
pParams->fTruth = 0; // compute truth tables
pParams->fFilter = 1; // filter dominated cuts
pParams->fSeq = 0; // compute sequential cuts
pParams->fDrop = 0; // drop cuts on the fly
pParams->fVerbose = 0; // the verbosiness flag
pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
pManCut = Cut_ManStart( pParams );
if ( pParams->fDrop )
Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) );
// set cuts for PIs
Abc_NtkForEachCi( pNtk, pObj, i )
if ( Abc_ObjFanoutNum(pObj) > 0 )
Cut_NodeSetTriv( pManCut, pObj->Id );
return pManCut;
}
/**Function*************************************************************
Synopsis [Starts the manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax )
{
Abc_ManScl_t * p;
int i, k;
assert( sizeof(unsigned) == 4 );
p = ABC_ALLOC( Abc_ManScl_t, 1 );
memset( p, 0, sizeof(Abc_ManScl_t) );
p->nLutSize = nLutSize;
p->nCutSizeMax = nCutSizeMax;
p->nNodesMax = nNodesMax;
p->nWords = Extra_TruthWordNum(nCutSizeMax);
// allocate simulation info
p->uVars = (unsigned **)Extra_ArrayAlloc( nCutSizeMax, p->nWords, 4 );
p->uSims = (unsigned **)Extra_ArrayAlloc( nNodesMax, p->nWords, 4 );
p->uCofs = (unsigned **)Extra_ArrayAlloc( 2 << nLutSize, p->nWords, 4 );
memset( p->uVars[0], 0, nCutSizeMax * p->nWords * 4 );
// assign elementary truth tables
for ( k = 0; k < p->nCutSizeMax; k++ )
for ( i = 0; i < p->nWords * 32; i++ )
if ( i & (1 << k) )
p->uVars[k][i>>5] |= (1 << (i&31));
// other data structures
// p->vBound = Vec_IntAlloc( nCutSizeMax );
return p;
}
/**Function*************************************************************
Synopsis [Stops the manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_ManSclStop( Abc_ManScl_t * p )
{
// Vec_IntFree( p->vBound );
ABC_FREE( p->uVars );
ABC_FREE( p->uSims );
ABC_FREE( p->uCofs );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Performs superchoicing for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
unsigned * Abc_NodeSuperChoiceTruth( Abc_ManScl_t * pManScl )
{
Abc_Obj_t * pObj;
unsigned * puData0, * puData1, * puData = NULL;
char * pSop;
int i, k;
// set elementary truth tables
Vec_PtrForEachEntry( Abc_Obj_t *, pManScl->vLeaves, pObj, i )
pObj->pNext = (Abc_Obj_t *)pManScl->uVars[i];
// compute truth tables for internal nodes
Vec_PtrForEachEntry( Abc_Obj_t *, pManScl->vVolume, pObj, i )
{
// set storage for the node's simulation info
pObj->pNext = (Abc_Obj_t *)pManScl->uSims[i];
// get pointer to the simulation info
puData = (unsigned *)pObj->pNext;
puData0 = (unsigned *)Abc_ObjFanin0(pObj)->pNext;
puData1 = (unsigned *)Abc_ObjFanin1(pObj)->pNext;
// simulate
pSop = (char *)pObj->pData;
if ( pSop[0] == '0' && pSop[1] == '0' )
for ( k = 0; k < pManScl->nWords; k++ )
puData[k] = ~puData0[k] & ~puData1[k];
else if ( pSop[0] == '0' )
for ( k = 0; k < pManScl->nWords; k++ )
puData[k] = ~puData0[k] & puData1[k];
else if ( pSop[1] == '0' )
for ( k = 0; k < pManScl->nWords; k++ )
puData[k] = puData0[k] & ~puData1[k];
else
for ( k = 0; k < pManScl->nWords; k++ )
puData[k] = puData0[k] & puData1[k];
}
return puData;
}
/**Function*************************************************************
Synopsis [Performs superchoicing for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeSuperChoiceCollect2_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vVolume )
{
if ( pObj->fMarkC )
return;
pObj->fMarkC = 1;
assert( Abc_ObjFaninNum(pObj) == 2 );
Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin0(pObj), vVolume );
Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin1(pObj), vVolume );
Vec_PtrPush( vVolume, pObj );
}
/**Function*************************************************************
Synopsis [Performs superchoicing for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeSuperChoiceCollect2( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume )
{
Abc_Obj_t * pObj;
int i;
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
pObj->fMarkC = 1;
Vec_PtrClear( vVolume );
Abc_NodeSuperChoiceCollect2_rec( pRoot, vVolume );
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
pObj->fMarkC = 0;
Vec_PtrForEachEntry( Abc_Obj_t *, vVolume, pObj, i )
pObj->fMarkC = 0;
}
/**Function*************************************************************
Synopsis [Performs superchoicing for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeSuperChoiceCollect_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume )
{
if ( pObj->fMarkB )
{
Vec_PtrPush( vLeaves, pObj );
pObj->fMarkB = 0;
}
if ( pObj->fMarkC )
return;
pObj->fMarkC = 1;
assert( Abc_ObjFaninNum(pObj) == 2 );
Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin0(pObj), vLeaves, vVolume );
Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin1(pObj), vLeaves, vVolume );
Vec_PtrPush( vVolume, pObj );
}
/**Function*************************************************************
Synopsis [Performs superchoicing for one node.]
Description [Orders the leaves topologically.]
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeSuperChoiceCollect( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume )
{
Abc_Obj_t * pObj;
int i, nLeaves;
nLeaves = Vec_PtrSize(vLeaves);
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
pObj->fMarkB = pObj->fMarkC = 1;
Vec_PtrClear( vVolume );
Vec_PtrClear( vLeaves );
Abc_NodeSuperChoiceCollect_rec( pRoot, vLeaves, vVolume );
assert( Vec_PtrSize(vLeaves) == nLeaves );
Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i )
pObj->fMarkC = 0;
Vec_PtrForEachEntry( Abc_Obj_t *, vVolume, pObj, i )
pObj->fMarkC = 0;
}
/**Function*************************************************************
Synopsis [Performs superchoicing for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeLeavesRemove( Vec_Ptr_t * vLeaves, unsigned uPhase, int nVars )
{
int i;
for ( i = nVars - 1; i >= 0; i-- )
if ( uPhase & (1 << i) )
Vec_PtrRemove( vLeaves, Vec_PtrEntry(vLeaves, i) );
}
/**Function*************************************************************
Synopsis [Performs superchoicing for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeGetLevel( Abc_Obj_t * pObj )
{
Abc_Obj_t * pFanin;
int i, Level;
Level = 0;
Abc_ObjForEachFanin( pObj, pFanin, i )
Level = Abc_MaxInt( Level, (int)pFanin->Level );
return Level + 1;
}
/**Function*************************************************************
Synopsis [Performs superchoicing for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * p, Abc_Obj_t * pObj )
{
Abc_Obj_t * pFanin, * pObjNew;
int i, nVars, uSupport, nSuppVars;
// collect the cone using DFS (excluding leaves)
Abc_NodeSuperChoiceCollect2( pObj, p->vLeaves, p->vVolume );
assert( Vec_PtrEntryLast(p->vVolume) == pObj );
// compute the truth table
p->uTruth = Abc_NodeSuperChoiceTruth( p );
// get the support of this truth table
nVars = Vec_PtrSize(p->vLeaves);
uSupport = Extra_TruthSupport(p->uTruth, nVars);
nSuppVars = Extra_WordCountOnes(uSupport);
assert( nSuppVars <= nVars );
if ( nSuppVars == 0 )
{
pObj->Level = 0;
return NULL;
}
if ( nSuppVars == 1 )
{
// find the variable
for ( i = 0; i < nVars; i++ )
if ( uSupport & (1 << i) )
break;
assert( i < nVars );
pFanin = (Abc_Obj_t *)Vec_PtrEntry( p->vLeaves, i );
pObj->Level = pFanin->Level;
return NULL;
}
// support-minimize the truth table
if ( nSuppVars != nVars )
{
Extra_TruthShrink( p->uCofs[0], p->uTruth, nSuppVars, nVars, uSupport );
Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars );
Abc_NodeLeavesRemove( p->vLeaves, ((1 << nVars) - 1) & ~uSupport, nVars );
}
// return NULL;
// decompose the truth table recursively
while ( Vec_PtrSize(p->vLeaves) > p->nLutSize )
if ( !Abc_NodeDecomposeStep( p ) )
{
Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pFanin, i )
if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 0 )
Abc_NtkDeleteObj_rec( pFanin, 1 );
return NULL;
}
// create the topmost node
pObjNew = Abc_NtkCreateNode( pObj->pNtk );
Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pFanin, i )
Abc_ObjAddFanin( pObjNew, pFanin );
// create the function
pObjNew->pData = Abc_SopCreateFromTruth( (Mem_Flex_t *)pObj->pNtk->pManFunc, Vec_PtrSize(p->vLeaves), p->uTruth ); // need ISOP
pObjNew->Level = Abc_NodeGetLevel( pObjNew );
return pObjNew;
}
/**Function*************************************************************
Synopsis [Procedure used for sorting the nodes in increasing order of levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeCompareLevelsInc( int * pp1, int * pp2 )
{
Abc_Obj_t * pNode1, * pNode2;
pNode1 = (Abc_Obj_t *)Vec_PtrEntry(s_pLeaves, *pp1);
pNode2 = (Abc_Obj_t *)Vec_PtrEntry(s_pLeaves, *pp2);
if ( pNode1->Level < pNode2->Level )
return -1;
if ( pNode1->Level > pNode2->Level )
return 1;
return 0;
}
/**Function*************************************************************
Synopsis [Selects the earliest arriving nodes from the array.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeDecomposeSort( Abc_Obj_t ** pLeaves, int nVars, int * pBSet, int nLutSize )
{
Abc_Obj_t * pTemp[SCL_VARS_MAX];
int i, k, kBest, LevelMin;
assert( nLutSize < nVars );
assert( nVars <= SCL_VARS_MAX );
// copy nodes into the internal storage
// printf( "(" );
for ( i = 0; i < nVars; i++ )
{
pTemp[i] = pLeaves[i];
// printf( " %d", pLeaves[i]->Level );
}
// printf( " )\n" );
// choose one node at a time
for ( i = 0; i < nLutSize; i++ )
{
kBest = -1;
LevelMin = LARGE_LEVEL;
for ( k = 0; k < nVars; k++ )
if ( pTemp[k] && LevelMin > (int)pTemp[k]->Level )
{
LevelMin = pTemp[k]->Level;
kBest = k;
}
pBSet[i] = kBest;
pTemp[kBest] = NULL;
}
}
/**Function*************************************************************
Synopsis [Performs superchoicing for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeDecomposeStep( Abc_ManScl_t * p )
{
static char pCofClasses[1<<SCL_LUT_MAX][1<<SCL_LUT_MAX];
static char nCofClasses[1<<SCL_LUT_MAX];
Abc_Ntk_t * pNtk;
Abc_Obj_t * pObjNew, * pFanin, * pNodesNew[SCL_LUT_MAX];
unsigned * pTruthCof, * pTruthClass, * pTruth, uPhase;
int i, k, c, v, w, nVars, nVarsNew, nClasses, nCofs;
// set the network
pNtk = ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, 0))->pNtk;
// find the earliest nodes
nVars = Vec_PtrSize(p->vLeaves);
assert( nVars > p->nLutSize );
/*
for ( v = 0; v < nVars; v++ )
p->pBSet[v] = v;
qsort( (void *)p->pBSet, nVars, sizeof(int),
(int (*)(const void *, const void *)) Abc_NodeCompareLevelsInc );
*/
Abc_NodeDecomposeSort( (Abc_Obj_t **)Vec_PtrArray(p->vLeaves), Vec_PtrSize(p->vLeaves), p->pBSet, p->nLutSize );
assert( ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[0]))->Level <=
((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[1]))->Level );
// cofactor w.r.t. the selected variables
Extra_TruthCopy( p->uCofs[1], p->uTruth, nVars );
c = 2;
for ( v = 0; v < p->nLutSize; v++ )
for ( k = 0; k < (1<<v); k++ )
{
Extra_TruthCopy( p->uCofs[c], p->uCofs[c/2], nVars );
Extra_TruthCopy( p->uCofs[c+1], p->uCofs[c/2], nVars );
Extra_TruthCofactor0( p->uCofs[c], nVars, p->pBSet[v] );
Extra_TruthCofactor1( p->uCofs[c+1], nVars, p->pBSet[v] );
c += 2;
}
assert( c == (2 << p->nLutSize) );
// count unique cofactors
nClasses = 0;
nCofs = (1 << p->nLutSize);
for ( i = 0; i < nCofs; i++ )
{
pTruthCof = p->uCofs[ nCofs + i ];
for ( k = 0; k < nClasses; k++ )
{
pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ];
if ( Extra_TruthIsEqual( pTruthCof, pTruthClass, nVars ) )
{
pCofClasses[k][(int)nCofClasses[k]++ ] = i;
break;
}
}
if ( k != nClasses )
continue;
// not found
pCofClasses[nClasses][0] = i;
nCofClasses[nClasses] = 1;
nClasses++;
if ( nClasses > nCofs/2 )
return 0;
}
// the number of cofactors is acceptable
nVarsNew = Abc_Base2Log( nClasses );
assert( nVarsNew < p->nLutSize );
// create the remainder truth table
// for each class of cofactors, multiply cofactor truth table by its code
Extra_TruthClear( p->uTruth, nVars );
for ( k = 0; k < nClasses; k++ )
{
pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ];
for ( v = 0; v < nVarsNew; v++ )
if ( k & (1 << v) )
Extra_TruthAnd( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars );
else
Extra_TruthSharp( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars );
Extra_TruthOr( p->uTruth, p->uTruth, pTruthClass, nVars );
}
// create nodes
pTruth = p->uCofs[0];
for ( v = 0; v < nVarsNew; v++ )
{
Extra_TruthClear( pTruth, p->nLutSize );
for ( k = 0; k < nClasses; k++ )
if ( k & (1 << v) )
for ( i = 0; i < nCofClasses[k]; i++ )
{
pTruthCof = p->uCofs[1];
Extra_TruthFill( pTruthCof, p->nLutSize );
for ( w = 0; w < p->nLutSize; w++ )
if ( pCofClasses[k][i] & (1 << (p->nLutSize-1-w)) )
Extra_TruthAnd( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize );
else
Extra_TruthSharp( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize );
Extra_TruthOr( pTruth, pTruth, pTruthCof, p->nLutSize );
}
// implement the node
pObjNew = Abc_NtkCreateNode( pNtk );
for ( i = 0; i < p->nLutSize; i++ )
{
pFanin = (Abc_Obj_t *)Vec_PtrEntry( p->vLeaves, p->pBSet[i] );
Abc_ObjAddFanin( pObjNew, pFanin );
}
// create the function
pObjNew->pData = Abc_SopCreateFromTruth( (Mem_Flex_t *)pNtk->pManFunc, p->nLutSize, pTruth ); // need ISOP
pObjNew->Level = Abc_NodeGetLevel( pObjNew );
pNodesNew[v] = pObjNew;
}
// put the new nodes back into the list
for ( v = 0; v < nVarsNew; v++ )
Vec_PtrWriteEntry( p->vLeaves, p->pBSet[v], pNodesNew[v] );
// compute the variables that should be removed
uPhase = 0;
for ( v = nVarsNew; v < p->nLutSize; v++ )
uPhase |= (1 << p->pBSet[v]);
// remove entries from the array
Abc_NodeLeavesRemove( p->vLeaves, uPhase, nVars );
// update truth table
Extra_TruthShrink( p->uCofs[0], p->uTruth, nVars - p->nLutSize + nVarsNew, nVars, ((1 << nVars) - 1) & ~uPhase );
Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars );
assert( !Extra_TruthVarInSupport( p->uTruth, nVars, nVars - p->nLutSize + nVarsNew ) );
return 1;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END