summaryrefslogtreecommitdiffstats
path: root/abc70930/src/map/fpga/fpgaCreate.c
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2007-09-30 08:01:00 -0700
committerAlan Mishchenko <alanmi@berkeley.edu>2007-09-30 08:01:00 -0700
commite54d9691616b9a0326e2fdb3156bb4eeb8abfcd7 (patch)
treede3ffe87c3e17950351e3b7d97fa18318bd5ea9a /abc70930/src/map/fpga/fpgaCreate.c
parent7d7e60f2dc84393cd4c5db22d2eaf7b1fb1a79b2 (diff)
downloadabc-e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7.tar.gz
abc-e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7.tar.bz2
abc-e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7.zip
Version abc70930
Diffstat (limited to 'abc70930/src/map/fpga/fpgaCreate.c')
-rw-r--r--abc70930/src/map/fpga/fpgaCreate.c580
1 files changed, 580 insertions, 0 deletions
diff --git a/abc70930/src/map/fpga/fpgaCreate.c b/abc70930/src/map/fpga/fpgaCreate.c
new file mode 100644
index 00000000..fa0f80d1
--- /dev/null
+++ b/abc70930/src/map/fpga/fpgaCreate.c
@@ -0,0 +1,580 @@
+/**CFile****************************************************************
+
+ FileName [fpgaCreate.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Technology mapping for variable-size-LUT FPGAs.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - August 18, 2004.]
+
+ Revision [$Id: fpgaCreate.c,v 1.8 2004/09/30 21:18:09 satrajit Exp $]
+
+***********************************************************************/
+
+#include "fpgaInt.h"
+#include "main.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Fpga_TableCreate( Fpga_Man_t * p );
+static void Fpga_TableResize( Fpga_Man_t * p );
+static Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 );
+
+// hash key for the structural hash table
+static inline unsigned Fpga_HashKey2( Fpga_Node_t * p0, Fpga_Node_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reads parameters of the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_ManReadInputNum( Fpga_Man_t * p ) { return p->nInputs; }
+int Fpga_ManReadOutputNum( Fpga_Man_t * p ) { return p->nOutputs; }
+Fpga_Node_t ** Fpga_ManReadInputs ( Fpga_Man_t * p ) { return p->pInputs; }
+Fpga_Node_t ** Fpga_ManReadOutputs( Fpga_Man_t * p ) { return p->pOutputs; }
+Fpga_Node_t * Fpga_ManReadConst1 ( Fpga_Man_t * p ) { return p->pConst1; }
+float * Fpga_ManReadInputArrivals( Fpga_Man_t * p ) { return p->pInputArrivals;}
+int Fpga_ManReadVerbose( Fpga_Man_t * p ) { return p->fVerbose; }
+float * Fpga_ManReadLutAreas( Fpga_Man_t * p ) { return p->pLutLib->pLutAreas; }
+void Fpga_ManSetTimeToMap( Fpga_Man_t * p, int Time ) { p->timeToMap = Time; }
+void Fpga_ManSetTimeToNet( Fpga_Man_t * p, int Time ) { p->timeToNet = Time; }
+void Fpga_ManSetTimeTotal( Fpga_Man_t * p, int Time ) { p->timeTotal = Time; }
+void Fpga_ManSetOutputNames( Fpga_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; }
+void Fpga_ManSetInputArrivals( Fpga_Man_t * p, float * pArrivals ) { p->pInputArrivals = pArrivals; }
+void Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery ) { p->fAreaRecovery = fAreaRecovery;}
+void Fpga_ManSetDelayLimit( Fpga_Man_t * p, float DelayLimit ) { p->DelayLimit = DelayLimit; }
+void Fpga_ManSetAreaLimit( Fpga_Man_t * p, float AreaLimit ) { p->AreaLimit = AreaLimit; }
+void Fpga_ManSetTimeLimit( Fpga_Man_t * p, float TimeLimit ) { p->TimeLimit = TimeLimit; }
+void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes ) { p->nChoiceNodes = nChoiceNodes; }
+void Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices ) { p->nChoices = nChoices; }
+void Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; }
+void Fpga_ManSetSwitching( Fpga_Man_t * p, int fSwitching ) { p->fSwitching = fSwitching; }
+void Fpga_ManSetLatchPaths( Fpga_Man_t * p, int fLatchPaths ) { p->fLatchPaths = fLatchPaths; }
+void Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches ) { p->nLatches = nLatches; }
+void Fpga_ManSetDelayTarget( Fpga_Man_t * p, float DelayTarget ) { p->DelayTarget = DelayTarget; }
+void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName ) { p->pFileName = pFileName; }
+
+/**Function*************************************************************
+
+ Synopsis [Reads the parameters of the LUT library.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib ) { return pLib->LutMax; }
+
+/**Function*************************************************************
+
+ Synopsis [Reads parameters of the mapping node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Fpga_NodeReadData0( Fpga_Node_t * p ) { return p->pData0; }
+Fpga_Node_t * Fpga_NodeReadData1( Fpga_Node_t * p ) { return p->pLevel; }
+int Fpga_NodeReadRefs( Fpga_Node_t * p ) { return p->nRefs; }
+int Fpga_NodeReadNum( Fpga_Node_t * p ) { return p->Num; }
+int Fpga_NodeReadLevel( Fpga_Node_t * p ) { return Fpga_Regular(p)->Level; }
+Fpga_Cut_t * Fpga_NodeReadCuts( Fpga_Node_t * p ) { return p->pCuts; }
+Fpga_Cut_t * Fpga_NodeReadCutBest( Fpga_Node_t * p ) { return p->pCutBest; }
+Fpga_Node_t * Fpga_NodeReadOne( Fpga_Node_t * p ) { return p->p1; }
+Fpga_Node_t * Fpga_NodeReadTwo( Fpga_Node_t * p ) { return p->p2; }
+void Fpga_NodeSetData0( Fpga_Node_t * p, char * pData ) { p->pData0 = pData; }
+void Fpga_NodeSetData1( Fpga_Node_t * p, Fpga_Node_t * pNode ) { p->pLevel = pNode; }
+void Fpga_NodeSetNextE( Fpga_Node_t * p, Fpga_Node_t * pNextE ) { p->pNextE = pNextE; }
+void Fpga_NodeSetRepr( Fpga_Node_t * p, Fpga_Node_t * pRepr ) { p->pRepr = pRepr; }
+void Fpga_NodeSetSwitching( Fpga_Node_t * p, float Switching ) { p->Switching = Switching; }
+
+/**Function*************************************************************
+
+ Synopsis [Checks the type of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_NodeIsConst( Fpga_Node_t * p ) { return (Fpga_Regular(p))->Num == -1; }
+int Fpga_NodeIsVar( Fpga_Node_t * p ) { return (Fpga_Regular(p))->p1 == NULL && (Fpga_Regular(p))->Num >= 0; }
+int Fpga_NodeIsAnd( Fpga_Node_t * p ) { return (Fpga_Regular(p))->p1 != NULL; }
+int Fpga_NodeComparePhase( Fpga_Node_t * p1, Fpga_Node_t * p2 ) { assert( !Fpga_IsComplement(p1) ); assert( !Fpga_IsComplement(p2) ); return p1->fInv ^ p2->fInv; }
+
+/**Function*************************************************************
+
+ Synopsis [Reads parameters from the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fpga_CutReadLeavesNum( Fpga_Cut_t * p ) { return p->nLeaves; }
+Fpga_Node_t ** Fpga_CutReadLeaves( Fpga_Cut_t * p ) { return p->ppLeaves; }
+
+
+/**Function*************************************************************
+
+ Synopsis [Create the mapping manager.]
+
+ Description [The number of inputs and outputs is assumed to be
+ known is advance. It is much simpler to have them fixed upfront.
+ When it comes to representing the object graph in the form of
+ AIG, the resulting manager is similar to the regular AIG manager,
+ except that it does not use reference counting (and therefore
+ does not have garbage collections). It does have table resizing.
+ The data structure is more flexible to represent additional
+ information needed for mapping.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose )
+{
+ Fpga_Man_t * p;
+ int i;
+
+ // start the manager
+ p = ALLOC( Fpga_Man_t, 1 );
+ memset( p, 0, sizeof(Fpga_Man_t) );
+ p->pLutLib = Abc_FrameReadLibLut();
+ p->nVarsMax = p->pLutLib->LutMax;
+ p->fVerbose = fVerbose;
+ p->fAreaRecovery = 1;
+ p->fEpsilon = (float)0.001;
+
+ Fpga_TableCreate( p );
+//if ( p->fVerbose )
+// printf( "Node = %d (%d) bytes. Cut = %d bytes.\n", sizeof(Fpga_Node_t), FPGA_NUM_BYTES(sizeof(Fpga_Node_t)), sizeof(Fpga_Cut_t) );
+ p->mmNodes = Extra_MmFixedStart( FPGA_NUM_BYTES(sizeof(Fpga_Node_t)) );
+ p->mmCuts = Extra_MmFixedStart( sizeof(Fpga_Cut_t) );
+
+ assert( p->nVarsMax > 0 );
+// Fpga_MappingSetupTruthTables( p->uTruths );
+
+ // make sure the constant node will get index -1
+ p->nNodes = -1;
+ // create the constant node
+ p->pConst1 = Fpga_NodeCreate( p, NULL, NULL );
+ p->vNodesAll = Fpga_NodeVecAlloc( 1000 );
+ p->vMapping = Fpga_NodeVecAlloc( 1000 );
+
+ // create the PI nodes
+ p->nInputs = nInputs;
+ p->pInputs = ALLOC( Fpga_Node_t *, nInputs );
+ for ( i = 0; i < nInputs; i++ )
+ p->pInputs[i] = Fpga_NodeCreate( p, NULL, NULL );
+
+ // create the place for the output nodes
+ p->nOutputs = nOutputs;
+ p->pOutputs = ALLOC( Fpga_Node_t *, nOutputs );
+ memset( p->pOutputs, 0, sizeof(Fpga_Node_t *) * nOutputs );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_ManFree( Fpga_Man_t * p )
+{
+// Fpga_ManStats( p );
+// int i;
+// for ( i = 0; i < p->vNodesAll->nSize; i++ )
+// Fpga_NodeVecFree( p->vNodesAll->pArray[i]->vFanouts );
+// Fpga_NodeVecFree( p->pConst1->vFanouts );
+ if ( p->vMapping )
+ Fpga_NodeVecFree( p->vMapping );
+ if ( p->vAnds )
+ Fpga_NodeVecFree( p->vAnds );
+ if ( p->vNodesAll )
+ Fpga_NodeVecFree( p->vNodesAll );
+ Extra_MmFixedStop( p->mmNodes );
+ Extra_MmFixedStop( p->mmCuts );
+ FREE( p->ppOutputNames );
+ FREE( p->pInputArrivals );
+ FREE( p->pInputs );
+ FREE( p->pOutputs );
+ FREE( p->pBins );
+ FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints runtime statistics of the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_ManPrintTimeStats( Fpga_Man_t * p )
+{
+ extern char * pNetName;
+ extern int TotalLuts;
+// FILE * pTable;
+
+
+/*
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%s ", pNetName );
+ fprintf( pTable, "%.0f ", p->fRequiredGlo );
+// fprintf( pTable, "%.0f ", p->fAreaGlo );//+ (float)nOutputInvs );
+ fprintf( pTable, "%.0f ", (float)TotalLuts );
+ fprintf( pTable, "%4.2f\n", (float)(p->timeTotal-p->timeToMap)/(float)(CLOCKS_PER_SEC) );
+ fclose( pTable );
+*/
+
+// printf( "N-canonical = %d. Matchings = %d. ", p->nCanons, p->nMatches );
+// printf( "Choice nodes = %d. Choices = %d.\n", p->nChoiceNodes, p->nChoices );
+ PRT( "ToMap", p->timeToMap );
+ PRT( "Cuts ", p->timeCuts );
+ PRT( "Match", p->timeMatch );
+ PRT( "Area ", p->timeRecover );
+ PRT( "ToNet", p->timeToNet );
+ PRT( "TOTAL", p->timeTotal );
+ if ( p->time1 ) { PRT( "time1", p->time1 ); }
+ if ( p->time2 ) { PRT( "time2", p->time2 ); }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new node.]
+
+ Description [This procedure should be called to create the constant
+ node and the PI nodes first.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+ Fpga_Node_t * pNode;
+ // create the node
+ pNode = (Fpga_Node_t *)Extra_MmFixedEntryFetch( p->mmNodes );
+ memset( pNode, 0, sizeof(Fpga_Node_t) );
+ // set very large required time
+ pNode->tRequired = FPGA_FLOAT_LARGE;
+ pNode->aEstFanouts = -1;
+ pNode->p1 = p1;
+ pNode->p2 = p2;
+ // set the number of this node
+ pNode->Num = p->nNodes++;
+ // place to store the fanouts
+// pNode->vFanouts = Fpga_NodeVecAlloc( 5 );
+ // store this node in the internal array
+ if ( pNode->Num >= 0 )
+ Fpga_NodeVecPush( p->vNodesAll, pNode );
+ else
+ pNode->fInv = 1;
+ // set the level of this node
+ if ( p1 )
+ {
+#ifdef FPGA_ALLOCATE_FANOUT
+ // create the fanout info
+ Fpga_NodeAddFaninFanout( Fpga_Regular(p1), pNode );
+ Fpga_NodeAddFaninFanout( Fpga_Regular(p2), pNode );
+#endif
+ // compute the level
+ pNode->Level = 1 + FPGA_MAX(Fpga_Regular(p1)->Level, Fpga_Regular(p2)->Level);
+ pNode->fInv = Fpga_NodeIsSimComplement(p1) & Fpga_NodeIsSimComplement(p2);
+ }
+ // reference the inputs
+ if ( p1 ) Fpga_NodeRef(p1);
+ if ( p2 ) Fpga_NodeRef(p2);
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create the unique table of AND gates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_TableCreate( Fpga_Man_t * pMan )
+{
+ assert( pMan->pBins == NULL );
+ pMan->nBins = Cudd_Prime(50000);
+ pMan->pBins = ALLOC( Fpga_Node_t *, pMan->nBins );
+ memset( pMan->pBins, 0, sizeof(Fpga_Node_t *) * pMan->nBins );
+ pMan->nNodes = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looks up the AND2 node in the unique table.]
+
+ Description [This procedure implements one-level hashing. All the nodes
+ are hashed by their children. If the node with the same children was already
+ created, it is returned by the call to this procedure. If it does not exist,
+ this procedure creates a new node with these children. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * pMan, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+ Fpga_Node_t * pEnt;
+ unsigned Key;
+
+ if ( p1 == p2 )
+ return p1;
+ if ( p1 == Fpga_Not(p2) )
+ return Fpga_Not(pMan->pConst1);
+ if ( Fpga_NodeIsConst(p1) )
+ {
+ if ( p1 == pMan->pConst1 )
+ return p2;
+ return Fpga_Not(pMan->pConst1);
+ }
+ if ( Fpga_NodeIsConst(p2) )
+ {
+ if ( p2 == pMan->pConst1 )
+ return p1;
+ return Fpga_Not(pMan->pConst1);
+ }
+
+ if ( Fpga_Regular(p1)->Num > Fpga_Regular(p2)->Num )
+ pEnt = p1, p1 = p2, p2 = pEnt;
+
+ Key = Fpga_HashKey2( p1, p2, pMan->nBins );
+ for ( pEnt = pMan->pBins[Key]; pEnt; pEnt = pEnt->pNext )
+ if ( pEnt->p1 == p1 && pEnt->p2 == p2 )
+ return pEnt;
+ // resize the table
+ if ( pMan->nNodes >= 2 * pMan->nBins )
+ {
+ Fpga_TableResize( pMan );
+ Key = Fpga_HashKey2( p1, p2, pMan->nBins );
+ }
+ // create the new node
+ pEnt = Fpga_NodeCreate( pMan, p1, p2 );
+ // add the node to the corresponding linked list in the table
+ pEnt->pNext = pMan->pBins[Key];
+ pMan->pBins[Key] = pEnt;
+ return pEnt;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_TableResize( Fpga_Man_t * pMan )
+{
+ Fpga_Node_t ** pBinsNew;
+ Fpga_Node_t * pEnt, * pEnt2;
+ int nBinsNew, Counter, i, clk;
+ unsigned Key;
+
+clk = clock();
+ // get the new table size
+ nBinsNew = Cudd_Prime(2 * pMan->nBins);
+ // allocate a new array
+ pBinsNew = ALLOC( Fpga_Node_t *, nBinsNew );
+ memset( pBinsNew, 0, sizeof(Fpga_Node_t *) * nBinsNew );
+ // rehash the entries from the old table
+ Counter = 0;
+ for ( i = 0; i < pMan->nBins; i++ )
+ for ( pEnt = pMan->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt;
+ pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL )
+ {
+ Key = Fpga_HashKey2( pEnt->p1, pEnt->p2, nBinsNew );
+ pEnt->pNext = pBinsNew[Key];
+ pBinsNew[Key] = pEnt;
+ Counter++;
+ }
+ assert( Counter == pMan->nNodes - pMan->nInputs );
+ if ( pMan->fVerbose )
+ {
+// printf( "Increasing the unique table size from %6d to %6d. ", pMan->nBins, nBinsNew );
+// PRT( "Time", clock() - clk );
+ }
+ // replace the table and the parameters
+ free( pMan->pBins );
+ pMan->pBins = pBinsNew;
+ pMan->nBins = nBinsNew;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Elementary AND operation on the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeAnd( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+ Fpga_Node_t * pNode;
+ pNode = Fpga_TableLookup( p, p1, p2 );
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Elementary OR operation on the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeOr( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+ Fpga_Node_t * pNode;
+ pNode = Fpga_Not( Fpga_TableLookup( p, Fpga_Not(p1), Fpga_Not(p2) ) );
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Elementary EXOR operation on the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeExor( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 )
+{
+ return Fpga_NodeMux( p, p1, Fpga_Not(p2), p2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Elementary MUX operation on the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fpga_Node_t * Fpga_NodeMux( Fpga_Man_t * p, Fpga_Node_t * pC, Fpga_Node_t * pT, Fpga_Node_t * pE )
+{
+ Fpga_Node_t * pAnd1, * pAnd2, * pRes;
+ pAnd1 = Fpga_TableLookup( p, pC, pT );
+ pAnd2 = Fpga_TableLookup( p, Fpga_Not(pC), pE );
+ pRes = Fpga_NodeOr( p, pAnd1, pAnd2 );
+ return pRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets the node to be equivalent to the given one.]
+
+ Description [This procedure is a work-around for the equivalence check.
+ Does not verify the equivalence. Use at the user's risk.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_NodeSetChoice( Fpga_Man_t * pMan, Fpga_Node_t * pNodeOld, Fpga_Node_t * pNodeNew )
+{
+ pNodeNew->pNextE = pNodeOld->pNextE;
+ pNodeOld->pNextE = pNodeNew;
+ pNodeNew->pRepr = pNodeOld;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints some interesting stats.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fpga_ManStats( Fpga_Man_t * p )
+{
+ FILE * pTable;
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%s ", p->pFileName );
+ fprintf( pTable, "%4d ", p->nInputs - p->nLatches );
+ fprintf( pTable, "%4d ", p->nOutputs - p->nLatches );
+ fprintf( pTable, "%4d ", p->nLatches );
+ fprintf( pTable, "%7d ", p->vAnds->nSize );
+ fprintf( pTable, "%7d ", Fpga_CutCountAll(p) );
+ fprintf( pTable, "%2d\n", (int)p->fRequiredGlo );
+ fclose( pTable );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+