Commit 54670783 by Alan Mishchenko

Better resolution of CO drivers. Should impact the QoR after 'if'.

parent 76539c19
...@@ -282,6 +282,7 @@ extern int Hop_DagSize( Hop_Obj_t * pObj ); ...@@ -282,6 +282,7 @@ extern int Hop_DagSize( Hop_Obj_t * pObj );
extern void Hop_ConeUnmark_rec( Hop_Obj_t * pObj ); extern void Hop_ConeUnmark_rec( Hop_Obj_t * pObj );
extern Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pObj, int nVars ); extern Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pObj, int nVars );
extern Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar ); extern Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar );
extern Hop_Obj_t * Hop_Complement( Hop_Man_t * p, Hop_Obj_t * pRoot, int iVar );
extern Hop_Obj_t * Hop_Remap( Hop_Man_t * p, Hop_Obj_t * pRoot, unsigned uSupp, int nVars ); extern Hop_Obj_t * Hop_Remap( Hop_Man_t * p, Hop_Obj_t * pRoot, unsigned uSupp, int nVars );
/*=== hopMan.c ==========================================================*/ /*=== hopMan.c ==========================================================*/
extern Hop_Man_t * Hop_ManStart(); extern Hop_Man_t * Hop_ManStart();
......
...@@ -397,6 +397,60 @@ Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, in ...@@ -397,6 +397,60 @@ Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, in
/**Function************************************************************* /**Function*************************************************************
Synopsis [Complements the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Hop_Complement_rec( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pVar )
{
assert( !Hop_IsComplement(pObj) );
if ( Hop_ObjIsMarkA(pObj) )
return;
if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) )
{
pObj->pData = pObj == pVar ? Hop_Not(pObj) : pObj;
return;
}
Hop_Complement_rec( p, Hop_ObjFanin0(pObj), pVar );
Hop_Complement_rec( p, Hop_ObjFanin1(pObj), pVar );
pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) );
assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
Hop_ObjSetMarkA( pObj );
}
/**Function*************************************************************
Synopsis [Complements the AIG (pRoot) with the function (pFunc) using PI var (iVar).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Hop_Obj_t * Hop_Complement( Hop_Man_t * p, Hop_Obj_t * pRoot, int iVar )
{
// quit if the PI variable is not defined
if ( iVar >= Hop_ManPiNum(p) )
{
printf( "Hop_Complement(): The PI variable %d is not defined.\n", iVar );
return NULL;
}
// recursively perform composition
Hop_Complement_rec( p, Hop_Regular(pRoot), Hop_ManPi(p, iVar) );
// clear the markings
Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
}
/**Function*************************************************************
Synopsis [Remaps the AIG (pRoot) to have the given support (uSupp).] Synopsis [Remaps the AIG (pRoot) to have the given support (uSupp).]
Description [] Description []
......
...@@ -746,6 +746,7 @@ extern ABC_DLL int Abc_NodeIsConst1( Abc_Obj_t * pNode ); ...@@ -746,6 +746,7 @@ extern ABC_DLL int Abc_NodeIsConst1( Abc_Obj_t * pNode );
extern ABC_DLL int Abc_NodeIsBuf( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeIsBuf( Abc_Obj_t * pNode );
extern ABC_DLL int Abc_NodeIsInv( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeIsInv( Abc_Obj_t * pNode );
extern ABC_DLL void Abc_NodeComplement( Abc_Obj_t * pNode ); extern ABC_DLL void Abc_NodeComplement( Abc_Obj_t * pNode );
extern ABC_DLL void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin );
/*=== abcOdc.c ==========================================================*/ /*=== abcOdc.c ==========================================================*/
typedef struct Odc_Man_t_ Odc_Man_t; typedef struct Odc_Man_t_ Odc_Man_t;
extern ABC_DLL Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ); extern ABC_DLL Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose );
......
...@@ -952,14 +952,55 @@ void Abc_NodeComplement( Abc_Obj_t * pNode ) ...@@ -952,14 +952,55 @@ void Abc_NodeComplement( Abc_Obj_t * pNode )
assert( Abc_ObjIsNode(pNode) ); assert( Abc_ObjIsNode(pNode) );
if ( Abc_NtkHasSop(pNode->pNtk) ) if ( Abc_NtkHasSop(pNode->pNtk) )
Abc_SopComplement( (char *)pNode->pData ); Abc_SopComplement( (char *)pNode->pData );
else if ( Abc_NtkHasAig(pNode->pNtk) )
pNode->pData = Hop_Not( (Hop_Obj_t *)pNode->pData );
else if ( Abc_NtkHasBdd(pNode->pNtk) ) else if ( Abc_NtkHasBdd(pNode->pNtk) )
pNode->pData = Cudd_Not( pNode->pData ); pNode->pData = Cudd_Not( pNode->pData );
else
assert( 0 );
}
/**Function*************************************************************
Synopsis [Changes the polarity of one fanin.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin )
{
int iFanin;
if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 )
{
printf( "Node %s should be among", Abc_ObjName(pFanin) );
printf( " the fanins of node %s...\n", Abc_ObjName(pNode) );
return;
}
if ( Abc_NtkHasSop(pNode->pNtk) )
Abc_SopComplementVar( (char *)pNode->pData, iFanin );
else if ( Abc_NtkHasAig(pNode->pNtk) ) else if ( Abc_NtkHasAig(pNode->pNtk) )
pNode->pData = Hop_Not( (Hop_Obj_t *)pNode->pData ); pNode->pData = Hop_Complement( (Hop_Man_t *)pNode->pNtk->pManFunc, (Hop_Obj_t *)pNode->pData, iFanin );
else if ( Abc_NtkHasBdd(pNode->pNtk) )
{
DdManager * dd = (DdManager *)pNode->pNtk->pManFunc;
DdNode * bVar, * bCof0, * bCof1;
bVar = Cudd_bddIthVar( dd, iFanin );
bCof0 = Cudd_Cofactor( dd, (DdNode *)pNode->pData, Cudd_Not(bVar) ); Cudd_Ref( bCof0 );
bCof1 = Cudd_Cofactor( dd, (DdNode *)pNode->pData, bVar ); Cudd_Ref( bCof1 );
Cudd_RecursiveDeref( dd, (DdNode *)pNode->pData );
pNode->pData = Cudd_bddIte( dd, bVar, bCof0, bCof1 ); Cudd_Ref( (DdNode *)pNode->pData );
Cudd_RecursiveDeref( dd, bCof0 );
Cudd_RecursiveDeref( dd, bCof1 );
}
else else
assert( 0 ); assert( 0 );
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
/// END OF FILE /// /// END OF FILE ///
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
......
...@@ -943,7 +943,7 @@ int Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ) ...@@ -943,7 +943,7 @@ int Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, int fDuplicate ) int Abc_NtkLogicMakeSimpleCos2( Abc_Ntk_t * pNtk, int fDuplicate )
{ {
Abc_Obj_t * pNode, * pDriver; Abc_Obj_t * pNode, * pDriver;
int i, nDupGates = 0; int i, nDupGates = 0;
...@@ -985,6 +985,173 @@ int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, int fDuplicate ) ...@@ -985,6 +985,173 @@ int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, int fDuplicate )
return nDupGates; return nDupGates;
} }
/**Function*************************************************************
Synopsis [Transforms the network to have simple COs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, int fDuplicate )
{
Vec_Ptr_t * vDrivers, * vCoTerms;
Abc_Obj_t * pNode, * pDriver, * pDriverNew, * pFanin;
int i, k, LevelMax, nTotal = 0;
assert( Abc_NtkIsLogic(pNtk) );
LevelMax = Abc_NtkLevel(pNtk);
// collect drivers pointed by complemented edges
vDrivers = Vec_PtrAlloc( 100 );
Abc_NtkIncrementTravId( pNtk );
Abc_NtkForEachCo( pNtk, pNode, i )
{
if ( !Abc_ObjFaninC0(pNode) )
continue;
pDriver = Abc_ObjFanin0(pNode);
if ( Abc_NodeIsTravIdCurrent(pDriver) )
continue;
Abc_NodeSetTravIdCurrent(pDriver);
Vec_PtrPush( vDrivers, pDriver );
}
// fix complemented drivers
if ( Vec_PtrSize(vDrivers) > 0 )
{
int nDupGates = 0, nDupInvs = 0, nDupChange = 0;
Vec_Ptr_t * vFanouts = Vec_PtrAlloc( 100 );
Vec_PtrForEachEntry( Abc_Obj_t *, vDrivers, pDriver, i )
{
int fHasDir = 0, fHasInv = 0, fHasOther = 0;
Abc_ObjForEachFanout( pDriver, pNode, k )
{
if ( !Abc_ObjIsCo(pNode) )
{
assert( !Abc_ObjFaninC0(pNode) );
fHasOther = 1;
continue;
}
if ( Abc_ObjFaninC0(pNode) )
fHasInv = 1;
else //if ( Abc_ObjFaninC0(pNode) )
fHasDir = 1;
}
assert( fHasInv );
if ( Abc_ObjIsCi(pDriver) || fHasDir || (fHasOther && Abc_NtkHasMapping(pNtk)) ) // cannot change
{
// duplicate if critical
if ( fDuplicate && Abc_ObjIsNode(pDriver) && Abc_ObjLevel(pDriver) == LevelMax )
{
pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 );
Abc_ObjForEachFanin( pDriver, pFanin, k )
Abc_ObjAddFanin( pDriverNew, pFanin );
Abc_NodeComplement( pDriverNew );
nDupGates++;
}
else // add inverter
{
pDriverNew = Abc_NtkCreateNodeInv( pNtk, pDriver );
nDupInvs++;
}
// collect CO fanouts to be redirected to the new node
Vec_PtrClear( vFanouts );
Abc_ObjForEachFanout( pDriver, pNode, k )
if ( Abc_ObjIsCo(pNode) && Abc_ObjFaninC0(pNode) )
Vec_PtrPush( vFanouts, pNode );
assert( Vec_PtrSize(vFanouts) > 0 );
Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pNode, k )
{
Abc_ObjXorFaninC( pNode, 0 );
Abc_ObjPatchFanin( pNode, pDriver, pDriverNew );
assert( Abc_ObjIsCi(pDriver) || Abc_ObjFanoutNum(pDriver) > 0 );
}
}
else // can change
{
// change polarity of the driver
assert( Abc_ObjIsNode(pDriver) );
Abc_NodeComplement( pDriver );
Abc_ObjForEachFanout( pDriver, pNode, k )
{
if ( Abc_ObjIsCo(pNode) )
{
assert( Abc_ObjFaninC0(pNode) );
Abc_ObjXorFaninC( pNode, 0 );
}
else if ( Abc_ObjIsNode(pNode) )
Abc_NodeComplementInput( pNode, pDriver );
else assert( 0 );
}
nDupChange++;
}
}
Vec_PtrFree( vFanouts );
// printf( "Resolving inverted CO drivers: Invs = %d. Dups = %d. Changes = %d.\n",
// nDupInvs, nDupGates, nDupChange );
nTotal += nDupInvs + nDupGates;
}
Vec_PtrFree( vDrivers );
// collect COs that needs fixing by adding buffers or duplicating
vCoTerms = Vec_PtrAlloc( 100 );
Abc_NtkIncrementTravId( pNtk );
Abc_NtkForEachCo( pNtk, pNode, i )
{
// if the driver is a CI and has different name, this is an error
pDriver = Abc_ObjFanin0(pNode);
if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) )
{
Vec_PtrPush( vCoTerms, pNode );
continue;
}
// if the driver is visited for the first time, remember the CO name
if ( !Abc_NodeIsTravIdCurrent(pDriver) )
{
pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode);
Abc_NodeSetTravIdCurrent(pDriver);
continue;
}
// the driver has second CO - if they have different name, this is an error
if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names
{
Vec_PtrPush( vCoTerms, pNode );
continue;
}
}
// fix duplication problem
if ( Vec_PtrSize(vCoTerms) > 0 )
{
int nDupBufs = 0, nDupGates = 0;
Vec_PtrForEachEntry( Abc_Obj_t *, vCoTerms, pNode, i )
{
pDriver = Abc_ObjFanin0(pNode);
// duplicate if critical
if ( fDuplicate && Abc_ObjIsNode(pDriver) && Abc_ObjLevel(pDriver) == LevelMax )
{
pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 );
Abc_ObjForEachFanin( pDriver, pFanin, k )
Abc_ObjAddFanin( pDriverNew, pFanin );
nDupGates++;
}
else // add buffer
{
pDriverNew = Abc_NtkCreateNodeBuf( pNtk, pDriver );
nDupBufs++;
}
// swing the PO
Abc_ObjPatchFanin( pNode, pDriver, pDriverNew );
assert( Abc_ObjIsCi(pDriver) || Abc_ObjFanoutNum(pDriver) > 0 );
}
// printf( "Resolving shared CO drivers: Bufs = %d. Dups = %d.\n", nDupBufs, nDupGates );
nTotal += nDupBufs + nDupGates;
}
Vec_PtrFree( vCoTerms );
return nTotal;
}
/**Function************************************************************* /**Function*************************************************************
Synopsis [Inserts a new node in the order by levels.] Synopsis [Inserts a new node in the order by levels.]
......
...@@ -39,7 +39,6 @@ static int Abc_NodeDroppingCost( Abc_Obj_t * pNode ); ...@@ -39,7 +39,6 @@ static int Abc_NodeDroppingCost( Abc_Obj_t * pNode );
static int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ); static int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes );
static void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose ); static void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose );
static void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, int fConst0 ); static void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, int fConst0 );
static void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin );
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS /// /// FUNCTION DEFINITIONS ///
...@@ -684,39 +683,6 @@ void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, int fConst0 ) ...@@ -684,39 +683,6 @@ void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, int fConst0 )
Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bTemp );
} }
/**Function*************************************************************
Synopsis [Changes the polarity of one fanin.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin )
{
DdManager * dd = (DdManager *)pNode->pNtk->pManFunc;
DdNode * bVar, * bCof0, * bCof1;
int iFanin;
assert( Abc_NtkIsBddLogic(pNode->pNtk) );
if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 )
{
printf( "Node %s should be among", Abc_ObjName(pFanin) );
printf( " the fanins of node %s...\n", Abc_ObjName(pNode) );
return;
}
bVar = Cudd_bddIthVar( dd, iFanin );
bCof0 = Cudd_Cofactor( dd, (DdNode *)pNode->pData, Cudd_Not(bVar) ); Cudd_Ref( bCof0 );
bCof1 = Cudd_Cofactor( dd, (DdNode *)pNode->pData, bVar ); Cudd_Ref( bCof1 );
Cudd_RecursiveDeref( dd, (DdNode *)pNode->pData );
pNode->pData = Cudd_bddIte( dd, bVar, bCof0, bCof1 ); Cudd_Ref( (DdNode *)pNode->pData );
Cudd_RecursiveDeref( dd, bCof0 );
Cudd_RecursiveDeref( dd, bCof1 );
}
/**Function************************************************************* /**Function*************************************************************
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment