mirror of https://github.com/YosysHQ/abc.git
291 lines
9.5 KiB
C
291 lines
9.5 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [wlcAbs.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: wlcAbs.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "wlc.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**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 ( 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 );
|
|
Wlc_NtkTransferNames( pNew, p );
|
|
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_AND, 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 );
|
|
Wlc_NtkTransferNames( pNew, p );
|
|
return pNew;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|