mirror of
https://github.com/YosysHQ/abc.git
synced 2026-09-07 19:17:35 +02:00
321 lines
9.2 KiB
C
321 lines
9.2 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [pgaUtil.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [FPGA mapper.]
|
|
|
|
Synopsis [Verious utilities.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: pgaUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "pgaInt.h"
|
|
|
|
#define PGA_CO_LIST_SIZE 5
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the results of mapping.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Ptr_t * Pga_MappingResults( Pga_Man_t * p )
|
|
{
|
|
Vec_Ptr_t * vResult;
|
|
Pga_Node_t * pNode;
|
|
int i;
|
|
vResult = Vec_PtrAlloc( 1000 );
|
|
Pga_ManForEachObjDirect( p, pNode, i )
|
|
{
|
|
// skip the CIs and nodes not used in the mapping
|
|
if ( !pNode->Match.pCut || !pNode->nRefs )
|
|
continue;
|
|
pNode->Match.pCut->uSign = pNode->Id;
|
|
Vec_PtrPush( vResult, pNode->Match.pCut );
|
|
}
|
|
return vResult;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes the maximum arrival times.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
float Pga_TimeComputeArrivalMax( Pga_Man_t * p )
|
|
{
|
|
Pga_Node_t * pNode;
|
|
float ArrivalMax;
|
|
int i;
|
|
ArrivalMax = -ABC_INFINITY;
|
|
Pga_ManForEachCoDriver( p, pNode, i )
|
|
ArrivalMax = ABC_MAX( ArrivalMax, pNode->Match.Delay );
|
|
return ArrivalMax;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes required times of all nodes.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Pga_MappingComputeRequired( Pga_Man_t * p )
|
|
{
|
|
Pga_Node_t * pNode, * pFanin;
|
|
Cut_Cut_t * pCutBest;
|
|
float RequiredNew;
|
|
int i, k;
|
|
// clean the required times of all nodes
|
|
Pga_ManForEachObjDirect( p, pNode, i )
|
|
pNode->Required = ABC_INFINITY;
|
|
// get the global required times
|
|
p->AreaGlobal = Pga_TimeComputeArrivalMax( p );
|
|
p->RequiredGlobal = ABC_MAX( p->AreaGlobal, p->RequiredUser );
|
|
// set the global required times of the CO drivers
|
|
Pga_ManForEachCoDriver( p, pNode, i )
|
|
pNode->Required = p->RequiredGlobal;
|
|
// propagate the required times in the reverse topological order
|
|
Pga_ManForEachObjReverse( p, pNode, i )
|
|
{
|
|
// skip the CIs and nodes not used in the mapping
|
|
if ( !pNode->Match.pCut || !pNode->nRefs )
|
|
continue;
|
|
// get the required time for children
|
|
pCutBest = pNode->Match.pCut;
|
|
RequiredNew = pNode->Required - p->pLutDelays[pCutBest->nLeaves];
|
|
// update the required time of the children
|
|
for ( k = 0; k < (int)pCutBest->nLeaves; k++ )
|
|
{
|
|
pFanin = Pga_Node( p, pCutBest->pLeaves[k] );
|
|
pFanin->Required = ABC_MIN( pFanin->Required, RequiredNew );
|
|
}
|
|
}
|
|
// check that the required times does not contradict the arrival times
|
|
Pga_ManForEachObjDirect( p, pNode, i )
|
|
assert( !pNode->Match.pCut || pNode->Match.Delay < pNode->Required + p->Epsilon );
|
|
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Sets references and computes area for the current mapping.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
float Pga_MappingSetRefsAndArea( Pga_Man_t * p )
|
|
{
|
|
Pga_Node_t * pNode, * pFanin;
|
|
Cut_Cut_t * pCutBest;
|
|
float AreaTotal;
|
|
int i, k;
|
|
// clean all the references
|
|
Pga_ManForEachObjDirect( p, pNode, i )
|
|
pNode->nRefs = 0;
|
|
// set the references of the CO drivers
|
|
Pga_ManForEachCoDriver( p, pNode, i )
|
|
pNode->nRefs++;
|
|
// go through the nodes in the reverse order
|
|
AreaTotal = 0.0;
|
|
Pga_ManForEachObjReverse( p, pNode, i )
|
|
{
|
|
// skip the CIs and nodes not used in the mapping
|
|
if ( !pNode->Match.pCut || !pNode->nRefs )
|
|
continue;
|
|
// increate the reference count of the children
|
|
pCutBest = pNode->Match.pCut;
|
|
AreaTotal += p->pLutAreas[pCutBest->nLeaves];
|
|
// update the required time of the children
|
|
for ( k = 0; k < (int)pCutBest->nLeaves; k++ )
|
|
{
|
|
pFanin = Pga_Node( p, pCutBest->pLeaves[k] );
|
|
pFanin->nRefs++;
|
|
}
|
|
}
|
|
return AreaTotal;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Computes switching activity of the mapping.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
float Pga_MappingGetSwitching( Pga_Man_t * p )
|
|
{
|
|
float Switching;
|
|
Pga_Node_t * pNode;
|
|
int i;
|
|
Switching = 0;
|
|
Pga_ManForEachObjDirect( p, pNode, i )
|
|
{
|
|
// skip the CIs and nodes not used in the mapping
|
|
if ( !pNode->Match.pCut || !pNode->nRefs )
|
|
continue;
|
|
Switching += pNode->Switching;
|
|
}
|
|
return Switching;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Compares the outputs by their arrival times.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Pga_MappingCompareOutputDelay( Pga_Node_t ** ppNode1, Pga_Node_t ** ppNode2 )
|
|
{
|
|
Pga_Node_t * pNode1 = *ppNode1;
|
|
Pga_Node_t * pNode2 = *ppNode2;
|
|
float Arrival1 = pNode1->Match.Delay;
|
|
float Arrival2 = pNode2->Match.Delay;
|
|
if ( Arrival1 < Arrival2 )
|
|
return -1;
|
|
if ( Arrival1 > Arrival2 )
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Finds given number of latest arriving COs.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Pga_MappingFindLatest( Pga_Man_t * p, int * pNodes, int nNodesMax )
|
|
{
|
|
Pga_Node_t * pNodeI, * pNodeK;
|
|
Abc_Obj_t * pObjCo;
|
|
int nNodes, i, k, v;
|
|
assert( Abc_NtkCoNum(p->pParams->pNtk) >= nNodesMax );
|
|
pNodes[0] = 0;
|
|
nNodes = 1;
|
|
// for ( i = 1; i < p->nOutputs; i++ )
|
|
Pga_ManForEachCoDriver( p, pNodeI, i )
|
|
{
|
|
for ( k = nNodes - 1; k >= 0; k-- )
|
|
{
|
|
pObjCo = Abc_NtkCo( p->pParams->pNtk, pNodes[k] );
|
|
pNodeK = Pga_Node( p, Abc_ObjFaninId0(pObjCo) );
|
|
if ( Pga_MappingCompareOutputDelay( &pNodeK, &pNodeI ) >= 0 )
|
|
break;
|
|
}
|
|
if ( k == nNodesMax - 1 )
|
|
continue;
|
|
if ( nNodes < nNodesMax )
|
|
nNodes++;
|
|
for ( v = nNodes - 1; v > k+1; v-- )
|
|
pNodes[v] = pNodes[v-1];
|
|
pNodes[k+1] = i;
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Prints a bunch of latest arriving outputs.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Pga_MappingPrintOutputArrivals( Pga_Man_t * p )
|
|
{
|
|
int pSorted[PGA_CO_LIST_SIZE];
|
|
Abc_Ntk_t * pNtk = p->pParams->pNtk;
|
|
Abc_Obj_t * pObjCo;
|
|
Pga_Node_t * pNode;
|
|
int Limit, MaxNameSize, i;
|
|
|
|
// determine the number of nodes to print
|
|
Limit = (Abc_NtkCoNum(pNtk) < PGA_CO_LIST_SIZE)? Abc_NtkCoNum(pNtk) : PGA_CO_LIST_SIZE;
|
|
|
|
// determine the order
|
|
Pga_MappingFindLatest( p, pSorted, Limit );
|
|
|
|
// determine max size of the node's name
|
|
MaxNameSize = 0;
|
|
for ( i = 0; i < Limit; i++ )
|
|
{
|
|
pObjCo = Abc_NtkCo( pNtk, pSorted[i] );
|
|
if ( MaxNameSize < (int)strlen( Abc_ObjName(pObjCo) ) )
|
|
MaxNameSize = strlen( Abc_ObjName(pObjCo) );
|
|
}
|
|
|
|
// print the latest outputs
|
|
for ( i = 0; i < Limit; i++ )
|
|
{
|
|
// get the i-th latest output
|
|
pObjCo = Abc_NtkCo( pNtk, pSorted[i] );
|
|
pNode = Pga_Node( p, pObjCo->Id );
|
|
// print out the best arrival time
|
|
printf( "Output %-*s : ", MaxNameSize + 3, Abc_ObjName(pObjCo) );
|
|
printf( "Delay = %8.2f ", (double)pNode->Match.Delay );
|
|
if ( Abc_ObjFaninC0(pObjCo) )
|
|
printf( "NEG" );
|
|
else
|
|
printf( "POS" );
|
|
printf( "\n" );
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|