From e52e48c3643b0a69ee84291634d5a31956d183db Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 10 Sep 2005 08:01:00 -0700 Subject: Version abc50910 --- src/map/fpga/fpga.c | 4 +- src/map/fpga/fpga.h | 5 + src/map/fpga/fpgaCreate.c | 2 +- src/map/fpga/fpgaCut.c | 2 +- src/map/fpga/fpgaLib.c | 17 ++ src/map/mapper/mapper.c | 2 +- src/map/mapper/mapperCreate.c | 4 +- src/map/mapper/mapperCut.c | 2 +- src/map/mio/mio.c | 6 +- src/map/pga/module.make | 4 + src/map/pga/pga.h | 72 ++++++++ src/map/pga/pgaCore.c | 152 +++++++++++++++++ src/map/pga/pgaInt.h | 132 +++++++++++++++ src/map/pga/pgaMan.c | 180 ++++++++++++++++++++ src/map/pga/pgaMatch.c | 378 ++++++++++++++++++++++++++++++++++++++++++ src/map/pga/pgaUtil.c | 320 +++++++++++++++++++++++++++++++++++ 16 files changed, 1271 insertions(+), 11 deletions(-) create mode 100644 src/map/pga/module.make create mode 100644 src/map/pga/pga.h create mode 100644 src/map/pga/pgaCore.c create mode 100644 src/map/pga/pgaInt.h create mode 100644 src/map/pga/pgaMan.c create mode 100644 src/map/pga/pgaMatch.c create mode 100644 src/map/pga/pgaUtil.c (limited to 'src/map') diff --git a/src/map/fpga/fpga.c b/src/map/fpga/fpga.c index 3d2ca913..9c56f6af 100644 --- a/src/map/fpga/fpga.c +++ b/src/map/fpga/fpga.c @@ -77,7 +77,7 @@ void Fpga_Init( Abc_Frame_t * pAbc ) ***********************************************************************/ void Fpga_End() { - Fpga_LutLibFree( Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame()) ); + Fpga_LutLibFree( Abc_FrameReadLibLut() ); } @@ -221,7 +221,7 @@ int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) } // set the new network - Fpga_LutLibPrint( Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame()) ); + Fpga_LutLibPrint( Abc_FrameReadLibLut() ); return 0; usage: diff --git a/src/map/fpga/fpga.h b/src/map/fpga/fpga.h index 19241a74..04894d23 100644 --- a/src/map/fpga/fpga.h +++ b/src/map/fpga/fpga.h @@ -142,6 +142,11 @@ extern Fpga_Man_t * Fpga_ManDupFraig( Fraig_Man_t * pManFraig ); extern Fpga_Man_t * Fpga_ManBalanceFraig( Fraig_Man_t * pManFraig, int * pInputArrivals ); /*=== fpgaLib.c =============================================================*/ extern Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p ); +extern int Fpga_LutLibReadVarMax( Fpga_LutLib_t * p ); +extern float * Fpga_LutLibReadLutAreas( Fpga_LutLib_t * p ); +extern float * Fpga_LutLibReadLutDelays( Fpga_LutLib_t * p ); +extern float Fpga_LutLibReadLutArea( Fpga_LutLib_t * p, int Size ); +extern float Fpga_LutLibReadLutDelay( Fpga_LutLib_t * p, int Size ); /*=== fpgaTruth.c =============================================================*/ extern void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut ); /*=== fpgaUtil.c =============================================================*/ diff --git a/src/map/fpga/fpgaCreate.c b/src/map/fpga/fpgaCreate.c index b7bfa3c5..c7acf974 100644 --- a/src/map/fpga/fpgaCreate.c +++ b/src/map/fpga/fpgaCreate.c @@ -164,7 +164,7 @@ Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose ) // start the manager p = ALLOC( Fpga_Man_t, 1 ); memset( p, 0, sizeof(Fpga_Man_t) ); - p->pLutLib = Abc_FrameReadLibLut(Abc_FrameGetGlobalFrame()); + p->pLutLib = Abc_FrameReadLibLut(); p->nVarsMax = p->pLutLib->LutMax; p->fVerbose = fVerbose; p->fAreaRecovery = 1; diff --git a/src/map/fpga/fpgaCut.c b/src/map/fpga/fpgaCut.c index 5b5fbe69..f9afa581 100644 --- a/src/map/fpga/fpgaCut.c +++ b/src/map/fpga/fpgaCut.c @@ -245,7 +245,7 @@ Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Nod // set at the node pNode->pCuts = pCut; // remove the dominated cuts - Fpga_CutFilter( p, pNode ); +// Fpga_CutFilter( p, pNode ); // set the phase correctly if ( pNode->pRepr && Fpga_NodeComparePhase(pNode, pNode->pRepr) ) { diff --git a/src/map/fpga/fpgaLib.c b/src/map/fpga/fpgaLib.c index 9fd8e281..eb0b5c93 100644 --- a/src/map/fpga/fpgaLib.c +++ b/src/map/fpga/fpgaLib.c @@ -26,6 +26,23 @@ /// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [APIs to access LUT library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_LutLibReadVarMax( Fpga_LutLib_t * p ) { return p->LutMax; } +float * Fpga_LutLibReadLutAreas( Fpga_LutLib_t * p ) { return p->pLutAreas; } +float * Fpga_LutLibReadLutDelays( Fpga_LutLib_t * p ) { return p->pLutDelays; } +float Fpga_LutLibReadLutArea( Fpga_LutLib_t * p, int Size ) { assert( Size <= p->LutMax ); return p->pLutAreas[Size]; } +float Fpga_LutLibReadLutDelay( Fpga_LutLib_t * p, int Size ) { assert( Size <= p->LutMax ); return p->pLutDelays[Size]; } + /**Function************************************************************* Synopsis [Reads the description of LUTs from the LUT library file.] diff --git a/src/map/mapper/mapper.c b/src/map/mapper/mapper.c index e59fa4a3..3cfd159f 100644 --- a/src/map/mapper/mapper.c +++ b/src/map/mapper/mapper.c @@ -61,7 +61,7 @@ void Map_Init( Abc_Frame_t * pAbc ) void Map_End() { // Map_SuperLibFree( s_pSuperLib ); - Map_SuperLibFree( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) ); + Map_SuperLibFree( Abc_FrameReadLibSuper() ); } diff --git a/src/map/mapper/mapperCreate.c b/src/map/mapper/mapperCreate.c index 31fbf0ea..3dee7f7e 100644 --- a/src/map/mapper/mapperCreate.c +++ b/src/map/mapper/mapperCreate.c @@ -183,7 +183,7 @@ Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose ) int i; // derive the supergate library - if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) == NULL ) + if ( Abc_FrameReadLibSuper() == NULL ) { printf( "The supergate library is not specified. Use \"read_library\" or \"read_super\".\n" ); return NULL; @@ -192,7 +192,7 @@ Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose ) // start the manager p = ALLOC( Map_Man_t, 1 ); memset( p, 0, sizeof(Map_Man_t) ); - p->pSuperLib = Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()); + p->pSuperLib = Abc_FrameReadLibSuper(); p->nVarsMax = p->pSuperLib->nVarsMax; p->fVerbose = fVerbose; p->fEpsilon = (float)0.001; diff --git a/src/map/mapper/mapperCut.c b/src/map/mapper/mapperCut.c index b5ce4018..514d9da8 100644 --- a/src/map/mapper/mapperCut.c +++ b/src/map/mapper/mapperCut.c @@ -208,7 +208,7 @@ Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * // set at the node pNode->pCuts = pCut; // remove the dominated cuts -// Map_CutFilter( p, pNode ); + Map_CutFilter( p, pNode ); // set the phase correctly if ( pNode->pRepr && Map_NodeComparePhase(pNode, pNode->pRepr) ) { diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c index bb6dbba1..569bcceb 100644 --- a/src/map/mio/mio.c +++ b/src/map/mio/mio.c @@ -108,7 +108,7 @@ void Mio_Init( Abc_Frame_t * pAbc ) void Mio_End() { // Mio_LibraryDelete( s_pLib ); - Mio_LibraryDelete( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) ); + Mio_LibraryDelete( Abc_FrameReadLibGen() ); } @@ -181,7 +181,7 @@ int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) return 1; } // free the current superlib because it depends on the old Mio library - if ( Abc_FrameReadLibSuper(Abc_FrameGetGlobalFrame()) ) + if ( Abc_FrameReadLibSuper() ) { extern void Map_SuperLibFree( Map_SuperLib_t * p ); // Map_SuperLibFree( s_pSuperLib ); @@ -252,7 +252,7 @@ int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) } // set the new network - Mio_WriteLibrary( stdout, Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()), 0 ); + Mio_WriteLibrary( stdout, Abc_FrameReadLibGen(), 0 ); return 0; usage: diff --git a/src/map/pga/module.make b/src/map/pga/module.make new file mode 100644 index 00000000..2a45327e --- /dev/null +++ b/src/map/pga/module.make @@ -0,0 +1,4 @@ +SRC += src/map/pga/pgaCore.c \ + src/map/pga/pgaMan.c \ + src/map/pga/pgaMatch.c \ + src/map/pga/pgaUtil.c diff --git a/src/map/pga/pga.h b/src/map/pga/pga.h new file mode 100644 index 00000000..5575e0ce --- /dev/null +++ b/src/map/pga/pga.h @@ -0,0 +1,72 @@ +/**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__ + +//////////////////////////////////////////////////////////////////////// +/// 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 DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// 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 ); + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/src/map/pga/pgaCore.c b/src/map/pga/pgaCore.c new file mode 100644 index 00000000..09a9d218 --- /dev/null +++ b/src/map/pga/pgaCore.c @@ -0,0 +1,152 @@ +/**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 DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**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 /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/pga/pgaInt.h b/src/map/pga/pgaInt.h new file mode 100644 index 00000000..27355459 --- /dev/null +++ b/src/map/pga/pgaInt.h @@ -0,0 +1,132 @@ +/**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 +#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 DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +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 ); + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/src/map/pga/pgaMan.c b/src/map/pga/pgaMan.c new file mode 100644 index 00000000..d7573ecf --- /dev/null +++ b/src/map/pga/pgaMan.c @@ -0,0 +1,180 @@ +/**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 DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**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 /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/pga/pgaMatch.c b/src/map/pga/pgaMatch.c new file mode 100644 index 00000000..f9f6b5c4 --- /dev/null +++ b/src/map/pga/pgaMatch.c @@ -0,0 +1,378 @@ +/**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 DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**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 ); +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 /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/map/pga/pgaUtil.c b/src/map/pga/pgaUtil.c new file mode 100644 index 00000000..73f3d381 --- /dev/null +++ b/src/map/pga/pgaUtil.c @@ -0,0 +1,320 @@ +/**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 DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**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 /// +//////////////////////////////////////////////////////////////////////// + + -- cgit v1.2.3