mirror of https://github.com/YosysHQ/abc.git
230 lines
8.0 KiB
C
230 lines
8.0 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [mapperSwitch.c]
|
|
|
|
PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
|
|
|
|
Synopsis [Generic technology mapping engine.]
|
|
|
|
Author [MVSIS Group]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - September 8, 2003.]
|
|
|
|
Revision [$Id: mapperSwitch.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "mapperInt.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
static float Map_SwitchCutRefDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, int fReference );
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**function*************************************************************
|
|
|
|
synopsis [Computes the exact area associated with the cut.]
|
|
|
|
description []
|
|
|
|
sideeffects []
|
|
|
|
seealso []
|
|
|
|
***********************************************************************/
|
|
float Map_SwitchCutGetDerefed( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase )
|
|
{
|
|
float aResult, aResult2;
|
|
// assert( pNode->Switching > 0 );
|
|
aResult2 = Map_SwitchCutRefDeref( pNode, pCut, fPhase, 1 ); // reference
|
|
aResult = Map_SwitchCutRefDeref( pNode, pCut, fPhase, 0 ); // dereference
|
|
// assert( aResult == aResult2 );
|
|
return aResult;
|
|
}
|
|
|
|
/**function*************************************************************
|
|
|
|
synopsis [References the cut.]
|
|
|
|
description []
|
|
|
|
sideeffects []
|
|
|
|
seealso []
|
|
|
|
***********************************************************************/
|
|
float Map_SwitchCutRef( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase )
|
|
{
|
|
return Map_SwitchCutRefDeref( pNode, pCut, fPhase, 1 ); // reference
|
|
}
|
|
|
|
/**function*************************************************************
|
|
|
|
synopsis [References the cut.]
|
|
|
|
description []
|
|
|
|
sideeffects []
|
|
|
|
seealso []
|
|
|
|
***********************************************************************/
|
|
float Map_SwitchCutDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase )
|
|
{
|
|
return Map_SwitchCutRefDeref( pNode, pCut, fPhase, 0 ); // dereference
|
|
}
|
|
|
|
/**function*************************************************************
|
|
|
|
synopsis [References or dereferences the cut.]
|
|
|
|
description [This reference part is similar to Cudd_NodeReclaim().
|
|
The dereference part is similar to Cudd_RecursiveDeref().]
|
|
|
|
sideeffects []
|
|
|
|
seealso []
|
|
|
|
***********************************************************************/
|
|
float Map_SwitchCutRefDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, int fReference )
|
|
{
|
|
Map_Node_t * pNodeChild;
|
|
Map_Cut_t * pCutChild;
|
|
float aSwitchActivity;
|
|
int i, fPhaseChild;
|
|
|
|
// start switching activity for the node
|
|
aSwitchActivity = pNode->Switching;
|
|
// consider the elementary variable
|
|
if ( pCut->nLeaves == 1 )
|
|
return aSwitchActivity;
|
|
|
|
// go through the children
|
|
assert( pCut->M[fPhase].pSuperBest );
|
|
for ( i = 0; i < pCut->nLeaves; i++ )
|
|
{
|
|
pNodeChild = pCut->ppLeaves[i];
|
|
fPhaseChild = Map_CutGetLeafPhase( pCut, fPhase, i );
|
|
// get the reference counter of the child
|
|
|
|
if ( fReference )
|
|
{
|
|
if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present
|
|
{
|
|
// if this phase of the node is referenced, there is no recursive call
|
|
pNodeChild->nRefAct[2]++;
|
|
if ( pNodeChild->nRefAct[fPhaseChild]++ > 0 )
|
|
continue;
|
|
}
|
|
else // only one phase is present
|
|
{
|
|
// inverter should be added if the phase
|
|
// (a) has no reference and (b) is implemented using other phase
|
|
if ( pNodeChild->nRefAct[fPhaseChild]++ == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL )
|
|
aSwitchActivity += pNodeChild->Switching; // inverter switches the same as the node
|
|
// if the node is referenced, there is no recursive call
|
|
if ( pNodeChild->nRefAct[2]++ > 0 )
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present
|
|
{
|
|
// if this phase of the node is referenced, there is no recursive call
|
|
--pNodeChild->nRefAct[2];
|
|
if ( --pNodeChild->nRefAct[fPhaseChild] > 0 )
|
|
continue;
|
|
}
|
|
else // only one phase is present
|
|
{
|
|
// inverter should be added if the phase
|
|
// (a) has no reference and (b) is implemented using other phase
|
|
if ( --pNodeChild->nRefAct[fPhaseChild] == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL )
|
|
aSwitchActivity += pNodeChild->Switching; // inverter switches the same as the node
|
|
// if the node is referenced, there is no recursive call
|
|
if ( --pNodeChild->nRefAct[2] > 0 )
|
|
continue;
|
|
}
|
|
assert( pNodeChild->nRefAct[fPhaseChild] >= 0 );
|
|
}
|
|
|
|
// get the child cut
|
|
pCutChild = pNodeChild->pCutBest[fPhaseChild];
|
|
// if the child does not have this phase mapped, take the opposite phase
|
|
if ( pCutChild == NULL )
|
|
{
|
|
fPhaseChild = !fPhaseChild;
|
|
pCutChild = pNodeChild->pCutBest[fPhaseChild];
|
|
}
|
|
// reference and compute area recursively
|
|
aSwitchActivity += Map_SwitchCutRefDeref( pNodeChild, pCutChild, fPhaseChild, fReference );
|
|
}
|
|
return aSwitchActivity;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes the array of mapping.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
float Map_MappingGetSwitching( Map_Man_t * pMan )
|
|
{
|
|
Map_Node_t * pNode;
|
|
float Switch = 0.0;
|
|
int i;
|
|
for ( i = 0; i < pMan->vMapObjs->nSize; i++ )
|
|
{
|
|
pNode = pMan->vMapObjs->pArray[i];
|
|
if ( pNode->nRefAct[2] == 0 )
|
|
continue;
|
|
// at least one phase has the best cut assigned
|
|
assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL );
|
|
// at least one phase is used in the mapping
|
|
assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 );
|
|
// compute the array due to the supergate
|
|
if ( Map_NodeIsAnd(pNode) )
|
|
{
|
|
// count switching of the negative phase
|
|
if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) )
|
|
Switch += pNode->Switching;
|
|
// count switching of the positive phase
|
|
if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) )
|
|
Switch += pNode->Switching;
|
|
}
|
|
// count switching of the interver if we need to implement one phase with another phase
|
|
if ( (pNode->pCutBest[0] == NULL && pNode->nRefAct[0] > 0) ||
|
|
(pNode->pCutBest[1] == NULL && pNode->nRefAct[1] > 0) )
|
|
Switch += pNode->Switching; // inverter switches the same as the node
|
|
}
|
|
// add buffers for each CO driven by a CI
|
|
for ( i = 0; i < pMan->nOutputs; i++ )
|
|
if ( Map_NodeIsVar(pMan->pOutputs[i]) && !Map_IsComplement(pMan->pOutputs[i]) )
|
|
Switch += pMan->pOutputs[i]->Switching;
|
|
return Switch;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|