mirror of https://github.com/YosysHQ/abc.git
377 lines
12 KiB
C
377 lines
12 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [playerCore.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [PLA decomposition package.]
|
|
|
|
Synopsis []
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - May 11, 2006.]
|
|
|
|
Revision [$Id: playerCore.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "player.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
static int Pla_ManDecomposeInt( Pla_Man_t * p );
|
|
static int Pla_ManDecomposeNode( Pla_Man_t * p, Ivy_Obj_t * pObj );
|
|
static void Pla_NodeGetSuppsAndCovers( Pla_Man_t * p, Ivy_Obj_t * pObj, int Level,
|
|
Vec_Int_t ** pvSuppA, Vec_Int_t ** pvSuppB, Esop_Cube_t ** pvCovA, Esop_Cube_t ** pvCovB );
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs decomposition/mapping into PLAs and K-LUTs.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Pla_Man_t * Pla_ManDecompose( Ivy_Man_t * pAig, int nLutMax, int nPlaMax, int fVerbose )
|
|
{
|
|
Pla_Man_t * p;
|
|
p = Pla_ManAlloc( pAig, nLutMax, nPlaMax );
|
|
if ( !Pla_ManDecomposeInt( p ) )
|
|
{
|
|
printf( "Decomposition/mapping failed.\n" );
|
|
Pla_ManFree( p );
|
|
return NULL;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs decomposition/mapping into PLAs and K-LUTs.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Pla_ManDecomposeInt( Pla_Man_t * p )
|
|
{
|
|
Ivy_Man_t * pAig = p->pManAig;
|
|
Ivy_Obj_t * pObj;
|
|
Pla_Obj_t * pStr;
|
|
int i;
|
|
|
|
// prepare the PI structures
|
|
Ivy_ManForEachPi( pAig, pObj, i )
|
|
{
|
|
pStr = Ivy_ObjPlaStr( pAig, pObj );
|
|
pStr->fFixed = 1;
|
|
pStr->Depth = 0;
|
|
pStr->nRefs = (unsigned)pObj->nRefs;
|
|
pStr->pCover[0] = PLA_EMPTY;
|
|
pStr->pCover[1] = PLA_EMPTY;
|
|
}
|
|
|
|
// assuming DFS ordering of nodes in the manager
|
|
Ivy_ManForEachNode( pAig, pObj, i )
|
|
if ( !Pla_ManDecomposeNode(p, pObj) )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Records decomposition statistics for one node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline void Pla_ManCountDecNodes( Pla_Man_t * p, Pla_Obj_t * pStr )
|
|
{
|
|
if ( Vec_IntSize(pStr->vSupp) <= p->nLutMax && pStr->pCover[1] != PLA_EMPTY )
|
|
p->nNodesBoth++;
|
|
else if ( Vec_IntSize(pStr->vSupp) <= p->nLutMax )
|
|
p->nNodesLut++;
|
|
else if ( pStr->pCover[1] != PLA_EMPTY )
|
|
p->nNodesPla++;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs decomposition/mapping for one node.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Pla_ManDecomposeNode( Pla_Man_t * p, Ivy_Obj_t * pObj )
|
|
{
|
|
Pla_Obj_t * pStr, * pStr0, * pStr1;
|
|
Vec_Int_t * vSuppA, * vSuppB, * vSupp0, * vSupp1;
|
|
Esop_Cube_t * pCovA, * pCovB;
|
|
int nSuppSize1, nSuppSize2;
|
|
|
|
assert( pObj->nRefs > 0 );
|
|
p->nNodes++;
|
|
|
|
// get the structures
|
|
pStr = Ivy_ObjPlaStr( p->pManAig, pObj );
|
|
pStr0 = Ivy_ObjPlaStr( p->pManAig, Ivy_ObjFanin0( pObj ) );
|
|
pStr1 = Ivy_ObjPlaStr( p->pManAig, Ivy_ObjFanin1( pObj ) );
|
|
vSupp0 = &pStr->vSupp[0];
|
|
vSupp1 = &pStr->vSupp[1];
|
|
pStr->pCover[0] = PLA_EMPTY;
|
|
pStr->pCover[1] = PLA_EMPTY;
|
|
|
|
// process level 1
|
|
Pla_NodeGetSuppsAndCovers( p, pObj, 1, &vSuppA, &vSuppB, &pCovA, &pCovB );
|
|
nSuppSize1 = Pla_ManMergeTwoSupports( p, vSuppA, vSuppB, vSupp0 );
|
|
if ( nSuppSize1 > p->nPlaMax || pCovA == PLA_EMPTY || pCovB == PLA_EMPTY )
|
|
pStr->pCover[0] = PLA_EMPTY;
|
|
else if ( Ivy_ObjIsAnd(pObj) )
|
|
pStr->pCover[0] = Pla_ManAndTwoCovers( p, pCovA, pCovB, nSuppSize1, 1 );
|
|
else
|
|
pStr->pCover[0] = Pla_ManExorTwoCovers( p, pCovA, pCovB, nSuppSize1, 1 );
|
|
|
|
// process level 2
|
|
if ( PLA_MAX(pStr0->Depth, pStr1->Depth) > 1 )
|
|
{
|
|
Pla_NodeGetSuppsAndCovers( p, pObj, 2, &vSuppA, &vSuppB, &pCovA, &pCovB );
|
|
nSuppSize2 = Pla_ManMergeTwoSupports( p, vSuppA, vSuppB, vSupp1 );
|
|
if ( nSuppSize2 > p->nPlaMax || pCovA == PLA_EMPTY || pCovB == PLA_EMPTY )
|
|
pStr->pCover[1] = PLA_EMPTY;
|
|
else if ( Ivy_ObjIsAnd(pObj) )
|
|
pStr->pCover[1] = Pla_ManAndTwoCovers( p, pCovA, pCovB, nSuppSize2, 1 );
|
|
else
|
|
pStr->pCover[1] = Pla_ManExorTwoCovers( p, pCovA, pCovB, nSuppSize2, 1 );
|
|
}
|
|
|
|
// determine the level of this node
|
|
pStr->nRefs = (unsigned)pObj->nRefs;
|
|
pStr->Depth = PLA_MAX( pStr0->Depth, pStr1->Depth );
|
|
pStr->Depth = pStr->Depth? pStr->Depth : 1;
|
|
if ( nSuppSize1 > p->nLutMax && pStr->pCover[1] == PLA_EMPTY )
|
|
{
|
|
pStr->Depth++;
|
|
// free second level
|
|
if ( pStr->pCover[1] != PLA_EMPTY )
|
|
Esop_CoverRecycle( p->pManMin, pStr->pCover[1] );
|
|
vSupp1->nCap = 0;
|
|
vSupp1->nSize = 0;
|
|
FREE( vSupp1->pArray );
|
|
pStr->pCover[1] = PLA_EMPTY;
|
|
// move first to second
|
|
pStr->vSupp[1] = pStr->vSupp[0];
|
|
pStr->pCover[1] = pStr->pCover[0];
|
|
vSupp0->nCap = 0;
|
|
vSupp0->nSize = 0;
|
|
vSupp0->pArray = NULL;
|
|
pStr->pCover[0] = PLA_EMPTY;
|
|
// get zero level
|
|
Pla_NodeGetSuppsAndCovers( p, pObj, 0, &vSuppA, &vSuppB, &pCovA, &pCovB );
|
|
nSuppSize2 = Pla_ManMergeTwoSupports( p, vSuppA, vSuppB, vSupp0 );
|
|
assert( nSuppSize2 == 2 );
|
|
if ( pCovA == PLA_EMPTY || pCovB == PLA_EMPTY )
|
|
pStr->pCover[0] = PLA_EMPTY;
|
|
else if ( Ivy_ObjIsAnd(pObj) )
|
|
pStr->pCover[0] = Pla_ManAndTwoCovers( p, pCovA, pCovB, nSuppSize2, 0 );
|
|
else
|
|
pStr->pCover[0] = Pla_ManExorTwoCovers( p, pCovA, pCovB, nSuppSize2, 0 );
|
|
// count stats
|
|
if ( pStr0->fFixed == 0 ) Pla_ManCountDecNodes( p, pStr0 );
|
|
if ( pStr1->fFixed == 0 ) Pla_ManCountDecNodes( p, pStr1 );
|
|
// mark the nodes
|
|
pStr0->fFixed = 1;
|
|
pStr1->fFixed = 1;
|
|
}
|
|
else if ( pStr0->Depth < pStr1->Depth )
|
|
{
|
|
if ( pStr0->fFixed == 0 ) Pla_ManCountDecNodes( p, pStr0 );
|
|
pStr0->fFixed = 1;
|
|
}
|
|
else // if ( pStr0->Depth > pStr1->Depth )
|
|
{
|
|
if ( pStr1->fFixed == 0 ) Pla_ManCountDecNodes( p, pStr1 );
|
|
pStr1->fFixed = 1;
|
|
}
|
|
assert( pStr->Depth );
|
|
|
|
// free some of the covers to save memory
|
|
assert( pStr0->nRefs > 0 );
|
|
assert( pStr1->nRefs > 0 );
|
|
pStr0->nRefs--;
|
|
pStr1->nRefs--;
|
|
|
|
if ( pStr0->nRefs == 0 && !pStr0->fFixed )
|
|
Pla_ManFreeStr( p, pStr0 ), p->nNodesDeref++;
|
|
if ( pStr1->nRefs == 0 && !pStr1->fFixed )
|
|
Pla_ManFreeStr( p, pStr1 ), p->nNodesDeref++;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns pointers to the support arrays on the given level.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Pla_NodeGetSuppsAndCovers( Pla_Man_t * p, Ivy_Obj_t * pObj, int Level,
|
|
Vec_Int_t ** pvSuppA, Vec_Int_t ** pvSuppB, Esop_Cube_t ** pvCovA, Esop_Cube_t ** pvCovB )
|
|
{
|
|
Ivy_Obj_t * pFan0, * pFan1;
|
|
Pla_Obj_t * pStr, * pStr0, * pStr1;
|
|
Esop_Cube_t * pCovA, * pCovB;
|
|
int fCompl0, fCompl1;
|
|
assert( Level >= 0 && Level <= 2 );
|
|
// get the complemented attributes
|
|
fCompl0 = Ivy_ObjFaninC0( pObj );
|
|
fCompl1 = Ivy_ObjFaninC1( pObj );
|
|
// get the fanins
|
|
pFan0 = Ivy_ObjFanin0( pObj );
|
|
pFan1 = Ivy_ObjFanin1( pObj );
|
|
// get the structures
|
|
pStr = Ivy_ObjPlaStr( p->pManAig, pObj );
|
|
pStr0 = Ivy_ObjPlaStr( p->pManAig, pFan0 );
|
|
pStr1 = Ivy_ObjPlaStr( p->pManAig, pFan1 );
|
|
// make sure the fanins are processed
|
|
assert( Ivy_ObjIsPi(pFan0) || pStr0->Depth > 0 );
|
|
assert( Ivy_ObjIsPi(pFan1) || pStr1->Depth > 0 );
|
|
// prepare the return values depending on the level
|
|
Vec_IntWriteEntry( p->vTriv0, 0, pFan0->Id );
|
|
Vec_IntWriteEntry( p->vTriv1, 0, pFan1->Id );
|
|
*pvSuppA = p->vTriv0;
|
|
*pvSuppB = p->vTriv1;
|
|
pCovA = p->pManMin->pTriv0;
|
|
pCovB = p->pManMin->pTriv1;
|
|
if ( Level == 1 )
|
|
{
|
|
if ( pStr0->Depth == pStr1->Depth )
|
|
{
|
|
if ( pStr0->Depth > 0 )
|
|
{
|
|
*pvSuppA = &pStr0->vSupp[0];
|
|
*pvSuppB = &pStr1->vSupp[0];
|
|
pCovA = pStr0->pCover[0];
|
|
pCovB = pStr1->pCover[0];
|
|
}
|
|
}
|
|
else if ( pStr0->Depth < pStr1->Depth )
|
|
{
|
|
*pvSuppB = &pStr1->vSupp[0];
|
|
pCovB = pStr1->pCover[0];
|
|
}
|
|
else // if ( pStr0->Depth > pStr1->Depth )
|
|
{
|
|
*pvSuppA = &pStr0->vSupp[0];
|
|
pCovA = pStr0->pCover[0];
|
|
}
|
|
}
|
|
else if ( Level == 2 )
|
|
{
|
|
if ( pStr0->Depth == pStr1->Depth )
|
|
{
|
|
*pvSuppA = &pStr0->vSupp[1];
|
|
*pvSuppB = &pStr1->vSupp[1];
|
|
pCovA = pStr0->pCover[1];
|
|
pCovB = pStr1->pCover[1];
|
|
}
|
|
else if ( pStr0->Depth + 1 == pStr1->Depth )
|
|
{
|
|
*pvSuppA = &pStr0->vSupp[0];
|
|
*pvSuppB = &pStr1->vSupp[1];
|
|
pCovA = pStr0->pCover[0];
|
|
pCovB = pStr1->pCover[1];
|
|
}
|
|
else if ( pStr0->Depth == pStr1->Depth + 1 )
|
|
{
|
|
*pvSuppA = &pStr0->vSupp[1];
|
|
*pvSuppB = &pStr1->vSupp[0];
|
|
pCovA = pStr0->pCover[1];
|
|
pCovB = pStr1->pCover[0];
|
|
}
|
|
else if ( pStr0->Depth < pStr1->Depth )
|
|
{
|
|
*pvSuppB = &pStr1->vSupp[1];
|
|
pCovB = pStr1->pCover[1];
|
|
}
|
|
else // if ( pStr0->Depth > pStr1->Depth )
|
|
{
|
|
*pvSuppA = &pStr0->vSupp[1];
|
|
pCovA = pStr0->pCover[1];
|
|
}
|
|
}
|
|
// complement the first if needed
|
|
if ( pCovA == PLA_EMPTY || !fCompl0 )
|
|
*pvCovA = pCovA;
|
|
else if ( pCovA && pCovA->nLits == 0 ) // topmost one is the tautology cube
|
|
*pvCovA = pCovA->pNext;
|
|
else
|
|
*pvCovA = p->pManMin->pOne0, p->pManMin->pOne0->pNext = pCovA;
|
|
// complement the second if needed
|
|
if ( pCovB == PLA_EMPTY || !fCompl1 )
|
|
*pvCovB = pCovB;
|
|
else if ( pCovB && pCovB->nLits == 0 ) // topmost one is the tautology cube
|
|
*pvCovB = pCovB->pNext;
|
|
else
|
|
*pvCovB = p->pManMin->pOne1, p->pManMin->pOne1->pNext = pCovB;
|
|
}
|
|
|
|
|
|
/*
|
|
if ( pObj->Id == 1371 )
|
|
{
|
|
int k;
|
|
printf( "Zero : " );
|
|
for ( k = 0; k < vSuppA->nSize; k++ )
|
|
printf( "%d ", vSuppA->pArray[k] );
|
|
printf( "\n" );
|
|
printf( "One : " );
|
|
for ( k = 0; k < vSuppB->nSize; k++ )
|
|
printf( "%d ", vSuppB->pArray[k] );
|
|
printf( "\n" );
|
|
printf( "Node : " );
|
|
for ( k = 0; k < vSupp0->nSize; k++ )
|
|
printf( "%d ", vSupp0->pArray[k] );
|
|
printf( "\n" );
|
|
printf( "\n" );
|
|
printf( "\n" );
|
|
Esop_CoverWrite( stdout, pCovA );
|
|
printf( "\n" );
|
|
Esop_CoverWrite( stdout, pCovB );
|
|
printf( "\n" );
|
|
}
|
|
*/
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|