blob: 82a50d27d791a85a151ce4a6d0d043e6759438d1 [file] [log] [blame]
/**CFile****************************************************************
Copyright (c) The Regents of the University of California. All rights reserved.
Permission is hereby granted, without written agreement and without license or
royalty fees, to use, copy, modify, and distribute this software and its
documentation for any purpose, provided that the above copyright notice and
the following two paragraphs appear in all copies of this software.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
FileName [cnfCut.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [AIG-to-CNF conversion.]
Synopsis []
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - April 28, 2007.]
Revision [$Id: cnfCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
***********************************************************************/
#include "cnf.h"
#include "kit.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Allocates cut of the given size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Cnf_Cut_t * Cnf_CutAlloc( Cnf_Man_t * p, int nLeaves )
{
Cnf_Cut_t * pCut;
int nSize = sizeof(Cnf_Cut_t) + sizeof(int) * nLeaves + sizeof(unsigned) * Aig_TruthWordNum(nLeaves);
pCut = (Cnf_Cut_t *)Aig_MmFlexEntryFetch( p->pMemCuts, nSize );
pCut->nFanins = nLeaves;
pCut->nWords = Aig_TruthWordNum(nLeaves);
pCut->vIsop[0] = pCut->vIsop[1] = NULL;
return pCut;
}
/**Function*************************************************************
Synopsis [Deallocates cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cnf_CutFree( Cnf_Cut_t * pCut )
{
if ( pCut->vIsop[0] )
Vec_IntFree( pCut->vIsop[0] );
if ( pCut->vIsop[1] )
Vec_IntFree( pCut->vIsop[1] );
}
/**Function*************************************************************
Synopsis [Creates cut for the given node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Cnf_Cut_t * Cnf_CutCreate( Cnf_Man_t * p, Aig_Obj_t * pObj )
{
Dar_Cut_t * pCutBest;
Cnf_Cut_t * pCut;
unsigned * pTruth;
assert( Aig_ObjIsNode(pObj) );
pCutBest = Dar_ObjBestCut( pObj );
assert( pCutBest != NULL );
assert( pCutBest->nLeaves <= 4 );
pCut = Cnf_CutAlloc( p, pCutBest->nLeaves );
memcpy( pCut->pFanins, pCutBest->pLeaves, sizeof(int) * pCutBest->nLeaves );
pTruth = Cnf_CutTruth(pCut);
*pTruth = (pCutBest->uTruth << 16) | pCutBest->uTruth;
pCut->Cost = Cnf_CutSopCost( p, pCutBest );
return pCut;
}
/**Function*************************************************************
Synopsis [Deallocates cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cnf_CutPrint( Cnf_Cut_t * pCut )
{
int i;
printf( "{" );
for ( i = 0; i < pCut->nFanins; i++ )
printf( "%d ", pCut->pFanins[i] );
printf( " } " );
}
/**Function*************************************************************
Synopsis [Allocates cut of the given size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cnf_CutDeref( Cnf_Man_t * p, Cnf_Cut_t * pCut )
{
Aig_Obj_t * pObj;
int i;
Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i )
{
assert( pObj->nRefs > 0 );
pObj->nRefs--;
}
}
/**Function*************************************************************
Synopsis [Allocates cut of the given size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cnf_CutRef( Cnf_Man_t * p, Cnf_Cut_t * pCut )
{
Aig_Obj_t * pObj;
int i;
Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i )
{
pObj->nRefs++;
}
}
/**Function*************************************************************
Synopsis [Allocates cut of the given size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cnf_CutUpdateRefs( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, Cnf_Cut_t * pCutRes )
{
Cnf_CutDeref( p, pCut );
Cnf_CutDeref( p, pCutFan );
Cnf_CutRef( p, pCutRes );
}
/**Function*************************************************************
Synopsis [Merges two arrays of integers.]
Description [Returns the number of items.]
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Cnf_CutMergeLeaves( Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int * pFanins )
{
int i, k, nFanins = 0;
for ( i = k = 0; i < pCut->nFanins && k < pCutFan->nFanins; )
{
if ( pCut->pFanins[i] == pCutFan->pFanins[k] )
pFanins[nFanins++] = pCut->pFanins[i], i++, k++;
else if ( pCut->pFanins[i] < pCutFan->pFanins[k] )
pFanins[nFanins++] = pCut->pFanins[i], i++;
else
pFanins[nFanins++] = pCutFan->pFanins[k], k++;
}
for ( ; i < pCut->nFanins; i++ )
pFanins[nFanins++] = pCut->pFanins[i];
for ( ; k < pCutFan->nFanins; k++ )
pFanins[nFanins++] = pCutFan->pFanins[k];
return nFanins;
}
/**Function*************************************************************
Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline unsigned Cnf_TruthPhase( Cnf_Cut_t * pCut, Cnf_Cut_t * pCut1 )
{
unsigned uPhase = 0;
int i, k;
for ( i = k = 0; i < pCut->nFanins; i++ )
{
if ( k == pCut1->nFanins )
break;
if ( pCut->pFanins[i] < pCut1->pFanins[k] )
continue;
assert( pCut->pFanins[i] == pCut1->pFanins[k] );
uPhase |= (1 << i);
k++;
}
return uPhase;
}
/**Function*************************************************************
Synopsis [Removes the fanin variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cnf_CutRemoveIthVar( Cnf_Cut_t * pCut, int iVar, int iFan )
{
int i;
assert( pCut->pFanins[iVar] == iFan );
pCut->nFanins--;
for ( i = iVar; i < pCut->nFanins; i++ )
pCut->pFanins[i] = pCut->pFanins[i+1];
}
/**Function*************************************************************
Synopsis [Inserts the fanin variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cnf_CutInsertIthVar( Cnf_Cut_t * pCut, int iVar, int iFan )
{
int i;
for ( i = pCut->nFanins; i > iVar; i-- )
pCut->pFanins[i] = pCut->pFanins[i-1];
pCut->pFanins[iVar] = iFan;
pCut->nFanins++;
}
/**Function*************************************************************
Synopsis [Merges two cuts.]
Description [Returns NULL of the cuts cannot be merged.]
SideEffects []
SeeAlso []
***********************************************************************/
Cnf_Cut_t * Cnf_CutCompose( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int iFan )
{
Cnf_Cut_t * pCutRes;
static int pFanins[32];
unsigned * pTruth, * pTruthFan, * pTruthRes;
unsigned * pTop = p->pTruths[0], * pFan = p->pTruths[2], * pTemp = p->pTruths[3];
unsigned uPhase, uPhaseFan;
int i, iVar, nFanins, RetValue;
// make sure the second cut is the fanin of the first
for ( iVar = 0; iVar < pCut->nFanins; iVar++ )
if ( pCut->pFanins[iVar] == iFan )
break;
assert( iVar < pCut->nFanins );
// remove this variable
Cnf_CutRemoveIthVar( pCut, iVar, iFan );
// merge leaves of the cuts
nFanins = Cnf_CutMergeLeaves( pCut, pCutFan, pFanins );
if ( nFanins+1 > p->nMergeLimit )
{
Cnf_CutInsertIthVar( pCut, iVar, iFan );
return NULL;
}
// create new cut
pCutRes = Cnf_CutAlloc( p, nFanins );
memcpy( pCutRes->pFanins, pFanins, sizeof(int) * nFanins );
assert( pCutRes->nFanins <= pCut->nFanins + pCutFan->nFanins );
// derive its truth table
// get the truth tables in the composition space
pTruth = Cnf_CutTruth(pCut);
pTruthFan = Cnf_CutTruth(pCutFan);
pTruthRes = Cnf_CutTruth(pCutRes);
for ( i = 0; i < 2*pCutRes->nWords; i++ )
pTop[i] = pTruth[i % pCut->nWords];
for ( i = 0; i < pCutRes->nWords; i++ )
pFan[i] = pTruthFan[i % pCutFan->nWords];
// move the variable to the end
uPhase = Kit_BitMask( pCutRes->nFanins+1 ) & ~(1 << iVar);
Kit_TruthShrink( pTemp, pTop, pCutRes->nFanins, pCutRes->nFanins+1, uPhase, 1 );
// compute the phases
uPhase = Cnf_TruthPhase( pCutRes, pCut ) | (1 << pCutRes->nFanins);
uPhaseFan = Cnf_TruthPhase( pCutRes, pCutFan );
// permute truth-tables to the common support
Kit_TruthStretch( pTemp, pTop, pCut->nFanins+1, pCutRes->nFanins+1, uPhase, 1 );
Kit_TruthStretch( pTemp, pFan, pCutFan->nFanins, pCutRes->nFanins, uPhaseFan, 1 );
// perform Boolean operation
Kit_TruthMux( pTruthRes, pTop, pTop+pCutRes->nWords, pFan, pCutRes->nFanins );
// return the cut to its original condition
Cnf_CutInsertIthVar( pCut, iVar, iFan );
// consider the simple case
if ( pCutRes->nFanins < 5 )
{
pCutRes->Cost = p->pSopSizes[0xFFFF & *pTruthRes] + p->pSopSizes[0xFFFF & ~*pTruthRes];
return pCutRes;
}
// derive ISOP for positive phase
RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 );
pCutRes->vIsop[1] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory );
// derive ISOP for negative phase
Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins );
RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 );
pCutRes->vIsop[0] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory );
Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins );
// compute the cut cost
if ( pCutRes->vIsop[0] == NULL || pCutRes->vIsop[1] == NULL )
pCutRes->Cost = 127;
else if ( Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]) > 127 )
pCutRes->Cost = 127;
else
pCutRes->Cost = Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]);
return pCutRes;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////