mirror of https://github.com/YosysHQ/abc.git
Version abc61205
This commit is contained in:
parent
52e5b91cbb
commit
38254947a5
16
abc.dsp
16
abc.dsp
|
|
@ -262,6 +262,10 @@ SOURCE=.\src\base\abci\abcMiter.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\abci\abcMulti.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\abci\abcMv.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
@ -294,6 +298,10 @@ SOURCE=.\src\base\abci\abcRenode.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\abci\abcReorder.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\abci\abcRestruct.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
@ -1826,15 +1834,19 @@ SOURCE=.\src\map\if\ifMap.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\map\if\ifPrepro.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\map\if\ifReduce.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\map\if\ifSelect.c
|
||||
SOURCE=.\src\map\if\ifSeq.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\map\if\ifSeq.c
|
||||
SOURCE=.\src\map\if\ifTruth.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
|
|
|
|||
1
abc.rc
1
abc.rc
|
|
@ -30,7 +30,6 @@ alias fs fraig_sweep
|
|||
alias fsto fraig_store
|
||||
alias fres fraig_restore
|
||||
alias ft fraig_trust
|
||||
alias mu renode -m
|
||||
alias pex print_exdc -d
|
||||
alias pf print_factor
|
||||
alias pfan print_fanio
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -19,7 +19,6 @@
|
|||
***********************************************************************/
|
||||
|
||||
#include "ivy.h"
|
||||
#include "mem.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
|
|
|
|||
|
|
@ -698,9 +698,6 @@ extern int Abc_NodeMffcLabel( Abc_Obj_t * pNode );
|
|||
extern void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp );
|
||||
extern int Abc_NodeDeref_rec( Abc_Obj_t * pNode );
|
||||
extern int Abc_NodeRef_rec( Abc_Obj_t * pNode );
|
||||
/*=== abcRenode.c ==========================================================*/
|
||||
extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
|
||||
extern DdNode * Abc_NtkRenodeDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld );
|
||||
/*=== abcRefactor.c ==========================================================*/
|
||||
extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose );
|
||||
/*=== abcRewrite.c ==========================================================*/
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** arg
|
|||
static int Abc_CommandCollapse ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandStrash ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandBalance ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandMulti ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandRenode ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
static int Abc_CommandSweep ( Abc_Frame_t * pAbc, int argc, char ** argv );
|
||||
|
|
@ -184,6 +185,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
|
|||
Cmd_CommandAdd( pAbc, "Synthesis", "collapse", Abc_CommandCollapse, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "balance", Abc_CommandBalance, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "multi", Abc_CommandMulti, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "renode", Abc_CommandRenode, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "cleanup", Abc_CommandCleanup, 1 );
|
||||
Cmd_CommandAdd( pAbc, "Synthesis", "sweep", Abc_CommandSweep, 1 );
|
||||
|
|
@ -1911,7 +1913,7 @@ usage:
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
int Abc_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
FILE * pOut, * pErr;
|
||||
Abc_Ntk_t * pNtk, * pNtkRes;
|
||||
|
|
@ -1920,6 +1922,7 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
int fMulti;
|
||||
int fSimple;
|
||||
int fFactor;
|
||||
extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
|
||||
|
||||
pNtk = Abc_FrameReadNtk(pAbc);
|
||||
pOut = Abc_FrameReadOut(pAbc);
|
||||
|
|
@ -1990,7 +1993,7 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
}
|
||||
|
||||
// get the new network
|
||||
pNtkRes = Abc_NtkRenode( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple, fFactor );
|
||||
pNtkRes = Abc_NtkMulti( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple, fFactor );
|
||||
if ( pNtkRes == NULL )
|
||||
{
|
||||
fprintf( pErr, "Renoding has failed.\n" );
|
||||
|
|
@ -2001,7 +2004,7 @@ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
return 0;
|
||||
|
||||
usage:
|
||||
fprintf( pErr, "usage: renode [-T num] [-F num] [-msfch]\n" );
|
||||
fprintf( pErr, "usage: multi [-T num] [-F num] [-msfch]\n" );
|
||||
fprintf( pErr, "\t transforms an AIG into a logic network by creating larger nodes\n" );
|
||||
fprintf( pErr, "\t-F num : the maximum fanin size after renoding [default = %d]\n", nFaninMax );
|
||||
fprintf( pErr, "\t-T num : the threshold for AIG node duplication [default = %d]\n", nThresh );
|
||||
|
|
@ -2016,6 +2019,95 @@ usage:
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
FILE * pOut, * pErr;
|
||||
Abc_Ntk_t * pNtk, * pNtkRes;
|
||||
int nFaninMax, c;
|
||||
int fUseBdds;
|
||||
int fVerbose;
|
||||
extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int fUseBdds, int fVerbose );
|
||||
|
||||
pNtk = Abc_FrameReadNtk(pAbc);
|
||||
pOut = Abc_FrameReadOut(pAbc);
|
||||
pErr = Abc_FrameReadErr(pAbc);
|
||||
|
||||
// set defaults
|
||||
nFaninMax = 8;
|
||||
fUseBdds = 0;
|
||||
fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "Fbvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'F':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" );
|
||||
goto usage;
|
||||
}
|
||||
nFaninMax = atoi(argv[globalUtilOptind]);
|
||||
globalUtilOptind++;
|
||||
if ( nFaninMax < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'b':
|
||||
fUseBdds ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
fVerbose ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pNtk == NULL )
|
||||
{
|
||||
fprintf( pErr, "Empty network.\n" );
|
||||
return 1;
|
||||
}
|
||||
if ( !Abc_NtkIsStrash(pNtk) )
|
||||
{
|
||||
fprintf( pErr, "Cannot renode a network that is not an AIG (run \"strash\").\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get the new network
|
||||
pNtkRes = Abc_NtkRenode( pNtk, nFaninMax, fUseBdds, fVerbose );
|
||||
if ( pNtkRes == NULL )
|
||||
{
|
||||
fprintf( pErr, "Renoding has failed.\n" );
|
||||
return 1;
|
||||
}
|
||||
// replace the current network
|
||||
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
fprintf( pErr, "usage: renode [-F num] [-bv]\n" );
|
||||
fprintf( pErr, "\t transforms an AIG into a logic network by creating larger nodes\n" );
|
||||
fprintf( pErr, "\t-F num : the maximum fanin size after renoding [default = %d]\n", nFaninMax );
|
||||
fprintf( pErr, "\t-b : toggles cost function (BDD nodes or FF literals) [default = %s]\n", fUseBdds? "BDD nodes": "FF literals" );
|
||||
fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
fprintf( pErr, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -7391,19 +7483,26 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
|
||||
// set defaults
|
||||
memset( pPars, 0, sizeof(If_Par_t) );
|
||||
// user-controlable paramters
|
||||
pPars->Mode = 0;
|
||||
pPars->nLutSize = 4;
|
||||
// pPars->pLutLib = Abc_FrameReadLibLut();
|
||||
pPars->nCutsMax = 20;
|
||||
pPars->DelayTarget = -1;
|
||||
pPars->fPreprocess = 1;
|
||||
pPars->fArea = 0;
|
||||
pPars->fFancy = 0;
|
||||
pPars->fLatchPaths = 0;
|
||||
pPars->fExpRed = 1;
|
||||
pPars->fLatchPaths = 0;
|
||||
pPars->fSeq = 0;
|
||||
pPars->nLatches = 0;
|
||||
pPars->DelayTarget = -1;
|
||||
pPars->fVerbose = 0;
|
||||
// internal parameters
|
||||
pPars->fTruth = 1;
|
||||
pPars->nLatches = pNtk? Abc_NtkLatchNum(pNtk) : 0;
|
||||
pPars->pLutLib = NULL; // Abc_FrameReadLibLut();
|
||||
pPars->pTimesArr = NULL;
|
||||
pPars->pTimesArr = NULL;
|
||||
pPars->pFuncCost = NULL;
|
||||
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "MKCDpaflrsvh" ) ) != EOF )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@
|
|||
static If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
|
||||
static Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk );
|
||||
static Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj );
|
||||
static Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Cut_t * pCut );
|
||||
static Hop_Obj_t * Abc_NodeIfToHop2( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj );
|
||||
static Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
|
|
@ -75,7 +74,7 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// transform the result of mapping into a BDD network
|
||||
// transform the result of mapping into the new network
|
||||
pNtkNew = Abc_NtkFromIf( pIfMan, pNtk );
|
||||
if ( pNtkNew == NULL )
|
||||
return NULL;
|
||||
|
|
@ -163,7 +162,10 @@ Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk )
|
|||
Abc_Obj_t * pNode, * pNodeNew;
|
||||
int i, nDupGates;
|
||||
// create the new network
|
||||
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG );
|
||||
if ( pIfMan->pPars->fUseBdds )
|
||||
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
|
||||
else
|
||||
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG );
|
||||
// prepare the mapping manager
|
||||
If_ManCleanNodeCopy( pIfMan );
|
||||
If_ManCleanCutData( pIfMan );
|
||||
|
|
@ -221,8 +223,33 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t
|
|||
If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i )
|
||||
Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf) );
|
||||
// derive the function of this node
|
||||
// pNodeNew->pData = Abc_NodeIfToHop( pNtkNew->pManFunc, pIfMan, pCutBest );
|
||||
pNodeNew->pData = Abc_NodeIfToHop2( pNtkNew->pManFunc, pIfMan, pIfObj );
|
||||
|
||||
if ( pIfMan->pPars->fTruth )
|
||||
{
|
||||
if ( pIfMan->pPars->fUseBdds )
|
||||
{
|
||||
extern void Abc_NodeBddReorder( void * p, Abc_Obj_t * pNode );
|
||||
extern DdNode * Kit_TruthToBdd( DdManager * dd, unsigned * pTruth, int nVars );
|
||||
// transform truth table into the BDD
|
||||
pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), pCutBest->nLimit );
|
||||
// reorder the fanins to minimize the BDD size
|
||||
Abc_NodeBddReorder( pIfMan->pPars->pReoMan, pNodeNew );
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef int Kit_Graph_t;
|
||||
extern Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars );
|
||||
extern Hop_Obj_t * Dec_GraphToNetworkAig( Hop_Man_t * pMan, Kit_Graph_t * pGraph );
|
||||
// transform truth table into the decomposition tree
|
||||
Kit_Graph_t * pGraph = Kit_TruthToGraph( If_CutTruth(pCutBest), pCutBest->nLimit );
|
||||
// derive the AIG for that tree
|
||||
pNodeNew->pData = Dec_GraphToNetworkAig( pNtkNew->pManFunc, pGraph );
|
||||
Kit_GraphFree( pGraph );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
pNodeNew->pData = Abc_NodeIfToHop( pNtkNew->pManFunc, pIfMan, pIfObj );
|
||||
If_ObjSetCopy( pIfObj, pNodeNew );
|
||||
return pNodeNew;
|
||||
}
|
||||
|
|
@ -238,70 +265,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Ptr_t * vVisited )
|
||||
{
|
||||
Hop_Obj_t * gFunc, * gFunc0, * gFunc1;
|
||||
// if the cut is visited, return the result
|
||||
if ( If_CutData(pCut) )
|
||||
return If_CutData(pCut);
|
||||
// compute the functions of the children
|
||||
gFunc0 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pCut->pOne, vVisited );
|
||||
gFunc1 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pCut->pTwo, vVisited );
|
||||
// get the function of the cut
|
||||
gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pCut->fCompl0), Hop_NotCond(gFunc1, pCut->fCompl1) );
|
||||
gFunc = Hop_NotCond( gFunc, pCut->Phase );
|
||||
assert( If_CutData(pCut) == NULL );
|
||||
If_CutSetData( pCut, gFunc );
|
||||
// add this cut to the visited list
|
||||
Vec_PtrPush( vVisited, pCut );
|
||||
return gFunc;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Derives the truth table for one cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Cut_t * pCut )
|
||||
{
|
||||
Hop_Obj_t * gFunc;
|
||||
If_Obj_t * pLeaf;
|
||||
int i;
|
||||
assert( pCut->nLeaves > 1 );
|
||||
// set the leaf variables
|
||||
If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
|
||||
If_CutSetData( If_ObjCutTriv(pLeaf), Hop_IthVar(pHopMan, i) );
|
||||
// recursively compute the function while collecting visited cuts
|
||||
Vec_PtrClear( pIfMan->vTemp );
|
||||
gFunc = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pCut, pIfMan->vTemp );
|
||||
// printf( "%d ", Vec_PtrSize(p->vTemp) );
|
||||
// clean the cuts
|
||||
If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
|
||||
If_CutSetData( If_ObjCutTriv(pLeaf), NULL );
|
||||
Vec_PtrForEachEntry( pIfMan->vTemp, pCut, i )
|
||||
If_CutSetData( pCut, NULL );
|
||||
return gFunc;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Recursively derives the truth table for the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Hop_Obj_t * Abc_NodeIfToHop2_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited )
|
||||
Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited )
|
||||
{
|
||||
If_Cut_t * pCut;
|
||||
Hop_Obj_t * gFunc, * gFunc0, * gFunc1;
|
||||
|
|
@ -311,11 +275,10 @@ Hop_Obj_t * Abc_NodeIfToHop2_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj
|
|||
if ( If_CutData(pCut) )
|
||||
return If_CutData(pCut);
|
||||
// compute the functions of the children
|
||||
gFunc0 = Abc_NodeIfToHop2_rec( pHopMan, pIfMan, pIfObj->pFanin0, vVisited );
|
||||
gFunc1 = Abc_NodeIfToHop2_rec( pHopMan, pIfMan, pIfObj->pFanin1, vVisited );
|
||||
gFunc0 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin0, vVisited );
|
||||
gFunc1 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin1, vVisited );
|
||||
// get the function of the cut
|
||||
gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pIfObj->fCompl0), Hop_NotCond(gFunc1, pIfObj->fCompl1) );
|
||||
gFunc = Hop_NotCond( gFunc, pCut->Phase );
|
||||
assert( If_CutData(pCut) == NULL );
|
||||
If_CutSetData( pCut, gFunc );
|
||||
// add this cut to the visited list
|
||||
|
|
@ -334,7 +297,7 @@ Hop_Obj_t * Abc_NodeIfToHop2_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Hop_Obj_t * Abc_NodeIfToHop2( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj )
|
||||
Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj )
|
||||
{
|
||||
If_Cut_t * pCut;
|
||||
Hop_Obj_t * gFunc;
|
||||
|
|
@ -348,7 +311,7 @@ Hop_Obj_t * Abc_NodeIfToHop2( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t *
|
|||
If_CutSetData( If_ObjCutTriv(pLeaf), Hop_IthVar(pHopMan, i) );
|
||||
// recursively compute the function while collecting visited cuts
|
||||
Vec_PtrClear( pIfMan->vTemp );
|
||||
gFunc = Abc_NodeIfToHop2_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp );
|
||||
gFunc = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp );
|
||||
// printf( "%d ", Vec_PtrSize(p->vTemp) );
|
||||
// clean the cuts
|
||||
If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
|
||||
|
|
|
|||
|
|
@ -469,6 +469,7 @@ Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk )
|
|||
***********************************************************************/
|
||||
Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
|
||||
{
|
||||
extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
|
||||
ProgressBar * pProgress;
|
||||
Abc_Ntk_t * pNtkNew, * pNtkNew2;
|
||||
Abc_Obj_t * pNode;
|
||||
|
|
@ -484,7 +485,7 @@ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk )
|
|||
|
||||
// duplicate the network
|
||||
pNtkNew2 = Abc_NtkDup( pNtk );
|
||||
pNtkNew = Abc_NtkRenode( pNtkNew2, 0, 20, 0, 0, 1, 0 );
|
||||
pNtkNew = Abc_NtkMulti( pNtkNew2, 0, 20, 0, 0, 1, 0 );
|
||||
if ( !Abc_NtkBddToSop( pNtkNew, 0 ) )
|
||||
{
|
||||
printf( "Abc_NtkFromMapSuperChoice(): Converting to SOPs has failed.\n" );
|
||||
|
|
|
|||
|
|
@ -0,0 +1,643 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [abcMulti.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Network and node package.]
|
||||
|
||||
Synopsis [Procedures which transform an AIG into multi-input AND-graph.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: abcMulti.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "abc.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
|
||||
static Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld );
|
||||
|
||||
static DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFanins );
|
||||
static DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld );
|
||||
|
||||
static void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax );
|
||||
static void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk );
|
||||
static void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh );
|
||||
static void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk );
|
||||
static void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk );
|
||||
static void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Transforms the AIG into nodes.]
|
||||
|
||||
Description [Threhold is the max number of nodes duplicated at a node.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor )
|
||||
{
|
||||
Abc_Ntk_t * pNtkNew;
|
||||
|
||||
assert( Abc_NtkIsStrash(pNtk) );
|
||||
assert( nThresh >= 0 );
|
||||
assert( nFaninMax > 1 );
|
||||
|
||||
// print a warning about choice nodes
|
||||
if ( Abc_NtkGetChoiceNum( pNtk ) )
|
||||
printf( "Warning: The choice nodes in the AIG are removed by renoding.\n" );
|
||||
|
||||
// define the boundary
|
||||
if ( fCnf )
|
||||
Abc_NtkMultiSetBoundsCnf( pNtk );
|
||||
else if ( fMulti )
|
||||
Abc_NtkMultiSetBoundsMulti( pNtk, nThresh );
|
||||
else if ( fSimple )
|
||||
Abc_NtkMultiSetBoundsSimple( pNtk );
|
||||
else if ( fFactor )
|
||||
Abc_NtkMultiSetBoundsFactor( pNtk );
|
||||
else
|
||||
Abc_NtkMultiSetBounds( pNtk, nThresh, nFaninMax );
|
||||
|
||||
// perform renoding for this boundary
|
||||
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
|
||||
Abc_NtkMultiInt( pNtk, pNtkNew );
|
||||
Abc_NtkFinalize( pNtk, pNtkNew );
|
||||
|
||||
// make the network minimum base
|
||||
Abc_NtkMinimumBase( pNtkNew );
|
||||
|
||||
// fix the problem with complemented and duplicated CO edges
|
||||
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
|
||||
|
||||
// report the number of CNF objects
|
||||
if ( fCnf )
|
||||
{
|
||||
// int nClauses = Abc_NtkGetClauseNum(pNtkNew) + 2*Abc_NtkPoNum(pNtkNew) + 2*Abc_NtkLatchNum(pNtkNew);
|
||||
// printf( "CNF variables = %d. CNF clauses = %d.\n", Abc_NtkNodeNum(pNtkNew), nClauses );
|
||||
}
|
||||
//printf( "Maximum fanin = %d.\n", Abc_NtkGetFaninMax(pNtkNew) );
|
||||
|
||||
if ( pNtk->pExdc )
|
||||
pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
|
||||
// make sure everything is okay
|
||||
if ( !Abc_NtkCheck( pNtkNew ) )
|
||||
{
|
||||
printf( "Abc_NtkMulti: The network check has failed.\n" );
|
||||
Abc_NtkDelete( pNtkNew );
|
||||
return NULL;
|
||||
}
|
||||
return pNtkNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Transforms the AIG into nodes.]
|
||||
|
||||
Description [Threhold is the max number of nodes duplicated at a node.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
|
||||
{
|
||||
ProgressBar * pProgress;
|
||||
Abc_Obj_t * pNode, * pConst1, * pNodeNew;
|
||||
int i;
|
||||
|
||||
// set the constant node
|
||||
pConst1 = Abc_AigConst1(pNtk);
|
||||
if ( Abc_ObjFanoutNum(pConst1) > 0 )
|
||||
{
|
||||
pNodeNew = Abc_NtkCreateNode( pNtkNew );
|
||||
pNodeNew->pData = Cudd_ReadOne( pNtkNew->pManFunc ); Cudd_Ref( pNodeNew->pData );
|
||||
pConst1->pCopy = pNodeNew;
|
||||
}
|
||||
|
||||
// perform renoding for POs
|
||||
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
|
||||
Abc_NtkForEachCo( pNtk, pNode, i )
|
||||
{
|
||||
Extra_ProgressBarUpdate( pProgress, i, NULL );
|
||||
if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
|
||||
continue;
|
||||
Abc_NtkMulti_rec( pNtkNew, Abc_ObjFanin0(pNode) );
|
||||
}
|
||||
Extra_ProgressBarStop( pProgress );
|
||||
|
||||
// clean the boundaries and data field in the old network
|
||||
Abc_NtkForEachObj( pNtk, pNode, i )
|
||||
{
|
||||
pNode->fMarkA = 0;
|
||||
pNode->pData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Find the best multi-input node rooted at the given node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld )
|
||||
{
|
||||
Vec_Ptr_t * vCone;
|
||||
Abc_Obj_t * pNodeNew;
|
||||
int i;
|
||||
|
||||
assert( !Abc_ObjIsComplement(pNodeOld) );
|
||||
// return if the result if known
|
||||
if ( pNodeOld->pCopy )
|
||||
return pNodeOld->pCopy;
|
||||
assert( Abc_ObjIsNode(pNodeOld) );
|
||||
assert( !Abc_AigNodeIsConst(pNodeOld) );
|
||||
assert( pNodeOld->fMarkA );
|
||||
|
||||
//printf( "%d ", Abc_NodeMffcSizeSupp(pNodeOld) );
|
||||
|
||||
// collect the renoding cone
|
||||
vCone = Vec_PtrAlloc( 10 );
|
||||
Abc_NtkMultiCone( pNodeOld, vCone );
|
||||
|
||||
// create a new node
|
||||
pNodeNew = Abc_NtkCreateNode( pNtkNew );
|
||||
for ( i = 0; i < vCone->nSize; i++ )
|
||||
Abc_ObjAddFanin( pNodeNew, Abc_NtkMulti_rec(pNtkNew, vCone->pArray[i]) );
|
||||
|
||||
// derive the function of this node
|
||||
pNodeNew->pData = Abc_NtkMultiDeriveBdd( pNtkNew->pManFunc, pNodeOld, vCone );
|
||||
Cudd_Ref( pNodeNew->pData );
|
||||
Vec_PtrFree( vCone );
|
||||
|
||||
// remember the node
|
||||
pNodeOld->pCopy = pNodeNew;
|
||||
return pNodeOld->pCopy;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Derives the local BDD of the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld )
|
||||
{
|
||||
Abc_Obj_t * pFaninOld;
|
||||
DdNode * bFunc;
|
||||
int i;
|
||||
assert( !Abc_AigNodeIsConst(pNodeOld) );
|
||||
assert( Abc_ObjIsNode(pNodeOld) );
|
||||
// set the elementary BDD variables for the input nodes
|
||||
for ( i = 0; i < vFaninsOld->nSize; i++ )
|
||||
{
|
||||
pFaninOld = vFaninsOld->pArray[i];
|
||||
pFaninOld->pData = Cudd_bddIthVar( dd, i ); Cudd_Ref( pFaninOld->pData );
|
||||
pFaninOld->fMarkC = 1;
|
||||
}
|
||||
// call the recursive BDD computation
|
||||
bFunc = Abc_NtkMultiDeriveBdd_rec( dd, pNodeOld, vFaninsOld ); Cudd_Ref( bFunc );
|
||||
// dereference the intermediate nodes
|
||||
for ( i = 0; i < vFaninsOld->nSize; i++ )
|
||||
{
|
||||
pFaninOld = vFaninsOld->pArray[i];
|
||||
Cudd_RecursiveDeref( dd, pFaninOld->pData );
|
||||
pFaninOld->fMarkC = 0;
|
||||
}
|
||||
Cudd_Deref( bFunc );
|
||||
return bFunc;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Derives the local BDD of the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins )
|
||||
{
|
||||
DdNode * bFunc, * bFunc0, * bFunc1;
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
// if the result is available return
|
||||
if ( pNode->fMarkC )
|
||||
{
|
||||
assert( pNode->pData ); // network has a cycle
|
||||
return pNode->pData;
|
||||
}
|
||||
// mark the node as visited
|
||||
pNode->fMarkC = 1;
|
||||
Vec_PtrPush( vFanins, pNode );
|
||||
// compute the result for both branches
|
||||
bFunc0 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,0), vFanins ); Cudd_Ref( bFunc0 );
|
||||
bFunc1 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,1), vFanins ); Cudd_Ref( bFunc1 );
|
||||
bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) );
|
||||
bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) );
|
||||
// get the final result
|
||||
bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
|
||||
Cudd_RecursiveDeref( dd, bFunc0 );
|
||||
Cudd_RecursiveDeref( dd, bFunc1 );
|
||||
// set the result
|
||||
pNode->pData = bFunc;
|
||||
assert( pNode->pData );
|
||||
return bFunc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Limits the cones to be no more than the given size.]
|
||||
|
||||
Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NtkMultiLimit_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax, int fCanStop, int fFirst )
|
||||
{
|
||||
int nNodes0, nNodes1;
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
// check if the node should be added to the fanins
|
||||
if ( !fFirst && (pNode->fMarkA || !Abc_ObjIsNode(pNode)) )
|
||||
{
|
||||
Vec_PtrPushUnique( vCone, pNode );
|
||||
return 0;
|
||||
}
|
||||
// if we cannot stop in this branch, collect all nodes
|
||||
if ( !fCanStop )
|
||||
{
|
||||
Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 0, 0 );
|
||||
Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
|
||||
return 0;
|
||||
}
|
||||
// if we can stop, try the left branch first, and return if we stopped
|
||||
assert( vCone->nSize == 0 );
|
||||
if ( Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 1, 0 ) )
|
||||
return 1;
|
||||
// save the number of nodes in the left branch and call for the right branch
|
||||
nNodes0 = vCone->nSize;
|
||||
assert( nNodes0 <= nFaninMax );
|
||||
Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
|
||||
// check the number of nodes
|
||||
if ( vCone->nSize <= nFaninMax )
|
||||
return 0;
|
||||
// the number of nodes exceeds the limit
|
||||
|
||||
// get the number of nodes in the right branch
|
||||
vCone->nSize = 0;
|
||||
Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
|
||||
// if this number exceeds the limit, solve the problem for this branch
|
||||
if ( vCone->nSize > nFaninMax )
|
||||
{
|
||||
int RetValue;
|
||||
vCone->nSize = 0;
|
||||
RetValue = Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 1, 0 );
|
||||
assert( RetValue == 1 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
nNodes1 = vCone->nSize;
|
||||
assert( nNodes1 <= nFaninMax );
|
||||
if ( nNodes0 >= nNodes1 )
|
||||
{ // the left branch is larger - cut it
|
||||
assert( Abc_ObjFanin(pNode,0)->fMarkA == 0 );
|
||||
Abc_ObjFanin(pNode,0)->fMarkA = 1;
|
||||
}
|
||||
else
|
||||
{ // the right branch is larger - cut it
|
||||
assert( Abc_ObjFanin(pNode,1)->fMarkA == 0 );
|
||||
Abc_ObjFanin(pNode,1)->fMarkA = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Limits the cones to be no more than the given size.]
|
||||
|
||||
Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NtkMultiLimit( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax )
|
||||
{
|
||||
vCone->nSize = 0;
|
||||
return Abc_NtkMultiLimit_rec( pNode, vCone, nFaninMax, 1, 1 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets the expansion boundary for multi-input nodes.]
|
||||
|
||||
Description [The boundary includes the set of PIs and all nodes such that
|
||||
when expanding over the node we duplicate no more than nThresh nodes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax )
|
||||
{
|
||||
Vec_Ptr_t * vCone = Vec_PtrAlloc(10);
|
||||
Abc_Obj_t * pNode;
|
||||
int i, nFanouts, nConeSize;
|
||||
|
||||
// make sure the mark is not set
|
||||
Abc_NtkForEachObj( pNtk, pNode, i )
|
||||
assert( pNode->fMarkA == 0 );
|
||||
|
||||
// mark the nodes where expansion stops using pNode->fMarkA
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
// skip PI/PO nodes
|
||||
// if ( Abc_NodeIsConst(pNode) )
|
||||
// continue;
|
||||
// mark the nodes with multiple fanouts
|
||||
nFanouts = Abc_ObjFanoutNum(pNode);
|
||||
nConeSize = Abc_NodeMffcSize(pNode);
|
||||
if ( (nFanouts - 1) * nConeSize > nThresh )
|
||||
pNode->fMarkA = 1;
|
||||
}
|
||||
|
||||
// mark the PO drivers
|
||||
Abc_NtkForEachCo( pNtk, pNode, i )
|
||||
Abc_ObjFanin0(pNode)->fMarkA = 1;
|
||||
|
||||
// make sure the fanin limit is met
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
// skip PI/PO nodes
|
||||
// if ( Abc_NodeIsConst(pNode) )
|
||||
// continue;
|
||||
if ( pNode->fMarkA == 0 )
|
||||
continue;
|
||||
// continue cutting branches until it meets the fanin limit
|
||||
while ( Abc_NtkMultiLimit(pNode, vCone, nFaninMax) );
|
||||
assert( vCone->nSize <= nFaninMax );
|
||||
}
|
||||
Vec_PtrFree(vCone);
|
||||
/*
|
||||
// make sure the fanin limit is met
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
// skip PI/PO nodes
|
||||
// if ( Abc_NodeIsConst(pNode) )
|
||||
// continue;
|
||||
if ( pNode->fMarkA == 0 )
|
||||
continue;
|
||||
Abc_NtkMultiCone( pNode, vCone );
|
||||
assert( vCone->nSize <= nFaninMax );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets the expansion boundary for conversion into CNF.]
|
||||
|
||||
Description [The boundary includes the set of PIs, the roots of MUXes,
|
||||
the nodes with multiple fanouts and the nodes with complemented outputs.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pNode;
|
||||
int i, nMuxes;
|
||||
|
||||
// make sure the mark is not set
|
||||
Abc_NtkForEachObj( pNtk, pNode, i )
|
||||
assert( pNode->fMarkA == 0 );
|
||||
|
||||
// mark the nodes where expansion stops using pNode->fMarkA
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
// skip PI/PO nodes
|
||||
// if ( Abc_NodeIsConst(pNode) )
|
||||
// continue;
|
||||
// mark the nodes with multiple fanouts
|
||||
if ( Abc_ObjFanoutNum(pNode) > 1 )
|
||||
pNode->fMarkA = 1;
|
||||
// mark the nodes that are roots of MUXes
|
||||
if ( Abc_NodeIsMuxType( pNode ) )
|
||||
{
|
||||
pNode->fMarkA = 1;
|
||||
Abc_ObjFanin0( Abc_ObjFanin0(pNode) )->fMarkA = 1;
|
||||
Abc_ObjFanin0( Abc_ObjFanin1(pNode) )->fMarkA = 1;
|
||||
Abc_ObjFanin1( Abc_ObjFanin0(pNode) )->fMarkA = 1;
|
||||
Abc_ObjFanin1( Abc_ObjFanin1(pNode) )->fMarkA = 1;
|
||||
}
|
||||
else // mark the complemented edges
|
||||
{
|
||||
if ( Abc_ObjFaninC0(pNode) )
|
||||
Abc_ObjFanin0(pNode)->fMarkA = 1;
|
||||
if ( Abc_ObjFaninC1(pNode) )
|
||||
Abc_ObjFanin1(pNode)->fMarkA = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// mark the PO drivers
|
||||
Abc_NtkForEachCo( pNtk, pNode, i )
|
||||
Abc_ObjFanin0(pNode)->fMarkA = 1;
|
||||
|
||||
// count the number of MUXes
|
||||
nMuxes = 0;
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
// skip PI/PO nodes
|
||||
// if ( Abc_NodeIsConst(pNode) )
|
||||
// continue;
|
||||
if ( Abc_NodeIsMuxType(pNode) &&
|
||||
Abc_ObjFanin0(pNode)->fMarkA == 0 &&
|
||||
Abc_ObjFanin1(pNode)->fMarkA == 0 )
|
||||
nMuxes++;
|
||||
}
|
||||
// printf( "The number of MUXes detected = %d (%5.2f %% of logic).\n", nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets the expansion boundary for conversion into multi-input AND graph.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh )
|
||||
{
|
||||
Abc_Obj_t * pNode;
|
||||
int i, nFanouts, nConeSize;
|
||||
|
||||
// make sure the mark is not set
|
||||
Abc_NtkForEachObj( pNtk, pNode, i )
|
||||
assert( pNode->fMarkA == 0 );
|
||||
|
||||
// mark the nodes where expansion stops using pNode->fMarkA
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
// skip PI/PO nodes
|
||||
// if ( Abc_NodeIsConst(pNode) )
|
||||
// continue;
|
||||
// mark the nodes with multiple fanouts
|
||||
// if ( Abc_ObjFanoutNum(pNode) > 1 )
|
||||
// pNode->fMarkA = 1;
|
||||
// mark the nodes with multiple fanouts
|
||||
nFanouts = Abc_ObjFanoutNum(pNode);
|
||||
nConeSize = Abc_NodeMffcSizeStop(pNode);
|
||||
if ( (nFanouts - 1) * nConeSize > nThresh )
|
||||
pNode->fMarkA = 1;
|
||||
// mark the children if they are pointed by the complemented edges
|
||||
if ( Abc_ObjFaninC0(pNode) )
|
||||
Abc_ObjFanin0(pNode)->fMarkA = 1;
|
||||
if ( Abc_ObjFaninC1(pNode) )
|
||||
Abc_ObjFanin1(pNode)->fMarkA = 1;
|
||||
}
|
||||
|
||||
// mark the PO drivers
|
||||
Abc_NtkForEachCo( pNtk, pNode, i )
|
||||
Abc_ObjFanin0(pNode)->fMarkA = 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets a simple boundary.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pNode;
|
||||
int i;
|
||||
// make sure the mark is not set
|
||||
Abc_NtkForEachObj( pNtk, pNode, i )
|
||||
assert( pNode->fMarkA == 0 );
|
||||
// mark the nodes where expansion stops using pNode->fMarkA
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
pNode->fMarkA = 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets a factor-cut boundary.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pNode;
|
||||
int i;
|
||||
// make sure the mark is not set
|
||||
Abc_NtkForEachObj( pNtk, pNode, i )
|
||||
assert( pNode->fMarkA == 0 );
|
||||
// mark the nodes where expansion stops using pNode->fMarkA
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
pNode->fMarkA = (pNode->vFanouts.nSize > 1 && !Abc_NodeIsMuxControlType(pNode));
|
||||
// mark the PO drivers
|
||||
Abc_NtkForEachCo( pNtk, pNode, i )
|
||||
Abc_ObjFanin0(pNode)->fMarkA = 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the fanins of a large node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkMultiCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
|
||||
{
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
if ( pNode->fMarkA || !Abc_ObjIsNode(pNode) )
|
||||
{
|
||||
Vec_PtrPushUnique( vCone, pNode );
|
||||
return;
|
||||
}
|
||||
Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone );
|
||||
Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the fanins of a large node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
|
||||
{
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
assert( Abc_ObjIsNode(pNode) );
|
||||
vCone->nSize = 0;
|
||||
Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone );
|
||||
Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
|
@ -536,73 +536,6 @@ double Abc_NtkSpacePercentage( Abc_Obj_t * pNode )
|
|||
|
||||
|
||||
|
||||
#include "reo.h"
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reorders BDD of the local function of the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NodeBddReorder( reo_man * p, Abc_Obj_t * pNode )
|
||||
{
|
||||
Abc_Obj_t * pFanin;
|
||||
DdNode * bFunc;
|
||||
int * pOrder, i;
|
||||
// create the temporary array for the variable order
|
||||
pOrder = ALLOC( int, Abc_ObjFaninNum(pNode) );
|
||||
for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
|
||||
pOrder[i] = -1;
|
||||
// reorder the BDD
|
||||
bFunc = Extra_Reorder( p, pNode->pNtk->pManFunc, pNode->pData, pOrder ); Cudd_Ref( bFunc );
|
||||
Cudd_RecursiveDeref( pNode->pNtk->pManFunc, pNode->pData );
|
||||
pNode->pData = bFunc;
|
||||
// update the fanin order
|
||||
Abc_ObjForEachFanin( pNode, pFanin, i )
|
||||
pOrder[i] = pNode->vFanins.pArray[ pOrder[i] ];
|
||||
Abc_ObjForEachFanin( pNode, pFanin, i )
|
||||
pNode->vFanins.pArray[i] = pOrder[i];
|
||||
free( pOrder );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reorders BDDs of the local functions.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose )
|
||||
{
|
||||
reo_man * p;
|
||||
Abc_Obj_t * pNode;
|
||||
int i;
|
||||
p = Extra_ReorderInit( Abc_NtkGetFaninMax(pNtk), 100 );
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
if ( Abc_ObjFaninNum(pNode) < 3 )
|
||||
continue;
|
||||
if ( fVerbose )
|
||||
fprintf( stdout, "%10s: ", Abc_ObjName(pNode) );
|
||||
if ( fVerbose )
|
||||
fprintf( stdout, "Before = %5d BDD nodes. ", Cudd_DagSize(pNode->pData) );
|
||||
Abc_NodeBddReorder( p, pNode );
|
||||
if ( fVerbose )
|
||||
fprintf( stdout, "After = %5d BDD nodes.\n", Cudd_DagSize(pNode->pData) );
|
||||
}
|
||||
Extra_ReorderQuit( p );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
PackageName [Network and node package.]
|
||||
|
||||
Synopsis [Procedures which transform an AIG into the network of SOP logic nodes.]
|
||||
Synopsis []
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
|
|
@ -19,22 +19,22 @@
|
|||
***********************************************************************/
|
||||
|
||||
#include "abc.h"
|
||||
#include "reo.h"
|
||||
#include "if.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void Abc_NtkRenodeInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
|
||||
static Abc_Obj_t * Abc_NtkRenode_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld );
|
||||
static int Abc_NtkRenodeEvalBdd( unsigned * pTruth, int nVars );
|
||||
static int Abc_NtkRenodeEvalSop( unsigned * pTruth, int nVars );
|
||||
|
||||
static DdNode * Abc_NtkRenodeDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFanins );
|
||||
static reo_man * s_pReo = NULL;
|
||||
static DdManager * s_pDd = NULL;
|
||||
|
||||
static void Abc_NtkRenodeSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax );
|
||||
static void Abc_NtkRenodeSetBoundsCnf( Abc_Ntk_t * pNtk );
|
||||
static void Abc_NtkRenodeSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh );
|
||||
static void Abc_NtkRenodeSetBoundsSimple( Abc_Ntk_t * pNtk );
|
||||
static void Abc_NtkRenodeSetBoundsFactor( Abc_Ntk_t * pNtk );
|
||||
static void Abc_NtkRenodeCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone );
|
||||
typedef int Kit_Graph_t;
|
||||
extern DdNode * Kit_TruthToBdd( DdManager * dd, unsigned * pTruth, int nVars );
|
||||
extern Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
|
|
@ -42,118 +42,70 @@ static void Abc_NtkRenodeCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone );
|
|||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Transforms the AIG into nodes.]
|
||||
Synopsis [Performs renoding as technology mapping.]
|
||||
|
||||
Description [Threhold is the max number of nodes duplicated at a node.]
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor )
|
||||
Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int fUseBdds, int fVerbose )
|
||||
{
|
||||
extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
|
||||
If_Par_t Pars, * pPars = &Pars;
|
||||
Abc_Ntk_t * pNtkNew;
|
||||
|
||||
assert( Abc_NtkIsStrash(pNtk) );
|
||||
assert( nThresh >= 0 );
|
||||
assert( nFaninMax > 1 );
|
||||
// set defaults
|
||||
memset( pPars, 0, sizeof(If_Par_t) );
|
||||
// user-controlable paramters
|
||||
pPars->Mode = 0;
|
||||
pPars->nLutSize = nFaninMax;
|
||||
pPars->nCutsMax = 10;
|
||||
pPars->DelayTarget = -1;
|
||||
pPars->fPreprocess = 1;
|
||||
pPars->fArea = 0;
|
||||
pPars->fFancy = 0;
|
||||
pPars->fExpRed = 0; //
|
||||
pPars->fLatchPaths = 0;
|
||||
pPars->fSeq = 0;
|
||||
pPars->fVerbose = 0;
|
||||
// internal parameters
|
||||
pPars->fTruth = 1;
|
||||
pPars->nLatches = 0;
|
||||
pPars->pLutLib = NULL; // Abc_FrameReadLibLut();
|
||||
pPars->pTimesArr = NULL;
|
||||
pPars->pTimesArr = NULL;
|
||||
pPars->pFuncCost = fUseBdds? Abc_NtkRenodeEvalBdd : Abc_NtkRenodeEvalSop;
|
||||
|
||||
// print a warning about choice nodes
|
||||
if ( Abc_NtkGetChoiceNum( pNtk ) )
|
||||
printf( "Warning: The choice nodes in the AIG are removed by renoding.\n" );
|
||||
|
||||
// define the boundary
|
||||
if ( fCnf )
|
||||
Abc_NtkRenodeSetBoundsCnf( pNtk );
|
||||
else if ( fMulti )
|
||||
Abc_NtkRenodeSetBoundsMulti( pNtk, nThresh );
|
||||
else if ( fSimple )
|
||||
Abc_NtkRenodeSetBoundsSimple( pNtk );
|
||||
else if ( fFactor )
|
||||
Abc_NtkRenodeSetBoundsFactor( pNtk );
|
||||
else
|
||||
Abc_NtkRenodeSetBounds( pNtk, nThresh, nFaninMax );
|
||||
|
||||
// perform renoding for this boundary
|
||||
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
|
||||
Abc_NtkRenodeInt( pNtk, pNtkNew );
|
||||
Abc_NtkFinalize( pNtk, pNtkNew );
|
||||
|
||||
// make the network minimum base
|
||||
Abc_NtkMinimumBase( pNtkNew );
|
||||
|
||||
// fix the problem with complemented and duplicated CO edges
|
||||
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
|
||||
|
||||
// report the number of CNF objects
|
||||
if ( fCnf )
|
||||
// start the manager
|
||||
if ( fUseBdds )
|
||||
{
|
||||
// int nClauses = Abc_NtkGetClauseNum(pNtkNew) + 2*Abc_NtkPoNum(pNtkNew) + 2*Abc_NtkLatchNum(pNtkNew);
|
||||
// printf( "CNF variables = %d. CNF clauses = %d.\n", Abc_NtkNodeNum(pNtkNew), nClauses );
|
||||
assert( s_pReo == NULL );
|
||||
s_pDd = Cudd_Init( nFaninMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
|
||||
s_pReo = Extra_ReorderInit( nFaninMax, 100 );
|
||||
pPars->fUseBdds = 1;
|
||||
pPars->pReoMan = s_pReo;
|
||||
}
|
||||
//printf( "Maximum fanin = %d.\n", Abc_NtkGetFaninMax(pNtkNew) );
|
||||
|
||||
if ( pNtk->pExdc )
|
||||
pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
|
||||
// make sure everything is okay
|
||||
if ( !Abc_NtkCheck( pNtkNew ) )
|
||||
// perform mapping/renoding
|
||||
pNtkNew = Abc_NtkIf( pNtk, pPars );
|
||||
|
||||
// start the manager
|
||||
if ( fUseBdds )
|
||||
{
|
||||
printf( "Abc_NtkRenode: The network check has failed.\n" );
|
||||
Abc_NtkDelete( pNtkNew );
|
||||
return NULL;
|
||||
Extra_StopManager( s_pDd );
|
||||
Extra_ReorderQuit( s_pReo );
|
||||
s_pReo = NULL;
|
||||
s_pDd = NULL;
|
||||
}
|
||||
return pNtkNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Transforms the AIG into nodes.]
|
||||
|
||||
Description [Threhold is the max number of nodes duplicated at a node.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkRenodeInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
|
||||
{
|
||||
ProgressBar * pProgress;
|
||||
Abc_Obj_t * pNode, * pConst1, * pNodeNew;
|
||||
int i;
|
||||
|
||||
// set the constant node
|
||||
pConst1 = Abc_AigConst1(pNtk);
|
||||
if ( Abc_ObjFanoutNum(pConst1) > 0 )
|
||||
{
|
||||
pNodeNew = Abc_NtkCreateNode( pNtkNew );
|
||||
pNodeNew->pData = Cudd_ReadOne( pNtkNew->pManFunc ); Cudd_Ref( pNodeNew->pData );
|
||||
pConst1->pCopy = pNodeNew;
|
||||
}
|
||||
|
||||
// perform renoding for POs
|
||||
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
|
||||
Abc_NtkForEachCo( pNtk, pNode, i )
|
||||
{
|
||||
Extra_ProgressBarUpdate( pProgress, i, NULL );
|
||||
if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
|
||||
continue;
|
||||
Abc_NtkRenode_rec( pNtkNew, Abc_ObjFanin0(pNode) );
|
||||
}
|
||||
Extra_ProgressBarStop( pProgress );
|
||||
|
||||
// clean the boundaries and data field in the old network
|
||||
Abc_NtkForEachObj( pNtk, pNode, i )
|
||||
{
|
||||
pNode->fMarkA = 0;
|
||||
pNode->pData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Find the best multi-input node rooted at the given node.]
|
||||
Synopsis [Derives the BDD after reordering.]
|
||||
|
||||
Description []
|
||||
|
||||
|
|
@ -162,45 +114,22 @@ void Abc_NtkRenodeInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Abc_Obj_t * Abc_NtkRenode_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld )
|
||||
int Abc_NtkRenodeEvalBdd( unsigned * pTruth, int nVars )
|
||||
{
|
||||
Vec_Ptr_t * vCone;
|
||||
Abc_Obj_t * pNodeNew;
|
||||
int i;
|
||||
|
||||
assert( !Abc_ObjIsComplement(pNodeOld) );
|
||||
// return if the result if known
|
||||
if ( pNodeOld->pCopy )
|
||||
return pNodeOld->pCopy;
|
||||
assert( Abc_ObjIsNode(pNodeOld) );
|
||||
assert( !Abc_AigNodeIsConst(pNodeOld) );
|
||||
assert( pNodeOld->fMarkA );
|
||||
|
||||
//printf( "%d ", Abc_NodeMffcSizeSupp(pNodeOld) );
|
||||
|
||||
// collect the renoding cone
|
||||
vCone = Vec_PtrAlloc( 10 );
|
||||
Abc_NtkRenodeCone( pNodeOld, vCone );
|
||||
|
||||
// create a new node
|
||||
pNodeNew = Abc_NtkCreateNode( pNtkNew );
|
||||
for ( i = 0; i < vCone->nSize; i++ )
|
||||
Abc_ObjAddFanin( pNodeNew, Abc_NtkRenode_rec(pNtkNew, vCone->pArray[i]) );
|
||||
|
||||
// derive the function of this node
|
||||
pNodeNew->pData = Abc_NtkRenodeDeriveBdd( pNtkNew->pManFunc, pNodeOld, vCone );
|
||||
Cudd_Ref( pNodeNew->pData );
|
||||
Vec_PtrFree( vCone );
|
||||
|
||||
// remember the node
|
||||
pNodeOld->pCopy = pNodeNew;
|
||||
return pNodeOld->pCopy;
|
||||
DdNode * bFunc, * bFuncNew;
|
||||
int nNodes, nSupport;
|
||||
bFunc = Kit_TruthToBdd( s_pDd, pTruth, nVars ); Cudd_Ref( bFunc );
|
||||
bFuncNew = Extra_Reorder( s_pReo, s_pDd, bFunc, NULL ); Cudd_Ref( bFuncNew );
|
||||
nSupport = Cudd_SupportSize( s_pDd, bFuncNew );
|
||||
nNodes = Cudd_DagSize( bFuncNew );
|
||||
Cudd_RecursiveDeref( s_pDd, bFuncNew );
|
||||
Cudd_RecursiveDeref( s_pDd, bFunc );
|
||||
return (nSupport << 16) | nNodes;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Derives the local BDD of the node.]
|
||||
Synopsis [Derives the BDD after reordering.]
|
||||
|
||||
Description []
|
||||
|
||||
|
|
@ -209,430 +138,15 @@ Abc_Obj_t * Abc_NtkRenode_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
DdNode * Abc_NtkRenodeDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld )
|
||||
int Abc_NtkRenodeEvalSop( unsigned * pTruth, int nVars )
|
||||
{
|
||||
Abc_Obj_t * pFaninOld;
|
||||
DdNode * bFunc;
|
||||
int i;
|
||||
assert( !Abc_AigNodeIsConst(pNodeOld) );
|
||||
assert( Abc_ObjIsNode(pNodeOld) );
|
||||
// set the elementary BDD variables for the input nodes
|
||||
for ( i = 0; i < vFaninsOld->nSize; i++ )
|
||||
{
|
||||
pFaninOld = vFaninsOld->pArray[i];
|
||||
pFaninOld->pData = Cudd_bddIthVar( dd, i ); Cudd_Ref( pFaninOld->pData );
|
||||
pFaninOld->fMarkC = 1;
|
||||
}
|
||||
// call the recursive BDD computation
|
||||
bFunc = Abc_NtkRenodeDeriveBdd_rec( dd, pNodeOld, vFaninsOld ); Cudd_Ref( bFunc );
|
||||
// dereference the intermediate nodes
|
||||
for ( i = 0; i < vFaninsOld->nSize; i++ )
|
||||
{
|
||||
pFaninOld = vFaninsOld->pArray[i];
|
||||
Cudd_RecursiveDeref( dd, pFaninOld->pData );
|
||||
pFaninOld->fMarkC = 0;
|
||||
}
|
||||
Cudd_Deref( bFunc );
|
||||
return bFunc;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Derives the local BDD of the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
DdNode * Abc_NtkRenodeDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins )
|
||||
{
|
||||
DdNode * bFunc, * bFunc0, * bFunc1;
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
// if the result is available return
|
||||
if ( pNode->fMarkC )
|
||||
{
|
||||
assert( pNode->pData ); // network has a cycle
|
||||
return pNode->pData;
|
||||
}
|
||||
// mark the node as visited
|
||||
pNode->fMarkC = 1;
|
||||
Vec_PtrPush( vFanins, pNode );
|
||||
// compute the result for both branches
|
||||
bFunc0 = Abc_NtkRenodeDeriveBdd_rec( dd, Abc_ObjFanin(pNode,0), vFanins ); Cudd_Ref( bFunc0 );
|
||||
bFunc1 = Abc_NtkRenodeDeriveBdd_rec( dd, Abc_ObjFanin(pNode,1), vFanins ); Cudd_Ref( bFunc1 );
|
||||
bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) );
|
||||
bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) );
|
||||
// get the final result
|
||||
bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
|
||||
Cudd_RecursiveDeref( dd, bFunc0 );
|
||||
Cudd_RecursiveDeref( dd, bFunc1 );
|
||||
// set the result
|
||||
pNode->pData = bFunc;
|
||||
assert( pNode->pData );
|
||||
return bFunc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Limits the cones to be no more than the given size.]
|
||||
|
||||
Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NtkRenodeLimit_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax, int fCanStop, int fFirst )
|
||||
{
|
||||
int nNodes0, nNodes1;
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
// check if the node should be added to the fanins
|
||||
if ( !fFirst && (pNode->fMarkA || !Abc_ObjIsNode(pNode)) )
|
||||
{
|
||||
Vec_PtrPushUnique( vCone, pNode );
|
||||
return 0;
|
||||
}
|
||||
// if we cannot stop in this branch, collect all nodes
|
||||
if ( !fCanStop )
|
||||
{
|
||||
Abc_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 0, 0 );
|
||||
Abc_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
|
||||
return 0;
|
||||
}
|
||||
// if we can stop, try the left branch first, and return if we stopped
|
||||
assert( vCone->nSize == 0 );
|
||||
if ( Abc_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 1, 0 ) )
|
||||
return 1;
|
||||
// save the number of nodes in the left branch and call for the right branch
|
||||
nNodes0 = vCone->nSize;
|
||||
assert( nNodes0 <= nFaninMax );
|
||||
Abc_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
|
||||
// check the number of nodes
|
||||
if ( vCone->nSize <= nFaninMax )
|
||||
return 0;
|
||||
// the number of nodes exceeds the limit
|
||||
|
||||
// get the number of nodes in the right branch
|
||||
vCone->nSize = 0;
|
||||
Abc_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 );
|
||||
// if this number exceeds the limit, solve the problem for this branch
|
||||
if ( vCone->nSize > nFaninMax )
|
||||
{
|
||||
int RetValue;
|
||||
vCone->nSize = 0;
|
||||
RetValue = Abc_NtkRenodeLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 1, 0 );
|
||||
assert( RetValue == 1 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
nNodes1 = vCone->nSize;
|
||||
assert( nNodes1 <= nFaninMax );
|
||||
if ( nNodes0 >= nNodes1 )
|
||||
{ // the left branch is larger - cut it
|
||||
assert( Abc_ObjFanin(pNode,0)->fMarkA == 0 );
|
||||
Abc_ObjFanin(pNode,0)->fMarkA = 1;
|
||||
}
|
||||
else
|
||||
{ // the right branch is larger - cut it
|
||||
assert( Abc_ObjFanin(pNode,1)->fMarkA == 0 );
|
||||
Abc_ObjFanin(pNode,1)->fMarkA = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Limits the cones to be no more than the given size.]
|
||||
|
||||
Description [Returns 1 if the last cone was limited. Returns 0 if no changes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NtkRenodeLimit( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax )
|
||||
{
|
||||
vCone->nSize = 0;
|
||||
return Abc_NtkRenodeLimit_rec( pNode, vCone, nFaninMax, 1, 1 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets the expansion boundary for multi-input nodes.]
|
||||
|
||||
Description [The boundary includes the set of PIs and all nodes such that
|
||||
when expanding over the node we duplicate no more than nThresh nodes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkRenodeSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax )
|
||||
{
|
||||
Vec_Ptr_t * vCone = Vec_PtrAlloc(10);
|
||||
Abc_Obj_t * pNode;
|
||||
int i, nFanouts, nConeSize;
|
||||
|
||||
// make sure the mark is not set
|
||||
Abc_NtkForEachObj( pNtk, pNode, i )
|
||||
assert( pNode->fMarkA == 0 );
|
||||
|
||||
// mark the nodes where expansion stops using pNode->fMarkA
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
// skip PI/PO nodes
|
||||
// if ( Abc_NodeIsConst(pNode) )
|
||||
// continue;
|
||||
// mark the nodes with multiple fanouts
|
||||
nFanouts = Abc_ObjFanoutNum(pNode);
|
||||
nConeSize = Abc_NodeMffcSize(pNode);
|
||||
if ( (nFanouts - 1) * nConeSize > nThresh )
|
||||
pNode->fMarkA = 1;
|
||||
}
|
||||
|
||||
// mark the PO drivers
|
||||
Abc_NtkForEachCo( pNtk, pNode, i )
|
||||
Abc_ObjFanin0(pNode)->fMarkA = 1;
|
||||
|
||||
// make sure the fanin limit is met
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
// skip PI/PO nodes
|
||||
// if ( Abc_NodeIsConst(pNode) )
|
||||
// continue;
|
||||
if ( pNode->fMarkA == 0 )
|
||||
continue;
|
||||
// continue cutting branches until it meets the fanin limit
|
||||
while ( Abc_NtkRenodeLimit(pNode, vCone, nFaninMax) );
|
||||
assert( vCone->nSize <= nFaninMax );
|
||||
}
|
||||
Vec_PtrFree(vCone);
|
||||
/*
|
||||
// make sure the fanin limit is met
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
// skip PI/PO nodes
|
||||
// if ( Abc_NodeIsConst(pNode) )
|
||||
// continue;
|
||||
if ( pNode->fMarkA == 0 )
|
||||
continue;
|
||||
Abc_NtkRenodeCone( pNode, vCone );
|
||||
assert( vCone->nSize <= nFaninMax );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets the expansion boundary for conversion into CNF.]
|
||||
|
||||
Description [The boundary includes the set of PIs, the roots of MUXes,
|
||||
the nodes with multiple fanouts and the nodes with complemented outputs.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkRenodeSetBoundsCnf( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pNode;
|
||||
int i, nMuxes;
|
||||
|
||||
// make sure the mark is not set
|
||||
Abc_NtkForEachObj( pNtk, pNode, i )
|
||||
assert( pNode->fMarkA == 0 );
|
||||
|
||||
// mark the nodes where expansion stops using pNode->fMarkA
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
// skip PI/PO nodes
|
||||
// if ( Abc_NodeIsConst(pNode) )
|
||||
// continue;
|
||||
// mark the nodes with multiple fanouts
|
||||
if ( Abc_ObjFanoutNum(pNode) > 1 )
|
||||
pNode->fMarkA = 1;
|
||||
// mark the nodes that are roots of MUXes
|
||||
if ( Abc_NodeIsMuxType( pNode ) )
|
||||
{
|
||||
pNode->fMarkA = 1;
|
||||
Abc_ObjFanin0( Abc_ObjFanin0(pNode) )->fMarkA = 1;
|
||||
Abc_ObjFanin0( Abc_ObjFanin1(pNode) )->fMarkA = 1;
|
||||
Abc_ObjFanin1( Abc_ObjFanin0(pNode) )->fMarkA = 1;
|
||||
Abc_ObjFanin1( Abc_ObjFanin1(pNode) )->fMarkA = 1;
|
||||
}
|
||||
else // mark the complemented edges
|
||||
{
|
||||
if ( Abc_ObjFaninC0(pNode) )
|
||||
Abc_ObjFanin0(pNode)->fMarkA = 1;
|
||||
if ( Abc_ObjFaninC1(pNode) )
|
||||
Abc_ObjFanin1(pNode)->fMarkA = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// mark the PO drivers
|
||||
Abc_NtkForEachCo( pNtk, pNode, i )
|
||||
Abc_ObjFanin0(pNode)->fMarkA = 1;
|
||||
|
||||
// count the number of MUXes
|
||||
nMuxes = 0;
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
// skip PI/PO nodes
|
||||
// if ( Abc_NodeIsConst(pNode) )
|
||||
// continue;
|
||||
if ( Abc_NodeIsMuxType(pNode) &&
|
||||
Abc_ObjFanin0(pNode)->fMarkA == 0 &&
|
||||
Abc_ObjFanin1(pNode)->fMarkA == 0 )
|
||||
nMuxes++;
|
||||
}
|
||||
// printf( "The number of MUXes detected = %d (%5.2f %% of logic).\n", nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets the expansion boundary for conversion into multi-input AND graph.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkRenodeSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh )
|
||||
{
|
||||
Abc_Obj_t * pNode;
|
||||
int i, nFanouts, nConeSize;
|
||||
|
||||
// make sure the mark is not set
|
||||
Abc_NtkForEachObj( pNtk, pNode, i )
|
||||
assert( pNode->fMarkA == 0 );
|
||||
|
||||
// mark the nodes where expansion stops using pNode->fMarkA
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
// skip PI/PO nodes
|
||||
// if ( Abc_NodeIsConst(pNode) )
|
||||
// continue;
|
||||
// mark the nodes with multiple fanouts
|
||||
// if ( Abc_ObjFanoutNum(pNode) > 1 )
|
||||
// pNode->fMarkA = 1;
|
||||
// mark the nodes with multiple fanouts
|
||||
nFanouts = Abc_ObjFanoutNum(pNode);
|
||||
nConeSize = Abc_NodeMffcSizeStop(pNode);
|
||||
if ( (nFanouts - 1) * nConeSize > nThresh )
|
||||
pNode->fMarkA = 1;
|
||||
// mark the children if they are pointed by the complemented edges
|
||||
if ( Abc_ObjFaninC0(pNode) )
|
||||
Abc_ObjFanin0(pNode)->fMarkA = 1;
|
||||
if ( Abc_ObjFaninC1(pNode) )
|
||||
Abc_ObjFanin1(pNode)->fMarkA = 1;
|
||||
}
|
||||
|
||||
// mark the PO drivers
|
||||
Abc_NtkForEachCo( pNtk, pNode, i )
|
||||
Abc_ObjFanin0(pNode)->fMarkA = 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets a simple boundary.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkRenodeSetBoundsSimple( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pNode;
|
||||
int i;
|
||||
// make sure the mark is not set
|
||||
Abc_NtkForEachObj( pNtk, pNode, i )
|
||||
assert( pNode->fMarkA == 0 );
|
||||
// mark the nodes where expansion stops using pNode->fMarkA
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
pNode->fMarkA = 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sets a factor-cut boundary.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkRenodeSetBoundsFactor( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pNode;
|
||||
int i;
|
||||
// make sure the mark is not set
|
||||
Abc_NtkForEachObj( pNtk, pNode, i )
|
||||
assert( pNode->fMarkA == 0 );
|
||||
// mark the nodes where expansion stops using pNode->fMarkA
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
pNode->fMarkA = (pNode->vFanouts.nSize > 1 && !Abc_NodeIsMuxControlType(pNode));
|
||||
// mark the PO drivers
|
||||
Abc_NtkForEachCo( pNtk, pNode, i )
|
||||
Abc_ObjFanin0(pNode)->fMarkA = 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the fanins of a large node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkRenodeCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
|
||||
{
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
if ( pNode->fMarkA || !Abc_ObjIsNode(pNode) )
|
||||
{
|
||||
Vec_PtrPushUnique( vCone, pNode );
|
||||
return;
|
||||
}
|
||||
Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,0), vCone );
|
||||
Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,1), vCone );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the fanins of a large node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkRenodeCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone )
|
||||
{
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
assert( Abc_ObjIsNode(pNode) );
|
||||
vCone->nSize = 0;
|
||||
Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,0), vCone );
|
||||
Abc_NtkRenodeCone_rec( Abc_ObjFanin(pNode,1), vCone );
|
||||
Kit_Graph_t * pGraph;
|
||||
int nNodes, nDepth;
|
||||
pGraph = Kit_TruthToGraph( pTruth, nVars );
|
||||
nNodes = Kit_GraphNodeNum( pGraph );
|
||||
nDepth = Kit_GraphLevelNum( pGraph );
|
||||
Kit_GraphFree( pGraph );
|
||||
return (nDepth << 16) | nNodes;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [abcReorder.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Network and node package.]
|
||||
|
||||
Synopsis [Reordering local BDDs of the nodes.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: abcReorder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "abc.h"
|
||||
#include "reo.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reorders BDD of the local function of the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NodeBddReorder( reo_man * p, Abc_Obj_t * pNode )
|
||||
{
|
||||
Abc_Obj_t * pFanin;
|
||||
DdNode * bFunc;
|
||||
int * pOrder, i;
|
||||
// create the temporary array for the variable order
|
||||
pOrder = ALLOC( int, Abc_ObjFaninNum(pNode) );
|
||||
for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
|
||||
pOrder[i] = -1;
|
||||
// reorder the BDD
|
||||
bFunc = Extra_Reorder( p, pNode->pNtk->pManFunc, pNode->pData, pOrder ); Cudd_Ref( bFunc );
|
||||
Cudd_RecursiveDeref( pNode->pNtk->pManFunc, pNode->pData );
|
||||
pNode->pData = bFunc;
|
||||
// update the fanin order
|
||||
Abc_ObjForEachFanin( pNode, pFanin, i )
|
||||
pOrder[i] = pNode->vFanins.pArray[ pOrder[i] ];
|
||||
Abc_ObjForEachFanin( pNode, pFanin, i )
|
||||
pNode->vFanins.pArray[i] = pOrder[i];
|
||||
free( pOrder );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reorders BDDs of the local functions.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose )
|
||||
{
|
||||
reo_man * p;
|
||||
Abc_Obj_t * pNode;
|
||||
int i;
|
||||
p = Extra_ReorderInit( Abc_NtkGetFaninMax(pNtk), 100 );
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
if ( Abc_ObjFaninNum(pNode) < 3 )
|
||||
continue;
|
||||
if ( fVerbose )
|
||||
fprintf( stdout, "%10s: ", Abc_ObjName(pNode) );
|
||||
if ( fVerbose )
|
||||
fprintf( stdout, "Before = %5d BDD nodes. ", Cudd_DagSize(pNode->pData) );
|
||||
Abc_NodeBddReorder( p, pNode );
|
||||
if ( fVerbose )
|
||||
fprintf( stdout, "After = %5d BDD nodes.\n", Cudd_DagSize(pNode->pData) );
|
||||
}
|
||||
Extra_ReorderQuit( p );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
|
@ -46,6 +46,7 @@ static void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2,
|
|||
***********************************************************************/
|
||||
void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit )
|
||||
{
|
||||
extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
|
||||
Abc_Ntk_t * pMiter;
|
||||
Abc_Ntk_t * pCnf;
|
||||
int RetValue;
|
||||
|
|
@ -76,7 +77,7 @@ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nI
|
|||
}
|
||||
|
||||
// convert the miter into a CNF
|
||||
pCnf = Abc_NtkRenode( pMiter, 0, 100, 1, 0, 0, 0 );
|
||||
pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 );
|
||||
Abc_NtkDelete( pMiter );
|
||||
if ( pCnf == NULL )
|
||||
{
|
||||
|
|
@ -207,6 +208,7 @@ void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fV
|
|||
***********************************************************************/
|
||||
void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames )
|
||||
{
|
||||
extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor );
|
||||
Abc_Ntk_t * pMiter;
|
||||
Abc_Ntk_t * pFrames;
|
||||
Abc_Ntk_t * pCnf;
|
||||
|
|
@ -256,7 +258,7 @@ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nI
|
|||
}
|
||||
|
||||
// convert the miter into a CNF
|
||||
pCnf = Abc_NtkRenode( pFrames, 0, 100, 1, 0, 0, 0 );
|
||||
pCnf = Abc_NtkMulti( pFrames, 0, 100, 1, 0, 0, 0 );
|
||||
Abc_NtkDelete( pFrames );
|
||||
if ( pCnf == NULL )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ SRC += src/base/abci/abc.c \
|
|||
src/base/abci/abcMap.c \
|
||||
src/base/abci/abcMini.c \
|
||||
src/base/abci/abcMiter.c \
|
||||
src/base/abci/abcMulti.c \
|
||||
src/base/abci/abcNtbdd.c \
|
||||
src/base/abci/abcOrder.c \
|
||||
src/base/abci/abcPrint.c \
|
||||
|
|
@ -28,6 +29,7 @@ SRC += src/base/abci/abc.c \
|
|||
src/base/abci/abcReconv.c \
|
||||
src/base/abci/abcRefactor.c \
|
||||
src/base/abci/abcRenode.c \
|
||||
src/base/abci/abcReorder.c \
|
||||
src/base/abci/abcRestruct.c \
|
||||
src/base/abci/abcResub.c \
|
||||
src/base/abci/abcRewrite.c \
|
||||
|
|
|
|||
|
|
@ -70,21 +70,27 @@ typedef struct If_Cut_t_ If_Cut_t;
|
|||
// parameters
|
||||
struct If_Par_t_
|
||||
{
|
||||
// user-controlable paramters
|
||||
int Mode; // the mapping mode
|
||||
int nLutSize; // the LUT size
|
||||
If_Lib_t * pLutLib; // the LUT library
|
||||
int nCutsMax; // the max number of cuts
|
||||
int fVerbose; // the verbosity flag
|
||||
float DelayTarget; // delay target
|
||||
int fPreprocess; // preprossing
|
||||
int fArea; // area-oriented mapping
|
||||
int fFancy; // a fancy feature
|
||||
int fExpRed; // expand/reduce of the best cuts
|
||||
int fLatchPaths; // reset timing on latch paths
|
||||
int fSeq; // sequential mapping
|
||||
int nLatches; // the number of latches
|
||||
float DelayTarget; // delay target
|
||||
int fVerbose; // the verbosity flag
|
||||
// internal parameters
|
||||
int fTruth; // truth table computation enabled
|
||||
int fUseBdds; // sets local BDDs at the nodes
|
||||
int nLatches; // the number of latches in seq mapping
|
||||
If_Lib_t * pLutLib; // the LUT library
|
||||
float * pTimesArr; // arrival times
|
||||
float * pTimesReq; // required times
|
||||
int(*pFuncCost)(unsigned *, int); // procedure the user's cost of a cut
|
||||
void * pReoMan; // reordering manager
|
||||
};
|
||||
|
||||
// the LUT library
|
||||
|
|
@ -118,10 +124,13 @@ struct If_Man_t_
|
|||
int nCutsMerged; // the total number of cuts merged
|
||||
int nCutsMax; // the maximum number of cuts at a node
|
||||
float Fi; // the current value of the clock period (for seq mapping)
|
||||
unsigned * puTemp[4]; // used for the truth table computation
|
||||
// memory management
|
||||
Mem_Fixed_t * pMem; // memory manager
|
||||
int nEntrySize; // the size of the entry
|
||||
int nEntryBase; // the size of the entry minus cut leaf arrays
|
||||
int nTruthSize; // the size of the truth table if allocated
|
||||
int nCutSize; // the size of the cut
|
||||
// temporary cut storage
|
||||
int nCuts; // the number of cuts used
|
||||
If_Cut_t ** ppCuts; // the storage space for cuts
|
||||
|
|
@ -132,14 +141,14 @@ struct If_Cut_t_
|
|||
{
|
||||
float Delay; // delay of the cut
|
||||
float Area; // area (or area-flow) of the cut
|
||||
If_Cut_t * pOne; // parent cut
|
||||
If_Cut_t * pTwo; // parent cut
|
||||
unsigned uSign; // cut signature
|
||||
char fCompl0; // complemented attribute
|
||||
char fCompl1; // complemented attribute
|
||||
char Phase; // complemented attribute
|
||||
char nLeaves; // number of leaves
|
||||
unsigned Cost : 10; // the user's cost of the cut
|
||||
unsigned Depth : 9; // the user's depth of the cut
|
||||
unsigned fCompl : 1; // the complemented attribute
|
||||
unsigned nLimit : 6; // the maximum number of leaves
|
||||
unsigned nLeaves : 6; // the number of leaves
|
||||
int * pLeaves; // array of fanins
|
||||
unsigned * pTruth; // the truth table
|
||||
};
|
||||
|
||||
// node extension
|
||||
|
|
@ -197,8 +206,11 @@ static inline unsigned If_ObjCutSign( unsigned ObjId ) { r
|
|||
static inline void * If_CutData( If_Cut_t * pCut ) { return *(void **)pCut; }
|
||||
static inline void If_CutSetData( If_Cut_t * pCut, void * pData ) { *(void **)pCut = pData; }
|
||||
|
||||
static inline float If_CutLutDelay( If_Man_t * p, If_Cut_t * pCut ) { return p->pPars->pLutLib? p->pPars->pLutLib->pLutDelays[pCut->nLeaves] : (float)1.0; }
|
||||
static inline float If_CutLutArea( If_Man_t * p, If_Cut_t * pCut ) { return p->pPars->pLutLib? p->pPars->pLutLib->pLutAreas[pCut->nLeaves] : (float)1.0; }
|
||||
static inline int If_CutTruthWords( int nVarsMax ) { return nVarsMax <= 5 ? 1 : (1 << (nVarsMax - 5)); }
|
||||
static inline unsigned * If_CutTruth( If_Cut_t * pCut ) { return pCut->pTruth; }
|
||||
|
||||
static inline float If_CutLutDelay( If_Man_t * p, If_Cut_t * pCut ) { return pCut->Depth? (float)pCut->Depth : (p->pPars->pLutLib? p->pPars->pLutLib->pLutDelays[pCut->nLeaves] : (float)1.0); }
|
||||
static inline float If_CutLutArea( If_Man_t * p, If_Cut_t * pCut ) { return pCut->Cost? (float)pCut->Cost : (p->pPars->pLutLib? p->pPars->pLutLib->pLutAreas[pCut->nLeaves] : (float)1.0); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// MACRO DEFINITIONS ///
|
||||
|
|
@ -244,6 +256,18 @@ static inline float If_CutLutArea( If_Man_t * p, If_Cut_t * pCut ) { r
|
|||
/*=== ifCore.c ==========================================================*/
|
||||
extern int If_ManPerformMapping( If_Man_t * p );
|
||||
extern int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fRequired );
|
||||
/*=== ifCut.c ==========================================================*/
|
||||
extern float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut, int nLevels );
|
||||
extern float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut, int nLevels );
|
||||
extern float If_CutDeref( If_Man_t * p, If_Cut_t * pCut, int nLevels );
|
||||
extern float If_CutRef( If_Man_t * p, If_Cut_t * pCut, int nLevels );
|
||||
extern void If_CutPrint( If_Man_t * p, If_Cut_t * pCut );
|
||||
extern float If_CutDelay( If_Man_t * p, If_Cut_t * pCut );
|
||||
extern float If_CutFlow( If_Man_t * p, If_Cut_t * pCut );
|
||||
extern int If_CutFilter( If_Man_t * p, If_Cut_t * pCut );
|
||||
extern int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut );
|
||||
extern void If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc );
|
||||
extern void If_ManSortCuts( If_Man_t * p, int Mode );
|
||||
/*=== ifMan.c ==========================================================*/
|
||||
extern If_Man_t * If_ManStart( If_Par_t * pPars );
|
||||
extern void If_ManStop( If_Man_t * p );
|
||||
|
|
@ -252,19 +276,14 @@ extern If_Obj_t * If_ManCreatePo( If_Man_t * p, If_Obj_t * pDriver, int fCo
|
|||
extern If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, int fCompl0, If_Obj_t * pFan1, int fCompl1 );
|
||||
/*=== ifMap.c ==========================================================*/
|
||||
extern void If_ObjPerformMapping( If_Man_t * p, If_Obj_t * pObj, int Mode );
|
||||
extern float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut, int nLevels );
|
||||
extern float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut, int nLevels );
|
||||
extern float If_CutDeref( If_Man_t * p, If_Cut_t * pCut, int nLevels );
|
||||
extern float If_CutRef( If_Man_t * p, If_Cut_t * pCut, int nLevels );
|
||||
extern void If_CutPrint( If_Man_t * p, If_Cut_t * pCut );
|
||||
extern float If_CutDelay( If_Man_t * p, If_Cut_t * pCut );
|
||||
extern float If_CutFlow( If_Man_t * p, If_Cut_t * pCut );
|
||||
extern int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut, int nLimit );
|
||||
extern void If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc );
|
||||
/*=== ifPrepro.c ==========================================================*/
|
||||
extern void If_ManPerformMappingPreprocess( If_Man_t * p );
|
||||
/*=== ifReduce.c ==========================================================*/
|
||||
extern void If_ManImproveMapping( If_Man_t * p );
|
||||
/*=== ifSelect.c ==========================================================*/
|
||||
extern void If_ManPerformMappingPreprocess( If_Man_t * p );
|
||||
/*=== ifSeq.c ==========================================================*/
|
||||
extern int If_ManPerformMappingSeq( If_Man_t * p );
|
||||
/*=== ifTruth.c ==========================================================*/
|
||||
extern void If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 );
|
||||
/*=== ifUtil.c ==========================================================*/
|
||||
extern float If_ManDelayMax( If_Man_t * p );
|
||||
extern void If_ManCleanNodeCopy( If_Man_t * p );
|
||||
|
|
|
|||
|
|
@ -59,20 +59,20 @@ int If_ManPerformMapping( If_Man_t * p )
|
|||
else
|
||||
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1 );
|
||||
// try to improve area by expanding and reducing the cuts
|
||||
if ( p->pPars->fExpRed )
|
||||
if ( p->pPars->fExpRed && !p->pPars->fTruth )
|
||||
If_ManImproveMapping( p );
|
||||
// area flow oriented mapping
|
||||
for ( i = 0; i < nItersFlow; i++ )
|
||||
{
|
||||
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 1, 1 );
|
||||
if ( p->pPars->fExpRed )
|
||||
if ( p->pPars->fExpRed && !p->pPars->fTruth )
|
||||
If_ManImproveMapping( p );
|
||||
}
|
||||
// area oriented mapping
|
||||
for ( i = 0; i < nItersArea; i++ )
|
||||
{
|
||||
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 2, 1 );
|
||||
if ( p->pPars->fExpRed )
|
||||
if ( p->pPars->fExpRed && !p->pPars->fTruth )
|
||||
If_ManImproveMapping( p );
|
||||
}
|
||||
if ( p->pPars->fVerbose )
|
||||
|
|
|
|||
|
|
@ -28,9 +28,10 @@
|
|||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
Synopsis [Returns 1 if pDom is contained in pCut.]
|
||||
|
||||
Description []
|
||||
|
||||
|
|
@ -39,6 +40,561 @@
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int If_CutCheckDominance( If_Cut_t * pDom, If_Cut_t * pCut )
|
||||
{
|
||||
int i, k;
|
||||
for ( i = 0; i < (int)pDom->nLeaves; i++ )
|
||||
{
|
||||
for ( k = 0; k < (int)pCut->nLeaves; k++ )
|
||||
if ( pDom->pLeaves[i] == pCut->pLeaves[k] )
|
||||
break;
|
||||
if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut
|
||||
return 0;
|
||||
}
|
||||
// every node in pDom is contained in pCut
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if pDom is equal to pCut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int If_CutCheckEquality( If_Cut_t * pDom, If_Cut_t * pCut )
|
||||
{
|
||||
int i;
|
||||
if ( (int)pDom->nLeaves != (int)pCut->nLeaves )
|
||||
return 0;
|
||||
for ( i = 0; i < (int)pDom->nLeaves; i++ )
|
||||
if ( pDom->pLeaves[i] != pCut->pLeaves[i] )
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if the cut is contained.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutFilter( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
If_Cut_t * pTemp;
|
||||
int i;
|
||||
for ( i = 0; i < p->nCuts; i++ )
|
||||
{
|
||||
pTemp = p->ppCuts[i];
|
||||
if ( pTemp->nLeaves > pCut->nLeaves )
|
||||
{
|
||||
// continue;
|
||||
// skip the non-contained cuts
|
||||
if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
|
||||
continue;
|
||||
// check containment seriously
|
||||
if ( If_CutCheckDominance( pCut, pTemp ) )
|
||||
{
|
||||
// removed contained cut
|
||||
p->ppCuts[i] = p->ppCuts[p->nCuts-1];
|
||||
p->ppCuts[p->nCuts-1] = pTemp;
|
||||
p->nCuts--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// skip the non-contained cuts
|
||||
if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
|
||||
continue;
|
||||
// check containment seriously
|
||||
if ( If_CutCheckDominance( pTemp, pCut ) )
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Merges two cuts.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int If_CutMergeOrdered( If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC )
|
||||
{
|
||||
int i, k, c;
|
||||
assert( pC0->nLeaves >= pC1->nLeaves );
|
||||
// the case of the largest cut sizes
|
||||
if ( pC0->nLeaves == pC->nLimit && pC1->nLeaves == pC->nLimit )
|
||||
{
|
||||
for ( i = 0; i < (int)pC0->nLeaves; i++ )
|
||||
if ( pC0->pLeaves[i] != pC1->pLeaves[i] )
|
||||
return 0;
|
||||
for ( i = 0; i < (int)pC0->nLeaves; i++ )
|
||||
pC->pLeaves[i] = pC0->pLeaves[i];
|
||||
pC->nLeaves = pC0->nLeaves;
|
||||
return 1;
|
||||
}
|
||||
// the case when one of the cuts is the largest
|
||||
if ( pC0->nLeaves == pC->nLimit )
|
||||
{
|
||||
for ( i = 0; i < (int)pC1->nLeaves; i++ )
|
||||
{
|
||||
for ( k = (int)pC0->nLeaves - 1; k >= 0; k-- )
|
||||
if ( pC0->pLeaves[k] == pC1->pLeaves[i] )
|
||||
break;
|
||||
if ( k == -1 ) // did not find
|
||||
return 0;
|
||||
}
|
||||
for ( i = 0; i < (int)pC0->nLeaves; i++ )
|
||||
pC->pLeaves[i] = pC0->pLeaves[i];
|
||||
pC->nLeaves = pC0->nLeaves;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// compare two cuts with different numbers
|
||||
i = k = 0;
|
||||
for ( c = 0; c < (int)pC->nLimit; c++ )
|
||||
{
|
||||
if ( k == (int)pC1->nLeaves )
|
||||
{
|
||||
if ( i == (int)pC0->nLeaves )
|
||||
{
|
||||
pC->nLeaves = c;
|
||||
return 1;
|
||||
}
|
||||
pC->pLeaves[c] = pC0->pLeaves[i++];
|
||||
continue;
|
||||
}
|
||||
if ( i == (int)pC0->nLeaves )
|
||||
{
|
||||
if ( k == (int)pC1->nLeaves )
|
||||
{
|
||||
pC->nLeaves = c;
|
||||
return 1;
|
||||
}
|
||||
pC->pLeaves[c] = pC1->pLeaves[k++];
|
||||
continue;
|
||||
}
|
||||
if ( pC0->pLeaves[i] < pC1->pLeaves[k] )
|
||||
{
|
||||
pC->pLeaves[c] = pC0->pLeaves[i++];
|
||||
continue;
|
||||
}
|
||||
if ( pC0->pLeaves[i] > pC1->pLeaves[k] )
|
||||
{
|
||||
pC->pLeaves[c] = pC1->pLeaves[k++];
|
||||
continue;
|
||||
}
|
||||
pC->pLeaves[c] = pC0->pLeaves[i++];
|
||||
k++;
|
||||
}
|
||||
if ( i < (int)pC0->nLeaves || k < (int)pC1->nLeaves )
|
||||
return 0;
|
||||
pC->nLeaves = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Merges two cuts.]
|
||||
|
||||
Description [Special case when the cut is known to exist.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int If_CutMergeOrdered2( If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC )
|
||||
{
|
||||
int i, k, c;
|
||||
assert( pC0->nLeaves >= pC1->nLeaves );
|
||||
// copy the first cut
|
||||
for ( i = 0; i < (int)pC0->nLeaves; i++ )
|
||||
pC->pLeaves[i] = pC0->pLeaves[i];
|
||||
pC->nLeaves = pC0->nLeaves;
|
||||
// the case when one of the cuts is the largest
|
||||
if ( pC0->nLeaves == pC->nLimit )
|
||||
return 1;
|
||||
// add nodes of the second cut
|
||||
k = 0;
|
||||
for ( i = 0; i < (int)pC1->nLeaves; i++ )
|
||||
{
|
||||
// find k-th node before which i-th node should be added
|
||||
for ( ; k < (int)pC->nLeaves; k++ )
|
||||
if ( pC->pLeaves[k] >= pC1->pLeaves[i] )
|
||||
break;
|
||||
// check the case when this should be the last node
|
||||
if ( k == (int)pC->nLeaves )
|
||||
{
|
||||
pC->pLeaves[k++] = pC1->pLeaves[i];
|
||||
pC->nLeaves++;
|
||||
continue;
|
||||
}
|
||||
// check the case when equal node is found
|
||||
if ( pC1->pLeaves[i] == pC->pLeaves[k] )
|
||||
continue;
|
||||
// add the node
|
||||
for ( c = (int)pC->nLeaves; c > k; c-- )
|
||||
pC->pLeaves[c] = pC->pLeaves[c-1];
|
||||
pC->pLeaves[k++] = pC1->pLeaves[i];
|
||||
pC->nLeaves++;
|
||||
}
|
||||
assert( pC->nLeaves <= pC->nLimit );
|
||||
for ( i = 1; i < (int)pC->nLeaves; i++ )
|
||||
assert( pC->pLeaves[i-1] < pC->pLeaves[i] );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut )
|
||||
{
|
||||
assert( pCut->nLimit > 0 );
|
||||
// merge the nodes
|
||||
if ( pCut0->nLeaves < pCut1->nLeaves )
|
||||
{
|
||||
if ( !If_CutMergeOrdered( pCut1, pCut0, pCut ) )
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !If_CutMergeOrdered( pCut0, pCut1, pCut ) )
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutCompareDelay( If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
|
||||
{
|
||||
If_Cut_t * pC0 = *ppC0;
|
||||
If_Cut_t * pC1 = *ppC1;
|
||||
if ( pC0->Delay < pC1->Delay - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Delay > pC1->Delay + 0.0001 )
|
||||
return 1;
|
||||
if ( pC0->nLeaves < pC1->nLeaves )
|
||||
return -1;
|
||||
if ( pC0->nLeaves > pC1->nLeaves )
|
||||
return 1;
|
||||
if ( pC0->Area < pC1->Area - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Area > pC1->Area + 0.0001 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutCompareDelayOld( If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
|
||||
{
|
||||
If_Cut_t * pC0 = *ppC0;
|
||||
If_Cut_t * pC1 = *ppC1;
|
||||
if ( pC0->Delay < pC1->Delay - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Delay > pC1->Delay + 0.0001 )
|
||||
return 1;
|
||||
if ( pC0->Area < pC1->Area - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Area > pC1->Area + 0.0001 )
|
||||
return 1;
|
||||
if ( pC0->nLeaves < pC1->nLeaves )
|
||||
return -1;
|
||||
if ( pC0->nLeaves > pC1->nLeaves )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutCompareArea( If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
|
||||
{
|
||||
If_Cut_t * pC0 = *ppC0;
|
||||
If_Cut_t * pC1 = *ppC1;
|
||||
if ( pC0->Area < pC1->Area - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Area > pC1->Area + 0.0001 )
|
||||
return 1;
|
||||
if ( pC0->nLeaves < pC1->nLeaves )
|
||||
return -1;
|
||||
if ( pC0->nLeaves > pC1->nLeaves )
|
||||
return 1;
|
||||
if ( pC0->Delay < pC1->Delay - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Delay > pC1->Delay + 0.0001 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sorts the cuts.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_ManSortCuts( If_Man_t * p, int Mode )
|
||||
{
|
||||
// sort the cuts
|
||||
if ( Mode || p->pPars->fArea ) // area
|
||||
qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareArea );
|
||||
else if ( p->pPars->fFancy )
|
||||
qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelayOld );
|
||||
else
|
||||
qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelay );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes delay.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutDelay( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
float Delay;
|
||||
int i;
|
||||
assert( pCut->nLeaves > 1 );
|
||||
Delay = -IF_FLOAT_LARGE;
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
Delay = IF_MAX( Delay, If_ObjCutBest(pLeaf)->Delay );
|
||||
return Delay + If_CutLutDelay(p, pCut);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area flow.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutFlow( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
float Flow;
|
||||
int i;
|
||||
assert( pCut->nLeaves > 1 );
|
||||
Flow = If_CutLutArea(p, pCut);
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
{
|
||||
if ( pLeaf->nRefs == 0 )
|
||||
Flow += If_ObjCutBest(pLeaf)->Area;
|
||||
else
|
||||
{
|
||||
assert( pLeaf->EstRefs > p->fEpsilon );
|
||||
Flow += If_ObjCutBest(pLeaf)->Area / pLeaf->EstRefs;
|
||||
}
|
||||
}
|
||||
return Flow;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutDeref( If_Man_t * p, If_Cut_t * pCut, int nLevels )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
float Area;
|
||||
int i;
|
||||
Area = If_CutLutArea(p, pCut);
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
{
|
||||
assert( pLeaf->nRefs > 0 );
|
||||
if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) || nLevels == 1 )
|
||||
continue;
|
||||
Area += If_CutDeref( p, If_ObjCutBest(pLeaf), nLevels - 1 );
|
||||
}
|
||||
return Area;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutRef( If_Man_t * p, If_Cut_t * pCut, int nLevels )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
float Area;
|
||||
int i;
|
||||
Area = If_CutLutArea(p, pCut);
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
{
|
||||
assert( pLeaf->nRefs >= 0 );
|
||||
if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) || nLevels == 1 )
|
||||
continue;
|
||||
Area += If_CutRef( p, If_ObjCutBest(pLeaf), nLevels - 1 );
|
||||
}
|
||||
return Area;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prints one cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_CutPrint( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
unsigned i;
|
||||
printf( "{" );
|
||||
for ( i = 0; i < pCut->nLeaves; i++ )
|
||||
printf( " %d", pCut->pLeaves[i] );
|
||||
printf( " }\n" );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut, int nLevels )
|
||||
{
|
||||
float aResult, aResult2;
|
||||
assert( pCut->nLeaves > 1 );
|
||||
aResult2 = If_CutRef( p, pCut, nLevels );
|
||||
aResult = If_CutDeref( p, pCut, nLevels );
|
||||
assert( aResult == aResult2 );
|
||||
return aResult;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut, int nLevels )
|
||||
{
|
||||
float aResult, aResult2;
|
||||
assert( pCut->nLeaves > 1 );
|
||||
aResult2 = If_CutDeref( p, pCut, nLevels );
|
||||
aResult = If_CutRef( p, pCut, nLevels );
|
||||
assert( aResult == aResult2 );
|
||||
return aResult;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc )
|
||||
{
|
||||
int * pLeaves;
|
||||
unsigned * pTruth;
|
||||
pLeaves = pCutDest->pLeaves;
|
||||
pTruth = pCutDest->pTruth;
|
||||
*pCutDest = *pCutSrc;
|
||||
pCutDest->pLeaves = pLeaves;
|
||||
pCutDest->pTruth = pTruth;
|
||||
memcpy( pCutDest->pLeaves, pCutSrc->pLeaves, sizeof(int) * pCutSrc->nLeaves );
|
||||
if ( pCutSrc->pTruth )
|
||||
memcpy( pCutDest->pTruth, pCutSrc->pTruth, sizeof(unsigned) * If_CutTruthWords(pCutSrc->nLimit) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
|
|
|
|||
|
|
@ -57,9 +57,20 @@ If_Man_t * If_ManStart( If_Par_t * pPars )
|
|||
p->vMapped = Vec_PtrAlloc( 100 );
|
||||
p->vTemp = Vec_PtrAlloc( 100 );
|
||||
// prepare the memory manager
|
||||
p->nEntrySize = sizeof(If_Obj_t) + p->pPars->nCutsMax * (sizeof(If_Cut_t) + sizeof(int) * p->pPars->nLutSize);
|
||||
p->nEntryBase = sizeof(If_Obj_t) + p->pPars->nCutsMax * (sizeof(If_Cut_t));
|
||||
p->nTruthSize = p->pPars->fTruth? If_CutTruthWords( p->pPars->nLutSize ) : 0;
|
||||
p->nCutSize = sizeof(If_Cut_t) + sizeof(int) * p->pPars->nLutSize + sizeof(unsigned) * p->nTruthSize;
|
||||
p->nEntrySize = sizeof(If_Obj_t) + p->pPars->nCutsMax * p->nCutSize;
|
||||
p->nEntryBase = sizeof(If_Obj_t) + p->pPars->nCutsMax * sizeof(If_Cut_t);
|
||||
p->pMem = Mem_FixedStart( p->nEntrySize );
|
||||
// report expected memory usage
|
||||
if ( p->pPars->fVerbose )
|
||||
printf( "Memory (bytes): Truth = %3d. Cut = %3d. Entry = %4d. Total = %.2f Mb / 1K AIG nodes\n",
|
||||
4 * p->nTruthSize, p->nCutSize, p->nEntrySize, 1000.0 * p->nEntrySize / (1<<20) );
|
||||
// room for temporary truth tables
|
||||
p->puTemp[0] = p->pPars->fTruth? ALLOC( unsigned, 4 * p->nTruthSize ) : NULL;
|
||||
p->puTemp[1] = p->puTemp[0] + p->nTruthSize;
|
||||
p->puTemp[2] = p->puTemp[1] + p->nTruthSize;
|
||||
p->puTemp[3] = p->puTemp[2] + p->nTruthSize;
|
||||
// create the constant node
|
||||
p->pConst1 = If_ManSetupObj( p );
|
||||
p->pConst1->Type = IF_CONST1;
|
||||
|
|
@ -100,6 +111,7 @@ void If_ManStop( If_Man_t * p )
|
|||
for ( i = 1; i < 1 + p->pPars->nCutsMax * p->pPars->nCutsMax; i++ )
|
||||
if ( pTemp > p->ppCuts[i] )
|
||||
pTemp = p->ppCuts[i];
|
||||
FREE( p->puTemp[0] );
|
||||
free( pTemp );
|
||||
free( p->ppCuts );
|
||||
free( p );
|
||||
|
|
@ -200,7 +212,12 @@ If_Obj_t * If_ManSetupObj( If_Man_t * p )
|
|||
// organize memory
|
||||
pArrays = (int *)((char *)pObj + p->nEntryBase);
|
||||
for ( i = 0; i < p->pPars->nCutsMax; i++ )
|
||||
pObj->Cuts[i].pLeaves = pArrays + i * p->pPars->nLutSize;
|
||||
{
|
||||
pCut = pObj->Cuts + i;
|
||||
pCut->nLimit = p->pPars->nLutSize;
|
||||
pCut->pLeaves = pArrays + i * p->pPars->nLutSize;
|
||||
pCut->pTruth = pArrays + p->pPars->nCutsMax * p->pPars->nLutSize + i * p->nTruthSize;
|
||||
}
|
||||
// assign ID and save
|
||||
pObj->Id = Vec_PtrSize(p->vObjs);
|
||||
Vec_PtrPush( p->vObjs, pObj );
|
||||
|
|
@ -230,22 +247,24 @@ If_Obj_t * If_ManSetupObj( If_Man_t * p )
|
|||
If_Cut_t ** If_ManSetupCuts( If_Man_t * p )
|
||||
{
|
||||
If_Cut_t ** pCutStore;
|
||||
int * pArrays, nCutSize, nCutsTotal, i;
|
||||
int * pArrays, nCutsTotal, i;
|
||||
// decide how many cuts to alloc
|
||||
nCutsTotal = 1 + p->pPars->nCutsMax * p->pPars->nCutsMax;
|
||||
// figure out the cut size
|
||||
nCutSize = sizeof(If_Cut_t) + sizeof(int) * p->pPars->nLutSize;
|
||||
// allocate and clean space for cuts
|
||||
pCutStore = (If_Cut_t **)ALLOC( If_Cut_t *, (nCutsTotal + 1) );
|
||||
memset( pCutStore, 0, sizeof(If_Cut_t *) * (nCutsTotal + 1) );
|
||||
pCutStore[0] = (If_Cut_t *)ALLOC( char, nCutSize * nCutsTotal );
|
||||
memset( pCutStore[0], 0, nCutSize * nCutsTotal );
|
||||
for ( i = 1; i < nCutsTotal; i++ )
|
||||
pCutStore[i] = (If_Cut_t *)((char *)pCutStore[0] + sizeof(If_Cut_t) * i);
|
||||
// assign room for cut leaves
|
||||
pCutStore[0] = (If_Cut_t *)ALLOC( char, p->nCutSize * nCutsTotal );
|
||||
memset( pCutStore[0], 0, p->nCutSize * nCutsTotal );
|
||||
// assign cut paramters and space for the cut leaves
|
||||
assert( sizeof(int) == sizeof(unsigned) );
|
||||
pArrays = (int *)((char *)pCutStore[0] + sizeof(If_Cut_t) * nCutsTotal);
|
||||
for ( i = 0; i < nCutsTotal; i++ )
|
||||
{
|
||||
pCutStore[i] = (If_Cut_t *)((char *)pCutStore[0] + sizeof(If_Cut_t) * i);
|
||||
pCutStore[i]->nLimit = p->pPars->nLutSize;
|
||||
pCutStore[i]->pLeaves = pArrays + i * p->pPars->nLutSize;
|
||||
pCutStore[i]->pTruth = pArrays + nCutsTotal * p->pPars->nLutSize + i * p->nTruthSize;
|
||||
}
|
||||
return pCutStore;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,567 +57,6 @@ static inline int If_WordCountOnes( unsigned uWord )
|
|||
return (uWord & 0x0000FFFF) + (uWord>>16);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if pDom is contained in pCut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int If_CutCheckDominance( If_Cut_t * pDom, If_Cut_t * pCut )
|
||||
{
|
||||
int i, k;
|
||||
for ( i = 0; i < (int)pDom->nLeaves; i++ )
|
||||
{
|
||||
for ( k = 0; k < (int)pCut->nLeaves; k++ )
|
||||
if ( pDom->pLeaves[i] == pCut->pLeaves[k] )
|
||||
break;
|
||||
if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut
|
||||
return 0;
|
||||
}
|
||||
// every node in pDom is contained in pCut
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if pDom is equal to pCut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int If_CutCheckEquality( If_Cut_t * pDom, If_Cut_t * pCut )
|
||||
{
|
||||
int i;
|
||||
if ( (int)pDom->nLeaves != (int)pCut->nLeaves )
|
||||
return 0;
|
||||
for ( i = 0; i < (int)pDom->nLeaves; i++ )
|
||||
if ( pDom->pLeaves[i] != pCut->pLeaves[i] )
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if the cut is contained.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutFilter( If_Man_t * p, If_Cut_t * pCut, int Mode )
|
||||
{
|
||||
If_Cut_t * pTemp;
|
||||
int i;
|
||||
for ( i = 0; i < p->nCuts; i++ )
|
||||
{
|
||||
pTemp = p->ppCuts[i];
|
||||
if ( pTemp->nLeaves > pCut->nLeaves )
|
||||
{
|
||||
// continue;
|
||||
// skip the non-contained cuts
|
||||
if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
|
||||
continue;
|
||||
// check containment seriously
|
||||
if ( If_CutCheckDominance( pCut, pTemp ) )
|
||||
{
|
||||
// removed contained cut
|
||||
p->ppCuts[i] = p->ppCuts[p->nCuts-1];
|
||||
p->ppCuts[p->nCuts-1] = pTemp;
|
||||
p->nCuts--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// skip the non-contained cuts
|
||||
if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
|
||||
continue;
|
||||
// check containment seriously
|
||||
if ( If_CutCheckDominance( pTemp, pCut ) )
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Merges two cuts.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int If_CutMergeOrdered( If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC, int nLimit )
|
||||
{
|
||||
int i, k, c;
|
||||
assert( pC0->nLeaves >= pC1->nLeaves );
|
||||
// the case of the largest cut sizes
|
||||
if ( pC0->nLeaves == nLimit && pC1->nLeaves == nLimit )
|
||||
{
|
||||
for ( i = 0; i < pC0->nLeaves; i++ )
|
||||
if ( pC0->pLeaves[i] != pC1->pLeaves[i] )
|
||||
return 0;
|
||||
for ( i = 0; i < pC0->nLeaves; i++ )
|
||||
pC->pLeaves[i] = pC0->pLeaves[i];
|
||||
pC->nLeaves = pC0->nLeaves;
|
||||
return 1;
|
||||
}
|
||||
// the case when one of the cuts is the largest
|
||||
if ( pC0->nLeaves == nLimit )
|
||||
{
|
||||
for ( i = 0; i < pC1->nLeaves; i++ )
|
||||
{
|
||||
for ( k = pC0->nLeaves - 1; k >= 0; k-- )
|
||||
if ( pC0->pLeaves[k] == pC1->pLeaves[i] )
|
||||
break;
|
||||
if ( k == -1 ) // did not find
|
||||
return 0;
|
||||
}
|
||||
for ( i = 0; i < pC0->nLeaves; i++ )
|
||||
pC->pLeaves[i] = pC0->pLeaves[i];
|
||||
pC->nLeaves = pC0->nLeaves;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// compare two cuts with different numbers
|
||||
i = k = 0;
|
||||
for ( c = 0; c < nLimit; c++ )
|
||||
{
|
||||
if ( k == pC1->nLeaves )
|
||||
{
|
||||
if ( i == pC0->nLeaves )
|
||||
{
|
||||
pC->nLeaves = c;
|
||||
return 1;
|
||||
}
|
||||
pC->pLeaves[c] = pC0->pLeaves[i++];
|
||||
continue;
|
||||
}
|
||||
if ( i == pC0->nLeaves )
|
||||
{
|
||||
if ( k == pC1->nLeaves )
|
||||
{
|
||||
pC->nLeaves = c;
|
||||
return 1;
|
||||
}
|
||||
pC->pLeaves[c] = pC1->pLeaves[k++];
|
||||
continue;
|
||||
}
|
||||
if ( pC0->pLeaves[i] < pC1->pLeaves[k] )
|
||||
{
|
||||
pC->pLeaves[c] = pC0->pLeaves[i++];
|
||||
continue;
|
||||
}
|
||||
if ( pC0->pLeaves[i] > pC1->pLeaves[k] )
|
||||
{
|
||||
pC->pLeaves[c] = pC1->pLeaves[k++];
|
||||
continue;
|
||||
}
|
||||
pC->pLeaves[c] = pC0->pLeaves[i++];
|
||||
k++;
|
||||
}
|
||||
if ( i < pC0->nLeaves || k < pC1->nLeaves )
|
||||
return 0;
|
||||
pC->nLeaves = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Merges two cuts.]
|
||||
|
||||
Description [Special case when the cut is known to exist.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int If_CutMergeOrdered2( If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC, int nLimit )
|
||||
{
|
||||
int i, k, c;
|
||||
assert( pC0->nLeaves >= pC1->nLeaves );
|
||||
// copy the first cut
|
||||
for ( i = 0; i < pC0->nLeaves; i++ )
|
||||
pC->pLeaves[i] = pC0->pLeaves[i];
|
||||
pC->nLeaves = pC0->nLeaves;
|
||||
// the case when one of the cuts is the largest
|
||||
if ( pC0->nLeaves == nLimit )
|
||||
return 1;
|
||||
// add nodes of the second cut
|
||||
k = 0;
|
||||
for ( i = 0; i < pC1->nLeaves; i++ )
|
||||
{
|
||||
// find k-th node before which i-th node should be added
|
||||
for ( ; k < pC->nLeaves; k++ )
|
||||
if ( pC->pLeaves[k] >= pC1->pLeaves[i] )
|
||||
break;
|
||||
// check the case when this should be the last node
|
||||
if ( k == pC->nLeaves )
|
||||
{
|
||||
pC->pLeaves[k++] = pC1->pLeaves[i];
|
||||
pC->nLeaves++;
|
||||
continue;
|
||||
}
|
||||
// check the case when equal node is found
|
||||
if ( pC1->pLeaves[i] == pC->pLeaves[k] )
|
||||
continue;
|
||||
// add the node
|
||||
for ( c = pC->nLeaves; c > k; c-- )
|
||||
pC->pLeaves[c] = pC->pLeaves[c-1];
|
||||
pC->pLeaves[k++] = pC1->pLeaves[i];
|
||||
pC->nLeaves++;
|
||||
}
|
||||
assert( pC->nLeaves <= nLimit );
|
||||
for ( i = 1; i < pC->nLeaves; i++ )
|
||||
assert( pC->pLeaves[i-1] < pC->pLeaves[i] );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut, int nLimit )
|
||||
{
|
||||
// merge the nodes
|
||||
if ( pCut0->nLeaves < pCut1->nLeaves )
|
||||
{
|
||||
if ( !If_CutMergeOrdered( pCut1, pCut0, pCut, nLimit ) )
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !If_CutMergeOrdered( pCut0, pCut1, pCut, nLimit ) )
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutCompareDelay( If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
|
||||
{
|
||||
If_Cut_t * pC0 = *ppC0;
|
||||
If_Cut_t * pC1 = *ppC1;
|
||||
if ( pC0->Delay < pC1->Delay - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Delay > pC1->Delay + 0.0001 )
|
||||
return 1;
|
||||
if ( pC0->nLeaves < pC1->nLeaves )
|
||||
return -1;
|
||||
if ( pC0->nLeaves > pC1->nLeaves )
|
||||
return 1;
|
||||
if ( pC0->Area < pC1->Area - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Area > pC1->Area + 0.0001 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutCompareDelayOld( If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
|
||||
{
|
||||
If_Cut_t * pC0 = *ppC0;
|
||||
If_Cut_t * pC1 = *ppC1;
|
||||
if ( pC0->Delay < pC1->Delay - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Delay > pC1->Delay + 0.0001 )
|
||||
return 1;
|
||||
if ( pC0->Area < pC1->Area - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Area > pC1->Area + 0.0001 )
|
||||
return 1;
|
||||
if ( pC0->nLeaves < pC1->nLeaves )
|
||||
return -1;
|
||||
if ( pC0->nLeaves > pC1->nLeaves )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the object for FPGA mapping.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutCompareArea( If_Cut_t ** ppC0, If_Cut_t ** ppC1 )
|
||||
{
|
||||
If_Cut_t * pC0 = *ppC0;
|
||||
If_Cut_t * pC1 = *ppC1;
|
||||
if ( pC0->Area < pC1->Area - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Area > pC1->Area + 0.0001 )
|
||||
return 1;
|
||||
if ( pC0->nLeaves < pC1->nLeaves )
|
||||
return -1;
|
||||
if ( pC0->nLeaves > pC1->nLeaves )
|
||||
return 1;
|
||||
if ( pC0->Delay < pC1->Delay - 0.0001 )
|
||||
return -1;
|
||||
if ( pC0->Delay > pC1->Delay + 0.0001 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Sorts the cuts.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_ManSortCuts( If_Man_t * p, int Mode )
|
||||
{
|
||||
// sort the cuts
|
||||
if ( Mode || p->pPars->fArea ) // area
|
||||
qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareArea );
|
||||
else if ( p->pPars->fFancy )
|
||||
qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelayOld );
|
||||
else
|
||||
qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelay );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes delay.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutDelay( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
float Delay;
|
||||
int i;
|
||||
assert( pCut->nLeaves > 1 );
|
||||
Delay = -IF_FLOAT_LARGE;
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
Delay = IF_MAX( Delay, If_ObjCutBest(pLeaf)->Delay );
|
||||
return Delay + If_CutLutDelay(p, pCut);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area flow.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutFlow( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
float Flow;
|
||||
int i;
|
||||
assert( pCut->nLeaves > 1 );
|
||||
Flow = If_CutLutArea(p, pCut);
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
{
|
||||
if ( pLeaf->nRefs == 0 )
|
||||
Flow += If_ObjCutBest(pLeaf)->Area;
|
||||
else
|
||||
{
|
||||
assert( pLeaf->EstRefs > p->fEpsilon );
|
||||
Flow += If_ObjCutBest(pLeaf)->Area / pLeaf->EstRefs;
|
||||
}
|
||||
}
|
||||
return Flow;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutDeref( If_Man_t * p, If_Cut_t * pCut, int nLevels )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
float Area;
|
||||
int i;
|
||||
Area = If_CutLutArea(p, pCut);
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
{
|
||||
assert( pLeaf->nRefs > 0 );
|
||||
if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) || nLevels == 1 )
|
||||
continue;
|
||||
Area += If_CutDeref( p, If_ObjCutBest(pLeaf), nLevels - 1 );
|
||||
}
|
||||
return Area;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutRef( If_Man_t * p, If_Cut_t * pCut, int nLevels )
|
||||
{
|
||||
If_Obj_t * pLeaf;
|
||||
float Area;
|
||||
int i;
|
||||
Area = If_CutLutArea(p, pCut);
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
{
|
||||
assert( pLeaf->nRefs >= 0 );
|
||||
if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) || nLevels == 1 )
|
||||
continue;
|
||||
Area += If_CutRef( p, If_ObjCutBest(pLeaf), nLevels - 1 );
|
||||
}
|
||||
return Area;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prints one cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_CutPrint( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
int i;
|
||||
printf( "{" );
|
||||
for ( i = 0; i < pCut->nLeaves; i++ )
|
||||
printf( " %d", pCut->pLeaves[i] );
|
||||
printf( " }\n" );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut, int nLevels )
|
||||
{
|
||||
float aResult, aResult2;
|
||||
assert( pCut->nLeaves > 1 );
|
||||
aResult2 = If_CutRef( p, pCut, nLevels );
|
||||
aResult = If_CutDeref( p, pCut, nLevels );
|
||||
assert( aResult == aResult2 );
|
||||
return aResult;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut, int nLevels )
|
||||
{
|
||||
float aResult, aResult2;
|
||||
assert( pCut->nLeaves > 1 );
|
||||
aResult2 = If_CutDeref( p, pCut, nLevels );
|
||||
aResult = If_CutRef( p, pCut, nLevels );
|
||||
assert( aResult == aResult2 );
|
||||
return aResult;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes area of the first level.]
|
||||
|
||||
Description [The cut need to be derefed.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc )
|
||||
{
|
||||
int * pArray;
|
||||
pArray = pCutDest->pLeaves;
|
||||
*pCutDest = *pCutSrc;
|
||||
pCutDest->pLeaves = pArray;
|
||||
memcpy( pCutDest->pLeaves, pCutSrc->pLeaves, sizeof(int) * pCutSrc->nLeaves );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Finds the best cut.]
|
||||
|
|
@ -632,7 +71,7 @@ void If_CutCopy( If_Cut_t * pCutDest, If_Cut_t * pCutSrc )
|
|||
void If_ObjPerformMapping( If_Man_t * p, If_Obj_t * pObj, int Mode )
|
||||
{
|
||||
If_Cut_t * pCut0, * pCut1, * pCut;
|
||||
int i, k, iCut;
|
||||
int i, k, iCut, Temp;
|
||||
|
||||
// prepare
|
||||
if ( Mode == 0 )
|
||||
|
|
@ -670,29 +109,34 @@ void If_ObjPerformMapping( If_Man_t * p, If_Obj_t * pObj, int Mode )
|
|||
if ( Mode && (pCut0->Delay > pObj->Required + p->fEpsilon || pCut1->Delay > pObj->Required + p->fEpsilon) )
|
||||
continue;
|
||||
// merge the nodes
|
||||
if ( !If_CutMerge( pCut0, pCut1, pCut, p->pPars->nLutSize ) )
|
||||
if ( !If_CutMerge( pCut0, pCut1, pCut ) )
|
||||
continue;
|
||||
// check if this cut is contained in any of the available cuts
|
||||
pCut->uSign = pCut0->uSign | pCut1->uSign;
|
||||
if ( If_CutFilter( p, pCut, Mode ) )
|
||||
if ( If_CutFilter( p, pCut ) )
|
||||
continue;
|
||||
// check if the cut satisfies the required times
|
||||
pCut->Delay = If_CutDelay( p, pCut );
|
||||
if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon )
|
||||
continue;
|
||||
// the cuts have been successfully merged
|
||||
pCut->pOne = pCut0; pCut->fCompl0 = pObj->fCompl0;
|
||||
pCut->pTwo = pCut1; pCut->fCompl1 = pObj->fCompl1;
|
||||
// pCut->Phase = ...
|
||||
// pCut->Phase = (char)(int)If_CutAreaDerefed( p, pCut, 1 );
|
||||
pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, 100 ) : If_CutFlow( p, pCut );
|
||||
p->nCutsMerged++;
|
||||
// compute the truth table
|
||||
if ( p->pPars->fTruth )
|
||||
If_CutComputeTruth( p, pCut, pCut0, pCut1, pObj->fCompl0, pObj->fCompl1 );
|
||||
// compute the application-specific cost and depth
|
||||
Temp = p->pPars->pFuncCost? p->pPars->pFuncCost(If_CutTruth(pCut), pCut->nLimit) : 0;
|
||||
pCut->Cost = (Temp & 0xffff); pCut->Depth = (Temp >> 16);
|
||||
// compute area of the cut (this area may depend on the application specific cost)
|
||||
pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, 100 ) : If_CutFlow( p, pCut );
|
||||
// make sure the cut is the last one (after filtering it may not be so)
|
||||
assert( pCut == p->ppCuts[iCut] );
|
||||
p->ppCuts[iCut] = p->ppCuts[p->nCuts];
|
||||
p->ppCuts[p->nCuts] = pCut;
|
||||
// count the cut
|
||||
p->nCuts++;
|
||||
p->nCutsMerged++;
|
||||
// prepare room for the next cut
|
||||
iCut = ++p->nCuts;
|
||||
iCut = p->nCuts;
|
||||
pCut = p->ppCuts[iCut];
|
||||
}
|
||||
//printf( "%d ", p->nCuts );
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [ifSelect.c]
|
||||
FileName [ifPrepro.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapping based on priority cuts.]
|
||||
|
||||
Synopsis [Selects what mapping to use.]
|
||||
Synopsis [Selects the starting mapping.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
Date [Ver. 1.0. Started - November 21, 2006.]
|
||||
|
||||
Revision [$Id: ifSelect.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
|
||||
Revision [$Id: ifPrepro.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
|
@ -522,11 +522,11 @@ void If_ManImproveNodeReduce( If_Man_t * p, If_Obj_t * pObj, int nLimit )
|
|||
|
||||
// merge the cuts
|
||||
pCutR = p->ppCuts[0];
|
||||
RetValue = If_CutMerge( pCut0, pCut1, pCutR, nLimit );
|
||||
RetValue = If_CutMerge( pCut0, pCut1, pCutR );
|
||||
// try very simple cut
|
||||
if ( !RetValue )
|
||||
{
|
||||
RetValue = If_CutMerge( If_ObjCutTriv(pFanin0), If_ObjCutTriv(pFanin1), pCutR, nLimit );
|
||||
RetValue = If_CutMerge( If_ObjCutTriv(pFanin0), If_ObjCutTriv(pFanin1), pCutR );
|
||||
assert( RetValue == 1 );
|
||||
}
|
||||
if ( RetValue )
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ int If_ManPerformMappingSeq( If_Man_t * p )
|
|||
***********************************************************************/
|
||||
void If_CutLift( If_Cut_t * pCut )
|
||||
{
|
||||
int i;
|
||||
unsigned i;
|
||||
for ( i = 0; i < pCut->nLeaves; i++ )
|
||||
pCut->pLeaves[i] = ((pCut->pLeaves[i] >> 8) << 8) | ((pCut->pLeaves[i] & 255) + 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [ifTruth.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [FPGA mapping based on priority cuts.]
|
||||
|
||||
Synopsis [Computation of truth tables of the cuts.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - November 21, 2006.]
|
||||
|
||||
Revision [$Id: ifTruth.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "if.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline unsigned Cut_TruthPhase( If_Cut_t * pCut, If_Cut_t * pCut1 )
|
||||
{
|
||||
unsigned uPhase = 0;
|
||||
int i, k;
|
||||
for ( i = k = 0; i < (int)pCut->nLeaves; i++ )
|
||||
{
|
||||
if ( k == (int)pCut1->nLeaves )
|
||||
break;
|
||||
if ( pCut->pLeaves[i] < pCut1->pLeaves[k] )
|
||||
continue;
|
||||
assert( pCut->pLeaves[i] == pCut1->pLeaves[k] );
|
||||
uPhase |= (1 << i);
|
||||
k++;
|
||||
}
|
||||
return uPhase;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs truth table computation.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 )
|
||||
{
|
||||
// permute the first table
|
||||
if ( fCompl0 )
|
||||
Extra_TruthNot( p->puTemp[0], If_CutTruth(pCut0), pCut->nLimit );
|
||||
else
|
||||
Extra_TruthCopy( p->puTemp[0], If_CutTruth(pCut0), pCut->nLimit );
|
||||
Extra_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nLeaves, pCut->nLimit, Cut_TruthPhase(pCut, pCut0) );
|
||||
// permute the second table
|
||||
if ( fCompl1 )
|
||||
Extra_TruthNot( p->puTemp[1], If_CutTruth(pCut1), pCut->nLimit );
|
||||
else
|
||||
Extra_TruthCopy( p->puTemp[1], If_CutTruth(pCut1), pCut->nLimit );
|
||||
Extra_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nLeaves, pCut->nLimit, Cut_TruthPhase(pCut, pCut1) );
|
||||
// produce the resulting table
|
||||
if ( pCut->fCompl )
|
||||
Extra_TruthNand( If_CutTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nLimit );
|
||||
else
|
||||
Extra_TruthAnd( If_CutTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nLimit );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
|
@ -2,7 +2,8 @@ SRC += src/map/if/ifCore.c \
|
|||
src/map/if/ifCut.c \
|
||||
src/map/if/ifMan.c \
|
||||
src/map/if/ifMap.c \
|
||||
src/map/if/ifPrepro.c \
|
||||
src/map/if/ifReduce.c \
|
||||
src/map/if/ifSelect.c \
|
||||
src/map/if/ifSeq.c \
|
||||
src/map/if/ifTruth.c \
|
||||
src/map/if/ifUtil.c
|
||||
|
|
|
|||
Loading…
Reference in New Issue