mirror of
https://github.com/YosysHQ/abc.git
synced 2026-09-07 11:11:19 +02:00
Version abc61122
This commit is contained in:
+1
-1
@@ -32,7 +32,7 @@ extern "C" {
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// the maximum size of LUTs used for mapping
|
||||
#define FPGA_MAX_LUTSIZE 10
|
||||
#define FPGA_MAX_LUTSIZE 32
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// STRUCTURE DEFINITIONS ///
|
||||
|
||||
@@ -684,7 +684,8 @@ int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNo
|
||||
{
|
||||
min = i;
|
||||
for ( k = i+1; k < nTotal; k++ )
|
||||
if ( ppNodes[k] < ppNodes[min] )
|
||||
// if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!)
|
||||
if ( ppNodes[k]->Num < ppNodes[min]->Num )
|
||||
min = k;
|
||||
pNodeTemp = ppNodes[i];
|
||||
ppNodes[i] = ppNodes[min];
|
||||
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
/**CFile****************************************************************
|
||||
|
||||
FileName [if.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapping based on priority cuts.]
|
||||
|
||||
Synopsis [External declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 21, 2006.]
|
||||
|
||||
Revision [$Id: if.h,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __IF_H__
|
||||
#define __IF_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include "vec.h"
|
||||
#include "mem.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// the maximum size of LUTs used for mapping (should be the same as FPGA_MAX_LUTSIZE defined in "fpga.h"!!!)
|
||||
#define IF_MAX_LUTSIZE 32
|
||||
|
||||
// object types
|
||||
typedef enum {
|
||||
IF_NONE, // 0: non-existent object
|
||||
IF_CONST1, // 1: constant 1
|
||||
IF_PI, // 2: primary input
|
||||
IF_PO, // 3: primary output
|
||||
IF_AND, // 4: AND node
|
||||
IF_BI, // 5: box input
|
||||
IF_BO, // 6: box output
|
||||
IF_BOX, // 7: box
|
||||
IF_VOID // 8: unused object
|
||||
} Hop_Type_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct If_Par_t_ If_Par_t;
|
||||
typedef struct If_Lib_t_ If_Lib_t;
|
||||
typedef struct If_Man_t_ If_Man_t;
|
||||
typedef struct If_Obj_t_ If_Obj_t;
|
||||
typedef struct If_Cut_t_ If_Cut_t;
|
||||
|
||||
// parameters
|
||||
struct If_Par_t_
|
||||
{
|
||||
int Mode; // the mapping mode
|
||||
int nLutSize; // the LUT size
|
||||
If_Lib_t * pLutLib; // the LUT library
|
||||
int nCutsMax; // the max number of cuts
|
||||
int fVerbose; // the verbosity flag
|
||||
int fSeq; // sequential mapping
|
||||
int fLatchPaths; // reset timing on latch paths
|
||||
int nLatches; // the number of latches
|
||||
float DelayTarget; // delay target
|
||||
float * pTimesArr; // arrival times
|
||||
float * pTimesReq; // required times
|
||||
};
|
||||
|
||||
// the LUT library
|
||||
struct If_Lib_t_
|
||||
{
|
||||
char * pName; // the name of the LUT library
|
||||
int LutMax; // the maximum LUT size
|
||||
float pLutAreas[IF_MAX_LUTSIZE+1]; // the areas of LUTs
|
||||
float pLutDelays[IF_MAX_LUTSIZE+1];// the delays of LUTs
|
||||
};
|
||||
|
||||
// manager
|
||||
struct If_Man_t_
|
||||
{
|
||||
// mapping parameters
|
||||
If_Par_t * pPars;
|
||||
// mapping nodes
|
||||
If_Obj_t * pConst1; // the constant 1 node
|
||||
Vec_Ptr_t * vPis; // the primary inputs
|
||||
Vec_Ptr_t * vPos; // the primary outputs
|
||||
Vec_Ptr_t * vObjs; // all objects
|
||||
Vec_Ptr_t * vMapped; // objects used in the mapping
|
||||
Vec_Ptr_t * vTemp; // temporary array
|
||||
int nObjs[IF_VOID];// the number of objects by type
|
||||
// various data
|
||||
int nLevelMax; // the max number of AIG levels
|
||||
float fEpsilon; // epsilon used for comparison
|
||||
float RequiredGlo; // global required times
|
||||
float AreaGlo; // global area
|
||||
// memory management
|
||||
Mem_Fixed_t * pMem; // memory manager
|
||||
int nEntrySize; // the size of the entry
|
||||
int nEntryBase; // the size of the entry minus cut leaf arrays
|
||||
// temporary cut storage
|
||||
int nCuts; // the number of cuts used
|
||||
If_Cut_t ** ppCuts; // the storage space for cuts
|
||||
};
|
||||
|
||||
// priority cut
|
||||
struct If_Cut_t_
|
||||
{
|
||||
float Delay; // the delay of the cut
|
||||
float Flow; // the area flow of the cut
|
||||
float Area; // the area of the cut
|
||||
If_Cut_t * pOne; // the parent cut
|
||||
If_Cut_t * pTwo; // the parent cut
|
||||
char fCompl0; // the complemented attribute
|
||||
char fCompl1; // the complemented attribute
|
||||
char Phase; // the complemented attribute
|
||||
char nLeaves; // the number of leaves
|
||||
int * pLeaves; // the array of fanins
|
||||
};
|
||||
|
||||
// node extension
|
||||
struct If_Obj_t_
|
||||
{
|
||||
unsigned Type : 4; // object
|
||||
unsigned fCompl0 : 1; // complemented attribute
|
||||
unsigned fCompl1 : 1; // complemented attribute
|
||||
unsigned fPhase : 1; // phase of the node
|
||||
unsigned fMark : 1; // multipurpose mark
|
||||
unsigned Level : 24; // logic level of the node
|
||||
int Id; // integer ID
|
||||
int nRefs; // the number of references
|
||||
short nCuts; // the number of cuts
|
||||
short iCut; // the number of the best cut
|
||||
If_Obj_t * pFanin0; // the first fanin
|
||||
If_Obj_t * pFanin1; // the second fanin
|
||||
If_Obj_t * pEquiv; // the choice node
|
||||
float EstRefs; // estimated reference counter
|
||||
float Required; // required time of the onde
|
||||
void * pCopy; // used for duplication
|
||||
If_Cut_t Cuts[0]; // the cuts of the node
|
||||
};
|
||||
|
||||
static inline If_Obj_t * If_ManConst1( If_Man_t * p ) { return p->pConst1; }
|
||||
static inline If_Obj_t * If_ManPi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vPis, i ); }
|
||||
static inline If_Obj_t * If_ManPo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vPos, i ); }
|
||||
static inline If_Obj_t * If_ManObj( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vObjs, i ); }
|
||||
static inline If_Cut_t * If_ManCut( If_Man_t * p, int i ) { return p->ppCuts[i]; }
|
||||
|
||||
static inline int If_ObjIsConst1( If_Obj_t * pObj ) { return pObj->Type == IF_CONST1; }
|
||||
static inline int If_ObjIsPi( If_Obj_t * pObj ) { return pObj->Type == IF_PI; }
|
||||
static inline int If_ObjIsPo( If_Obj_t * pObj ) { return pObj->Type == IF_PO; }
|
||||
static inline int If_ObjIsAnd( If_Obj_t * pObj ) { return pObj->Type == IF_AND; }
|
||||
static inline int If_ObjIsBi( If_Obj_t * pObj ) { return pObj->Type == IF_BI; }
|
||||
static inline int If_ObjIsBo( If_Obj_t * pObj ) { return pObj->Type == IF_BO; }
|
||||
static inline int If_ObjIsBox( If_Obj_t * pObj ) { return pObj->Type == IF_BOX; }
|
||||
|
||||
static inline If_Obj_t * If_ObjFanin0( If_Obj_t * pObj ) { return pObj->pFanin0; }
|
||||
static inline If_Obj_t * If_ObjFanin1( If_Obj_t * pObj ) { return pObj->pFanin1; }
|
||||
static inline int If_ObjFaninC0( If_Obj_t * pObj ) { return pObj->fCompl0; }
|
||||
static inline int If_ObjFaninC1( If_Obj_t * pObj ) { return pObj->fCompl1; }
|
||||
static inline void * If_ObjCopy( If_Obj_t * pObj ) { return pObj->pCopy; }
|
||||
static inline void If_ObjSetCopy( If_Obj_t * pObj, void * pCopy ) { pObj->pCopy = pCopy; }
|
||||
static inline void If_ObjSetChoice( If_Obj_t * pObj, If_Obj_t * pEqu ) { pObj->pEquiv = pEqu; }
|
||||
|
||||
static inline If_Cut_t * If_ObjCut( If_Obj_t * pObj, int iCut ) { return pObj->Cuts + iCut; }
|
||||
static inline If_Cut_t * If_ObjCutTriv( If_Obj_t * pObj ) { return pObj->Cuts; }
|
||||
static inline If_Cut_t * If_ObjCutBest( If_Obj_t * pObj ) { return pObj->Cuts + pObj->iCut; }
|
||||
|
||||
static inline void * If_CutData( If_Cut_t * pCut ) { return *(void **)pCut; }
|
||||
static inline void If_CutSetData( If_Cut_t * pCut, void * pData ) { *(void **)pCut = pData; }
|
||||
|
||||
static inline float If_CutLutDelay( If_Man_t * p, If_Cut_t * pCut ) { return p->pPars->pLutLib? p->pPars->pLutLib->pLutDelays[pCut->nLeaves] : (float)1.0; }
|
||||
static inline float If_CutLutArea( If_Man_t * p, If_Cut_t * pCut ) { return p->pPars->pLutLib? p->pPars->pLutLib->pLutAreas[pCut->nLeaves] : (float)1.0; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define IF_MIN(a,b) (((a) < (b))? (a) : (b))
|
||||
#define IF_MAX(a,b) (((a) > (b))? (a) : (b))
|
||||
|
||||
// the small and large numbers (min/max float are 1.17e-38/3.40e+38)
|
||||
#define IF_FLOAT_LARGE ((float)1.0e+20)
|
||||
#define IF_FLOAT_SMALL ((float)1.0e-20)
|
||||
#define IF_INT_LARGE (10000000)
|
||||
|
||||
// iterator over the primary inputs
|
||||
#define If_ManForEachPi( p, pObj, i ) \
|
||||
Vec_PtrForEachEntry( p->vPis, pObj, i )
|
||||
// iterator over the primary outputs
|
||||
#define If_ManForEachPo( p, pObj, i ) \
|
||||
Vec_PtrForEachEntry( p->vPos, pObj, i )
|
||||
// iterator over the latches
|
||||
#define If_ManForEachLatch( p, pObj, i ) \
|
||||
Vec_PtrForEachEntryStart( p->vPos, pObj, i, p->pPars->nLatches )
|
||||
// iterator over all objects, including those currently not used
|
||||
#define If_ManForEachObj( p, pObj, i ) \
|
||||
Vec_PtrForEachEntry( p->vObjs, pObj, i )
|
||||
// iterator over logic nodes (AND and EXOR gates)
|
||||
#define If_ManForEachNode( p, pObj, i ) \
|
||||
If_ManForEachObj( p, pObj, i ) if ( pObj->Type != IF_AND ) {} else
|
||||
// iterator over cuts of the node
|
||||
#define If_ObjForEachCut( pObj, pCut, i ) \
|
||||
for ( i = 0; (i < (int)(pObj)->nCuts) && ((pCut) = (pObj)->Cuts + i); i++ )
|
||||
// iterator over cuts of the node
|
||||
#define If_ObjForEachCutStart( pObj, pCut, i, Start ) \
|
||||
for ( i = Start; (i < (int)(pObj)->nCuts) && ((pCut) = (pObj)->Cuts + i); i++ )
|
||||
// iterator leaves of the cut
|
||||
#define If_CutForEachLeaf( p, pCut, pLeaf, i ) \
|
||||
for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i++ )
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== ifMan.c ==========================================================*/
|
||||
extern If_Man_t * If_ManStart( If_Par_t * pPars );
|
||||
extern void If_ManStop( If_Man_t * p );
|
||||
extern If_Obj_t * If_ManCreatePi( If_Man_t * p );
|
||||
extern If_Obj_t * If_ManCreatePo( If_Man_t * p, If_Obj_t * pDriver, int fCompl0 );
|
||||
extern If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, int fCompl0, If_Obj_t * pFan1, int fCompl1 );
|
||||
/*=== ifMap.c ==========================================================*/
|
||||
extern int If_ManPerformMapping( If_Man_t * p );
|
||||
/*=== ifUtil.c ==========================================================*/
|
||||
extern float If_ManDelayMax( If_Man_t * p );
|
||||
extern void If_ManCleanNodeCopy( If_Man_t * p );
|
||||
extern void If_ManCleanCutData( If_Man_t * p );
|
||||
extern float If_ManScanMapping( If_Man_t * p );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/**CFile****************************************************************
|
||||
|
||||
FileName [ifCore.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapping based on priority cuts.]
|
||||
|
||||
Synopsis [The central part of the mapper.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 21, 2006.]
|
||||
|
||||
Revision [$Id: ifCore.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "if.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/**CFile****************************************************************
|
||||
|
||||
FileName [ifCut.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapping based on priority cuts.]
|
||||
|
||||
Synopsis [Cut computation.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 21, 2006.]
|
||||
|
||||
Revision [$Id: ifCut.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "if.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/**CFile****************************************************************
|
||||
|
||||
FileName [ifMan.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapping based on priority cuts.]
|
||||
|
||||
Synopsis [Mapping manager.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 21, 2006.]
|
||||
|
||||
Revision [$Id: ifMan.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "if.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static If_Obj_t * If_ManSetupObj( If_Man_t * p );
|
||||
static If_Cut_t ** If_ManSetupCuts( If_Man_t * p );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the AIG manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
If_Man_t * If_ManStart( If_Par_t * pPars )
|
||||
{
|
||||
If_Man_t * p;
|
||||
// start the manager
|
||||
p = ALLOC( If_Man_t, 1 );
|
||||
memset( p, 0, sizeof(If_Man_t) );
|
||||
p->pPars = pPars;
|
||||
p->fEpsilon = (float)0.001;
|
||||
// allocate arrays for nodes
|
||||
p->vPis = Vec_PtrAlloc( 100 );
|
||||
p->vPos = Vec_PtrAlloc( 100 );
|
||||
p->vObjs = Vec_PtrAlloc( 100 );
|
||||
p->vMapped = Vec_PtrAlloc( 100 );
|
||||
p->vTemp = Vec_PtrAlloc( 100 );
|
||||
// prepare the memory manager
|
||||
p->nEntrySize = sizeof(If_Obj_t) + p->pPars->nCutsMax * (sizeof(If_Cut_t) + sizeof(int) * p->pPars->nLutSize);
|
||||
p->nEntryBase = sizeof(If_Obj_t) + p->pPars->nCutsMax * (sizeof(If_Cut_t));
|
||||
p->pMem = Mem_FixedStart( p->nEntrySize );
|
||||
// create the constant node
|
||||
p->pConst1 = If_ManSetupObj( p );
|
||||
p->pConst1->Type = IF_CONST1;
|
||||
p->pConst1->fPhase = 1;
|
||||
// create temporary cuts
|
||||
p->ppCuts = If_ManSetupCuts( p );
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_ManStop( If_Man_t * p )
|
||||
{
|
||||
If_Cut_t * pTemp;
|
||||
int i;
|
||||
Vec_PtrFree( p->vPis );
|
||||
Vec_PtrFree( p->vPos );
|
||||
Vec_PtrFree( p->vObjs );
|
||||
Vec_PtrFree( p->vMapped );
|
||||
Vec_PtrFree( p->vTemp );
|
||||
Mem_FixedStop( p->pMem, 0 );
|
||||
// free pars memory
|
||||
if ( p->pPars->pTimesArr )
|
||||
FREE( p->pPars->pTimesArr );
|
||||
if ( p->pPars->pTimesReq )
|
||||
FREE( p->pPars->pTimesReq );
|
||||
// free temporary cut memory
|
||||
pTemp = p->ppCuts[0];
|
||||
for ( i = 1; i < p->pPars->nCutsMax * p->pPars->nCutsMax; i++ )
|
||||
if ( pTemp > p->ppCuts[i] )
|
||||
pTemp = p->ppCuts[i];
|
||||
free( pTemp );
|
||||
free( p->ppCuts );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates primary input.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
If_Obj_t * If_ManCreatePi( If_Man_t * p )
|
||||
{
|
||||
If_Obj_t * pObj;
|
||||
pObj = If_ManSetupObj( p );
|
||||
pObj->Type = IF_PI;
|
||||
Vec_PtrPush( p->vPis, pObj );
|
||||
p->nObjs[IF_PI]++;
|
||||
return pObj;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Creates primary output with the given driver.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
If_Obj_t * If_ManCreatePo( If_Man_t * p, If_Obj_t * pDriver, int fCompl0 )
|
||||
{
|
||||
If_Obj_t * pObj;
|
||||
pObj = If_ManSetupObj( p );
|
||||
pObj->Type = IF_PO;
|
||||
pObj->fCompl0 = fCompl0;
|
||||
Vec_PtrPush( p->vPos, pObj );
|
||||
pObj->pFanin0 = pDriver; pDriver->nRefs++;
|
||||
p->nObjs[IF_PO]++;
|
||||
return pObj;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Create the new node assuming it does not exist.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, int fCompl0, If_Obj_t * pFan1, int fCompl1 )
|
||||
{
|
||||
If_Obj_t * pObj;
|
||||
// get memory for the new object
|
||||
pObj = If_ManSetupObj( p );
|
||||
pObj->Type = IF_AND;
|
||||
pObj->fCompl0 = fCompl0;
|
||||
pObj->fCompl1 = fCompl1;
|
||||
pObj->pFanin0 = pFan0; pFan0->nRefs++;
|
||||
pObj->pFanin1 = pFan1; pFan1->nRefs++;
|
||||
pObj->fPhase = (fCompl0? !pFan0->fPhase : pFan0->fPhase) & (fCompl1? !pFan1->fPhase : pFan1->fPhase);
|
||||
pObj->Level = 1 + IF_MAX( pFan0->Level, pFan1->Level );
|
||||
if ( p->nLevelMax < (int)pObj->Level )
|
||||
p->nLevelMax = (int)pObj->Level;
|
||||
p->nObjs[IF_AND]++;
|
||||
return pObj;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares memory for the node with cuts.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
If_Obj_t * If_ManSetupObj( If_Man_t * p )
|
||||
{
|
||||
If_Obj_t * pObj;
|
||||
int i, * pArrays;
|
||||
// get memory for the object
|
||||
pObj = (If_Obj_t *)Mem_FixedEntryFetch( p->pMem );
|
||||
memset( pObj, 0, p->nEntryBase );
|
||||
// organize memory
|
||||
pArrays = (int *)((char *)pObj + p->nEntryBase);
|
||||
for ( i = 0; i < p->pPars->nCutsMax; i++ )
|
||||
pObj->Cuts[i].pLeaves = pArrays + i * p->pPars->nLutSize;
|
||||
// assign ID and save
|
||||
pObj->Id = Vec_PtrSize(p->vObjs);
|
||||
Vec_PtrPush( p->vObjs, pObj );
|
||||
// assign elementary cut
|
||||
pObj->nCuts = 1;
|
||||
pObj->Cuts[0].nLeaves = 1;
|
||||
pObj->Cuts[0].pLeaves[0] = pObj->Id;
|
||||
pObj->iCut = 0;
|
||||
// set the required times
|
||||
pObj->Required = IF_FLOAT_LARGE;
|
||||
return pObj;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares memory for additional cuts of the manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
If_Cut_t ** If_ManSetupCuts( If_Man_t * p )
|
||||
{
|
||||
If_Cut_t ** pCutStore;
|
||||
int * pArrays, nCutSize, nCutsTotal, i;
|
||||
nCutsTotal = p->pPars->nCutsMax * p->pPars->nCutsMax;
|
||||
nCutSize = sizeof(If_Cut_t) + sizeof(int) * p->pPars->nLutSize;
|
||||
pCutStore = (If_Cut_t **)ALLOC( If_Cut_t *, (nCutsTotal + 1) );
|
||||
memset( pCutStore, 0, sizeof(If_Cut_t *) * (nCutsTotal + 1) );
|
||||
pCutStore[0] = (If_Cut_t *)ALLOC( char, nCutSize * nCutsTotal );
|
||||
memset( pCutStore[0], 0, nCutSize * nCutsTotal );
|
||||
for ( i = 1; i < nCutsTotal; i++ )
|
||||
pCutStore[i] = (If_Cut_t *)((char *)pCutStore[0] + sizeof(If_Cut_t) * i);
|
||||
pArrays = (int *)((char *)pCutStore[0] + sizeof(If_Cut_t) * nCutsTotal);
|
||||
for ( i = 0; i < nCutsTotal; i++ )
|
||||
pCutStore[i]->pLeaves = pArrays + i * p->pPars->nLutSize;
|
||||
return pCutStore;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,391 @@
|
||||
/**CFile****************************************************************
|
||||
|
||||
FileName [ifMap.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapping based on priority cuts.]
|
||||
|
||||
Synopsis [Mapping procedures.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 21, 2006.]
|
||||
|
||||
Revision [$Id: ifMap.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "if.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutMerge( If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC, int nLimit )
|
||||
{
|
||||
int i, k, c;
|
||||
assert( pC0->nLeaves >= pC1->nLeaves );
|
||||
// the case of the largest cut sizes
|
||||
if ( pC0->nLeaves == nLimit && pC1->nLeaves == nLimit )
|
||||
{
|
||||
for ( i = 0; i < pC0->nLeaves; i++ )
|
||||
if ( pC0->pLeaves[i] != pC1->pLeaves[i] )
|
||||
return 0;
|
||||
for ( i = 0; i < pC0->nLeaves; i++ )
|
||||
pC->pLeaves[i] = pC0->pLeaves[i];
|
||||
pC->nLeaves = pC0->nLeaves;
|
||||
return 1;
|
||||
}
|
||||
// the case when one of the cuts is the largest
|
||||
if ( pC0->nLeaves == nLimit )
|
||||
{
|
||||
for ( i = 0; i < pC1->nLeaves; i++ )
|
||||
{
|
||||
for ( k = pC0->nLeaves - 1; k >= 0; k-- )
|
||||
if ( pC0->pLeaves[k] == pC1->pLeaves[i] )
|
||||
break;
|
||||
if ( k == -1 ) // did not find
|
||||
return 0;
|
||||
}
|
||||
for ( i = 0; i < pC0->nLeaves; i++ )
|
||||
pC->pLeaves[i] = pC0->pLeaves[i];
|
||||
pC->nLeaves = pC0->nLeaves;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// compare two cuts with different numbers
|
||||
i = k = 0;
|
||||
for ( c = 0; c < nLimit; c++ )
|
||||
{
|
||||
if ( k == pC1->nLeaves )
|
||||
{
|
||||
if ( i == pC0->nLeaves )
|
||||
{
|
||||
pC->nLeaves = c;
|
||||
return 1;
|
||||
}
|
||||
pC->pLeaves[c] = pC0->pLeaves[i++];
|
||||
continue;
|
||||
}
|
||||
if ( i == pC0->nLeaves )
|
||||
{
|
||||
if ( k == pC1->nLeaves )
|
||||
{
|
||||
pC->nLeaves = c;
|
||||
return 1;
|
||||
}
|
||||
pC->pLeaves[c] = pC1->pLeaves[k++];
|
||||
continue;
|
||||
}
|
||||
if ( pC0->pLeaves[i] < pC1->pLeaves[k] )
|
||||
{
|
||||
pC->pLeaves[c] = pC0->pLeaves[i++];
|
||||
continue;
|
||||
}
|
||||
if ( pC0->pLeaves[i] > pC1->pLeaves[k] )
|
||||
{
|
||||
pC->pLeaves[c] = pC1->pLeaves[k++];
|
||||
continue;
|
||||
}
|
||||
pC->pLeaves[c] = pC0->pLeaves[i++];
|
||||
k++;
|
||||
}
|
||||
if ( i < pC0->nLeaves || k < pC1->nLeaves )
|
||||
return 0;
|
||||
pC->nLeaves = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutCompareDelay( If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
|
||||
{
|
||||
If_Cut_t * pC0 = *ppC0;
|
||||
If_Cut_t * pC1 = *ppC1;
|
||||
if ( pC0->Delay < pC1->Delay )
|
||||
return -1;
|
||||
if ( pC0->Delay > pC1->Delay )
|
||||
return 1;
|
||||
if ( pC0->nLeaves < pC1->nLeaves )
|
||||
return -1;
|
||||
if ( pC0->nLeaves > pC1->nLeaves )
|
||||
return 1;
|
||||
if ( pC0->Flow < pC1->Flow )
|
||||
return -1;
|
||||
if ( pC0->Flow > pC1->Flow )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutCompareArea( If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
|
||||
{
|
||||
If_Cut_t * pC0 = *ppC0;
|
||||
If_Cut_t * pC1 = *ppC1;
|
||||
if ( pC0->Flow < pC1->Flow )
|
||||
return -1;
|
||||
if ( pC0->Flow > pC1->Flow )
|
||||
return 1;
|
||||
if ( pC0->nLeaves < pC1->nLeaves )
|
||||
return -1;
|
||||
if ( pC0->nLeaves > pC1->nLeaves )
|
||||
return 1;
|
||||
if ( pC0->Delay < pC1->Delay )
|
||||
return -1;
|
||||
if ( pC0->Delay > pC1->Delay )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes delay.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutDelay( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
float Delay;
|
||||
int i;
|
||||
Delay = -IF_FLOAT_LARGE;
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
Delay = IF_MAX( Delay, If_ObjCutBest(pLeaf)->Delay );
|
||||
return Delay + If_CutLutDelay(p, pCut);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area flow.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutFlow( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
float Flow;
|
||||
int i;
|
||||
Flow = If_CutLutArea(p, pCut);
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
Flow += If_ObjCutBest(pLeaf)->Flow / pLeaf->EstRefs;
|
||||
return Flow;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutArea1( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
float Area;
|
||||
int i;
|
||||
Area = If_CutLutArea(p, pCut);
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
if ( pLeaf->nRefs == 0 )
|
||||
Area += If_CutLutArea(p, If_ObjCutBest(pLeaf));
|
||||
return Area;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_CutRef1( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
int i;
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
pLeaf->nRefs++;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_CutDeref1( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
int i;
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
pLeaf->nRefs--;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc )
|
||||
{
|
||||
int * pArray;
|
||||
pArray = pCutDest->pLeaves;
|
||||
*pCutDest = *pCutSrc;
|
||||
pCutDest->pLeaves = pArray;
|
||||
memcpy( pCutDest->pLeaves, pCutSrc->pLeaves, sizeof(int) * pCutSrc->nLeaves );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Finds the best cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_ObjPerformMapping( If_Man_t * p, If_Obj_t * pObj )
|
||||
{
|
||||
If_Cut_t * pCut0, * pCut1, * pCut;
|
||||
int i, k;
|
||||
// create cross-product of the cuts
|
||||
p->nCuts = 0;
|
||||
pCut = p->ppCuts[0];
|
||||
If_ObjForEachCut( pObj->pFanin0, pCut0, i )
|
||||
If_ObjForEachCut( pObj->pFanin1, pCut1, k )
|
||||
{
|
||||
if ( pCut0->nLeaves < pCut1->nLeaves )
|
||||
{
|
||||
if ( !If_CutMerge( pCut1, pCut0, pCut, p->pPars->nLutSize ) )
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !If_CutMerge( pCut0, pCut1, pCut, p->pPars->nLutSize ) )
|
||||
continue;
|
||||
}
|
||||
// the cuts have been successfully merged
|
||||
pCut->pOne = pCut0; pCut->fCompl0 = pObj->fCompl0;
|
||||
pCut->pTwo = pCut1; pCut->fCompl1 = pObj->fCompl1;
|
||||
// pCut->Phase = ...
|
||||
pCut->Delay = If_CutDelay( p, pCut );
|
||||
pCut->Flow = If_CutFlow( p, pCut );
|
||||
// prepare room for the next cut
|
||||
pCut = p->ppCuts[++p->nCuts];
|
||||
}
|
||||
// sort the cuts
|
||||
if ( p->pPars->Mode == 1 ) // delay
|
||||
qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelay );
|
||||
else
|
||||
qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareArea );
|
||||
// take the first
|
||||
pObj->nCuts = IF_MIN( p->nCuts + 1, p->pPars->nCutsMax );
|
||||
If_ObjForEachCutStart( pObj, pCut, i, 1 )
|
||||
If_CutCopy( pCut, p->ppCuts[i-1] );
|
||||
pObj->iCut = 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Maps the nodes for delay.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_ManPerformMapping( If_Man_t * p )
|
||||
{
|
||||
If_Obj_t * pObj;
|
||||
float DelayBest;
|
||||
int i, clk = clock();
|
||||
// set arrival times and trivial cuts at const 1 and PIs
|
||||
If_ManConst1(p)->Cuts[0].Delay = 0.0;
|
||||
If_ManForEachPi( p, pObj, i )
|
||||
pObj->Cuts[0].Delay = p->pPars->pTimesArr[i];
|
||||
// set the initial fanout estimates
|
||||
If_ManForEachObj( p, pObj, i )
|
||||
pObj->EstRefs = (float)pObj->nRefs;
|
||||
// map the internal nodes
|
||||
If_ManForEachNode( p, pObj, i )
|
||||
If_ObjPerformMapping( p, pObj );
|
||||
// get the best arrival time of the POs
|
||||
DelayBest = If_ManDelayMax(p);
|
||||
printf( "Best delay = %d. ", (int)DelayBest );
|
||||
PRT( "Time", clock() - clk );
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
/**CFile****************************************************************
|
||||
|
||||
FileName [ifUtil.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapping based on priority cuts.]
|
||||
|
||||
Synopsis [Various utilities.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 21, 2006.]
|
||||
|
||||
Revision [$Id: ifUtil.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "if.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the max delay of the POs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_ManDelayMax( If_Man_t * p )
|
||||
{
|
||||
If_Obj_t * pObj;
|
||||
float DelayBest;
|
||||
int i;
|
||||
DelayBest = -IF_FLOAT_LARGE;
|
||||
If_ManForEachPo( p, pObj, i )
|
||||
if ( DelayBest < If_ObjCutBest( If_ObjFanin0(pObj) )->Delay )
|
||||
DelayBest = If_ObjCutBest( If_ObjFanin0(pObj) )->Delay;
|
||||
return DelayBest;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets all the node copy to NULL.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_ManCleanNodeCopy( If_Man_t * p )
|
||||
{
|
||||
If_Obj_t * pObj;
|
||||
int i;
|
||||
If_ManForEachObj( p, pObj, i )
|
||||
If_ObjSetCopy( pObj, NULL );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets all the cut data to NULL.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_ManCleanCutData( If_Man_t * p )
|
||||
{
|
||||
If_Obj_t * pObj;
|
||||
If_Cut_t * pCut;
|
||||
int i, k;
|
||||
If_ManForEachObj( p, pObj, i )
|
||||
If_ObjForEachCut( pObj, pCut, k )
|
||||
If_CutSetData( pCut, NULL );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area, references, and nodes used in the mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_ManScanMapping_rec( If_Man_t * p, If_Obj_t * pObj, If_Obj_t ** ppStore )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
If_Cut_t * pCutBest;
|
||||
float aArea;
|
||||
int i;
|
||||
if ( pObj->nRefs++ || If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) )
|
||||
return 0.0;
|
||||
// store the node in the structure by level
|
||||
assert( If_ObjIsAnd(pObj) );
|
||||
pObj->pCopy = (char *)ppStore[pObj->Level];
|
||||
ppStore[pObj->Level] = pObj;
|
||||
// visit the transitive fanin of the selected cut
|
||||
pCutBest = If_ObjCutBest(pObj);
|
||||
aArea = If_CutLutArea( p, pCutBest );
|
||||
If_CutForEachLeaf( p, pCutBest, pLeaf, i )
|
||||
aArea += If_ManScanMapping_rec( p, pLeaf, ppStore );
|
||||
return aArea;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area, references, and nodes used in the mapping.]
|
||||
|
||||
Description [Collects the nodes in reverse topological order in array
|
||||
p->vMapping.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_ManScanMapping( If_Man_t * p )
|
||||
{
|
||||
If_Obj_t * pObj, ** ppStore;
|
||||
float aArea;
|
||||
int i;
|
||||
// clean all references
|
||||
If_ManForEachObj( p, pObj, i )
|
||||
{
|
||||
pObj->Required = IF_FLOAT_LARGE;
|
||||
pObj->nRefs = 0;
|
||||
}
|
||||
// allocate place to store the nodes
|
||||
ppStore = ALLOC( If_Obj_t *, p->nLevelMax + 1 );
|
||||
memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) );
|
||||
// collect nodes reachable from POs in the DFS order through the best cuts
|
||||
aArea = 0;
|
||||
If_ManForEachPo( p, pObj, i )
|
||||
aArea += If_ManScanMapping_rec( p, If_ObjFanin0(pObj), ppStore );
|
||||
// reconnect the nodes in reverse topological order
|
||||
Vec_PtrClear( p->vMapped );
|
||||
for ( i = p->nLevelMax; i >= 0; i-- )
|
||||
for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy )
|
||||
Vec_PtrPush( p->vMapped, pObj );
|
||||
free( ppStore );
|
||||
return aArea;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the required times of all nodes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_ManComputeRequired( If_Man_t * p, int fFirstTime )
|
||||
{
|
||||
If_Obj_t * pObj, * pLeaf;
|
||||
If_Cut_t * pCutBest;
|
||||
float Required;
|
||||
int i, k;
|
||||
// compute area, clean required times, collect nodes used in the mapping
|
||||
p->AreaGlo = If_ManScanMapping( p );
|
||||
// get the global required times
|
||||
p->RequiredGlo = If_ManDelayMax( p );
|
||||
// update the required times according to the target
|
||||
if ( p->pPars->DelayTarget != -1 )
|
||||
{
|
||||
if ( p->RequiredGlo > p->pPars->DelayTarget + p->fEpsilon )
|
||||
{
|
||||
if ( fFirstTime )
|
||||
printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->pPars->DelayTarget );
|
||||
}
|
||||
else if ( p->RequiredGlo < p->pPars->DelayTarget - p->fEpsilon )
|
||||
{
|
||||
if ( fFirstTime )
|
||||
printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->RequiredGlo, p->pPars->DelayTarget );
|
||||
p->RequiredGlo = p->pPars->DelayTarget;
|
||||
}
|
||||
}
|
||||
// set the required times for the POs
|
||||
if ( p->pPars->fLatchPaths )
|
||||
{
|
||||
If_ManForEachLatch( p, pObj, i )
|
||||
If_ObjFanin0(pObj)->Required = p->RequiredGlo;
|
||||
}
|
||||
else
|
||||
{
|
||||
If_ManForEachPo( p, pObj, i )
|
||||
If_ObjFanin0(pObj)->Required = p->RequiredGlo;
|
||||
}
|
||||
// go through the nodes in the reverse topological order
|
||||
Vec_PtrForEachEntry( p->vMapped, pObj, k )
|
||||
{
|
||||
// get the best cut of the node
|
||||
pCutBest = If_ObjCutBest(pObj);
|
||||
// get the required times for the leaves of the cut
|
||||
Required = pObj->Required - If_CutLutDelay( p, pCutBest );
|
||||
// update the required time of the leaves
|
||||
If_CutForEachLeaf( p, pCutBest, pLeaf, i )
|
||||
pLeaf->Required = IF_MIN( pLeaf->Required, Required );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/**CFile****************************************************************
|
||||
|
||||
FileName [if_.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapping based on priority cuts.]
|
||||
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 21, 2006.]
|
||||
|
||||
Revision [$Id: if_.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "if.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
SRC += src/map/if/ifCore.c \
|
||||
src/map/if/ifMan.c \
|
||||
src/map/if/ifMap.c \
|
||||
src/map/if/ifUtil.c
|
||||
@@ -1,4 +0,0 @@
|
||||
SRC += src/map/pga/pgaCore.c \
|
||||
src/map/pga/pgaMan.c \
|
||||
src/map/pga/pgaMatch.c \
|
||||
src/map/pga/pgaUtil.c
|
||||
@@ -1,80 +0,0 @@
|
||||
/**CFile****************************************************************
|
||||
|
||||
FileName [pga.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapper.]
|
||||
|
||||
Synopsis [External declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: pga.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __PGA_H__
|
||||
#define __PGA_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Pga_ManStruct_t_ Pga_Man_t;
|
||||
typedef struct Pga_ParamsStruct_t_ Pga_Params_t;
|
||||
|
||||
struct Pga_ParamsStruct_t_
|
||||
{
|
||||
// data for mapping
|
||||
Abc_Ntk_t * pNtk; // the network to be mapped
|
||||
Fpga_LutLib_t * pLutLib; // the LUT library
|
||||
float * pSwitching; // switching activity for each node
|
||||
// mapping parameters
|
||||
int fDropCuts; // enables cut dropping
|
||||
int fAreaFlow; // enables area flow minimization
|
||||
int fArea; // enables area minimization
|
||||
int fSwitching; // enables switching activity minimization
|
||||
int fVerbose; // enables verbose output
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== pgaApi.c ==========================================================*/
|
||||
extern Vec_Ptr_t * Pga_DoMapping( Pga_Man_t * p );
|
||||
/*=== pgaMan.c ==========================================================*/
|
||||
extern Pga_Man_t * Pga_ManStart( Pga_Params_t * pParams );
|
||||
extern void Pga_ManStop( Pga_Man_t * p );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
/**CFile****************************************************************
|
||||
|
||||
FileName [pgaCore.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapper.]
|
||||
|
||||
Synopsis [External APIs of the FPGA manager.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: pgaCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "pgaInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void Pga_MappingInitCis( Pga_Man_t * p );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs technology mapping for the given object graph.]
|
||||
|
||||
Description [The object graph is stored in the mapping manager.
|
||||
First, all the AND-nodes, which fanout into the POs, are collected
|
||||
in the DFS fashion. Next, three steps are performed: the k-feasible
|
||||
cuts are computed for each node, the truth tables are computed for
|
||||
each cut, and the delay-optimal matches are assigned for each node.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Pga_DoMapping( Pga_Man_t * p )
|
||||
{
|
||||
int fShowSwitching = 0;
|
||||
float aAreaTotalCur;
|
||||
int Iter, clk, clkTotal = clock();
|
||||
|
||||
// assign the arrival times of the PIs
|
||||
Pga_MappingInitCis( p );
|
||||
|
||||
// map the AIG for delay
|
||||
clk = clock();
|
||||
Pga_MappingMatches( p, 0 );
|
||||
p->timeDelay = clock() - clk;
|
||||
|
||||
// compute area, set references, and collect nodes used in the mapping
|
||||
Iter = 1;
|
||||
aAreaTotalCur = Pga_MappingSetRefsAndArea( p );
|
||||
if ( p->pParams->fVerbose )
|
||||
{
|
||||
printf( "Iteration %dD : Area = %8.1f ", Iter++, aAreaTotalCur );
|
||||
if ( fShowSwitching )
|
||||
printf( "Switch = %8.1f ", Pga_MappingGetSwitching(p) );
|
||||
PRT( "Time", p->timeDelay );
|
||||
}
|
||||
|
||||
if ( p->pParams->fAreaFlow )
|
||||
{
|
||||
clk = clock();
|
||||
// compute the required times and the fanouts
|
||||
Pga_MappingComputeRequired( p );
|
||||
// remap topologically
|
||||
Pga_MappingMatches( p, 1 );
|
||||
p->timeAreaFlow = clock() - clk;
|
||||
// get the resulting area
|
||||
aAreaTotalCur = Pga_MappingSetRefsAndArea( p );
|
||||
// note that here we do not update the reference counter
|
||||
// for some reason, this works better on benchmarks
|
||||
if ( p->pParams->fVerbose )
|
||||
{
|
||||
printf( "Iteration %dF : Area = %8.1f ", Iter++, aAreaTotalCur );
|
||||
if ( fShowSwitching )
|
||||
printf( "Switch = %8.1f ", Pga_MappingGetSwitching(p) );
|
||||
PRT( "Time", p->timeAreaFlow );
|
||||
}
|
||||
}
|
||||
|
||||
if ( p->pParams->fArea )
|
||||
{
|
||||
clk = clock();
|
||||
// compute the required times and the fanouts
|
||||
Pga_MappingComputeRequired( p );
|
||||
// remap topologically
|
||||
if ( p->pParams->fSwitching )
|
||||
Pga_MappingMatches( p, 3 );
|
||||
else
|
||||
Pga_MappingMatches( p, 2 );
|
||||
p->timeArea = clock() - clk;
|
||||
// get the resulting area
|
||||
aAreaTotalCur = Pga_MappingSetRefsAndArea( p );
|
||||
if ( p->pParams->fVerbose )
|
||||
{
|
||||
printf( "Iteration %d%s : Area = %8.1f ", Iter++, (p->pParams->fSwitching?"S":"A"), aAreaTotalCur );
|
||||
if ( fShowSwitching )
|
||||
printf( "Switch = %8.1f ", Pga_MappingGetSwitching(p) );
|
||||
PRT( "Time", p->timeArea );
|
||||
}
|
||||
}
|
||||
p->AreaGlobal = aAreaTotalCur;
|
||||
|
||||
if ( p->pParams->fVerbose )
|
||||
Pga_MappingPrintOutputArrivals( p );
|
||||
|
||||
// return the mapping
|
||||
return Pga_MappingResults( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Initializes the CI node arrival times.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Pga_MappingInitCis( Pga_Man_t * p )
|
||||
{
|
||||
Pga_Node_t * pNode;
|
||||
float * pCiArrs;
|
||||
int i;
|
||||
// get the CI arrival times
|
||||
pCiArrs = Abc_NtkGetCiArrivalFloats( p->pParams->pNtk );
|
||||
// assign the arrival times of the PIs
|
||||
Pga_ManForEachCi( p, pNode, i )
|
||||
pNode->Match.Delay = pCiArrs[i];
|
||||
free( pCiArrs );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
/**CFile****************************************************************
|
||||
|
||||
FileName [pgaInt.h]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapper.]
|
||||
|
||||
Synopsis [Internal declarations.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: pgaInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __PGA_INT_H__
|
||||
#define __PGA_INT_H__
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// INCLUDES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include "abc.h"
|
||||
#include "fraig.h"
|
||||
#include "fpga.h"
|
||||
#include "cut.h"
|
||||
#include "pga.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// PARAMETERS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// BASIC TYPES ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct Pga_NodeStruct_t_ Pga_Node_t;
|
||||
typedef struct Pga_MatchStruct_t_ Pga_Match_t;
|
||||
|
||||
struct Pga_ManStruct_t_
|
||||
{
|
||||
// mapping parameters
|
||||
Pga_Params_t * pParams; // input data
|
||||
// mapping structures
|
||||
Pga_Node_t * pMemory; // the memory for all mapping structures
|
||||
Vec_Ptr_t * vStructs; // mapping structures one-to-one with ABC nodes
|
||||
Vec_Ptr_t * vOrdering; // mapping nodes ordered by level
|
||||
// k-feasible cuts
|
||||
int nVarsMax; // the "k" of k-feasible cuts
|
||||
Cut_Man_t * pManCut; // the cut manager
|
||||
// LUT library
|
||||
float * pLutDelays; // the delay of the LUTs
|
||||
float * pLutAreas; // the areas of the LUTs
|
||||
float Epsilon;
|
||||
// global parameters
|
||||
float AreaGlobal; // the total area of this mapping
|
||||
float ArrivalGlobal; // the largest delay of any path
|
||||
float RequiredGlobal;// the global required time (may be different from largest delay)
|
||||
float RequiredUser; // the required time given by the user
|
||||
// runtime stats
|
||||
int timeToMap; // the time to start the mapper
|
||||
int timeCuts; // the time to compute the cuts
|
||||
int timeDelay; // the time to compute delay
|
||||
int timeAreaFlow; // the time to perform area flow optimization
|
||||
int timeArea; // the time to perform area flow optimization
|
||||
int timeToNet; // the time to transform back to network
|
||||
int timeTotal; // the total time
|
||||
int time1; // temporary
|
||||
int time2; // temporary
|
||||
};
|
||||
|
||||
struct Pga_MatchStruct_t_
|
||||
{
|
||||
Cut_Cut_t * pCut; // the best cut
|
||||
float Delay; // the arrival time of this cut
|
||||
float Area; // the area of this cut
|
||||
};
|
||||
|
||||
struct Pga_NodeStruct_t_
|
||||
{
|
||||
int Id; // ID of the node
|
||||
int nRefs; // the number of references
|
||||
float EstRefs; // the estimated reference counter
|
||||
float Required; // the required time
|
||||
float Switching; // the switching activity
|
||||
Pga_Match_t Match; // the best match at the node
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline Pga_Node_t * Pga_Node( Pga_Man_t * p, int Id ) { return p->vStructs->pArray[Id]; }
|
||||
|
||||
// iterator through the CIs
|
||||
#define Pga_ManForEachCi( p, pCi, i ) \
|
||||
for ( i = 0; (i < Abc_NtkCiNum(p->pParams->pNtk)) && (((pCi) = Pga_Node(p, Abc_NtkCi(p->pParams->pNtk,i)->Id)), 1); i++ )
|
||||
// iterator through the CO derivers
|
||||
#define Pga_ManForEachCoDriver( p, pCo, i ) \
|
||||
for ( i = 0; (i < Abc_NtkCoNum(p->pParams->pNtk)) && (((pCo) = Pga_Node(p, Abc_ObjFaninId0(Abc_NtkCo(p->pParams->pNtk,i)))), 1); i++ )
|
||||
// iterators through the CIs and internal nodes
|
||||
#define Pga_ManForEachObjDirect( p, pNode, i ) \
|
||||
Vec_PtrForEachEntry( p->vOrdering, pNode, i )
|
||||
#define Pga_ManForEachObjReverse( p, pNode, i ) \
|
||||
Vec_PtrForEachEntryReverse( p->vOrdering, pNode, i )
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*=== pgaMatch.c ==========================================================*/
|
||||
extern void Pga_MappingMatches( Pga_Man_t * p, int Mode );
|
||||
/*=== pgaUtil.c ==========================================================*/
|
||||
extern Vec_Ptr_t * Pga_MappingResults( Pga_Man_t * p );
|
||||
extern float Pga_TimeComputeArrivalMax( Pga_Man_t * p );
|
||||
extern void Pga_MappingComputeRequired( Pga_Man_t * p );
|
||||
extern float Pga_MappingSetRefsAndArea( Pga_Man_t * p );
|
||||
extern float Pga_MappingGetSwitching( Pga_Man_t * p );
|
||||
extern void Pga_MappingPrintOutputArrivals( Pga_Man_t * p );
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
/**CFile****************************************************************
|
||||
|
||||
FileName [pgaMan.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapper.]
|
||||
|
||||
Synopsis [Mapping manager.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: pgaMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "pgaInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Cut_Man_t * Pga_ManStartCutMan( Pga_Params_t * pParamsPga );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Pga_Man_t * Pga_ManStart( Pga_Params_t * pParams )
|
||||
{
|
||||
Pga_Man_t * p;
|
||||
Pga_Node_t * pNode;
|
||||
Cut_Man_t * pManCut;
|
||||
Abc_Ntk_t * pNtk;
|
||||
Abc_Obj_t * pObj;
|
||||
int i, Counter;
|
||||
int clk = clock();
|
||||
|
||||
// make sure the network is given
|
||||
pNtk = pParams->pNtk;
|
||||
if ( pNtk == NULL )
|
||||
{
|
||||
printf( "Network is not specified.\n" );
|
||||
return NULL;
|
||||
}
|
||||
if ( !Abc_NtkIsStrash(pNtk) )
|
||||
{
|
||||
printf( "Mapping can only be applied to an AIG.\n" );
|
||||
return NULL;
|
||||
}
|
||||
// the cut manager if given should be in sinc
|
||||
pManCut = pNtk->pManCut;
|
||||
if ( pManCut && Cut_ManReadVarsMax(pManCut) != Fpga_LutLibReadVarMax(pParams->pLutLib) )
|
||||
{
|
||||
printf( "The precomputed cuts have different size.\n" );
|
||||
return NULL;
|
||||
}
|
||||
// make sure the nodes are in the topological order
|
||||
if ( !Abc_NtkIsDfsOrdered(pNtk) )
|
||||
{
|
||||
printf( "The nodes of the network are not DFS ordered.\n" );
|
||||
// Abc_NtkReassignIds( pNtk );
|
||||
return NULL;
|
||||
}
|
||||
// make sure there are no dangling nodes (unless they are choices)
|
||||
|
||||
// start the mapping manager
|
||||
p = ALLOC( Pga_Man_t, 1 );
|
||||
memset( p, 0, sizeof(Pga_Man_t) );
|
||||
p->pParams = pParams;
|
||||
p->nVarsMax = Fpga_LutLibReadVarMax(pParams->pLutLib);
|
||||
p->pManCut = pManCut? pManCut : Pga_ManStartCutMan(pParams);
|
||||
p->vOrdering = Abc_AigGetLevelizedOrder(pNtk, 0); // what happens with dangling nodes???
|
||||
p->pLutAreas = Fpga_LutLibReadLutAreas(pParams->pLutLib);
|
||||
p->pLutDelays = Fpga_LutLibReadLutDelays(pParams->pLutLib);
|
||||
p->Epsilon = (float)0.00001;
|
||||
|
||||
// allocate mapping structures
|
||||
p->pMemory = ALLOC( Pga_Node_t, Abc_NtkObjNum(pNtk) );
|
||||
memset( p->pMemory, 0, sizeof(Pga_Node_t) * Abc_NtkObjNum(pNtk) );
|
||||
p->vStructs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) );
|
||||
Counter = 0;
|
||||
Abc_NtkForEachObj( pNtk, pObj, i )
|
||||
{
|
||||
pNode = p->pMemory + Counter++;
|
||||
pNode->Id = pObj->Id;
|
||||
pNode->nRefs = pObj->vFanouts.nSize;
|
||||
pNode->Required = ABC_INFINITY;
|
||||
pNode->Match.Area = ABC_INFINITY;
|
||||
// skip secondary nodes
|
||||
if ( Abc_ObjFanoutNum(pObj) == 0 )
|
||||
continue;
|
||||
Vec_PtrWriteEntry( p->vStructs, pObj->Id, pNode );
|
||||
}
|
||||
assert( Counter == Abc_NtkObjNum(pNtk) );
|
||||
// update order to depend on mapping nodes
|
||||
Vec_PtrForEachEntry( p->vOrdering, pObj, i )
|
||||
Vec_PtrWriteEntry( p->vOrdering, i, Pga_Node(p,pObj->Id) );
|
||||
p->timeToMap = clock() - clk;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stops the manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Pga_ManStop( Pga_Man_t * p )
|
||||
{
|
||||
Cut_ManStop( p->pManCut );
|
||||
Vec_PtrFree( p->vOrdering );
|
||||
Vec_PtrFree( p->vStructs );
|
||||
free( p->pMemory );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the cut manager for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Cut_Man_t * Pga_ManStartCutMan( Pga_Params_t * pParamsPga )
|
||||
{
|
||||
static Cut_Params_t Params, * pParams = &Params;
|
||||
Abc_Ntk_t * pNtk = pParamsPga->pNtk;
|
||||
Cut_Man_t * pManCut;
|
||||
Abc_Obj_t * pObj;
|
||||
int i;
|
||||
// start the cut manager
|
||||
memset( pParams, 0, sizeof(Cut_Params_t) );
|
||||
pParams->nVarsMax = Fpga_LutLibReadVarMax(pParamsPga->pLutLib); // max cut size
|
||||
pParams->nKeepMax = 250; // the max number of cuts kept at a node
|
||||
pParams->fTruth = 0; // compute truth tables
|
||||
pParams->fFilter = 1; // filter dominated cuts
|
||||
pParams->fSeq = 0; // compute sequential cuts
|
||||
pParams->fDrop = pParamsPga->fDropCuts; // drop cuts on the fly
|
||||
pParams->fVerbose = 0; // the verbosiness flag
|
||||
pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
|
||||
pManCut = Cut_ManStart( pParams );
|
||||
if ( pParams->fDrop )
|
||||
Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) );
|
||||
// set cuts for PIs
|
||||
Abc_NtkForEachCi( pNtk, pObj, i )
|
||||
if ( Abc_ObjFanoutNum(pObj) > 0 )
|
||||
Cut_NodeSetTriv( pManCut, pObj->Id );
|
||||
return pManCut;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -1,378 +0,0 @@
|
||||
/**CFile****************************************************************
|
||||
|
||||
FileName [pgaMatch.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapper.]
|
||||
|
||||
Synopsis [Mapping procedures.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: pgaMatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "pgaInt.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static char * s_Modes[4] = { "Delay", "Flow", "Area", "Switch" };
|
||||
|
||||
static int Pga_MappingMatchNode( Pga_Man_t * p, int NodeId, Cut_Cut_t * pList, int Mode );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs mapping for delay, area-flow, area, switching.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Pga_MappingMatches( Pga_Man_t * p, int Mode )
|
||||
{
|
||||
ProgressBar * pProgress;
|
||||
Abc_Ntk_t * pNtk;
|
||||
Abc_Obj_t * pObj;
|
||||
Cut_Cut_t * pList;
|
||||
int i, clk;
|
||||
|
||||
assert( Mode >= 0 && Mode <= 2 );
|
||||
|
||||
// match LUTs with nodes in the topological order
|
||||
pNtk = p->pParams->pNtk;
|
||||
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
|
||||
Abc_NtkForEachObj( pNtk, pObj, i )
|
||||
{
|
||||
// skip the CIs
|
||||
if ( Abc_ObjIsCi(pObj) )
|
||||
continue;
|
||||
// when we reached a CO, it is time to deallocate the cuts
|
||||
if ( Abc_ObjIsCo(pObj) )
|
||||
{
|
||||
if ( p->pParams->fDropCuts )
|
||||
Cut_NodeTryDroppingCuts( p->pManCut, Abc_ObjFaninId0(pObj) );
|
||||
continue;
|
||||
}
|
||||
// skip constant node, it has no cuts
|
||||
// if ( Abc_NodeIsConst(pObj) )
|
||||
// continue;
|
||||
// get the cuts
|
||||
clk = clock();
|
||||
pList = Abc_NodeGetCutsRecursive( p->pManCut, pObj, 0, 0 );
|
||||
p->timeCuts += clock() - clk;
|
||||
// match the node
|
||||
Pga_MappingMatchNode( p, pObj->Id, pList, Mode );
|
||||
Extra_ProgressBarUpdate( pProgress, i, s_Modes[Mode] );
|
||||
}
|
||||
Extra_ProgressBarStop( pProgress );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the match of the cut.]
|
||||
|
||||
Description [Returns 1 if feasible.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline float Pga_CutGetArrival( Pga_Man_t * p, Cut_Cut_t * pCut )
|
||||
{
|
||||
float DelayCur, DelayWorst;
|
||||
unsigned i;
|
||||
assert( pCut->nLeaves > 1 );
|
||||
DelayWorst = -ABC_INFINITY;
|
||||
for ( i = 0; i < pCut->nLeaves; i++ )
|
||||
{
|
||||
DelayCur = Pga_Node(p, pCut->pLeaves[i])->Match.Delay;
|
||||
if ( DelayWorst < DelayCur )
|
||||
DelayWorst = DelayCur;
|
||||
}
|
||||
DelayWorst += p->pLutDelays[pCut->nLeaves];
|
||||
return DelayWorst;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the match of the cut.]
|
||||
|
||||
Description [Returns 1 if feasible.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline float Pga_CutGetAreaFlow( Pga_Man_t * p, Cut_Cut_t * pCut )
|
||||
{
|
||||
float Flow;
|
||||
Pga_Node_t * pNode;
|
||||
unsigned i;
|
||||
assert( pCut->nLeaves > 1 );
|
||||
Flow = p->pLutAreas[pCut->nLeaves];
|
||||
for ( i = 0; i < pCut->nLeaves; i++ )
|
||||
{
|
||||
pNode = Pga_Node(p, pCut->pLeaves[i]);
|
||||
assert( pNode->EstRefs > 0 );
|
||||
Flow += pNode->Match.Area / pNode->EstRefs;
|
||||
}
|
||||
return Flow;
|
||||
}
|
||||
|
||||
/**function*************************************************************
|
||||
|
||||
synopsis [References the cut.]
|
||||
|
||||
description [This procedure is similar to the procedure NodeReclaim.]
|
||||
|
||||
sideeffects []
|
||||
|
||||
seealso []
|
||||
|
||||
***********************************************************************/
|
||||
float Pga_CutRef( Pga_Man_t * p, Pga_Node_t * pNode, Cut_Cut_t * pCut )
|
||||
{
|
||||
Pga_Node_t * pFanin;
|
||||
float aArea;
|
||||
unsigned i;
|
||||
// start the area of this cut
|
||||
aArea = p->pLutAreas[pCut->nLeaves];
|
||||
// go through the children
|
||||
for ( i = 0; i < pCut->nLeaves; i++ )
|
||||
{
|
||||
pFanin = Pga_Node(p, pCut->pLeaves[i]);
|
||||
assert( pFanin->nRefs >= 0 );
|
||||
if ( pFanin->nRefs++ > 0 )
|
||||
continue;
|
||||
if ( pFanin->Match.pCut == NULL )
|
||||
continue;
|
||||
aArea += Pga_CutRef( p, pFanin, pFanin->Match.pCut );
|
||||
}
|
||||
return aArea;
|
||||
}
|
||||
|
||||
/**function*************************************************************
|
||||
|
||||
synopsis [Dereferences the cut.]
|
||||
|
||||
description [This procedure is similar to the procedure NodeRecusiveDeref.]
|
||||
|
||||
sideeffects []
|
||||
|
||||
seealso []
|
||||
|
||||
***********************************************************************/
|
||||
float Pga_CutDeref( Pga_Man_t * p, Pga_Node_t * pNode, Cut_Cut_t * pCut )
|
||||
{
|
||||
Pga_Node_t * pFanin;
|
||||
float aArea;
|
||||
unsigned i;
|
||||
// start the area of this cut
|
||||
aArea = p->pLutAreas[pCut->nLeaves];
|
||||
// go through the children
|
||||
for ( i = 0; i < pCut->nLeaves; i++ )
|
||||
{
|
||||
pFanin = Pga_Node(p, pCut->pLeaves[i]);
|
||||
assert( pFanin->nRefs > 0 );
|
||||
if ( --pFanin->nRefs > 0 )
|
||||
continue;
|
||||
if ( pFanin->Match.pCut == NULL )
|
||||
continue;
|
||||
aArea += Pga_CutDeref( p, pFanin, pFanin->Match.pCut );
|
||||
}
|
||||
return aArea;
|
||||
}
|
||||
|
||||
/**function*************************************************************
|
||||
|
||||
synopsis [Computes the exact area associated with the cut.]
|
||||
|
||||
description [Assumes that the cut is deferenced.]
|
||||
|
||||
sideeffects []
|
||||
|
||||
seealso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline float Pga_CutGetAreaDerefed( Pga_Man_t * p, Pga_Node_t * pNode, Cut_Cut_t * pCut )
|
||||
{
|
||||
float aResult, aResult2;
|
||||
assert( pCut->nLeaves > 1 );
|
||||
aResult2 = Pga_CutRef( p, pNode, pCut );
|
||||
aResult = Pga_CutDeref( p, pNode, pCut );
|
||||
assert( aResult == aResult2 );
|
||||
return aResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the match of the cut.]
|
||||
|
||||
Description [Returns 1 if feasible.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Pga_MappingMatchCut( Pga_Man_t * p, Pga_Node_t * pNode, Cut_Cut_t * pCut, int Mode, Pga_Match_t * pMatch )
|
||||
{
|
||||
// compute the arrival time of the cut and its area flow
|
||||
pMatch->Delay = Pga_CutGetArrival( p, pCut );
|
||||
// drop the cut if it does not meet the required times
|
||||
if ( pMatch->Delay > pNode->Required + p->Epsilon )
|
||||
return 0;
|
||||
// get the second parameter
|
||||
if ( Mode == 0 || Mode == 1 )
|
||||
pMatch->Area = Pga_CutGetAreaFlow( p, pCut );
|
||||
else if ( Mode == 2 )
|
||||
pMatch->Area = Pga_CutGetAreaDerefed( p, pNode, pCut );
|
||||
// else if ( Mode == 3 )
|
||||
// pMatch->Area = Pga_CutGetSwitching( p, pNode, pCut );
|
||||
// if no cut is assigned, use the current one
|
||||
pMatch->pCut = pCut;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Compares two matches.]
|
||||
|
||||
Description [Returns 1 if the second match is better.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Pga_MappingCompareMatches( Pga_Man_t * p, Pga_Match_t * pMatchBest, Pga_Match_t * pMatchCur, int Mode )
|
||||
{
|
||||
if ( pMatchBest->pCut == NULL )
|
||||
return 1;
|
||||
if ( Mode == 0 )
|
||||
{
|
||||
// compare delays
|
||||
if ( pMatchBest->Delay < pMatchCur->Delay - p->Epsilon )
|
||||
return 0;
|
||||
if ( pMatchBest->Delay > pMatchCur->Delay + p->Epsilon )
|
||||
return 1;
|
||||
// compare areas
|
||||
if ( pMatchBest->Area < pMatchCur->Area - p->Epsilon )
|
||||
return 0;
|
||||
if ( pMatchBest->Area > pMatchCur->Area + p->Epsilon )
|
||||
return 1;
|
||||
// if equal, do not update
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// compare areas
|
||||
if ( pMatchBest->Area < pMatchCur->Area - p->Epsilon )
|
||||
return 0;
|
||||
if ( pMatchBest->Area > pMatchCur->Area + p->Epsilon )
|
||||
return 1;
|
||||
// compare delays
|
||||
if ( pMatchBest->Delay < pMatchCur->Delay - p->Epsilon )
|
||||
return 0;
|
||||
if ( pMatchBest->Delay > pMatchCur->Delay + p->Epsilon )
|
||||
return 1;
|
||||
// if equal, do not update
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the best matching for one node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Pga_MappingMatchNode( Pga_Man_t * p, int NodeId, Cut_Cut_t * pList, int Mode )
|
||||
{
|
||||
Pga_Match_t MatchCur, * pMatchCur = &MatchCur;
|
||||
Pga_Match_t MatchBest, * pMatchBest = &MatchBest;
|
||||
Pga_Node_t * pNode;
|
||||
Cut_Cut_t * pCut;
|
||||
|
||||
// get the mapping node
|
||||
pNode = Pga_Node( p, NodeId );
|
||||
|
||||
// prepare for mapping
|
||||
if ( Mode == 0 )
|
||||
pNode->EstRefs = (float)pNode->nRefs;
|
||||
else if ( Mode == 1 )
|
||||
pNode->EstRefs = (float)((2.0 * pNode->EstRefs + pNode->nRefs) / 3.0);
|
||||
else if ( Mode == 2 && pNode->nRefs > 0 )
|
||||
Pga_CutDeref( p, pNode, pNode->Match.pCut );
|
||||
// else if ( Mode == 3 && pNode->nRefs > 0 )
|
||||
// Pga_CutDerefSwitch( p, pNode, pNode->Match.pCut );
|
||||
|
||||
// start the best match
|
||||
pMatchBest->pCut = NULL;
|
||||
|
||||
// go through the other cuts
|
||||
assert( pList->pNext );
|
||||
for ( pCut = pList->pNext; pCut; pCut = pCut->pNext )
|
||||
{
|
||||
// compute match for this cut
|
||||
if ( !Pga_MappingMatchCut( p, pNode, pCut, Mode, pMatchCur ) )
|
||||
continue;
|
||||
// compare matches
|
||||
if ( !Pga_MappingCompareMatches( p, pMatchBest, pMatchCur, Mode ) )
|
||||
continue;
|
||||
// the best match should be updated
|
||||
*pMatchBest = *pMatchCur;
|
||||
}
|
||||
|
||||
// make sure the match is found
|
||||
if ( pMatchBest->pCut != NULL )
|
||||
pNode->Match = *pMatchBest;
|
||||
else
|
||||
{
|
||||
assert( 0 );
|
||||
// Pga_MappingMatchCut( p, pNode, pCut, Mode, pNode->Match );
|
||||
}
|
||||
|
||||
// reference the best cut
|
||||
if ( Mode == 2 && pNode->nRefs > 0 )
|
||||
Pga_CutRef( p, pNode, pNode->Match.pCut );
|
||||
// else if ( Mode == 3 && pNode->nRefs > 0 )
|
||||
// Pga_CutRefSwitch( p, pNode, pNode->Match.pCut );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -1,320 +0,0 @@
|
||||
/**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 ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
Reference in New Issue
Block a user