blob: 0b3eed01660288dc7a678172d7615e5285b8a3d5 [file] [log] [blame]
/**CFile****************************************************************
FileName [wlcUif.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Verilog parser.]
Synopsis [Abstraction for word-level networks.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - August 22, 2014.]
Revision [$Id: wlcUif.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $]
***********************************************************************/
#include "wlc.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Collect adds and mults.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Wlc_NtkCollectBoxes( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds )
{
int i, iObj;
Vec_Int_t * vBoxes = Vec_IntAlloc( Vec_IntSize(vBoxIds) + 1 );
Vec_IntPush( vBoxes, Vec_IntSize(vBoxIds) );
Vec_IntForEachEntry( vBoxIds, iObj, i )
Vec_IntPush( vBoxes, Wlc_ObjNameId(p, iObj) );
Abc_FrameSetBoxes( Vec_IntReleaseArray(vBoxes) );
Vec_IntFree( vBoxes );
}
Vec_Int_t * Wlc_NtkCollectAddMult( Wlc_Ntk_t * p, Wlc_BstPar_t * pPar, int * pCountA, int * pCountM )
{
Vec_Int_t * vBoxIds;
Wlc_Obj_t * pObj; int i;
*pCountA = *pCountM = 0;
if ( pPar->nAdderLimit == 0 && pPar->nMultLimit == 0 )
return NULL;
vBoxIds = Vec_IntAlloc( 100 );
Wlc_NtkForEachObj( p, pObj, i )
{
if ( pObj->Type == WLC_OBJ_ARI_ADD && pPar->nAdderLimit && Wlc_ObjRange(pObj) >= pPar->nAdderLimit )
Vec_IntPush( vBoxIds, i ), (*pCountA)++;
else if ( pObj->Type == WLC_OBJ_ARI_MULTI && pPar->nMultLimit && Wlc_ObjRange(pObj) >= pPar->nMultLimit )
Vec_IntPush( vBoxIds, i ), (*pCountM)++;
}
if ( Vec_IntSize( vBoxIds ) > 0 )
{
Wlc_NtkCollectBoxes( p, vBoxIds );
return vBoxIds;
}
Vec_IntFree( vBoxIds );
return NULL;
}
/**Function*************************************************************
Synopsis [Check if two objects have the same input/output signatures.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Wlc_NtkPairIsUifable( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Wlc_Obj_t * pObj2 )
{
Wlc_Obj_t * pFanin, * pFanin2; int k;
if ( Wlc_ObjRange(pObj) != Wlc_ObjRange(pObj2) )
return 0;
if ( Wlc_ObjIsSigned(pObj) != Wlc_ObjIsSigned(pObj2) )
return 0;
if ( Wlc_ObjFaninNum(pObj) != Wlc_ObjFaninNum(pObj2) )
return 0;
for ( k = 0; k < Wlc_ObjFaninNum(pObj); k++ )
{
pFanin = Wlc_ObjFanin(p, pObj, k);
pFanin2 = Wlc_ObjFanin(p, pObj2, k);
if ( Wlc_ObjRange(pFanin) != Wlc_ObjRange(pFanin2) )
return 0;
if ( Wlc_ObjIsSigned(pFanin) != Wlc_ObjIsSigned(pFanin2) )
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis [Collect IDs of the multipliers.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Wlc_NtkCollectMultipliers( Wlc_Ntk_t * p )
{
Wlc_Obj_t * pObj; int i;
Vec_Int_t * vBoxIds = Vec_IntAlloc( 100 );
Wlc_NtkForEachObj( p, pObj, i )
if ( pObj->Type == WLC_OBJ_ARI_MULTI )
Vec_IntPush( vBoxIds, i );
if ( Vec_IntSize( vBoxIds ) > 0 )
return vBoxIds;
Vec_IntFree( vBoxIds );
return NULL;
}
/**Function*************************************************************
Synopsis [Returns all pairs of uifable multipliers.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Wlc_NtkFindUifableMultiplierPairs( Wlc_Ntk_t * p )
{
Vec_Int_t * vMultis = Wlc_NtkCollectMultipliers( p );
Vec_Int_t * vPairs = Vec_IntAlloc( 2 );
Wlc_Obj_t * pObj, * pObj2; int i, k;
// iterate through unique pairs
Wlc_NtkForEachObjVec( vMultis, p, pObj, i )
Wlc_NtkForEachObjVec( vMultis, p, pObj2, k )
{
if ( k == i )
break;
if ( Wlc_NtkPairIsUifable( p, pObj, pObj2 ) )
{
Vec_IntPush( vPairs, Wlc_ObjId(p, pObj) );
Vec_IntPush( vPairs, Wlc_ObjId(p, pObj2) );
}
}
Vec_IntFree( vMultis );
if ( Vec_IntSize( vPairs ) > 0 )
return vPairs;
Vec_IntFree( vPairs );
return NULL;
}
/**Function*************************************************************
Synopsis [Abstracts nodes by replacing their outputs with new PIs.]
Description [If array is NULL, abstract all multipliers.]
SideEffects []
SeeAlso []
***********************************************************************/
Wlc_Ntk_t * Wlc_NtkAbstractNodes( Wlc_Ntk_t * p, Vec_Int_t * vNodesInit )
{
Vec_Int_t * vNodes = vNodesInit;
Wlc_Ntk_t * pNew;
Wlc_Obj_t * pObj;
int i, k, iObj, iFanin;
// get multipliers if not given
if ( vNodes == NULL )
vNodes = Wlc_NtkCollectMultipliers( p );
if ( vNodes == NULL )
return NULL;
// mark nodes
Wlc_NtkForEachObjVec( vNodes, p, pObj, i )
pObj->Mark = 1;
// iterate through the nodes in the DFS order
Wlc_NtkCleanCopy( p );
Wlc_NtkForEachObj( p, pObj, i )
{
if ( i == Vec_IntSize(&p->vCopies) )
break;
if ( pObj->Mark ) {
// clean
pObj->Mark = 0;
// add fresh PI with the same number of bits
iObj = Wlc_ObjAlloc( p, WLC_OBJ_PI, Wlc_ObjIsSigned(pObj), Wlc_ObjRange(pObj) - 1, 0 );
}
else {
// update fanins
Wlc_ObjForEachFanin( pObj, iFanin, k )
Wlc_ObjFanins(pObj)[k] = Wlc_ObjCopy(p, iFanin);
// node to remain
iObj = i;
}
Wlc_ObjSetCopy( p, i, iObj );
}
// POs do not change in this procedure
if ( vNodes != vNodesInit )
Vec_IntFree( vNodes );
// reconstruct topological order
pNew = Wlc_NtkDupDfs( p, 0, 1 );
return pNew;
}
/**Function*************************************************************
Synopsis [Adds UIF constraints to node pairs and updates POs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Wlc_Ntk_t * Wlc_NtkUifNodePairs( Wlc_Ntk_t * p, Vec_Int_t * vPairsInit )
{
Vec_Int_t * vPairs = vPairsInit;
Wlc_Ntk_t * pNew;
Wlc_Obj_t * pObj, * pObj2;
Vec_Int_t * vUifConstrs, * vCompares, * vFanins;
int i, k, iObj, iObj2, iObjNew, iObjNew2;
int iFanin, iFanin2, iFaninNew;
// get multiplier pairs if not given
if ( vPairs == NULL )
vPairs = Wlc_NtkFindUifableMultiplierPairs( p );
if ( vPairs == NULL )
return NULL;
// sanity checks
assert( Vec_IntSize(vPairs) > 0 && Vec_IntSize(vPairs) % 2 == 0 );
// iterate through node pairs
vFanins = Vec_IntAlloc( 100 );
vCompares = Vec_IntAlloc( 100 );
vUifConstrs = Vec_IntAlloc( 100 );
Vec_IntForEachEntryDouble( vPairs, iObj, iObj2, i )
{
// get two nodes
pObj = Wlc_NtkObj( p, iObj );
pObj2 = Wlc_NtkObj( p, iObj2 );
assert( Wlc_NtkPairIsUifable(p, pObj, pObj2) );
// create fanin comparator nodes
Vec_IntClear( vCompares );
Wlc_ObjForEachFanin( pObj, iFanin, k )
{
iFanin2 = Wlc_ObjFaninId( pObj2, k );
Vec_IntFillTwo( vFanins, 2, iFanin, iFanin2 );
iFaninNew = Wlc_ObjCreate( p, WLC_OBJ_COMP_NOTEQU, 0, 0, 0, vFanins );
Vec_IntPush( vCompares, iFaninNew );
// note that a pointer to Wlc_Obj_t (for example, pObj) can be invalidated after a call to
// Wlc_ObjCreate() due to a possible realloc of the internal array of objects...
pObj = Wlc_NtkObj( p, iObj );
}
// concatenate fanin comparators
iObjNew = Wlc_ObjCreate( p, WLC_OBJ_BIT_CONCAT, 0, Vec_IntSize(vCompares) - 1, 0, vCompares );
// create reduction-OR node
Vec_IntFill( vFanins, 1, iObjNew );
iObjNew = Wlc_ObjCreate( p, WLC_OBJ_REDUCT_OR, 0, 0, 0, vFanins );
// craete output comparator node
Vec_IntFillTwo( vFanins, 2, iObj, iObj2 );
iObjNew2 = Wlc_ObjCreate( p, WLC_OBJ_COMP_EQU, 0, 0, 0, vFanins );
// create implication node (iObjNew is already complemented above)
Vec_IntFillTwo( vFanins, 2, iObjNew, iObjNew2 );
iObjNew = Wlc_ObjCreate( p, WLC_OBJ_LOGIC_OR, 0, 0, 0, vFanins );
// save the constraint
Vec_IntPush( vUifConstrs, iObjNew );
}
// derive the AND of the UIF contraints
assert( Vec_IntSize(vUifConstrs) > 0 );
if ( Vec_IntSize(vUifConstrs) == 1 )
iObjNew = Vec_IntEntry( vUifConstrs, 0 );
else
{
// concatenate
iObjNew = Wlc_ObjCreate( p, WLC_OBJ_BIT_CONCAT, 0, Vec_IntSize(vUifConstrs) - 1, 0, vUifConstrs );
// create reduction-AND node
Vec_IntFill( vFanins, 1, iObjNew );
iObjNew = Wlc_ObjCreate( p, WLC_OBJ_REDUCT_AND, 0, 0, 0, vFanins );
}
// update each PO to point to the new node
Wlc_NtkForEachPo( p, pObj, i )
{
iObj = Wlc_ObjId(p, pObj);
Vec_IntFillTwo( vFanins, 2, iObj, iObjNew );
iObjNew = Wlc_ObjCreate( p, WLC_OBJ_LOGIC_AND, 0, 0, 0, vFanins );
// note that a pointer to Wlc_Obj_t (for example, pObj) can be invalidated after a call to
// Wlc_ObjCreate() due to a possible realloc of the internal array of objects...
pObj = Wlc_NtkObj( p, iObj );
// update PO/CO arrays
assert( Vec_IntEntry(&p->vPos, i) == iObj );
assert( Vec_IntEntry(&p->vCos, i) == iObj );
Vec_IntWriteEntry( &p->vPos, i, iObjNew );
Vec_IntWriteEntry( &p->vCos, i, iObjNew );
// transfer the PO attribute
Wlc_NtkObj(p, iObjNew)->fIsPo = 1;
assert( pObj->fIsPo );
pObj->fIsPo = 0;
}
// cleanup
Vec_IntFree( vUifConstrs );
Vec_IntFree( vCompares );
Vec_IntFree( vFanins );
if ( vPairs != vPairsInit )
Vec_IntFree( vPairs );
// reconstruct topological order
pNew = Wlc_NtkDupDfs( p, 0, 1 );
return pNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END