Commit 0e4de190 by Alan Mishchenko

Version abc50819

parent dffcc93b
......@@ -1125,6 +1125,10 @@ SOURCE=.\src\opt\rwr\rwrMan.c
# End Source File
# Begin Source File
SOURCE=.\src\opt\rwr\rwrPrint.c
# End Source File
# Begin Source File
SOURCE=.\src\opt\rwr\rwrUtil.c
# End Source File
# End Group
......
No preview for this file type
......@@ -1323,34 +1323,26 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
int c;
bool fVerbose;
bool fPrecompute;
// external functions
extern void * Abc_NtkManRwrStart( char * pFileName );
extern void Abc_NtkManRwrStop( void * p );
extern void Rwr_Precompute();
extern int Abc_NtkRewrite( Abc_Ntk_t * pNtk );
/*
{
void * p;
int fFlag = 0;
if ( fFlag )
p = Abc_NtkManRwrStart( NULL );
else
p = Abc_NtkManRwrStart( "data.aaa" );
Abc_NtkManRwrStop( p );
return 0;
}
*/
pNtk = Abc_FrameReadNet(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fVerbose = 0;
fVerbose = 0;
fPrecompute = 0;
util_getopt_reset();
while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
while ( ( c = util_getopt( argc, argv, "zvh" ) ) != EOF )
{
switch ( c )
{
case 'z':
fPrecompute ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
......@@ -1361,6 +1353,12 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
}
}
if ( fPrecompute )
{
Rwr_Precompute();
return 0;
}
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
......
......@@ -144,7 +144,7 @@ int Abc_NtkAttach( Abc_Ntk_t * pNtk )
pNode->pData = pNode->pCopy, pNode->pCopy = NULL;
pNtk->Type = ABC_NTK_LOGIC_MAP;
Extra_MmFlexStop( pNtk->pManFunc, 0 );
pNtk->pManFunc = NULL;
pNtk->pManFunc = pGenlib;
printf( "Library gates are successfully attached to the nodes.\n" );
......
......@@ -46,6 +46,8 @@ int Abc_NodeMffcSize( Abc_Obj_t * pNode )
int nConeSize1, nConeSize2;
assert( !Abc_ObjIsComplement( pNode ) );
assert( Abc_ObjIsNode( pNode ) );
if ( Abc_ObjFaninNum(pNode) == 0 )
return 0;
nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference
nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference
assert( nConeSize1 == nConeSize2 );
......@@ -69,6 +71,8 @@ int Abc_NodeMffcLabel( Abc_Obj_t * pNode )
int nConeSize1, nConeSize2;
assert( !Abc_ObjIsComplement( pNode ) );
assert( Abc_ObjIsNode( pNode ) );
if ( Abc_ObjFaninNum(pNode) == 0 )
return 0;
nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference
nConeSize2 = Abc_NodeRefDeref( pNode, 1, 1 ); // reference
assert( nConeSize1 == nConeSize2 );
......
......@@ -50,7 +50,9 @@ int Abc_NtkRewrite( Abc_Ntk_t * pNtk )
assert( Abc_NtkIsAig(pNtk) );
// start the rewriting manager
p = Rwr_ManStart( "data.aaa" );
p = Rwr_ManStart( 0 );
if ( p == NULL )
return 0;
Rwr_ManPrepareNetwork( p, pNtk );
// resynthesize each node once
......
......@@ -80,10 +80,7 @@ extern void Fpga_ManSetTimeToNet( Fpga_Man_t * p, int Time );
extern void Fpga_ManSetTimeTotal( Fpga_Man_t * p, int Time );
extern void Fpga_ManSetOutputNames( Fpga_Man_t * p, char ** ppNames );
extern void Fpga_ManSetInputArrivals( Fpga_Man_t * p, float * pArrivals );
extern void Fpga_ManSetTree( Fpga_Man_t * p, int fTree );
extern void Fpga_ManSetPower( Fpga_Man_t * p, int fPower );
extern void Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery );
extern void Fpga_ManSetResyn( Fpga_Man_t * p, int fResynthesis );
extern void Fpga_ManSetDelayLimit( Fpga_Man_t * p, float DelayLimit );
extern void Fpga_ManSetAreaLimit( Fpga_Man_t * p, float AreaLimit );
extern void Fpga_ManSetTimeLimit( Fpga_Man_t * p, float TimeLimit );
......@@ -95,7 +92,6 @@ extern void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNode
extern void Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices );
extern void Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose );
extern void Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches );
extern void Fpga_ManSetSequential( Fpga_Man_t * p, int fSequential );
extern void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName );
extern int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib );
......
......@@ -17,18 +17,12 @@
***********************************************************************/
#include "fpgaInt.h"
//#include "res.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int Fpga_MappingPostProcess( Fpga_Man_t * p );
extern void Fpga_Experiment( Fpga_Man_t * p );
extern void Fpga_MappingCutsSeq( Fpga_Man_t * p );
extern void Fpga_MappingLValues( Fpga_Man_t * pMan, int fVerbose );
static int Fpga_MappingPostProcess( Fpga_Man_t * p );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
......@@ -51,35 +45,18 @@ extern void Fpga_MappingLValues( Fpga_Man_t * pMan, int fVerbose );
***********************************************************************/
int Fpga_Mapping( Fpga_Man_t * p )
{
int clk;
int clk, clkTotal = clock();
// collect the nodes reachable from POs in the DFS order (including the choices)
p->vAnds = Fpga_MappingDfs( p, 1 );
Fpga_ManReportChoices( p ); // recomputes levels
Fpga_MappingSetChoiceLevels( p );
if ( p->fSequential )
{
// Fpga_MappingCutsSeq( p );
Fpga_MappingCuts( p );
//clk = clock();
// Fpga_MappingLValues( p, p->fVerbose );
//PRT( "Time", clock() - clk );
return 0;
}
// compute the cuts of nodes in the DFS order
clk = clock();
Fpga_MappingCuts( p );
p->timeCuts = clock() - clk;
// Fpga_MappingSortByLevel( p, p->vAnds, 1 );
// derive the truth tables
clk = clock();
// Fpga_MappingTruths( p );
p->timeTruth = clock() - clk;
// match the truth tables to the supergates
clk = clock();
if ( !Fpga_MappingMatches( p, 1 ) )
......@@ -94,10 +71,7 @@ int Fpga_Mapping( Fpga_Man_t * p )
return 0;
p->timeRecover = clock() - clk;
}
// perform resynthesis
// if ( p->fResynthesis )
// Res_Resynthesize( p, p->DelayLimit, p->AreaLimit, p->TimeLimit, 1 );
PRT( "Total mapping time", clock() - clkTotal );
// print the AI-graph used for mapping
//Fpga_ManShow( p, "test" );
......@@ -124,128 +98,59 @@ int Fpga_Mapping( Fpga_Man_t * p )
int Fpga_MappingPostProcess( Fpga_Man_t * p )
{
float aAreaTotalPrev, aAreaTotalCur, aAreaTotalCur2;
float aSwitchTotalPrev, aSwitchTotalCur;
int Iter, clk;
// compute area, set references, and collect nodes used in the mapping
aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
if ( p->fVerbose )
{
printf( "Iteration %dD : Area = %11.1f ", 0, Fpga_MappingArea( p ) );
printf( "Iteration %dD : Area = %11.1f ", 0, aAreaTotalCur );
PRT( "Time", p->timeMatch );
}
// Fpga_MappingExplore( p );
// p->fAreaGlo = Fpga_MappingArea( p );
// return;
// aAreaTotalCur = FPGA_FLOAT_LARGE;
aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
Iter = 1;
do {
clk = clock();
// save the previous area flow
aAreaTotalPrev = aAreaTotalCur;
// compute the required times and the fanouts
Fpga_TimeComputeRequiredGlobal( p );
// remap topologically
Fpga_MappingMatches( p, 0 );
// get the resulting area
aAreaTotalCur = Fpga_MappingArea( p );
// aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
aAreaTotalCur = Fpga_MappingAreaTrav( p );
// note that here we do not update the reference counter
// for some reason, this works better on benchmarks
if ( p->fVerbose )
{
printf( "Iteration %dF : Area = %11.1f ", Iter++, aAreaTotalCur );
PRT( "Time", clock() - clk );
}
if ( p->fPower )
aSwitchTotalCur = Fpga_MappingPrintSwitching( p );
// quit if this iteration reduced area flow by less than 1%
} while ( aAreaTotalPrev > 1.02 * aAreaTotalCur );
// Fpga_MappingExplore( p );
// p->fAreaGlo = Fpga_MappingArea( p );
// return;
/*
// compute the area of each cut
aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
// compute the required times and the fanouts
Fpga_TimeComputeRequiredGlobal( p );
// perform experiment
Fpga_Experiment( p );
*/
// compute the area of each cut
aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
aAreaTotalCur2 = Fpga_MappingComputeCutAreas( p );
// update reference counters
aAreaTotalCur2 = Fpga_MappingSetRefsAndArea( p );
assert( aAreaTotalCur == aAreaTotalCur2 );
// aAreaTotalCur = FPGA_FLOAT_LARGE;
// Iter = 1;
do {
clk = clock();
// save the previous area flow
aAreaTotalPrev = aAreaTotalCur;
// compute the required times and the fanouts
Fpga_TimeComputeRequiredGlobal( p );
// remap topologically
Fpga_MappingMatchesArea( p );
// get the resulting area
aAreaTotalCur = Fpga_MappingArea( p );
aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
if ( p->fVerbose )
{
printf( "Iteration %dA : Area = %11.1f ", Iter++, aAreaTotalCur );
PRT( "Time", clock() - clk );
}
if ( p->fPower )
{
aSwitchTotalPrev = aSwitchTotalCur;
aSwitchTotalCur = Fpga_MappingPrintSwitching( p );
}
// quit if this iteration reduced area flow by less than 1%
} while ( aAreaTotalPrev > 1.02 * aAreaTotalCur );
if ( p->fPower )
{
do {
clk = clock();
// save the previous area flow
aAreaTotalPrev = aAreaTotalCur;
// compute the required times and the fanouts
Fpga_TimeComputeRequiredGlobal( p );
// remap topologically
Fpga_MappingMatchesSwitch( p );
// get the resulting area
aAreaTotalCur = Fpga_MappingArea( p );
if ( p->fVerbose )
{
printf( "Iteration %dS : Area = %11.1f ", Iter++, aAreaTotalCur );
PRT( "Time", clock() - clk );
}
aSwitchTotalPrev = aSwitchTotalCur;
aSwitchTotalCur = Fpga_MappingPrintSwitching( p );
// quit if this iteration reduced area flow by less than 1%
} while ( aSwitchTotalPrev > 1.01 * aSwitchTotalCur );
}
/*
// compute the area of each cut
aAreaTotalCur = Fpga_MappingSetRefsAndArea( p );
// compute the required times and the fanouts
Fpga_TimeComputeRequiredGlobal( p );
// perform experiment
Fpga_Experiment( p );
*/
p->fAreaGlo = aAreaTotalCur;
return 1;
}
......
......@@ -58,10 +58,7 @@ void Fpga_ManSetTimeToNet( Fpga_Man_t * p, int Time ) { p->t
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_ManSetTree( Fpga_Man_t * p, int fTree ) { p->fTree = fTree; }
void Fpga_ManSetPower( Fpga_Man_t * p, int fPower ) { p->fPower = fPower; }
void Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery ) { p->fAreaRecovery = fAreaRecovery;}
void Fpga_ManSetResyn( Fpga_Man_t * p, int fResynthesis ) { p->fResynthesis = fResynthesis; }
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; }
......@@ -69,7 +66,6 @@ void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes ) { p
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_ManSetLatchNum( Fpga_Man_t * p, int nLatches ) { p->nLatches = nLatches; }
void Fpga_ManSetSequential( Fpga_Man_t * p, int fSequential ) { p->fSequential = fSequential; }
void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName ) { p->pFileName = pFileName; }
/**Function*************************************************************
......@@ -170,8 +166,6 @@ Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose )
p->nVarsMax = p->pLutLib->LutMax;
p->fVerbose = fVerbose;
p->fAreaRecovery = 1;
p->fTree = 0;
p->fRefCount = 1;
p->fEpsilon = (float)0.001;
Fpga_TableCreate( p );
......@@ -181,13 +175,14 @@ Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose )
p->mmCuts = Extra_MmFixedStart( sizeof(Fpga_Cut_t) );
assert( p->nVarsMax > 0 );
Fpga_MappingSetupTruthTables( p->uTruths );
// 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( 100 );
p->vNodesAll = Fpga_NodeVecAlloc( 1000 );
p->vMapping = Fpga_NodeVecAlloc( 1000 );
// create the PI nodes
p->nInputs = nInputs;
......@@ -216,27 +211,23 @@ Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose )
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, 0 );
Extra_MmFixedStop( p->mmCuts, 0 );
FREE( p->ppOutputNames );
FREE( p->pInputArrivals );
FREE( p->pInputs );
FREE( p->pOutputs );
FREE( p->pBins );
FREE( p->ppOutputNames );
if ( p->pSimInfo )
{
FREE( p->pSimInfo[0] );
FREE( p->pSimInfo );
}
FREE( p );
}
......@@ -316,19 +307,18 @@ Fpga_Node_t * Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p
// 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 (will be used to compute the number of fanouts)
if ( p->fRefCount )
{
if ( p1 ) Fpga_NodeRef(p1);
if ( p2 ) Fpga_NodeRef(p2);
}
// reference the inputs
if ( p1 ) Fpga_NodeRef(p1);
if ( p2 ) Fpga_NodeRef(p2);
return pNode;
}
......
......@@ -206,8 +206,9 @@ Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Nod
Fpga_Node_t * pTemp;
Fpga_Cut_t * pList, * pList1, * pList2;
Fpga_Cut_t * pCut;
int fPivot1 = p->fTree && (Fpga_NodeReadRef(pNode->p1)>2);
int fPivot2 = p->fTree && (Fpga_NodeReadRef(pNode->p2)>2);
int fTree = 0;
int fPivot1 = fTree && (Fpga_NodeReadRef(pNode->p1)>2);
int fPivot2 = fTree && (Fpga_NodeReadRef(pNode->p2)>2);
// if the cuts are computed return them
if ( pNode->pCuts )
......
......@@ -18,6 +18,8 @@
#include "fpgaInt.h"
#ifdef MAP_ALLOCATE_FANOUT
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
......@@ -26,7 +28,6 @@
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Add the fanout to the node.]
......@@ -136,4 +137,5 @@ int Fpga_NodeGetFanoutNum( Fpga_Node_t * pNode )
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
#endif
......@@ -35,6 +35,9 @@
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
// uncomment to have fanouts represented in the mapping graph
//#define FPGA_ALLOCATE_FANOUT 1
////////////////////////////////////////////////////////////////////////
/// MACRO DEFITIONS ///
////////////////////////////////////////////////////////////////////////
......@@ -104,10 +107,11 @@ struct Fpga_ManStruct_t_
Fpga_Node_t ** pOutputs; // the array of outputs
int nOutputs; // the number of outputs
int nNodes; // the total number of nodes
Fpga_Node_t * pConst1; // the constant 1 node
Fpga_NodeVec_t * vAnds; // the array of pointer to nodes by number
Fpga_NodeVec_t * vNodesAll; // the array of pointer to nodes by number
int nLatches; // the number of latches in the circuit
Fpga_Node_t * pConst1; // the constant 1 node
Fpga_NodeVec_t * vNodesAll; // the nodes by number
Fpga_NodeVec_t * vAnds; // the nodes reachable from COs
Fpga_NodeVec_t * vMapping; // the nodes used in the current mapping
// info about the original circuit
char * pFileName; // the file name
......@@ -116,12 +120,12 @@ struct Fpga_ManStruct_t_
// mapping parameters
int nVarsMax; // the max number of variables
int fTree; // the flag to enable tree mapping
int fPower; // the flag to enable power optimization
// int fTree; // the flag to enable tree mapping
// int fPower; // the flag to enable power optimization
int fAreaRecovery; // the flag to use area flow as the first parameter
int fVerbose; // the verbosiness flag
int fRefCount; // enables reference counting
int fSequential; // use sequential mapping
// int fRefCount; // enables reference counting
// int fSequential; // use sequential mapping
int nTravIds;
// support of choice nodes
......@@ -133,16 +137,12 @@ struct Fpga_ManStruct_t_
// the supergate library
Fpga_LutLib_t * pLutLib; // the current LUT library
unsigned uTruths[6][2]; // the elementary truth tables
// unsigned uTruths[6][2]; // the elementary truth tables
// the memory managers
Extra_MmFixed_t * mmNodes; // the memory manager for nodes
Extra_MmFixed_t * mmCuts; // the memory manager for cuts
// simulation info from the FRAIG manager
int nSimRounds; // the number of words in the simulation info
unsigned ** pSimInfo; // the simulation info for each PI
// resynthesis parameters
int fResynthesis; // the resynthesis flag
float fRequiredGlo; // the global required times
......@@ -203,12 +203,14 @@ struct Fpga_NodeStruct_t_
Fpga_Node_t * p2; // the second child
Fpga_Node_t * pNextE; // the next functionally equivalent node
Fpga_Node_t * pRepr; // the representative of the functionally equivalent class
// Fpga_NodeVec_t * vFanouts; // the array of fanouts of the node
#ifdef FPGA_ALLOCATE_FANOUT
// representation of node's fanouts
Fpga_Node_t * pFanPivot; // the first fanout of this node
Fpga_Node_t * pFanFanin1; // the next fanout of p1
Fpga_Node_t * pFanFanin2; // the next fanout of p2
// Fpga_NodeVec_t * vFanouts; // the array of fanouts of the gate
#endif
// the delay information
float tRequired; // the best area flow
......@@ -335,8 +337,6 @@ extern void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p );
extern void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired );
extern void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes );
extern void Fpga_TimePropagateArrival( Fpga_Man_t * p );
/*=== fpgaTruth.c ===============================================================*/
extern void Fpga_MappingTruths( Fpga_Man_t * pMan );
/*=== fpgaVec.c =============================================================*/
extern Fpga_NodeVec_t * Fpga_NodeVecAlloc( int nCap );
extern void Fpga_NodeVecFree( Fpga_NodeVec_t * p );
......@@ -359,23 +359,11 @@ extern void Fpga_NodeVecReverse( Fpga_NodeVec_t * vNodes );
/*=== fpgaUtils.c ===============================================================*/
extern Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv );
extern Fpga_NodeVec_t * Fpga_MappingDfsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes, int fEquiv );
extern Fpga_NodeVec_t * Fpga_MappingDfsCutsNode( Fpga_Man_t * pMan, Fpga_Node_t * pNode );
//extern Sat_IntVec_t * Fpga_MappingDfsNodesSat( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes );
extern Fpga_NodeVec_t * Fpga_MappingDfsCuts( Fpga_Man_t * pMan );
extern int Fpga_CountLevels( Fpga_Man_t * pMan );
extern int Fpga_CountLevelsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppRoots, int nRoots );
extern void Fpga_MappingMarkUsed( Fpga_Man_t * pMan );
extern float Fpga_MappingGetAreaFlow( Fpga_Man_t * p );
extern float Fpga_MappingArea( Fpga_Man_t * pMan );
extern float Fpga_MappingComputeCutAreas( Fpga_Man_t * pMan );
extern float Fpga_MappingAreaTrav( Fpga_Man_t * pMan );
extern float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan );
extern Fpga_NodeVec_t * Fpga_MappingCollectRefed( Fpga_Man_t * pMan );
extern int Fpga_MappingCountLevels( Fpga_Man_t * pMan );
extern void Fpga_MappingUnmark( Fpga_Man_t * pMan );
extern void Fpga_MappingUnmark_rec( Fpga_Node_t * pNode );
extern void Fpga_MappingMark_rec( Fpga_Node_t * pNode );
extern void Fpga_MappedMark_rec( Fpga_Node_t * pNode );
extern void Fpga_MappedUnmark_rec( Fpga_Node_t * pNode );
extern void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p );
extern void Fpga_MappingSetupTruthTables( unsigned uTruths[][2] );
extern void Fpga_MappingSetupMask( unsigned uMask[], int nVarsMax );
......@@ -383,7 +371,7 @@ extern void Fpga_MappingSortByLevel( Fpga_Man_t * pMan, Fpga_NodeVe
extern Fpga_NodeVec_t * Fpga_DfsLim( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int nLevels );
extern Fpga_NodeVec_t * Fpga_MappingLevelize( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes );
extern float Fpga_MappingPrintSwitching( Fpga_Man_t * pMan );
extern int Fpga_GetMaxLevel( Fpga_Man_t * pMan );
extern int Fpga_MappingMaxLevel( Fpga_Man_t * pMan );
extern void Fpga_ManReportChoices( Fpga_Man_t * pMan );
extern void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan );
......
......@@ -777,59 +777,6 @@ float Fpga_FindBestNode( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes, Fpga_Node_t **
return Gain;
}
/**function*************************************************************
synopsis [Performs area minimization using a heuristic algorithm.]
description []
sideeffects []
seealso []
***********************************************************************/
void Fpga_MappingExplore( Fpga_Man_t * p )
{
Fpga_Cut_t * pCutBest;
Fpga_Node_t * pNodeBest;
Fpga_NodeVec_t * vNodes;
float Area, Gain, CutArea1, CutArea2;
int i;
// compute the arrival times
Fpga_TimePropagateArrival( p );
p->fRequiredGlo = Fpga_TimeComputeArrivalMax( p );
Fpga_TimeComputeRequired( p, p->fRequiredGlo );
// assign the refs
Area = Fpga_MappingSetRefsAndArea( p );
// collect the nodes
vNodes = Fpga_MappingCollectRefed( p );
// find the best node to update
for ( i = 0; Gain = Fpga_FindBestNode(p, vNodes, &pNodeBest, &pCutBest); i++ )
{
// update the node
assert( pNodeBest->pCutBest != pCutBest );
// deref the current cut
CutArea1 = Fpga_CutDeref( p, pNodeBest, pNodeBest->pCutBest, 0 );
// ref the new cut
CutArea2 = Fpga_CutRef( p, pNodeBest, pCutBest, 0 );
assert( CutArea1 - CutArea2 == Gain );
printf( "Iteration %2d: Gain = %5.2f.\n", i, Gain );
// update the node
pNodeBest->pCutBest = pCutBest;
// collect new nodes
Fpga_NodeVecFree( vNodes );
vNodes = Fpga_MappingCollectRefed( p );
// compute the arrival and required times
Fpga_TimePropagateArrival( p );
Fpga_TimeComputeRequired( p, p->fRequiredGlo );
}
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -128,21 +128,15 @@ void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p )
***********************************************************************/
void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired )
{
Fpga_NodeVec_t * vNodes;
int i;
// clean the required times and the fanout counts for all nodes
for ( i = 0; i < p->vAnds->nSize; i++ )
p->vAnds->pArray[i]->tRequired = FPGA_FLOAT_LARGE;
// set the required times for the POs
for ( i = 0; i < p->nOutputs; i++ )
Fpga_Regular(p->pOutputs[i])->tRequired = fRequired;
// collect nodes reachable from POs in the DFS order through the best cuts
vNodes = Fpga_MappingDfsCuts( p );
Fpga_TimePropagateRequired( p, vNodes );
Fpga_NodeVecFree( vNodes );
Fpga_TimePropagateRequired( p, p->vMapping );
}
/**Function*************************************************************
......@@ -163,7 +157,9 @@ void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes )
int i, k;
// sorts the nodes in the decreasing order of levels
Fpga_MappingSortByLevel( p, vNodes, 0 );
// Fpga_MappingSortByLevel( p, vNodes, 0 );
// the nodes area already sorted in Fpga_MappingSetRefsAndArea()
// go through the nodes in the reverse topological order
for ( k = 0; k < vNodes->nSize; k++ )
{
......
......@@ -152,8 +152,8 @@ extern void Map_NodeSetChoice( Map_Man_t * pMan, Map_Node_t * pNodeOl
/*=== resmCanon.c =============================================================*/
extern int Map_CanonComputeSlow( unsigned uTruths[][2], int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] );
extern int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] );
/*=== mapperCut.c =============================================================*/
extern void Map_MappingCreatePiCuts( Map_Man_t * p );
extern Map_Cut_t * Map_CutAlloc( Map_Man_t * p );
/*=== mapperCutUtils.c =============================================================*/
extern void Map_CutCreateFromNode( Map_Man_t * p, Map_Super_t * pSuper, int iRoot, unsigned uPhaseRoot,
......
......@@ -154,6 +154,95 @@ void Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[]
}
}
/**Function*************************************************************
Synopsis [Computes the N-canonical form of the Boolean function.]
Description [The N-canonical form is defined as the truth table with
the minimum integer value. This function exhaustively enumerates
through the complete set of 2^N phase assignments.]
SideEffects []
SeeAlso []
***********************************************************************/
int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] )
{
unsigned uTruth0, uTruth1;
unsigned uCanon0, uCanon1, uCanonBest;
int i, Limit;
if ( nVarsMax != 5 || nVarsReal < 5 )
return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes );
assert( nVarsMax == 5 );
uTruth0 = uTruth[0] & 0xFFFF;
uTruth1 = (uTruth[0] >> 16);
if ( uTruth1 == 0 )
{
uTruthRes[0] = p->uCanons[uTruth0];
uTruthRes[1] = uTruthRes[0];
Limit = (p->pCounters[uTruth0] > 4)? 4 : p->pCounters[uTruth0];
for ( i = 0; i < Limit; i++ )
puPhases[i] = p->uPhases[uTruth0][i];
return Limit;
}
else if ( uTruth0 == 0 )
{
uTruthRes[0] = p->uCanons[uTruth1];
uTruthRes[1] = uTruthRes[0];
Limit = (p->pCounters[uTruth1] > 4)? 4 : p->pCounters[uTruth1];
for ( i = 0; i < Limit; i++ )
{
puPhases[i] = p->uPhases[uTruth1][i];
puPhases[i] |= (1 << 4);
}
return Limit;
}
uCanon0 = p->uCanons[uTruth0];
uCanon1 = p->uCanons[uTruth1];
if ( uCanon0 && uCanon1 && uCanon0 > uCanon1 ) // using nCanon1 as the main one
{
assert( p->pCounters[uTruth1] > 0 );
uCanonBest = 0xFFFF;
for ( i = 0; i < p->pCounters[uTruth1]; i++ )
{
uCanon0 = Extra_TruthPolarize( uTruth0, p->uPhases[uTruth1][i], 4 );
if ( uCanonBest > uCanon0 )
uCanonBest = uCanon0;
}
uTruthRes[0] = (uCanon1 << 16) | uCanonBest;
uTruthRes[1] = uTruthRes[0];
Limit = (p->pCounters[uTruth1] > 4)? 4 : p->pCounters[uTruth1];
for ( i = 0; i < Limit; i++ )
puPhases[i] = p->uPhases[uTruth1][i];
return Limit;
}
else if ( uCanon0 && uCanon1 && uCanon0 < uCanon1 )
{
assert( p->pCounters[uTruth0] > 0 );
uCanonBest = 0xFFFF;
for ( i = 0; i < p->pCounters[uTruth0]; i++ )
{
uCanon1 = Extra_TruthPolarize( uTruth1, p->uPhases[uTruth0][i], 4 );
if ( uCanonBest > uCanon1 )
uCanonBest = uCanon1;
}
uTruthRes[0] = (uCanon0 << 16) | uCanonBest;
uTruthRes[1] = uTruthRes[0];
Limit = (p->pCounters[uTruth0] > 4)? 4 : p->pCounters[uTruth0];
for ( i = 0; i < Limit; i++ )
{
puPhases[i] = p->uPhases[uTruth0][i];
puPhases[i] |= (1 << 4);
}
return Limit;
}
else
return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -69,6 +69,7 @@ int Map_Mapping( Map_Man_t * p )
Map_MappingTruths( p );
p->timeTruth = clock() - clk;
//////////////////////////////////////////////////////////////////////
//PRT( "Truths", clock() - clk );
//////////////////////////////////////////////////////////////////////
// compute the minimum-delay mapping
......
......@@ -196,6 +196,9 @@ Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose )
p->fEpsilon = (float)0.001;
assert( p->nVarsMax > 0 );
if ( p->nVarsMax == 5 )
Extra_Truth4VarN( &p->uCanons, &p->uPhases, &p->pCounters, 16 );
// start various data structures
Map_TableCreate( p );
Map_MappingSetupTruthTables( p->uTruths );
......@@ -211,8 +214,6 @@ Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose )
p->vNodesAll = Map_NodeVecAlloc( 100 );
p->vNodesTemp = Map_NodeVecAlloc( 100 );
p->vMapping = Map_NodeVecAlloc( 100 );
p->vInside = Map_NodeVecAlloc( 100 );
p->vFanins = Map_NodeVecAlloc( 100 );
p->vVisited = Map_NodeVecAlloc( 100 );
// create the PI nodes
......@@ -245,10 +246,6 @@ void Map_ManFree( Map_Man_t * p )
// for ( i = 0; i < p->vNodesAll->nSize; i++ )
// Map_NodeVecFree( p->vNodesAll->pArray[i]->vFanouts );
// Map_NodeVecFree( p->pConst1->vFanouts );
if ( p->vInside )
Map_NodeVecFree( p->vInside );
if ( p->vFanins )
Map_NodeVecFree( p->vFanins );
if ( p->vAnds )
Map_NodeVecFree( p->vAnds );
if ( p->vNodesAll )
......@@ -259,6 +256,9 @@ void Map_ManFree( Map_Man_t * p )
Map_NodeVecFree( p->vMapping );
if ( p->vVisited )
Map_NodeVecFree( p->vVisited );
if ( p->uCanons ) free( p->uCanons );
if ( p->uPhases ) free( p->uPhases );
if ( p->pCounters ) free( p->pCounters );
Extra_MmFixedStop( p->mmNodes, 0 );
Extra_MmFixedStop( p->mmCuts, 0 );
FREE( p->pInputArrivals );
......@@ -266,8 +266,6 @@ void Map_ManFree( Map_Man_t * p )
FREE( p->pOutputs );
FREE( p->pBins );
FREE( p->ppOutputNames );
if ( p->pSimInfo ) FREE( p->pSimInfo[0] );
FREE( p->pSimInfo );
FREE( p );
}
......@@ -357,9 +355,11 @@ Map_Node_t * Map_NodeCreate( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 )
// set the level of this node
if ( p1 )
{
#ifdef MAP_ALLOCATE_FANOUT
// create the fanout info
Map_NodeAddFaninFanout( Map_Regular(p1), pNode );
Map_NodeAddFaninFanout( Map_Regular(p2), pNode );
#endif
pNode->Level = 1 + MAP_MAX(Map_Regular(pNode->p1)->Level, Map_Regular(pNode->p2)->Level);
pNode->fInv = Map_NodeIsSimComplement(p1) & Map_NodeIsSimComplement(p2);
}
......
......@@ -18,6 +18,8 @@
#include "mapperInt.h"
#ifdef MAP_ALLOCATE_FANOUT
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
......@@ -26,7 +28,6 @@
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Add the fanout to the node.]
......@@ -136,4 +137,5 @@ int Map_NodeGetFanoutNum( Map_Node_t * pNode )
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
#endif
......@@ -36,7 +36,10 @@
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
// uncomment to have fanouts represented in the mapping graph
//#define MAP_ALLOCATE_FANOUT 1
////////////////////////////////////////////////////////////////////////
/// MACRO DEFITIONS ///
////////////////////////////////////////////////////////////////////////
......@@ -123,18 +126,15 @@ struct Map_ManStruct_t_
int nCountsBest[32];// the counter of minterms
Map_NodeVec_t * vVisited; // the visited cuts during cut computation
// simulation info from the FRAIG manager
int nSimRounds; // the number of words in the simulation info
unsigned ** pSimInfo; // the simulation info for each PI
// don't-care computation
Map_NodeVec_t * vInside; // the array of nodes for SDC computation
Map_NodeVec_t * vFanins; // the array of nodes for SDC computation
// the memory managers
Extra_MmFixed_t * mmNodes; // the memory manager for nodes
Extra_MmFixed_t * mmCuts; // the memory manager for cuts
// precomputed N-canonical forms
unsigned short * uCanons; // N-canonical forms
char ** uPhases; // N-canonical phases
char * pCounters; // counters of phases
// various statistical variables
int nChoiceNodes; // the number of choice nodes
int nChoices; // the number of all choices
......@@ -211,27 +211,25 @@ struct Map_NodeStruct_t_
int nRefAct[3]; // estimated fanout for current covering phase, neg and pos and sum
float nRefEst[3]; // actual fanout for previous covering phase, neg and pos and sum
// the successors of this node
// connectivity
Map_Node_t * p1; // the first child
Map_Node_t * p2; // the second child
Map_Node_t * pNextE; // the next functionally equivalent node
Map_Node_t * pRepr; // the representative of the functionally equivalent class
// Map_NodeVec_t * vFanouts; // the array of fanouts of the node
#ifdef MAP_ALLOCATE_FANOUT
// representation of node's fanouts
Map_Node_t * pFanPivot; // the first fanout of this node
Map_Node_t * pFanFanin1; // the next fanout of p1
Map_Node_t * pFanFanin2; // the next fanout of p2
unsigned * pSims; // the simulation info
float SwitchProb; // the switching probability
// Map_NodeVec_t * vFanouts; // the array of fanouts of the gate
#endif
// the delay information
Map_Time_t tArrival[2]; // the best arrival time of the neg (0) and pos (1) phases
Map_Time_t tRequired[2]; // the required time of the neg (0) and pos (1) phases
// misc information
Map_Cut_t * pCutOld[2]; // the old mapping for neg and pos phase
Map_Cut_t * pCutBest[2]; // the best mapping for neg and pos phase
Map_Cut_t * pCuts; // mapping choices for the node (elementary comes first)
char * pData0; // temporary storage for the corresponding network node
......@@ -259,6 +257,7 @@ struct Map_CutStruct_t_
Map_Cut_t * pOne; // the father of this cut
Map_Cut_t * pTwo; // the mother of this cut
Map_Node_t * ppLeaves[6]; // the leaves of this cut
unsigned uTruth; // truth table for five-input cuts
char nLeaves; // the number of leaves
char nVolume; // the volume of this cut
char fMark; // the mark to denote visited cut
......
......@@ -25,7 +25,7 @@
static int Map_NodeIncRefPhaseAct( Map_Node_t * pNode, int fPhase );
static int Map_NodeDecRefPhaseAct( Map_Node_t * pNode, int fPhase );
static float Map_CutRefDeref( Map_Cut_t * pCut, int fPhase, int fReference );
static void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode );
static void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_Node_t ** ppStore );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
......@@ -401,8 +401,9 @@ float Map_CutRefDeref( Map_Cut_t * pCut, int fPhase, int fReference )
Synopsis [Computes actual reference counters.]
Description [Stores all the nodes used in the mapping in the array pMan->vMapping.
The nodes are stored in the random order.]
Description [Collects the nodes used in the mapping in array pMan->vMapping.
Nodes are collected in reverse topological order to facilitate the
computation of required times.]
SideEffects []
......@@ -411,8 +412,9 @@ float Map_CutRefDeref( Map_Cut_t * pCut, int fPhase, int fReference )
***********************************************************************/
void Map_MappingSetRefs( Map_Man_t * pMan )
{
Map_Node_t * pNode;
int i, fPhase;
Map_Node_t * pNode, ** ppStore;
int i, fPhase, LevelMax;
// clean all references
for ( i = 0; i < pMan->vNodesAll->nSize; i++ )
{
......@@ -421,18 +423,32 @@ void Map_MappingSetRefs( Map_Man_t * pMan )
pNode->nRefAct[1] = 0;
pNode->nRefAct[2] = 0;
}
// find the largest level of a node
LevelMax = 0;
for ( i = 0; i < pMan->nOutputs; i++ )
if ( LevelMax < (int)Map_Regular(pMan->pOutputs[i])->Level )
LevelMax = Map_Regular(pMan->pOutputs[i])->Level;
// allocate place to store the nodes
ppStore = ALLOC( Map_Node_t *, LevelMax + 1 );
memset( ppStore, 0, sizeof(Map_Node_t *) * (LevelMax + 1) );
// visit nodes reachable from POs in the DFS order through the best cuts
pMan->vMapping->nSize = 0;
for ( i = 0; i < pMan->nOutputs; i++ )
{
pNode = pMan->pOutputs[i];
fPhase = !Map_IsComplement(pNode);
if ( !Map_NodeIsConst(pNode) )
Map_MappingSetRefs_rec( pMan, pNode );
// reference count the PO node
// Map_Regular(pNode)->nRefAct[fPhase]++;
// Map_Regular(pNode)->nRefAct[2]++;
Map_MappingSetRefs_rec( pMan, pNode, ppStore );
}
// reconnect the nodes in reverse topological order
pMan->vMapping->nSize = 0;
for ( i = LevelMax; i >= 0; i-- )
for ( pNode = ppStore[i]; pNode; pNode = (Map_Node_t *)pNode->pData0 )
Map_NodeVecPush( pMan->vMapping, pNode );
free( ppStore );
}
/**Function*************************************************************
......@@ -446,7 +462,7 @@ void Map_MappingSetRefs( Map_Man_t * pMan )
SeeAlso []
***********************************************************************/
void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode )
void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_Node_t ** ppStore )
{
Map_Cut_t * pCut;
Map_Node_t * pNodeR;
......@@ -459,7 +475,8 @@ void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode )
// add the node to the list of all visited nodes
if ( pNodeR->nRefAct[2]++ == 0 )
Map_NodeVecPush( pMan->vMapping, pNodeR );
// Map_NodeVecPush( pMan->vMapping, pNodeR );
pNodeR->pData0 = (char *)ppStore[pNodeR->Level], ppStore[pNodeR->Level] = pNodeR;
// quit if the node was already visited in this phase
if ( pNodeR->nRefAct[fPhase]++ )
......@@ -482,7 +499,7 @@ void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode )
for ( i = 0; i < pCut->nLeaves; i++ )
{
fInvPin = ((uPhase & (1 << i)) > 0);
Map_MappingSetRefs_rec( pMan, Map_NotCond(pCut->ppLeaves[i], fInvPin) );
Map_MappingSetRefs_rec( pMan, Map_NotCond(pCut->ppLeaves[i], fInvPin), ppStore );
}
}
......
......@@ -252,7 +252,9 @@ void Map_TimeComputeRequired( Map_Man_t * p, float fRequired )
// sorts the nodes in the decreasing order of levels
// this puts the nodes in reverse topological order
Map_MappingSortByLevel( p, p->vMapping );
// Map_MappingSortByLevel( p, p->vMapping );
// the array is already sorted by construction in Map_MappingSetRefs()
Map_TimePropagateRequired( p, p->vMapping );
}
......
......@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
static void Map_TruthsCut( Map_Man_t * pMan, Map_Cut_t * pCut );
static void Map_TruthsCutOne( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[] );
extern void Map_TruthsCutOne( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[] );
static void Map_CutsCollect_rec( Map_Cut_t * pCut, Map_NodeVec_t * vVisited );
////////////////////////////////////////////////////////////////////////
......@@ -90,18 +90,30 @@ void Map_MappingTruths( Map_Man_t * pMan )
***********************************************************************/
void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut )
{
unsigned uTruth[2], uCanon[2];
// unsigned uCanon1, uCanon2;
unsigned uTruth[2], uCanon[2];
unsigned char uPhases[16];
int fUseFast = 1;
// generally speaking, 1-input cut can be matched into a wire!
if ( pCut->nLeaves == 1 )
return;
/*
if ( p->nVarsMax == 5 )
{
uTruth[0] = pCut->uTruth;
uTruth[1] = pCut->uTruth;
}
else
*/
Map_TruthsCutOne( p, pCut, uTruth );
// compute the canonical form for the positive phase
Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
if ( fUseFast )
Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
else
Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
pCut->M[1].uPhase = uPhases[0];
p->nCanons++;
......@@ -111,13 +123,15 @@ void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut )
// compute the canonical form for the negative phase
uTruth[0] = ~uTruth[0];
uTruth[1] = ~uTruth[1];
Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
if ( fUseFast )
Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
else
Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
pCut->M[0].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
pCut->M[0].uPhase = uPhases[0];
p->nCanons++;
//uCanon2 = uCanon[0] & 0xFFFF;
//assert( p->nVarsMax == 4 );
//Rwt_Man4ExploreCount( uCanon1 < uCanon2 ? uCanon1 : uCanon2 );
......
......@@ -405,7 +405,7 @@ void Map_MappingPrintOutputArrivals( Map_Man_t * p )
Map_Time_t * pTimes;
Map_Node_t * pNode;
int fPhase, Limit, i;
int nOutputs;
int nOutputs, MaxNameSize;
int * pSorted;
// sort outputs by arrival time
......@@ -423,16 +423,22 @@ void Map_MappingPrintOutputArrivals( Map_Man_t * p )
assert( Map_MappingCompareOutputDelay( pSorted, pSorted + nOutputs - 1 ) <= 0 );
s_pMan = NULL;
// print the latest outputs
// determine max size of the node's name
MaxNameSize = 0;
Limit = (nOutputs > 5)? 5 : nOutputs;
for ( i = 0; i < Limit; i++ )
if ( MaxNameSize < (int)strlen(p->ppOutputNames[pSorted[i]]) )
MaxNameSize = strlen(p->ppOutputNames[pSorted[i]]);
// print the latest outputs
for ( i = 0; i < Limit; i++ )
{
// get the i-th latest output
pNode = Map_Regular(p->pOutputs[pSorted[i]]);
fPhase =!Map_IsComplement(p->pOutputs[pSorted[i]]);
pTimes = pNode->tArrival + fPhase;
// print out the best arrival time
printf( "Out %20s : ", p->ppOutputNames[pSorted[i]] );
printf( "Output %-*s : ", MaxNameSize + 3, p->ppOutputNames[pSorted[i]] );
printf( "Delay = (%5.2f, %5.2f) ", (double)pTimes->Rise, (double)pTimes->Fall );
printf( "%s", fPhase? "POS" : "NEG" );
printf( "\n" );
......@@ -1013,136 +1019,6 @@ void Map_MappingReportChoices( Map_Man_t * pMan )
printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices );
}
/*
void Map_MappingReportChoices( Map_Man_t * pMan )
{
Map_Node_t * pNode, * pTemp;
int nChoiceNodes, nChoices;
int i, LevelMax1, LevelMax2;
int DiffMaxTotal, DiffMinTotal, Min, Max;
int CounterByMin[300]={0}, CounterByMax[300]={0};
// report the number of levels
LevelMax1 = Map_MappingGetMaxLevel( pMan );
pMan->nTravIds++;
for ( i = 0; i < pMan->nOutputs; i++ )
// Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 0 );
Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 1 );
LevelMax2 = Map_MappingGetMaxLevel( pMan );
// report statistics about choices
nChoiceNodes = nChoices = 0;
DiffMaxTotal = DiffMinTotal = 0;
for ( i = 0; i < pMan->vAnds->nSize; i++ )
{
pNode = pMan->vAnds->pArray[i];
if ( pNode->pRepr == NULL && pNode->pNextE != NULL )
{ // this is a choice node = the primary node that has equivalent nodes
nChoiceNodes++;
for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE )
nChoices++;
// call to compare the levels
Map_MappingGetChoiceLevels( pMan, pNode, pNode->pNextE, &Min, &Max );
assert( Min < (int)pNode->Level );
assert( Max < (int)pNode->Level );
DiffMinTotal += pNode->Level - Max;
DiffMaxTotal += pNode->Level - Min;
CounterByMin[pNode->Level - Max]++;
CounterByMax[pNode->Level - Min]++;
}
}
printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 );
printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices );
printf( "Choice depth: Minimum = %4.2f. Maximum = %4.2f.\n",
((float)DiffMinTotal)/nChoiceNodes, ((float)DiffMaxTotal)/nChoiceNodes );
{
FILE * pTable;
pTable = fopen( "statsc.txt", "a+" );
fprintf( pTable, "%6d ", pMan->vAnds->nSize );
fprintf( pTable, "%5d ", LevelMax2 );
fprintf( pTable, "%5d ", nChoiceNodes );
fprintf( pTable, "%5d ", nChoices );
fprintf( pTable, "%5.2f ", ((float)DiffMinTotal)/nChoiceNodes );
fprintf( pTable, "%5.2f ", ((float)DiffMaxTotal)/nChoiceNodes );
// fprintf( pTable, "%4.2f\n", (float)(Time)/(float)(CLOCKS_PER_SEC) );
fprintf( pTable, "\n" );
fclose( pTable );
}
printf( "Distribution by min/max levels:\n" );
for ( i = 0; i < LevelMax2; i++ )
printf( "%3d : %5d %5d\n", i, CounterByMin[i], CounterByMax[i] );
printf( "\n" );
}
*/
/*
void Map_MappingReportChoices( Map_Man_t * pMan )
{
Map_Node_t * pNode, * pTemp;
int nChoiceNodes, nChoices;
int i, LevelMax1, LevelMax2;
int CounterByVol[1000]={0};
float VolumeAve, Volume;
// report the number of levels
LevelMax1 = Map_MappingGetMaxLevel( pMan );
pMan->nTravIds++;
for ( i = 0; i < pMan->nOutputs; i++ )
Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 0 );
// Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 1 );
LevelMax2 = Map_MappingGetMaxLevel( pMan );
// report statistics about choices
nChoiceNodes = nChoices = 0;
VolumeAve = 0.0;
for ( i = 0; i < pMan->vAnds->nSize; i++ )
{
pNode = pMan->vAnds->pArray[i];
if ( pNode->pRepr == NULL && pNode->pNextE != NULL )
{ // this is a choice node = the primary node that has equivalent nodes
nChoiceNodes++;
for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE )
nChoices++;
Volume = Map_MappingGetChoiceVolumes( pMan, pNode, pNode->pNextE );
VolumeAve += Volume;
assert( Volume < 1000 );
CounterByVol[(int)Volume]++;
}
}
printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 );
printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices );
printf( "Average volume = %5.4f.\n", VolumeAve/nChoiceNodes );
*/
/*
{
FILE * pTable;
pTable = fopen( "statsv.txt", "a+" );
fprintf( pTable, "%6d ", Map_MappingCountUsedNodes(pMan,1) );
fprintf( pTable, "%6d ", Map_MappingCountUsedNodes(pMan,0) );
fprintf( pTable, "%5d ", LevelMax1 );
fprintf( pTable, " " );
fprintf( pTable, "%5d ", nChoiceNodes );
fprintf( pTable, "%5d ", nChoices );
fprintf( pTable, " " );
fprintf( pTable, "%5.4f ", VolumeAve/nChoiceNodes );
fprintf( pTable, "\n" );
fclose( pTable );
}
printf( "Distribution by volume:\n" );
for ( i = 0; i < 1000; i++ )
if ( CounterByVol[i] > 0 )
printf( "%3d : %5d\n", i, CounterByVol[i] );
printf( "\n" );
*/
/*
}
*/
/**Function*************************************************************
Synopsis [Computes the maximum and minimum levels of the choice nodes.]
......
......@@ -89,6 +89,10 @@
(((((((unsigned)(a) + (unsigned)(b)) * DD_P1 + (unsigned)(c)) * DD_P2 + \
(unsigned)(d)) * DD_P3 + (unsigned)(e)) * DD_P1) % TSIZE)
#ifndef PRT
#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))
#endif
/*===========================================================================*/
/* Various Utilities */
/*===========================================================================*/
......@@ -209,7 +213,13 @@ extern unsigned Extra_TruthCanonP( unsigned uTruth, int nVars );
extern unsigned Extra_TruthCanonNP( unsigned uTruth, int nVars );
extern unsigned Extra_TruthCanonNPN( unsigned uTruth, int nVars );
/* canonical forms of 4-variable functions */
extern void Extra_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms );
extern void Extra_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap );
extern void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int nPhasesMax );
/* permutation mapping */
extern void ** Extra_ArrayAlloc( int nCols, int nRows, int Size );
extern unsigned short ** Extra_TruthPerm43();
extern unsigned ** Extra_TruthPerm53();
extern unsigned ** Extra_TruthPerm54();
/* for independence from CUDD */
extern unsigned int Cudd_PrimeCopy( unsigned int p );
......
......@@ -44,17 +44,19 @@ typedef struct Rwr_Cut_t_ Rwr_Cut_t;
struct Rwr_Man_t_
{
// internal lookups
int nFuncs; // the number of four var functions
int nFuncs; // number of four var functions
unsigned short * puCanons; // canonical forms
char * pPhases; // canonical phases
char * pPerms; // canonical permutations
unsigned char * pMap; // mapping of functions into class numbers
char * pPractical; // practical classes
unsigned short puPerms[256][16]; // permutations for three var functions
char * pPractical; // practical NPN classes
unsigned short ** puPerms43; // four-var permutations for three var functions
// node space
Vec_Ptr_t * vForest; // all the nodes
Rwr_Node_t ** pTable; // the hash table of nodes by their canonical form
Vec_Vec_t * vClasses; // the nodes of the equivalence classes
Extra_MmFixed_t * pMmNode; // memory for nodes and cuts
// statistical variables
int nTravIds; // the counter of traversal IDs
int nConsidered; // the number of nodes considered
int nAdded; // the number of nodes added to lists
......@@ -64,10 +66,8 @@ struct Rwr_Man_t_
Vec_Int_t * vReqTimes; // the required times for each node (used for delay-driven evalution)
// the result of resynthesis
Vec_Int_t * vForm; // the decomposition tree (temporary)
Vec_Int_t * vLevNums; // the array of levels (temporary)
Vec_Ptr_t * vFanins; // the fanins array (temporary)
Vec_Ptr_t * vTfo; // the TFO node array (temporary)
Vec_Ptr_t * vTfoFor; // the TFO node array (temporary)
Vec_Vec_t * vLevels; // the levelized structure (temporary)
int nGainMax;
// runtime statistics
int time1;
......@@ -82,8 +82,7 @@ struct Rwr_Node_t_ // 24 bytes
int TravId; // traversal ID
unsigned uTruth : 16; // truth table
unsigned Volume : 8; // volume
unsigned Level : 5; // level
unsigned fMark : 1; // mark
unsigned Level : 6; // level
unsigned fUsed : 1; // mark
unsigned fExor : 1; // mark
Rwr_Node_t * p0; // first child
......@@ -122,22 +121,29 @@ extern void Rwr_NtkStartCuts( Rwr_Man_t * p, Abc_Ntk_t * pNtk );
extern void Rwr_NodeComputeCuts( Rwr_Man_t * p, Abc_Obj_t * pNode );
/*=== rwrEva.c ========================================================*/
extern int Rwr_NodeRewrite( Rwr_Man_t * p, Abc_Obj_t * pNode );
extern void Rwr_ManPreprocess( Rwr_Man_t * p );
/*=== rwrLib.c ========================================================*/
extern void Rwr_ManPrecompute( Rwr_Man_t * p );
extern void Rwr_ManWriteToFile( Rwr_Man_t * p, char * pFileName );
extern void Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName );
extern void Rwr_ManPrintFirst( Rwr_Man_t * p );
extern void Rwr_ManPrintNext( Rwr_Man_t * p );
extern Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, char * pFileName );
extern Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute );
extern Rwr_Node_t * Rwr_ManAddNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume );
extern int Rwr_ManNodeVolume( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1 );
extern void Rwr_ManIncTravId( Rwr_Man_t * p );
/*=== rwrMan.c ========================================================*/
extern Rwr_Man_t * Rwr_ManStart( char * pFileName );
extern Rwr_Man_t * Rwr_ManStart( bool fPrecompute );
extern void Rwr_ManStop( Rwr_Man_t * p );
extern void Rwr_ManPrepareNetwork( Rwr_Man_t * p, Abc_Ntk_t * pNtk );
extern Vec_Ptr_t * Rwr_ManReadFanins( Rwr_Man_t * p );
extern Vec_Int_t * Rwr_ManReadDecs( Rwr_Man_t * p );
extern unsigned short Rwr_FunctionPhase( unsigned uTruth, unsigned uPhase );
/*=== rwrPrint.c ========================================================*/
extern void Rwr_ManPrint( Rwr_Man_t * p );
/*=== rwrUtil.c ========================================================*/
extern void Rwr_ManWriteToArray( Rwr_Man_t * p );
extern void Rwr_ManLoadFromArray( Rwr_Man_t * p );
extern void Rwr_ManWriteToFile( Rwr_Man_t * p, char * pFileName );
extern void Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName );
extern Vec_Int_t * Rwt_NtkFanoutCounters( Abc_Ntk_t * pNtk );
extern void Rwr_ListAddToTail( Rwr_Node_t ** ppList, Rwr_Node_t * pNode );
extern char * Rwr_ManGetPractical( Rwr_Man_t * p );
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
......
......@@ -174,7 +174,7 @@ Rwr_Cut_t * Rwr_CutsMerge( Rwr_Man_t * p, Rwr_Cut_t * pCut0, Rwr_Cut_t * pCut1,
}
assert( uPhase < 16 );
assert( pCut0->uTruth < 256 );
uTruth0 = p->puPerms[pCut0->uTruth][uPhase];
uTruth0 = p->puPerms43[pCut0->uTruth][uPhase];
}
// find the mapping from the old nodes to the new
......@@ -192,7 +192,7 @@ Rwr_Cut_t * Rwr_CutsMerge( Rwr_Man_t * p, Rwr_Cut_t * pCut0, Rwr_Cut_t * pCut1,
}
assert( uPhase < 16 );
assert( pCut1->uTruth < 256 );
uTruth1 = p->puPerms[pCut1->uTruth][uPhase];
uTruth1 = p->puPerms43[pCut1->uTruth][uPhase];
}
// create the cut
......
......@@ -19,13 +19,13 @@
***********************************************************************/
#include "rwr.h"
#include "ft.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static void Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pNode, Rwr_Cut_t * pCut );
static void Rwr_CutDecompose( Rwr_Man_t * p, Abc_Obj_t * pNode, Rwr_Cut_t * pCut, Vec_Int_t * vForm );
static Vec_Int_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Rwr_Cut_t * pCut, int NodeMax, int LevelMax );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
......@@ -51,43 +51,34 @@ static void Rwr_CutDecompose( Rwr_Man_t * p, Abc_Obj_t * pNode, Rwr_Cut_t * pCut
***********************************************************************/
int Rwr_NodeRewrite( Rwr_Man_t * p, Abc_Obj_t * pNode )
{
Vec_Ptr_t Vector = {0,0,0}, * vFanins = &Vector;
Rwr_Cut_t * pCut, * pCutBest;
int BestGain = -1;
int i, Required = Vec_IntEntry( p->vReqTimes, pNode->Id );
// compute the cuts of the node
Vec_Int_t * vForm;
Rwr_Cut_t * pCut;
int Required, nNodesSaved;
int i, BestGain = -1;
// compute the cuts for this node
Rwr_NodeComputeCuts( p, pNode );
// get the required times
Required = Vec_IntEntry( p->vReqTimes, pNode->Id );
// label MFFC with current ID
nNodesSaved = Abc_NodeMffcLabel( pNode );
// go through the cuts
for ( pCut = (Rwr_Cut_t *)pNode->pCopy, pCut = pCut->pNext; pCut; pCut = pCut->pNext )
{
// collect the TFO
vFanins->nSize = pCut->nLeaves;
vFanins->pArray = pCut->ppLeaves;
Abc_NodeCollectTfoCands( pNode->pNtk, pNode, vFanins, Required, p->vLevels, p->vTfo );
// evaluate the cut
Rwr_CutEvaluate( p, pNode, pCut );
// check if the cut is the best
if ( pCut->fTime && pCut->fGain )
vForm = Rwr_CutEvaluate( p, pNode, pCut, nNodesSaved, Required );
// check if the cut is better than the currently best one
if ( vForm != NULL && BestGain < (int)pCut->Volume )
{
pCutBest = pCut;
BestGain = pCut->Volume;
assert( pCut->Volume >= 0 );
BestGain = pCut->Volume;
// save this form
p->vForm = vForm;
// collect fanins
Vec_PtrClear( p->vFanins );
for ( i = 0; i < (int)pCut->nLeaves; i++ )
Vec_PtrPush( p->vFanins, pCut->ppLeaves[i] );
}
}
if ( BestGain == -1 )
return -1;
// we found a good cut
// prepare the fanins
Vec_PtrClear( p->vFanins );
for ( i = 0; i < (int)pCutBest->nLeaves; i++ )
Vec_PtrPush( p->vFanins, pCutBest->ppLeaves[i] );
// collect the TFO again
Abc_NodeCollectTfoCands( pNode->pNtk, pNode, p->vFanins, Required, p->vLevels, p->vTfo );
// perform the decomposition
Rwr_CutDecompose( p, pNode, pCutBest, p->vForm );
// the best fanins are in p->vFanins, the result of decomposition is in p->vForm
return BestGain;
}
......@@ -102,46 +93,113 @@ int Rwr_NodeRewrite( Rwr_Man_t * p, Abc_Obj_t * pNode )
SeeAlso []
***********************************************************************/
void Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Rwr_Cut_t * pCut )
Vec_Int_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Rwr_Cut_t * pCut, int NodeMax, int LevelMax )
{
Abc_Obj_t * pNode, * pFanin0, * pFanin1;
Rwr_Node_t * pNodeFor;
int i;
// mark forest PIs corresponding to cut leaves
Vec_PtrClear( p->vTfoFor );
for ( i = 0; i < (int)pCut->nLeaves; i++ )
Vec_Ptr_t Vector = {0,0,0}, * vFanins = &Vector;
Vec_Ptr_t * vSubgraphs;
Vec_Int_t * vFormBest;
Rwr_Node_t * pNode;
int GainCur, GainBest = -1, i;
// find the matching class of subgraphs
vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[pCut->uTruth] );
// determine the best subgraph
Vec_PtrForEachEntry( vSubgraphs, pNode, i )
{
pNodeFor = p->vForest->pArray[i];
Vec_PtrPush( p->vTfoFor, pNodeFor );
pCut->ppLeaves[i]->pData = pNodeFor;
pNodeFor->fMark = 1;
// create the fanin array
vFanins->nSize = pCut->nLeaves;
vFanins->pArray = pCut->ppLeaves;
// detect how many unlabeled nodes will be reused
GainCur = Abc_NodeStrashDecCount( pRoot->pNtk->pManFunc, vFanins, (Vec_Int_t *)pNode->pNext,
p->vLevNums, NodeMax, LevelMax );
if ( GainBest < GainCur )
{
GainBest = GainCur;
vFormBest = (Vec_Int_t *)pNode->pNext;
}
}
// detect forest nodes corresponding to TFO
Vec_PtrForEachEntry( p->vTfo, pNode, i )
{
pFanin0 = Abc_ObjFanin0(pNode);
if ( pFanin0->pData == NULL )
continue;
pFanin1 = Abc_ObjFanin1(pNode);
if ( pFanin1->pData == NULL )
continue;
if ( GainBest == -1 )
return NULL;
pCut->Volume = GainBest;
return vFormBest;
}
}
// find the best implementation of the root
/**Function*************************************************************
Synopsis [Adds one node.]
// assign costs
Description []
SideEffects []
SeeAlso []
// clean the nodes
for ( i = 0; i < (int)pCut->nLeaves; i++ )
pCut->ppLeaves[i]->pData = NULL;
Vec_PtrForEachEntry( p->vTfo, pNode, i )
pNode->pData = NULL;
***********************************************************************/
int Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Vec_Int_t * vForm )
{
Ft_Node_t Node, NodeA, NodeB;
int Node0, Node1;
// elementary variable
if ( pNode->fUsed )
return ((pNode->Id - 1) << 1);
// previously visited node
if ( pNode->TravId == p->nTravIds )
return pNode->Volume;
pNode->TravId = p->nTravIds;
// solve for children
Node0 = Rwr_TravCollect_rec( p, Rwr_Regular(pNode->p0), vForm );
Node1 = Rwr_TravCollect_rec( p, Rwr_Regular(pNode->p1), vForm );
// create the decomposition node(s)
if ( pNode->fExor )
{
assert( !Rwr_IsComplement(pNode->p0) );
assert( !Rwr_IsComplement(pNode->p1) );
NodeA.fIntern = 1;
NodeA.fConst = 0;
NodeA.fCompl = 0;
NodeA.fCompl0 = !(Node0 & 1);
NodeA.fCompl1 = (Node1 & 1);
NodeA.iFanin0 = (Node0 >> 1);
NodeA.iFanin1 = (Node1 >> 1);
Vec_IntPush( vForm, Ft_Node2Int(NodeA) );
NodeB.fIntern = 1;
NodeB.fConst = 0;
NodeB.fCompl = 0;
NodeB.fCompl0 = (Node0 & 1);
NodeB.fCompl1 = !(Node1 & 1);
NodeB.iFanin0 = (Node0 >> 1);
NodeB.iFanin1 = (Node1 >> 1);
Vec_IntPush( vForm, Ft_Node2Int(NodeB) );
Node.fIntern = 1;
Node.fConst = 0;
Node.fCompl = 0;
Node.fCompl0 = 1;
Node.fCompl1 = 1;
Node.iFanin0 = vForm->nSize - 2;
Node.iFanin1 = vForm->nSize - 1;
Vec_IntPush( vForm, Ft_Node2Int(Node) );
}
else
{
Node.fIntern = 1;
Node.fConst = 0;
Node.fCompl = 0;
Node.fCompl0 = Rwr_IsComplement(pNode->p0) ^ (Node0 & 1);
Node.fCompl1 = Rwr_IsComplement(pNode->p1) ^ (Node1 & 1);
Node.iFanin0 = (Node0 >> 1);
Node.iFanin1 = (Node1 >> 1);
Vec_IntPush( vForm, Ft_Node2Int(Node) );
}
// save the number of this node
pNode->Volume = ((vForm->nSize - 1) << 1) | pNode->fExor;
return pNode->Volume;
}
/**Function*************************************************************
Synopsis [Decomposes the cut.]
Synopsis [Preprocesses subgraphs rooted at this node.]
Description []
......@@ -150,11 +208,45 @@ void Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Rwr_Cut_t * pCut )
SeeAlso []
***********************************************************************/
void Rwr_CutDecompose( Rwr_Man_t * p, Abc_Obj_t * pRoot, Rwr_Cut_t * pCut, Vec_Int_t * vForm )
void Rwr_NodePreprocess( Rwr_Man_t * p, Rwr_Node_t * pNode )
{
Vec_Int_t * vForm;
int i, Root;
vForm = Vec_IntAlloc( 10 );
for ( i = 0; i < 5; i++ )
Vec_IntPush( vForm, 0 );
// collect the nodes
Rwr_ManIncTravId( p );
Root = Rwr_TravCollect_rec( p, pNode, vForm );
if ( Root & 1 )
Ft_FactorComplement( vForm );
pNode->pNext = (Rwr_Node_t *)vForm;
}
/**Function*************************************************************
Synopsis [Preprocesses computed library of subgraphs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_ManPreprocess( Rwr_Man_t * p )
{
Rwr_Node_t * pNode;
int i, k;
// put the nodes into the structure
p->vClasses = Vec_VecAlloc( 222 );
for ( i = 0; i < p->nFuncs; i++ )
for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext )
Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode );
// compute decomposition forms for each node
Vec_VecForEachEntry( p->vClasses, pNode, i, k )
Rwr_NodePreprocess( p, pNode );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
......
......@@ -69,7 +69,7 @@ void Rwt_Man4ExploreStart()
// canonical forms
p->nFuncs = (1<<16);
// canonical forms, phases, perms
Extra_Truth4VarNPN( &p->puCanons, NULL, NULL );
Extra_Truth4VarNPN( &p->puCanons, NULL, NULL, NULL );
// counters
p->pnCounts = ALLOC( int, p->nFuncs );
memset( p->pnCounts, 0, sizeof(int) * p->nFuncs );
......
......@@ -24,34 +24,13 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// the following practical NPN classes of 4-variable functions were computed
// by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks
#define RWR_NUM_CLASSES 135
static int s_PracticalClasses[RWR_NUM_CLASSES] = {
0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b,
0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff,
0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c,
0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183,
0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab,
0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe,
0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368,
0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5,
0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669,
0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2,
0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8,
0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4,
0x1ee1, 0x3cc3, 0x6996
};
static unsigned short Rwr_FunctionPerm( unsigned uTruth, int Phase );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Starts the resynthesis manager.]
Synopsis [Starts rewriting manager.]
Description []
......@@ -60,85 +39,56 @@ static unsigned short Rwr_FunctionPerm( unsigned uTruth, int Phase );
SeeAlso []
***********************************************************************/
Rwr_Man_t * Rwr_ManStart( char * pFileName )
Rwr_Man_t * Rwr_ManStart( bool fPrecompute )
{
Rwr_Man_t * p;
int i, k, nClasses;
int clk = clock();
int TableSize;
p = ALLOC( Rwr_Man_t, 1 );
memset( p, 0, sizeof(Rwr_Man_t) );
p->nFuncs = (1<<16);
// create the table
TableSize = pFileName? 222: (1<<16);
p->pTable = ALLOC( Rwr_Node_t *, TableSize );
memset( p->pTable, 0, sizeof(Rwr_Node_t *) * TableSize );
p->nFuncs = (1<<16);
// canonical forms, phases, perms
Extra_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms );
// initialize practical classes
p->pPractical = ALLOC( char, p->nFuncs );
memset( p->pPractical, 0, sizeof(char) * p->nFuncs );
for ( i = 0; i < RWR_NUM_CLASSES; i++ )
p->pPractical[ s_PracticalClasses[i] ] = 1;
// set the mapping of classes
nClasses = 0;
p->pMap = ALLOC( unsigned char, p->nFuncs );
for ( i = 0; i < p->nFuncs; i++ )
{
if ( i != p->puCanons[i] )
{
assert( i > p->puCanons[i] );
p->pMap[i] = p->pMap[p->puCanons[i]];
continue;
}
p->pMap[i] = nClasses++;
}
printf( "The number of NPN-canonical forms = %d.\n", nClasses );
// initialize permutations
for ( i = 0; i < 256; i++ )
for ( k = 0; k < 16; k++ )
p->puPerms[i][k] = Rwr_FunctionPerm( i, k );
// other stuff
p->nTravIds = 1;
p->vForest = Vec_PtrAlloc( 100 );
p->vForm = Vec_IntAlloc( 50 );
p->vFanins = Vec_PtrAlloc( 50 );
p->vTfo = Vec_PtrAlloc( 50 );
p->vTfoFor = Vec_PtrAlloc( 50 );
p->vLevels = Vec_VecAlloc( 50 );
p->pMmNode = Extra_MmFixedStart( sizeof(Rwr_Node_t) );
clk = clock();
Extra_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms, &p->pMap );
PRT( "NPN classes precomputation time", clock() - clk );
// initialize practical NPN classes
p->pPractical = Rwr_ManGetPractical( p );
// create the table
p->pTable = ALLOC( Rwr_Node_t *, p->nFuncs );
memset( p->pTable, 0, sizeof(Rwr_Node_t *) * p->nFuncs );
// create the elementary nodes
assert( sizeof(Rwr_Node_t) == sizeof(Rwr_Cut_t) );
// initialize forest
Rwr_ManAddVar( p, 0x0000, pFileName ); // constant 0
Rwr_ManAddVar( p, 0xAAAA, pFileName ); // var A
Rwr_ManAddVar( p, 0xCCCC, pFileName ); // var B
Rwr_ManAddVar( p, 0xF0F0, pFileName ); // var C
Rwr_ManAddVar( p, 0xFF00, pFileName ); // var D
p->pMmNode = Extra_MmFixedStart( sizeof(Rwr_Node_t) );
p->vForest = Vec_PtrAlloc( 100 );
Rwr_ManAddVar( p, 0x0000, fPrecompute ); // constant 0
Rwr_ManAddVar( p, 0xAAAA, fPrecompute ); // var A
Rwr_ManAddVar( p, 0xCCCC, fPrecompute ); // var B
Rwr_ManAddVar( p, 0xF0F0, fPrecompute ); // var C
Rwr_ManAddVar( p, 0xFF00, fPrecompute ); // var D
p->nClasses = 5;
PRT( "Manager startup time", clock() - clk );
// create the nodes
if ( pFileName == NULL )
{ // precompute
// other stuff
p->nTravIds = 1;
p->puPerms43 = Extra_TruthPerm43();
p->vLevNums = Vec_IntAlloc( 50 );
p->vFanins = Vec_PtrAlloc( 50 );
if ( fPrecompute )
{ // precompute subgraphs
Rwr_ManPrecompute( p );
Rwr_ManWriteToFile( p, "data.aaa" );
Rwr_ManPrintFirst( p );
Rwr_ManWriteToArray( p );
Rwr_ManPrint( p );
}
else
{ // load previously saved nodes
Rwr_ManLoadFromFile( p, pFileName );
Rwr_ManPrintNext( p );
{ // load saved subgraphs
Rwr_ManLoadFromArray( p );
// Rwr_ManPrint( p );
Rwr_ManPreprocess( p );
return NULL;
}
return p;
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Synopsis [Stops rewriting manager.]
Description []
......@@ -149,21 +99,27 @@ PRT( "Manager startup time", clock() - clk );
***********************************************************************/
void Rwr_ManStop( Rwr_Man_t * p )
{
if ( p->vClasses )
{
Rwr_Node_t * pNode;
int i, k;
Vec_VecForEachEntry( p->vClasses, pNode, i, k )
Vec_IntFree( (Vec_Int_t *)pNode->pNext );
}
if ( p->vFanNums ) Vec_IntFree( p->vFanNums );
if ( p->vReqTimes ) Vec_IntFree( p->vReqTimes );
Vec_IntFree( p->vForm );
Vec_PtrFree( p->vFanins );
Vec_PtrFree( p->vTfoFor );
Vec_PtrFree( p->vTfo );
Vec_VecFree( p->vLevels );
if ( p->vClasses ) Vec_VecFree( p->vClasses );
Vec_PtrFree( p->vForest );
Extra_MmFixedStop( p->pMmNode, 0 );
Vec_IntFree( p->vLevNums );
Vec_PtrFree( p->vFanins );
Extra_MmFixedStop( p->pMmNode, 0 );
free( p->pTable );
free( p->pPractical );
free( p->puPerms43 );
free( p->puCanons );
free( p->pPhases );
free( p->pPerms );
free( p->pMap );
free( p->pTable );
free( p );
}
......@@ -220,9 +176,10 @@ Vec_Int_t * Rwr_ManReadDecs( Rwr_Man_t * p )
return p->vForm;
}
/**Function*************************************************************
Synopsis [Computes a phase of the 3-var function.]
Synopsis [Precomputes AIG subgraphs.]
Description []
......@@ -231,42 +188,13 @@ Vec_Int_t * Rwr_ManReadDecs( Rwr_Man_t * p )
SeeAlso []
***********************************************************************/
unsigned short Rwr_FunctionPerm( unsigned uTruth, int Phase )
void Rwr_Precompute()
{
static int Perm[16][4] = {
{ 0, 1, 2, 3 }, // 0000 - skip
{ 0, 1, 2, 3 }, // 0001 - skip
{ 1, 0, 2, 3 }, // 0010
{ 0, 1, 2, 3 }, // 0011 - skip
{ 2, 1, 0, 3 }, // 0100
{ 0, 2, 1, 3 }, // 0101
{ 2, 0, 1, 3 }, // 0110
{ 0, 1, 2, 3 }, // 0111 - skip
{ 3, 1, 2, 0 }, // 1000
{ 0, 3, 2, 1 }, // 1001
{ 3, 0, 2, 1 }, // 1010
{ 0, 1, 3, 2 }, // 1011
{ 2, 3, 0, 1 }, // 1100
{ 0, 3, 1, 2 }, // 1101
{ 3, 0, 1, 2 }, // 1110
{ 0, 1, 2, 3 } // 1111 - skip
};
int i, k, iRes;
unsigned uTruthRes;
assert( Phase < 16 );
uTruthRes = 0;
for ( i = 0; i < 16; i++ )
if ( uTruth & (1 << i) )
{
for ( iRes = 0, k = 0; k < 4; k++ )
if ( i & (1 << k) )
iRes |= (1 << Perm[Phase][k]);
uTruthRes |= (1 << iRes);
}
return uTruthRes;
Rwr_Man_t * p;
p = Rwr_ManStart( 1 );
Rwr_ManStop( p );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
/**CFile****************************************************************
FileName [rwrCut.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [DAG-aware AIG rewriting package.]
Synopsis [Cut computation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: rwrCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "rwr.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_Trav2_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, int * pVolume )
{
if ( pNode->fUsed || pNode->TravId == p->nTravIds )
return;
pNode->TravId = p->nTravIds;
(*pVolume)++;
Rwr_Trav2_rec( p, Rwr_Regular(pNode->p0), pVolume );
Rwr_Trav2_rec( p, Rwr_Regular(pNode->p1), pVolume );
}
/**Function*************************************************************
Synopsis [Adds the node to the end of the list.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_GetBushVolume( Rwr_Man_t * p, int Entry, int * pVolume, int * pnFuncs )
{
Rwr_Node_t * pNode;
int Volume = 0;
int nFuncs = 0;
Rwr_ManIncTravId( p );
for ( pNode = p->pTable[Entry]; pNode; pNode = pNode->pNext )
{
if ( pNode->uTruth != p->puCanons[pNode->uTruth] )
continue;
nFuncs++;
Rwr_Trav2_rec( p, pNode, &Volume );
}
*pVolume = Volume;
*pnFuncs = nFuncs;
}
/**Function*************************************************************
Synopsis [Prints one rwr node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_NodePrint_rec( FILE * pFile, Rwr_Node_t * pNode )
{
assert( !Rwr_IsComplement(pNode) );
if ( pNode->Id == 0 )
{
fprintf( pFile, "Const1" );
return;
}
if ( pNode->Id < 5 )
{
fprintf( pFile, "%c", 'a' + pNode->Id - 1 );
return;
}
if ( Rwr_IsComplement(pNode->p0) )
{
if ( Rwr_Regular(pNode->p0)->Id < 5 )
{
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) );
fprintf( pFile, "\'" );
}
else
{
fprintf( pFile, "(" );
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) );
fprintf( pFile, ")\'" );
}
}
else
{
if ( Rwr_Regular(pNode->p0)->Id < 5 )
{
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) );
}
else
{
fprintf( pFile, "(" );
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) );
fprintf( pFile, ")" );
}
}
if ( pNode->fExor )
fprintf( pFile, "+" );
if ( Rwr_IsComplement(pNode->p1) )
{
if ( Rwr_Regular(pNode->p1)->Id < 5 )
{
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) );
fprintf( pFile, "\'" );
}
else
{
fprintf( pFile, "(" );
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) );
fprintf( pFile, ")\'" );
}
}
else
{
if ( Rwr_Regular(pNode->p1)->Id < 5 )
{
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) );
}
else
{
fprintf( pFile, "(" );
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) );
fprintf( pFile, ")" );
}
}
}
/**Function*************************************************************
Synopsis [Prints one rwr node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_NodePrint( FILE * pFile, Rwr_Man_t * p, Rwr_Node_t * pNode )
{
unsigned uTruth;
fprintf( pFile, "%5d : ", pNode->Id );
Extra_PrintHex( pFile, pNode->uTruth, 4 );
fprintf( pFile, " tt=" );
uTruth = pNode->uTruth;
Extra_PrintBinary( pFile, &uTruth, 16 );
// fprintf( pFile, " cn=", pNode->Id );
// uTruth = p->puCanons[pNode->uTruth];
// Extra_PrintBinary( pFile, &uTruth, 16 );
fprintf( pFile, " lev=%d", pNode->Level );
fprintf( pFile, " vol=%d", pNode->Volume );
fprintf( pFile, " " );
Rwr_NodePrint_rec( pFile, pNode );
fprintf( pFile, "\n" );
}
/**Function*************************************************************
Synopsis [Prints one rwr node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_ManPrint( Rwr_Man_t * p )
{
FILE * pFile;
Rwr_Node_t * pNode;
unsigned uTruth;
int Counter, Volume, nFuncs, i;
pFile = fopen( "graph_lib.txt", "w" );
Counter = 0;
nFuncs = (1 << 16);
for ( i = 0; i < nFuncs; i++ )
{
if ( p->pTable[i] == NULL )
continue;
if ( i != p->puCanons[i] )
continue;
fprintf( pFile, "\nClass %3d ", Counter++ );
Rwr_GetBushVolume( p, i, &Volume, &nFuncs );
fprintf( pFile, "Functions = %2d. Volume = %2d. ", nFuncs, Volume );
uTruth = i;
Extra_PrintBinary( pFile, &uTruth, 16 );
fprintf( pFile, "\n" );
for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext )
if ( pNode->uTruth == p->puCanons[pNode->uTruth] )
Rwr_NodePrint( pFile, p, pNode );
}
fclose( pFile );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -94,6 +94,7 @@ extern void Ft_FactorStopMan();
extern Vec_Int_t * Ft_Factor( char * pSop );
extern int Ft_FactorGetNumNodes( Vec_Int_t * vForm );
extern int Ft_FactorGetNumVars( Vec_Int_t * vForm );
extern void Ft_FactorComplement( Vec_Int_t * vForm );
/*=== ftPrint.c =====================================================*/
extern void Ft_FactorPrint( FILE * pFile, Vec_Int_t * vForm, char * pNamesIn[], char * pNameOut );
......
......@@ -39,7 +39,6 @@ static Ft_Node_t * Ft_FactorTrivialCubeCascade( Vec_Int_t * vForm, Mvc_Cov
static Ft_Node_t * Ft_FactorNodeCreate( Vec_Int_t * vForm, int Type, Ft_Node_t * pNode1, Ft_Node_t * pNode2 );
static Ft_Node_t * Ft_FactorLeafCreate( Vec_Int_t * vForm, int iLit );
static void Ft_FactorFinalize( Vec_Int_t * vForm, Ft_Node_t * pNode, int nVars );
static void Ft_FactorComplement( Vec_Int_t * vForm );
static Vec_Int_t * Ft_FactorConst( int fConst1 );
// temporary procedures that work with the covers
......@@ -585,8 +584,6 @@ int Ft_FactorGetNumNodes( Vec_Int_t * vForm )
void Ft_FactorComplement( Vec_Int_t * vForm )
{
Ft_Node_t * pNode;
int nVars = Ft_FactorGetNumVars( vForm );
assert( nVars >= 0 );
pNode = Ft_NodeReadLast(vForm);
pNode->fCompl ^= 1;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment