summaryrefslogtreecommitdiffstats
path: root/src/opt
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2008-01-30 20:01:00 -0800
committerAlan Mishchenko <alanmi@berkeley.edu>2008-01-30 20:01:00 -0800
commit0c6505a26a537dc911b6566f82d759521e527c08 (patch)
treef2687995efd4943fe3b1307fce7ef5942d0a57b3 /src/opt
parent4d30a1e4f1edecff86d5066ce4653a370e59e5e1 (diff)
downloadabc-0c6505a26a537dc911b6566f82d759521e527c08.tar.gz
abc-0c6505a26a537dc911b6566f82d759521e527c08.tar.bz2
abc-0c6505a26a537dc911b6566f82d759521e527c08.zip
Version abc80130_2
Diffstat (limited to 'src/opt')
-rw-r--r--src/opt/cut/abcCut.c492
-rw-r--r--src/opt/cut/cut.h124
-rw-r--r--src/opt/cut/cutApi.c197
-rw-r--r--src/opt/cut/cutCut.c359
-rw-r--r--src/opt/cut/cutExpand.c184
-rw-r--r--src/opt/cut/cutInt.h79
-rw-r--r--src/opt/cut/cutList.h120
-rw-r--r--src/opt/cut/cutMan.c243
-rw-r--r--src/opt/cut/cutMerge.c11
-rw-r--r--src/opt/cut/cutNode.c1072
-rw-r--r--src/opt/cut/cutOracle.c428
-rw-r--r--src/opt/cut/cutPre22.c988
-rw-r--r--src/opt/cut/cutSeq.c184
-rw-r--r--src/opt/cut/cutTable.c253
-rw-r--r--src/opt/cut/cutTruth.c314
-rw-r--r--src/opt/cut/module.make7
-rw-r--r--src/opt/dec/dec.h118
-rw-r--r--src/opt/dec/decAbc.c154
-rw-r--r--src/opt/dec/decFactor.c18
-rw-r--r--src/opt/dec/decMan.c2
-rw-r--r--src/opt/dec/decPrint.c67
-rw-r--r--src/opt/dec/decUtil.c2
-rw-r--r--src/opt/fret/fretFlow.c696
-rw-r--r--src/opt/fret/fretInit.c762
-rw-r--r--src/opt/fret/fretMain.c1059
-rw-r--r--src/opt/fret/fretTime.c763
-rw-r--r--src/opt/fret/fretime.h165
-rw-r--r--src/opt/fret/module.make5
-rw-r--r--src/opt/fxu/fxu.c19
-rw-r--r--src/opt/fxu/fxu.h21
-rw-r--r--src/opt/fxu/fxuCreate.c46
-rw-r--r--src/opt/fxu/fxuHeapD.c2
-rw-r--r--src/opt/fxu/fxuHeapS.c2
-rw-r--r--src/opt/fxu/fxuInt.h12
-rw-r--r--src/opt/fxu/fxuList.c2
-rw-r--r--src/opt/fxu/fxuMatrix.c4
-rw-r--r--src/opt/fxu/fxuPair.c2
-rw-r--r--src/opt/fxu/fxuPrint.c2
-rw-r--r--src/opt/fxu/fxuReduce.c12
-rw-r--r--src/opt/fxu/fxuSelect.c2
-rw-r--r--src/opt/fxu/fxuSingle.c140
-rw-r--r--src/opt/fxu/fxuUpdate.c5
-rw-r--r--src/opt/lpk/lpk.h84
-rw-r--r--src/opt/lpk/lpkAbcDec.c290
-rw-r--r--src/opt/lpk/lpkAbcDsd.c603
-rw-r--r--src/opt/lpk/lpkAbcMux.c235
-rw-r--r--src/opt/lpk/lpkAbcUtil.c244
-rw-r--r--src/opt/lpk/lpkCore.c659
-rw-r--r--src/opt/lpk/lpkCut.c683
-rw-r--r--src/opt/lpk/lpkInt.h246
-rw-r--r--src/opt/lpk/lpkMan.c122
-rw-r--r--src/opt/lpk/lpkMap.c205
-rw-r--r--src/opt/lpk/lpkMulti.c495
-rw-r--r--src/opt/lpk/lpkMux.c247
-rw-r--r--src/opt/lpk/lpkSets.c440
-rw-r--r--src/opt/lpk/lpk_.c48
-rw-r--r--src/opt/lpk/module.make11
-rw-r--r--src/opt/res/module.make7
-rw-r--r--src/opt/res/res.h75
-rw-r--r--src/opt/res/resCore.c419
-rw-r--r--src/opt/res/resDivs.c285
-rw-r--r--src/opt/res/resFilter.c434
-rw-r--r--src/opt/res/resInt.h137
-rw-r--r--src/opt/res/resSat.c407
-rw-r--r--src/opt/res/resSim.c790
-rw-r--r--src/opt/res/resSim_old.c521
-rw-r--r--src/opt/res/resStrash.c117
-rw-r--r--src/opt/res/resWin.c485
-rw-r--r--src/opt/res/res_.c50
-rw-r--r--src/opt/ret/module.make8
-rw-r--r--src/opt/ret/retArea.c540
-rw-r--r--src/opt/ret/retCore.c132
-rw-r--r--src/opt/ret/retDelay.c305
-rw-r--r--src/opt/ret/retFlow.c783
-rw-r--r--src/opt/ret/retIncrem.c464
-rw-r--r--src/opt/ret/retInit.c349
-rw-r--r--src/opt/ret/retInt.h80
-rw-r--r--src/opt/ret/retLvalue.c395
-rw-r--r--src/opt/ret/ret_.c48
-rw-r--r--src/opt/rwr/rwr.h40
-rw-r--r--src/opt/rwr/rwrDec.c7
-rw-r--r--src/opt/rwr/rwrEva.c431
-rw-r--r--src/opt/rwr/rwrExp.c2
-rw-r--r--src/opt/rwr/rwrLib.c2
-rw-r--r--src/opt/rwr/rwrMan.c79
-rw-r--r--src/opt/rwr/rwrPrint.c33
-rw-r--r--src/opt/rwr/rwrTemp.c121
-rw-r--r--src/opt/rwr/rwrUtil.c2
-rw-r--r--src/opt/sim/module.make1
-rw-r--r--src/opt/sim/sim.h38
-rw-r--r--src/opt/sim/simMan.c43
-rw-r--r--src/opt/sim/simSat.c2
-rw-r--r--src/opt/sim/simSeq.c171
-rw-r--r--src/opt/sim/simSupp.c17
-rw-r--r--src/opt/sim/simSwitch.c6
-rw-r--r--src/opt/sim/simSym.c5
-rw-r--r--src/opt/sim/simSymSat.c8
-rw-r--r--src/opt/sim/simSymSim.c12
-rw-r--r--src/opt/sim/simSymStr.c12
-rw-r--r--src/opt/sim/simUtils.c210
100 files changed, 20668 insertions, 1154 deletions
diff --git a/src/opt/cut/abcCut.c b/src/opt/cut/abcCut.c
new file mode 100644
index 00000000..9bbd5790
--- /dev/null
+++ b/src/opt/cut/abcCut.c
@@ -0,0 +1,492 @@
+/**CFile****************************************************************
+
+ FileName [abcCut.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Interface to cut computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "cut.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq );
+static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq );
+
+
+extern int nTotal, nGood, nEqual;
+
+// temporary
+//Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) { return NULL; }
+Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+ int i;
+ Abc_Obj_t * pObj;
+
+// Abc_NtkForEachCi( pNtk, pObj, i )
+// Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+// if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) )
+ if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) )
+ Vec_IntWriteEntry( vAttrs, pObj->Id, 1 );
+ }
+ return vAttrs;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
+{
+ ProgressBar * pProgress;
+ Cut_Man_t * p;
+ Abc_Obj_t * pObj, * pNode;
+ Vec_Ptr_t * vNodes;
+ Vec_Int_t * vChoices;
+ int i;
+ int clk = clock();
+
+ extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk );
+ extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk );
+
+ nTotal = nGood = nEqual = 0;
+
+ assert( Abc_NtkIsStrash(pNtk) );
+ // start the manager
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ p = Cut_ManStart( pParams );
+ // compute node attributes if local or global cuts are requested
+ if ( pParams->fGlobal || pParams->fLocal )
+ {
+ extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk );
+ Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) );
+ }
+ // prepare for cut dropping
+ if ( pParams->fDrop )
+ Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) );
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( p, pObj->Id );
+ // compute cuts for internal nodes
+ vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs
+ vChoices = Vec_IntAlloc( 100 );
+ pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ // when we reached a CO, it is time to deallocate the cuts
+ if ( Abc_ObjIsCo(pObj) )
+ {
+ if ( pParams->fDrop )
+ Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ continue;
+ }
+ // skip constant node, it has no cuts
+// if ( Abc_NodeIsConst(pObj) )
+// continue;
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // compute the cuts to the internal node
+ Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree );
+ // consider dropping the fanins cuts
+ if ( pParams->fDrop )
+ {
+ Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) );
+ }
+ // add cuts due to choices
+ if ( Abc_AigNodeIsChoice(pObj) )
+ {
+ Vec_IntClear( vChoices );
+ for ( pNode = pObj; pNode; pNode = pNode->pData )
+ Vec_IntPush( vChoices, pNode->Id );
+ Cut_NodeUnionCuts( p, vChoices );
+ }
+ }
+ Extra_ProgressBarStop( pProgress );
+ Vec_PtrFree( vNodes );
+ Vec_IntFree( vChoices );
+PRT( "Total", clock() - clk );
+//Abc_NtkPrintCuts( p, pNtk, 0 );
+// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk );
+
+ // temporary printout of stats
+ if ( nTotal )
+ printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cut computation using the oracle.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p )
+{
+ Abc_Obj_t * pObj;
+ Vec_Ptr_t * vNodes;
+ int i, clk = clock();
+ int fDrop = Cut_OracleReadDrop(p);
+
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // prepare cut droppping
+ if ( fDrop )
+ Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) );
+
+ // set cuts for PIs
+ Abc_NtkForEachCi( pNtk, pObj, i )
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_OracleNodeSetTriv( p, pObj->Id );
+
+ // compute cuts for internal nodes
+ vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ // when we reached a CO, it is time to deallocate the cuts
+ if ( Abc_ObjIsCo(pObj) )
+ {
+ if ( fDrop )
+ Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ continue;
+ }
+ // skip constant node, it has no cuts
+// if ( Abc_NodeIsConst(pObj) )
+// continue;
+ // compute the cuts to the internal node
+ Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
+ Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ // consider dropping the fanins cuts
+ if ( fDrop )
+ {
+ Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) );
+ Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) );
+ }
+ }
+ Vec_PtrFree( vNodes );
+//PRT( "Total", clock() - clk );
+//Abc_NtkPrintCuts_( p, pNtk, 0 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
+{
+/*
+ Cut_Man_t * p;
+ Abc_Obj_t * pObj, * pNode;
+ int i, nIters, fStatus;
+ Vec_Int_t * vChoices;
+ int clk = clock();
+
+ assert( Abc_NtkIsSeq(pNtk) );
+ assert( pParams->fSeq );
+// assert( Abc_NtkIsDfsOrdered(pNtk) );
+
+ // start the manager
+ pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
+ pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk );
+ p = Cut_ManStart( pParams );
+
+ // set cuts for the constant node and the PIs
+ pObj = Abc_AigConst1(pNtk);
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Cut_NodeSetTriv( p, pObj->Id );
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+//printf( "Setting trivial cut %d.\n", pObj->Id );
+ Cut_NodeSetTriv( p, pObj->Id );
+ }
+ // label the cutset nodes and set their number in the array
+ // assign the elementary cuts to the cutset nodes
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ {
+ assert( pObj->fMarkC == 0 );
+ pObj->fMarkC = 1;
+ pObj->pCopy = (Abc_Obj_t *)i;
+ Cut_NodeSetTriv( p, pObj->Id );
+//printf( "Setting trivial cut %d.\n", pObj->Id );
+ }
+
+ // process the nodes
+ vChoices = Vec_IntAlloc( 100 );
+ for ( nIters = 0; nIters < 10; nIters++ )
+ {
+//printf( "ITERATION %d:\n", nIters );
+ // compute the cuts for the internal nodes
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ {
+ Abc_NodeGetCutsSeq( p, pObj, nIters==0 );
+ // add cuts due to choices
+ if ( Abc_AigNodeIsChoice(pObj) )
+ {
+ Vec_IntClear( vChoices );
+ for ( pNode = pObj; pNode; pNode = pNode->pData )
+ Vec_IntPush( vChoices, pNode->Id );
+ Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 );
+ }
+ }
+ // merge the new cuts with the old cuts
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Cut_NodeNewMergeWithOld( p, pObj->Id );
+ Abc_AigForEachAnd( pNtk, pObj, i )
+ Cut_NodeNewMergeWithOld( p, pObj->Id );
+ // for the cutset, transfer temp cuts to new cuts
+ fStatus = 0;
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i );
+ if ( fStatus == 0 )
+ break;
+ }
+ Vec_IntFree( vChoices );
+
+ // if the status is not finished, transfer new to old for the cutset
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ Cut_NodeNewMergeWithOld( p, pObj->Id );
+
+ // transfer the old cuts to the new positions
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Cut_NodeOldTransferToNew( p, pObj->Id );
+
+ // unlabel the cutset nodes
+ Abc_SeqForEachCutsetNode( pNtk, pObj, i )
+ pObj->fMarkC = 0;
+if ( pParams->fVerbose )
+{
+PRT( "Total", clock() - clk );
+printf( "Converged after %d iterations.\n", nIters );
+}
+//Abc_NtkPrintCuts( p, pNtk, 1 );
+ return p;
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
+{
+ void * pList;
+ if ( pList = Abc_NodeReadCuts( p, pObj ) )
+ return pList;
+ Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree );
+ Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree );
+ return Abc_NodeGetCuts( p, pObj, fDag, fTree );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree )
+{
+ Abc_Obj_t * pFanin;
+ int fDagNode, fTriv, TreeCode = 0;
+// assert( Abc_NtkIsStrash(pObj->pNtk) );
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+
+
+ // check if the node is a DAG node
+ fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj));
+ // increment the counter of DAG nodes
+ if ( fDagNode ) Cut_ManIncrementDagNodes( p );
+ // add the trivial cut if the node is a DAG node, or if we compute all cuts
+ fTriv = fDagNode || !fDag;
+ // check if fanins are DAG nodes
+ if ( fTree )
+ {
+ pFanin = Abc_ObjFanin0(pObj);
+ TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin));
+ pFanin = Abc_ObjFanin1(pObj);
+ TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1);
+ }
+
+
+ // changes due to the global/local cut computation
+ {
+ Cut_Params_t * pParams = Cut_ManReadParams(p);
+ if ( pParams->fLocal )
+ {
+ Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs(p);
+ fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id );
+ if ( fDagNode ) Cut_ManIncrementDagNodes( p );
+// fTriv = fDagNode || !pParams->fGlobal;
+ fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id );
+ TreeCode = 0;
+ pFanin = Abc_ObjFanin0(pObj);
+ TreeCode |= Vec_IntEntry( vNodeAttrs, pFanin->Id );
+ pFanin = Abc_ObjFanin1(pObj);
+ TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1);
+ }
+ }
+ return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
+ Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv )
+{
+ int CutSetNum;
+ assert( Abc_NtkIsSeq(pObj->pNtk) );
+ assert( Abc_ObjFaninNum(pObj) == 2 );
+ fTriv = pObj->fMarkC ? 0 : fTriv;
+ CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1;
+ Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj),
+ Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj )
+{
+ return Cut_NodeReadCutsNew( p, pObj->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj )
+{
+ Cut_NodeFreeCuts( p, pObj->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq )
+{
+ Cut_Man_t * pMan = p;
+ Cut_Cut_t * pList;
+ Abc_Obj_t * pObj;
+ int i;
+ printf( "Cuts of the network:\n" );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ pList = Abc_NodeReadCuts( p, pObj );
+ printf( "Node %s:\n", Abc_ObjName(pObj) );
+ Cut_CutPrintList( pList, fSeq );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts for the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq )
+{
+ Cut_Man_t * pMan = p;
+ Cut_Cut_t * pList;
+ Abc_Obj_t * pObj;
+ pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 );
+ pList = Abc_NodeReadCuts( p, pObj );
+ printf( "Node %s:\n", Abc_ObjName(pObj) );
+ Cut_CutPrintList( pList, fSeq );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/cut/cut.h b/src/opt/cut/cut.h
index 6719ed4d..dee05dfc 100644
--- a/src/opt/cut/cut.h
+++ b/src/opt/cut/cut.h
@@ -21,6 +21,10 @@
#ifndef __CUT_H__
#define __CUT_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -29,81 +33,133 @@
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
+#define CUT_SIZE_MIN 3 // the min K of the K-feasible cut computation
+#define CUT_SIZE_MAX 12 // the max K of the K-feasible cut computation
+
+#define CUT_SHIFT 8 // the number of bits for storing latch number in the cut leaves
+#define CUT_MASK 0xFF // the mask to get the stored latch number
+
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
typedef struct Cut_ManStruct_t_ Cut_Man_t;
+typedef struct Cut_OracleStruct_t_ Cut_Oracle_t;
typedef struct Cut_CutStruct_t_ Cut_Cut_t;
typedef struct Cut_ParamsStruct_t_ Cut_Params_t;
struct Cut_ParamsStruct_t_
{
- int nVarsMax; // the max cut size ("k" of the k-feasible cuts)
- int nKeepMax; // the max number of cuts kept at a node
- int nIdsMax; // the max number of IDs of cut objects
- int fTruth; // compute truth tables
- int fHash; // hash cuts to detect unique
- int fFilter; // filter dominated cuts
- int fSeq; // compute sequential cuts
- int fDrop; // drop cuts on the fly
- int fVerbose; // the verbosiness flag
+ int nVarsMax; // the max cut size ("k" of the k-feasible cuts)
+ int nKeepMax; // the max number of cuts kept at a node
+ int nIdsMax; // the max number of IDs of cut objects
+ int nBitShift; // the number of bits used for the latch counter of an edge
+ int nCutSet; // the number of nodes in the cut set
+ int fTruth; // compute truth tables
+ int fFilter; // filter dominated cuts
+ int fSeq; // compute sequential cuts
+ int fDrop; // drop cuts on the fly
+ int fDag; // compute only DAG cuts
+ int fTree; // compute only tree cuts
+ int fGlobal; // compute only global cuts
+ int fLocal; // compute only local cuts
+ int fRecord; // record the cut computation flow
+ int fFancy; // perform fancy computations
+ int fMap; // computes delay of FPGA mapping with cuts
+ int fVerbose; // the verbosiness flag
};
struct Cut_CutStruct_t_
{
- unsigned uTruth : 16; // truth table for 4-input cuts
- unsigned uPhase : 7; // the phase when mapping into a canonical form
+ unsigned Num0 : 11; // temporary number
+ unsigned Num1 : 11; // temporary number
unsigned fSimul : 1; // the value of cut's output at 000.. pattern
unsigned fCompl : 1; // the cut is complemented
- unsigned fSeq : 1; // the cut is sequential
- unsigned nVarsMax : 3; // the max number of vars [4-6]
- unsigned nLeaves : 3; // the number of leaves [4-6]
+ unsigned nVarsMax : 4; // the max number of vars [4-6]
+ unsigned nLeaves : 4; // the number of leaves [4-6]
+ unsigned uSign; // the signature
+ unsigned uCanon0; // the canonical form
+ unsigned uCanon1; // the canonical form
Cut_Cut_t * pNext; // the next cut in the list
- void * pData; // the user data
int pLeaves[0]; // the array of leaves
};
-static inline unsigned * Cut_CutReadTruth( Cut_Cut_t * p ) { if ( p->nVarsMax == 4 ) return (unsigned *)p; return (unsigned *)(p->pLeaves + p->nVarsMax + p->fSeq); }
-static inline unsigned Cut_CutReadPhase( Cut_Cut_t * p ) { return p->uPhase; }
static inline int Cut_CutReadLeaveNum( Cut_Cut_t * p ) { return p->nLeaves; }
static inline int * Cut_CutReadLeaves( Cut_Cut_t * p ) { return p->pLeaves; }
-static inline void * Cut_CutReadData( Cut_Cut_t * p ) { return p->pData; }
-
-static inline void Cut_CutWriteData( Cut_Cut_t * p, void * pData ) { p->pData = pData; }
+static inline unsigned * Cut_CutReadTruth( Cut_Cut_t * p ) { return (unsigned *)(p->pLeaves + p->nVarsMax); }
static inline void Cut_CutWriteTruth( Cut_Cut_t * p, unsigned * puTruth ) {
- if ( p->nVarsMax == 4 ) { p->uTruth = *puTruth; return; }
- p->pLeaves[p->nVarsMax + p->fSeq] = (int)puTruth[0];
- if ( p->nVarsMax == 6 ) p->pLeaves[p->nVarsMax + p->fSeq + 1] = (int)puTruth[1];
+ int i;
+ for ( i = (p->nVarsMax <= 5) ? 0 : ((1 << (p->nVarsMax - 5)) - 1); i >= 0; i-- )
+ p->pLeaves[p->nVarsMax + i] = (int)puTruth[i];
}
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+/*=== cutApi.c ==========================================================*/
+extern Cut_Cut_t * Cut_NodeReadCutsNew( Cut_Man_t * p, int Node );
+extern Cut_Cut_t * Cut_NodeReadCutsOld( Cut_Man_t * p, int Node );
+extern Cut_Cut_t * Cut_NodeReadCutsTemp( Cut_Man_t * p, int Node );
+extern void Cut_NodeWriteCutsNew( Cut_Man_t * p, int Node, Cut_Cut_t * pList );
+extern void Cut_NodeWriteCutsOld( Cut_Man_t * p, int Node, Cut_Cut_t * pList );
+extern void Cut_NodeWriteCutsTemp( Cut_Man_t * p, int Node, Cut_Cut_t * pList );
+extern void Cut_NodeSetTriv( Cut_Man_t * p, int Node );
+extern void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node );
+extern void Cut_NodeFreeCuts( Cut_Man_t * p, int Node );
+/*=== cutCut.c ==========================================================*/
+extern void Cut_CutPrint( Cut_Cut_t * pCut, int fSeq );
+extern void Cut_CutPrintList( Cut_Cut_t * pList, int fSeq );
+extern int Cut_CutCountList( Cut_Cut_t * pList );
/*=== cutMan.c ==========================================================*/
extern Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams );
extern void Cut_ManStop( Cut_Man_t * p );
extern void Cut_ManPrintStats( Cut_Man_t * p );
+extern void Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, int TimeTotal );
extern void Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts );
+extern void Cut_ManSetNodeAttrs( Cut_Man_t * p, Vec_Int_t * vFanCounts );
+extern int Cut_ManReadVarsMax( Cut_Man_t * p );
+extern Cut_Params_t * Cut_ManReadParams( Cut_Man_t * p );
+extern Vec_Int_t * Cut_ManReadNodeAttrs( Cut_Man_t * p );
+extern void Cut_ManIncrementDagNodes( Cut_Man_t * p );
/*=== cutNode.c ==========================================================*/
-extern void Cut_NodeSetTriv( Cut_Man_t * p, int Node );
-extern Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 );
+extern Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode );
extern Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes );
-extern Cut_Cut_t * Cut_NodeReadCuts( Cut_Man_t * p, int Node );
-extern void Cut_NodeWriteCuts( Cut_Man_t * p, int Node, Cut_Cut_t * pList );
-extern void Cut_NodeFreeCuts( Cut_Man_t * p, int Node );
-extern void Cut_NodeSetComputedAsNew( Cut_Man_t * p, int Node );
-extern void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node );
-extern void Cut_CutPrint( Cut_Cut_t * pCut );
+extern Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst );
+extern int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node );
+/*=== cutSeq.c ==========================================================*/
+extern void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum );
+extern void Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node );
+extern int Cut_NodeTempTransferToNew( Cut_Man_t * p, int Node, int CutSetNum );
+extern void Cut_NodeOldTransferToNew( Cut_Man_t * p, int Node );
+/*=== cutOracle.c ==========================================================*/
+extern Cut_Oracle_t * Cut_OracleStart( Cut_Man_t * pMan );
+extern void Cut_OracleStop( Cut_Oracle_t * p );
+extern void Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts );
+extern int Cut_OracleReadDrop( Cut_Oracle_t * p );
+extern void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node );
+extern Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 );
+extern void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node );
+/*=== cutTruth.c ==========================================================*/
+extern void Cut_TruthNCanonicize( Cut_Cut_t * pCut );
+/*=== cutPre22.c ==========================================================*/
+extern void Cut_CellPrecompute();
+extern void Cut_CellLoad();
+extern int Cut_CellIsRunning();
+extern void Cut_CellDumpToFile();
+extern int Cut_CellTruthLookup( unsigned * pTruth, int nVars );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/cut/cutApi.c b/src/opt/cut/cutApi.c
new file mode 100644
index 00000000..980c6b12
--- /dev/null
+++ b/src/opt/cut/cutApi.c
@@ -0,0 +1,197 @@
+/**CFile****************************************************************
+
+ FileName [cutNode.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [K-feasible cut computation package.]
+
+ Synopsis [Procedures to compute cuts for a node.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_NodeReadCutsNew( Cut_Man_t * p, int Node )
+{
+ if ( Node >= p->vCutsNew->nSize )
+ return NULL;
+ return Vec_PtrEntry( p->vCutsNew, Node );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_NodeReadCutsOld( Cut_Man_t * p, int Node )
+{
+ assert( Node < p->vCutsOld->nSize );
+ return Vec_PtrEntry( p->vCutsOld, Node );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_NodeReadCutsTemp( Cut_Man_t * p, int Node )
+{
+ assert( Node < p->vCutsTemp->nSize );
+ return Vec_PtrEntry( p->vCutsTemp, Node );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeWriteCutsNew( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
+{
+ Vec_PtrWriteEntry( p->vCutsNew, Node, pList );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeWriteCutsOld( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
+{
+ Vec_PtrWriteEntry( p->vCutsOld, Node, pList );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeWriteCutsTemp( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
+{
+ Vec_PtrWriteEntry( p->vCutsTemp, Node, pList );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the trivial cut for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeSetTriv( Cut_Man_t * p, int Node )
+{
+ assert( Cut_NodeReadCutsNew(p, Node) == NULL );
+ Cut_NodeWriteCutsNew( p, Node, Cut_CutCreateTriv(p, Node) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Consider dropping cuts if they are useless by now.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node )
+{
+ int nFanouts;
+ assert( p->vFanCounts );
+ nFanouts = Vec_IntEntry( p->vFanCounts, Node );
+ assert( nFanouts > 0 );
+ if ( --nFanouts == 0 )
+ Cut_NodeFreeCuts( p, Node );
+ Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the cuts at the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeFreeCuts( Cut_Man_t * p, int Node )
+{
+ Cut_Cut_t * pList, * pCut, * pCut2;
+ pList = Cut_NodeReadCutsNew( p, Node );
+ if ( pList == NULL )
+ return;
+ Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+ Cut_CutRecycle( p, pCut );
+ Cut_NodeWriteCutsNew( p, Node, NULL );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/cut/cutCut.c b/src/opt/cut/cutCut.c
new file mode 100644
index 00000000..94147278
--- /dev/null
+++ b/src/opt/cut/cutCut.c
@@ -0,0 +1,359 @@
+/**CFile****************************************************************
+
+ FileName [cutNode.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [K-feasible cut computation package.]
+
+ Synopsis [Procedures to compute cuts for a node.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p )
+{
+ Cut_Cut_t * pCut;
+ // cut allocation
+ pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts );
+ memset( pCut, 0, sizeof(Cut_Cut_t) );
+ pCut->nVarsMax = p->pParams->nVarsMax;
+ pCut->fSimul = p->fSimul;
+ // statistics
+ p->nCutsAlloc++;
+ p->nCutsCur++;
+ if ( p->nCutsPeak < p->nCutsAlloc - p->nCutsDealloc )
+ p->nCutsPeak = p->nCutsAlloc - p->nCutsDealloc;
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recybles the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut )
+{
+ p->nCutsDealloc++;
+ p->nCutsCur--;
+ if ( pCut->nLeaves == 1 )
+ p->nCutsTriv--;
+ Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares two cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 )
+{
+ int i;
+ if ( pCut1->nLeaves < pCut2->nLeaves )
+ return -1;
+ if ( pCut1->nLeaves > pCut2->nLeaves )
+ return 1;
+ for ( i = 0; i < (int)pCut1->nLeaves; i++ )
+ {
+ if ( pCut1->pLeaves[i] < pCut2->pLeaves[i] )
+ return -1;
+ if ( pCut1->pLeaves[i] > pCut2->pLeaves[i] )
+ return 1;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList )
+{
+ Cut_Cut_t * pHead = NULL, ** ppTail = &pHead;
+ Cut_Cut_t * pTemp, * pCopy;
+ if ( pList == NULL )
+ return NULL;
+ Cut_ListForEachCut( pList, pTemp )
+ {
+ pCopy = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts );
+ memcpy( pCopy, pTemp, p->EntrySize );
+ *ppTail = pCopy;
+ ppTail = &pCopy->pNext;
+ }
+ *ppTail = NULL;
+ return pHead;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recycles the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList )
+{
+ Cut_Cut_t * pCut, * pCut2;
+ Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+ Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of cuts in the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_CutCountList( Cut_Cut_t * pList )
+{
+ int Counter = 0;
+ Cut_ListForEachCut( pList, pList )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two NULL-terminated linked lists.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 )
+{
+ Cut_Cut_t * pList = NULL, ** ppTail = &pList;
+ Cut_Cut_t * pCut;
+ while ( pList1 && pList2 )
+ {
+ if ( Cut_CutCompare(pList1, pList2) < 0 )
+ {
+ pCut = pList1;
+ pList1 = pList1->pNext;
+ }
+ else
+ {
+ pCut = pList2;
+ pList2 = pList2->pNext;
+ }
+ *ppTail = pCut;
+ ppTail = &pCut->pNext;
+ }
+ *ppTail = pList1? pList1: pList2;
+ return pList;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the number of the cuts in the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CutNumberList( Cut_Cut_t * pList )
+{
+ Cut_Cut_t * pCut;
+ int i = 0;
+ Cut_ListForEachCut( pList, pCut )
+ pCut->Num0 = i++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the trivial cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node )
+{
+ Cut_Cut_t * pCut;
+ if ( p->pParams->fSeq )
+ Node <<= CUT_SHIFT;
+ pCut = Cut_CutAlloc( p );
+ pCut->nLeaves = 1;
+ pCut->pLeaves[0] = Node;
+ pCut->uSign = Cut_NodeSign( Node );
+ if ( p->pParams->fTruth )
+ {
+/*
+ if ( pCut->nVarsMax == 4 )
+ Cut_CutWriteTruth( pCut, p->uTruthVars[0] );
+ else
+ Extra_BitCopy( pCut->nLeaves, p->uTruths[0], (uint8*)Cut_CutReadTruth(pCut) );
+*/
+ unsigned * pTruth = Cut_CutReadTruth(pCut);
+ int i;
+ for ( i = 0; i < p->nTruthWords; i++ )
+ pTruth[i] = 0xAAAAAAAA;
+ }
+ p->nCutsTriv++;
+ return pCut;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Print the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CutPrint( Cut_Cut_t * pCut, int fSeq )
+{
+ int i;
+ assert( pCut->nLeaves > 0 );
+ printf( "%d : {", pCut->nLeaves );
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ {
+ if ( fSeq )
+ {
+ printf( " %d", pCut->pLeaves[i] >> CUT_SHIFT );
+ if ( pCut->pLeaves[i] & CUT_MASK )
+ printf( "(%d)", pCut->pLeaves[i] & CUT_MASK );
+ }
+ else
+ printf( " %d", pCut->pLeaves[i] );
+ }
+ printf( " }" );
+// printf( "\nSign = " );
+// Extra_PrintBinary( stdout, &pCut->uSign, 32 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Print the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CutPrintList( Cut_Cut_t * pList, int fSeq )
+{
+ Cut_Cut_t * pCut;
+ for ( pCut = pList; pCut; pCut = pCut->pNext )
+ Cut_CutPrint( pCut, fSeq ), printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Consider dropping cuts if they are useless by now.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+{
+ printf( "\n" );
+ printf( "%d : %5d %5d %5d %5d %5d\n",
+ pCut0->nLeaves,
+ pCut0->nLeaves > 0 ? pCut0->pLeaves[0] : -1,
+ pCut0->nLeaves > 1 ? pCut0->pLeaves[1] : -1,
+ pCut0->nLeaves > 2 ? pCut0->pLeaves[2] : -1,
+ pCut0->nLeaves > 3 ? pCut0->pLeaves[3] : -1,
+ pCut0->nLeaves > 4 ? pCut0->pLeaves[4] : -1
+ );
+ printf( "%d : %5d %5d %5d %5d %5d\n",
+ pCut1->nLeaves,
+ pCut1->nLeaves > 0 ? pCut1->pLeaves[0] : -1,
+ pCut1->nLeaves > 1 ? pCut1->pLeaves[1] : -1,
+ pCut1->nLeaves > 2 ? pCut1->pLeaves[2] : -1,
+ pCut1->nLeaves > 3 ? pCut1->pLeaves[3] : -1,
+ pCut1->nLeaves > 4 ? pCut1->pLeaves[4] : -1
+ );
+ if ( pCut == NULL )
+ printf( "Cannot merge\n" );
+ else
+ printf( "%d : %5d %5d %5d %5d %5d\n",
+ pCut->nLeaves,
+ pCut->nLeaves > 0 ? pCut->pLeaves[0] : -1,
+ pCut->nLeaves > 1 ? pCut->pLeaves[1] : -1,
+ pCut->nLeaves > 2 ? pCut->pLeaves[2] : -1,
+ pCut->nLeaves > 3 ? pCut->pLeaves[3] : -1,
+ pCut->nLeaves > 4 ? pCut->pLeaves[4] : -1
+ );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/cut/cutExpand.c b/src/opt/cut/cutExpand.c
new file mode 100644
index 00000000..d389ef7a
--- /dev/null
+++ b/src/opt/cut/cutExpand.c
@@ -0,0 +1,184 @@
+/**CFile****************************************************************
+
+ FileName [cutExpand.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [K-feasible cut computation package.]
+
+ Synopsis [Computes the truth table of the cut after expansion.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cutExpand.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define CUT_CELL_MVAR 9
+
+////////////////////////////////////////////////////////////////////////
+/// 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( Cut_Cut_t * pCut, Cut_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 [Computes the truth table of the composition of cuts.]
+
+ Description [Inputs are:
+ - a factor cut (truth table is stored inside)
+ - a node in the factor cut
+ - a tree cut to be substituted (truth table is stored inside)
+ - the resulting cut (truth table will be filled in).
+ Note that all cuts, including the resulting one, should be already
+ computed and the nodes should be stored in the ascending order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_TruthCompose( Cut_Cut_t * pCutF, int Node, Cut_Cut_t * pCutT, Cut_Cut_t * pCutRes )
+{
+ static unsigned uCof0[1<<(CUT_CELL_MVAR-5)];
+ static unsigned uCof1[1<<(CUT_CELL_MVAR-5)];
+ static unsigned uTemp[1<<(CUT_CELL_MVAR-5)];
+ unsigned * pIn, * pOut, * pTemp;
+ unsigned uPhase;
+ int NodeIndex, i, k;
+
+ // sanity checks
+ assert( pCutF->nVarsMax == pCutT->nVarsMax );
+ assert( pCutF->nVarsMax == pCutRes->nVarsMax );
+ assert( pCutF->nVarsMax <= CUT_CELL_MVAR );
+ // the factor cut (pCutF) should have its nodes sorted in the ascending order
+ assert( pCutF->nLeaves <= pCutF->nVarsMax );
+ for ( i = 0; i < (int)pCutF->nLeaves - 1; i++ )
+ assert( pCutF->pLeaves[i] < pCutF->pLeaves[i+1] );
+ // the tree cut (pCutT) should have its nodes sorted in the ascending order
+ assert( pCutT->nLeaves <= pCutT->nVarsMax );
+ for ( i = 0; i < (int)pCutT->nLeaves - 1; i++ )
+ assert( pCutT->pLeaves[i] < pCutT->pLeaves[i+1] );
+ // the resulting cut (pCutRes) should have its nodes sorted in the ascending order
+ assert( pCutRes->nLeaves <= pCutRes->nVarsMax );
+ for ( i = 0; i < (int)pCutRes->nLeaves - 1; i++ )
+ assert( pCutRes->pLeaves[i] < pCutRes->pLeaves[i+1] );
+ // make sure that every node in pCutF (except Node) appears in pCutRes
+ for ( i = 0; i < (int)pCutF->nLeaves; i++ )
+ {
+ if ( pCutF->pLeaves[i] == Node )
+ continue;
+ for ( k = 0; k < (int)pCutRes->nLeaves; k++ )
+ if ( pCutF->pLeaves[i] == pCutRes->pLeaves[k] )
+ break;
+ assert( k < (int)pCutRes->nLeaves ); // node i from pCutF is not found in pCutRes!!!
+ }
+ // make sure that every node in pCutT appears in pCutRes
+ for ( i = 0; i < (int)pCutT->nLeaves; i++ )
+ {
+ for ( k = 0; k < (int)pCutRes->nLeaves; k++ )
+ if ( pCutT->pLeaves[i] == pCutRes->pLeaves[k] )
+ break;
+ assert( k < (int)pCutRes->nLeaves ); // node i from pCutT is not found in pCutRes!!!
+ }
+
+
+ // find the index of the given node in the factor cut
+ NodeIndex = -1;
+ for ( NodeIndex = 0; NodeIndex < (int)pCutF->nLeaves; NodeIndex++ )
+ if ( pCutF->pLeaves[NodeIndex] == Node )
+ break;
+ assert( NodeIndex >= 0 ); // Node should be in pCutF
+
+ // copy the truth table
+ Extra_TruthCopy( uTemp, Cut_CutReadTruth(pCutF), pCutF->nLeaves );
+
+ // bubble-move the NodeIndex variable to be the last one (the most significant one)
+ pIn = uTemp; pOut = uCof0; // uCof0 is used for temporary storage here
+ for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ )
+ {
+ Extra_TruthSwapAdjacentVars( pOut, pIn, pCutF->nLeaves, i );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ }
+ if ( (pCutF->nLeaves - 1 - NodeIndex) & 1 )
+ Extra_TruthCopy( pOut, pIn, pCutF->nLeaves );
+ // the result of stretching is in uTemp
+
+ // cofactor the factor cut with respect to the node
+ Extra_TruthCopy( uCof0, uTemp, pCutF->nLeaves );
+ Extra_TruthCofactor0( uCof0, pCutF->nLeaves, pCutF->nLeaves-1 );
+ Extra_TruthCopy( uCof1, uTemp, pCutF->nLeaves );
+ Extra_TruthCofactor1( uCof1, pCutF->nLeaves, pCutF->nLeaves-1 );
+
+ // temporarily shrink the factor cut's variables by removing Node
+ for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ )
+ pCutF->pLeaves[i] = pCutF->pLeaves[i+1];
+ pCutF->nLeaves--;
+
+ // spread out the cofactors' truth tables to the same var order as the resulting cut
+ uPhase = Cut_TruthPhase(pCutRes, pCutF);
+ assert( Extra_WordCountOnes(uPhase) == (int)pCutF->nLeaves );
+ Extra_TruthStretch( uTemp, uCof0, pCutF->nLeaves, pCutF->nVarsMax, uPhase );
+ Extra_TruthCopy( uCof0, uTemp, pCutF->nVarsMax );
+ Extra_TruthStretch( uTemp, uCof1, pCutF->nLeaves, pCutF->nVarsMax, uPhase );
+ Extra_TruthCopy( uCof1, uTemp, pCutF->nVarsMax );
+
+ // spread out the tree cut's truth table to the same var order as the resulting cut
+ uPhase = Cut_TruthPhase(pCutRes, pCutT);
+ assert( Extra_WordCountOnes(uPhase) == (int)pCutT->nLeaves );
+ Extra_TruthStretch( uTemp, Cut_CutReadTruth(pCutT), pCutT->nLeaves, pCutT->nVarsMax, uPhase );
+
+ // create the resulting truth table
+ pTemp = Cut_CutReadTruth(pCutRes);
+ for ( i = Extra_TruthWordNum(pCutRes->nLeaves)-1; i >= 0; i-- )
+ pTemp[i] = (uCof0[i] & ~uTemp[i]) | (uCof1[i] & uTemp[i]);
+
+ // undo the removal of the node from the cut
+ for ( i = (int)pCutF->nLeaves - 1; i >= NodeIndex; --i )
+ pCutF->pLeaves[i+1] = pCutF->pLeaves[i];
+ pCutF->pLeaves[NodeIndex] = Node;
+ pCutF->nLeaves++;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/cut/cutInt.h b/src/opt/cut/cutInt.h
index fe5080b4..17f268c7 100644
--- a/src/opt/cut/cutInt.h
+++ b/src/opt/cut/cutInt.h
@@ -29,6 +29,7 @@
#include "extra.h"
#include "vec.h"
#include "cut.h"
+#include "cutList.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
@@ -41,56 +42,103 @@
typedef struct Cut_HashTableStruct_t_ Cut_HashTable_t;
struct Cut_ManStruct_t_
-{
+{
// user preferences
Cut_Params_t * pParams; // computation parameters
Vec_Int_t * vFanCounts; // the array of fanout counters
+ Vec_Int_t * vNodeAttrs; // node attributes (1 = global; 0 = local)
// storage for cuts
- Vec_Ptr_t * vCuts; // cuts by ID
- Vec_Ptr_t * vCutsNew; // cuts by ID
- Cut_HashTable_t * tTable; // cuts by their leaves (and root)
+ Vec_Ptr_t * vCutsNew; // new cuts by node ID
+ Vec_Ptr_t * vCutsOld; // old cuts by node ID
+ Vec_Ptr_t * vCutsTemp; // temp cuts for cutset nodes by cutset node number
// memory management
Extra_MmFixed_t * pMmCuts;
int EntrySize;
+ int nTruthWords;
// temporary variables
Cut_Cut_t * pReady;
Vec_Ptr_t * vTemp;
int fCompl0;
int fCompl1;
int fSimul;
- // precomputations
- unsigned uTruthVars[6][2];
- unsigned short ** pPerms43;
- unsigned ** pPerms53;
- unsigned ** pPerms54;
+ int nNodeCuts;
+ Cut_Cut_t * pStore0[2];
+ Cut_Cut_t * pStore1[2];
+ Cut_Cut_t * pCompareOld;
+ Cut_Cut_t * pCompareNew;
+ unsigned * puTemp[4];
+ // record of the cut computation
+ Vec_Int_t * vNodeCuts; // the number of cuts for each node
+ Vec_Int_t * vNodeStarts; // the number of the starting cut of each node
+ Vec_Int_t * vCutPairs; // the pairs of parent cuts for each cut
+ // minimum delay mapping with the given cuts
+ Vec_Ptr_t * vCutsMax;
+ Vec_Int_t * vDelays;
+ Vec_Int_t * vDelays2;
+ int nDelayMin;
// statistics
int nCutsCur;
int nCutsAlloc;
int nCutsDealloc;
int nCutsPeak;
int nCutsTriv;
- int nCutsNode;
+ int nCutsFilter;
+ int nCutsLimit;
int nNodes;
+ int nNodesDag;
+ int nNodesNoCuts;
// runtime
int timeMerge;
int timeUnion;
int timeTruth;
int timeFilter;
int timeHash;
+ int timeMap;
};
+// iterator through all the cuts of the list
+#define Cut_ListForEachCut( pList, pCut ) \
+ for ( pCut = pList; \
+ pCut; \
+ pCut = pCut->pNext )
+#define Cut_ListForEachCutStop( pList, pCut, pStop ) \
+ for ( pCut = pList; \
+ pCut != pStop; \
+ pCut = pCut->pNext )
+#define Cut_ListForEachCutSafe( pList, pCut, pCut2 ) \
+ for ( pCut = pList, \
+ pCut2 = pCut? pCut->pNext: NULL; \
+ pCut; \
+ pCut = pCut2, \
+ pCut2 = pCut? pCut->pNext: NULL )
+
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
+// computes signature of the node
+static inline unsigned Cut_NodeSign( int Node ) { return (1 << (Node % 31)); }
+static inline int Cut_TruthWords( int nVarsMax ) { return nVarsMax <= 5 ? 1 : (1 << (nVarsMax - 5)); }
+
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+/*=== cutCut.c ==========================================================*/
+extern Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p );
+extern void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut );
+extern int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 );
+extern Cut_Cut_t * Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList );
+extern void Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList );
+extern Cut_Cut_t * Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 );
+extern void Cut_CutNumberList( Cut_Cut_t * pList );
+extern Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node );
+extern void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
/*=== cutMerge.c ==========================================================*/
extern Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
/*=== cutNode.c ==========================================================*/
-extern Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p );
+extern void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode );
+extern int Cut_CutListVerify( Cut_Cut_t * pList );
/*=== cutTable.c ==========================================================*/
extern Cut_HashTable_t * Cut_TableStart( int Size );
extern void Cut_TableStop( Cut_HashTable_t * pTable );
@@ -98,11 +146,12 @@ extern int Cut_TableLookup( Cut_HashTable_t * pTable, Cut_Cut_t
extern void Cut_TableClear( Cut_HashTable_t * pTable );
extern int Cut_TableReadTime( Cut_HashTable_t * pTable );
/*=== cutTruth.c ==========================================================*/
-extern void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
+extern void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 );
+extern void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 );
+
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/cut/cutList.h b/src/opt/cut/cutList.h
index eb008ef9..a03ec9d5 100644
--- a/src/opt/cut/cutList.h
+++ b/src/opt/cut/cutList.h
@@ -36,12 +36,12 @@
typedef struct Cut_ListStruct_t_ Cut_List_t;
struct Cut_ListStruct_t_
{
- Cut_Cut_t * pHead[7];
- Cut_Cut_t ** ppTail[7];
+ Cut_Cut_t * pHead[CUT_SIZE_MAX+1];
+ Cut_Cut_t ** ppTail[CUT_SIZE_MAX+1];
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@@ -50,7 +50,7 @@ struct Cut_ListStruct_t_
/**Function*************************************************************
- Synopsis []
+ Synopsis [Start the cut list.]
Description []
@@ -62,7 +62,7 @@ struct Cut_ListStruct_t_
static inline void Cut_ListStart( Cut_List_t * p )
{
int i;
- for ( i = 1; i <= 6; i++ )
+ for ( i = 1; i <= CUT_SIZE_MAX; i++ )
{
p->pHead[i] = 0;
p->ppTail[i] = &p->pHead[i];
@@ -71,7 +71,7 @@ static inline void Cut_ListStart( Cut_List_t * p )
/**Function*************************************************************
- Synopsis []
+ Synopsis [Adds one cut to the cut list.]
Description []
@@ -82,14 +82,100 @@ static inline void Cut_ListStart( Cut_List_t * p )
***********************************************************************/
static inline void Cut_ListAdd( Cut_List_t * p, Cut_Cut_t * pCut )
{
- assert( pCut->nLeaves > 0 && pCut->nLeaves < 7 );
+ assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX );
*p->ppTail[pCut->nLeaves] = pCut;
p->ppTail[pCut->nLeaves] = &pCut->pNext;
}
/**Function*************************************************************
- Synopsis []
+ Synopsis [Adds one cut to the cut list while preserving order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cut_ListAdd2( Cut_List_t * p, Cut_Cut_t * pCut )
+{
+ extern int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 );
+ Cut_Cut_t * pTemp, ** ppSpot;
+ assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX );
+ if ( p->pHead[pCut->nLeaves] != NULL )
+ {
+ ppSpot = &p->pHead[pCut->nLeaves];
+ for ( pTemp = p->pHead[pCut->nLeaves]; pTemp; pTemp = pTemp->pNext )
+ {
+ if ( Cut_CutCompare(pCut, pTemp) < 0 )
+ {
+ *ppSpot = pCut;
+ pCut->pNext = pTemp;
+ return;
+ }
+ else
+ ppSpot = &pTemp->pNext;
+ }
+ }
+ *p->ppTail[pCut->nLeaves] = pCut;
+ p->ppTail[pCut->nLeaves] = &pCut->pNext;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derive the super list from the linked list of cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cut_ListDerive( Cut_List_t * p, Cut_Cut_t * pList )
+{
+ Cut_Cut_t * pPrev;
+ int nLeaves;
+ Cut_ListStart( p );
+ while ( pList != NULL )
+ {
+ nLeaves = pList->nLeaves;
+ p->pHead[nLeaves] = pList;
+ for ( pPrev = pList, pList = pList->pNext; pList; pPrev = pList, pList = pList->pNext )
+ if ( nLeaves < (int)pList->nLeaves )
+ break;
+ p->ppTail[nLeaves] = &pPrev->pNext;
+ pPrev->pNext = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the second list to the first list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cut_ListAddList( Cut_List_t * pOld, Cut_List_t * pNew )
+{
+ int i;
+ for ( i = 1; i <= CUT_SIZE_MAX; i++ )
+ {
+ if ( pNew->pHead[i] == NULL )
+ continue;
+ *pOld->ppTail[i] = pNew->pHead[i];
+ pOld->ppTail[i] = pNew->ppTail[i];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the cut list linked into one sequence of cuts.]
Description []
@@ -100,16 +186,22 @@ static inline void Cut_ListAdd( Cut_List_t * p, Cut_Cut_t * pCut )
***********************************************************************/
static inline Cut_Cut_t * Cut_ListFinish( Cut_List_t * p )
{
+ Cut_Cut_t * pHead = NULL, ** ppTail = &pHead;
int i;
- for ( i = 1; i < 6; i++ )
- *p->ppTail[i] = p->pHead[i+1];
- *p->ppTail[6] = NULL;
- return p->pHead[1];
+ for ( i = 1; i <= CUT_SIZE_MAX; i++ )
+ {
+ if ( p->pHead[i] == NULL )
+ continue;
+ *ppTail = p->pHead[i];
+ ppTail = p->ppTail[i];
+ }
+ *ppTail = NULL;
+ return pHead;
}
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/cut/cutMan.c b/src/opt/cut/cutMan.c
index 4ad3a66a..8593ef93 100644
--- a/src/opt/cut/cutMan.c
+++ b/src/opt/cut/cutMan.c
@@ -24,8 +24,10 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+extern void Npn_StartTruth8( uint8 uTruths[][32] );
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -43,47 +45,65 @@ Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams )
{
Cut_Man_t * p;
int clk = clock();
- assert( pParams->nVarsMax >= 4 && pParams->nVarsMax <= 6 );
+// extern int nTruthDsd;
+// nTruthDsd = 0;
+ assert( pParams->nVarsMax >= 3 && pParams->nVarsMax <= CUT_SIZE_MAX );
p = ALLOC( Cut_Man_t, 1 );
memset( p, 0, sizeof(Cut_Man_t) );
// set and correct parameters
p->pParams = pParams;
- if ( p->pParams->fSeq )
- p->pParams->fHash = 1;
- // space for cuts
- p->vCuts = Vec_PtrAlloc( pParams->nIdsMax );
- Vec_PtrFill( p->vCuts, pParams->nIdsMax, NULL );
+ // prepare storage for cuts
+ p->vCutsNew = Vec_PtrAlloc( pParams->nIdsMax );
+ Vec_PtrFill( p->vCutsNew, pParams->nIdsMax, NULL );
+ // prepare storage for sequential cuts
if ( pParams->fSeq )
{
- p->vCutsNew = Vec_PtrAlloc( pParams->nIdsMax );
- Vec_PtrFill( p->vCuts, pParams->nIdsMax, NULL );
+ p->pParams->fFilter = 1;
+ p->vCutsOld = Vec_PtrAlloc( pParams->nIdsMax );
+ Vec_PtrFill( p->vCutsOld, pParams->nIdsMax, NULL );
+ p->vCutsTemp = Vec_PtrAlloc( pParams->nCutSet );
+ Vec_PtrFill( p->vCutsTemp, pParams->nCutSet, NULL );
+ if ( pParams->fTruth && pParams->nVarsMax > 5 )
+ {
+ pParams->fTruth = 0;
+ printf( "Skipping computation of truth tables for sequential cuts with more than 5 inputs.\n" );
+ }
}
- // hash tables
- if ( pParams->fHash )
- p->tTable = Cut_TableStart( p->pParams->nKeepMax );
// entry size
- p->EntrySize = sizeof(Cut_Cut_t) + (pParams->nVarsMax + pParams->fSeq) * sizeof(int);
- if ( pParams->nVarsMax == 5 )
- p->EntrySize += sizeof(unsigned);
- else if ( pParams->nVarsMax == 6 )
- p->EntrySize += 2 * sizeof(unsigned);
+ p->EntrySize = sizeof(Cut_Cut_t) + pParams->nVarsMax * sizeof(int);
+ if ( pParams->fTruth )
+ {
+ if ( pParams->nVarsMax > 14 )
+ {
+ pParams->fTruth = 0;
+ printf( "Skipping computation of truth table for more than %d inputs.\n", 14 );
+ }
+ else
+ {
+ p->nTruthWords = Cut_TruthWords( pParams->nVarsMax );
+ p->EntrySize += p->nTruthWords * sizeof(unsigned);
+ }
+ p->puTemp[0] = ALLOC( unsigned, 4 * p->nTruthWords );
+ p->puTemp[1] = p->puTemp[0] + p->nTruthWords;
+ p->puTemp[2] = p->puTemp[1] + p->nTruthWords;
+ p->puTemp[3] = p->puTemp[2] + p->nTruthWords;
+ }
+ // enable cut computation recording
+ if ( pParams->fRecord )
+ {
+ p->vNodeCuts = Vec_IntStart( pParams->nIdsMax );
+ p->vNodeStarts = Vec_IntStart( pParams->nIdsMax );
+ p->vCutPairs = Vec_IntAlloc( 0 );
+ }
+ // allocate storage for delays
+ if ( pParams->fMap && !p->pParams->fSeq )
+ {
+ p->vDelays = Vec_IntStart( pParams->nIdsMax );
+ p->vDelays2 = Vec_IntStart( pParams->nIdsMax );
+ p->vCutsMax = Vec_PtrStart( pParams->nIdsMax );
+ }
// memory for cuts
p->pMmCuts = Extra_MmFixedStart( p->EntrySize );
- // precomputations
-// if ( pParams->fTruth && pParams->nVarsMax == 4 )
-// p->pPerms43 = Extra_TruthPerm43();
-// else if ( pParams->fTruth )
-// {
-// p->pPerms53 = Extra_TruthPerm53();
-// p->pPerms54 = Extra_TruthPerm54();
-// }
- p->uTruthVars[0][1] = p->uTruthVars[0][0] = 0xAAAAAAAA; // 1010 1010 1010 1010 1010 1010 1010 1010
- p->uTruthVars[1][1] = p->uTruthVars[1][0] = 0xCCCCCCCC; // 1010 1010 1010 1010 1010 1010 1010 1010
- p->uTruthVars[2][1] = p->uTruthVars[2][0] = 0xF0F0F0F0; // 1111 0000 1111 0000 1111 0000 1111 0000
- p->uTruthVars[3][1] = p->uTruthVars[3][0] = 0xFF00FF00; // 1111 1111 0000 0000 1111 1111 0000 0000
- p->uTruthVars[4][1] = p->uTruthVars[4][0] = 0xFFFF0000; // 1111 1111 1111 1111 0000 0000 0000 0000
- p->uTruthVars[5][0] = 0x00000000;
- p->uTruthVars[5][1] = 0xFFFFFFFF;
p->vTemp = Vec_PtrAlloc( 100 );
return p;
}
@@ -103,23 +123,29 @@ void Cut_ManStop( Cut_Man_t * p )
{
Cut_Cut_t * pCut;
int i;
- Vec_PtrForEachEntry( p->vCuts, pCut, i )
- {
+// extern int nTruthDsd;
+// printf( "Decomposable cuts = %d.\n", nTruthDsd );
+
+ Vec_PtrForEachEntry( p->vCutsNew, pCut, i )
if ( pCut != NULL )
{
int k = 0;
}
- }
-
- if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew );
- if ( p->vCuts ) Vec_PtrFree( p->vCuts );
- if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts );
- if ( p->pPerms43 ) free( p->pPerms43 );
- if ( p->pPerms53 ) free( p->pPerms53 );
- if ( p->pPerms54 ) free( p->pPerms54 );
- if ( p->vTemp ) Vec_PtrFree( p->vTemp );
- if ( p->tTable ) Cut_TableStop( p->tTable );
- Extra_MmFixedStop( p->pMmCuts, 0 );
+ if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew );
+ if ( p->vCutsOld ) Vec_PtrFree( p->vCutsOld );
+ if ( p->vCutsTemp ) Vec_PtrFree( p->vCutsTemp );
+ if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts );
+ if ( p->vTemp ) Vec_PtrFree( p->vTemp );
+
+ if ( p->vCutsMax ) Vec_PtrFree( p->vCutsMax );
+ if ( p->vDelays ) Vec_IntFree( p->vDelays );
+ if ( p->vDelays2 ) Vec_IntFree( p->vDelays2 );
+ if ( p->vNodeCuts ) Vec_IntFree( p->vNodeCuts );
+ if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts );
+ if ( p->vCutPairs ) Vec_IntFree( p->vCutPairs );
+ if ( p->puTemp[0] ) free( p->puTemp[0] );
+
+ Extra_MmFixedStop( p->pMmCuts );
free( p );
}
@@ -136,21 +162,66 @@ void Cut_ManStop( Cut_Man_t * p )
***********************************************************************/
void Cut_ManPrintStats( Cut_Man_t * p )
{
+ if ( p->pReady )
+ {
+ Cut_CutRecycle( p, p->pReady );
+ p->pReady = NULL;
+ }
printf( "Cut computation statistics:\n" );
printf( "Current cuts = %8d. (Trivial = %d.)\n", p->nCutsCur-p->nCutsTriv, p->nCutsTriv );
printf( "Peak cuts = %8d.\n", p->nCutsPeak );
printf( "Total allocated = %8d.\n", p->nCutsAlloc );
printf( "Total deallocated = %8d.\n", p->nCutsDealloc );
+ printf( "Cuts filtered = %8d.\n", p->nCutsFilter );
+ printf( "Nodes saturated = %8d. (Max cuts = %d.)\n", p->nCutsLimit, p->pParams->nKeepMax );
printf( "Cuts per node = %8.1f\n", ((float)(p->nCutsCur-p->nCutsTriv))/p->nNodes );
printf( "The cut size = %8d bytes.\n", p->EntrySize );
printf( "Peak memory = %8.2f Mb.\n", (float)p->nCutsPeak * p->EntrySize / (1<<20) );
+ printf( "Total nodes = %8d.\n", p->nNodes );
+ if ( p->pParams->fDag || p->pParams->fTree )
+ {
+ printf( "DAG nodes = %8d.\n", p->nNodesDag );
+ printf( "Tree nodes = %8d.\n", p->nNodes - p->nNodesDag );
+ }
+ printf( "Nodes w/o cuts = %8d.\n", p->nNodesNoCuts );
+ if ( p->pParams->fMap && !p->pParams->fSeq )
+ printf( "Mapping delay = %8d.\n", p->nDelayMin );
+
PRT( "Merge ", p->timeMerge );
PRT( "Union ", p->timeUnion );
- PRT( "Hash ", Cut_TableReadTime(p->tTable) );
PRT( "Filter", p->timeFilter );
PRT( "Truth ", p->timeTruth );
+ PRT( "Map ", p->timeMap );
+// printf( "Nodes = %d. Multi = %d. Cuts = %d. Multi = %d.\n",
+// p->nNodes, p->nNodesMulti, p->nCutsCur-p->nCutsTriv, p->nCutsMulti );
+// printf( "Count0 = %d. Count1 = %d. Count2 = %d.\n\n", p->Count0, p->Count1, p->Count2 );
}
+
+/**Function*************************************************************
+
+ Synopsis [Prints some interesting stats.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, int TimeTotal )
+{
+ FILE * pTable;
+ pTable = fopen( "cut_stats.txt", "a+" );
+ fprintf( pTable, "%-20s ", pFileName );
+ fprintf( pTable, "%8d ", p->nNodes );
+ fprintf( pTable, "%6.1f ", ((float)(p->nCutsCur))/p->nNodes );
+ fprintf( pTable, "%6.2f ", ((float)(100.0 * p->nCutsLimit))/p->nNodes );
+ fprintf( pTable, "%6.2f ", (float)p->nCutsPeak * p->EntrySize / (1<<20) );
+ fprintf( pTable, "%6.2f ", (float)(TimeTotal)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+}
/**Function*************************************************************
@@ -168,6 +239,86 @@ void Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts )
p->vFanCounts = vFanCounts;
}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_ManSetNodeAttrs( Cut_Man_t * p, Vec_Int_t * vNodeAttrs )
+{
+ p->vNodeAttrs = vNodeAttrs;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_ManReadVarsMax( Cut_Man_t * p )
+{
+ return p->pParams->nVarsMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Params_t * Cut_ManReadParams( Cut_Man_t * p )
+{
+ return p->pParams;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Cut_ManReadNodeAttrs( Cut_Man_t * p )
+{
+ return p->vNodeAttrs;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_ManIncrementDagNodes( Cut_Man_t * p )
+{
+ p->nNodesDag++;
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/cut/cutMerge.c b/src/opt/cut/cutMerge.c
index ba1afce4..d8a9989c 100644
--- a/src/opt/cut/cutMerge.c
+++ b/src/opt/cut/cutMerge.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -39,7 +39,7 @@
SeeAlso []
***********************************************************************/
-Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+Cut_Cut_t * Cut_CutMergeTwo2( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
{
static int M[7][3] = {{0},{0},{0},{0},{0},{0},{0}};
Cut_Cut_t * pRes;
@@ -164,7 +164,7 @@ Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1
SeeAlso []
***********************************************************************/
-Cut_Cut_t * Cut_CutMergeTwo2( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
{
Cut_Cut_t * pRes;
int * pLeaves;
@@ -526,7 +526,7 @@ Cut_Cut_t * Cut_CutMergeTwo5( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut
return NULL;
}
pRes = Cut_CutAlloc( p );
- pRes->uTruth = (uSign1 << 8);
+ pRes->Num1 = uSign1;
}
for ( i = 0; i < (int)pCut0->nLeaves; i++ )
pRes->pLeaves[i] = pCut0->pLeaves[i];
@@ -645,7 +645,8 @@ Cut_Cut_t * Cut_CutMergeTwo5( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut
}
assert( Count == nNodes );
pRes->nLeaves = nNodes;
- pRes->uTruth = (uSign1 << 8) | uSign0;
+ pRes->Num1 = uSign1;
+ pRes->Num0 = uSign0;
return pRes;
}
diff --git a/src/opt/cut/cutNode.c b/src/opt/cut/cutNode.c
index 8d16ac8a..1f93b14b 100644
--- a/src/opt/cut/cutNode.c
+++ b/src/opt/cut/cutNode.c
@@ -19,42 +19,21 @@
***********************************************************************/
#include "cutInt.h"
-#include "cutList.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static inline Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node );
-static inline void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut );
-static inline int Cut_CutProcessTwo( Cut_Man_t * p, int Root, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, Cut_List_t * pSuperList );
-
-static void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
-static void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList );
-
-// iterator through all the cuts of the list
-#define Cut_ListForEachCut( pList, pCut ) \
- for ( pCut = pList; \
- pCut; \
- pCut = pCut->pNext )
-#define Cut_ListForEachCutStop( pList, pCut, pStop ) \
- for ( pCut = pList; \
- pCut != pStop; \
- pCut = pCut->pNext )
-#define Cut_ListForEachCutSafe( pList, pCut, pCut2 ) \
- for ( pCut = pList, \
- pCut2 = pCut? pCut->pNext: NULL; \
- pCut; \
- pCut = pCut2, \
- pCut2 = pCut? pCut->pNext: NULL )
+static int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 );
+static int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Returns the pointer to the linked list of cuts.]
+ Synopsis [Returns 1 if pDom is contained in pCut.]
Description []
@@ -63,16 +42,24 @@ static void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList );
SeeAlso []
***********************************************************************/
-Cut_Cut_t * Cut_NodeReadCuts( Cut_Man_t * p, int Node )
+static inline int Cut_CutCheckDominance( Cut_Cut_t * pDom, Cut_Cut_t * pCut )
{
- if ( Node >= p->vCuts->nSize )
- return NULL;
- return Vec_PtrEntry( p->vCuts, Node );
+ 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 the pointer to the linked list of cuts.]
+ Synopsis [Filters cuts using dominance.]
Description []
@@ -81,14 +68,293 @@ Cut_Cut_t * Cut_NodeReadCuts( Cut_Man_t * p, int Node )
SeeAlso []
***********************************************************************/
-void Cut_NodeWriteCuts( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
+static inline void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList )
+{
+ Cut_Cut_t * pListR, ** ppListR = &pListR;
+ Cut_Cut_t * pCut, * pCut2, * pDom, * pPrev;
+ // save the first cut
+ *ppListR = pList, ppListR = &pList->pNext;
+ // try to filter out other cuts
+ pPrev = pList;
+ Cut_ListForEachCutSafe( pList->pNext, pCut, pCut2 )
+ {
+ assert( pCut->nLeaves > 1 );
+ // go through all the previous cuts up to pCut
+ Cut_ListForEachCutStop( pList->pNext, pDom, pCut )
+ {
+ if ( pDom->nLeaves > pCut->nLeaves )
+ continue;
+ if ( (pDom->uSign & pCut->uSign) != pDom->uSign )
+ continue;
+ if ( Cut_CutCheckDominance( pDom, pCut ) )
+ break;
+ }
+ if ( pDom != pCut ) // pDom is contained in pCut - recycle pCut
+ {
+ // make sure cuts are connected after removing
+ pPrev->pNext = pCut->pNext;
+ // recycle the cut
+ Cut_CutRecycle( p, pCut );
+ }
+ else // pDom is NOT contained in pCut - save pCut
+ {
+ *ppListR = pCut, ppListR = &pCut->pNext;
+ pPrev = pCut;
+ }
+ }
+ *ppListR = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks equality of one cut.]
+
+ Description [Returns 1 if the cut is removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cut_CutFilterOneEqual( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut )
{
- Vec_PtrWriteEntry( p->vCuts, Node, pList );
+ Cut_Cut_t * pTemp;
+ Cut_ListForEachCut( pSuperList->pHead[pCut->nLeaves], pTemp )
+ {
+ // skip the non-contained cuts
+ if ( pCut->uSign != pTemp->uSign )
+ continue;
+ // check containment seriously
+ if ( Cut_CutCheckDominance( pTemp, pCut ) )
+ {
+ p->nCutsFilter++;
+ Cut_CutRecycle( p, pCut );
+ return 1;
+ }
+ }
+ return 0;
}
/**Function*************************************************************
- Synopsis [Sets the trivial cut for the node.]
+ Synopsis [Checks containment for one cut.]
+
+ Description [Returns 1 if the cut is removed.]
+
+ SideEffects [May remove other cuts in the set.]
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cut_CutFilterOne( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut )
+{
+ Cut_Cut_t * pTemp, * pTemp2, ** ppTail;
+ int a;
+
+ // check if this cut is filtered out by smaller cuts
+ for ( a = 2; a <= (int)pCut->nLeaves; a++ )
+ {
+ Cut_ListForEachCut( pSuperList->pHead[a], pTemp )
+ {
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
+ continue;
+ // check containment seriously
+ if ( Cut_CutCheckDominance( pTemp, pCut ) )
+ {
+ p->nCutsFilter++;
+ Cut_CutRecycle( p, pCut );
+ return 1;
+ }
+ }
+ }
+
+ // filter out other cuts using this one
+ for ( a = pCut->nLeaves + 1; a <= (int)pCut->nVarsMax; a++ )
+ {
+ ppTail = pSuperList->pHead + a;
+ Cut_ListForEachCutSafe( pSuperList->pHead[a], pTemp, pTemp2 )
+ {
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
+ {
+ ppTail = &pTemp->pNext;
+ continue;
+ }
+ // check containment seriously
+ if ( Cut_CutCheckDominance( pCut, pTemp ) )
+ {
+ p->nCutsFilter++;
+ p->nNodeCuts--;
+ // move the head
+ if ( pSuperList->pHead[a] == pTemp )
+ pSuperList->pHead[a] = pTemp->pNext;
+ // move the tail
+ if ( pSuperList->ppTail[a] == &pTemp->pNext )
+ pSuperList->ppTail[a] = ppTail;
+ // skip the given cut in the list
+ *ppTail = pTemp->pNext;
+ // recycle pTemp
+ Cut_CutRecycle( p, pTemp );
+ }
+ else
+ ppTail = &pTemp->pNext;
+ }
+ assert( ppTail == pSuperList->ppTail[a] );
+ assert( *ppTail == NULL );
+ }
+
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the cut is local and can be removed.]
+
+ Description [Returns 1 if the cut is removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cut_CutFilterGlobal( Cut_Man_t * p, Cut_Cut_t * pCut )
+{
+ int a;
+ if ( pCut->nLeaves == 1 )
+ return 0;
+ for ( a = 0; a < (int)pCut->nLeaves; a++ )
+ if ( Vec_IntEntry( p->vNodeAttrs, pCut->pLeaves[a] ) ) // global
+ return 0;
+ // there is no global nodes, the cut should be removed
+ p->nCutsFilter++;
+ Cut_CutRecycle( p, pCut );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks containment for one cut.]
+
+ Description [Returns 1 if the cut is removed.]
+
+ SideEffects [May remove other cuts in the set.]
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cut_CutFilterOld( Cut_Man_t * p, Cut_Cut_t * pList, Cut_Cut_t * pCut )
+{
+ Cut_Cut_t * pPrev, * pTemp, * pTemp2, ** ppTail;
+
+ // check if this cut is filtered out by smaller cuts
+ pPrev = NULL;
+ Cut_ListForEachCut( pList, pTemp )
+ {
+ if ( pTemp->nLeaves > pCut->nLeaves )
+ break;
+ pPrev = pTemp;
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign )
+ continue;
+ // check containment seriously
+ if ( Cut_CutCheckDominance( pTemp, pCut ) )
+ {
+ p->nCutsFilter++;
+ Cut_CutRecycle( p, pCut );
+ return 1;
+ }
+ }
+ assert( pPrev->pNext == pTemp );
+
+ // filter out other cuts using this one
+ ppTail = &pPrev->pNext;
+ Cut_ListForEachCutSafe( pTemp, pTemp, pTemp2 )
+ {
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pCut->uSign) != pCut->uSign )
+ {
+ ppTail = &pTemp->pNext;
+ continue;
+ }
+ // check containment seriously
+ if ( Cut_CutCheckDominance( pCut, pTemp ) )
+ {
+ p->nCutsFilter++;
+ p->nNodeCuts--;
+ // skip the given cut in the list
+ *ppTail = pTemp->pNext;
+ // recycle pTemp
+ Cut_CutRecycle( p, pTemp );
+ }
+ else
+ ppTail = &pTemp->pNext;
+ }
+ assert( *ppTail == NULL );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Processes two cuts.]
+
+ Description [Returns 1 if the limit has been reached.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cut_CutProcessTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, Cut_List_t * pSuperList )
+{
+ Cut_Cut_t * pCut;
+ // merge the cuts
+ if ( pCut0->nLeaves >= pCut1->nLeaves )
+ pCut = Cut_CutMergeTwo( p, pCut0, pCut1 );
+ else
+ pCut = Cut_CutMergeTwo( p, pCut1, pCut0 );
+ if ( pCut == NULL )
+ return 0;
+ assert( p->pParams->fSeq || pCut->nLeaves > 1 );
+ // set the signature
+ pCut->uSign = pCut0->uSign | pCut1->uSign;
+ if ( p->pParams->fRecord )
+ pCut->Num0 = pCut0->Num0, pCut->Num1 = pCut1->Num0;
+ // check containment
+ if ( p->pParams->fFilter )
+ {
+ if ( Cut_CutFilterOne(p, pSuperList, pCut) )
+// if ( Cut_CutFilterOneEqual(p, pSuperList, pCut) )
+ return 0;
+ if ( p->pParams->fSeq )
+ {
+ if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) )
+ return 0;
+ if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) )
+ return 0;
+ }
+ }
+
+ if ( p->pParams->fGlobal )
+ {
+ assert( p->vNodeAttrs != NULL );
+ if ( Cut_CutFilterGlobal( p, pCut ) )
+ return 0;
+ }
+
+ // compute the truth table
+ if ( p->pParams->fTruth )
+ Cut_TruthCompute( p, pCut, pCut0, pCut1, p->fCompl0, p->fCompl1 );
+ // add to the list
+ Cut_ListAdd( pSuperList, pCut );
+ // return status (0 if okay; 1 if exceeded the limit)
+ return ++p->nNodeCuts == p->pParams->nKeepMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the cuts by merging cuts at two nodes.]
Description []
@@ -97,15 +363,68 @@ void Cut_NodeWriteCuts( Cut_Man_t * p, int Node, Cut_Cut_t * pList )
SeeAlso []
***********************************************************************/
-void Cut_NodeSetTriv( Cut_Man_t * p, int Node )
+Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode )
{
- assert( Cut_NodeReadCuts(p, Node) == NULL );
- Cut_NodeWriteCuts( p, Node, Cut_CutCreateTriv(p, Node) );
+ Cut_List_t Super, * pSuper = &Super;
+ Cut_Cut_t * pList, * pCut;
+ int clk;
+ // start the number of cuts at the node
+ p->nNodes++;
+ p->nNodeCuts = 0;
+ // prepare information for recording
+ if ( p->pParams->fRecord )
+ {
+ Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node0) );
+ Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node1) );
+ }
+ // compute the cuts
+clk = clock();
+ Cut_ListStart( pSuper );
+ Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, Cut_NodeReadCutsNew(p, Node0), Cut_NodeReadCutsNew(p, Node1), fTriv, TreeCode );
+ pList = Cut_ListFinish( pSuper );
+p->timeMerge += clock() - clk;
+ // verify the result of cut computation
+// Cut_CutListVerify( pList );
+ // performing the recording
+ if ( p->pParams->fRecord )
+ {
+ Vec_IntWriteEntry( p->vNodeStarts, Node, Vec_IntSize(p->vCutPairs) );
+ Cut_ListForEachCut( pList, pCut )
+ Vec_IntPush( p->vCutPairs, ((pCut->Num1 << 16) | pCut->Num0) );
+ Vec_IntWriteEntry( p->vNodeCuts, Node, Vec_IntSize(p->vCutPairs) - Vec_IntEntry(p->vNodeStarts, Node) );
+ }
+ // check if the node is over the list
+ if ( p->nNodeCuts == p->pParams->nKeepMax )
+ p->nCutsLimit++;
+ // set the list at the node
+ Vec_PtrFillExtra( p->vCutsNew, Node + 1, NULL );
+ assert( Cut_NodeReadCutsNew(p, Node) == NULL );
+ /////
+// pList->pNext = NULL;
+ /////
+ Cut_NodeWriteCutsNew( p, Node, pList );
+ // filter the cuts
+//clk = clock();
+// if ( p->pParams->fFilter )
+// Cut_CutFilter( p, pList0 );
+//p->timeFilter += clock() - clk;
+ // perform mapping of this node with these cuts
+clk = clock();
+ if ( p->pParams->fMap && !p->pParams->fSeq )
+ {
+// int Delay1, Delay2;
+// Delay1 = Cut_NodeMapping( p, pList, Node, Node0, Node1 );
+// Delay2 = Cut_NodeMapping2( p, pList, Node, Node0, Node1 );
+// assert( Delay1 >= Delay2 );
+ Cut_NodeMapping( p, pList, Node, Node0, Node1 );
+ }
+p->timeMap += clock() - clk;
+ return pList;
}
/**Function*************************************************************
- Synopsis [Deallocates the cuts at the node.]
+ Synopsis [Returns optimum delay mapping.]
Description []
@@ -114,21 +433,96 @@ void Cut_NodeSetTriv( Cut_Man_t * p, int Node )
SeeAlso []
***********************************************************************/
-void Cut_NodeFreeCuts( Cut_Man_t * p, int Node )
+int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 )
{
- Cut_Cut_t * pList, * pCut, * pCut2;
- pList = Cut_NodeReadCuts( p, Node );
- if ( pList == NULL )
- return;
- Cut_ListForEachCutSafe( pList, pCut, pCut2 )
- Cut_CutRecycle( p, pCut );
- Cut_NodeWriteCuts( p, Node, NULL );
+ Cut_Cut_t * pCut;
+ int DelayMin, DelayCur, i;
+ if ( pCuts == NULL )
+ p->nDelayMin = -1;
+ if ( p->nDelayMin == -1 )
+ return -1;
+ DelayMin = 1000000;
+ Cut_ListForEachCut( pCuts, pCut )
+ {
+ if ( pCut->nLeaves == 1 )
+ continue;
+ DelayCur = 0;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ if ( DelayCur < Vec_IntEntry(p->vDelays, pCut->pLeaves[i]) )
+ DelayCur = Vec_IntEntry(p->vDelays, pCut->pLeaves[i]);
+ if ( DelayMin > DelayCur )
+ DelayMin = DelayCur;
+ }
+ if ( DelayMin == 1000000 )
+ {
+ p->nDelayMin = -1;
+ return -1;
+ }
+ DelayMin++;
+ Vec_IntWriteEntry( p->vDelays, Node, DelayMin );
+ if ( p->nDelayMin < DelayMin )
+ p->nDelayMin = DelayMin;
+ return DelayMin;
}
+/**Function*************************************************************
+
+ Synopsis [Returns optimum delay mapping using the largest cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 )
+{
+ Cut_Cut_t * pCut0, * pCut1, * pCut;
+ int Delay0, Delay1, Delay;
+ // get the fanin cuts
+ Delay0 = Vec_IntEntry( p->vDelays2, Node0 );
+ Delay1 = Vec_IntEntry( p->vDelays2, Node1 );
+ pCut0 = (Delay0 == 0) ? Vec_PtrEntry( p->vCutsNew, Node0 ) : Vec_PtrEntry( p->vCutsMax, Node0 );
+ pCut1 = (Delay1 == 0) ? Vec_PtrEntry( p->vCutsNew, Node1 ) : Vec_PtrEntry( p->vCutsMax, Node1 );
+ if ( Delay0 == Delay1 )
+ Delay = (Delay0 == 0) ? Delay0 + 1: Delay0;
+ else if ( Delay0 > Delay1 )
+ {
+ Delay = Delay0;
+ pCut1 = Vec_PtrEntry( p->vCutsNew, Node1 );
+ assert( pCut1->nLeaves == 1 );
+ }
+ else // if ( Delay0 < Delay1 )
+ {
+ Delay = Delay1;
+ pCut0 = Vec_PtrEntry( p->vCutsNew, Node0 );
+ assert( pCut0->nLeaves == 1 );
+ }
+ // merge the cuts
+ if ( pCut0->nLeaves < pCut1->nLeaves )
+ pCut = Cut_CutMergeTwo( p, pCut1, pCut0 );
+ else
+ pCut = Cut_CutMergeTwo( p, pCut0, pCut1 );
+ if ( pCut == NULL )
+ {
+ Delay++;
+ pCut = Cut_CutAlloc( p );
+ pCut->nLeaves = 2;
+ pCut->pLeaves[0] = Node0 < Node1 ? Node0 : Node1;
+ pCut->pLeaves[1] = Node0 < Node1 ? Node1 : Node0;
+ }
+ assert( Delay > 0 );
+ Vec_IntWriteEntry( p->vDelays2, Node, Delay );
+ Vec_PtrWriteEntry( p->vCutsMax, Node, pCut );
+ if ( p->nDelayMin < Delay )
+ p->nDelayMin = Delay;
+ return Delay;
+}
/**Function*************************************************************
- Synopsis []
+ Synopsis [Computes area after mapping.]
Description []
@@ -137,10 +531,23 @@ void Cut_NodeFreeCuts( Cut_Man_t * p, int Node )
SeeAlso []
***********************************************************************/
-void Cut_NodeSetComputedAsNew( Cut_Man_t * p, int Node )
+int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node )
{
+ Cut_Cut_t * pCut;
+ int i, Counter;
+ if ( p->vCutsMax == NULL )
+ return 0;
+ pCut = Vec_PtrEntry( p->vCutsMax, Node );
+ if ( pCut == NULL || pCut->nLeaves == 1 )
+ return 0;
+ Counter = 0;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ Counter += Cut_ManMappingArea_rec( p, pCut->pLeaves[i] );
+ Vec_PtrWriteEntry( p->vCutsMax, Node, NULL );
+ return 1 + Counter;
}
+
/**Function*************************************************************
Synopsis [Computes the cuts by merging cuts at two nodes.]
@@ -152,24 +559,43 @@ void Cut_NodeSetComputedAsNew( Cut_Man_t * p, int Node )
SeeAlso []
***********************************************************************/
-Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 )
+void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode )
{
- Cut_List_t SuperList;
- Cut_Cut_t * pList0, * pList1, * pStop0, * pStop1, * pTemp0, * pTemp1;
- int i, Limit = p->pParams->nVarsMax;
- int clk = clock();
- assert( p->pParams->nVarsMax <= 6 );
- // start the new list
- Cut_ListStart( &SuperList );
+ Cut_Cut_t * pStop0, * pStop1, * pTemp0, * pTemp1, * pStore0, * pStore1;
+ int i, nCutsOld, Limit;
+ // start with the elementary cut
+ if ( fTriv )
+ {
+// printf( "Creating trivial cut %d.\n", Node );
+ pTemp0 = Cut_CutCreateTriv( p, Node );
+ Cut_ListAdd( pSuper, pTemp0 );
+ p->nNodeCuts++;
+ }
// get the cut lists of children
- pList0 = Cut_NodeReadCuts( p, Node0 );
- pList1 = Cut_NodeReadCuts( p, Node1 );
- assert( pList0 && pList1 );
+ if ( pList0 == NULL || pList1 == NULL || (p->pParams->fLocal && TreeCode) )
+ return;
+
+ // remember the old number of cuts
+ nCutsOld = p->nCutsCur;
+ Limit = p->pParams->nVarsMax;
// get the simultation bit of the node
p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul);
// set temporary variables
p->fCompl0 = fCompl0;
p->fCompl1 = fCompl1;
+ // if tree cuts are computed, make sure only the unit cuts propagate over the DAG nodes
+ if ( TreeCode & 1 )
+ {
+ assert( pList0->nLeaves == 1 );
+ pStore0 = pList0->pNext;
+ pList0->pNext = NULL;
+ }
+ if ( TreeCode & 2 )
+ {
+ assert( pList1->nLeaves == 1 );
+ pStore1 = pList1->pNext;
+ pList1->pNext = NULL;
+ }
// find the point in the list where the max-var cuts begin
Cut_ListForEachCut( pList0, pStop0 )
if ( pStop0->nLeaves == (unsigned)Limit )
@@ -177,101 +603,54 @@ Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1,
Cut_ListForEachCut( pList1, pStop1 )
if ( pStop1->nLeaves == (unsigned)Limit )
break;
- // start with the elementary cut
- pTemp0 = Cut_CutCreateTriv( p, Node );
- Cut_ListAdd( &SuperList, pTemp0 );
- p->nCutsNode = 1;
+
// small by small
Cut_ListForEachCutStop( pList0, pTemp0, pStop0 )
Cut_ListForEachCutStop( pList1, pTemp1, pStop1 )
- if ( Cut_CutProcessTwo( p, Node, pTemp0, pTemp1, &SuperList ) )
- goto finish;
- // all by large
- Cut_ListForEachCut( pList0, pTemp0 )
+ {
+ if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) )
+ goto Quits;
+ }
+ // small by large
+ Cut_ListForEachCutStop( pList0, pTemp0, pStop0 )
Cut_ListForEachCut( pStop1, pTemp1 )
- if ( Cut_CutProcessTwo( p, Node, pTemp0, pTemp1, &SuperList ) )
- goto finish;
- // all by large
- Cut_ListForEachCut( pList1, pTemp1 )
+ {
+ if ( (pTemp0->uSign & pTemp1->uSign) != pTemp0->uSign )
+ continue;
+ if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) )
+ goto Quits;
+ }
+ // small by large
+ Cut_ListForEachCutStop( pList1, pTemp1, pStop1 )
Cut_ListForEachCut( pStop0, pTemp0 )
- if ( Cut_CutProcessTwo( p, Node, pTemp0, pTemp1, &SuperList ) )
- goto finish;
+ {
+ if ( (pTemp0->uSign & pTemp1->uSign) != pTemp1->uSign )
+ continue;
+ if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) )
+ goto Quits;
+ }
// large by large
Cut_ListForEachCut( pStop0, pTemp0 )
Cut_ListForEachCut( pStop1, pTemp1 )
{
assert( pTemp0->nLeaves == (unsigned)Limit && pTemp1->nLeaves == (unsigned)Limit );
+ if ( pTemp0->uSign != pTemp1->uSign )
+ continue;
for ( i = 0; i < Limit; i++ )
if ( pTemp0->pLeaves[i] != pTemp1->pLeaves[i] )
break;
if ( i < Limit )
continue;
- if ( Cut_CutProcessTwo( p, Node, pTemp0, pTemp1, &SuperList ) )
- goto finish;
- }
-finish :
- // set the list at the node
- Vec_PtrFillExtra( p->vCuts, Node + 1, NULL );
- assert( Cut_NodeReadCuts(p, Node) == NULL );
- pList0 = Cut_ListFinish( &SuperList );
- Cut_NodeWriteCuts( p, Node, pList0 );
- // clear the hash table
- if ( p->pParams->fHash && !p->pParams->fSeq )
- Cut_TableClear( p->tTable );
- // consider dropping the fanins cuts
- if ( p->pParams->fDrop )
- {
- Cut_NodeTryDroppingCuts( p, Node0 );
- Cut_NodeTryDroppingCuts( p, Node1 );
- }
-p->timeMerge += clock() - clk;
- // filter the cuts
-clk = clock();
- if ( p->pParams->fFilter )
- Cut_CutFilter( p, pList0 );
-p->timeFilter += clock() - clk;
- p->nNodes++;
- return pList0;
-}
-
-/**Function*************************************************************
-
- Synopsis [Processes two cuts.]
-
- Description [Returns 1 if the limit has been reached.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Cut_CutProcessTwo( Cut_Man_t * p, int Root, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, Cut_List_t * pSuperList )
-{
- Cut_Cut_t * pCut;
- // merge the cuts
- if ( pCut0->nLeaves >= pCut1->nLeaves )
- pCut = Cut_CutMergeTwo( p, pCut0, pCut1 );
- else
- pCut = Cut_CutMergeTwo( p, pCut1, pCut0 );
- if ( pCut == NULL )
- return 0;
- assert( pCut->nLeaves > 1 );
- // add the root if sequential
- if ( p->pParams->fSeq )
- pCut->pLeaves[pCut->nLeaves] = Root;
- // check the lookup table
- if ( p->pParams->fHash && Cut_TableLookup( p->tTable, pCut, !p->pParams->fSeq ) )
- {
- Cut_CutRecycle( p, pCut );
- return 0;
- }
- // compute the truth table
- if ( p->pParams->fTruth )
- Cut_TruthCompute( p, pCut, pCut0, pCut1 );
- // add to the list
- Cut_ListAdd( pSuperList, pCut );
- // return status (0 if okay; 1 if exceeded the limit)
- return ++p->nCutsNode == p->pParams->nKeepMax;
+ if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) )
+ goto Quits;
+ }
+ if ( p->nNodeCuts == 0 )
+ p->nNodesNoCuts++;
+Quits:
+ if ( TreeCode & 1 )
+ pList0->pNext = pStore0;
+ if ( TreeCode & 2 )
+ pList1->pNext = pStore1;
}
/**Function*************************************************************
@@ -287,33 +666,32 @@ int Cut_CutProcessTwo( Cut_Man_t * p, int Root, Cut_Cut_t * pCut0, Cut_Cut_t * p
***********************************************************************/
Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes )
{
- Cut_List_t SuperList;
+ Cut_List_t Super, * pSuper = &Super;
Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop;
int i, k, Node, Root, Limit = p->pParams->nVarsMax;
int clk = clock();
- assert( p->pParams->nVarsMax <= 6 );
-
// start the new list
- Cut_ListStart( &SuperList );
+ Cut_ListStart( pSuper );
// remember the root node to save the resulting cuts
Root = Vec_IntEntry( vNodes, 0 );
- p->nCutsNode = 1;
+ p->nNodeCuts = 1;
// collect small cuts first
Vec_PtrClear( p->vTemp );
Vec_IntForEachEntry( vNodes, Node, i )
{
// get the cuts of this node
- pList = Cut_NodeReadCuts( p, Node );
- Cut_NodeWriteCuts( p, Node, NULL );
+ pList = Cut_NodeReadCutsNew( p, Node );
+ Cut_NodeWriteCutsNew( p, Node, NULL );
assert( pList );
// remember the starting point
pListStart = pList->pNext;
+ pList->pNext = NULL;
// save or recycle the elementary cut
if ( i == 0 )
- Cut_ListAdd( &SuperList, pList ), pTop = pList;
+ Cut_ListAdd( pSuper, pList ), pTop = pList;
else
Cut_CutRecycle( p, pList );
// save all the cuts that are smaller than the limit
@@ -324,20 +702,19 @@ Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes )
Vec_PtrPush( p->vTemp, pCut );
break;
}
- // check hash tables
- if ( p->pParams->fHash && Cut_TableLookup( p->tTable, pCut, !p->pParams->fSeq ) )
- {
- Cut_CutRecycle( p, pCut );
+ // check containment
+ if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
continue;
- }
// set the complemented bit by comparing the first cut with the current cut
pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
+ pListStart = pCut->pNext;
+ pCut->pNext = NULL;
// add to the list
- Cut_ListAdd( &SuperList, pCut );
- if ( ++p->nCutsNode == p->pParams->nKeepMax )
+ Cut_ListAdd( pSuper, pCut );
+ if ( ++p->nNodeCuts == p->pParams->nKeepMax )
{
// recycle the rest of the cuts of this node
- Cut_ListForEachCutSafe( pCut->pNext, pCut, pCut2 )
+ Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
Cut_CutRecycle( p, pCut );
// recycle all cuts of other nodes
Vec_IntForEachEntryStart( vNodes, Node, k, i+1 )
@@ -349,25 +726,25 @@ Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes )
goto finish;
}
}
- }
+ }
// collect larger cuts next
Vec_PtrForEachEntry( p->vTemp, pList, i )
{
Cut_ListForEachCutSafe( pList, pCut, pCut2 )
{
- if ( p->pParams->fHash && Cut_TableLookup( p->tTable, pCut, !p->pParams->fSeq ) )
- {
- Cut_CutRecycle( p, pCut );
+ // check containment
+ if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
continue;
- }
// set the complemented bit
pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
+ pListStart = pCut->pNext;
+ pCut->pNext = NULL;
// add to the list
- Cut_ListAdd( &SuperList, pCut );
- if ( ++p->nCutsNode == p->pParams->nKeepMax )
+ Cut_ListAdd( pSuper, pCut );
+ if ( ++p->nNodeCuts == p->pParams->nKeepMax )
{
// recycle the rest of the cuts
- Cut_ListForEachCutSafe( pCut->pNext, pCut, pCut2 )
+ Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
Cut_CutRecycle( p, pCut );
// recycle the saved cuts of other nodes
Vec_PtrForEachEntryStart( p->vTemp, pList, k, i+1 )
@@ -379,97 +756,22 @@ Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes )
}
finish :
// set the cuts at the node
- assert( Cut_NodeReadCuts(p, Root) == NULL );
- pList = Cut_ListFinish( &SuperList );
- Cut_NodeWriteCuts( p, Root, pList );
- // clear the hash table
- if ( p->pParams->fHash && !p->pParams->fSeq )
- Cut_TableClear( p->tTable );
+ assert( Cut_NodeReadCutsNew(p, Root) == NULL );
+ pList = Cut_ListFinish( pSuper );
+ Cut_NodeWriteCutsNew( p, Root, pList );
p->timeUnion += clock() - clk;
// filter the cuts
-clk = clock();
- if ( p->pParams->fFilter )
- Cut_CutFilter( p, pList );
-p->timeFilter += clock() - clk;
+//clk = clock();
+// if ( p->pParams->fFilter )
+// Cut_CutFilter( p, pList );
+//p->timeFilter += clock() - clk;
p->nNodes -= vNodes->nSize - 1;
return pList;
}
/**Function*************************************************************
- Synopsis [Start the cut computation.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p )
-{
- Cut_Cut_t * pCut;
- // cut allocation
- pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts );
- memset( pCut, 0, sizeof(Cut_Cut_t) );
- pCut->nVarsMax = p->pParams->nVarsMax;
- pCut->fSeq = p->pParams->fSeq;
- pCut->fSimul = p->fSimul;
- // statistics
- p->nCutsAlloc++;
- p->nCutsCur++;
- if ( p->nCutsPeak < p->nCutsAlloc - p->nCutsDealloc )
- p->nCutsPeak = p->nCutsAlloc - p->nCutsDealloc;
- return pCut;
-}
-
-/**Function*************************************************************
-
- Synopsis [Start the cut computation.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node )
-{
- Cut_Cut_t * pCut;
- pCut = Cut_CutAlloc( p );
- pCut->nLeaves = 1;
- pCut->pLeaves[0] = Node;
- if ( p->pParams->fTruth )
- Cut_CutWriteTruth( pCut, p->uTruthVars[0] );
- p->nCutsTriv++;
- return pCut;
-}
-
-/**Function*************************************************************
-
- Synopsis [Start the cut computation.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut )
-{
- p->nCutsDealloc++;
- p->nCutsCur--;
- if ( pCut->nLeaves == 1 )
- p->nCutsTriv--;
- Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut );
-}
-
-
-/**Function*************************************************************
-
- Synopsis [Consider dropping cuts if they are useless by now.]
+ Synopsis [Computes the cuts by unioning cuts at a choice node.]
Description []
@@ -478,85 +780,182 @@ void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut )
SeeAlso []
***********************************************************************/
-void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node )
+Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst )
{
- int nFanouts;
- assert( p->vFanCounts );
- nFanouts = Vec_IntEntry( p->vFanCounts, Node );
- assert( nFanouts > 0 );
- if ( --nFanouts == 0 )
- Cut_NodeFreeCuts( p, Node );
- Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts );
-}
+ Cut_List_t Super, * pSuper = &Super;
+ Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop;
+ int i, k, Node, Root, Limit = p->pParams->nVarsMax;
+ int clk = clock();
-/**Function*************************************************************
+ // start the new list
+ Cut_ListStart( pSuper );
- Synopsis [Print the cut.]
+ // remember the root node to save the resulting cuts
+ Root = Vec_IntEntry( vNodes, 0 );
+ p->nNodeCuts = 1;
- Description []
-
- SideEffects []
+ // store the original lists for comparison
+ p->pCompareOld = Cut_NodeReadCutsOld( p, Root );
+ p->pCompareNew = (CutSetNum >= 0)? Cut_NodeReadCutsNew( p, Root ) : NULL;
- SeeAlso []
+ // get the topmost cut
+ pTop = NULL;
+ if ( (pTop = Cut_NodeReadCutsOld( p, Root )) == NULL )
+ pTop = Cut_NodeReadCutsNew( p, Root );
+ assert( pTop != NULL );
-***********************************************************************/
-void Cut_CutPrint( Cut_Cut_t * pCut )
-{
- int i;
- assert( pCut->nLeaves > 0 );
- printf( "%d : {", pCut->nLeaves );
- for ( i = 0; i < (int)pCut->nLeaves; i++ )
- printf( " %d", pCut->pLeaves[i] );
- printf( " }" );
-}
+ // collect small cuts first
+ Vec_PtrClear( p->vTemp );
+ Vec_IntForEachEntry( vNodes, Node, i )
+ {
+ // get the cuts of this node
+ if ( i == 0 && CutSetNum >= 0 )
+ {
+ pList = Cut_NodeReadCutsTemp( p, CutSetNum );
+ Cut_NodeWriteCutsTemp( p, CutSetNum, NULL );
+ }
+ else
+ {
+ pList = Cut_NodeReadCutsNew( p, Node );
+ Cut_NodeWriteCutsNew( p, Node, NULL );
+ }
+ if ( pList == NULL )
+ continue;
-/**Function*************************************************************
+ // process the cuts
+ if ( fFirst )
+ {
+ // remember the starting point
+ pListStart = pList->pNext;
+ pList->pNext = NULL;
+ // save or recycle the elementary cut
+ if ( i == 0 )
+ Cut_ListAdd( pSuper, pList );
+ else
+ Cut_CutRecycle( p, pList );
+ }
+ else
+ pListStart = pList;
- Synopsis [Consider dropping cuts if they are useless by now.]
+ // save all the cuts that are smaller than the limit
+ Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
+ {
+ if ( pCut->nLeaves == (unsigned)Limit )
+ {
+ Vec_PtrPush( p->vTemp, pCut );
+ break;
+ }
+ // check containment
+// if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
+// continue;
+ if ( p->pParams->fFilter )
+ {
+ if ( Cut_CutFilterOne(p, pSuper, pCut) )
+ continue;
+ if ( p->pParams->fSeq )
+ {
+ if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) )
+ continue;
+ if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) )
+ continue;
+ }
+ }
- Description []
-
- SideEffects []
+ // set the complemented bit by comparing the first cut with the current cut
+ pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
+ pListStart = pCut->pNext;
+ pCut->pNext = NULL;
+ // add to the list
+ Cut_ListAdd( pSuper, pCut );
+ if ( ++p->nNodeCuts == p->pParams->nKeepMax )
+ {
+ // recycle the rest of the cuts of this node
+ Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
+ Cut_CutRecycle( p, pCut );
+ // recycle all cuts of other nodes
+ Vec_IntForEachEntryStart( vNodes, Node, k, i+1 )
+ Cut_NodeFreeCuts( p, Node );
+ // recycle the saved cuts of other nodes
+ Vec_PtrForEachEntry( p->vTemp, pList, k )
+ Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+ Cut_CutRecycle( p, pCut );
+ goto finish;
+ }
+ }
+ }
+ // collect larger cuts next
+ Vec_PtrForEachEntry( p->vTemp, pList, i )
+ {
+ Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+ {
+ // check containment
+// if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
+// continue;
+ if ( p->pParams->fFilter )
+ {
+ if ( Cut_CutFilterOne(p, pSuper, pCut) )
+ continue;
+ if ( p->pParams->fSeq )
+ {
+ if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) )
+ continue;
+ if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) )
+ continue;
+ }
+ }
- SeeAlso []
+ // set the complemented bit
+ pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
+ pListStart = pCut->pNext;
+ pCut->pNext = NULL;
+ // add to the list
+ Cut_ListAdd( pSuper, pCut );
+ if ( ++p->nNodeCuts == p->pParams->nKeepMax )
+ {
+ // recycle the rest of the cuts
+ Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
+ Cut_CutRecycle( p, pCut );
+ // recycle the saved cuts of other nodes
+ Vec_PtrForEachEntryStart( p->vTemp, pList, k, i+1 )
+ Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+ Cut_CutRecycle( p, pCut );
+ goto finish;
+ }
+ }
+ }
+finish :
+ // set the cuts at the node
+ pList = Cut_ListFinish( pSuper );
-***********************************************************************/
-void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
-{
- printf( "\n" );
- printf( "%d : %5d %5d %5d %5d %5d\n",
- pCut0->nLeaves,
- pCut0->nLeaves > 0 ? pCut0->pLeaves[0] : -1,
- pCut0->nLeaves > 1 ? pCut0->pLeaves[1] : -1,
- pCut0->nLeaves > 2 ? pCut0->pLeaves[2] : -1,
- pCut0->nLeaves > 3 ? pCut0->pLeaves[3] : -1,
- pCut0->nLeaves > 4 ? pCut0->pLeaves[4] : -1
- );
- printf( "%d : %5d %5d %5d %5d %5d\n",
- pCut1->nLeaves,
- pCut1->nLeaves > 0 ? pCut1->pLeaves[0] : -1,
- pCut1->nLeaves > 1 ? pCut1->pLeaves[1] : -1,
- pCut1->nLeaves > 2 ? pCut1->pLeaves[2] : -1,
- pCut1->nLeaves > 3 ? pCut1->pLeaves[3] : -1,
- pCut1->nLeaves > 4 ? pCut1->pLeaves[4] : -1
- );
- if ( pCut == NULL )
- printf( "Cannot merge\n" );
+ // set the lists at the node
+// assert( Cut_NodeReadCutsNew(p, Root) == NULL );
+// Cut_NodeWriteCutsNew( p, Root, pList );
+ if ( CutSetNum >= 0 )
+ {
+ assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL );
+ Cut_NodeWriteCutsTemp( p, CutSetNum, pList );
+ }
else
- printf( "%d : %5d %5d %5d %5d %5d\n",
- pCut->nLeaves,
- pCut->nLeaves > 0 ? pCut->pLeaves[0] : -1,
- pCut->nLeaves > 1 ? pCut->pLeaves[1] : -1,
- pCut->nLeaves > 2 ? pCut->pLeaves[2] : -1,
- pCut->nLeaves > 3 ? pCut->pLeaves[3] : -1,
- pCut->nLeaves > 4 ? pCut->pLeaves[4] : -1
- );
+ {
+ assert( Cut_NodeReadCutsNew(p, Root) == NULL );
+ Cut_NodeWriteCutsNew( p, Root, pList );
+ }
+
+p->timeUnion += clock() - clk;
+ // filter the cuts
+//clk = clock();
+// if ( p->pParams->fFilter )
+// Cut_CutFilter( p, pList );
+//p->timeFilter += clock() - clk;
+// if ( fFirst )
+// p->nNodes -= vNodes->nSize - 1;
+ return pList;
}
/**Function*************************************************************
- Synopsis [Filter the cuts using dominance.]
+ Synopsis [Verifies that the list contains only non-dominated cuts.]
Description []
@@ -565,62 +964,27 @@ void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
SeeAlso []
***********************************************************************/
-void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList )
+int Cut_CutListVerify( Cut_Cut_t * pList )
{
- Cut_Cut_t * pListR, ** ppListR = &pListR;
- Cut_Cut_t * pCut, * pCut2, * pDom, * pPrev;
- int i, k;
- // save the first cut
- *ppListR = pList, ppListR = &pList->pNext;
- // try to filter out other cuts
- pPrev = pList;
- Cut_ListForEachCutSafe( pList->pNext, pCut, pCut2 )
+ Cut_Cut_t * pCut, * pDom;
+ Cut_ListForEachCut( pList, pCut )
{
- assert( pCut->nLeaves > 1 );
- // go through all the previous cuts up to pCut
- Cut_ListForEachCutStop( pList->pNext, pDom, pCut )
+ Cut_ListForEachCutStop( pList, pDom, pCut )
{
- if ( pDom->nLeaves >= pCut->nLeaves )
- continue;
- // check if every node in pDom is contained in pCut
- for ( i = 0; i < (int)pDom->nLeaves; i++ )
+ if ( Cut_CutCheckDominance( pDom, pCut ) )
{
- 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
- break;
+ int x = 0;
+ printf( "******************* These are contained cuts:\n" );
+ Cut_CutPrint( pDom, 1 );
+ Cut_CutPrint( pDom, 1 );
+
+ return 0;
}
- if ( i == (int)pDom->nLeaves ) // every node in pDom is contained in pCut
- break;
- }
- if ( pDom != pCut ) // pDom is contained in pCut - recycle pCut
- {
- // make sure cuts are connected after removing
- pPrev->pNext = pCut->pNext;
-/*
- // report
- printf( "Recycling cut: " );
- Cut_CutPrint( pCut );
- printf( "\n" );
- printf( "As contained in: " );
- Cut_CutPrint( pDom );
- printf( "\n" );
-*/
- // recycle the cut
- Cut_CutRecycle( p, pCut );
- }
- else // pDom is NOT contained in pCut - save pCut
- {
- *ppListR = pCut, ppListR = &pCut->pNext;
- pPrev = pCut;
}
}
- *ppListR = NULL;
+ return 1;
}
-
-
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/cut/cutOracle.c b/src/opt/cut/cutOracle.c
new file mode 100644
index 00000000..3eb4462b
--- /dev/null
+++ b/src/opt/cut/cutOracle.c
@@ -0,0 +1,428 @@
+/**CFile****************************************************************
+
+ FileName [cutOracle.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [K-feasible cut computation package.]
+
+ Synopsis [Procedures to compute cuts for a node using the oracle.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cutOracle.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+struct Cut_OracleStruct_t_
+{
+ // cut comptupatation parameters
+ Cut_Params_t * pParams;
+ Vec_Int_t * vFanCounts;
+ int fSimul;
+ // storage for cuts
+ Vec_Ptr_t * vCutsNew;
+ Vec_Ptr_t * vCuts0;
+ Vec_Ptr_t * vCuts1;
+ // oracle info
+ Vec_Int_t * vNodeCuts;
+ Vec_Int_t * vNodeStarts;
+ Vec_Int_t * vCutPairs;
+ // memory management
+ Extra_MmFixed_t * pMmCuts;
+ int EntrySize;
+ int nTruthWords;
+ // stats
+ int timeTotal;
+ int nCuts;
+ int nCutsTriv;
+};
+
+static Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p );
+static Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node );
+static Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the cut oracle.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Oracle_t * Cut_OracleStart( Cut_Man_t * pMan )
+{
+ Cut_Oracle_t * p;
+ int clk = clock();
+
+ assert( pMan->pParams->nVarsMax >= 3 && pMan->pParams->nVarsMax <= CUT_SIZE_MAX );
+ assert( pMan->pParams->fRecord );
+
+ p = ALLOC( Cut_Oracle_t, 1 );
+ memset( p, 0, sizeof(Cut_Oracle_t) );
+
+ // set and correct parameters
+ p->pParams = pMan->pParams;
+
+ // transfer the recording info
+ p->vNodeCuts = pMan->vNodeCuts; pMan->vNodeCuts = NULL;
+ p->vNodeStarts = pMan->vNodeStarts; pMan->vNodeStarts = NULL;
+ p->vCutPairs = pMan->vCutPairs; pMan->vCutPairs = NULL;
+
+ // prepare storage for cuts
+ p->vCutsNew = Vec_PtrAlloc( p->pParams->nIdsMax );
+ Vec_PtrFill( p->vCutsNew, p->pParams->nIdsMax, NULL );
+ p->vCuts0 = Vec_PtrAlloc( 100 );
+ p->vCuts1 = Vec_PtrAlloc( 100 );
+
+ // entry size
+ p->EntrySize = sizeof(Cut_Cut_t) + p->pParams->nVarsMax * sizeof(int);
+ if ( p->pParams->fTruth )
+ {
+ if ( p->pParams->nVarsMax > 8 )
+ {
+ p->pParams->fTruth = 0;
+ printf( "Skipping computation of truth table for more than 8 inputs.\n" );
+ }
+ else
+ {
+ p->nTruthWords = Cut_TruthWords( p->pParams->nVarsMax );
+ p->EntrySize += p->nTruthWords * sizeof(unsigned);
+ }
+ }
+ // memory for cuts
+ p->pMmCuts = Extra_MmFixedStart( p->EntrySize );
+ return p;
+}
+/**Function*************************************************************
+
+ Synopsis [Stop the cut oracle.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_OracleStop( Cut_Oracle_t * p )
+{
+ Cut_Cut_t * pCut;
+ int i;
+
+// if ( p->pParams->fVerbose )
+ {
+ printf( "Cut computation statistics with oracle:\n" );
+ printf( "Current cuts = %8d. (Trivial = %d.)\n", p->nCuts-p->nCutsTriv, p->nCutsTriv );
+ PRT( "Total time ", p->timeTotal );
+ }
+
+ Vec_PtrForEachEntry( p->vCutsNew, pCut, i )
+ if ( pCut != NULL )
+ {
+ int k = 0;
+ }
+ if ( p->vCuts0 ) Vec_PtrFree( p->vCuts0 );
+ if ( p->vCuts1 ) Vec_PtrFree( p->vCuts1 );
+ if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew );
+ if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts );
+
+ if ( p->vNodeCuts ) Vec_IntFree( p->vNodeCuts );
+ if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts );
+ if ( p->vCutPairs ) Vec_IntFree( p->vCutPairs );
+
+ Extra_MmFixedStop( p->pMmCuts );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts )
+{
+ p->vFanCounts = vFanCounts;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_OracleReadDrop( Cut_Oracle_t * p )
+{
+ return p->pParams->fDrop;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the trivial cut for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node )
+{
+ assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL );
+ Vec_PtrWriteEntry( p->vCutsNew, Node, Cut_CutTriv(p, Node) );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p )
+{
+ Cut_Cut_t * pCut;
+ // cut allocation
+ pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts );
+ memset( pCut, 0, sizeof(Cut_Cut_t) );
+ pCut->nVarsMax = p->pParams->nVarsMax;
+ pCut->fSimul = p->fSimul;
+ p->nCuts++;
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the trivial cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node )
+{
+ Cut_Cut_t * pCut;
+ pCut = Cut_CutStart( p );
+ pCut->nLeaves = 1;
+ pCut->pLeaves[0] = Node;
+ if ( p->pParams->fTruth )
+ {
+ unsigned * pTruth = Cut_CutReadTruth(pCut);
+ int i;
+ for ( i = 0; i < p->nTruthWords; i++ )
+ pTruth[i] = 0xAAAAAAAA;
+ }
+ p->nCutsTriv++;
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+{
+ Cut_Cut_t * pCut;
+ int Limit, i, k, c;
+ // create the leaves of the new cut
+ pCut = Cut_CutStart( p );
+ Limit = p->pParams->nVarsMax;
+ for ( i = k = c = 0; c < Limit; c++ )
+ {
+ if ( k == (int)pCut1->nLeaves )
+ {
+ if ( i == (int)pCut0->nLeaves )
+ {
+ pCut->nLeaves = c;
+ return pCut;
+ }
+ pCut->pLeaves[c] = pCut0->pLeaves[i++];
+ continue;
+ }
+ if ( i == (int)pCut0->nLeaves )
+ {
+ if ( k == (int)pCut1->nLeaves )
+ {
+ pCut->nLeaves = c;
+ return pCut;
+ }
+ pCut->pLeaves[c] = pCut1->pLeaves[k++];
+ continue;
+ }
+ if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] )
+ {
+ pCut->pLeaves[c] = pCut0->pLeaves[i++];
+ continue;
+ }
+ if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] )
+ {
+ pCut->pLeaves[c] = pCut1->pLeaves[k++];
+ continue;
+ }
+ pCut->pLeaves[c] = pCut0->pLeaves[i++];
+ k++;
+ }
+ assert( i == (int)pCut0->nLeaves && k == (int)pCut1->nLeaves );
+ pCut->nLeaves = c;
+ return pCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reconstruct the cuts of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 )
+{
+ Cut_Cut_t * pList = NULL, ** ppTail = &pList;
+ Cut_Cut_t * pCut, * pCut0, * pCut1, * pList0, * pList1;
+ int iCutStart, nCuts, i, Entry;
+ int clk = clock();
+
+ // get the cuts of the children
+ pList0 = Vec_PtrEntry( p->vCutsNew, Node0 );
+ pList1 = Vec_PtrEntry( p->vCutsNew, Node1 );
+ assert( pList0 && pList1 );
+
+ // get the complemented attribute of the cut
+ p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul);
+
+ // collect the cuts
+ Vec_PtrClear( p->vCuts0 );
+ Cut_ListForEachCut( pList0, pCut )
+ Vec_PtrPush( p->vCuts0, pCut );
+ Vec_PtrClear( p->vCuts1 );
+ Cut_ListForEachCut( pList1, pCut )
+ Vec_PtrPush( p->vCuts1, pCut );
+
+ // get the first and last cuts of this node
+ nCuts = Vec_IntEntry(p->vNodeCuts, Node);
+ iCutStart = Vec_IntEntry(p->vNodeStarts, Node);
+
+ // create trivial cut
+ assert( Vec_IntEntry(p->vCutPairs, iCutStart) == 0 );
+ pCut = Cut_CutTriv( p, Node );
+ *ppTail = pCut;
+ ppTail = &pCut->pNext;
+ // create other cuts
+ for ( i = 1; i < nCuts; i++ )
+ {
+ Entry = Vec_IntEntry( p->vCutPairs, iCutStart + i );
+ pCut0 = Vec_PtrEntry( p->vCuts0, Entry & 0xFFFF );
+ pCut1 = Vec_PtrEntry( p->vCuts1, Entry >> 16 );
+ pCut = Cut_CutMerge( p, pCut0, pCut1 );
+ *ppTail = pCut;
+ ppTail = &pCut->pNext;
+ // compute the truth table
+ if ( p->pParams->fTruth )
+ Cut_TruthComputeOld( pCut, pCut0, pCut1, fCompl0, fCompl1 );
+ }
+ *ppTail = NULL;
+
+ // write the new cut
+ assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL );
+ Vec_PtrWriteEntry( p->vCutsNew, Node, pList );
+p->timeTotal += clock() - clk;
+ return pList;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the cuts at the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_OracleFreeCuts( Cut_Oracle_t * p, int Node )
+{
+ Cut_Cut_t * pList, * pCut, * pCut2;
+ pList = Vec_PtrEntry( p->vCutsNew, Node );
+ if ( pList == NULL )
+ return;
+ Cut_ListForEachCutSafe( pList, pCut, pCut2 )
+ Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut );
+ Vec_PtrWriteEntry( p->vCutsNew, Node, pList );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Consider dropping cuts if they are useless by now.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node )
+{
+ int nFanouts;
+ assert( p->vFanCounts );
+ nFanouts = Vec_IntEntry( p->vFanCounts, Node );
+ assert( nFanouts > 0 );
+ if ( --nFanouts == 0 )
+ Cut_OracleFreeCuts( p, Node );
+ Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/cut/cutPre22.c b/src/opt/cut/cutPre22.c
new file mode 100644
index 00000000..5cb87a9c
--- /dev/null
+++ b/src/opt/cut/cutPre22.c
@@ -0,0 +1,988 @@
+/**CFile****************************************************************
+
+ FileName [cutPre22.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Precomputes truth tables for the 2x2 macro cell.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cutPre22.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cutInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define CUT_CELL_MVAR 9
+
+typedef struct Cut_Cell_t_ Cut_Cell_t;
+typedef struct Cut_CMan_t_ Cut_CMan_t;
+
+struct Cut_Cell_t_
+{
+ Cut_Cell_t * pNext; // pointer to the next cell in the table
+ Cut_Cell_t * pNextVar; // pointer to the next cell of this support size
+ Cut_Cell_t * pParent; // pointer to the cell used to derive this one
+ int nUsed; // the number of times the cell is used
+ char Box[4]; // functions in the boxes
+ unsigned nVars : 4; // the number of variables
+ unsigned CrossBar0 : 4; // the variable set equal
+ unsigned CrossBar1 : 4; // the variable set equal
+ unsigned CrossBarPhase : 2; // the phase of the cross bar (0, 1, or 2)
+ unsigned CanonPhase : 18; // the canonical phase
+ char CanonPerm[CUT_CELL_MVAR+3]; // semicanonical permutation
+ short Store[2*CUT_CELL_MVAR]; // minterm counts in the cofactors
+ unsigned uTruth[1<<(CUT_CELL_MVAR-5)]; // the current truth table
+};
+
+struct Cut_CMan_t_
+{
+ // storage for canonical cells
+ Extra_MmFixed_t * pMem;
+ st_table * tTable;
+ Cut_Cell_t * pSameVar[CUT_CELL_MVAR+1];
+ // elementary truth tables
+ unsigned uInputs[CUT_CELL_MVAR][1<<(CUT_CELL_MVAR-5)];
+ // temporary truth tables
+ unsigned uTemp1[22][1<<(CUT_CELL_MVAR-5)];
+ unsigned uTemp2[22][1<<(CUT_CELL_MVAR-5)];
+ unsigned uTemp3[22][1<<(CUT_CELL_MVAR-5)];
+ unsigned uFinal[1<<(CUT_CELL_MVAR-5)];
+ unsigned puAux[1<<(CUT_CELL_MVAR-5)];
+ // statistical variables
+ int nTotal;
+ int nGood;
+ int nVarCounts[CUT_CELL_MVAR+1];
+ int nSymGroups[CUT_CELL_MVAR+1];
+ int nSymGroupsE[CUT_CELL_MVAR+1];
+ int timeCanon;
+ int timeSupp;
+ int timeTable;
+ int nCellFound;
+ int nCellNotFound;
+};
+
+// NP-classes of functions of 3 variables (22)
+static char * s_NP3[22] = {
+ " 0\n", // 00 const 0 // 0 vars
+ " 1\n", // 01 const 1 // 0 vars
+ "1 1\n", // 02 a // 1 vars
+ "11 1\n", // 03 ab // 2 vars
+ "11 0\n", // 04 (ab)' // 2 vars
+ "10 1\n01 1\n", // 05 a<+>b // 2 vars
+ "111 1\n", // 06 0s abc // 3 vars
+ "111 0\n", // 07 (abc)' //
+ "11- 1\n1-1 1\n", // 08 1p a(b+c) //
+ "11- 0\n1-1 0\n", // 09 (a(b+c))' //
+ "111 1\n100 1\n010 1\n001 1\n", // 10 2s a<+>b<+>c //
+ "10- 0\n1-0 0\n011 0\n", // 11 3p a<+>bc //
+ "101 1\n110 1\n", // 12 4p a(b<+>c) //
+ "101 0\n110 0\n", // 13 (a(b<+>c))' //
+ "11- 1\n1-1 1\n-11 1\n", // 14 5s ab+bc+ac //
+ "111 1\n000 1\n", // 15 6s abc+a'b'c' //
+ "111 0\n000 0\n", // 16 (abc+a'b'c')' //
+ "11- 1\n-11 1\n0-1 1\n", // 17 7 ab+bc+a'c //
+ "011 1\n101 1\n110 1\n", // 18 8s a'bc+ab'c+abc' //
+ "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' //
+ "100 1\n-11 1\n", // 20 9p ab'c'+bc //
+ "100 0\n-11 0\n" // 21 (ab'c'+bc)' //
+};
+
+// NP-classes of functions of 3 variables (22)
+static char * s_NP3Names[22] = {
+ " const 0 ",
+ " const 1 ",
+ " a ",
+ " ab ",
+ " (ab)' ",
+ " a<+>b ",
+ "0s abc ",
+ " (abc)' ",
+ "1p a(b+c) ",
+ " (a(b+c))' ",
+ "2s a<+>b<+>c ",
+ "3p a<+>bc ",
+ "4p a(b<+>c) ",
+ " (a(b<+>c))' ",
+ "5s ab+bc+ac ",
+ "6s abc+a'b'c' ",
+ " (abc+a'b'c')' ",
+ "7 ab+bc+a'c ",
+ "8s a'bc+ab'c+abc' ",
+ " (a'bc+ab'c+abc')' ",
+ "9p ab'c'+bc ",
+ " (ab'c'+bc)' "
+};
+
+// the number of variables in each function
+static int s_NP3VarNums[22] = { 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
+
+// NPN classes of functions of exactly 3 inputs (10)
+static int s_NPNe3[10] = { 6, 8, 10, 11, 12, 14, 15, 17, 18, 20 };
+
+// NPN classes of functions of exactly 3 inputs that are symmetric (5)
+static int s_NPNe3s[10] = { 6, 10, 14, 15, 18 };
+
+// NPN classes of functions of exactly 3 inputs (4)
+static int s_NPNe3p[10] = { 8, 11, 12, 20 };
+
+static Cut_CMan_t * Cut_CManStart();
+static void Cut_CManStop( Cut_CMan_t * p );
+static void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type );
+static void Cut_CellCanonicize( Cut_CMan_t * p, Cut_Cell_t * pCell );
+static int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell );
+static void Cut_CellSuppMin( Cut_Cell_t * pCell );
+static void Cut_CellCrossBar( Cut_Cell_t * pCell );
+
+
+static Cut_CMan_t * s_pCMan = NULL;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Start the precomputation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CellLoad()
+{
+ FILE * pFile;
+ char * pFileName = "cells22_daomap_iwls.txt";
+ char pString[1000];
+ Cut_CMan_t * p;
+ Cut_Cell_t * pCell;
+ int Length; //, i;
+ pFile = fopen( pFileName, "r" );
+ if ( pFile == NULL )
+ {
+ printf( "Cannot open file \"%s\".\n", pFileName );
+ return;
+ }
+ // start the manager
+ p = Cut_CManStart();
+ // load truth tables
+ while ( fgets(pString, 1000, pFile) )
+ {
+ Length = strlen(pString);
+ pString[Length--] = 0;
+ if ( Length == 0 )
+ continue;
+ // derive the cell
+ pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = Extra_Base2Log(Length*4);
+ pCell->nUsed = 1;
+// Extra_TruthCopy( pCell->uTruth, pTruth, nVars );
+ Extra_ReadHexadecimal( pCell->uTruth, pString, pCell->nVars );
+ Cut_CellSuppMin( pCell );
+/*
+ // set the elementary permutation
+ for ( i = 0; i < (int)pCell->nVars; i++ )
+ pCell->CanonPerm[i] = i;
+ // canonicize
+ pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
+*/
+ // add to the table
+ p->nTotal++;
+
+// Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); printf( "\n" );
+// if ( p->nTotal == 500 )
+// break;
+
+ if ( !Cut_CellTableLookup( p, pCell ) ) // new cell
+ p->nGood++;
+ }
+ printf( "Read %d cells from file \"%s\". Added %d cells to the table.\n", p->nTotal, pFileName, p->nGood );
+ fclose( pFile );
+// return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Precomputes truth tables for the 2x2 macro cell.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CellPrecompute()
+{
+ Cut_CMan_t * p;
+ Cut_Cell_t * pCell, * pTemp;
+ int i1, i2, i3, i, j, k, c, clk = clock(), clk2 = clock();
+
+ p = Cut_CManStart();
+
+ // precompute truth tables
+ for ( i = 0; i < 22; i++ )
+ Cut_CellTruthElem( p->uInputs[0], p->uInputs[1], p->uInputs[2], p->uTemp1[i], 9, i );
+ for ( i = 0; i < 22; i++ )
+ Cut_CellTruthElem( p->uInputs[3], p->uInputs[4], p->uInputs[5], p->uTemp2[i], 9, i );
+ for ( i = 0; i < 22; i++ )
+ Cut_CellTruthElem( p->uInputs[6], p->uInputs[7], p->uInputs[8], p->uTemp3[i], 9, i );
+/*
+ if ( k == 8 && ((i1 == 6 && i2 == 14 && i3 == 20) || (i1 == 20 && i2 == 6 && i3 == 14)) )
+ {
+ Extra_PrintBinary( stdout, &pCell->CanonPhase, pCell->nVars+1 ); printf( " : " );
+ for ( i = 0; i < pCell->nVars; i++ )
+ printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] );
+ Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars );
+ printf( "\n" );
+ }
+*/
+/*
+ // go through symmetric roots
+ for ( k = 0; k < 5; k++ )
+ for ( i1 = 0; i1 < 22; i1++ )
+ for ( i2 = i1; i2 < 22; i2++ )
+ for ( i3 = i2; i3 < 22; i3++ )
+ {
+ // derive the cell
+ pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = 9;
+ pCell->Box[0] = s_NPNe3s[k];
+ pCell->Box[1] = i1;
+ pCell->Box[2] = i2;
+ pCell->Box[3] = i3;
+ // fill in the truth table
+ Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3s[k] );
+ // canonicize
+ Cut_CellCanonicize( pCell );
+
+ // add to the table
+ p->nTotal++;
+ if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+ Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+ else
+ p->nGood++;
+ }
+
+ // go through partially symmetric roots
+ for ( k = 0; k < 4; k++ )
+ for ( i1 = 0; i1 < 22; i1++ )
+ for ( i2 = 0; i2 < 22; i2++ )
+ for ( i3 = i2; i3 < 22; i3++ )
+ {
+ // derive the cell
+ pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = 9;
+ pCell->Box[0] = s_NPNe3p[k];
+ pCell->Box[1] = i1;
+ pCell->Box[2] = i2;
+ pCell->Box[3] = i3;
+ // fill in the truth table
+ Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3p[k] );
+ // canonicize
+ Cut_CellCanonicize( pCell );
+
+ // add to the table
+ p->nTotal++;
+ if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+ Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+ else
+ p->nGood++;
+ }
+
+ // go through non-symmetric functions
+ for ( i1 = 0; i1 < 22; i1++ )
+ for ( i2 = 0; i2 < 22; i2++ )
+ for ( i3 = 0; i3 < 22; i3++ )
+ {
+ // derive the cell
+ pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = 9;
+ pCell->Box[0] = 17;
+ pCell->Box[1] = i1;
+ pCell->Box[2] = i2;
+ pCell->Box[3] = i3;
+ // fill in the truth table
+ Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, 17 );
+ // canonicize
+ Cut_CellCanonicize( pCell );
+
+ // add to the table
+ p->nTotal++;
+ if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+ Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+ else
+ p->nGood++;
+ }
+*/
+
+ // go through non-symmetric functions
+ for ( k = 0; k < 10; k++ )
+ for ( i1 = 0; i1 < 22; i1++ )
+ for ( i2 = 0; i2 < 22; i2++ )
+ for ( i3 = 0; i3 < 22; i3++ )
+ {
+ // derive the cell
+ pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = 9;
+ pCell->Box[0] = s_NPNe3[k];
+ pCell->Box[1] = i1;
+ pCell->Box[2] = i2;
+ pCell->Box[3] = i3;
+ // set the elementary permutation
+ for ( i = 0; i < (int)pCell->nVars; i++ )
+ pCell->CanonPerm[i] = i;
+ // fill in the truth table
+ Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3[k] );
+ // minimize the support
+ Cut_CellSuppMin( pCell );
+
+ // canonicize
+ pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
+
+ // add to the table
+ p->nTotal++;
+ if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+ Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+ else
+ {
+ p->nGood++;
+ p->nVarCounts[pCell->nVars]++;
+
+ if ( pCell->nVars )
+ for ( i = 0; i < (int)pCell->nVars-1; i++ )
+ {
+ if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric
+ continue;
+ // i and i+1 can be symmetric
+ // find the end of this group
+ for ( j = i+1; j < (int)pCell->nVars; j++ )
+ if ( pCell->Store[2*i] != pCell->Store[2*j] )
+ break;
+
+ if ( pCell->Store[2*i] == pCell->Store[2*i+1] )
+ p->nSymGroupsE[j-i]++;
+ else
+ p->nSymGroups[j-i]++;
+ i = j - 1;
+ }
+/*
+ if ( pCell->nVars == 3 )
+ {
+ Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" );
+ for ( i = 0; i < (int)pCell->nVars; i++ )
+ printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] );
+ printf( "\n" );
+ }
+*/
+ }
+ }
+
+ printf( "BASIC: Total = %d. Good = %d. Entry = %d. ", p->nTotal, p->nGood, sizeof(Cut_Cell_t) );
+ PRT( "Time", clock() - clk );
+ printf( "Cells: " );
+ for ( i = 0; i <= 9; i++ )
+ printf( "%d=%d ", i, p->nVarCounts[i] );
+ printf( "\nDiffs: " );
+ for ( i = 0; i <= 9; i++ )
+ printf( "%d=%d ", i, p->nSymGroups[i] );
+ printf( "\nEquals: " );
+ for ( i = 0; i <= 9; i++ )
+ printf( "%d=%d ", i, p->nSymGroupsE[i] );
+ printf( "\n" );
+
+ // continue adding new cells using support
+ for ( k = CUT_CELL_MVAR; k > 3; k-- )
+ {
+ for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar )
+ for ( i1 = 0; i1 < k; i1++ )
+ for ( i2 = i1+1; i2 < k; i2++ )
+ for ( c = 0; c < 3; c++ )
+ {
+ // derive the cell
+ pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = pTemp->nVars;
+ pCell->pParent = pTemp;
+ // set the elementary permutation
+ for ( i = 0; i < (int)pCell->nVars; i++ )
+ pCell->CanonPerm[i] = i;
+ // fill in the truth table
+ Extra_TruthCopy( pCell->uTruth, pTemp->uTruth, pTemp->nVars );
+ // create the cross-bar
+ pCell->CrossBar0 = i1;
+ pCell->CrossBar1 = i2;
+ pCell->CrossBarPhase = c;
+ Cut_CellCrossBar( pCell );
+ // minimize the support
+//clk2 = clock();
+ Cut_CellSuppMin( pCell );
+//p->timeSupp += clock() - clk2;
+ // canonicize
+//clk2 = clock();
+ pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
+//p->timeCanon += clock() - clk2;
+
+ // add to the table
+//clk2 = clock();
+ p->nTotal++;
+ if ( Cut_CellTableLookup( p, pCell ) ) // already exists
+ Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
+ else
+ {
+ p->nGood++;
+ p->nVarCounts[pCell->nVars]++;
+
+ for ( i = 0; i < (int)pCell->nVars-1; i++ )
+ {
+ if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric
+ continue;
+ // i and i+1 can be symmetric
+ // find the end of this group
+ for ( j = i+1; j < (int)pCell->nVars; j++ )
+ if ( pCell->Store[2*i] != pCell->Store[2*j] )
+ break;
+
+ if ( pCell->Store[2*i] == pCell->Store[2*i+1] )
+ p->nSymGroupsE[j-i]++;
+ else
+ p->nSymGroups[j-i]++;
+ i = j - 1;
+ }
+/*
+ if ( pCell->nVars == 3 )
+ {
+ Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" );
+ for ( i = 0; i < (int)pCell->nVars; i++ )
+ printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] );
+ printf( "\n" );
+ }
+*/
+ }
+//p->timeTable += clock() - clk2;
+ }
+
+ printf( "VAR %d: Total = %d. Good = %d. Entry = %d. ", k, p->nTotal, p->nGood, sizeof(Cut_Cell_t) );
+ PRT( "Time", clock() - clk );
+ printf( "Cells: " );
+ for ( i = 0; i <= 9; i++ )
+ printf( "%d=%d ", i, p->nVarCounts[i] );
+ printf( "\nDiffs: " );
+ for ( i = 0; i <= 9; i++ )
+ printf( "%d=%d ", i, p->nSymGroups[i] );
+ printf( "\nEquals: " );
+ for ( i = 0; i <= 9; i++ )
+ printf( "%d=%d ", i, p->nSymGroupsE[i] );
+ printf( "\n" );
+ }
+// printf( "\n" );
+ PRT( "Supp ", p->timeSupp );
+ PRT( "Canon", p->timeCanon );
+ PRT( "Table", p->timeTable );
+// Cut_CManStop( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check the table.]
+
+ Description [Returns 1 if such a truth table already exists.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell )
+{
+ Cut_Cell_t ** pSlot, * pTemp;
+ unsigned Hash;
+ Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum( pCell->nVars ) );
+ if ( !st_find_or_add( p->tTable, (char *)Hash, (char ***)&pSlot ) )
+ *pSlot = NULL;
+ for ( pTemp = *pSlot; pTemp; pTemp = pTemp->pNext )
+ {
+ if ( pTemp->nVars != pCell->nVars )
+ continue;
+ if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) )
+ return 1;
+ }
+ // the entry is new
+ pCell->pNext = *pSlot;
+ *pSlot = pCell;
+ // add it to the variable support list
+ pCell->pNextVar = p->pSameVar[pCell->nVars];
+ p->pSameVar[pCell->nVars] = pCell;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CellSuppMin( Cut_Cell_t * pCell )
+{
+ static unsigned uTemp[1<<(CUT_CELL_MVAR-5)];
+ unsigned * pIn, * pOut, * pTemp;
+ int i, k, Counter, Temp;
+
+ // go backward through the support variables and remove redundant
+ for ( k = pCell->nVars - 1; k >= 0; k-- )
+ if ( !Extra_TruthVarInSupport(pCell->uTruth, pCell->nVars, k) )
+ {
+ // shift all the variables above this one
+ Counter = 0;
+ pIn = pCell->uTruth; pOut = uTemp;
+ for ( i = k; i < (int)pCell->nVars - 1; i++ )
+ {
+ Extra_TruthSwapAdjacentVars( pOut, pIn, pCell->nVars, i );
+ pTemp = pIn; pIn = pOut; pOut = pTemp;
+ // swap the support vars
+ Temp = pCell->CanonPerm[i];
+ pCell->CanonPerm[i] = pCell->CanonPerm[i+1];
+ pCell->CanonPerm[i+1] = Temp;
+ Counter++;
+ }
+ // return the function back into its place
+ if ( Counter & 1 )
+ Extra_TruthCopy( pOut, pIn, pCell->nVars );
+ // remove one variable
+ pCell->nVars--;
+// Extra_PrintBinary( stdout, pCell->uTruth, (1<<pCell->nVars) ); printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CellCrossBar( Cut_Cell_t * pCell )
+{
+ static unsigned uTemp0[1<<(CUT_CELL_MVAR-5)];
+ static unsigned uTemp1[1<<(CUT_CELL_MVAR-5)];
+ Extra_TruthCopy( uTemp0, pCell->uTruth, pCell->nVars );
+ Extra_TruthCopy( uTemp1, pCell->uTruth, pCell->nVars );
+ if ( pCell->CanonPhase == 0 )
+ {
+ Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 );
+ Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 );
+ Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 );
+ Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 );
+ }
+ else if ( pCell->CanonPhase == 1 )
+ {
+ Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar0 );
+ Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 );
+ Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar0 );
+ Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 );
+ }
+ else if ( pCell->CanonPhase == 2 )
+ {
+ Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 );
+ Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar1 );
+ Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 );
+ Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar1 );
+ }
+ else assert( 0 );
+ Extra_TruthMux( pCell->uTruth, uTemp0, uTemp1, pCell->nVars, pCell->CrossBar0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type )
+{
+ int nWords = Extra_TruthWordNum( nVars );
+ int i;
+
+ assert( Type < 22 );
+ switch ( Type )
+ {
+ // " 0\n", // 00 const 0
+ case 0:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = 0;
+ return;
+ // " 1\n", // 01 const 1
+ case 1:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = 0xFFFFFFFF;
+ return;
+ // "1 1\n", // 02 a
+ case 2:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i];
+ return;
+ // "11 1\n", // 03 ab
+ case 3:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] & InB[i];
+ return;
+ // "11 0\n", // 04 (ab)'
+ case 4:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~(InA[i] & InB[i]);
+ return;
+ // "10 1\n01 1\n", // 05 a<+>b
+ case 5:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] ^ InB[i];
+ return;
+ // "111 1\n", // 06 + abc
+ case 6:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] & InB[i] & InC[i];
+ return;
+ // "111 0\n", // 07 (abc)'
+ case 7:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~(InA[i] & InB[i] & InC[i]);
+ return;
+ // "11- 1\n1-1 1\n", // 08 + a(b+c)
+ case 8:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] & (InB[i] | InC[i]);
+ return;
+ // "11- 0\n1-1 0\n", // 09 (a(b+c))'
+ case 9:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~(InA[i] & (InB[i] | InC[i]));
+ return;
+ // "111 1\n100 1\n010 1\n001 1\n", // 10 + a<+>b<+>c
+ case 10:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] ^ InB[i] ^ InC[i];
+ return;
+ // "10- 0\n1-0 0\n011 0\n", // 11 + a<+>bc
+ case 11:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] ^ (InB[i] & InC[i]);
+ return;
+ // "101 1\n110 1\n", // 12 + a(b<+>c)
+ case 12:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = InA[i] & (InB[i] ^ InC[i]);
+ return;
+ // "101 0\n110 0\n", // 13 (a(b<+>c))'
+ case 13:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~(InA[i] & (InB[i] ^ InC[i]));
+ return;
+ // "11- 1\n1-1 1\n-11 1\n", // 14 + ab+bc+ac
+ case 14:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (InA[i] & InC[i]);
+ return;
+ // "111 1\n000 1\n", // 15 + abc+a'b'c'
+ case 15:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]);
+ return;
+ // "111 0\n000 0\n", // 16 (abc+a'b'c')'
+ case 16:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~((InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]));
+ return;
+ // "11- 1\n-11 1\n0-1 1\n", // 17 + ab+bc+a'c
+ case 17:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (~InA[i] & InC[i]);
+ return;
+ // "011 1\n101 1\n110 1\n", // 18 + a'bc+ab'c+abc'
+ case 18:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]);
+ return;
+ // "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')'
+ case 19:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~((~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]));
+ return;
+ // "100 1\n-11 1\n", // 20 + ab'c'+bc
+ case 20:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = (InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]);
+ return;
+ // "100 0\n-11 0\n" // 21 (ab'c'+bc)'
+ case 21:
+ for ( i = 0; i < nWords; i++ )
+ pOut[i] = ~((InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]));
+ return;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Start the precomputation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cut_CMan_t * Cut_CManStart()
+{
+ Cut_CMan_t * p;
+ int i, k;
+ // start the manager
+ assert( sizeof(unsigned) == 4 );
+ p = ALLOC( Cut_CMan_t, 1 );
+ memset( p, 0, sizeof(Cut_CMan_t) );
+ // start the table and the memory manager
+ p->tTable = st_init_table(st_ptrcmp,st_ptrhash);
+ p->pMem = Extra_MmFixedStart( sizeof(Cut_Cell_t) );
+ // set elementary truth tables
+ for ( k = 0; k < CUT_CELL_MVAR; k++ )
+ for ( i = 0; i < (1<<CUT_CELL_MVAR); i++ )
+ if ( i & (1 << k) )
+ p->uInputs[k][i>>5] |= (1 << (i&31));
+ s_pCMan = p;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CManStop( Cut_CMan_t * p )
+{
+ st_free_table( p->tTable );
+ Extra_MmFixedStop( p->pMem );
+ free( p );
+}
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_CellIsRunning()
+{
+ return s_pCMan != NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_CellDumpToFile()
+{
+ FILE * pFile;
+ Cut_CMan_t * p = s_pCMan;
+ Cut_Cell_t * pTemp;
+ char * pFileName = "celllib22.txt";
+ int NumUsed[10][5] = {{0}};
+ int BoxUsed[22][5] = {{0}};
+ int i, k, Counter;
+ int clk = clock();
+
+ if ( p == NULL )
+ {
+ printf( "Cut_CellDumpToFile: Cell manager is not defined.\n" );
+ return;
+ }
+
+ // count the number of cells used
+ for ( k = CUT_CELL_MVAR; k >= 0; k-- )
+ {
+ for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar )
+ {
+ if ( pTemp->nUsed == 0 )
+ NumUsed[k][0]++;
+ else if ( pTemp->nUsed < 10 )
+ NumUsed[k][1]++;
+ else if ( pTemp->nUsed < 100 )
+ NumUsed[k][2]++;
+ else if ( pTemp->nUsed < 1000 )
+ NumUsed[k][3]++;
+ else
+ NumUsed[k][4]++;
+
+ for ( i = 0; i < 4; i++ )
+ if ( pTemp->nUsed == 0 )
+ BoxUsed[ pTemp->Box[i] ][0]++;
+ else if ( pTemp->nUsed < 10 )
+ BoxUsed[ pTemp->Box[i] ][1]++;
+ else if ( pTemp->nUsed < 100 )
+ BoxUsed[ pTemp->Box[i] ][2]++;
+ else if ( pTemp->nUsed < 1000 )
+ BoxUsed[ pTemp->Box[i] ][3]++;
+ else
+ BoxUsed[ pTemp->Box[i] ][4]++;
+ }
+ }
+
+ printf( "Functions found = %10d. Functions not found = %10d.\n", p->nCellFound, p->nCellNotFound );
+ for ( k = 0; k <= CUT_CELL_MVAR; k++ )
+ {
+ printf( "%3d : ", k );
+ for ( i = 0; i < 5; i++ )
+ printf( "%8d ", NumUsed[k][i] );
+ printf( "\n" );
+ }
+ printf( "Box usage:\n" );
+ for ( k = 0; k < 22; k++ )
+ {
+ printf( "%3d : ", k );
+ for ( i = 0; i < 5; i++ )
+ printf( "%8d ", BoxUsed[k][i] );
+ printf( " %s", s_NP3Names[k] );
+ printf( "\n" );
+ }
+
+ pFile = fopen( pFileName, "w" );
+ if ( pFile == NULL )
+ {
+ printf( "Cut_CellDumpToFile: Cannout open output file.\n" );
+ return;
+ }
+
+ Counter = 0;
+ for ( k = 0; k <= CUT_CELL_MVAR; k++ )
+ {
+ for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar )
+ if ( pTemp->nUsed > 0 )
+ {
+ Extra_PrintHexadecimal( pFile, pTemp->uTruth, (k <= 5? 5 : k) );
+ fprintf( pFile, "\n" );
+ Counter++;
+ }
+ fprintf( pFile, "\n" );
+ }
+ fclose( pFile );
+
+ printf( "Library composed of %d functions is written into file \"%s\". ", Counter, pFileName );
+
+ PRT( "Time", clock() - clk );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Looks up if the given function exists in the hash table.]
+
+ Description [If the function exists, returns 1, meaning that it can be
+ implemented using two levels of 3-input LUTs. If the function does not
+ exist, return 0.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_CellTruthLookup( unsigned * pTruth, int nVars )
+{
+ Cut_CMan_t * p = s_pCMan;
+ Cut_Cell_t * pTemp;
+ Cut_Cell_t Cell, * pCell = &Cell;
+ unsigned Hash;
+ int i;
+
+ // cell manager is not defined
+ if ( p == NULL )
+ {
+ printf( "Cut_CellTruthLookup: Cell manager is not defined.\n" );
+ return 0;
+ }
+
+ // canonicize
+ memset( pCell, 0, sizeof(Cut_Cell_t) );
+ pCell->nVars = nVars;
+ Extra_TruthCopy( pCell->uTruth, pTruth, nVars );
+ Cut_CellSuppMin( pCell );
+ // set the elementary permutation
+ for ( i = 0; i < (int)pCell->nVars; i++ )
+ pCell->CanonPerm[i] = i;
+ // canonicize
+ pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
+
+
+ // check if the cell exists
+ Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum(pCell->nVars) );
+ if ( st_lookup( p->tTable, (char *)Hash, (char **)&pTemp ) )
+ {
+ for ( ; pTemp; pTemp = pTemp->pNext )
+ {
+ if ( pTemp->nVars != pCell->nVars )
+ continue;
+ if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) )
+ {
+ pTemp->nUsed++;
+ p->nCellFound++;
+ return 1;
+ }
+ }
+ }
+ p->nCellNotFound++;
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/cut/cutSeq.c b/src/opt/cut/cutSeq.c
index 869bd7b3..d36f94f7 100644
--- a/src/opt/cut/cutSeq.c
+++ b/src/opt/cut/cutSeq.c
@@ -25,12 +25,12 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis []
+ Synopsis [Shifts all cut leaves of the node by the given number of latches.]
Description []
@@ -39,6 +39,186 @@
SeeAlso []
***********************************************************************/
+static inline void Cut_NodeShiftCutLeaves( Cut_Cut_t * pList, int nLat )
+{
+ Cut_Cut_t * pTemp;
+ int i;
+ // shift the cuts by as many latches
+ Cut_ListForEachCut( pList, pTemp )
+ {
+ pTemp->uSign = 0;
+ for ( i = 0; i < (int)pTemp->nLeaves; i++ )
+ {
+ pTemp->pLeaves[i] += nLat;
+ pTemp->uSign |= Cut_NodeSign( pTemp->pLeaves[i] );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes sequential cuts for the node from its fanins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum )
+{
+ Cut_List_t Super, * pSuper = &Super;
+ Cut_Cut_t * pListNew;
+ int clk;
+
+ // get the number of cuts at the node
+ p->nNodeCuts = Cut_CutCountList( Cut_NodeReadCutsOld(p, Node) );
+ if ( p->nNodeCuts >= p->pParams->nKeepMax )
+ return;
+
+ // count only the first visit
+ if ( p->nNodeCuts == 0 )
+ p->nNodes++;
+
+ // store the fanin lists
+ p->pStore0[0] = Cut_NodeReadCutsOld( p, Node0 );
+ p->pStore0[1] = Cut_NodeReadCutsNew( p, Node0 );
+ p->pStore1[0] = Cut_NodeReadCutsOld( p, Node1 );
+ p->pStore1[1] = Cut_NodeReadCutsNew( p, Node1 );
+
+ // duplicate the cut lists if fanin nodes are non-standard
+ if ( Node == Node0 || Node == Node1 || Node0 == Node1 )
+ {
+ p->pStore0[0] = Cut_CutDupList( p, p->pStore0[0] );
+ p->pStore0[1] = Cut_CutDupList( p, p->pStore0[1] );
+ p->pStore1[0] = Cut_CutDupList( p, p->pStore1[0] );
+ p->pStore1[1] = Cut_CutDupList( p, p->pStore1[1] );
+ }
+
+ // shift the cuts by as many latches and recompute signatures
+ if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[0], nLat0 );
+ if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[1], nLat0 );
+ if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[0], nLat1 );
+ if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[1], nLat1 );
+
+ // store the original lists for comparison
+ p->pCompareOld = Cut_NodeReadCutsOld( p, Node );
+ p->pCompareNew = Cut_NodeReadCutsNew( p, Node );
+
+ // merge the old and the new
+clk = clock();
+ Cut_ListStart( pSuper );
+ Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[0], p->pStore1[1], 0, 0 );
+ Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[0], 0, 0 );
+ Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[1], fTriv, 0 );
+ pListNew = Cut_ListFinish( pSuper );
+p->timeMerge += clock() - clk;
+
+ // shift the cuts by as many latches and recompute signatures
+ if ( Node == Node0 || Node == Node1 || Node0 == Node1 )
+ {
+ Cut_CutRecycleList( p, p->pStore0[0] );
+ Cut_CutRecycleList( p, p->pStore0[1] );
+ Cut_CutRecycleList( p, p->pStore1[0] );
+ Cut_CutRecycleList( p, p->pStore1[1] );
+ }
+ else
+ {
+ if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[0], -nLat0 );
+ if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[1], -nLat0 );
+ if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[0], -nLat1 );
+ if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[1], -nLat1 );
+ }
+
+ // set the lists at the node
+ if ( CutSetNum >= 0 )
+ {
+ assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL );
+ Cut_NodeWriteCutsTemp( p, CutSetNum, pListNew );
+ }
+ else
+ {
+ assert( Cut_NodeReadCutsNew(p, Node) == NULL );
+ Cut_NodeWriteCutsNew( p, Node, pListNew );
+ }
+
+ // mark the node if we exceeded the number of cuts
+ if ( p->nNodeCuts >= p->pParams->nKeepMax )
+ p->nCutsLimit++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges the new cuts with the old cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node )
+{
+ Cut_Cut_t * pListOld, * pListNew, * pList;
+ // get the new cuts
+ pListNew = Cut_NodeReadCutsNew( p, Node );
+ if ( pListNew == NULL )
+ return;
+ Cut_NodeWriteCutsNew( p, Node, NULL );
+ // get the old cuts
+ pListOld = Cut_NodeReadCutsOld( p, Node );
+ if ( pListOld == NULL )
+ {
+ Cut_NodeWriteCutsOld( p, Node, pListNew );
+ return;
+ }
+ // merge the lists
+ pList = Cut_CutMergeLists( pListOld, pListNew );
+ Cut_NodeWriteCutsOld( p, Node, pList );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the temporary cuts to be the new cuts.]
+
+ Description [Returns 1 if something was transferred.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cut_NodeTempTransferToNew( Cut_Man_t * p, int Node, int CutSetNum )
+{
+ Cut_Cut_t * pList;
+ pList = Cut_NodeReadCutsTemp( p, CutSetNum );
+ Cut_NodeWriteCutsTemp( p, CutSetNum, NULL );
+ Cut_NodeWriteCutsNew( p, Node, pList );
+ return pList != NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the old cuts to be the new cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cut_NodeOldTransferToNew( Cut_Man_t * p, int Node )
+{
+ Cut_Cut_t * pList;
+ pList = Cut_NodeReadCutsOld( p, Node );
+ Cut_NodeWriteCutsOld( p, Node, NULL );
+ Cut_NodeWriteCutsNew( p, Node, pList );
+// Cut_CutListVerify( pList );
+}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/opt/cut/cutTable.c b/src/opt/cut/cutTable.c
deleted file mode 100644
index 5dfaca7b..00000000
--- a/src/opt/cut/cutTable.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/**CFile****************************************************************
-
- FileName [cutTable.c]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [K-feasible cut computation package.]
-
- Synopsis [Hashing cuts to prevent duplication.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: cutTable.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#include "cutInt.h"
-
-////////////////////////////////////////////////////////////////////////
-/// DECLARATIONS ///
-////////////////////////////////////////////////////////////////////////
-
-struct Cut_HashTableStruct_t_
-{
- int nBins;
- Cut_Cut_t ** pBins;
- int nEntries;
- int * pPlaces;
- int nPlaces;
- int timeLookup;
-};
-
-// iterator through all the cuts of the list
-#define Cut_TableListForEachCut( pList, pCut ) \
- for ( pCut = pList; \
- pCut; \
- pCut = pCut->pData )
-#define Cut_TableListForEachCutSafe( pList, pCut, pCut2 ) \
- for ( pCut = pList, \
- pCut2 = pCut? pCut->pData: NULL; \
- pCut; \
- pCut = pCut2, \
- pCut2 = pCut? pCut->pData: NULL )
-
-// primes used to compute the hash key
-static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 };
-
-// hashing function
-static inline unsigned Cut_HashKey( Cut_Cut_t * pCut )
-{
- unsigned i, uRes = pCut->nLeaves * s_HashPrimes[9];
- for ( i = 0; i < pCut->nLeaves + pCut->fSeq; i++ )
- uRes += s_HashPrimes[i] * pCut->pLeaves[i];
- return uRes;
-}
-
-// hashing function
-static inline int Cut_CompareTwo( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 )
-{
- unsigned i;
- if ( pCut1->nLeaves != pCut2->nLeaves )
- return 1;
- for ( i = 0; i < pCut1->nLeaves; i++ )
- if ( pCut1->pLeaves[i] != pCut2->pLeaves[i] )
- return 1;
- return 0;
-}
-
-static void Cut_TableResize( Cut_HashTable_t * pTable );
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis [Starts the hash table.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Cut_HashTable_t * Cut_TableStart( int Size )
-{
- Cut_HashTable_t * pTable;
- pTable = ALLOC( Cut_HashTable_t, 1 );
- memset( pTable, 0, sizeof(Cut_HashTable_t) );
- // allocate the table
- pTable->nBins = Cudd_PrimeCopy( Size );
- pTable->pBins = ALLOC( Cut_Cut_t *, pTable->nBins );
- memset( pTable->pBins, 0, sizeof(Cut_Cut_t *) * pTable->nBins );
- pTable->pPlaces = ALLOC( int, pTable->nBins );
- return pTable;
-}
-
-/**Function*************************************************************
-
- Synopsis [Stops the hash table.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Cut_TableStop( Cut_HashTable_t * pTable )
-{
- FREE( pTable->pPlaces );
- free( pTable->pBins );
- free( pTable );
-}
-
-/**Function*************************************************************
-
- Synopsis [Check the existence of a cut in the lookup table]
-
- Description [Returns 1 if the entry is found.]
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Cut_TableLookup( Cut_HashTable_t * pTable, Cut_Cut_t * pCut, int fStore )
-{
- Cut_Cut_t * pEnt;
- unsigned Key;
- int clk = clock();
-
- Key = Cut_HashKey(pCut) % pTable->nBins;
- Cut_TableListForEachCut( pTable->pBins[Key], pEnt )
- {
- if ( !Cut_CompareTwo( pEnt, pCut ) )
- {
-pTable->timeLookup += clock() - clk;
- return 1;
- }
- }
- if ( pTable->nEntries > 2 * pTable->nBins )
- {
- Cut_TableResize( pTable );
- Key = Cut_HashKey(pCut) % pTable->nBins;
- }
- // remember the place
- if ( fStore && pTable->pBins[Key] == NULL )
- pTable->pPlaces[ pTable->nPlaces++ ] = Key;
- // add the cut to the table
- pCut->pData = pTable->pBins[Key];
- pTable->pBins[Key] = pCut;
- pTable->nEntries++;
-pTable->timeLookup += clock() - clk;
- return 0;
-}
-
-
-/**Function*************************************************************
-
- Synopsis [Stops the hash table.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Cut_TableClear( Cut_HashTable_t * pTable )
-{
- int i;
- assert( pTable->nPlaces <= pTable->nBins );
- for ( i = 0; i < pTable->nPlaces; i++ )
- {
- assert( pTable->pBins[ pTable->pPlaces[i] ] );
- pTable->pBins[ pTable->pPlaces[i] ] = NULL;
- }
- pTable->nPlaces = 0;
- pTable->nEntries = 0;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Cut_TableResize( Cut_HashTable_t * pTable )
-{
- Cut_Cut_t ** pBinsNew;
- Cut_Cut_t * pEnt, * pEnt2;
- int nBinsNew, Counter, i, clk;
- unsigned Key;
-
-clk = clock();
- // get the new table size
- nBinsNew = Cudd_PrimeCopy( 3 * pTable->nBins );
- // allocate a new array
- pBinsNew = ALLOC( Cut_Cut_t *, nBinsNew );
- memset( pBinsNew, 0, sizeof(Cut_Cut_t *) * nBinsNew );
- // rehash the entries from the old table
- Counter = 0;
- for ( i = 0; i < pTable->nBins; i++ )
- Cut_TableListForEachCutSafe( pTable->pBins[i], pEnt, pEnt2 )
- {
- Key = Cut_HashKey(pEnt) % nBinsNew;
- pEnt->pData = pBinsNew[Key];
- pBinsNew[Key] = pEnt;
- Counter++;
- }
- assert( Counter == pTable->nEntries );
-// printf( "Increasing the structural table size from %6d to %6d. ", pMan->nBins, nBinsNew );
-// PRT( "Time", clock() - clk );
- // replace the table and the parameters
- free( pTable->pBins );
- pTable->pBins = pBinsNew;
- pTable->nBins = nBinsNew;
-}
-
-/**Function*************************************************************
-
- Synopsis [Stops the hash table.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Cut_TableReadTime( Cut_HashTable_t * pTable )
-{
- if ( pTable == NULL )
- return 0;
- return pTable->timeLookup;
-}
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
-
diff --git a/src/opt/cut/cutTruth.c b/src/opt/cut/cutTruth.c
index efacd456..c3514ad7 100644
--- a/src/opt/cut/cutTruth.c
+++ b/src/opt/cut/cutTruth.c
@@ -20,21 +20,27 @@
#include "cutInt.h"
+/*
+ Truth tables computed in this package are represented as bit-strings
+ stored in the cut data structure. Cuts of any number of inputs have
+ the truth table with 2^k bits, where k is the max number of cut inputs.
+*/
+
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Cut_TruthCompute4( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
-static void Cut_TruthCompute5( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
-static void Cut_TruthCompute6( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 );
+extern int nTotal = 0;
+extern int nGood = 0;
+extern int nEqual = 0;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Performs truth table computation.]
+ Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.]
Description []
@@ -64,58 +70,42 @@ static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 )
Synopsis [Performs truth table computation.]
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
-{
-int clk = clock();
- if ( pCut->nVarsMax == 4 )
- Cut_TruthCompute4( p, pCut, pCut0, pCut1 );
- else if ( pCut->nVarsMax == 5 )
- Cut_TruthCompute5( p, pCut, pCut0, pCut1 );
- else // if ( pCut->nVarsMax == 6 )
- Cut_TruthCompute6( p, pCut, pCut0, pCut1 );
-p->timeTruth += clock() - clk;
-}
-
-/**Function*************************************************************
-
- Synopsis [Performs truth table computation.]
-
- Description []
+ Description [This procedure cannot be used while recording oracle
+ because it will overwrite Num0 and Num1.]
SideEffects []
SeeAlso []
***********************************************************************/
-void Cut_TruthCompute4( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+void Cut_TruthNCanonicize( Cut_Cut_t * pCut )
{
- unsigned * puTruthCut0, * puTruthCut1;
- unsigned uTruth0, uTruth1, uPhase;
-
- puTruthCut0 = Cut_CutReadTruth(pCut0);
- puTruthCut1 = Cut_CutReadTruth(pCut1);
-
- uPhase = Cut_TruthPhase( pCut, pCut0 );
- uTruth0 = Extra_TruthPerm4One( *puTruthCut0, uPhase );
- uTruth0 = p->fCompl0? ~uTruth0: uTruth0;
-
- uPhase = Cut_TruthPhase( pCut, pCut1 );
- uTruth1 = Extra_TruthPerm4One( *puTruthCut1, uPhase );
- uTruth1 = p->fCompl1? ~uTruth1: uTruth1;
+ unsigned uTruth;
+ unsigned * uCanon2;
+ char * pPhases2;
+ assert( pCut->nVarsMax < 6 );
- uTruth1 = uTruth0 & uTruth1;
- if ( pCut->fCompl )
- uTruth1 = ~uTruth1;
- if ( pCut->nVarsMax == 4 )
- uTruth1 &= 0xFFFF;
- Cut_CutWriteTruth( pCut, &uTruth1 );
+ // get the direct truth table
+ uTruth = *Cut_CutReadTruth(pCut);
+
+ // compute the direct truth table
+ Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 );
+// uCanon[0] = uCanon2[0];
+// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0];
+// uPhases[0] = pPhases2[0];
+ pCut->uCanon0 = uCanon2[0];
+ pCut->Num0 = pPhases2[0];
+
+ // get the complemented truth table
+ uTruth = ~*Cut_CutReadTruth(pCut);
+
+ // compute the direct truth table
+ Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 );
+// uCanon[0] = uCanon2[0];
+// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0];
+// uPhases[0] = pPhases2[0];
+ pCut->uCanon1 = uCanon2[0];
+ pCut->Num1 = pPhases2[0];
}
/**Function*************************************************************
@@ -129,26 +119,44 @@ void Cut_TruthCompute4( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_
SeeAlso []
***********************************************************************/
-void Cut_TruthCompute5( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 )
{
- unsigned * puTruthCut0, * puTruthCut1;
- unsigned uTruth0, uTruth1, uPhase;
+ static unsigned uTruth0[8], uTruth1[8];
+ int nTruthWords = Cut_TruthWords( pCut->nVarsMax );
+ unsigned * pTruthRes;
+ int i, uPhase;
- puTruthCut0 = Cut_CutReadTruth(pCut0);
- puTruthCut1 = Cut_CutReadTruth(pCut1);
+ // permute the first table
+ uPhase = Cut_TruthPhase( pCut, pCut0 );
+ Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut0), uPhase, uTruth0 );
+ if ( fCompl0 )
+ {
+ for ( i = 0; i < nTruthWords; i++ )
+ uTruth0[i] = ~uTruth0[i];
+ }
- uPhase = Cut_TruthPhase( pCut, pCut0 );
- uTruth0 = Extra_TruthPerm5One( *puTruthCut0, uPhase );
- uTruth0 = p->fCompl0? ~uTruth0: uTruth0;
+ // permute the second table
+ uPhase = Cut_TruthPhase( pCut, pCut1 );
+ Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut1), uPhase, uTruth1 );
+ if ( fCompl1 )
+ {
+ for ( i = 0; i < nTruthWords; i++ )
+ uTruth1[i] = ~uTruth1[i];
+ }
- uPhase = Cut_TruthPhase( pCut, pCut1 );
- uTruth1 = Extra_TruthPerm5One( *puTruthCut1, uPhase );
- uTruth1 = p->fCompl1? ~uTruth1: uTruth1;
+ // write the resulting table
+ pTruthRes = Cut_CutReadTruth(pCut);
- uTruth1 = uTruth0 & uTruth1;
if ( pCut->fCompl )
- uTruth1 = ~uTruth1;
- Cut_CutWriteTruth( pCut, &uTruth1 );
+ {
+ for ( i = 0; i < nTruthWords; i++ )
+ pTruthRes[i] = ~(uTruth0[i] & uTruth1[i]);
+ }
+ else
+ {
+ for ( i = 0; i < nTruthWords; i++ )
+ pTruthRes[i] = uTruth0[i] & uTruth1[i];
+ }
}
/**Function*************************************************************
@@ -162,158 +170,54 @@ void Cut_TruthCompute5( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_
SeeAlso []
***********************************************************************/
-void Cut_TruthCompute6( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
+void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 )
{
- unsigned * puTruthCut0, * puTruthCut1;
- unsigned uTruth0[2], uTruth1[2], uPhase;
-
- puTruthCut0 = Cut_CutReadTruth(pCut0);
- puTruthCut1 = Cut_CutReadTruth(pCut1);
-
- uPhase = Cut_TruthPhase( pCut, pCut0 );
- Extra_TruthPerm6One( puTruthCut0, uPhase, uTruth0 );
- uTruth0[0] = p->fCompl0? ~uTruth0[0]: uTruth0[0];
- uTruth0[1] = p->fCompl0? ~uTruth0[1]: uTruth0[1];
-
- uPhase = Cut_TruthPhase( pCut, pCut1 );
- Extra_TruthPerm6One( puTruthCut1, uPhase, uTruth1 );
- uTruth1[0] = p->fCompl1? ~uTruth1[0]: uTruth1[0];
- uTruth1[1] = p->fCompl1? ~uTruth1[1]: uTruth1[1];
-
- uTruth1[0] = uTruth0[0] & uTruth1[0];
- uTruth1[1] = uTruth0[1] & uTruth1[1];
+ // permute the first table
+ if ( fCompl0 )
+ Extra_TruthNot( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax );
+ else
+ Extra_TruthCopy( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax );
+ Extra_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut0) );
+ // permute the second table
+ if ( fCompl1 )
+ Extra_TruthNot( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax );
+ else
+ Extra_TruthCopy( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax );
+ Extra_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut1) );
+ // produce the resulting table
if ( pCut->fCompl )
- {
- uTruth1[0] = ~uTruth0[0];
- uTruth1[1] = ~uTruth0[1];
- }
- Cut_CutWriteTruth( pCut, uTruth1 );
-}
-
+ Extra_TruthNand( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax );
+ else
+ Extra_TruthAnd( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax );
+// Ivy_TruthTestOne( *Cut_CutReadTruth(pCut) );
+ // quit if no fancy computation is needed
+ if ( !p->pParams->fFancy )
+ return;
+ if ( pCut->nLeaves != 7 )
+ return;
+ // count the total number of truth tables computed
+ nTotal++;
-/**Function*************************************************************
-
- Synopsis [Performs truth table computation.]
-
- Description []
-
- SideEffects []
+ // MAPPING INTO ALTERA 6-2 LOGIC BLOCKS
+ // call this procedure to find the minimum number of common variables in the cofactors
+ // if this number is less or equal than 3, the cut can be implemented using the 6-2 logic block
+ if ( Extra_TruthMinCofSuppOverlap( Cut_CutReadTruth(pCut), pCut->nVarsMax, NULL ) <= 4 )
+ nGood++;
- SeeAlso []
+ // MAPPING INTO ACTEL 2x2 CELLS
+ // call this procedure to see if a semi-canonical form can be found in the lookup table
+ // (if it exists, then a two-level 3-input LUT implementation of the cut exists)
+ // Before this procedure is called, cell manager should be defined by calling
+ // Cut_CellLoad (make sure file "cells22_daomap_iwls.txt" is available in the working dir)
+// if ( Cut_CellIsRunning() && pCut->nVarsMax <= 9 )
+// nGood += Cut_CellTruthLookup( Cut_CutReadTruth(pCut), pCut->nVarsMax );
+}
-***********************************************************************/
-void Cut_TruthComputeOld( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 )
-{
- unsigned uTruth0, uTruth1, uPhase;
- int clk = clock();
- assert( pCut->nVarsMax < 6 );
-
- // assign the truth table
- if ( pCut0->nLeaves == pCut->nLeaves )
- uTruth0 = *Cut_CutReadTruth(pCut0);
- else
- {
- assert( pCut0->nLeaves < pCut->nLeaves );
- uPhase = Cut_TruthPhase( pCut, pCut0 );
- if ( pCut->nVarsMax == 4 )
- {
- assert( pCut0->nLeaves < 4 );
- assert( uPhase < 16 );
- uTruth0 = p->pPerms43[pCut0->uTruth & 0xFF][uPhase];
- }
- else
- {
- assert( pCut->nVarsMax == 5 );
- assert( pCut0->nLeaves < 5 );
- assert( uPhase < 32 );
- if ( pCut0->nLeaves == 4 )
- {
-// Count4++;
-/*
- if ( uPhase == 31-16 ) // 01111
- uTruth0 = pCut0->uTruth;
- else if ( uPhase == 31-8 ) // 10111
- uTruth0 = p->pPerms54[pCut0->uTruth & 0xFFFF][0];
- else if ( uPhase == 31-4 ) // 11011
- uTruth0 = p->pPerms54[pCut0->uTruth & 0xFFFF][1];
- else if ( uPhase == 31-2 ) // 11101
- uTruth0 = p->pPerms54[pCut0->uTruth & 0xFFFF][2];
- else if ( uPhase == 31-1 ) // 11110
- uTruth0 = p->pPerms54[pCut0->uTruth & 0xFFFF][3];
- else
- assert( 0 );
-*/
- uTruth0 = Extra_TruthPerm5One( *Cut_CutReadTruth(pCut0), uPhase );
- }
- else
- {
-// Count5++;
-// uTruth0 = p->pPerms53[pCut0->uTruth & 0xFF][uPhase];
- uTruth0 = Extra_TruthPerm5One( *Cut_CutReadTruth(pCut0), uPhase );
- }
- }
- }
- uTruth0 = p->fCompl0? ~uTruth0: uTruth0;
-
- // assign the truth table
- if ( pCut1->nLeaves == pCut->nLeaves )
- uTruth0 = *Cut_CutReadTruth(pCut1);
- else
- {
- assert( pCut1->nLeaves < pCut->nLeaves );
- uPhase = Cut_TruthPhase( pCut, pCut1 );
- if ( pCut->nVarsMax == 4 )
- {
- assert( pCut1->nLeaves < 4 );
- assert( uPhase < 16 );
- uTruth1 = p->pPerms43[pCut1->uTruth & 0xFF][uPhase];
- }
- else
- {
- assert( pCut->nVarsMax == 5 );
- assert( pCut1->nLeaves < 5 );
- assert( uPhase < 32 );
- if ( pCut1->nLeaves == 4 )
- {
-// Count4++;
-/*
- if ( uPhase == 31-16 ) // 01111
- uTruth1 = pCut1->uTruth;
- else if ( uPhase == 31-8 ) // 10111
- uTruth1 = p->pPerms54[pCut1->uTruth & 0xFFFF][0];
- else if ( uPhase == 31-4 ) // 11011
- uTruth1 = p->pPerms54[pCut1->uTruth & 0xFFFF][1];
- else if ( uPhase == 31-2 ) // 11101
- uTruth1 = p->pPerms54[pCut1->uTruth & 0xFFFF][2];
- else if ( uPhase == 31-1 ) // 11110
- uTruth1 = p->pPerms54[pCut1->uTruth & 0xFFFF][3];
- else
- assert( 0 );
-*/
- uTruth1 = Extra_TruthPerm5One( *Cut_CutReadTruth(pCut1), uPhase );
- }
- else
- {
-// Count5++;
-// uTruth1 = p->pPerms53[pCut1->uTruth & 0xFF][uPhase];
- uTruth1 = Extra_TruthPerm5One( *Cut_CutReadTruth(pCut1), uPhase );
- }
- }
- }
- uTruth1 = p->fCompl1? ~uTruth1: uTruth1;
- uTruth1 = uTruth0 & uTruth1;
- if ( pCut->fCompl )
- uTruth1 = ~uTruth1;
- if ( pCut->nVarsMax == 4 )
- uTruth1 &= 0xFFFF;
- Cut_CutWriteTruth( pCut, &uTruth1 );
-p->timeTruth += clock() - clk;
-}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
diff --git a/src/opt/cut/module.make b/src/opt/cut/module.make
index 1175b3f2..132e730b 100644
--- a/src/opt/cut/module.make
+++ b/src/opt/cut/module.make
@@ -1,6 +1,9 @@
-SRC += src/opt/cut/cutMan.c \
+SRC += src/opt/cut/cutApi.c \
+ src/opt/cut/cutCut.c \
+ src/opt/cut/cutMan.c \
src/opt/cut/cutMerge.c \
src/opt/cut/cutNode.c \
+ src/opt/cut/cutOracle.c \
+ src/opt/cut/cutPre22.c \
src/opt/cut/cutSeq.c \
- src/opt/cut/cutTable.c \
src/opt/cut/cutTruth.c
diff --git a/src/opt/dec/dec.h b/src/opt/dec/dec.h
index 6ecc9678..d0d9981d 100644
--- a/src/opt/dec/dec.h
+++ b/src/opt/dec/dec.h
@@ -21,6 +21,10 @@
#ifndef __DEC_H__
#define __DEC_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -47,11 +51,15 @@ struct Dec_Node_t_
Dec_Edge_t eEdge1; // the right child of the node
// other info
void * pFunc; // the function of the node (BDD or AIG)
- unsigned Level : 16; // the level of this node in the global AIG
+ unsigned Level : 14; // the level of this node in the global AIG
// printing info
unsigned fNodeOr : 1; // marks the original OR node
unsigned fCompl0 : 1; // marks the original complemented edge
unsigned fCompl1 : 1; // marks the original complemented edge
+ // latch info
+ unsigned nLat0 : 5; // the number of latches on the first edge
+ unsigned nLat1 : 5; // the number of latches on the second edge
+ unsigned nLat2 : 5; // the number of latches on the output edge
};
typedef struct Dec_Graph_t_ Dec_Graph_t;
@@ -95,9 +103,6 @@ struct Dec_Man_t_
////////////////////////////////////////////////////////////////////////
/*=== decAbc.c ========================================================*/
-extern Abc_Obj_t * Dec_GraphToNetwork( Abc_Aig_t * pMan, Dec_Graph_t * pGraph );
-extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
-extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain );
/*=== decFactor.c ========================================================*/
extern Dec_Graph_t * Dec_Factor( char * pSop );
/*=== decMan.c ========================================================*/
@@ -106,11 +111,10 @@ extern void Dec_ManStop( Dec_Man_t * p );
/*=== decPrint.c ========================================================*/
extern void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut );
/*=== decUtil.c ========================================================*/
-extern DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph );
extern unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -308,7 +312,7 @@ static inline void Dec_GraphFree( Dec_Graph_t * pGraph )
SeeAlso []
***********************************************************************/
-static inline bool Dec_GraphIsConst( Dec_Graph_t * pGraph )
+static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph )
{
return pGraph->fConst;
}
@@ -324,7 +328,7 @@ static inline bool Dec_GraphIsConst( Dec_Graph_t * pGraph )
SeeAlso []
***********************************************************************/
-static inline bool Dec_GraphIsConst0( Dec_Graph_t * pGraph )
+static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph )
{
return pGraph->fConst && pGraph->eRoot.fCompl;
}
@@ -340,7 +344,7 @@ static inline bool Dec_GraphIsConst0( Dec_Graph_t * pGraph )
SeeAlso []
***********************************************************************/
-static inline bool Dec_GraphIsConst1( Dec_Graph_t * pGraph )
+static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph )
{
return pGraph->fConst && !pGraph->eRoot.fCompl;
}
@@ -356,7 +360,7 @@ static inline bool Dec_GraphIsConst1( Dec_Graph_t * pGraph )
SeeAlso []
***********************************************************************/
-static inline bool Dec_GraphIsComplement( Dec_Graph_t * pGraph )
+static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph )
{
return pGraph->eRoot.fCompl;
}
@@ -469,7 +473,7 @@ static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode )
SeeAlso []
***********************************************************************/
-static inline bool Dec_GraphIsVar( Dec_Graph_t * pGraph )
+static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph )
{
return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves;
}
@@ -485,7 +489,7 @@ static inline bool Dec_GraphIsVar( Dec_Graph_t * pGraph )
SeeAlso []
***********************************************************************/
-static inline bool Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode )
+static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode )
{
return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves;
}
@@ -627,24 +631,84 @@ static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eE
SeeAlso []
***********************************************************************/
-static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 )
-{
- Dec_Edge_t eNode0, eNode1;
- // derive the first AND
- eEdge0.fCompl = !eEdge0.fCompl;
- eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
- eEdge0.fCompl = !eEdge0.fCompl;
- // derive the second AND
- eEdge1.fCompl = !eEdge1.fCompl;
- eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
- eEdge1.fCompl = !eEdge1.fCompl;
- // derive the final OR
- return Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type )
+{
+ Dec_Edge_t eNode0, eNode1, eNode;
+ if ( Type == 0 )
+ {
+ // derive the first AND
+ eEdge0.fCompl ^= 1;
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ eEdge0.fCompl ^= 1;
+ // derive the second AND
+ eEdge1.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ }
+ else
+ {
+ // derive the first AND
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ // derive the second AND
+ eEdge0.fCompl ^= 1;
+ eEdge1.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ eNode.fCompl ^= 1;
+ }
+ return eNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates an XOR node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type )
+{
+ Dec_Edge_t eNode0, eNode1, eNode;
+ if ( Type == 0 )
+ {
+ // derive the first AND
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+ // derive the second AND
+ eEdgeC.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ }
+ else
+ {
+ // complement the arguments
+ eEdgeT.fCompl ^= 1;
+ eEdgeE.fCompl ^= 1;
+ // derive the first AND
+ eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT );
+ // derive the second AND
+ eEdgeC.fCompl ^= 1;
+ eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE );
+ // derive the final OR
+ eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ eNode.fCompl ^= 1;
+ }
+ return eNode;
+}
+
+#ifdef __cplusplus
}
+#endif
+
+#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/dec/decAbc.c b/src/opt/dec/decAbc.c
index 9931b136..6adb0f98 100644
--- a/src/opt/dec/decAbc.c
+++ b/src/opt/dec/decAbc.c
@@ -18,13 +18,14 @@
#include "abc.h"
#include "dec.h"
+#include "ivy.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -39,14 +40,14 @@
SeeAlso []
***********************************************************************/
-Abc_Obj_t * Dec_GraphToNetwork( Abc_Aig_t * pMan, Dec_Graph_t * pGraph )
+Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph )
{
Abc_Obj_t * pAnd0, * pAnd1;
Dec_Node_t * pNode;
int i;
// check for constant function
if ( Dec_GraphIsConst(pGraph) )
- return Abc_ObjNotCond( Abc_AigConst1(pMan), Dec_GraphIsComplement(pGraph) );
+ return Abc_ObjNotCond( Abc_AigConst1(pNtk), Dec_GraphIsComplement(pGraph) );
// check for a literal
if ( Dec_GraphIsVar(pGraph) )
return Abc_ObjNotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
@@ -55,7 +56,45 @@ Abc_Obj_t * Dec_GraphToNetwork( Abc_Aig_t * pMan, Dec_Graph_t * pGraph )
{
pAnd0 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
pAnd1 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
- pNode->pFunc = Abc_AigAnd( pMan, pAnd0, pAnd1 );
+ pNode->pFunc = Abc_AigAnd( pNtk->pManFunc, pAnd0, pAnd1 );
+ }
+ // complement the result if necessary
+ return Abc_ObjNotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the decomposition graph into the AIG.]
+
+ Description [AIG nodes for the fanins should be assigned to pNode->pFunc
+ of the leaves of the graph before calling this procedure.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Dec_GraphToNetworkNoStrash( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph )
+{
+ Abc_Obj_t * pAnd, * pAnd0, * pAnd1;
+ Dec_Node_t * pNode;
+ int i;
+ // check for constant function
+ if ( Dec_GraphIsConst(pGraph) )
+ return Abc_ObjNotCond( Abc_AigConst1(pNtk), Dec_GraphIsComplement(pGraph) );
+ // check for a literal
+ if ( Dec_GraphIsVar(pGraph) )
+ return Abc_ObjNotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+ // build the AIG nodes corresponding to the AND gates of the graph
+ Dec_GraphForEachNode( pGraph, pNode, i )
+ {
+ pAnd0 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
+ pAnd1 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
+// pNode->pFunc = Abc_AigAnd( pNtk->pManFunc, pAnd0, pAnd1 );
+ pAnd = Abc_NtkCreateNode( pNtk );
+ Abc_ObjAddFanin( pAnd, pAnd0 );
+ Abc_ObjAddFanin( pAnd, pAnd1 );
+ pNode->pFunc = pAnd;
}
// complement the result if necessary
return Abc_ObjNotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
@@ -119,14 +158,14 @@ int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMa
LevelNew = 1 + ABC_MAX( pNode0->Level, pNode1->Level );
if ( pAnd )
{
- if ( Abc_ObjRegular(pAnd) == Abc_AigConst1(pMan) )
+ if ( Abc_ObjRegular(pAnd) == Abc_AigConst1(pRoot->pNtk) )
LevelNew = 0;
else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd0) )
LevelNew = (int)Abc_ObjRegular(pAnd0)->Level;
else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd1) )
LevelNew = (int)Abc_ObjRegular(pAnd1)->Level;
LevelOld = (int)Abc_ObjRegular(pAnd)->Level;
- assert( LevelNew == LevelOld );
+// assert( LevelNew == LevelOld );
}
if ( LevelNew > LevelMax )
return -1;
@@ -148,21 +187,118 @@ int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMa
SeeAlso []
***********************************************************************/
-void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain )
+void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain )
{
+ extern Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph );
Abc_Obj_t * pRootNew;
Abc_Ntk_t * pNtk = pRoot->pNtk;
int nNodesNew, nNodesOld;
nNodesOld = Abc_NtkNodeNum(pNtk);
// create the new structure of nodes
- pRootNew = Dec_GraphToNetwork( pNtk->pManFunc, pGraph );
+ pRootNew = Dec_GraphToNetwork( pNtk, pGraph );
// remove the old nodes
- Abc_AigReplace( pNtk->pManFunc, pRoot, pRootNew );
+ Abc_AigReplace( pNtk->pManFunc, pRoot, pRootNew, fUpdateLevel );
// compare the gains
nNodesNew = Abc_NtkNodeNum(pNtk);
assert( nGain <= nNodesOld - nNodesNew );
}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the decomposition graph into the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Dec_GraphToNetworkAig( Hop_Man_t * pMan, Dec_Graph_t * pGraph )
+{
+ Dec_Node_t * pNode;
+ Hop_Obj_t * pAnd0, * pAnd1;
+ int i;
+ // check for constant function
+ if ( Dec_GraphIsConst(pGraph) )
+ return Hop_NotCond( Hop_ManConst1(pMan), Dec_GraphIsComplement(pGraph) );
+ // check for a literal
+ if ( Dec_GraphIsVar(pGraph) )
+ return Hop_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+ // build the AIG nodes corresponding to the AND gates of the graph
+ Dec_GraphForEachNode( pGraph, pNode, i )
+ {
+ pAnd0 = Hop_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
+ pAnd1 = Hop_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
+ pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 );
+ }
+ // complement the result if necessary
+ return Hop_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop )
+{
+ Hop_Obj_t * pFunc;
+ Dec_Graph_t * pFForm;
+ Dec_Node_t * pNode;
+ int i;
+ // perform factoring
+ pFForm = Dec_Factor( pSop );
+ // collect the fanins
+ Dec_GraphForEachLeaf( pFForm, pNode, i )
+ pNode->pFunc = Hop_IthVar( pMan, i );
+ // perform strashing
+ pFunc = Dec_GraphToNetworkAig( pMan, pFForm );
+ Dec_GraphFree( pFForm );
+ return pFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the decomposition graph into the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph )
+{
+ Dec_Node_t * pNode;
+ Ivy_Obj_t * pAnd0, * pAnd1;
+ int i;
+ // check for constant function
+ if ( Dec_GraphIsConst(pGraph) )
+ return Ivy_NotCond( Ivy_ManConst1(pMan), Dec_GraphIsComplement(pGraph) );
+ // check for a literal
+ if ( Dec_GraphIsVar(pGraph) )
+ return Ivy_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
+ // build the AIG nodes corresponding to the AND gates of the graph
+ Dec_GraphForEachNode( pGraph, pNode, i )
+ {
+ pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
+ pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
+ pNode->pFunc = Ivy_And( pMan, pAnd0, pAnd1 );
+ }
+ // complement the result if necessary
+ return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
+}
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/dec/decFactor.c b/src/opt/dec/decFactor.c
index f6654476..768dcd9b 100644
--- a/src/opt/dec/decFactor.c
+++ b/src/opt/dec/decFactor.c
@@ -34,7 +34,7 @@ static int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm );
static Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -183,7 +183,7 @@ Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover )
***********************************************************************/
Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple )
{
- Dec_Man_t * pManDec = Abc_FrameReadManDec(Abc_FrameGetGlobalFrame());
+ Dec_Man_t * pManDec = Abc_FrameReadManDec();
Vec_Int_t * vEdgeLits = pManDec->vLits;
Mvc_Cover_t * pDiv, * pQuo, * pRem;
Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem;
@@ -228,7 +228,7 @@ Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cov
***********************************************************************/
Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover )
{
- Dec_Man_t * pManDec = Abc_FrameReadManDec(Abc_FrameGetGlobalFrame());
+ Dec_Man_t * pManDec = Abc_FrameReadManDec();
Vec_Int_t * vEdgeCubes = pManDec->vCubes;
Vec_Int_t * vEdgeLits = pManDec->vLits;
Mvc_Manager_t * pMem = pManDec->pMvcMem;
@@ -258,16 +258,15 @@ Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover )
***********************************************************************/
Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits )
{
-// Dec_Edge_t eNode;
+ Dec_Edge_t eNode;
int iBit, Value;
// create the factored form for each literal
Vec_IntClear( vEdgeLits );
Mvc_CubeForEachBit( pCover, pCube, iBit, Value )
if ( Value )
{
-// eNode = Dec_EdgeCreate( iBit/2, iBit%2 ); // CST
-// Vec_IntPush( vEdgeLits, Dec_EdgeToInt_(eNode) );
- Vec_IntPush( vEdgeLits, iBit );
+ eNode = Dec_EdgeCreate( iBit/2, iBit%2 ); // CST
+ Vec_IntPush( vEdgeLits, Dec_EdgeToInt_(eNode) );
}
// balance the factored forms
return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeLits->pArray, vEdgeLits->nSize, 0 );
@@ -323,7 +322,7 @@ Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes
***********************************************************************/
Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop )
{
- Dec_Man_t * pManDec = Abc_FrameReadManDec(Abc_FrameGetGlobalFrame());
+ Dec_Man_t * pManDec = Abc_FrameReadManDec();
Mvc_Manager_t * pMem = pManDec->pMvcMem;
Mvc_Cover_t * pMvc;
Mvc_Cube_t * pMvcCube;
@@ -365,7 +364,8 @@ Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop )
***********************************************************************/
int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm )
{
- DdManager * dd = Abc_FrameReadManDd( Abc_FrameGetGlobalFrame() );
+ extern DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph );
+ DdManager * dd = Abc_FrameReadManDd();
DdNode * bFunc1, * bFunc2;
int RetValue;
bFunc1 = Abc_ConvertSopToBdd( dd, pSop ); Cudd_Ref( bFunc1 );
diff --git a/src/opt/dec/decMan.c b/src/opt/dec/decMan.c
index 1d44d5cb..65857461 100644
--- a/src/opt/dec/decMan.c
+++ b/src/opt/dec/decMan.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/dec/decPrint.c b/src/opt/dec/decPrint.c
index 6fb20327..2d8f09b3 100644
--- a/src/opt/dec/decPrint.c
+++ b/src/opt/dec/decPrint.c
@@ -29,7 +29,7 @@ static void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax
static int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut, int fCompl );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -101,7 +101,7 @@ void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char
SeeAlso []
***********************************************************************/
-void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax )
+void Dec_GraphPrint2_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax )
{
Dec_Node_t * pNode0, * pNode1;
pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node);
@@ -165,6 +165,69 @@ void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode,
SeeAlso []
***********************************************************************/
+void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax )
+{
+ Dec_Node_t * pNode0, * pNode1;
+ Dec_Node_t * pNode00, * pNode01, * pNode10, * pNode11;
+ pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node);
+ pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node);
+ if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF )
+ {
+ (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn );
+ return;
+ }
+ if ( !Dec_GraphNodeIsVar(pGraph, pNode0) && !Dec_GraphNodeIsVar(pGraph, pNode1) )
+ {
+ pNode00 = Dec_GraphNode(pGraph, pNode0->eEdge0.Node);
+ pNode01 = Dec_GraphNode(pGraph, pNode0->eEdge1.Node);
+ pNode10 = Dec_GraphNode(pGraph, pNode1->eEdge0.Node);
+ pNode11 = Dec_GraphNode(pGraph, pNode1->eEdge1.Node);
+ if ( (pNode00 == pNode10 || pNode00 == pNode11) && (pNode01 == pNode10 || pNode01 == pNode11) )
+ {
+ fprintf( pFile, "(" );
+ (*pPos)++;
+ Dec_GraphPrint_rec( pFile, pGraph, pNode00, pNode00->fCompl0, pNamesIn, pPos, LitSizeMax );
+ fprintf( pFile, " # " );
+ (*pPos) += 3;
+ Dec_GraphPrint_rec( pFile, pGraph, pNode01, pNode01->fCompl1, pNamesIn, pPos, LitSizeMax );
+ fprintf( pFile, ")" );
+ (*pPos)++;
+ return;
+ }
+ }
+ if ( fCompl )
+ {
+ fprintf( pFile, "(" );
+ (*pPos)++;
+ Dec_GraphPrint_rec( pFile, pGraph, pNode0, !pNode->fCompl0, pNamesIn, pPos, LitSizeMax );
+ fprintf( pFile, " + " );
+ (*pPos) += 3;
+ Dec_GraphPrint_rec( pFile, pGraph, pNode1, !pNode->fCompl1, pNamesIn, pPos, LitSizeMax );
+ fprintf( pFile, ")" );
+ (*pPos)++;
+ }
+ else
+ {
+ fprintf( pFile, "(" );
+ (*pPos)++;
+ Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax );
+ Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax );
+ fprintf( pFile, ")" );
+ (*pPos)++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] )
{
static char Buffer[100];
diff --git a/src/opt/dec/decUtil.c b/src/opt/dec/decUtil.c
index 02c3346e..463bc7e2 100644
--- a/src/opt/dec/decUtil.c
+++ b/src/opt/dec/decUtil.c
@@ -24,7 +24,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/fret/fretFlow.c b/src/opt/fret/fretFlow.c
new file mode 100644
index 00000000..a9cef327
--- /dev/null
+++ b/src/opt/fret/fretFlow.c
@@ -0,0 +1,696 @@
+/**CFile****************************************************************
+
+ FileName [fretFlow.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Flow-based retiming package.]
+
+ Synopsis [Max-flow computation.]
+
+ Author [Aaron Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2008.]
+
+ Revision [$Id: fretFlow.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "vec.h"
+#include "fretime.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void dfsfast_e_retreat( Abc_Obj_t *pObj );
+static void dfsfast_r_retreat( Abc_Obj_t *pObj );
+
+#define FDIST(xn, xe, yn, ye) (FDATA(xn)->xe##_dist == (FDATA(yn)->ye##_dist + 1))
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Fast DFS.]
+
+ Description [Uses sink-distance-histogram heuristic. May not find all
+ flow paths: this occurs in a small number of cases where
+ the flow predecessor points to a non-adjacent node and
+ the distance ordering is perturbed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+void dfsfast_preorder( Abc_Ntk_t *pNtk ) {
+ Abc_Obj_t *pObj, *pNext;
+ Vec_Ptr_t *vTimeIn, *qn = Vec_PtrAlloc(Abc_NtkObjNum(pNtk));
+ Vec_Int_t *qe = Vec_IntAlloc(Abc_NtkObjNum(pNtk));
+ int i, j, d = 0, end;
+ int qpos = 0;
+
+ // create reverse timing edges for backward traversal
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay) {
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, j ) {
+ vTimeIn = FDATA(pNext)->vNodes;
+ if (!vTimeIn) {
+ vTimeIn = FDATA(pNext)->vNodes = Vec_PtrAlloc(2);
+ }
+ Vec_PtrPush(vTimeIn, pObj);
+ }
+ }
+ }
+#endif
+
+ // clear histogram
+ memset(Vec_IntArray(pManMR->vSinkDistHist), 0, sizeof(int)*Vec_IntSize(pManMR->vSinkDistHist));
+
+ // seed queue : latches, PIOs, and blocks
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (Abc_ObjIsPo(pObj) ||
+ Abc_ObjIsLatch(pObj) ||
+ (pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) {
+ Vec_PtrPush(qn, pObj);
+ Vec_IntPush(qe, 'r');
+ FDATA(pObj)->r_dist = 1;
+ } else if (Abc_ObjIsPi(pObj) ||
+ (!pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) {
+ Vec_PtrPush(qn, pObj);
+ Vec_IntPush(qe, 'e');
+ FDATA(pObj)->e_dist = 1;
+ }
+
+ // until queue is empty...
+ while(qpos < Vec_PtrSize(qn)) {
+ pObj = (Abc_Obj_t *)Vec_PtrEntry(qn, qpos);
+ assert(pObj);
+ end = Vec_IntEntry(qe, qpos);
+ qpos++;
+
+ if (end == 'r') {
+ d = FDATA(pObj)->r_dist;
+
+ // 1. structural edges
+ if (pManMR->fIsForward) {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if (!FDATA(pNext)->e_dist) {
+ FDATA(pNext)->e_dist = d+1;
+ Vec_PtrPush(qn, pNext);
+ Vec_IntPush(qe, 'e');
+ }
+ } else
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if (!FDATA(pNext)->e_dist) {
+ FDATA(pNext)->e_dist = d+1;
+ Vec_PtrPush(qn, pNext);
+ Vec_IntPush(qe, 'e');
+ }
+
+ if (d == 1) continue;
+
+ // 2. reverse edges (forward retiming only)
+ if (pManMR->fIsForward) {
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if (!FDATA(pNext)->r_dist && !Abc_ObjIsLatch(pNext)) {
+ FDATA(pNext)->r_dist = d+1;
+ Vec_PtrPush(qn, pNext);
+ Vec_IntPush(qe, 'r');
+ }
+
+ // 3. timimg edges (forward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay && FDATA(pObj)->vNodes)
+ Vec_PtrForEachEntry( FDATA(pObj)->vNodes, pNext, i ) {
+ if (!FDATA(pNext)->r_dist) {
+ FDATA(pNext)->r_dist = d+1;
+ Vec_PtrPush(qn, pNext);
+ Vec_IntPush(qe, 'r');
+ }
+ }
+#endif
+ }
+
+ } else { // if 'e'
+ if (Abc_ObjIsLatch(pObj)) continue;
+
+ d = FDATA(pObj)->e_dist;
+
+ // 1. through node
+ if (!FDATA(pObj)->r_dist) {
+ FDATA(pObj)->r_dist = d+1;
+ Vec_PtrPush(qn, pObj);
+ Vec_IntPush(qe, 'r');
+ }
+
+ // 2. reverse edges (backward retiming only)
+ if (!pManMR->fIsForward) {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if (!FDATA(pNext)->e_dist && !Abc_ObjIsLatch(pNext)) {
+ FDATA(pNext)->e_dist = d+1;
+ Vec_PtrPush(qn, pNext);
+ Vec_IntPush(qe, 'e');
+ }
+
+ // 3. timimg edges (backward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay && FDATA(pObj)->vNodes)
+ Vec_PtrForEachEntry( FDATA(pObj)->vNodes, pNext, i ) {
+ if (!FDATA(pNext)->e_dist) {
+ FDATA(pNext)->e_dist = d+1;
+ Vec_PtrPush(qn, pNext);
+ Vec_IntPush(qe, 'e');
+ }
+ }
+#endif
+ }
+ }
+ }
+
+ // free time edges
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay) {
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ vTimeIn = FDATA(pObj)->vNodes;
+ if (vTimeIn) {
+ Vec_PtrFree(vTimeIn);
+ FDATA(pObj)->vNodes = 0;
+ }
+ }
+ }
+#endif
+
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ Vec_IntAddToEntry(pManMR->vSinkDistHist, FDATA(pObj)->r_dist, 1);
+ Vec_IntAddToEntry(pManMR->vSinkDistHist, FDATA(pObj)->e_dist, 1);
+
+#ifdef DEBUG_PREORDER
+ printf("node %d\t: r=%d\te=%d\n", Abc_ObjId(pObj), FDATA(pObj)->r_dist, FDATA(pObj)->e_dist);
+#endif
+ }
+
+ // printf("\t\tpre-ordered (max depth=%d)\n", d+1);
+
+ // deallocate
+ Vec_PtrFree( qn );
+ Vec_IntFree( qe );
+}
+
+int dfsfast_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) {
+ int i;
+ Abc_Obj_t *pNext;
+
+ if (pManMR->fSinkDistTerminate) return 0;
+
+ // have we reached the sink?
+ if(FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask ||
+ Abc_ObjIsPi(pObj)) {
+ assert(pPred);
+ assert(!pManMR->fIsForward);
+ return 1;
+ }
+
+ FSET(pObj, VISITED_E);
+
+#ifdef DEBUG_VISITED
+ printf("(%de=%d) ", Abc_ObjId(pObj), FDATA(pObj)->e_dist);
+#endif
+
+ // 1. structural edges
+ if (pManMR->fIsForward)
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_R) &&
+ FDIST(pObj, e, pNext, r) &&
+ dfsfast_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+ else
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_R) &&
+ FDIST(pObj, e, pNext, r) &&
+ dfsfast_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+
+ if (Abc_ObjIsLatch(pObj))
+ goto not_found;
+
+ // 2. reverse edges (backward retiming only)
+ if (!pManMR->fIsForward) {
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_E) &&
+ FDIST(pObj, e, pNext, e) &&
+ dfsfast_e(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("i");
+#endif
+ goto found;
+ }
+ }
+
+ // 3. timing edges (backward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay)
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) {
+ if (!FTEST(pNext, VISITED_E) &&
+ FDIST(pObj, e, pNext, e) &&
+ dfsfast_e(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+#endif
+ }
+
+ // unwind
+ if (FTEST(pObj, FLOW) &&
+ !FTEST(pObj, VISITED_R) &&
+ FDIST(pObj, e, pObj, r) &&
+ dfsfast_r(pObj, FGETPRED(pObj))) {
+
+ FUNSET(pObj, FLOW);
+ FSETPRED(pObj, NULL);
+#ifdef DEBUG_PRINT_FLOWS
+ printf("u");
+#endif
+ goto found;
+ }
+
+ not_found:
+ FUNSET(pObj, VISITED_E);
+ dfsfast_e_retreat(pObj);
+ return 0;
+
+ found:
+#ifdef DEBUG_PRINT_FLOWS
+ printf("%d ", Abc_ObjId(pObj));
+#endif
+ FUNSET(pObj, VISITED_E);
+ return 1;
+}
+
+int dfsfast_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) {
+ int i;
+ Abc_Obj_t *pNext, *pOldPred;
+
+ if (pManMR->fSinkDistTerminate) return 0;
+
+#ifdef DEBUG_VISITED
+ printf("(%dr=%d) ", Abc_ObjId(pObj), FDATA(pObj)->r_dist);
+#endif
+
+ // have we reached the sink?
+ if (Abc_ObjIsLatch(pObj) ||
+ (pManMR->fIsForward && Abc_ObjIsPo(pObj)) ||
+ (pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) {
+ assert(pPred);
+ return 1;
+ }
+
+ FSET(pObj, VISITED_R);
+
+ if (FTEST(pObj, FLOW)) {
+
+ pOldPred = FGETPRED(pObj);
+ if (pOldPred &&
+ !FTEST(pOldPred, VISITED_E) &&
+ FDIST(pObj, r, pOldPred, e) &&
+ dfsfast_e(pOldPred, pOldPred)) {
+
+ FSETPRED(pObj, pPred);
+
+#ifdef DEBUG_PRINT_FLOWS
+ printf("fr");
+#endif
+ goto found;
+ }
+
+ } else {
+
+ if (!FTEST(pObj, VISITED_E) &&
+ FDIST(pObj, r, pObj, e) &&
+ dfsfast_e(pObj, pObj)) {
+
+ FSET(pObj, FLOW);
+ FSETPRED(pObj, pPred);
+
+#ifdef DEBUG_PRINT_FLOWS
+ printf("f");
+#endif
+ goto found;
+ }
+ }
+
+ // 2. reverse edges (forward retiming only)
+ if (pManMR->fIsForward) {
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_R) &&
+ FDIST(pObj, r, pNext, r) &&
+ !Abc_ObjIsLatch(pNext) &&
+ dfsfast_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("i");
+#endif
+ goto found;
+ }
+ }
+
+ // 3. timing edges (forward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay)
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) {
+ if (!FTEST(pNext, VISITED_R) &&
+ FDIST(pObj, r, pNext, r) &&
+ dfsfast_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+#endif
+ }
+
+ FUNSET(pObj, VISITED_R);
+ dfsfast_r_retreat(pObj);
+ return 0;
+
+ found:
+#ifdef DEBUG_PRINT_FLOWS
+ printf("%d ", Abc_ObjId(pObj));
+#endif
+ FUNSET(pObj, VISITED_R);
+ return 1;
+}
+
+void
+dfsfast_e_retreat(Abc_Obj_t *pObj) {
+ Abc_Obj_t *pNext;
+ int i, *h;
+ int old_dist = FDATA(pObj)->e_dist;
+ int adj_dist, min_dist = MAX_DIST;
+
+ // 1. structural edges
+ if (pManMR->fIsForward)
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ adj_dist = FDATA(pNext)->r_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+ else
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ adj_dist = FDATA(pNext)->r_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+
+ if (Abc_ObjIsLatch(pObj)) goto update;
+
+ // 2. through
+ if (FTEST(pObj, FLOW)) {
+ adj_dist = FDATA(pObj)->r_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+
+ // 3. reverse edges (backward retiming only)
+ if (!pManMR->fIsForward) {
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ adj_dist = FDATA(pNext)->e_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+
+ // 4. timing edges (backward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay)
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) {
+ adj_dist = FDATA(pNext)->e_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+#endif
+ }
+
+ update:
+ ++min_dist;
+ if (min_dist >= MAX_DIST) min_dist = 0;
+ // printf("[%de=%d->%d] ", Abc_ObjId(pObj), old_dist, min_dist+1);
+ FDATA(pObj)->e_dist = min_dist;
+
+ assert(min_dist < Vec_IntSize(pManMR->vSinkDistHist));
+ h = Vec_IntArray(pManMR->vSinkDistHist);
+ h[old_dist]--;
+ h[min_dist]++;
+ if (!h[old_dist]) {
+ pManMR->fSinkDistTerminate = 1;
+ }
+}
+
+void
+dfsfast_r_retreat(Abc_Obj_t *pObj) {
+ Abc_Obj_t *pNext;
+ int i, *h;
+ int old_dist = FDATA(pObj)->r_dist;
+ int adj_dist, min_dist = MAX_DIST;
+
+ // 1. through or pred
+ if (FTEST(pObj, FLOW)) {
+ if (FGETPRED(pObj)) {
+ adj_dist = FDATA(FGETPRED(pObj))->e_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+ } else {
+ adj_dist = FDATA(pObj)->e_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+
+ // 2. reverse edges (forward retiming only)
+ if (pManMR->fIsForward) {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if (!Abc_ObjIsLatch(pNext)) {
+ adj_dist = FDATA(pNext)->r_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+
+ // 3. timing edges (forward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay)
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) {
+ adj_dist = FDATA(pNext)->r_dist;
+ if (adj_dist) min_dist = MIN(min_dist, adj_dist);
+ }
+#endif
+ }
+
+ ++min_dist;
+ if (min_dist >= MAX_DIST) min_dist = 0;
+ //printf("[%dr=%d->%d] ", Abc_ObjId(pObj), old_dist, min_dist+1);
+ FDATA(pObj)->r_dist = min_dist;
+
+ assert(min_dist < Vec_IntSize(pManMR->vSinkDistHist));
+ h = Vec_IntArray(pManMR->vSinkDistHist);
+ h[old_dist]--;
+ h[min_dist]++;
+ if (!h[old_dist]) {
+ pManMR->fSinkDistTerminate = 1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Plain DFS.]
+
+ Description [Does not use sink-distance-histogram heuristic.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+int dfsplain_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) {
+ int i;
+ Abc_Obj_t *pNext;
+
+ if (FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask ||
+ Abc_ObjIsPi(pObj)) {
+ assert(pPred);
+ assert(!pManMR->fIsForward);
+ return 1;
+ }
+
+ FSET(pObj, VISITED_E);
+
+ // printf(" %de\n", Abc_ObjId(pObj));
+
+ // 1. structural edges
+ if (pManMR->fIsForward)
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_R) &&
+ dfsplain_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+ else
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_R) &&
+ dfsplain_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+
+ if (Abc_ObjIsLatch(pObj))
+ return 0;
+
+ // 2. reverse edges (backward retiming only)
+ if (!pManMR->fIsForward) {
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_E) &&
+ dfsplain_e(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("i");
+#endif
+ goto found;
+ }
+ }
+
+ // 3. timing edges (backward retiming only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay)
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) {
+ if (!FTEST(pNext, VISITED_E) &&
+ dfsplain_e(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+#endif
+ }
+
+ // unwind
+ if (FTEST(pObj, FLOW) &&
+ !FTEST(pObj, VISITED_R) &&
+ dfsplain_r(pObj, FGETPRED(pObj))) {
+ FUNSET(pObj, FLOW);
+ FSETPRED(pObj, NULL);
+#ifdef DEBUG_PRINT_FLOWS
+ printf("u");
+#endif
+ goto found;
+ }
+
+ return 0;
+
+ found:
+#ifdef DEBUG_PRINT_FLOWS
+ printf("%d ", Abc_ObjId(pObj));
+#endif
+
+ return 1;
+}
+
+int dfsplain_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) {
+ int i;
+ Abc_Obj_t *pNext, *pOldPred;
+
+ // have we reached the sink?
+ if (Abc_ObjIsLatch(pObj) ||
+ (pManMR->fIsForward && Abc_ObjIsPo(pObj)) ||
+ (pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) {
+ assert(pPred);
+ return 1;
+ }
+
+ FSET(pObj, VISITED_R);
+
+ // printf(" %dr\n", Abc_ObjId(pObj));
+
+ if (FTEST(pObj, FLOW)) {
+
+ pOldPred = FGETPRED(pObj);
+ if (pOldPred &&
+ !FTEST(pOldPred, VISITED_E) &&
+ dfsplain_e(pOldPred, pOldPred)) {
+
+ FSETPRED(pObj, pPred);
+
+#ifdef DEBUG_PRINT_FLOWS
+ printf("fr");
+#endif
+ goto found;
+ }
+
+ } else {
+
+ if (!FTEST(pObj, VISITED_E) &&
+ dfsplain_e(pObj, pObj)) {
+
+ FSET(pObj, FLOW);
+ FSETPRED(pObj, pPred);
+
+#ifdef DEBUG_PRINT_FLOWS
+ printf("f");
+#endif
+ goto found;
+ }
+ }
+
+ // 2. follow reverse edges
+ if (pManMR->fIsForward) { // forward retiming only
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ if (!FTEST(pNext, VISITED_R) &&
+ !Abc_ObjIsLatch(pNext) &&
+ dfsplain_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("i");
+#endif
+ goto found;
+ }
+ }
+
+ // 3. timing edges (forward only)
+#if !defined(IGNORE_TIMING)
+ if (pManMR->maxDelay)
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), pNext, i) {
+ if (!FTEST(pNext, VISITED_R) &&
+ dfsplain_r(pNext, pPred)) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("o");
+#endif
+ goto found;
+ }
+ }
+#endif
+ }
+
+ return 0;
+
+ found:
+#ifdef DEBUG_PRINT_FLOWS
+ printf("%d ", Abc_ObjId(pObj));
+#endif
+ return 1;
+}
diff --git a/src/opt/fret/fretInit.c b/src/opt/fret/fretInit.c
new file mode 100644
index 00000000..53df7386
--- /dev/null
+++ b/src/opt/fret/fretInit.c
@@ -0,0 +1,762 @@
+/**CFile****************************************************************
+
+ FileName [fretInit.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Flow-based retiming package.]
+
+ Synopsis [Initialization for retiming package.]
+
+ Author [Aaron Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2008.]
+
+ Revision [$Id: fretInit.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "vec.h"
+#include "io.h"
+#include "fretime.h"
+#include "mio.h"
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION PROTOTYPES ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_FlowRetime_UpdateForwardInit_rec( Abc_Obj_t * pObj );
+static void Abc_FlowRetime_VerifyBackwardInit( Abc_Ntk_t * pNtk );
+static void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj );
+static Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj,
+ Abc_Obj_t *pUseThisPi, Vec_Ptr_t *vOtherPis,
+ int recurse);
+static void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj );
+static void Abc_FlowRetime_SimulateSop( Abc_Obj_t * pObj, char *pSop );
+
+extern void * Abc_FrameReadLibGen();
+extern Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Updates initial state information.]
+
+ Description [Assumes latch boxes in original position, latches in
+ new positions.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_InitState( Abc_Ntk_t * pNtk ) {
+
+ if (!pManMR->fComputeInitState) return;
+
+ if (pManMR->fIsForward)
+ Abc_FlowRetime_UpdateForwardInit( pNtk );
+ else {
+ Abc_FlowRetime_UpdateBackwardInit( pNtk );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints initial state information.]
+
+ Description [Prints distribution of 0,1,and X initial states.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_PrintInitStateInfo( Abc_Ntk_t * pNtk ) {
+ int i, n0=0, n1=0, nDC=0, nOther=0;
+ Abc_Obj_t *pLatch;
+
+ Abc_NtkForEachLatch( pNtk, pLatch, i ) {
+ if (Abc_LatchIsInit0(pLatch)) n0++;
+ else if (Abc_LatchIsInit1(pLatch)) n1++;
+ else if (Abc_LatchIsInitDc(pLatch)) nDC++;
+ else nOther++;
+ }
+
+ printf("\tinitial states {0,1,x} = {%d, %d, %d}", n0, n1, nDC);
+ if (nOther)
+ printf(" + %d UNKNOWN", nOther);
+ printf("\n");
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes initial state after forward retiming.]
+
+ Description [Assumes box outputs in old positions stored w/ init values.
+ Uses three-value simulation to preserve don't cares.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_UpdateForwardInit( Abc_Ntk_t * pNtk ) {
+ Abc_Obj_t *pObj, *pFanin;
+ int i;
+
+ vprintf("\t\tupdating init state\n");
+
+ Abc_NtkIncrementTravId( pNtk );
+
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ pFanin = Abc_ObjFanin0(pObj);
+ Abc_FlowRetime_UpdateForwardInit_rec( pFanin );
+
+ if (FTEST(pFanin, INIT_0))
+ Abc_LatchSetInit0( pObj );
+ else if (FTEST(pFanin, INIT_1))
+ Abc_LatchSetInit1( pObj );
+ else
+ Abc_LatchSetInitDc( pObj );
+ }
+}
+
+void Abc_FlowRetime_UpdateForwardInit_rec( Abc_Obj_t * pObj ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ assert(!Abc_ObjIsPi(pObj)); // should never reach the inputs
+
+ if (Abc_ObjIsBo(pObj)) return;
+
+ // visited?
+ if (Abc_NodeIsTravIdCurrent(pObj)) return;
+ Abc_NodeSetTravIdCurrent(pObj);
+
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ Abc_FlowRetime_UpdateForwardInit_rec( pNext );
+ }
+
+ Abc_FlowRetime_SimulateNode( pObj );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets initial value flags.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Abc_FlowRetime_SetInitValue( Abc_Obj_t * pObj,
+ int val, int dc ) {
+
+ // store init value
+ FUNSET(pObj, INIT_CARE);
+ if (!dc){
+ if (val) {
+ FSET(pObj, INIT_1);
+ } else {
+ FSET(pObj, INIT_0);
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Propogates initial state through a logic node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj ) {
+ Abc_Ntk_t *pNtk = Abc_ObjNtk(pObj);
+ Abc_Obj_t * pFanin;
+ int i, rAnd, rVar, dcAnd, dcVar;
+ DdManager * dd = pNtk->pManFunc;
+ DdNode *pBdd = pObj->pData, *pVar;
+
+ assert(!Abc_ObjIsLatch(pObj));
+
+ // (i) constant nodes
+ if (Abc_NtkHasAig(pNtk) && Abc_AigNodeIsConst(pObj)) {
+ Abc_FlowRetime_SetInitValue(pObj, 1, 0);
+ return;
+ }
+ if (!Abc_NtkIsStrash( pNtk ) && Abc_ObjIsNode(pObj)) {
+ if (Abc_NodeIsConst0(pObj)) {
+ Abc_FlowRetime_SetInitValue(pObj, 0, 0);
+ return;
+ } else if (Abc_NodeIsConst1(pObj)) {
+ Abc_FlowRetime_SetInitValue(pObj, 1, 0);
+ return;
+ }
+ }
+
+ // (ii) terminal nodes
+ if (!Abc_ObjIsNode(pObj)) {
+ pFanin = Abc_ObjFanin0(pObj);
+
+ Abc_FlowRetime_SetInitValue(pObj,
+ (FTEST(pFanin, INIT_1) ? 1 : 0) ^ pObj->fCompl0,
+ !FTEST(pFanin, INIT_CARE));
+ return;
+ }
+
+ // (iii) logic nodes
+
+ // ------ SOP network
+ if ( Abc_NtkHasSop( pNtk )) {
+ Abc_FlowRetime_SimulateSop( pObj, (char *)Abc_ObjData(pObj) );
+ return;
+ }
+
+ // ------ BDD network
+ else if ( Abc_NtkHasBdd( pNtk )) {
+ assert(dd);
+ assert(pBdd);
+
+ // cofactor for 0,1 inputs
+ // do nothing for X values
+ Abc_ObjForEachFanin(pObj, pFanin, i) {
+ pVar = Cudd_bddIthVar( dd, i );
+ if (FTEST(pFanin, INIT_CARE)) {
+ if (FTEST(pFanin, INIT_0))
+ pBdd = Cudd_Cofactor( dd, pBdd, Cudd_Not(pVar) );
+ else
+ pBdd = Cudd_Cofactor( dd, pBdd, pVar );
+ }
+ }
+
+ // if function has not been reduced to
+ // a constant, propagate an X
+ rVar = (pBdd == Cudd_ReadOne(dd));
+ dcVar = !Cudd_IsConstant(pBdd);
+
+ Abc_FlowRetime_SetInitValue(pObj, rVar, dcVar);
+ return;
+ }
+
+ // ------ AIG network
+ else if ( Abc_NtkHasAig( pNtk )) {
+
+ assert(Abc_AigNodeIsAnd(pObj));
+ dcAnd = 0, rAnd = 1;
+
+ pFanin = Abc_ObjFanin0(pObj);
+ dcAnd |= FTEST(pFanin, INIT_CARE) ? 0 : 1;
+ rVar = FTEST(pFanin, INIT_0) ? 0 : 1;
+ if (pObj->fCompl0) rVar ^= 1; // complimented?
+ rAnd &= rVar;
+
+ pFanin = Abc_ObjFanin1(pObj);
+ dcAnd |= FTEST(pFanin, INIT_CARE) ? 0 : 1;
+ rVar = FTEST(pFanin, INIT_0) ? 0 : 1;
+ if (pObj->fCompl1) rVar ^= 1; // complimented?
+ rAnd &= rVar;
+
+ if (!rAnd) dcAnd = 0; /* controlling value */
+
+ Abc_FlowRetime_SetInitValue(pObj, rAnd, dcAnd);
+ return;
+ }
+
+ // ------ MAPPED network
+ else if ( Abc_NtkHasMapping( pNtk )) {
+ Abc_FlowRetime_SimulateSop( pObj, (char *)Mio_GateReadSop(pObj->pData) );
+ return;
+ }
+
+ assert(0);
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Propogates initial state through a SOP node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_SimulateSop( Abc_Obj_t * pObj, char *pSop ) {
+ Abc_Obj_t * pFanin;
+ char *pCube;
+ int i, j, rAnd, rOr, rVar, dcAnd, dcOr, v;
+
+ assert( pSop && !Abc_SopIsExorType(pSop) );
+
+ rOr = 0, dcOr = 0;
+
+ i = Abc_SopGetVarNum(pSop);
+ Abc_SopForEachCube( pSop, i, pCube ) {
+ rAnd = 1, dcAnd = 0;
+ Abc_CubeForEachVar( pCube, v, j ) {
+ pFanin = Abc_ObjFanin(pObj, j);
+ if ( v == '0' )
+ rVar = FTEST(pFanin, INIT_0) ? 1 : 0;
+ else if ( v == '1' )
+ rVar = FTEST(pFanin, INIT_1) ? 1 : 0;
+ else
+ continue;
+
+ if (FTEST(pFanin, INIT_CARE))
+ rAnd &= rVar;
+ else
+ dcAnd = 1;
+ }
+ if (!rAnd) dcAnd = 0; /* controlling value */
+ if (dcAnd)
+ dcOr = 1;
+ else
+ rOr |= rAnd;
+ }
+ if (rOr) dcOr = 0; /* controlling value */
+
+ // complement the result if necessary
+ if ( !Abc_SopGetPhase(pSop) )
+ rOr ^= 1;
+
+ Abc_FlowRetime_SetInitValue(pObj, rOr, dcOr);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up backward initial state computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk ) {
+ Abc_Obj_t *pLatch, *pObj, *pPi;
+ int i;
+ Vec_Ptr_t *vObj = Vec_PtrAlloc(100);
+
+ // create the network used for the initial state computation
+ if (Abc_NtkHasMapping(pNtk))
+ pManMR->pInitNtk = Abc_NtkAlloc( pNtk->ntkType, ABC_FUNC_SOP, 1 );
+ else
+ pManMR->pInitNtk = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
+
+ // mitre inputs
+ Abc_NtkForEachLatch( pNtk, pLatch, i ) {
+ // map latch to initial state network
+ pPi = Abc_NtkCreatePi( pManMR->pInitNtk );
+
+ // has initial state requirement?
+ if (Abc_LatchIsInit0(pLatch)) {
+
+ if (Abc_NtkHasAig(pNtk))
+ pObj = Abc_ObjNot( pPi );
+ else
+ pObj = Abc_NtkCreateNodeInv( pManMR->pInitNtk, pPi );
+
+ Vec_PtrPush(vObj, pObj);
+ }
+ else if (Abc_LatchIsInit1(pLatch)) {
+ Vec_PtrPush(vObj, pPi);
+ }
+
+ Abc_ObjSetData( pLatch, pPi ); // if not verifying init state
+ // FDATA(pLatch)->pInitObj = pPi; // if verifying init state
+ }
+
+ // are there any nodes not DC?
+ if (!Vec_PtrSize(vObj)) {
+ pManMR->fSolutionIsDc = 1;
+ return;
+ } else
+ pManMR->fSolutionIsDc = 0;
+
+ // mitre output
+ if (Abc_NtkHasAig(pNtk)) {
+ // create AND-by-AND
+ pObj = Vec_PtrPop( vObj );
+ while( Vec_PtrSize(vObj) )
+ pObj = Abc_AigAnd( pManMR->pInitNtk->pManFunc, pObj, Vec_PtrPop( vObj ) );
+ } else
+ // create n-input AND gate
+ pObj = Abc_NtkCreateNodeAnd( pManMR->pInitNtk, vObj );
+
+ Abc_ObjAddFanin( Abc_NtkCreatePo( pManMR->pInitNtk ), pObj );
+
+ Vec_PtrFree( vObj );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Solves backward initial state computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) {
+ int i;
+ Abc_Obj_t *pObj, *pInitObj;
+ Vec_Ptr_t *vDelete = Vec_PtrAlloc(0);
+ int result;
+
+ assert(pManMR->pInitNtk);
+
+ // is the solution entirely DC's?
+ if (pManMR->fSolutionIsDc) {
+ Abc_NtkDelete(pManMR->pInitNtk);
+ Vec_PtrFree(vDelete);
+ Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj );
+ vprintf("\tno init state computation: all-don't-care solution\n");
+ return 1;
+ }
+
+ // check that network is combinational
+ // mark superfluous BI nodes for deletion
+ Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i ) {
+ assert(!Abc_ObjIsLatch(pObj));
+ assert(!Abc_ObjIsBo(pObj));
+
+ if (Abc_ObjIsBi(pObj)) {
+ Abc_ObjBetterTransferFanout( pObj, Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) );
+ Vec_PtrPush( vDelete, pObj );
+ }
+ }
+
+ // delete superfluous nodes
+ while(Vec_PtrSize( vDelete )) {
+ pObj = (Abc_Obj_t *)Vec_PtrPop( vDelete );
+ Abc_NtkDeleteObj( pObj );
+ }
+ Vec_PtrFree(vDelete);
+
+ // do some final cleanup on the network
+ Abc_NtkAddDummyPoNames(pManMR->pInitNtk);
+ Abc_NtkAddDummyPiNames(pManMR->pInitNtk);
+ if (Abc_NtkIsLogic(pManMR->pInitNtk))
+ Abc_NtkCleanup(pManMR->pInitNtk, 0);
+ else if (Abc_NtkIsStrash(pManMR->pInitNtk)) {
+ Abc_NtkReassignIds(pManMR->pInitNtk);
+ }
+
+ vprintf("\tsolving for init state (%d nodes)... ", Abc_NtkObjNum(pManMR->pInitNtk));
+ fflush(stdout);
+
+ // convert SOPs to BDD
+ if (Abc_NtkHasSop(pManMR->pInitNtk))
+ Abc_NtkSopToBdd( pManMR->pInitNtk );
+
+ // solve
+ result = Abc_NtkMiterSat( pManMR->pInitNtk, (sint64)500000, (sint64)50000000, 0, NULL, NULL );
+
+ if (!result) {
+ vprintf("SUCCESS\n");
+ } else {
+ vprintf("FAILURE\n");
+ printf("WARNING: no equivalent init state. setting all initial states to don't-cares\n");
+ Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj );
+ Abc_NtkDelete(pManMR->pInitNtk);
+ return 0;
+ }
+
+ // clear initial values, associate PIs to latches
+ Abc_NtkForEachPi( pManMR->pInitNtk, pInitObj, i ) Abc_ObjSetCopy( pInitObj, NULL );
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ pInitObj = Abc_ObjData( pObj );
+ assert( Abc_ObjIsPi( pInitObj ));
+ Abc_ObjSetCopy( pInitObj, pObj );
+ Abc_LatchSetInitNone( pObj );
+ }
+
+ // copy solution from PIs to latches
+ assert(pManMR->pInitNtk->pModel);
+ Abc_NtkForEachPi( pManMR->pInitNtk, pInitObj, i ) {
+ if ((pObj = Abc_ObjCopy( pInitObj ))) {
+ if ( pManMR->pInitNtk->pModel[i] )
+ Abc_LatchSetInit1( pObj );
+ else
+ Abc_LatchSetInit0( pObj );
+ }
+ }
+
+#if defined(DEBUG_CHECK)
+ // check that all latches have initial state
+ Abc_NtkForEachLatch( pNtk, pObj, i ) assert( !Abc_LatchIsInitNone( pObj ) );
+#endif
+
+ // deallocate
+ Abc_NtkDelete( pManMR->pInitNtk );
+
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Updates backward initial state computation problem.]
+
+ Description [Assumes box outputs in old positions stored w/ init values.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk ) {
+ Abc_Obj_t *pOrigObj, *pInitObj;
+ Vec_Ptr_t *vBo = Vec_PtrAlloc(100);
+ Vec_Ptr_t *vOldPis = Vec_PtrAlloc(100);
+ int i;
+
+ // remove PIs from network (from BOs)
+ Abc_NtkForEachObj( pNtk, pOrigObj, i )
+ if (Abc_ObjIsBo(pOrigObj)) {
+ pInitObj = FDATA(pOrigObj)->pInitObj;
+ assert(Abc_ObjIsPi(pInitObj));
+ Vec_PtrPush(vBo, pOrigObj);
+
+ Abc_FlowRetime_UpdateBackwardInit_rec( Abc_ObjFanin0( pOrigObj ), pInitObj, vOldPis, 0 );
+ }
+
+ // add PIs to network (at latches)
+ Abc_NtkForEachLatch( pNtk, pOrigObj, i )
+ Abc_FlowRetime_UpdateBackwardInit_rec( pOrigObj, NULL, vOldPis, 0 );
+
+ // connect nodes in init state network
+ Vec_PtrForEachEntry( vBo, pOrigObj, i )
+ Abc_FlowRetime_UpdateBackwardInit_rec( Abc_ObjFanin0( pOrigObj ), NULL, NULL, 1 );
+
+ // clear flags
+ Abc_NtkForEachObj( pNtk, pOrigObj, i )
+ pOrigObj->fMarkA = pOrigObj->fMarkB = 0;
+
+ // deallocate
+ Vec_PtrFree( vBo );
+ Vec_PtrFree( vOldPis );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Updates backward initial state computation problem.]
+
+ Description [Creates a duplicate node in the initial state network
+ corresponding to a node in the original circuit. If
+ fRecurse is set, the procedure recurses on and connects
+ the new node to its fan-ins. A latch in the original
+ circuit corresponds to a PI in the initial state network.
+ An existing PI may be supplied by pUseThisPi, and if the
+ node is a latch, it will be used; otherwise the PI is
+ saved in the list vOtherPis and subsequently used for
+ another latch.]
+
+ SideEffects [Nodes that have a corresponding initial state node
+ are marked with fMarkA. Nodes that have been fully
+ connected in the initial state network are marked with
+ fMarkB.]
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj,
+ Abc_Obj_t *pUseThisPi, Vec_Ptr_t *vOtherPis,
+ int fRecurse) {
+ Abc_Obj_t *pInitObj, *pOrigFanin, *pInitFanin;
+ void *pData;
+ int i;
+ Abc_Ntk_t *pNtk = Abc_ObjNtk( pOrigObj );
+
+ // should never reach primary IOs
+ assert(!Abc_ObjIsPi(pOrigObj));
+ assert(!Abc_ObjIsPo(pOrigObj));
+
+ // if fanin is latch, it becomes a primary input
+ if (Abc_ObjIsLatch( pOrigObj )) {
+ if (pOrigObj->fMarkA) return FDATA(pOrigObj)->pInitObj;
+
+ assert(vOtherPis);
+
+ if (pUseThisPi) {
+ // reuse curent PI
+ pInitObj = pUseThisPi; }
+ else {
+ // reuse previous PI
+ pInitObj = (Abc_Obj_t*)Vec_PtrPop(vOtherPis);
+ }
+
+ // remember link from original node to init ntk
+ Abc_ObjSetData( pOrigObj, pInitObj );
+
+ pOrigObj->fMarkA = 1;
+ return (FDATA(pOrigObj)->pInitObj = pInitObj);
+ }
+
+ // does an init node already exist?
+ if(!pOrigObj->fMarkA) {
+
+ if (Abc_NtkHasMapping( pNtk )) {
+ if (!pOrigObj->pData) {
+ // assume terminal...
+ assert(Abc_ObjFaninNum(pOrigObj) == 1);
+ pInitObj = Abc_NtkCreateNodeBuf( pManMR->pInitNtk, NULL );
+ } else {
+ pInitObj = Abc_NtkCreateObj( pManMR->pInitNtk, Abc_ObjType(pOrigObj) );
+ pData = Mio_GateReadSop(pOrigObj->pData);
+ assert( Abc_SopGetVarNum(pData) == Abc_ObjFaninNum(pOrigObj) );
+
+ pInitObj->pData = Abc_SopRegister( pManMR->pInitNtk->pManFunc, pData );
+ }
+ } else {
+ pData = Abc_ObjCopy( pOrigObj ); // save ptr to flow data
+ if (Abc_NtkIsStrash( pNtk ) && Abc_AigNodeIsConst( pOrigObj ))
+ pInitObj = Abc_AigConst1( pManMR->pInitNtk );
+ else
+ pInitObj = Abc_NtkDupObj( pManMR->pInitNtk, pOrigObj, 0 );
+ Abc_ObjSetCopy( pOrigObj, pData ); // restore ptr to flow data
+
+ // copy complementation
+ pInitObj->fCompl0 = pOrigObj->fCompl0;
+ pInitObj->fCompl1 = pOrigObj->fCompl1;
+ pInitObj->fPhase = pOrigObj->fPhase;
+ }
+
+ // if we didn't use given PI, immediately transfer fanouts
+ // and add to list for later reuse
+ if (pUseThisPi) {
+ Abc_ObjBetterTransferFanout( pUseThisPi, pInitObj, 0 );
+ Vec_PtrPush( vOtherPis, pUseThisPi );
+ }
+
+ pOrigObj->fMarkA = 1;
+ FDATA(pOrigObj)->pInitObj = pInitObj;
+ } else {
+ pInitObj = FDATA(pOrigObj)->pInitObj;
+ }
+
+ // have we already connected this object?
+ if (fRecurse && !pOrigObj->fMarkB) {
+
+ // create and/or connect fanins
+ Abc_ObjForEachFanin( pOrigObj, pOrigFanin, i ) {
+ pInitFanin = Abc_FlowRetime_UpdateBackwardInit_rec( pOrigFanin, NULL, NULL, fRecurse );
+ Abc_ObjAddFanin( pInitObj, pInitFanin );
+ }
+
+ pOrigObj->fMarkB = 1;
+ }
+
+ return pInitObj;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Verifies backward init state computation.]
+
+ Description [This procedure requires the BOs to store the original
+ latch values and the latches to store the new values:
+ both in the INIT_0 and INIT_1 flags in the Flow_Data
+ structure. (This is not currently the case in the rest
+ of the code.) Also, can not verify backward state
+ computations that span multiple combinational frames.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_VerifyBackwardInit( Abc_Ntk_t * pNtk ) {
+ Abc_Obj_t *pObj, *pFanin;
+ int i;
+
+ vprintf("\t\tupdating init state\n");
+
+ Abc_NtkIncrementTravId( pNtk );
+
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (Abc_ObjIsBo( pObj )) {
+ pFanin = Abc_ObjFanin0(pObj);
+ Abc_FlowRetime_VerifyBackwardInit_rec( pFanin );
+
+ if (FTEST(pObj, INIT_CARE)) {
+ if(FTEST(pObj, INIT_CARE) != FTEST(pFanin, INIT_CARE)) {
+ printf("ERROR: expected val=%d care=%d and got val=%d care=%d\n",
+ FTEST(pObj, INIT_1)?1:0, FTEST(pObj, INIT_CARE)?1:0,
+ FTEST(pFanin, INIT_1)?1:0, FTEST(pFanin, INIT_CARE)?1:0 );
+
+ }
+ }
+ }
+}
+
+void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ assert(!Abc_ObjIsBo(pObj)); // should never reach the inputs
+ assert(!Abc_ObjIsPi(pObj)); // should never reach the inputs
+
+ // visited?
+ if (Abc_NodeIsTravIdCurrent(pObj)) return;
+ Abc_NodeSetTravIdCurrent(pObj);
+
+ if (Abc_ObjIsLatch(pObj)) {
+ FUNSET(pObj, INIT_CARE);
+ if (Abc_LatchIsInit0(pObj))
+ FSET(pObj, INIT_0);
+ else if (Abc_LatchIsInit1(pObj))
+ FSET(pObj, INIT_1);
+ return;
+ }
+
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ Abc_FlowRetime_VerifyBackwardInit_rec( pNext );
+ }
+
+ Abc_FlowRetime_SimulateNode( pObj );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Constrains backward retiming for initializability.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_ConstrainInit( ) {
+ // unimplemented
+}
diff --git a/src/opt/fret/fretMain.c b/src/opt/fret/fretMain.c
new file mode 100644
index 00000000..780c1f6f
--- /dev/null
+++ b/src/opt/fret/fretMain.c
@@ -0,0 +1,1059 @@
+/**CFile****************************************************************
+
+ FileName [fretMain.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Flow-based retiming package.]
+
+ Synopsis [Main file for retiming package.]
+
+ Author [Aaron Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2008.]
+
+ Revision [$Id: fretMain.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "vec.h"
+#include "fretime.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_FlowRetime_AddDummyFanin( Abc_Obj_t * pObj );
+
+static void Abc_FlowRetime_MainLoop( );
+
+static void Abc_FlowRetime_MarkBlocks( Abc_Ntk_t * pNtk );
+static void Abc_FlowRetime_MarkReachable_rec( Abc_Obj_t * pObj, char end );
+static int Abc_FlowRetime_ImplementCut( Abc_Ntk_t * pNtk );
+static void Abc_FlowRetime_RemoveLatchBubbles( Abc_Obj_t * pLatch );
+
+static void Abc_FlowRetime_VerifyPathLatencies( Abc_Ntk_t * pNtk );
+static int Abc_FlowRetime_VerifyPathLatencies_rec( Abc_Obj_t * pObj, int markD );
+
+extern void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward );
+extern Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup );
+
+void
+print_node3(Abc_Obj_t *pObj);
+
+MinRegMan_t *pManMR;
+
+int fPathError = 0;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs minimum-register retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t *
+Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState,
+ int fForwardOnly, int fBackwardOnly, int nMaxIters,
+ int maxDelay, int fFastButConservative ) {
+
+ int i;
+ Abc_Obj_t *pObj, *pNext;
+
+ // create manager
+ pManMR = ALLOC( MinRegMan_t, 1 );
+
+ pManMR->pNtk = pNtk;
+ pManMR->fVerbose = fVerbose;
+ pManMR->fComputeInitState = fComputeInitState;
+ pManMR->fGuaranteeInitState = 0;
+ pManMR->fForwardOnly = fForwardOnly;
+ pManMR->fBackwardOnly = fBackwardOnly;
+ pManMR->nMaxIters = nMaxIters;
+ pManMR->maxDelay = maxDelay;
+ pManMR->fComputeInitState = fComputeInitState;
+ pManMR->fConservTimingOnly = fFastButConservative;
+ pManMR->vNodes = Vec_PtrAlloc(100);
+
+ vprintf("Flow-based minimum-register retiming...\n");
+
+ if (!Abc_NtkHasOnlyLatchBoxes(pNtk)) {
+ printf("\tERROR: Can not retime with black/white boxes\n");
+ return pNtk;
+ }
+
+ if (maxDelay) {
+ vprintf("\tmax delay constraint = %d\n", maxDelay);
+ if (maxDelay < (i = Abc_NtkLevel(pNtk))) {
+ printf("ERROR: max delay constraint must be > current max delay (%d)\n", i);
+ return pNtk;
+ }
+ }
+
+ // print info about type of network
+ vprintf("\tnetlist type = ");
+ if (Abc_NtkIsNetlist( pNtk )) { vprintf("netlist/"); }
+ else if (Abc_NtkIsLogic( pNtk )) { vprintf("logic/"); }
+ else if (Abc_NtkIsStrash( pNtk )) { vprintf("strash/"); }
+ else { vprintf("***unknown***/"); }
+ if (Abc_NtkHasSop( pNtk )) { vprintf("sop\n"); }
+ else if (Abc_NtkHasBdd( pNtk )) { vprintf("bdd\n"); }
+ else if (Abc_NtkHasAig( pNtk )) { vprintf("aig\n"); }
+ else if (Abc_NtkHasMapping( pNtk )) { vprintf("mapped\n"); }
+ else { vprintf("***unknown***\n"); }
+
+ vprintf("\tinitial reg count = %d\n", Abc_NtkLatchNum(pNtk));
+ vprintf("\tinitial levels = %d\n", Abc_NtkLevel(pNtk));
+
+ // remove bubbles from latch boxes
+ if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo(pNtk);
+ vprintf("\tpushing bubbles out of latch boxes\n");
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_FlowRetime_RemoveLatchBubbles(pObj);
+ if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo(pNtk);
+
+ // check for box inputs/outputs
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ assert(Abc_ObjFaninNum(pObj) == 1);
+ assert(Abc_ObjFanoutNum(pObj) == 1);
+ assert(!Abc_ObjFaninC0(pObj));
+
+ pNext = Abc_ObjFanin0(pObj);
+ assert(Abc_ObjIsBi(pNext));
+ assert(Abc_ObjFaninNum(pNext) <= 1);
+ if(Abc_ObjFaninNum(pNext) == 0) // every Bi should have a fanin
+ Abc_FlowRetime_AddDummyFanin( pNext );
+
+ pNext = Abc_ObjFanout0(pObj);
+ assert(Abc_ObjIsBo(pNext));
+ assert(Abc_ObjFaninNum(pNext) == 1);
+ assert(!Abc_ObjFaninC0(pNext));
+ }
+
+ pManMR->nLatches = Abc_NtkLatchNum( pNtk );
+ pManMR->nNodes = Abc_NtkObjNumMax( pNtk )+1;
+
+ // build histogram
+ pManMR->vSinkDistHist = Vec_IntStart( pManMR->nNodes*2+10 );
+
+ // initialize timing
+ if (maxDelay)
+ Abc_FlowRetime_InitTiming( pNtk );
+
+ // create Flow_Data structure
+ pManMR->pDataArray = ALLOC( Flow_Data_t, pManMR->nNodes );
+ Abc_FlowRetime_ClearFlows( 1 );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Abc_ObjSetCopy( pObj, (void *)(&pManMR->pDataArray[i]) );
+
+ // main loop!
+ Abc_FlowRetime_MainLoop();
+
+ // clear pCopy field
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ Abc_ObjSetCopy( pObj, NULL );
+
+ // if not computing init state, set all latches to DC
+ if (!fComputeInitState && Abc_ObjIsLatch(pObj))
+ Abc_LatchSetInitDc(pObj);
+ }
+
+ // deallocate space
+ FREE( pManMR->pDataArray );
+ if (pManMR->vNodes) Vec_PtrFree(pManMR->vNodes);
+ if (pManMR->vSinkDistHist) Vec_IntFree(pManMR->vSinkDistHist);
+ if (pManMR->maxDelay) Abc_FlowRetime_FreeTiming( pNtk );
+
+ // restrash if necessary
+ if (Abc_NtkIsStrash(pNtk)) {
+ Abc_NtkReassignIds( pNtk );
+ pNtk = Abc_NtkRestrash( pNtk, 1 );
+ }
+
+ vprintf("\tfinal reg count = %d\n", Abc_NtkLatchNum(pNtk));
+ vprintf("\tfinal levels = %d\n", Abc_NtkLevel(pNtk));
+
+#if defined(DEBUG_CHECK)
+ Abc_NtkDoCheck( pNtk );
+#endif
+
+ // free manager
+ FREE( pManMR );
+
+ return pNtk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Main loop.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_MainLoop( ) {
+ Abc_Ntk_t *pNtk = pManMR->pNtk;
+ // Abc_Obj_t *pObj; int i;
+ int last, flow = 0, cut;
+
+ // (i) forward retiming loop
+ pManMR->fIsForward = 1;
+ pManMR->iteration = 0;
+
+ if (!pManMR->fBackwardOnly) do {
+ if (pManMR->iteration == pManMR->nMaxIters) break;
+ pManMR->subIteration = 0;
+
+ vprintf("\tforward iteration %d\n", pManMR->iteration);
+ last = Abc_NtkLatchNum( pNtk );
+
+ Abc_FlowRetime_MarkBlocks( pNtk );
+
+ if (pManMR->maxDelay) {
+ // timing-constrained loop
+ Abc_FlowRetime_ConstrainConserv( pNtk );
+ while(Abc_FlowRetime_RefineConstraints( )) {
+ pManMR->subIteration++;
+ Abc_FlowRetime_ClearFlows( 0 );
+ }
+ } else {
+ flow = Abc_FlowRetime_PushFlows( pNtk, 1 );
+ }
+
+ cut = Abc_FlowRetime_ImplementCut( pNtk );
+
+ vprintf("\t\tlevels = %d\n", Abc_NtkLevel(pNtk));
+
+#if 0
+ Abc_NtkForEachObj( pNtk, pObj, i ) pObj->Level = 0;
+
+ Abc_NtkLevel(pNtk);
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (pObj->Level > pManMR->maxDelay) {
+ print_node( pObj );
+ Vec_PtrForEachEntry( FTIMEEDGES(pObj), p2,j ) {
+ printf(":%d ", p2->Id);
+ }
+ }
+ Abc_NtkLevelReverse(pNtk);
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (pObj->Level > pManMR->maxDelay) {
+ print_node( pObj );
+ }
+#endif
+
+ Abc_FlowRetime_ClearFlows( 1 );
+
+ pManMR->iteration++;
+ } while( cut != last );
+
+ // print info about initial states
+ if (pManMR->fComputeInitState && pManMR->fVerbose)
+ Abc_FlowRetime_PrintInitStateInfo( pNtk );
+
+ // (ii) backward retiming loop
+ pManMR->fIsForward = 0;
+ pManMR->iteration = 0;
+
+ if (!pManMR->fForwardOnly) do {
+ // initializability loop
+
+ if (pManMR->fComputeInitState) {
+ Abc_FlowRetime_SetupBackwardInit( pNtk );
+ }
+
+ do {
+ if (pManMR->iteration == pManMR->nMaxIters) break;
+ pManMR->subIteration = 0;
+
+ vprintf("\tbackward iteration %d\n", pManMR->iteration);
+ last = Abc_NtkLatchNum( pNtk );
+
+ Abc_FlowRetime_MarkBlocks( pNtk );
+
+ if (pManMR->maxDelay) {
+ // timing-constrained loop
+ Abc_FlowRetime_ConstrainConserv( pNtk );
+ while(Abc_FlowRetime_RefineConstraints( )) {
+ pManMR->subIteration++;
+ Abc_FlowRetime_ClearFlows( 0 );
+ }
+ } else {
+ flow = Abc_FlowRetime_PushFlows( pNtk, 1 );
+ }
+
+ cut = Abc_FlowRetime_ImplementCut( pNtk );
+
+ vprintf("\t\tlevels = %d\n", Abc_NtkLevelReverse(pNtk));
+
+#if 0
+ Abc_NtkForEachObj( pNtk, pObj, i ) pObj->Level = 0;
+
+ Abc_NtkLevel(pNtk);
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (pObj->Level > pManMR->maxDelay) {
+ print_node( pObj );
+ }
+ Abc_NtkLevelReverse(pNtk);
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (pObj->Level > pManMR->maxDelay) {
+ print_node( pObj );
+ }
+#endif
+
+ Abc_FlowRetime_ClearFlows( 1 );
+
+ pManMR->iteration++;
+ } while( cut != last );
+
+ // compute initial states
+ if (!pManMR->fComputeInitState) break;
+
+ if (Abc_FlowRetime_SolveBackwardInit( pNtk )) {
+ if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo( pNtk );
+ break;
+ } else {
+ if (!pManMR->fGuaranteeInitState) break;
+ Abc_FlowRetime_ConstrainInit( );
+ }
+ } while(1);
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Pushes latch bubbles outside of box.]
+
+ Description [If network is an AIG, a fCompl0 is allowed to remain on
+ the BI node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_RemoveLatchBubbles( Abc_Obj_t * pLatch ) {
+ int bubble = 0;
+ Abc_Ntk_t *pNtk = pManMR->pNtk;
+ Abc_Obj_t *pBi, *pBo, *pInv;
+
+ pBi = Abc_ObjFanin0(pLatch);
+ pBo = Abc_ObjFanout0(pLatch);
+ assert(!Abc_ObjIsComplement(pBi));
+ assert(!Abc_ObjIsComplement(pBo));
+
+ // push bubbles on BO into latch box
+ if (Abc_ObjFaninC0(pBo) && Abc_ObjFanoutNum(pBo) > 0) {
+ bubble = 1;
+ if (Abc_LatchIsInit0(pLatch)) Abc_LatchSetInit1(pLatch);
+ else if (Abc_LatchIsInit1(pLatch)) Abc_LatchSetInit0(pLatch);
+ }
+
+ // absorb bubbles on BI
+ pBi->fCompl0 ^= bubble ^ Abc_ObjFaninC0(pLatch);
+
+ // convert bubble to INV if not AIG
+ if (!Abc_NtkHasAig( pNtk ) && Abc_ObjFaninC0(pBi)) {
+ pBi->fCompl0 = 0;
+ pInv = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanin0(pBi) );
+ Abc_ObjPatchFanin( pBi, Abc_ObjFanin0(pBi), pInv );
+ }
+
+ pBo->fCompl0 = 0;
+ pLatch->fCompl0 = 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Marks nodes in TFO/TFI of PI/PO.]
+
+ Description [Sets flow data flag BLOCK appropriately.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_MarkBlocks( Abc_Ntk_t * pNtk ) {
+ int i;
+ Abc_Obj_t *pObj;
+
+ if (pManMR->fIsForward){
+ // mark the frontier
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ pObj->fMarkA = 1;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pObj->fMarkA = 1;
+ }
+ // mark the nodes reachable from the PIs
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_NtkMarkCone_rec( pObj, pManMR->fIsForward );
+ } else {
+ // mark the frontier
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->fMarkA = 1;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pObj->fMarkA = 1;
+ }
+ // mark the nodes reachable from the POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_NtkMarkCone_rec( pObj, pManMR->fIsForward );
+ }
+
+ // copy marks
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ if (pObj->fMarkA) {
+ pObj->fMarkA = 0;
+ if (!Abc_ObjIsLatch(pObj) /* && !Abc_ObjIsPi(pObj) */ )
+ FSET(pObj, BLOCK);
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes maximum flow.]
+
+ Description []
+
+ SideEffects [Leaves VISITED flags on source-reachable nodes.]
+
+ SeeAlso []
+
+***********************************************************************/
+int
+Abc_FlowRetime_PushFlows( Abc_Ntk_t * pNtk, bool fVerbose ) {
+ int i, j, flow = 0, last, srcDist = 0;
+ Abc_Obj_t *pObj, *pObj2;
+
+ pManMR->constraintMask |= BLOCK;
+
+ pManMR->fSinkDistTerminate = 0;
+ dfsfast_preorder( pNtk );
+
+ // (i) fast max-flow computation
+ while(!pManMR->fSinkDistTerminate && srcDist < MAX_DIST) {
+ srcDist = MAX_DIST;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ if (FDATA(pObj)->e_dist)
+ srcDist = MIN(srcDist, FDATA(pObj)->e_dist);
+
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ if (srcDist == FDATA(pObj)->e_dist &&
+ dfsfast_e( pObj, NULL )) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("\n\n");
+#endif
+ flow++;
+ }
+ }
+ }
+
+ if (fVerbose) vprintf("\t\tmax-flow1 = %d \t", flow);
+
+ // (ii) complete max-flow computation
+ // also, marks source-reachable nodes
+ do {
+ last = flow;
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ if (dfsplain_e( pObj, NULL )) {
+#ifdef DEBUG_PRINT_FLOWS
+ printf("\n\n");
+#endif
+ flow++;
+ Abc_NtkForEachObj( pNtk, pObj2, j )
+ FUNSET( pObj2, VISITED );
+ }
+ }
+ } while (flow > last);
+
+ if (fVerbose) vprintf("max-flow2 = %d\n", flow);
+
+ return flow;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Restores latch boxes.]
+
+ Description [Latchless BI/BO nodes are removed. Latch boxes are
+ restored around remaining latches.]
+
+ SideEffects [Deletes nodes as appropriate.]
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_FixLatchBoxes( Abc_Ntk_t *pNtk, Vec_Ptr_t *vBoxIns ) {
+ int i;
+ Abc_Obj_t *pObj, *pBo = NULL, *pBi = NULL;
+ Vec_Ptr_t *vFreeBi = Vec_PtrAlloc( 100 );
+ Vec_Ptr_t *vFreeBo = Vec_PtrAlloc( 100 );
+
+ // 1. remove empty bi/bo pairs
+ while(Vec_PtrSize( vBoxIns )) {
+ pBi = (Abc_Obj_t *)Vec_PtrPop( vBoxIns );
+ assert(Abc_ObjIsBi(pBi));
+ assert(Abc_ObjFanoutNum(pBi) == 1);
+ assert(Abc_ObjFaninNum(pBi) == 1);
+ pBo = Abc_ObjFanout0(pBi);
+ assert(!Abc_ObjFaninC0(pBo));
+
+ if (Abc_ObjIsBo(pBo)) {
+ // an empty bi/bo pair
+
+ Abc_ObjRemoveFanins( pBo );
+ // transfer complement from BI, if present
+ assert(!Abc_ObjIsComplement(Abc_ObjFanin0(pBi)));
+ Abc_ObjBetterTransferFanout( pBo, Abc_ObjFanin0(pBi), Abc_ObjFaninC0(pBi) );
+
+ Abc_ObjRemoveFanins( pBi );
+ pBi->fCompl0 = 0;
+ Vec_PtrPush( vFreeBi, pBi );
+ Vec_PtrPush( vFreeBo, pBo );
+
+ // free names
+ if (Nm_ManFindNameById(pNtk->pManName, Abc_ObjId(pBi)))
+ Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pBi));
+ if (Nm_ManFindNameById(pNtk->pManName, Abc_ObjId(pBo)))
+ Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pBo));
+
+ // check for complete detachment
+ assert(Abc_ObjFaninNum(pBi) == 0);
+ assert(Abc_ObjFanoutNum(pBi) == 0);
+ assert(Abc_ObjFaninNum(pBo) == 0);
+ assert(Abc_ObjFanoutNum(pBo) == 0);
+ } else assert(Abc_ObjIsLatch(pBo));
+ }
+
+ // 2. add bi/bos as necessary for latches
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ assert(Abc_ObjFaninNum(pObj) == 1);
+ if (Abc_ObjFanoutNum(pObj))
+ pBo = Abc_ObjFanout0(pObj);
+ else pBo = NULL;
+ pBi = Abc_ObjFanin0(pObj);
+
+ // add BO
+ if (!pBo || !Abc_ObjIsBo(pBo)) {
+ pBo = (Abc_Obj_t *)Vec_PtrPop( vFreeBo );
+ if (Abc_ObjFanoutNum(pObj)) Abc_ObjTransferFanout( pObj, pBo );
+ Abc_ObjAddFanin( pBo, pObj );
+ }
+ // add BI
+ if (!Abc_ObjIsBi(pBi)) {
+ pBi = (Abc_Obj_t *)Vec_PtrPop( vFreeBi );
+ assert(Abc_ObjFaninNum(pBi) == 0);
+ Abc_ObjAddFanin( pBi, Abc_ObjFanin0(pObj) );
+ pBi->fCompl0 = pObj->fCompl0;
+ Abc_ObjRemoveFanins( pObj );
+ Abc_ObjAddFanin( pObj, pBi );
+ }
+ }
+
+ // delete remaining BIs and BOs
+ while(Vec_PtrSize( vFreeBi )) {
+ pObj = (Abc_Obj_t *)Vec_PtrPop( vFreeBi );
+ Abc_NtkDeleteObj( pObj );
+ }
+ while(Vec_PtrSize( vFreeBo )) {
+ pObj = (Abc_Obj_t *)Vec_PtrPop( vFreeBo );
+ Abc_NtkDeleteObj( pObj );
+ }
+
+#if defined(DEBUG_CHECK)
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ if (Abc_ObjIsBo(pObj)) {
+ assert(Abc_ObjFaninNum(pObj) == 1);
+ assert(Abc_ObjIsLatch(Abc_ObjFanin0(pObj)));
+ }
+ if (Abc_ObjIsBi(pObj)) {
+ assert(Abc_ObjFaninNum(pObj) == 1);
+ assert(Abc_ObjFanoutNum(pObj) == 1);
+ assert(Abc_ObjIsLatch(Abc_ObjFanout0(pObj)));
+ }
+ if (Abc_ObjIsLatch(pObj)) {
+ assert(Abc_ObjFanoutNum(pObj) == 1);
+ assert(Abc_ObjFaninNum(pObj) == 1);
+ }
+ }
+#endif
+
+ Vec_PtrFree( vFreeBi );
+ Vec_PtrFree( vFreeBo );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks register count along all combinational paths.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_VerifyPathLatencies( Abc_Ntk_t * pNtk ) {
+ int i;
+ Abc_Obj_t *pObj;
+ fPathError = 0;
+
+ vprintf("\t\tVerifying latency along all paths...");
+
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ if (Abc_ObjIsBo(pObj)) {
+ Abc_FlowRetime_VerifyPathLatencies_rec( pObj, 0 );
+ } else if (!pManMR->fIsForward && Abc_ObjIsPi(pObj)) {
+ Abc_FlowRetime_VerifyPathLatencies_rec( pObj, 0 );
+ }
+
+ if (fPathError) {
+ if (Abc_ObjFaninNum(pObj) > 0) {
+ printf("fanin ");
+ print_node(Abc_ObjFanin0(pObj));
+ }
+ printf("\n");
+ exit(0);
+ }
+ }
+
+ vprintf(" ok\n");
+
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ pObj->fMarkA = 0;
+ pObj->fMarkB = 0;
+ pObj->fMarkC = 0;
+ }
+}
+
+
+int
+Abc_FlowRetime_VerifyPathLatencies_rec( Abc_Obj_t * pObj, int markD ) {
+ int i, j;
+ Abc_Obj_t *pNext;
+ int fCare = 0;
+ int markC = pObj->fMarkC;
+
+ if (!pObj->fMarkB) {
+ pObj->fMarkB = 1; // visited
+
+ if (Abc_ObjIsLatch(pObj))
+ markC = 1; // latch in output
+
+ if (!pManMR->fIsForward && !Abc_ObjIsPo(pObj) && !Abc_ObjFanoutNum(pObj))
+ return -1; // dangling non-PO outputs : don't care what happens
+
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ // reached end of cycle?
+ if ( Abc_ObjIsBo(pNext) ||
+ (pManMR->fIsForward && Abc_ObjIsPo(pNext)) ) {
+ if (!markD && !Abc_ObjIsLatch(pObj)) {
+ printf("\nERROR: no-latch path (end)\n");
+ print_node(pNext);
+ printf("\n");
+ fPathError = 1;
+ }
+ } else if (!pManMR->fIsForward && Abc_ObjIsPo(pNext)) {
+ if (markD || Abc_ObjIsLatch(pObj)) {
+ printf("\nERROR: extra-latch path to outputs\n");
+ print_node(pNext);
+ printf("\n");
+ fPathError = 1;
+ }
+ } else {
+ j = Abc_FlowRetime_VerifyPathLatencies_rec( pNext, markD || Abc_ObjIsLatch(pObj) );
+ if (j >= 0) {
+ markC |= j;
+ fCare = 1;
+ }
+ }
+
+ if (fPathError) {
+ print_node(pObj);
+ printf("\n");
+ return 0;
+ }
+ }
+ }
+
+ if (!fCare) return -1;
+
+ if (markC && markD) {
+ printf("\nERROR: mult-latch path\n");
+ print_node(pObj);
+ printf("\n");
+ fPathError = 1;
+ }
+ if (!markC && !markD) {
+ printf("\nERROR: no-latch path (inter)\n");
+ print_node(pObj);
+ printf("\n");
+ fPathError = 1;
+ }
+
+ return (pObj->fMarkC = markC);
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Copies initial state from latches to BO nodes.]
+
+ Description [Initial states are marked on BO nodes with INIT_0 and
+ INIT_1 flags in their Flow_Data structures.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_CopyInitState( Abc_Obj_t * pSrc, Abc_Obj_t * pDest ) {
+ Abc_Obj_t *pObj;
+
+ if (!pManMR->fComputeInitState) return;
+
+ assert(Abc_ObjIsLatch(pSrc));
+ assert(Abc_ObjFanin0(pDest) == pSrc);
+ assert(!Abc_ObjFaninC0(pDest));
+
+ FUNSET(pDest, INIT_CARE);
+ if (Abc_LatchIsInit0(pSrc)) {
+ FSET(pDest, INIT_0);
+ } else if (Abc_LatchIsInit1(pSrc)) {
+ FSET(pDest, INIT_1);
+ }
+
+ if (!pManMR->fIsForward) {
+ pObj = Abc_ObjData(pSrc);
+ assert(Abc_ObjIsPi(pObj));
+ FDATA(pDest)->pInitObj = pObj;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Implements min-cut.]
+
+ Description [Requires source-reachable nodes to be marked VISITED.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int
+Abc_FlowRetime_ImplementCut( Abc_Ntk_t * pNtk ) {
+ int i, j, cut = 0, unmoved = 0;
+ Abc_Obj_t *pObj, *pReg, *pNext, *pBo = NULL, *pBi = NULL;
+ Vec_Ptr_t *vFreeRegs = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+ Vec_Ptr_t *vBoxIns = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+ Vec_Ptr_t *vMove = Vec_PtrAlloc( 100 );
+
+ // remove latches from netlist
+ Abc_NtkForEachLatch( pNtk, pObj, i ) {
+ pBo = Abc_ObjFanout0(pObj);
+ pBi = Abc_ObjFanin0(pObj);
+ assert(Abc_ObjIsBo(pBo) && Abc_ObjIsBi(pBi));
+ Vec_PtrPush( vBoxIns, pBi );
+
+ // copy initial state values to BO
+ Abc_FlowRetime_CopyInitState( pObj, pBo );
+
+ // re-use latch elsewhere
+ Vec_PtrPush( vFreeRegs, pObj );
+ FSET(pBo, CROSS_BOUNDARY);
+
+ // cut out of netlist
+ Abc_ObjPatchFanin( pBo, pObj, pBi );
+ Abc_ObjRemoveFanins( pObj );
+
+ // free name
+ if (Nm_ManFindNameById(pNtk->pManName, Abc_ObjId(pObj)))
+ Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pObj));
+ }
+
+ // insert latches into netlist
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ if (Abc_ObjIsLatch( pObj )) continue;
+
+ // a latch is required on every node that lies across the min-cit
+ assert(!pManMR->fIsForward || !FTEST(pObj, VISITED_E) || FTEST(pObj, VISITED_R));
+ if (FTEST(pObj, VISITED_R) && !FTEST(pObj, VISITED_E)) {
+ assert(FTEST(pObj, FLOW));
+
+ // count size of cut
+ cut++;
+ if ((pManMR->fIsForward && Abc_ObjIsBo(pObj)) ||
+ (!pManMR->fIsForward && Abc_ObjIsBi(pObj)))
+ unmoved++;
+
+ // only insert latch between fanouts that lie across min-cut
+ // some fanout paths may be cut at deeper points
+ Abc_ObjForEachFanout( pObj, pNext, j )
+ if (Abc_FlowRetime_IsAcrossCut( pObj, pNext ))
+ Vec_PtrPush(vMove, pNext);
+
+ // check that move-set is non-zero
+ if (Vec_PtrSize(vMove) == 0)
+ print_node(pObj);
+ assert(Vec_PtrSize(vMove) > 0);
+
+ // insert one of re-useable registers
+ assert(Vec_PtrSize( vFreeRegs ));
+ pReg = (Abc_Obj_t *)Vec_PtrPop( vFreeRegs );
+
+ Abc_ObjAddFanin(pReg, pObj);
+ while(Vec_PtrSize( vMove )) {
+ pNext = (Abc_Obj_t *)Vec_PtrPop( vMove );
+ Abc_ObjPatchFanin( pNext, pObj, pReg );
+ if (Abc_ObjIsBi(pNext)) assert(Abc_ObjFaninNum(pNext) == 1);
+
+ }
+ if (Abc_ObjIsBi(pObj)) assert(Abc_ObjFaninNum(pObj) == 1);
+ }
+ }
+
+#if defined(DEBUG_CHECK)
+ Abc_FlowRetime_VerifyPathLatencies( pNtk );
+#endif
+
+ // delete remaining latches
+ while(Vec_PtrSize( vFreeRegs )) {
+ pReg = (Abc_Obj_t *)Vec_PtrPop( vFreeRegs );
+ Abc_NtkDeleteObj( pReg );
+ }
+
+ // update initial states
+ Abc_FlowRetime_InitState( pNtk );
+
+ // restore latch boxes
+ Abc_FlowRetime_FixLatchBoxes( pNtk, vBoxIns );
+
+ Vec_PtrFree( vFreeRegs );
+ Vec_PtrFree( vMove );
+ Vec_PtrFree( vBoxIns );
+
+ vprintf("\t\tmin-cut = %d (unmoved = %d)\n", cut, unmoved);
+ return cut;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Adds dummy fanin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_FlowRetime_AddDummyFanin( Abc_Obj_t * pObj ) {
+ Abc_Ntk_t *pNtk = Abc_ObjNtk( pObj );
+
+ if (Abc_NtkHasAig(pNtk))
+ Abc_ObjAddFanin(pObj, Abc_AigConst1( pNtk ));
+ else
+ Abc_ObjAddFanin(pObj, Abc_NtkCreateNodeConst0( pNtk ));
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints information about a node.]
+
+ Description [Debuging.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+print_node(Abc_Obj_t *pObj) {
+ int i;
+ Abc_Obj_t * pNext;
+ char m[6];
+
+ m[0] = 0;
+ if (pObj->fMarkA)
+ strcat(m, "A");
+ if (pObj->fMarkB)
+ strcat(m, "B");
+ if (pObj->fMarkC)
+ strcat(m, "C");
+
+ printf("node %d type=%d lev=%d tedge=%d (%x%s) fanouts {", Abc_ObjId(pObj), Abc_ObjType(pObj),
+ pObj->Level, Vec_PtrSize(FTIMEEDGES(pObj)), FDATA(pObj)->mark, m);
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ printf("%d[%d](%d),", Abc_ObjId(pNext), Abc_ObjType(pNext), FDATA(pNext)->mark);
+ printf("} fanins {");
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ printf("%d[%d](%d),", Abc_ObjId(pNext), Abc_ObjType(pNext), FDATA(pNext)->mark);
+ printf("}\n");
+}
+
+void
+print_node2(Abc_Obj_t *pObj) {
+ int i;
+ Abc_Obj_t * pNext;
+ char m[6];
+
+ m[0] = 0;
+ if (pObj->fMarkA)
+ strcat(m, "A");
+ if (pObj->fMarkB)
+ strcat(m, "B");
+ if (pObj->fMarkC)
+ strcat(m, "C");
+
+ printf("node %d type=%d %s fanouts {", Abc_ObjId(pObj), Abc_ObjType(pObj), m);
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ printf("%d ,", Abc_ObjId(pNext));
+ printf("} fanins {");
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ printf("%d ,", Abc_ObjId(pNext));
+ printf("} ");
+}
+
+void
+print_node3(Abc_Obj_t *pObj) {
+ int i;
+ Abc_Obj_t * pNext;
+ char m[6];
+
+ m[0] = 0;
+ if (pObj->fMarkA)
+ strcat(m, "A");
+ if (pObj->fMarkB)
+ strcat(m, "B");
+ if (pObj->fMarkC)
+ strcat(m, "C");
+
+ printf("\nnode %d type=%d mark=%d %s\n", Abc_ObjId(pObj), Abc_ObjType(pObj), FDATA(pObj)->mark, m);
+ printf("fanouts\n");
+ Abc_ObjForEachFanout( pObj, pNext, i ) {
+ print_node(pNext);
+ printf("\n");
+ }
+ printf("fanins\n");
+ Abc_ObjForEachFanin( pObj, pNext, i ) {
+ print_node(pNext);
+ printf("\n");
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transfers fanout.]
+
+ Description [Does not produce an error if there is no fanout.
+ Complements as necessary.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void
+Abc_ObjBetterTransferFanout( Abc_Obj_t * pFrom, Abc_Obj_t * pTo, int compl ) {
+ Abc_Obj_t *pNext;
+
+ while(Abc_ObjFanoutNum(pFrom) > 0) {
+ pNext = Abc_ObjFanout0(pFrom);
+ Abc_ObjPatchFanin( pNext, pFrom, Abc_ObjNotCond(pTo, compl) );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns true is a connection spans the min-cut.]
+
+ Description [pNext is a direct fanout of pObj.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool
+Abc_FlowRetime_IsAcrossCut( Abc_Obj_t *pObj, Abc_Obj_t *pNext ) {
+
+ if (FTEST(pObj, VISITED_R) && !FTEST(pObj, VISITED_E)) {
+ if (pManMR->fIsForward) {
+ if (!FTEST(pNext, VISITED_R) ||
+ (FTEST(pNext, BLOCK_OR_CONS) & pManMR->constraintMask)||
+ FTEST(pNext, CROSS_BOUNDARY) ||
+ Abc_ObjIsLatch(pNext))
+ return 1;
+ } else {
+ if (FTEST(pNext, VISITED_E) ||
+ FTEST(pNext, CROSS_BOUNDARY))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Resets flow problem]
+
+ Description [If fClearAll is true, all marks will be cleared; this is
+ typically appropriate after the circuit structure has
+ been modified.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_ClearFlows( bool fClearAll ) {
+ int i;
+
+ if (fClearAll)
+ memset(pManMR->pDataArray, 0, sizeof(Flow_Data_t)*pManMR->nNodes);
+ else {
+ // clear only data related to flow problem
+ for(i=0; i<pManMR->nNodes; i++) {
+ pManMR->pDataArray[i].mark &= ~(VISITED | FLOW );
+ pManMR->pDataArray[i].e_dist = 0;
+ pManMR->pDataArray[i].r_dist = 0;
+ pManMR->pDataArray[i].pred = NULL;
+ }
+ }
+}
diff --git a/src/opt/fret/fretTime.c b/src/opt/fret/fretTime.c
new file mode 100644
index 00000000..f497df60
--- /dev/null
+++ b/src/opt/fret/fretTime.c
@@ -0,0 +1,763 @@
+/**CFile****************************************************************
+
+ FileName [fretTime.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Flow-based retiming package.]
+
+ Synopsis [Delay-constrained retiming code.]
+
+ Author [Aaron Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2008.]
+
+ Revision [$Id: fretTime.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "vec.h"
+#include "fretime.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Abc_FlowRetime_Dfs_forw( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes );
+static void Abc_FlowRetime_Dfs_back( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes );
+
+static void Abc_FlowRetime_ConstrainExact_forw( Abc_Obj_t * pObj );
+static void Abc_FlowRetime_ConstrainExact_back( Abc_Obj_t * pObj );
+static void Abc_FlowRetime_ConstrainConserv_forw( Abc_Ntk_t * pNtk );
+static void Abc_FlowRetime_ConstrainConserv_back( Abc_Ntk_t * pNtk );
+
+
+void trace2(Abc_Obj_t *pObj) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ print_node(pObj);
+ Abc_ObjForEachFanin(pObj, pNext, i)
+ if (pNext->Level >= pObj->Level - 1) {
+ trace2(pNext);
+ break;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [Initializes timing]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_InitTiming( Abc_Ntk_t *pNtk ) {
+
+ pManMR->nConservConstraints = pManMR->nExactConstraints = 0;
+
+ pManMR->vExactNodes = Vec_PtrAlloc(1000);
+
+ pManMR->vTimeEdges = ALLOC( Vec_Ptr_t, Abc_NtkObjNumMax(pNtk)+1 );
+ assert(pManMR->vTimeEdges);
+ memset(pManMR->vTimeEdges, 0, (Abc_NtkObjNumMax(pNtk)+1) * sizeof(Vec_Ptr_t) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Marks nodes with conservative constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_ConstrainConserv( Abc_Ntk_t * pNtk ) {
+ Abc_Obj_t *pObj;
+ int i;
+ void *pArray;
+
+ // clear all exact constraints
+ pManMR->nExactConstraints = 0;
+ while( Vec_PtrSize( pManMR->vExactNodes )) {
+ pObj = Vec_PtrPop( pManMR->vExactNodes );
+
+ if ( Vec_PtrSize( FTIMEEDGES(pObj) )) {
+ pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) );
+ FREE( pArray );
+ }
+ }
+
+#if !defined(IGNORE_TIMING)
+ if (pManMR->fIsForward) {
+ Abc_FlowRetime_ConstrainConserv_forw(pNtk);
+ } else {
+ Abc_FlowRetime_ConstrainConserv_back(pNtk);
+ }
+#endif
+
+ Abc_NtkForEachObj( pNtk, pObj, i)
+ assert( !Vec_PtrSize(FTIMEEDGES(pObj)) );
+}
+
+
+void Abc_FlowRetime_ConstrainConserv_forw( Abc_Ntk_t * pNtk ) {
+ Vec_Ptr_t *vNodes = pManMR->vNodes;
+ Abc_Obj_t *pObj, *pNext, *pBi, *pBo;
+ int i, j;
+
+ assert(!Vec_PtrSize( vNodes ));
+ pManMR->nConservConstraints = 0;
+
+ // 1. hard constraints
+
+ // (i) collect TFO of PIs
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachPi(pNtk, pObj, i)
+ Abc_FlowRetime_Dfs_forw( pObj, vNodes );
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanin( pObj, pNext, j )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < pNext->Level )
+ pObj->Level = pNext->Level;
+ }
+ pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0;
+
+ if ( Abc_ObjIsBi(pObj) )
+ pObj->fMarkA = 1;
+
+ assert(pObj->Level <= pManMR->maxDelay);
+ }
+
+ // collect TFO of latches
+ // seed arrival times from BIs
+ Vec_PtrClear(vNodes);
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch(pNtk, pObj, i) {
+ pBo = Abc_ObjFanout0( pObj );
+ pBi = Abc_ObjFanin0( pObj );
+
+ Abc_NodeSetTravIdCurrent( pObj );
+ Abc_FlowRetime_Dfs_forw( pBo, vNodes );
+
+ if (pBi->fMarkA) {
+ pBi->fMarkA = 0;
+ pObj->Level = pBi->Level;
+ assert(pObj->Level <= pManMR->maxDelay);
+ } else
+ pObj->Level = 0;
+ }
+
+#if defined(DEBUG_CHECK)
+ // DEBUG: check DFS ordering
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->fMarkB = 1;
+
+ Abc_ObjForEachFanin( pObj, pNext, j )
+ if ( Abc_NodeIsTravIdCurrent(pNext) && !Abc_ObjIsLatch(pNext))
+ assert(pNext->fMarkB);
+ }
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i)
+ pObj->fMarkB = 0;
+#endif
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanin( pObj, pNext, j )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < pNext->Level )
+ pObj->Level = pNext->Level;
+ }
+ pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0;
+
+ if (pObj->Level > pManMR->maxDelay) {
+ FSET(pObj, BLOCK);
+ }
+ }
+
+ // 2. conservative constraints
+
+ // first pass: seed latches with T=0
+ Abc_NtkForEachLatch(pNtk, pObj, i) {
+ pObj->Level = 0;
+ }
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanin( pObj, pNext, j ) {
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < pNext->Level )
+ pObj->Level = pNext->Level;
+ }
+ pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0;
+
+ if ( Abc_ObjIsBi(pObj) )
+ pObj->fMarkA = 1;
+
+ assert(pObj->Level <= pManMR->maxDelay);
+ }
+
+ Abc_NtkForEachLatch(pNtk, pObj, i) {
+ pBo = Abc_ObjFanout0( pObj );
+ pBi = Abc_ObjFanin0( pObj );
+
+ if (pBi->fMarkA) {
+ pBi->fMarkA = 0;
+ pObj->Level = pBi->Level;
+ assert(pObj->Level <= pManMR->maxDelay);
+ } else
+ pObj->Level = 0;
+ }
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanin( pObj, pNext, j ) {
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < pNext->Level )
+ pObj->Level = pNext->Level;
+ }
+ pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0;
+
+ // constrained?
+ if (pObj->Level > pManMR->maxDelay) {
+ FSET( pObj, CONSERVATIVE );
+ pManMR->nConservConstraints++;
+ } else
+ FUNSET( pObj, CONSERVATIVE );
+ }
+
+ Vec_PtrClear( vNodes );
+}
+
+
+void Abc_FlowRetime_ConstrainConserv_back( Abc_Ntk_t * pNtk ) {
+ Vec_Ptr_t *vNodes = pManMR->vNodes;
+ Abc_Obj_t *pObj, *pNext, *pBi, *pBo;
+ int i, j, l;
+
+ assert(!Vec_PtrSize(vNodes));
+
+ pManMR->nConservConstraints = 0;
+
+ // 1. hard constraints
+
+ // (i) collect TFO of POs
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachPo(pNtk, pObj, i)
+ Abc_FlowRetime_Dfs_back( pObj, vNodes );
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanout( pObj, pNext, j )
+ {
+ l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0);
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < l )
+ pObj->Level = l;
+ }
+
+ if ( Abc_ObjIsBo(pObj) )
+ pObj->fMarkA = 1;
+
+ assert(pObj->Level <= pManMR->maxDelay);
+ }
+
+ // collect TFO of latches
+ // seed arrival times from BIs
+ Vec_PtrClear(vNodes);
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch(pNtk, pObj, i) {
+ pBo = Abc_ObjFanout0( pObj );
+ pBi = Abc_ObjFanin0( pObj );
+
+ Abc_NodeSetTravIdCurrent( pObj );
+ Abc_FlowRetime_Dfs_back( pBi, vNodes );
+
+ if (pBo->fMarkA) {
+ pBo->fMarkA = 0;
+ pObj->Level = pBo->Level;
+ assert(pObj->Level <= pManMR->maxDelay);
+ } else
+ pObj->Level = 0;
+ }
+
+#if defined(DEBUG_CHECK)
+ // DEBUG: check DFS ordering
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->fMarkB = 1;
+
+ Abc_ObjForEachFanout( pObj, pNext, j )
+ if ( Abc_NodeIsTravIdCurrent(pNext) && !Abc_ObjIsLatch(pNext))
+ assert(pNext->fMarkB);
+ }
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i)
+ pObj->fMarkB = 0;
+#endif
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanout( pObj, pNext, j )
+ {
+ l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0);
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < l )
+ pObj->Level = l;
+ }
+
+ if (pObj->Level + (Abc_ObjIsNode(pObj)?1:0) > pManMR->maxDelay) {
+ FSET(pObj, BLOCK);
+ }
+ }
+
+ // 2. conservative constraints
+
+ // first pass: seed latches with T=0
+ Abc_NtkForEachLatch(pNtk, pObj, i) {
+ pObj->Level = 0;
+ }
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanout( pObj, pNext, j ) {
+ l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0);
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < l )
+ pObj->Level = l;
+ }
+
+ if ( Abc_ObjIsBo(pObj) ) {
+ pObj->fMarkA = 1;
+ }
+
+ assert(pObj->Level <= pManMR->maxDelay);
+ }
+
+ Abc_NtkForEachLatch(pNtk, pObj, i) {
+ pBo = Abc_ObjFanout0( pObj );
+ assert(Abc_ObjIsBo(pBo));
+ pBi = Abc_ObjFanin0( pObj );
+ assert(Abc_ObjIsBi(pBi));
+
+ if (pBo->fMarkA) {
+ pBo->fMarkA = 0;
+ pObj->Level = pBo->Level;
+ } else
+ pObj->Level = 0;
+ }
+
+ // ... propagate values
+ Vec_PtrForEachEntryReverse(vNodes, pObj, i) {
+ pObj->Level = 0;
+ Abc_ObjForEachFanout( pObj, pNext, j ) {
+ l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0);
+ if ( Abc_NodeIsTravIdCurrent(pNext) &&
+ pObj->Level < l )
+ pObj->Level = l;
+ }
+
+ // constrained?
+ if (pObj->Level > pManMR->maxDelay) {
+ FSET( pObj, CONSERVATIVE );
+ pManMR->nConservConstraints++;
+ } else
+ FUNSET( pObj, CONSERVATIVE );
+ }
+
+ Vec_PtrClear( vNodes );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Introduces exact timing constraints for a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_ConstrainExact( Abc_Obj_t * pObj ) {
+
+ if (FTEST( pObj, CONSERVATIVE )) {
+ pManMR->nConservConstraints--;
+ FUNSET( pObj, CONSERVATIVE );
+ }
+
+#if !defined(IGNORE_TIMING)
+ if (pManMR->fIsForward) {
+ Abc_FlowRetime_ConstrainExact_forw(pObj);
+ } else {
+ Abc_FlowRetime_ConstrainExact_back(pObj);
+ }
+#endif
+}
+
+void Abc_FlowRetime_ConstrainExact_forw_rec( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes, int latch ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ // terminate?
+ if (Abc_ObjIsLatch(pObj)) {
+ if (latch) return;
+ latch = 1;
+ }
+
+ // already visited?
+ if (!latch) {
+ if (pObj->fMarkA) return;
+ pObj->fMarkA = 1;
+ } else {
+ if (pObj->fMarkB) return;
+ pObj->fMarkB = 1;
+ }
+
+ // recurse
+ Abc_ObjForEachFanin(pObj, pNext, i) {
+ Abc_FlowRetime_ConstrainExact_forw_rec( pNext, vNodes, latch );
+ }
+
+ // add
+ pObj->Level = 0;
+ Vec_PtrPush(vNodes, Abc_ObjNotCond(pObj, latch));
+}
+
+void Abc_FlowRetime_ConstrainExact_forw( Abc_Obj_t * pObj ) {
+ Vec_Ptr_t *vNodes = pManMR->vNodes;
+ Abc_Obj_t *pNext, *pCur, *pReg;
+ // Abc_Ntk_t *pNtk = pManMR->pNtk;
+ int i, j;
+
+ assert( !Vec_PtrSize(vNodes) );
+ assert( !Abc_ObjIsLatch(pObj) );
+ assert( !Vec_PtrSize( FTIMEEDGES(pObj) ));
+ Vec_PtrPush( pManMR->vExactNodes, pObj );
+
+ // rev topo order
+ Abc_FlowRetime_ConstrainExact_forw_rec( pObj, vNodes, 0 );
+
+ Vec_PtrForEachEntryReverse( vNodes, pCur, i) {
+ pReg = Abc_ObjRegular( pCur );
+
+ if (pReg == pCur) {
+ assert(!Abc_ObjIsLatch(pReg));
+ Abc_ObjForEachFanin(pReg, pNext, j)
+ pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0));
+ assert(pReg->Level <= pManMR->maxDelay);
+ pReg->Level = 0;
+ pReg->fMarkA = pReg->fMarkB = 0;
+ }
+ }
+ Vec_PtrForEachEntryReverse( vNodes, pCur, i) {
+ pReg = Abc_ObjRegular( pCur );
+ if (pReg != pCur) {
+ Abc_ObjForEachFanin(pReg, pNext, j)
+ if (!Abc_ObjIsLatch(pNext))
+ pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0));
+
+ if (pReg->Level == pManMR->maxDelay) {
+ Vec_PtrPush( FTIMEEDGES(pObj), pReg);
+ pManMR->nExactConstraints++;
+ }
+ pReg->Level = 0;
+ pReg->fMarkA = pReg->fMarkB = 0;
+ }
+ }
+
+ Vec_PtrClear( vNodes );
+}
+
+void Abc_FlowRetime_ConstrainExact_back_rec( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes, int latch ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ // terminate?
+ if (Abc_ObjIsLatch(pObj)) {
+ if (latch) return;
+ latch = 1;
+ }
+
+ // already visited?
+ if (!latch) {
+ if (pObj->fMarkA) return;
+ pObj->fMarkA = 1;
+ } else {
+ if (pObj->fMarkB) return;
+ pObj->fMarkB = 1;
+ }
+
+ // recurse
+ Abc_ObjForEachFanout(pObj, pNext, i) {
+ Abc_FlowRetime_ConstrainExact_back_rec( pNext, vNodes, latch );
+ }
+
+ // add
+ pObj->Level = 0;
+ Vec_PtrPush(vNodes, Abc_ObjNotCond(pObj, latch));
+}
+
+
+void Abc_FlowRetime_ConstrainExact_back( Abc_Obj_t * pObj ) {
+ Vec_Ptr_t *vNodes = pManMR->vNodes;
+ Abc_Obj_t *pNext, *pCur, *pReg;
+ // Abc_Ntk_t *pNtk = pManMR->pNtk;
+ int i, j;
+
+ assert( !Vec_PtrSize( vNodes ));
+ assert( !Abc_ObjIsLatch(pObj) );
+ assert( !Vec_PtrSize( FTIMEEDGES(pObj) ));
+ Vec_PtrPush( pManMR->vExactNodes, pObj );
+
+ // rev topo order
+ Abc_FlowRetime_ConstrainExact_back_rec( pObj, vNodes, 0 );
+
+ Vec_PtrForEachEntryReverse( vNodes, pCur, i) {
+ pReg = Abc_ObjRegular( pCur );
+
+ if (pReg == pCur) {
+ assert(!Abc_ObjIsLatch(pReg));
+ Abc_ObjForEachFanout(pReg, pNext, j)
+ pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0));
+ assert(pReg->Level <= pManMR->maxDelay);
+ pReg->Level = 0;
+ pReg->fMarkA = pReg->fMarkB = 0;
+ }
+ }
+ Vec_PtrForEachEntryReverse( vNodes, pCur, i) {
+ pReg = Abc_ObjRegular( pCur );
+ if (pReg != pCur) {
+ Abc_ObjForEachFanout(pReg, pNext, j)
+ if (!Abc_ObjIsLatch(pNext))
+ pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0));
+
+ if (pReg->Level == pManMR->maxDelay) {
+ Vec_PtrPush( FTIMEEDGES(pObj), pReg);
+ pManMR->nExactConstraints++;
+ }
+ pReg->Level = 0;
+ pReg->fMarkA = pReg->fMarkB = 0;
+ }
+ }
+
+ Vec_PtrClear( vNodes );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Introduces all exact timing constraints in a network]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_ConstrainExactAll( Abc_Ntk_t * pNtk ) {
+ int i;
+ Abc_Obj_t *pObj;
+ void *pArray;
+
+ // free existing constraints
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Vec_PtrSize( FTIMEEDGES(pObj) )) {
+ pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) );
+ FREE( pArray );
+ }
+ pManMR->nExactConstraints = 0;
+
+ // generate all constraints
+ Abc_NtkForEachObj(pNtk, pObj, i)
+ if (!Abc_ObjIsLatch(pObj) && FTEST( pObj, CONSERVATIVE ) && !FTEST( pObj, BLOCK ))
+ if (!Vec_PtrSize( FTIMEEDGES( pObj ) ))
+ Abc_FlowRetime_ConstrainExact( pObj );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates exact constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_FreeTiming( Abc_Ntk_t *pNtk ) {
+ Abc_Obj_t *pObj;
+ void *pArray;
+
+ while( Vec_PtrSize( pManMR->vExactNodes )) {
+ pObj = Vec_PtrPop( pManMR->vExactNodes );
+
+ if ( Vec_PtrSize( FTIMEEDGES(pObj) )) {
+ pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) );
+ FREE( pArray );
+ }
+ }
+
+ Vec_PtrFree(pManMR->vExactNodes);
+ FREE( pManMR->vTimeEdges );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [DFS order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_FlowRetime_Dfs_forw( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ if (Abc_ObjIsLatch(pObj)) return;
+
+ Abc_NodeSetTravIdCurrent( pObj );
+
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if (!Abc_NodeIsTravIdCurrent( pNext ))
+ Abc_FlowRetime_Dfs_forw( pNext, vNodes );
+
+ Vec_PtrPush( vNodes, pObj );
+}
+
+
+void Abc_FlowRetime_Dfs_back( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ) {
+ Abc_Obj_t *pNext;
+ int i;
+
+ if (Abc_ObjIsLatch(pObj)) return;
+
+ Abc_NodeSetTravIdCurrent( pObj );
+
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if (!Abc_NodeIsTravIdCurrent( pNext ))
+ Abc_FlowRetime_Dfs_back( pNext, vNodes );
+
+ Vec_PtrPush( vNodes, pObj );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Main timing-constrained routine.]
+
+ Description [Refines constraints that are limiting area improvement.
+ These are identified by computing
+ the min-cuts both with and without the conservative
+ constraints: these two situation represent an
+ over- and under-constrained version of the timing.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+bool Abc_FlowRetime_RefineConstraints( ) {
+ Abc_Ntk_t *pNtk = pManMR->pNtk;
+ int i, flow, count = 0;
+ Abc_Obj_t *pObj;
+ int maxTighten = 99999;
+
+ vprintf("\t\tsubiter %d : constraints = {cons, exact} = %d, %d\n",
+ pManMR->subIteration, pManMR->nConservConstraints, pManMR->nExactConstraints);
+
+ // 1. overconstrained
+ pManMR->constraintMask = BLOCK | CONSERVATIVE;
+ vprintf("\t\trefinement: over ");
+ fflush(stdout);
+ flow = Abc_FlowRetime_PushFlows( pNtk, 0 );
+ vprintf("= %d ", flow);
+
+ // remember nodes
+ if (pManMR->fIsForward) {
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (!FTEST(pObj, VISITED_R))
+ pObj->fMarkC = 1;
+ } else {
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if (!FTEST(pObj, VISITED_E))
+ pObj->fMarkC = 1;
+ }
+
+ if (pManMR->fConservTimingOnly) {
+ vprintf(" done\n");
+ return 0;
+ }
+
+ // 2. underconstrained
+ pManMR->constraintMask = BLOCK;
+ Abc_FlowRetime_ClearFlows( 0 );
+ vprintf("under = ");
+ fflush(stdout);
+ flow = Abc_FlowRetime_PushFlows( pNtk, 0 );
+ vprintf("%d refined nodes = ", flow);
+ fflush(stdout);
+
+ // find area-limiting constraints
+ if (pManMR->fIsForward) {
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ if (pObj->fMarkC &&
+ FTEST(pObj, VISITED_R) &&
+ FTEST(pObj, CONSERVATIVE) &&
+ count < maxTighten) {
+ count++;
+ Abc_FlowRetime_ConstrainExact( pObj );
+ }
+ pObj->fMarkC = 0;
+ }
+ } else {
+ Abc_NtkForEachObj( pNtk, pObj, i ) {
+ if (pObj->fMarkC &&
+ FTEST(pObj, VISITED_E) &&
+ FTEST(pObj, CONSERVATIVE) &&
+ count < maxTighten) {
+ count++;
+ Abc_FlowRetime_ConstrainExact( pObj );
+ }
+ pObj->fMarkC = 0;
+ }
+ }
+
+ vprintf("%d\n", count);
+
+ return (count > 0);
+}
+
+
diff --git a/src/opt/fret/fretime.h b/src/opt/fret/fretime.h
new file mode 100644
index 00000000..167543ce
--- /dev/null
+++ b/src/opt/fret/fretime.h
@@ -0,0 +1,165 @@
+/**CFile****************************************************************
+
+ FileName [fretime.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Flow-based retiming package.]
+
+ Synopsis [Header file for retiming package.]
+
+ Author [Aaron Hurst]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2008.]
+
+ Revision [$Id: fretime.h,v 1.00 2008/01/01 00:00:00 ahurst Exp $]
+
+***********************************************************************/
+
+#if !defined(RETIME_H_)
+#define RETIME_H_
+
+#include "abc.h"
+
+// #define IGNORE_TIMING
+// #define DEBUG_PRINT_FLOWS
+// #define DEBUG_VISITED
+// #define DEBUG_PREORDER
+// #define DEBUG_CHECK
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define MAX_DIST 30000
+
+// flags in Flow_Data structure...
+#define VISITED_E 0x01
+#define VISITED_R 0x02
+#define VISITED (VISITED_E | VISITED_R)
+#define FLOW 0x04
+#define CROSS_BOUNDARY 0x08
+#define BLOCK 0x10
+#define INIT_0 0x20
+#define INIT_1 0x40
+#define INIT_CARE (INIT_0 | INIT_1)
+#define CONSERVATIVE 0x80
+#define BLOCK_OR_CONS (BLOCK | CONSERVATIVE)
+
+typedef struct Flow_Data_t_ {
+ unsigned int mark : 16;
+
+ union {
+ Abc_Obj_t *pred;
+ /* unsigned int var; */
+ Abc_Obj_t *pInitObj;
+ Vec_Ptr_t *vNodes;
+ };
+
+ unsigned int e_dist : 16;
+ unsigned int r_dist : 16;
+} Flow_Data_t;
+
+// useful macros for manipulating Flow_Data structure...
+#define FDATA( x ) ((Flow_Data_t *)Abc_ObjCopy(x))
+#define FSET( x, y ) ((Flow_Data_t *)Abc_ObjCopy(x))->mark |= y
+#define FUNSET( x, y ) ((Flow_Data_t *)Abc_ObjCopy(x))->mark &= ~y
+#define FTEST( x, y ) (((Flow_Data_t *)Abc_ObjCopy(x))->mark & y)
+#define FTIMEEDGES( x ) &(pManMR->vTimeEdges[Abc_ObjId( x )])
+
+static inline void FSETPRED(Abc_Obj_t *pObj, Abc_Obj_t *pPred) {
+ assert(!Abc_ObjIsLatch(pObj)); // must preserve field to maintain init state linkage
+ FDATA(pObj)->pred = pPred;
+}
+static inline Abc_Obj_t * FGETPRED(Abc_Obj_t *pObj) {
+ return FDATA(pObj)->pred;
+}
+
+
+typedef struct MinRegMan_t_ {
+
+ // problem description:
+ int maxDelay;
+ bool fComputeInitState, fGuaranteeInitState;
+ int nNodes, nLatches;
+ bool fForwardOnly, fBackwardOnly;
+ bool fConservTimingOnly;
+ int nMaxIters;
+ bool fVerbose;
+ Abc_Ntk_t *pNtk;
+
+ int nPreRefine;
+
+ // problem state
+ bool fIsForward;
+ bool fSinkDistTerminate;
+ int nExactConstraints, nConservConstraints;
+ int fSolutionIsDc;
+ int constraintMask;
+ int iteration, subIteration;
+
+ // problem data
+ Vec_Int_t *vSinkDistHist;
+ Flow_Data_t *pDataArray;
+ Vec_Ptr_t *vTimeEdges;
+ Vec_Ptr_t *vExactNodes;
+ Abc_Ntk_t *pInitNtk;
+ Vec_Ptr_t *vNodes; // re-useable struct
+
+} MinRegMan_t ;
+
+#define vprintf if (pManMR->fVerbose) printf
+
+/*=== fretMain.c ==========================================================*/
+
+extern MinRegMan_t *pManMR;
+
+Abc_Ntk_t * Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState,
+ int fForward, int fBackward, int nMaxIters,
+ int maxDelay, int fFastButConservative);
+
+void print_node(Abc_Obj_t *pObj);
+
+void Abc_ObjBetterTransferFanout( Abc_Obj_t * pFrom, Abc_Obj_t * pTo, int compl );
+
+int Abc_FlowRetime_PushFlows( Abc_Ntk_t * pNtk, bool fVerbose );
+bool Abc_FlowRetime_IsAcrossCut( Abc_Obj_t *pCur, Abc_Obj_t *pNext );
+void Abc_FlowRetime_ClearFlows( bool fClearAll );
+
+/*=== fretFlow.c ==========================================================*/
+
+int dfsplain_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred );
+int dfsplain_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred );
+
+void dfsfast_preorder( Abc_Ntk_t *pNtk );
+int dfsfast_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred );
+int dfsfast_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred );
+
+/*=== fretInit.c ==========================================================*/
+
+void Abc_FlowRetime_PrintInitStateInfo( Abc_Ntk_t * pNtk );
+
+void Abc_FlowRetime_InitState( Abc_Ntk_t * pNtk );
+
+void Abc_FlowRetime_UpdateForwardInit( Abc_Ntk_t * pNtk );
+void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk );
+
+void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk );
+int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk );
+
+void Abc_FlowRetime_ConstrainInit( );
+
+/*=== fretTime.c ==========================================================*/
+
+void Abc_FlowRetime_InitTiming( Abc_Ntk_t *pNtk );
+void Abc_FlowRetime_FreeTiming( Abc_Ntk_t *pNtk );
+
+bool Abc_FlowRetime_RefineConstraints( );
+
+void Abc_FlowRetime_ConstrainConserv( Abc_Ntk_t * pNtk );
+void Abc_FlowRetime_ConstrainExact( Abc_Obj_t * pObj );
+void Abc_FlowRetime_ConstrainExactAll( Abc_Ntk_t * pNtk );
+
+#endif
diff --git a/src/opt/fret/module.make b/src/opt/fret/module.make
new file mode 100644
index 00000000..fda6a73d
--- /dev/null
+++ b/src/opt/fret/module.make
@@ -0,0 +1,5 @@
+SRC += src/opt/fret/fretMain.c \
+ src/opt/fret/fretFlow.c \
+ src/opt/fret/fretInit.c \
+ src/opt/fret/fretTime.c
+
diff --git a/src/opt/fxu/fxu.c b/src/opt/fxu/fxu.c
index 46f7ca1a..d11fd793 100644
--- a/src/opt/fxu/fxu.c
+++ b/src/opt/fxu/fxu.c
@@ -17,7 +17,6 @@
***********************************************************************/
#include "fxuInt.h"
-//#include "mvc.h"
#include "fxu.h"
////////////////////////////////////////////////////////////////////////
@@ -32,7 +31,7 @@ static int s_MemoryTotal;
static int s_MemoryPeak;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -59,6 +58,7 @@ int Fxu_FastExtract( Fxu_Data_t * pData )
Fxu_Single * pSingle;
Fxu_Double * pDouble;
int Weight1, Weight2, Weight3;
+ int Counter = 0;
s_MemoryTotal = 0;
s_MemoryPeak = 0;
@@ -78,7 +78,7 @@ int Fxu_FastExtract( Fxu_Data_t * pData )
{
Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle );
if ( pData->fVerbose )
- printf( "Best single = %3d.\n", Weight1 );
+ printf( "Div %5d : Best single = %5d.\r", Counter++, Weight1 );
if ( Weight1 > 0 || Weight1 == 0 && pData->fUse0 )
Fxu_UpdateSingle( p );
else
@@ -93,7 +93,7 @@ int Fxu_FastExtract( Fxu_Data_t * pData )
{
Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble );
if ( pData->fVerbose )
- printf( "Best double = %3d.\n", Weight2 );
+ printf( "Div %5d : Best double = %5d.\r", Counter++, Weight2 );
if ( Weight2 > 0 || Weight2 == 0 && pData->fUse0 )
Fxu_UpdateDouble( p );
else
@@ -110,7 +110,7 @@ int Fxu_FastExtract( Fxu_Data_t * pData )
Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble );
if ( pData->fVerbose )
- printf( "Best double = %3d. Best single = %3d.\n", Weight2, Weight1 );
+ printf( "Div %5d : Best double = %5d. Best single = %5d.\r", Counter++, Weight2, Weight1 );
//Fxu_Select( p, &pSingle, &pDouble );
if ( Weight1 >= Weight2 )
@@ -141,8 +141,8 @@ int Fxu_FastExtract( Fxu_Data_t * pData )
// select the best single and double
Weight3 = Fxu_Select( p, &pSingle, &pDouble );
if ( pData->fVerbose )
- printf( "Best double = %3d. Best single = %3d. Best complement = %3d.\n",
- Weight2, Weight1, Weight3 );
+ printf( "Div %5d : Best double = %5d. Best single = %5d. Best complement = %5d.\r",
+ Counter++, Weight2, Weight1, Weight3 );
if ( Weight3 > 0 || Weight3 == 0 && pData->fUse0 )
Fxu_Update( p, pSingle, pDouble );
@@ -153,13 +153,14 @@ int Fxu_FastExtract( Fxu_Data_t * pData )
}
if ( pData->fVerbose )
- printf( "Total single = %3d. Total double = %3d. Total compl = %3d.\n", p->nDivs1, p->nDivs2, p->nDivs3 );
+ printf( "Total single = %3d. Total double = %3d. Total compl = %3d. \n",
+ p->nDivs1, p->nDivs2, p->nDivs3 );
// create the new covers
if ( pData->nNodesNew )
Fxu_CreateCovers( p, pData );
Fxu_MatrixDelete( p );
-// printf( "Memory usage after delocation: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak );
+// printf( "Memory usage after deallocation: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak );
if ( pData->nNodesNew == pData->nNodesExt )
printf( "Warning: The limit on the number of extracted divisors has been reached.\n" );
return pData->nNodesNew;
diff --git a/src/opt/fxu/fxu.h b/src/opt/fxu/fxu.h
index e9f63ea3..e6d0b69e 100644
--- a/src/opt/fxu/fxu.h
+++ b/src/opt/fxu/fxu.h
@@ -19,6 +19,10 @@
#ifndef __FXU_H__
#define __FXU_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -33,9 +37,11 @@
/// STRUCTURE DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
+#ifndef __cplusplus
#ifndef bool
#define bool int
#endif
+#endif
typedef struct FxuDataStruct Fxu_Data_t;
@@ -49,7 +55,8 @@ struct FxuDataStruct
bool fUseCompl; // set to 1 to have complement taken into account
bool fVerbose; // set to 1 to have verbose output
int nNodesExt; // the number of divisors to extract
- int nPairsMax; // the maximum number of cube pairs to consider
+ int nSingleMax; // the max number of single-cube divisors to consider
+ int nPairsMax; // the max number of double-cube divisors to consider
// the input information
Vec_Ptr_t * vSops; // the SOPs for each node in the network
Vec_Ptr_t * vFanins; // the fanins of each node in the network
@@ -64,19 +71,23 @@ struct FxuDataStruct
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*===== fxu.c ==========================================================*/
extern int Fxu_FastExtract( Fxu_Data_t * pData );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/fxu/fxuCreate.c b/src/opt/fxu/fxuCreate.c
index b061f53d..55026b27 100644
--- a/src/opt/fxu/fxuCreate.c
+++ b/src/opt/fxu/fxuCreate.c
@@ -24,16 +24,16 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Fan_t * vFanins, int * pOrder );
+static void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder );
static int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY );
static void Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext );
static Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode );
-static Abc_Fan_t * s_pLits;
+static int * s_pLits;
extern int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -53,7 +53,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
Fxu_Var * pVar;
Fxu_Cube * pCubeFirst, * pCubeNew;
Fxu_Cube * pCube1, * pCube2;
- Vec_Fan_t * vFanins;
+ Vec_Int_t * vFanins;
char * pSopCover;
char * pSopCube;
int * pOrder, nBitsMax;
@@ -69,7 +69,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
nCubesTotal = 0;
nPairsTotal = 0;
nPairsStore = 0;
- nBitsMax = -1;
+ nBitsMax = -1;
for ( i = 0; i < pData->nNodesOld; i++ )
if ( pSopCover = pData->vSops->pArray[i] )
{
@@ -89,7 +89,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
return NULL;
}
- if ( nPairsStore > 10000000 )
+ if ( nPairsStore > 50000000 )
{
printf( "The problem is too large to be solved by \"fxu\" (%d cubes and %d cube pairs)\n", nCubesTotal, nPairsStore );
return NULL;
@@ -151,7 +151,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
pOrder[v] = v;
// reorder the fanins
qsort( (void *)pOrder, nFanins, sizeof(int),(int (*)(const void *, const void *))Fxu_CreateMatrixLitCompare);
- assert( s_pLits[ pOrder[0] ].iFan < s_pLits[ pOrder[nFanins-1] ].iFan );
+ assert( s_pLits[ pOrder[0] ] < s_pLits[ pOrder[nFanins-1] ] );
// create the corresponding cubes in the matrix
pCubeFirst = NULL;
c = 0;
@@ -178,11 +178,26 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
// consider the case when cube pairs should be preprocessed
// before adding them to the set of divisors
+// if ( pData->fVerbose )
+// printf( "The total number of cube pairs is %d.\n", nPairsTotal );
+ if ( nPairsTotal > 10000000 )
+ {
+ printf( "The total number of cube pairs of the network is more than 10,000,000.\n" );
+ printf( "Command \"fx\" takes a long time to run in such cases. It is suggested\n" );
+ printf( "that the user changes the network by reducing the size of logic node and\n" );
+ printf( "consequently the number of cube pairs to be processed by this command.\n" );
+ printf( "One way to achieve this is to run the commands \"st; multi -m -F <num>\"\n" );
+ printf( "as a proprocessing step, while selecting <num> as approapriate.\n" );
+ return NULL;
+ }
if ( nPairsTotal > pData->nPairsMax )
- Fxu_PreprocessCubePairs( p, pData->vSops, nPairsTotal, pData->nPairsMax );
+ if ( !Fxu_PreprocessCubePairs( p, pData->vSops, nPairsTotal, pData->nPairsMax ) )
+ return NULL;
+// if ( pData->fVerbose )
+// printf( "Only %d best cube pairs will be used by the fast extract command.\n", pData->nPairsMax );
// add the var pairs to the heap
- Fxu_MatrixComputeSingles( p );
+ Fxu_MatrixComputeSingles( p, pData->fUse0, pData->nSingleMax );
// print stats
if ( pData->fVerbose )
@@ -193,9 +208,8 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
p->lVars.nItems, p->lCubes.nItems );
fprintf( stdout, "Lits = %d Density = %.5f%%\n",
p->nEntries, Density );
- fprintf( stdout, "1-cube divisors = %6d. ", p->lSingles.nItems );
- fprintf( stdout, "2-cube divisors = %6d. ", p->nDivsTotal );
- fprintf( stdout, "Cube pairs = %6d.", nPairsTotal );
+ fprintf( stdout, "1-cube divs = %6d. (Total = %6d) ", p->lSingles.nItems, p->nSingleTotal );
+ fprintf( stdout, "2-cube divs = %6d. (Total = %6d)", p->nDivsTotal, nPairsTotal );
fprintf( stdout, "\n" );
}
// Fxu_MatrixPrint( stdout, p );
@@ -214,7 +228,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
SeeAlso []
***********************************************************************/
-void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Fan_t * vFanins, int * pOrder )
+void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder )
{
Fxu_Var * pVar;
int Value, i;
@@ -224,12 +238,12 @@ void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube,
Value = pSopCube[pOrder[i]];
if ( Value == '0' )
{
- pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]].iFan + 1 ]; // CST
+ pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] + 1 ]; // CST
Fxu_MatrixAddLiteral( p, pCube, pVar );
}
else if ( Value == '1' )
{
- pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]].iFan ]; // CST
+ pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] ]; // CST
Fxu_MatrixAddLiteral( p, pCube, pVar );
}
}
@@ -409,7 +423,7 @@ Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iV
***********************************************************************/
int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY )
{
- return s_pLits[*ptrX].iFan - s_pLits[*ptrY].iFan;
+ return s_pLits[*ptrX] - s_pLits[*ptrY];
}
////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/fxu/fxuHeapD.c b/src/opt/fxu/fxuHeapD.c
index 7c123249..c81ad818 100644
--- a/src/opt/fxu/fxuHeapD.c
+++ b/src/opt/fxu/fxuHeapD.c
@@ -38,7 +38,7 @@ static void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv );
static void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/fxu/fxuHeapS.c b/src/opt/fxu/fxuHeapS.c
index dbd66055..eaca8363 100644
--- a/src/opt/fxu/fxuHeapS.c
+++ b/src/opt/fxu/fxuHeapS.c
@@ -38,7 +38,7 @@ static void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle );
static void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/fxu/fxuInt.h b/src/opt/fxu/fxuInt.h
index 59b2df6d..ea85cb79 100644
--- a/src/opt/fxu/fxuInt.h
+++ b/src/opt/fxu/fxuInt.h
@@ -23,7 +23,6 @@
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
-#include "util.h"
#include "extra.h"
#include "vec.h"
@@ -173,6 +172,8 @@ struct FxuMatrix // ~ 30 words
// the single cube divisors
Fxu_ListSingle lSingles; // the linked list of single cube divisors
Fxu_HeapSingle * pHeapSingle; // the heap of variables by the number of literals in the matrix
+ int nWeightLimit;// the limit on weight of single cube divisors collected
+ int nSingleTotal;// the total number of single cube divisors
// storage for cube pairs
Fxu_Pair *** pppPairs;
Fxu_Pair ** ppPairs;
@@ -272,7 +273,7 @@ struct FxuSingle // 7 words
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// minimum/maximum
@@ -430,7 +431,7 @@ extern void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p );
#endif
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*===== fxu.c ====================================================*/
@@ -460,7 +461,7 @@ extern void Fxu_PairClearStorage( Fxu_Cube * pCube );
extern Fxu_Pair * Fxu_PairAlloc( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 );
extern void Fxu_PairAdd( Fxu_Pair * pPair );
/*===== fxuSingle.c ====================================================*/
-extern void Fxu_MatrixComputeSingles( Fxu_Matrix * p );
+extern void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax );
extern void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar );
extern int Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 );
/*===== fxuMatrix.c ====================================================*/
@@ -530,8 +531,9 @@ extern int Fxu_HeapSingleReadMaxWeight( Fxu_HeapSingle * p );
extern Fxu_Single * Fxu_HeapSingleReadMax( Fxu_HeapSingle * p );
extern Fxu_Single * Fxu_HeapSingleGetMax( Fxu_HeapSingle * p );
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
diff --git a/src/opt/fxu/fxuList.c b/src/opt/fxu/fxuList.c
index bb081d80..52995804 100644
--- a/src/opt/fxu/fxuList.c
+++ b/src/opt/fxu/fxuList.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// matrix -> var
diff --git a/src/opt/fxu/fxuMatrix.c b/src/opt/fxu/fxuMatrix.c
index 503ba2f1..93ec7b90 100644
--- a/src/opt/fxu/fxuMatrix.c
+++ b/src/opt/fxu/fxuMatrix.c
@@ -25,7 +25,7 @@
extern unsigned int Cudd_Prime( unsigned int p );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -130,7 +130,7 @@ void Fxu_MatrixDelete( Fxu_Matrix * p )
MEM_FREE_FXU( p, Fxu_Var, 1, pVar );
}
#else
- Extra_MmFixedStop( p->pMemMan, 0 );
+ Extra_MmFixedStop( p->pMemMan );
#endif
Vec_PtrFree( p->vPairs );
diff --git a/src/opt/fxu/fxuPair.c b/src/opt/fxu/fxuPair.c
index be6be5e9..3c031ce8 100644
--- a/src/opt/fxu/fxuPair.c
+++ b/src/opt/fxu/fxuPair.c
@@ -55,7 +55,7 @@ static s_Primes[MAX_PRIMES] =
};
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/fxu/fxuPrint.c b/src/opt/fxu/fxuPrint.c
index 2d25c0e9..232b109a 100644
--- a/src/opt/fxu/fxuPrint.c
+++ b/src/opt/fxu/fxuPrint.c
@@ -23,7 +23,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/fxu/fxuReduce.c b/src/opt/fxu/fxuReduce.c
index 652d807b..0ab8a157 100644
--- a/src/opt/fxu/fxuReduce.c
+++ b/src/opt/fxu/fxuReduce.c
@@ -27,7 +27,7 @@
static int Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -90,6 +90,16 @@ int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTota
pnPairCounters[ pnLitsDiff[k] ]++;
// determine what pairs to take starting from the lower
// so that there would be exactly pPairsMax pairs
+ if ( pnPairCounters[0] != 0 )
+ {
+ printf( "The SOPs of the nodes are not cube-free. Run \"bdd; sop\" before \"fx\".\n" );
+ return 0;
+ }
+ if ( pnPairCounters[1] != 0 )
+ {
+ printf( "The SOPs of the nodes are not SCC-free. Run \"bdd; sop\" before \"fx\".\n" );
+ return 0;
+ }
assert( pnPairCounters[0] == 0 ); // otherwise, covers are not dup-free
assert( pnPairCounters[1] == 0 ); // otherwise, covers are not SCC-free
nSum = 0;
diff --git a/src/opt/fxu/fxuSelect.c b/src/opt/fxu/fxuSelect.c
index b56407a9..b9265487 100644
--- a/src/opt/fxu/fxuSelect.c
+++ b/src/opt/fxu/fxuSelect.c
@@ -37,7 +37,7 @@ void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble,
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/fxu/fxuSingle.c b/src/opt/fxu/fxuSingle.c
index 5af5c341..73d9a76c 100644
--- a/src/opt/fxu/fxuSingle.c
+++ b/src/opt/fxu/fxuSingle.c
@@ -17,13 +17,16 @@
***********************************************************************/
#include "fxuInt.h"
+#include "vec.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
+static void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles );
+
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -38,12 +41,130 @@
SeeAlso []
***********************************************************************/
-void Fxu_MatrixComputeSingles( Fxu_Matrix * p )
+void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax )
{
Fxu_Var * pVar;
- // iterate through the columns in the matrix
+ Vec_Ptr_t * vSingles;
+ int i, k;
+ // set the weight limit
+ p->nWeightLimit = 1 - fUse0;
+ // iterate through columns in the matrix and collect single-cube divisors
+ vSingles = Vec_PtrAlloc( 10000 );
Fxu_MatrixForEachVariable( p, pVar )
- Fxu_MatrixComputeSinglesOne( p, pVar );
+ Fxu_MatrixComputeSinglesOneCollect( p, pVar, vSingles );
+ p->nSingleTotal = Vec_PtrSize(vSingles) / 3;
+ // check if divisors should be filtered
+ if ( Vec_PtrSize(vSingles) > nSingleMax )
+ {
+ int * pWeigtCounts, nDivCount, Weight, i, c;;
+ assert( Vec_PtrSize(vSingles) % 3 == 0 );
+ // count how many divisors have the given weight
+ pWeigtCounts = ALLOC( int, 1000 );
+ memset( pWeigtCounts, 0, sizeof(int) * 1000 );
+ for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 )
+ {
+ Weight = (int)Vec_PtrEntry(vSingles, i);
+ if ( Weight >= 999 )
+ pWeigtCounts[999]++;
+ else
+ pWeigtCounts[Weight]++;
+ }
+ // select the bound on the weight (above this bound, singles will be included)
+ nDivCount = 0;
+ for ( c = 999; c >= 0; c-- )
+ {
+ nDivCount += pWeigtCounts[c];
+ if ( nDivCount >= nSingleMax )
+ break;
+ }
+ free( pWeigtCounts );
+ // collect singles with the given costs
+ k = 0;
+ for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 )
+ {
+ Weight = (int)Vec_PtrEntry(vSingles, i);
+ if ( Weight < c )
+ continue;
+ Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-2) );
+ Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-1) );
+ Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i) );
+ if ( k/3 == nSingleMax )
+ break;
+ }
+ Vec_PtrShrink( vSingles, k );
+ // adjust the weight limit
+ p->nWeightLimit = c;
+ }
+ // collect the selected divisors
+ assert( Vec_PtrSize(vSingles) % 3 == 0 );
+ for ( i = 0; i < Vec_PtrSize(vSingles); i += 3 )
+ {
+ Fxu_MatrixAddSingle( p,
+ Vec_PtrEntry(vSingles,i),
+ Vec_PtrEntry(vSingles,i+1),
+ (int)Vec_PtrEntry(vSingles,i+2) );
+ }
+ Vec_PtrFree( vSingles );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds the single-cube divisors associated with a new column.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles )
+{
+ Fxu_Lit * pLitV, * pLitH;
+ Fxu_Var * pVar2;
+ int Coin;
+ int WeightCur;
+
+ // start collecting the affected vars
+ Fxu_MatrixRingVarsStart( p );
+ // go through all the literals of this variable
+ for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext )
+ // for this literal, go through all the horizontal literals
+ for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev )
+ {
+ // get another variable
+ pVar2 = pLitH->pVar;
+ // skip the var if it is already used
+ if ( pVar2->pOrder )
+ continue;
+ // skip the var if it belongs to the same node
+// if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] )
+// continue;
+ // collect the var
+ Fxu_MatrixRingVarsAdd( p, pVar2 );
+ }
+ // stop collecting the selected vars
+ Fxu_MatrixRingVarsStop( p );
+
+ // iterate through the selected vars
+ Fxu_MatrixForEachVarInRing( p, pVar2 )
+ {
+ // count the coincidence
+ Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar );
+ assert( Coin > 0 );
+ // get the new weight
+ WeightCur = Coin - 2;
+ // peformance fix (August 24, 2007)
+ if ( WeightCur >= p->nWeightLimit )
+ {
+ Vec_PtrPush( vSingles, pVar2 );
+ Vec_PtrPush( vSingles, pVar );
+ Vec_PtrPush( vSingles, (void *)WeightCur );
+ }
+ }
+
+ // unmark the vars
+ Fxu_MatrixRingVarsUnmark( p );
}
/**Function*************************************************************
@@ -59,12 +180,9 @@ void Fxu_MatrixComputeSingles( Fxu_Matrix * p )
***********************************************************************/
void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar )
{
-// int * pValue2Node = p->pValue2Node;
Fxu_Lit * pLitV, * pLitH;
Fxu_Var * pVar2;
int Coin;
-// int CounterAll;
-// int CounterTest;
int WeightCur;
// start collecting the affected vars
@@ -76,7 +194,6 @@ void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar )
{
// get another variable
pVar2 = pLitH->pVar;
-// CounterAll++;
// skip the var if it is already used
if ( pVar2->pOrder )
continue;
@@ -92,16 +209,17 @@ void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar )
// iterate through the selected vars
Fxu_MatrixForEachVarInRing( p, pVar2 )
{
-// CounterTest++;
// count the coincidence
Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar );
assert( Coin > 0 );
// get the new weight
WeightCur = Coin - 2;
- if ( WeightCur >= 0 )
+ // peformance fix (August 24, 2007)
+// if ( WeightCur >= 0 )
+// Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur );
+ if ( WeightCur >= p->nWeightLimit )
Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur );
}
-
// unmark the vars
Fxu_MatrixRingVarsUnmark( p );
}
diff --git a/src/opt/fxu/fxuUpdate.c b/src/opt/fxu/fxuUpdate.c
index 4006bc76..274f79f6 100644
--- a/src/opt/fxu/fxuUpdate.c
+++ b/src/opt/fxu/fxuUpdate.c
@@ -37,7 +37,7 @@ static void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p );
static void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -757,12 +757,14 @@ void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p )
{
Fxu_Single * pSingle, * pSingle2;
int WeightNew;
+ int Counter = 0;
Fxu_MatrixForEachSingleSafe( p, pSingle, pSingle2 )
{
// if at least one of the variables is marked, recalculate
if ( pSingle->pVar1->pOrder || pSingle->pVar2->pOrder )
{
+ Counter++;
// get the new weight
WeightNew = -2 + Fxu_SingleCountCoincidence( p, pSingle->pVar1, pSingle->pVar2 );
if ( WeightNew >= 0 )
@@ -778,6 +780,7 @@ void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p )
}
}
}
+// printf( "Called procedure %d times.\n", Counter );
}
/**Function*************************************************************
diff --git a/src/opt/lpk/lpk.h b/src/opt/lpk/lpk.h
new file mode 100644
index 00000000..2a642db2
--- /dev/null
+++ b/src/opt/lpk/lpk.h
@@ -0,0 +1,84 @@
+/**CFile****************************************************************
+
+ FileName [lpk.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpk.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __LPK_H__
+#define __LPK_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Lpk_Par_t_ Lpk_Par_t;
+struct Lpk_Par_t_
+{
+ // user-controlled parameters
+ int nLutsMax; // (N) the maximum number of LUTs in the structure
+ int nLutsOver; // (Q) the maximum number of LUTs not in the MFFC
+ int nVarsShared; // (S) the maximum number of shared variables (crossbars)
+ int nGrowthLevel; // (L) the maximum increase in the node level after resynthesis
+ int fSatur; // iterate till saturation
+ int fZeroCost; // accept zero-cost replacements
+ int fFirst; // use root node and first cut only
+ int fOldAlgo; // use old algorithm
+ int fVerbose; // the verbosiness flag
+ int fVeryVerbose; // additional verbose info printout
+ // internal parameters
+ int nLutSize; // (K) the LUT size (determined by the input network)
+ int nVarsMax; // (V) the largest number of variables: V = N * (K-1) + 1
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== lpkCore.c ========================================================*/
+extern int Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/opt/lpk/lpkAbcDec.c b/src/opt/lpk/lpkAbcDec.c
new file mode 100644
index 00000000..aa2d4bc0
--- /dev/null
+++ b/src/opt/lpk/lpkAbcDec.c
@@ -0,0 +1,290 @@
+/**CFile****************************************************************
+
+ FileName [lpkAbcDec.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis [The new core procedure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkAbcDec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Implements the function.]
+
+ Description [Returns the node implementing this function.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Lpk_ImplementFun( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * p )
+{
+ extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
+ unsigned * pTruth;
+ Abc_Obj_t * pObjNew;
+ int i;
+ if ( p->fMark )
+ pMan->nMuxes++;
+ else
+ pMan->nDsds++;
+ // create the new node
+ pObjNew = Abc_NtkCreateNode( pNtk );
+ for ( i = 0; i < (int)p->nVars; i++ )
+ Abc_ObjAddFanin( pObjNew, Abc_ObjRegular(Vec_PtrEntry(vLeaves, p->pFanins[i])) );
+ Abc_ObjSetLevel( pObjNew, Abc_ObjLevelNew(pObjNew) );
+ // assign the node's function
+ pTruth = Lpk_FunTruth(p, 0);
+ if ( p->nVars == 0 )
+ {
+ pObjNew->pData = Hop_NotCond( Hop_ManConst1(pNtk->pManFunc), !(pTruth[0] & 1) );
+ return pObjNew;
+ }
+ if ( p->nVars == 1 )
+ {
+ pObjNew->pData = Hop_NotCond( Hop_ManPi(pNtk->pManFunc, 0), (pTruth[0] & 1) );
+ return pObjNew;
+ }
+ // create the logic function
+ pObjNew->pData = Kit_TruthToHop( pNtk->pManFunc, pTruth, p->nVars, NULL );
+ return pObjNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements the function.]
+
+ Description [Returns the node implementing this function.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Lpk_Implement_rec( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * pFun )
+{
+ Abc_Obj_t * pFanin, * pRes;
+ int i;
+ // prepare the leaves of the function
+ for ( i = 0; i < (int)pFun->nVars; i++ )
+ {
+ pFanin = Vec_PtrEntry( vLeaves, pFun->pFanins[i] );
+ if ( !Abc_ObjIsComplement(pFanin) )
+ Lpk_Implement_rec( pMan, pNtk, vLeaves, (Lpk_Fun_t *)pFanin );
+ pFanin = Vec_PtrEntry( vLeaves, pFun->pFanins[i] );
+ assert( Abc_ObjIsComplement(pFanin) );
+ }
+ // construct the function
+ pRes = Lpk_ImplementFun( pMan, pNtk, vLeaves, pFun );
+ // replace the function
+ Vec_PtrWriteEntry( vLeaves, pFun->Id, Abc_ObjNot(pRes) );
+ Lpk_FunFree( pFun );
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements the function.]
+
+ Description [Returns the node implementing this function.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Lpk_Implement( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, int nLeavesOld )
+{
+ Abc_Obj_t * pFanin, * pRes;
+ int i;
+ assert( nLeavesOld < Vec_PtrSize(vLeaves) );
+ // mark implemented nodes
+ Vec_PtrForEachEntryStop( vLeaves, pFanin, i, nLeavesOld )
+ Vec_PtrWriteEntry( vLeaves, i, Abc_ObjNot(pFanin) );
+ // recursively construct starting from the first entry
+ pRes = Lpk_Implement_rec( pMan, pNtk, vLeaves, Vec_PtrEntry( vLeaves, nLeavesOld ) );
+ Vec_PtrShrink( vLeaves, nLeavesOld );
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Decomposes the function using recursive MUX decomposition.]
+
+ Description [Returns the ID of the top-most decomposition node
+ implementing this function, or 0 if there is no decomposition satisfying
+ the constraints on area and delay.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_Decompose_rec( Lpk_Man_t * pMan, Lpk_Fun_t * p )
+{
+ static Lpk_Res_t Res0, * pRes0 = &Res0;
+ Lpk_Res_t * pResMux, * pResDsd;
+ Lpk_Fun_t * p2;
+ int clk;
+
+ // is only called for non-trivial blocks
+ assert( p->nLutK >= 3 && p->nLutK <= 6 );
+ assert( p->nVars > p->nLutK );
+ // skip if area bound is exceeded
+ if ( Lpk_LutNumLuts(p->nVars, p->nLutK) > (int)p->nAreaLim )
+ return 0;
+ // skip if delay bound is exceeded
+ if ( Lpk_SuppDelay(p->uSupp, p->pDelays) > (int)p->nDelayLim )
+ return 0;
+
+ // compute supports if needed
+ if ( !p->fSupports )
+ Lpk_FunComputeCofSupps( p );
+
+ // check DSD decomposition
+clk = clock();
+ pResDsd = Lpk_DsdAnalize( pMan, p, pMan->pPars->nVarsShared );
+pMan->timeEvalDsdAn += clock() - clk;
+ if ( pResDsd && (pResDsd->nBSVars == (int)p->nLutK || pResDsd->nBSVars == (int)p->nLutK - 1) &&
+ pResDsd->AreaEst <= (int)p->nAreaLim && pResDsd->DelayEst <= (int)p->nDelayLim )
+ {
+clk = clock();
+ p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars );
+pMan->timeEvalDsdSp += clock() - clk;
+ assert( p2->nVars <= (int)p->nLutK );
+ if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) )
+ return 0;
+ return 1;
+ }
+
+ // check MUX decomposition
+clk = clock();
+ pResMux = Lpk_MuxAnalize( pMan, p );
+pMan->timeEvalMuxAn += clock() - clk;
+// pResMux = NULL;
+ assert( !pResMux || (pResMux->DelayEst <= (int)p->nDelayLim && pResMux->AreaEst <= (int)p->nAreaLim) );
+ // accept MUX decomposition if it is "good"
+ if ( pResMux && pResMux->nSuppSizeS <= (int)p->nLutK && pResMux->nSuppSizeL <= (int)p->nLutK )
+ pResDsd = NULL;
+ else if ( pResMux && pResDsd )
+ {
+ // compare two decompositions
+ if ( pResMux->AreaEst < pResDsd->AreaEst ||
+ (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL < pResDsd->nSuppSizeL) ||
+ (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL == pResDsd->nSuppSizeL && pResMux->DelayEst < pResDsd->DelayEst) )
+ pResDsd = NULL;
+ else
+ pResMux = NULL;
+ }
+ assert( pResMux == NULL || pResDsd == NULL );
+ if ( pResMux )
+ {
+clk = clock();
+ p2 = Lpk_MuxSplit( pMan, p, pResMux->Variable, pResMux->Polarity );
+pMan->timeEvalMuxSp += clock() - clk;
+ if ( p2->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p2 ) )
+ return 0;
+ if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) )
+ return 0;
+ return 1;
+ }
+ if ( pResDsd )
+ {
+clk = clock();
+ p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars );
+pMan->timeEvalDsdSp += clock() - clk;
+ assert( p2->nVars <= (int)p->nLutK );
+ if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) )
+ return 0;
+ return 1;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes decomposed nodes from the array of fanins.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_DecomposeClean( Vec_Ptr_t * vLeaves, int nLeavesOld )
+{
+ Lpk_Fun_t * pFunc;
+ int i;
+ Vec_PtrForEachEntryStart( vLeaves, pFunc, i, nLeavesOld )
+ Lpk_FunFree( pFunc );
+ Vec_PtrShrink( vLeaves, nLeavesOld );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Decomposes the function using recursive MUX decomposition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Lpk_Decompose( Lpk_Man_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, unsigned * puSupps, int nLutK, int AreaLim, int DelayLim )
+{
+ Lpk_Fun_t * pFun;
+ Abc_Obj_t * pObjNew = NULL;
+ int nLeaves = Vec_PtrSize( vLeaves );
+ pFun = Lpk_FunCreate( pNtk, vLeaves, pTruth, nLutK, AreaLim, DelayLim );
+ if ( puSupps[0] || puSupps[1] )
+ {
+/*
+ int i;
+ Lpk_FunComputeCofSupps( pFun );
+ for ( i = 0; i < nLeaves; i++ )
+ {
+ assert( pFun->puSupps[2*i+0] == puSupps[2*i+0] );
+ assert( pFun->puSupps[2*i+1] == puSupps[2*i+1] );
+ }
+*/
+ memcpy( pFun->puSupps, puSupps, sizeof(unsigned) * 2 * nLeaves );
+ pFun->fSupports = 1;
+ }
+ Lpk_FunSuppMinimize( pFun );
+ if ( pFun->nVars <= pFun->nLutK )
+ pObjNew = Lpk_ImplementFun( p, pNtk, vLeaves, pFun );
+ else if ( Lpk_Decompose_rec(p, pFun) )
+ pObjNew = Lpk_Implement( p, pNtk, vLeaves, nLeaves );
+ Lpk_DecomposeClean( vLeaves, nLeaves );
+ return pObjNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkAbcDsd.c b/src/opt/lpk/lpkAbcDsd.c
new file mode 100644
index 00000000..f4095914
--- /dev/null
+++ b/src/opt/lpk/lpkAbcDsd.c
@@ -0,0 +1,603 @@
+/**CFile****************************************************************
+
+ FileName [lpkAbcDsd.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis [LUT-decomposition based on recursive DSD.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkAbcDsd.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Cofactors TTs w.r.t. all vars and finds the best var.]
+
+ Description [The best variable is the variable with the minimum
+ sum total of the support sizes of all truth tables. This procedure
+ computes and returns cofactors w.r.t. the best variable.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_FunComputeMinSuppSizeVar( Lpk_Fun_t * p, unsigned ** ppTruths, int nTruths, unsigned ** ppCofs, unsigned uNonDecSupp )
+{
+ int i, Var, VarBest, nSuppSize0, nSuppSize1, nSuppTotalMin, nSuppTotalCur, nSuppMaxMin, nSuppMaxCur;
+ assert( nTruths > 0 );
+ VarBest = -1;
+ Lpk_SuppForEachVar( p->uSupp, Var )
+ {
+ if ( (uNonDecSupp & (1 << Var)) == 0 )
+ continue;
+ nSuppMaxCur = 0;
+ nSuppTotalCur = 0;
+ for ( i = 0; i < nTruths; i++ )
+ {
+ if ( nTruths == 1 )
+ {
+ nSuppSize0 = Kit_WordCountOnes( p->puSupps[2*Var+0] );
+ nSuppSize1 = Kit_WordCountOnes( p->puSupps[2*Var+1] );
+ }
+ else
+ {
+ Kit_TruthCofactor0New( ppCofs[2*i+0], ppTruths[i], p->nVars, Var );
+ Kit_TruthCofactor1New( ppCofs[2*i+1], ppTruths[i], p->nVars, Var );
+ nSuppSize0 = Kit_TruthSupportSize( ppCofs[2*i+0], p->nVars );
+ nSuppSize1 = Kit_TruthSupportSize( ppCofs[2*i+1], p->nVars );
+ }
+ nSuppMaxCur = ABC_MAX( nSuppMaxCur, nSuppSize0 );
+ nSuppMaxCur = ABC_MAX( nSuppMaxCur, nSuppSize1 );
+ nSuppTotalCur += nSuppSize0 + nSuppSize1;
+ }
+ if ( VarBest == -1 || nSuppMaxMin > nSuppMaxCur ||
+ (nSuppMaxMin == nSuppMaxCur && nSuppTotalMin > nSuppTotalCur) )
+ {
+ VarBest = Var;
+ nSuppMaxMin = nSuppMaxCur;
+ nSuppTotalMin = nSuppTotalCur;
+ }
+ }
+ // recompute cofactors for the best var
+ for ( i = 0; i < nTruths; i++ )
+ {
+ Kit_TruthCofactor0New( ppCofs[2*i+0], ppTruths[i], p->nVars, VarBest );
+ Kit_TruthCofactor1New( ppCofs[2*i+1], ppTruths[i], p->nVars, VarBest );
+ }
+ return VarBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes decomposable subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Lpk_ComputeBoundSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets, int nSizeMax )
+{
+ unsigned i, iLitFanin, uSupport, uSuppCur;
+ Kit_DsdObj_t * pObj;
+ // consider the case of simple gate
+ pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) );
+ if ( pObj == NULL )
+ return (1 << Kit_DsdLit2Var(iLit));
+ if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR )
+ {
+ unsigned uSupps[16], Limit, s;
+ uSupport = 0;
+ Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+ {
+ uSupps[i] = Lpk_ComputeBoundSets_rec( p, iLitFanin, vSets, nSizeMax );
+ uSupport |= uSupps[i];
+ }
+ // create all subsets, except empty and full
+ Limit = (1 << pObj->nFans) - 1;
+ for ( s = 1; s < Limit; s++ )
+ {
+ uSuppCur = 0;
+ for ( i = 0; i < pObj->nFans; i++ )
+ if ( s & (1 << i) )
+ uSuppCur |= uSupps[i];
+ if ( Kit_WordCountOnes(uSuppCur) <= nSizeMax )
+ Vec_IntPush( vSets, uSuppCur );
+ }
+ return uSupport;
+ }
+ assert( pObj->Type == KIT_DSD_PRIME );
+ // get the cumulative support of all fanins
+ uSupport = 0;
+ Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+ {
+ uSuppCur = Lpk_ComputeBoundSets_rec( p, iLitFanin, vSets, nSizeMax );
+ uSupport |= uSuppCur;
+ if ( Kit_WordCountOnes(uSuppCur) <= nSizeMax )
+ Vec_IntPush( vSets, uSuppCur );
+ }
+ return uSupport;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the set of subsets of decomposable variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Lpk_ComputeBoundSets( Kit_DsdNtk_t * p, int nSizeMax )
+{
+ Vec_Int_t * vSets;
+ unsigned uSupport, Entry;
+ int Number, i;
+ assert( p->nVars <= 16 );
+ vSets = Vec_IntAlloc( 100 );
+ Vec_IntPush( vSets, 0 );
+ if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 )
+ return vSets;
+ if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR )
+ {
+ uSupport = ( 1 << Kit_DsdLit2Var(Kit_DsdNtkRoot(p)->pFans[0]) );
+ if ( Kit_WordCountOnes(uSupport) <= nSizeMax )
+ Vec_IntPush( vSets, uSupport );
+ return vSets;
+ }
+ uSupport = Lpk_ComputeBoundSets_rec( p, p->Root, vSets, nSizeMax );
+ assert( (uSupport & 0xFFFF0000) == 0 );
+ // add the total support of the network
+ if ( Kit_WordCountOnes(uSupport) <= nSizeMax )
+ Vec_IntPush( vSets, uSupport );
+ // set the remaining variables
+ Vec_IntForEachEntry( vSets, Number, i )
+ {
+ Entry = Number;
+ Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) );
+ }
+ return vSets;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the sets of subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Lpk_PrintSetOne( int uSupport )
+{
+ unsigned k;
+ for ( k = 0; k < 16; k++ )
+ if ( uSupport & (1<<k) )
+ printf( "%c", 'a'+k );
+ printf( " " );
+}
+/**Function*************************************************************
+
+ Synopsis [Prints the sets of subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Lpk_PrintSets( Vec_Int_t * vSets )
+{
+ unsigned uSupport;
+ int Number, i;
+ printf( "Subsets(%d): ", Vec_IntSize(vSets) );
+ Vec_IntForEachEntry( vSets, Number, i )
+ {
+ uSupport = Number;
+ Lpk_PrintSetOne( uSupport );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two bound sets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Lpk_MergeBoundSets( Vec_Int_t * vSets0, Vec_Int_t * vSets1, int nSizeMax )
+{
+ Vec_Int_t * vSets;
+ int Entry0, Entry1, Entry;
+ int i, k;
+ vSets = Vec_IntAlloc( 100 );
+ Vec_IntForEachEntry( vSets0, Entry0, i )
+ Vec_IntForEachEntry( vSets1, Entry1, k )
+ {
+ Entry = Entry0 | Entry1;
+ if ( (Entry & (Entry >> 16)) )
+ continue;
+ if ( Kit_WordCountOnes(Entry & 0xffff) <= nSizeMax )
+ Vec_IntPush( vSets, Entry );
+ }
+ return vSets;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs DSD-based decomposition of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_FunCompareBoundSets( Lpk_Fun_t * p, Vec_Int_t * vBSets, int nCofDepth, unsigned uNonDecSupp, unsigned uLateArrSupp, Lpk_Res_t * pRes )
+{
+ int fVerbose = 0;
+ unsigned uBoundSet;
+ int i, nVarsBS, nVarsRem, Delay, Area;
+
+ // compare the resulting boundsets
+ memset( pRes, 0, sizeof(Lpk_Res_t) );
+ Vec_IntForEachEntry( vBSets, uBoundSet, i )
+ {
+ if ( (uBoundSet & 0xFFFF) == 0 ) // skip empty boundset
+ continue;
+ if ( (uBoundSet & uNonDecSupp) == 0 ) // skip those boundsets that are not in the domain of interest
+ continue;
+ if ( (uBoundSet & uLateArrSupp) ) // skip those boundsets that are late arriving
+ continue;
+if ( fVerbose )
+Lpk_PrintSetOne( uBoundSet );
+ assert( (uBoundSet & (uBoundSet >> 16)) == 0 );
+ nVarsBS = Kit_WordCountOnes( uBoundSet & 0xFFFF );
+ if ( nVarsBS == 1 )
+ continue;
+ assert( nVarsBS <= (int)p->nLutK - nCofDepth );
+ nVarsRem = p->nVars - nVarsBS + 1;
+ Area = 1 + Lpk_LutNumLuts( nVarsRem, p->nLutK );
+ Delay = 1 + Lpk_SuppDelay( uBoundSet & 0xFFFF, p->pDelays );
+if ( fVerbose )
+printf( "area = %d limit = %d delay = %d limit = %d\n", Area, (int)p->nAreaLim, Delay, (int)p->nDelayLim );
+ if ( Area > (int)p->nAreaLim || Delay > (int)p->nDelayLim )
+ continue;
+ if ( pRes->BSVars == 0 || pRes->nSuppSizeL > nVarsRem || (pRes->nSuppSizeL == nVarsRem && pRes->DelayEst > Delay) )
+ {
+ pRes->nBSVars = nVarsBS;
+ pRes->BSVars = (uBoundSet & 0xFFFF);
+ pRes->nSuppSizeS = nVarsBS + nCofDepth;
+ pRes->nSuppSizeL = nVarsRem;
+ pRes->DelayEst = Delay;
+ pRes->AreaEst = Area;
+ }
+ }
+if ( fVerbose )
+{
+if ( pRes->BSVars )
+{
+printf( "Found bound set " );
+Lpk_PrintSetOne( pRes->BSVars );
+printf( "\n" );
+}
+else
+printf( "Did not find boundsets.\n" );
+printf( "\n" );
+}
+ if ( pRes->BSVars )
+ {
+ assert( pRes->DelayEst <= (int)p->nDelayLim );
+ assert( pRes->AreaEst <= (int)p->nAreaLim );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds late arriving inputs, which cannot be in the bound set.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Lpk_DsdLateArriving( Lpk_Fun_t * p )
+{
+ unsigned i, uLateArrSupp = 0;
+ Lpk_SuppForEachVar( p->uSupp, i )
+ if ( p->pDelays[i] > (int)p->nDelayLim - 2 )
+ uLateArrSupp |= (1 << i);
+ return uLateArrSupp;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs DSD-based decomposition of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_DsdAnalizeOne( Lpk_Fun_t * p, unsigned * ppTruths[5][16], Kit_DsdNtk_t * pNtks[], char pCofVars[], int nCofDepth, Lpk_Res_t * pRes )
+{
+ int fVerbose = 0;
+ Vec_Int_t * pvBSets[4][8];
+ unsigned uNonDecSupp, uLateArrSupp;
+ int i, k, nNonDecSize, nNonDecSizeMax;
+ assert( nCofDepth >= 1 && nCofDepth <= 3 );
+ assert( nCofDepth < (int)p->nLutK - 1 );
+ assert( p->fSupports );
+
+ // find the support of the largest non-DSD block
+ nNonDecSizeMax = 0;
+ uNonDecSupp = p->uSupp;
+ for ( i = 0; i < (1<<(nCofDepth-1)); i++ )
+ {
+ nNonDecSize = Kit_DsdNonDsdSizeMax( pNtks[i] );
+ if ( nNonDecSizeMax < nNonDecSize )
+ {
+ nNonDecSizeMax = nNonDecSize;
+ uNonDecSupp = Kit_DsdNonDsdSupports( pNtks[i] );
+ }
+ else if ( nNonDecSizeMax == nNonDecSize )
+ uNonDecSupp |= Kit_DsdNonDsdSupports( pNtks[i] );
+ }
+
+ // remove those variables that cannot be used because of delay constraints
+ // if variables arrival time is more than p->DelayLim - 2, it cannot be used
+ uLateArrSupp = Lpk_DsdLateArriving( p );
+ if ( (uNonDecSupp & ~uLateArrSupp) == 0 )
+ {
+ memset( pRes, 0, sizeof(Lpk_Res_t) );
+ return 0;
+ }
+
+ // find the next cofactoring variable
+ pCofVars[nCofDepth-1] = Lpk_FunComputeMinSuppSizeVar( p, ppTruths[nCofDepth-1], 1<<(nCofDepth-1), ppTruths[nCofDepth], uNonDecSupp & ~uLateArrSupp );
+
+ // derive decomposed networks
+ for ( i = 0; i < (1<<nCofDepth); i++ )
+ {
+ if ( pNtks[i] )
+ Kit_DsdNtkFree( pNtks[i] );
+ pNtks[i] = Kit_DsdDecomposeExpand( ppTruths[nCofDepth][i], p->nVars );
+if ( fVerbose )
+Kit_DsdPrint( stdout, pNtks[i] );
+ pvBSets[nCofDepth][i] = Lpk_ComputeBoundSets( pNtks[i], p->nLutK - nCofDepth ); // try restricting to those in uNonDecSupp!!!
+ }
+
+ // derive the set of feasible boundsets
+ for ( i = nCofDepth - 1; i >= 0; i-- )
+ for ( k = 0; k < (1<<i); k++ )
+ pvBSets[i][k] = Lpk_MergeBoundSets( pvBSets[i+1][2*k+0], pvBSets[i+1][2*k+1], p->nLutK - nCofDepth );
+ // compare bound-sets
+ Lpk_FunCompareBoundSets( p, pvBSets[0][0], nCofDepth, uNonDecSupp, uLateArrSupp, pRes );
+ // free the bound sets
+ for ( i = nCofDepth; i >= 0; i-- )
+ for ( k = 0; k < (1<<i); k++ )
+ Vec_IntFree( pvBSets[i][k] );
+
+ // copy the cofactoring variables
+ if ( pRes->BSVars )
+ {
+ pRes->nCofVars = nCofDepth;
+ for ( i = 0; i < nCofDepth; i++ )
+ pRes->pCofVars[i] = pCofVars[i];
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs DSD-based decomposition of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Res_t * Lpk_DsdAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p, int nShared )
+{
+ static Lpk_Res_t Res0, * pRes0 = &Res0;
+ static Lpk_Res_t Res1, * pRes1 = &Res1;
+ static Lpk_Res_t Res2, * pRes2 = &Res2;
+ static Lpk_Res_t Res3, * pRes3 = &Res3;
+ int fUseBackLooking = 1;
+ Lpk_Res_t * pRes = NULL;
+ Vec_Int_t * vBSets;
+ Kit_DsdNtk_t * pNtks[8] = {NULL};
+ char pCofVars[5];
+ int i;
+
+ assert( p->nLutK >= 3 );
+ assert( nShared >= 0 && nShared <= 3 );
+ assert( p->uSupp == Kit_BitMask(p->nVars) );
+
+ // try decomposition without cofactoring
+ pNtks[0] = Kit_DsdDecomposeExpand( Lpk_FunTruth( p, 0 ), p->nVars );
+ if ( pMan->pPars->fVerbose )
+ pMan->nBlocks[ Kit_DsdNonDsdSizeMax(pNtks[0]) ]++;
+ vBSets = Lpk_ComputeBoundSets( pNtks[0], p->nLutK );
+ Lpk_FunCompareBoundSets( p, vBSets, 0, 0xFFFF, Lpk_DsdLateArriving(p), pRes0 );
+ Vec_IntFree( vBSets );
+
+ // check the result
+ if ( pRes0->nBSVars == (int)p->nLutK )
+ { pRes = pRes0; goto finish; }
+ if ( pRes0->nBSVars == (int)p->nLutK - 1 )
+ { pRes = pRes0; goto finish; }
+ if ( nShared == 0 )
+ goto finish;
+
+ // prepare storage
+ Kit_TruthCopy( pMan->ppTruths[0][0], Lpk_FunTruth( p, 0 ), p->nVars );
+
+ // cofactor 1 time
+ if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 1, pRes1 ) )
+ goto finish;
+ assert( pRes1->nBSVars <= (int)p->nLutK - 1 );
+ if ( pRes1->nBSVars == (int)p->nLutK - 1 )
+ { pRes = pRes1; goto finish; }
+ if ( pRes0->nBSVars == (int)p->nLutK - 2 )
+ { pRes = pRes0; goto finish; }
+ if ( pRes1->nBSVars == (int)p->nLutK - 2 )
+ { pRes = pRes1; goto finish; }
+ if ( nShared == 1 )
+ goto finish;
+
+ // cofactor 2 times
+ if ( p->nLutK >= 4 )
+ {
+ if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 2, pRes2 ) )
+ goto finish;
+ assert( pRes2->nBSVars <= (int)p->nLutK - 2 );
+ if ( pRes2->nBSVars == (int)p->nLutK - 2 )
+ { pRes = pRes2; goto finish; }
+ if ( fUseBackLooking )
+ {
+ if ( pRes0->nBSVars == (int)p->nLutK - 3 )
+ { pRes = pRes0; goto finish; }
+ if ( pRes1->nBSVars == (int)p->nLutK - 3 )
+ { pRes = pRes1; goto finish; }
+ }
+ if ( pRes2->nBSVars == (int)p->nLutK - 3 )
+ { pRes = pRes2; goto finish; }
+ if ( nShared == 2 )
+ goto finish;
+ assert( nShared == 3 );
+ }
+
+ // cofactor 3 times
+ if ( p->nLutK >= 5 )
+ {
+ if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 3, pRes3 ) )
+ goto finish;
+ assert( pRes3->nBSVars <= (int)p->nLutK - 3 );
+ if ( pRes3->nBSVars == (int)p->nLutK - 3 )
+ { pRes = pRes3; goto finish; }
+ if ( fUseBackLooking )
+ {
+ if ( pRes0->nBSVars == (int)p->nLutK - 4 )
+ { pRes = pRes0; goto finish; }
+ if ( pRes1->nBSVars == (int)p->nLutK - 4 )
+ { pRes = pRes1; goto finish; }
+ if ( pRes2->nBSVars == (int)p->nLutK - 4 )
+ { pRes = pRes2; goto finish; }
+ }
+ if ( pRes3->nBSVars == (int)p->nLutK - 4 )
+ { pRes = pRes3; goto finish; }
+ }
+
+finish:
+ // free the networks
+ for ( i = 0; i < (1<<nShared); i++ )
+ if ( pNtks[i] )
+ Kit_DsdNtkFree( pNtks[i] );
+ // choose the best under these conditions
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Splits the function into two subfunctions using DSD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_DsdSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, char * pCofVars, int nCofVars, unsigned uBoundSet )
+{
+ Lpk_Fun_t * pNew;
+ Kit_DsdNtk_t * pNtkDec;
+ int i, k, iVacVar, nCofs;
+ // prepare storage
+ Kit_TruthCopy( pMan->ppTruths[0][0], Lpk_FunTruth(p, 0), p->nVars );
+ // get the vacuous variable
+ iVacVar = Kit_WordFindFirstBit( uBoundSet );
+ // compute the cofactors
+ for ( i = 0; i < nCofVars; i++ )
+ for ( k = 0; k < (1<<i); k++ )
+ {
+ Kit_TruthCofactor0New( pMan->ppTruths[i+1][2*k+0], pMan->ppTruths[i][k], p->nVars, pCofVars[i] );
+ Kit_TruthCofactor1New( pMan->ppTruths[i+1][2*k+1], pMan->ppTruths[i][k], p->nVars, pCofVars[i] );
+ }
+ // decompose each cofactor w.r.t. the bound set
+ nCofs = (1<<nCofVars);
+ for ( k = 0; k < nCofs; k++ )
+ {
+ pNtkDec = Kit_DsdDecomposeExpand( pMan->ppTruths[nCofVars][k], p->nVars );
+ Kit_DsdTruthPartialTwo( pMan->pDsdMan, pNtkDec, uBoundSet, iVacVar, pMan->ppTruths[nCofVars+1][k], pMan->ppTruths[nCofVars+1][nCofs+k] );
+ Kit_DsdNtkFree( pNtkDec );
+ }
+ // compute the composition/decomposition functions (they will be in pMan->ppTruths[1][0]/pMan->ppTruths[1][1])
+ for ( i = nCofVars; i >= 1; i-- )
+ for ( k = 0; k < (1<<i); k++ )
+ Kit_TruthMuxVar( pMan->ppTruths[i][k], pMan->ppTruths[i+1][2*k+0], pMan->ppTruths[i+1][2*k+1], p->nVars, pCofVars[i-1] );
+
+ // derive the new component (decomposition function)
+ pNew = Lpk_FunDup( p, pMan->ppTruths[1][1] );
+ // update the old component (composition function)
+ Kit_TruthCopy( Lpk_FunTruth(p, 0), pMan->ppTruths[1][0], p->nVars );
+ p->uSupp = Kit_TruthSupport( Lpk_FunTruth(p, 0), p->nVars );
+ p->pFanins[iVacVar] = pNew->Id;
+ p->pDelays[iVacVar] = Lpk_SuppDelay( pNew->uSupp, pNew->pDelays );
+ // support minimize both
+ p->fSupports = 0;
+ Lpk_FunSuppMinimize( p );
+ Lpk_FunSuppMinimize( pNew );
+ // update delay and area requirements
+ pNew->nDelayLim = p->pDelays[iVacVar];
+ pNew->nAreaLim = 1;
+ p->nAreaLim = p->nAreaLim - 1;
+ return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkAbcMux.c b/src/opt/lpk/lpkAbcMux.c
new file mode 100644
index 00000000..d6f579ee
--- /dev/null
+++ b/src/opt/lpk/lpkAbcMux.c
@@ -0,0 +1,235 @@
+/**CFile****************************************************************
+
+ FileName [lpkAbcMux.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis [LUT-decomposition based on recursive MUX decomposition.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkAbcMux.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Checks the possibility of MUX decomposition.]
+
+ Description [Returns the best variable to use for MUX decomposition.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p )
+{
+ static Lpk_Res_t Res, * pRes = &Res;
+ int nSuppSize0, nSuppSize1, nSuppSizeS, nSuppSizeL;
+ int Var, Area, Polarity, Delay, Delay0, Delay1, DelayA, DelayB;
+ memset( pRes, 0, sizeof(Lpk_Res_t) );
+ assert( p->uSupp == Kit_BitMask(p->nVars) );
+ assert( p->fSupports );
+ // derive the delay and area after MUX-decomp with each var - and find the best var
+ pRes->Variable = -1;
+ Lpk_SuppForEachVar( p->uSupp, Var )
+ {
+ nSuppSize0 = Kit_WordCountOnes(p->puSupps[2*Var+0]);
+ nSuppSize1 = Kit_WordCountOnes(p->puSupps[2*Var+1]);
+ assert( nSuppSize0 < (int)p->nVars );
+ assert( nSuppSize1 < (int)p->nVars );
+ if ( nSuppSize0 < 1 || nSuppSize1 < 1 )
+ continue;
+//printf( "%d %d ", nSuppSize0, nSuppSize1 );
+ if ( nSuppSize0 <= (int)p->nLutK - 2 && nSuppSize1 <= (int)p->nLutK - 2 )
+ {
+ // include cof var into 0-block
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays );
+ Delay0 = ABC_MAX( DelayA, DelayB + 1 );
+ // include cof var into 1-block
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays );
+ Delay1 = ABC_MAX( DelayA, DelayB + 1 );
+ // get the best delay
+ Delay = ABC_MIN( Delay0, Delay1 );
+ Area = 2;
+ Polarity = (int)(Delay == Delay1);
+ }
+ else if ( nSuppSize0 <= (int)p->nLutK - 2 )
+ {
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays );
+ Delay = ABC_MAX( DelayA, DelayB + 1 );
+ Area = 1 + Lpk_LutNumLuts( nSuppSize1, p->nLutK );
+ Polarity = 0;
+ }
+ else if ( nSuppSize1 <= (int)p->nLutK - 2 )
+ {
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays );
+ Delay = ABC_MAX( DelayA, DelayB + 1 );
+ Area = 1 + Lpk_LutNumLuts( nSuppSize0, p->nLutK );
+ Polarity = 1;
+ }
+ else if ( nSuppSize0 <= (int)p->nLutK )
+ {
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays );
+ Delay = ABC_MAX( DelayA, DelayB + 1 );
+ Area = 1 + Lpk_LutNumLuts( nSuppSize1+2, p->nLutK );
+ Polarity = 1;
+ }
+ else if ( nSuppSize1 <= (int)p->nLutK )
+ {
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays );
+ Delay = ABC_MAX( DelayA, DelayB + 1 );
+ Area = 1 + Lpk_LutNumLuts( nSuppSize0+2, p->nLutK );
+ Polarity = 0;
+ }
+ else
+ {
+ // include cof var into 0-block
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays );
+ Delay0 = ABC_MAX( DelayA, DelayB + 1 );
+ // include cof var into 1-block
+ DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<<Var), p->pDelays );
+ DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays );
+ Delay1 = ABC_MAX( DelayA, DelayB + 1 );
+ // get the best delay
+ Delay = ABC_MIN( Delay0, Delay1 );
+ if ( Delay == Delay0 )
+ Area = Lpk_LutNumLuts( nSuppSize0+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize1, p->nLutK );
+ else
+ Area = Lpk_LutNumLuts( nSuppSize1+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize0, p->nLutK );
+ Polarity = (int)(Delay == Delay1);
+ }
+ // find the best variable
+ if ( Delay > (int)p->nDelayLim )
+ continue;
+ if ( Area > (int)p->nAreaLim )
+ continue;
+ nSuppSizeS = ABC_MIN( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity );
+ nSuppSizeL = ABC_MAX( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity );
+ if ( nSuppSizeL > (int)p->nVars )
+ continue;
+ if ( pRes->Variable == -1 || pRes->AreaEst > Area ||
+ (pRes->AreaEst == Area && pRes->nSuppSizeS + pRes->nSuppSizeL > nSuppSizeS + nSuppSizeL) ||
+ (pRes->AreaEst == Area && pRes->nSuppSizeS + pRes->nSuppSizeL == nSuppSizeS + nSuppSizeL && pRes->DelayEst > Delay) )
+ {
+ pRes->Variable = Var;
+ pRes->Polarity = Polarity;
+ pRes->AreaEst = Area;
+ pRes->DelayEst = Delay;
+ pRes->nSuppSizeS = nSuppSizeS;
+ pRes->nSuppSizeL = nSuppSizeL;
+ }
+ }
+ return pRes->Variable == -1 ? NULL : pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the function decomposed by the MUX decomposition.]
+
+ Description [Returns the best variable to use for MUX decomposition.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_MuxSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, int Var, int Pol )
+{
+ Lpk_Fun_t * pNew;
+ unsigned * pTruth = Lpk_FunTruth( p, 0 );
+ unsigned * pTruth0 = Lpk_FunTruth( p, 1 );
+ unsigned * pTruth1 = Lpk_FunTruth( p, 2 );
+// unsigned uSupp;
+ int iVarVac;
+ assert( Var >= 0 && Var < (int)p->nVars );
+ assert( p->nAreaLim >= 2 );
+ assert( p->uSupp == Kit_BitMask(p->nVars) );
+ Kit_TruthCofactor0New( pTruth0, pTruth, p->nVars, Var );
+ Kit_TruthCofactor1New( pTruth1, pTruth, p->nVars, Var );
+/*
+uSupp = Kit_TruthSupport( pTruth, p->nVars );
+Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n" );
+uSupp = Kit_TruthSupport( pTruth0, p->nVars );
+Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n" );
+uSupp = Kit_TruthSupport( pTruth1, p->nVars );
+Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n\n" );
+*/
+ // derive the new component
+ pNew = Lpk_FunDup( p, Pol ? pTruth0 : pTruth1 );
+ // update the support of the old component
+ p->uSupp = Kit_TruthSupport( Pol ? pTruth1 : pTruth0, p->nVars );
+ p->uSupp |= (1 << Var);
+ // update the truth table of the old component
+ iVarVac = Kit_WordFindFirstBit( ~p->uSupp );
+ assert( iVarVac < (int)p->nVars );
+ p->uSupp |= (1 << iVarVac);
+ Kit_TruthIthVar( pTruth, p->nVars, iVarVac );
+ if ( Pol )
+ Kit_TruthMuxVar( pTruth, pTruth, pTruth1, p->nVars, Var );
+ else
+ Kit_TruthMuxVar( pTruth, pTruth0, pTruth, p->nVars, Var );
+ assert( p->uSupp == Kit_TruthSupport(pTruth, p->nVars) );
+ // set the decomposed variable
+ p->pFanins[iVarVac] = pNew->Id;
+ p->pDelays[iVarVac] = p->nDelayLim - 1;
+ // support minimize both
+ p->fSupports = 0;
+ Lpk_FunSuppMinimize( p );
+ Lpk_FunSuppMinimize( pNew );
+ // update delay and area requirements
+ pNew->nDelayLim = p->nDelayLim - 1;
+ if ( pNew->nVars <= pNew->nLutK )
+ {
+ pNew->nAreaLim = 1;
+ p->nAreaLim = p->nAreaLim - 1;
+ }
+ else if ( p->nVars <= p->nLutK )
+ {
+ pNew->nAreaLim = p->nAreaLim - 1;
+ p->nAreaLim = 1;
+ }
+ else if ( p->nVars < pNew->nVars )
+ {
+ pNew->nAreaLim = p->nAreaLim / 2 + p->nAreaLim % 2;
+ p->nAreaLim = p->nAreaLim / 2 - p->nAreaLim % 2;
+ }
+ else // if ( pNew->nVars < p->nVars )
+ {
+ pNew->nAreaLim = p->nAreaLim / 2 - p->nAreaLim % 2;
+ p->nAreaLim = p->nAreaLim / 2 + p->nAreaLim % 2;
+ }
+ pNew->fMark = 1;
+ return pNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkAbcUtil.c b/src/opt/lpk/lpkAbcUtil.c
new file mode 100644
index 00000000..3f917ce2
--- /dev/null
+++ b/src/opt/lpk/lpkAbcUtil.c
@@ -0,0 +1,244 @@
+/**CFile****************************************************************
+
+ FileName [lpkAbcUtil.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis [Procedures working on decomposed functions.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkAbcUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_FunAlloc( int nVars )
+{
+ Lpk_Fun_t * p;
+ p = (Lpk_Fun_t *)malloc( sizeof(Lpk_Fun_t) + sizeof(unsigned) * Kit_TruthWordNum(nVars) * 3 );
+ memset( p, 0, sizeof(Lpk_Fun_t) );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the function]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_FunFree( Lpk_Fun_t * p )
+{
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the starting function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_FunCreate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, int nLutK, int AreaLim, int DelayLim )
+{
+ Lpk_Fun_t * p;
+ Abc_Obj_t * pNode;
+ int i;
+ p = Lpk_FunAlloc( Vec_PtrSize(vLeaves) );
+ p->Id = Vec_PtrSize(vLeaves);
+ p->vNodes = vLeaves;
+ p->nVars = Vec_PtrSize(vLeaves);
+ p->nLutK = nLutK;
+ p->nAreaLim = AreaLim;
+ p->nDelayLim = DelayLim;
+ p->uSupp = Kit_TruthSupport( pTruth, p->nVars );
+ Kit_TruthCopy( Lpk_FunTruth(p,0), pTruth, p->nVars );
+ Vec_PtrForEachEntry( vLeaves, pNode, i )
+ {
+ p->pFanins[i] = i;
+ p->pDelays[i] = pNode->Level;
+ }
+ Vec_PtrPush( p->vNodes, p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the new function with the given truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Fun_t * Lpk_FunDup( Lpk_Fun_t * p, unsigned * pTruth )
+{
+ Lpk_Fun_t * pNew;
+ pNew = Lpk_FunAlloc( p->nVars );
+ pNew->Id = Vec_PtrSize(p->vNodes);
+ pNew->vNodes = p->vNodes;
+ pNew->nVars = p->nVars;
+ pNew->nLutK = p->nLutK;
+ pNew->nAreaLim = p->nAreaLim;
+ pNew->nDelayLim = p->nDelayLim;
+ pNew->uSupp = Kit_TruthSupport( pTruth, p->nVars );
+ Kit_TruthCopy( Lpk_FunTruth(pNew,0), pTruth, p->nVars );
+ memcpy( pNew->pFanins, p->pFanins, 16 );
+ memcpy( pNew->pDelays, p->pDelays, 16 );
+ Vec_PtrPush( p->vNodes, pNew );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes support of the function.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_FunSuppMinimize( Lpk_Fun_t * p )
+{
+ int i, k, nVarsNew;
+ // compress the truth table
+ if ( p->uSupp == Kit_BitMask(p->nVars) )
+ return 0;
+ // invalidate support info
+ p->fSupports = 0;
+//Extra_PrintBinary( stdout, &p->uSupp, p->nVars ); printf( "\n" );
+ // minimize support
+ nVarsNew = Kit_WordCountOnes(p->uSupp);
+ Kit_TruthShrink( Lpk_FunTruth(p, 1), Lpk_FunTruth(p, 0), nVarsNew, p->nVars, p->uSupp, 1 );
+ k = 0;
+ Lpk_SuppForEachVar( p->uSupp, i )
+ {
+ p->pFanins[k] = p->pFanins[i];
+ p->pDelays[k] = p->pDelays[i];
+/*
+ if ( p->fSupports )
+ {
+ p->puSupps[2*k+0] = p->puSupps[2*i+0];
+ p->puSupps[2*k+1] = p->puSupps[2*i+1];
+ }
+*/
+ k++;
+ }
+ assert( k == nVarsNew );
+ p->nVars = k;
+ p->uSupp = Kit_BitMask(p->nVars);
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes cofactors w.r.t. each variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_FunComputeCofSupps( Lpk_Fun_t * p )
+{
+ unsigned * pTruth = Lpk_FunTruth( p, 0 );
+ unsigned * pTruth0 = Lpk_FunTruth( p, 1 );
+ unsigned * pTruth1 = Lpk_FunTruth( p, 2 );
+ int Var;
+ assert( p->fSupports == 0 );
+// Lpk_SuppForEachVar( p->uSupp, Var )
+ for ( Var = 0; Var < (int)p->nVars; Var++ )
+ {
+ Kit_TruthCofactor0New( pTruth0, pTruth, p->nVars, Var );
+ Kit_TruthCofactor1New( pTruth1, pTruth, p->nVars, Var );
+ p->puSupps[2*Var+0] = Kit_TruthSupport( pTruth0, p->nVars );
+ p->puSupps[2*Var+1] = Kit_TruthSupport( pTruth1, p->nVars );
+ }
+ p->fSupports = 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Get the delay of the bound set.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_SuppDelay( unsigned uSupp, char * pDelays )
+{
+ int Delay, Var;
+ Delay = 0;
+ Lpk_SuppForEachVar( uSupp, Var )
+ Delay = ABC_MAX( Delay, pDelays[Var] );
+ return Delay + 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts support into variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_SuppToVars( unsigned uBoundSet, char * pVars )
+{
+ int i, nVars = 0;
+ Lpk_SuppForEachVar( uBoundSet, i )
+ pVars[nVars++] = i;
+ return nVars;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkCore.c b/src/opt/lpk/lpkCore.c
new file mode 100644
index 00000000..e819a7fb
--- /dev/null
+++ b/src/opt/lpk/lpkCore.c
@@ -0,0 +1,659 @@
+/**CFile****************************************************************
+
+ FileName [lpkCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+#include "cloud.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_IfManStart( Lpk_Man_t * p )
+{
+ If_Par_t * pPars;
+ assert( p->pIfMan == NULL );
+ // set defaults
+ pPars = ALLOC( If_Par_t, 1 );
+ memset( pPars, 0, sizeof(If_Par_t) );
+ // user-controlable paramters
+ pPars->nLutSize = p->pPars->nLutSize;
+ pPars->nCutsMax = 16;
+ pPars->nFlowIters = 0; // 1
+ pPars->nAreaIters = 0; // 1
+ pPars->DelayTarget = -1;
+ pPars->fPreprocess = 0;
+ pPars->fArea = 1;
+ pPars->fFancy = 0;
+ pPars->fExpRed = 0; //
+ pPars->fLatchPaths = 0;
+ pPars->fSeqMap = 0;
+ pPars->fVerbose = 0;
+ // internal parameters
+ pPars->fTruth = 1;
+ pPars->fUsePerm = 0;
+ pPars->nLatches = 0;
+ pPars->pLutLib = NULL; // Abc_FrameReadLibLut();
+ pPars->pTimesArr = NULL;
+ pPars->pTimesArr = NULL;
+ pPars->fUseBdds = 0;
+ pPars->fUseSops = 0;
+ pPars->fUseCnfs = 0;
+ pPars->fUseMv = 0;
+ // start the mapping manager and set its parameters
+ p->pIfMan = If_ManStart( pPars );
+ If_ManSetupSetAll( p->pIfMan, 1000 );
+ p->pIfMan->pPars->pTimesArr = ALLOC( float, 32 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if at least one entry has changed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_NodeHasChanged( Lpk_Man_t * p, int iNode )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pTemp;
+ int i;
+ vNodes = Vec_VecEntry( p->vVisited, iNode );
+ if ( Vec_PtrSize(vNodes) == 0 )
+ return 1;
+ Vec_PtrForEachEntry( vNodes, pTemp, i )
+ {
+ // check if the node has changed
+ pTemp = Abc_NtkObj( p->pNtk, (int)pTemp );
+ if ( pTemp == NULL )
+ return 1;
+ // check if the number of fanouts has changed
+// if ( Abc_ObjFanoutNum(pTemp) != (int)Vec_PtrEntry(vNodes, i+1) )
+// return 1;
+ i++;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_ExploreCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, Kit_DsdNtk_t * pNtk )
+{
+ extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover );
+ Kit_DsdObj_t * pRoot;
+ If_Obj_t * pDriver, * ppLeaves[16];
+ Abc_Obj_t * pLeaf, * pObjNew;
+ int nGain, i, clk;
+ int nNodesBef;
+// int nOldShared;
+
+ // check special cases
+ pRoot = Kit_DsdNtkRoot( pNtk );
+ if ( pRoot->Type == KIT_DSD_CONST1 )
+ {
+ if ( Kit_DsdLitIsCompl(pNtk->Root) )
+ pObjNew = Abc_NtkCreateNodeConst0( p->pNtk );
+ else
+ pObjNew = Abc_NtkCreateNodeConst1( p->pNtk );
+ Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels );
+ p->nGainTotal += pCut->nNodes - pCut->nNodesDup;
+ return 1;
+ }
+ if ( pRoot->Type == KIT_DSD_VAR )
+ {
+ pObjNew = Abc_NtkObj( p->pNtk, pCut->pLeaves[ Kit_DsdLit2Var(pRoot->pFans[0]) ] );
+ if ( Kit_DsdLitIsCompl(pNtk->Root) ^ Kit_DsdLitIsCompl(pRoot->pFans[0]) )
+ pObjNew = Abc_NtkCreateNodeInv( p->pNtk, pObjNew );
+ Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels );
+ p->nGainTotal += pCut->nNodes - pCut->nNodesDup;
+ return 1;
+ }
+ assert( pRoot->Type == KIT_DSD_AND || pRoot->Type == KIT_DSD_XOR || pRoot->Type == KIT_DSD_PRIME );
+
+ // start the mapping manager
+ if ( p->pIfMan == NULL )
+ Lpk_IfManStart( p );
+
+ // prepare the mapping manager
+ If_ManRestart( p->pIfMan );
+ // create the PI variables
+ for ( i = 0; i < p->pPars->nVarsMax; i++ )
+ ppLeaves[i] = If_ManCreateCi( p->pIfMan );
+ // set the arrival times
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i )
+ p->pIfMan->pPars->pTimesArr[i] = (float)pLeaf->Level;
+ // prepare the PI cuts
+ If_ManSetupCiCutSets( p->pIfMan );
+ // create the internal nodes
+ p->fCalledOnce = 0;
+ p->nCalledSRed = 0;
+ pDriver = Lpk_MapTree_rec( p, pNtk, ppLeaves, pNtk->Root, NULL );
+ if ( pDriver == NULL )
+ return 0;
+ // create the PO node
+ If_ManCreateCo( p->pIfMan, If_Regular(pDriver) );
+
+ // perform mapping
+ p->pIfMan->pPars->fAreaOnly = 1;
+clk = clock();
+ If_ManPerformMappingComb( p->pIfMan );
+p->timeMap += clock() - clk;
+
+ // compute the gain in area
+ nGain = pCut->nNodes - pCut->nNodesDup - (int)p->pIfMan->AreaGlo;
+ if ( p->pPars->fVeryVerbose )
+ printf( " Mffc = %2d. Mapped = %2d. Gain = %3d. Depth increase = %d. SReds = %d.\n",
+ pCut->nNodes - pCut->nNodesDup, (int)p->pIfMan->AreaGlo, nGain, (int)p->pIfMan->RequiredGlo - (int)p->pObj->Level, p->nCalledSRed );
+
+ // quit if there is no gain
+ if ( !(nGain > 0 || (p->pPars->fZeroCost && nGain == 0)) )
+ return 0;
+
+ // quit if depth increases too much
+ if ( (int)p->pIfMan->RequiredGlo > Abc_ObjRequiredLevel(p->pObj) )
+ return 0;
+
+ // perform replacement
+ p->nGainTotal += nGain;
+ p->nChanges++;
+ if ( p->nCalledSRed )
+ p->nBenefited++;
+
+ nNodesBef = Abc_NtkNodeNum(p->pNtk);
+ // prepare the mapping manager
+ If_ManCleanNodeCopy( p->pIfMan );
+ If_ManCleanCutData( p->pIfMan );
+ // set the PIs of the cut
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i )
+ If_ObjSetCopy( If_ManCi(p->pIfMan, i), pLeaf );
+ // get the area of mapping
+ pObjNew = Abc_NodeFromIf_rec( p->pNtk, p->pIfMan, If_Regular(pDriver), p->vCover );
+ pObjNew->pData = Hop_NotCond( pObjNew->pData, If_IsComplement(pDriver) );
+ // perform replacement
+ Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels );
+//printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs resynthesis for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_ResynthesizeNode( Lpk_Man_t * p )
+{
+ static int Count = 0;
+ Kit_DsdNtk_t * pDsdNtk;
+ Lpk_Cut_t * pCut;
+ unsigned * pTruth;
+ int i, k, nSuppSize, nCutNodes, RetValue, clk;
+
+ // compute the cuts
+clk = clock();
+ if ( !Lpk_NodeCuts( p ) )
+ {
+p->timeCuts += clock() - clk;
+ return 0;
+ }
+p->timeCuts += clock() - clk;
+
+//return 0;
+
+ if ( p->pPars->fVeryVerbose )
+ printf( "Node %5d : Mffc size = %5d. Cuts = %5d.\n", p->pObj->Id, p->nMffc, p->nEvals );
+ // try the good cuts
+ p->nCutsTotal += p->nCuts;
+ p->nCutsUseful += p->nEvals;
+ for ( i = 0; i < p->nEvals; i++ )
+ {
+ // get the cut
+ pCut = p->pCuts + p->pEvals[i];
+ if ( p->pPars->fFirst && i == 1 )
+ break;
+
+ // skip bad cuts
+// printf( "Mffc size = %d. ", Abc_NodeMffcLabel(p->pObj) );
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++;
+ nCutNodes = Abc_NodeMffcLabel(p->pObj);
+// printf( "Mffc with cut = %d. ", nCutNodes );
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--;
+// printf( "Mffc cut = %d. ", (int)pCut->nNodes - (int)pCut->nNodesDup );
+// printf( "\n" );
+ if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup )
+ continue;
+
+ // compute the truth table
+clk = clock();
+ pTruth = Lpk_CutTruth( p, pCut, 0 );
+ nSuppSize = Extra_TruthSupportSize(pTruth, pCut->nLeaves);
+p->timeTruth += clock() - clk;
+
+ pDsdNtk = Kit_DsdDecompose( pTruth, pCut->nLeaves );
+// Kit_DsdVerify( pDsdNtk, pTruth, pCut->nLeaves );
+ // skip 16-input non-DSD because ISOP will not work
+ if ( Kit_DsdNtkRoot(pDsdNtk)->nFans == 16 )
+ {
+ Kit_DsdNtkFree( pDsdNtk );
+ continue;
+ }
+
+ // if DSD has nodes that require splitting to fit them into LUTs
+ // we can skip those cuts that cannot lead to improvement
+ // (a full DSD network requires V = Nmin * (K-1) + 1 for improvement)
+ if ( Kit_DsdNonDsdSizeMax(pDsdNtk) > p->pPars->nLutSize &&
+ nSuppSize >= ((int)pCut->nNodes - (int)pCut->nNodesDup - 1) * (p->pPars->nLutSize - 1) + 1 )
+ {
+ Kit_DsdNtkFree( pDsdNtk );
+ continue;
+ }
+
+ if ( p->pPars->fVeryVerbose )
+ {
+// char * pFileName;
+ printf( " C%02d: L= %2d/%2d V= %2d/%d N= %d W= %4.2f ",
+ i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight );
+ Kit_DsdPrint( stdout, pDsdNtk );
+ Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves );
+// pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ );
+// printf( "Saved truth table in file \"%s\".\n", pFileName );
+ }
+
+ // update the network
+clk = clock();
+ RetValue = Lpk_ExploreCut( p, pCut, pDsdNtk );
+p->timeEval += clock() - clk;
+ Kit_DsdNtkFree( pDsdNtk );
+ if ( RetValue )
+ break;
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes supports of the cofactors of the function.]
+
+ Description [This procedure should be called after Lpk_CutTruth(p,pCut,0)]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_ComputeSupports( Lpk_Man_t * p, Lpk_Cut_t * pCut, unsigned * pTruth )
+{
+ unsigned * pTruthInv;
+ int RetValue1, RetValue2;
+ pTruthInv = Lpk_CutTruth( p, pCut, 1 );
+ RetValue1 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruth, pCut->nLeaves, p->vBddDir );
+ RetValue2 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruthInv, pCut->nLeaves, p->vBddInv );
+ if ( RetValue1 && RetValue2 )
+ Kit_TruthCofSupports( p->vBddDir, p->vBddInv, pCut->nLeaves, p->vMemory, p->puSupps );
+ else
+ p->puSupps[0] = p->puSupps[1] = 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs resynthesis for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_ResynthesizeNodeNew( Lpk_Man_t * p )
+{
+ static int Count = 0;
+ Abc_Obj_t * pObjNew, * pLeaf;
+ Lpk_Cut_t * pCut;
+ unsigned * pTruth;
+ int nNodesBef, nNodesAft, nCutNodes;
+ int i, k, clk;
+ int Required = Abc_ObjRequiredLevel(p->pObj);
+// CloudNode * pFun2;//, * pFun1;
+
+ // compute the cuts
+clk = clock();
+ if ( !Lpk_NodeCuts( p ) )
+ {
+p->timeCuts += clock() - clk;
+ return 0;
+ }
+p->timeCuts += clock() - clk;
+
+ if ( p->pPars->fVeryVerbose )
+ printf( "Node %5d : Mffc size = %5d. Cuts = %5d. Level = %2d. Req = %2d.\n",
+ p->pObj->Id, p->nMffc, p->nEvals, p->pObj->Level, Required );
+ // try the good cuts
+ p->nCutsTotal += p->nCuts;
+ p->nCutsUseful += p->nEvals;
+ for ( i = 0; i < p->nEvals; i++ )
+ {
+ // get the cut
+ pCut = p->pCuts + p->pEvals[i];
+ if ( p->pPars->fFirst && i == 1 )
+ break;
+// if ( pCut->Weight < 1.05 )
+// continue;
+
+ // skip bad cuts
+// printf( "Mffc size = %d. ", Abc_NodeMffcLabel(p->pObj) );
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++;
+ nCutNodes = Abc_NodeMffcLabel(p->pObj);
+// printf( "Mffc with cut = %d. ", nCutNodes );
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--;
+// printf( "Mffc cut = %d. ", (int)pCut->nNodes - (int)pCut->nNodesDup );
+// printf( "\n" );
+ if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup )
+ continue;
+
+ // collect nodes into the array
+ Vec_PtrClear( p->vLeaves );
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ Vec_PtrPush( p->vLeaves, Abc_NtkObj(p->pNtk, pCut->pLeaves[k]) );
+
+ // compute the truth table
+clk = clock();
+ pTruth = Lpk_CutTruth( p, pCut, 0 );
+p->timeTruth += clock() - clk;
+clk = clock();
+ Lpk_ComputeSupports( p, pCut, pTruth );
+p->timeSupps += clock() - clk;
+//clk = clock();
+// pFun1 = Lpk_CutTruthBdd( p, pCut );
+//p->timeTruth2 += clock() - clk;
+/*
+clk = clock();
+ Cloud_Restart( p->pDsdMan->dd );
+ pFun2 = Kit_TruthToCloud( p->pDsdMan->dd, pTruth, pCut->nLeaves );
+ RetValue = Kit_CreateCloud( p->pDsdMan->dd, pFun2, p->vBddNodes );
+p->timeTruth3 += clock() - clk;
+*/
+// if ( pFun1 != pFun2 )
+// printf( "Truth tables do not agree!\n" );
+// else
+// printf( "Fine!\n" );
+
+ if ( p->pPars->fVeryVerbose )
+ {
+// char * pFileName;
+ int nSuppSize = Extra_TruthSupportSize( pTruth, pCut->nLeaves );
+ printf( " C%02d: L= %2d/%2d V= %2d/%d N= %d W= %4.2f ",
+ i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight );
+ Vec_PtrForEachEntry( p->vLeaves, pLeaf, k )
+ printf( "%c=%d ", 'a'+k, Abc_ObjLevel(pLeaf) );
+ printf( "\n" );
+ Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves );
+// pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ );
+// printf( "Saved truth table in file \"%s\".\n", pFileName );
+ }
+
+ // update the network
+ nNodesBef = Abc_NtkNodeNum(p->pNtk);
+clk = clock();
+ pObjNew = Lpk_Decompose( p, p->pNtk, p->vLeaves, pTruth, p->puSupps, p->pPars->nLutSize,
+ (int)pCut->nNodes - (int)pCut->nNodesDup - 1 + (int)(p->pPars->fZeroCost > 0), Required );
+p->timeEval += clock() - clk;
+ nNodesAft = Abc_NtkNodeNum(p->pNtk);
+
+ // perform replacement
+ if ( pObjNew )
+ {
+ int nGain = (int)pCut->nNodes - (int)pCut->nNodesDup - (nNodesAft - nNodesBef);
+ assert( nGain >= 1 - p->pPars->fZeroCost );
+ assert( Abc_ObjLevel(pObjNew) <= Required );
+/*
+ if ( nGain <= 0 )
+ {
+ int x = 0;
+ }
+ if ( Abc_ObjLevel(pObjNew) > Required )
+ {
+ int x = 0;
+ }
+*/
+ p->nGainTotal += nGain;
+ p->nChanges++;
+ if ( p->pPars->fVeryVerbose )
+ printf( "Performed resynthesis: Gain = %2d. Level = %2d. Req = %2d.\n", nGain, Abc_ObjLevel(pObjNew), Required );
+ Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels );
+//printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain );
+ break;
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs resynthesis for one network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars )
+{
+ ProgressBar * pProgress;
+ Lpk_Man_t * p;
+ Abc_Obj_t * pObj;
+ double Delta;
+ int i, Iter, nNodes, nNodesPrev, clk = clock();
+ assert( Abc_NtkIsLogic(pNtk) );
+
+ // sweep dangling nodes as a preprocessing step
+ Abc_NtkSweep( pNtk, 0 );
+
+ // get the number of inputs
+ pPars->nLutSize = Abc_NtkGetFaninMax( pNtk );
+ if ( pPars->nLutSize > 6 )
+ pPars->nLutSize = 6;
+ if ( pPars->nLutSize < 3 )
+ pPars->nLutSize = 3;
+ // adjust the number of crossbars based on LUT size
+ if ( pPars->nVarsShared > pPars->nLutSize - 2 )
+ pPars->nVarsShared = pPars->nLutSize - 2;
+ // get the max number of LUTs tried
+ pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1; // V = N * (K-1) + 1
+ while ( pPars->nVarsMax > 16 )
+ {
+ pPars->nLutsMax--;
+ pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1;
+
+ }
+ if ( pPars->fVerbose )
+ {
+ printf( "Resynthesis for %d %d-LUTs with %d non-MFFC LUTs, %d crossbars, and %d-input cuts.\n",
+ pPars->nLutsMax, pPars->nLutSize, pPars->nLutsOver, pPars->nVarsShared, pPars->nVarsMax );
+ }
+
+
+ // convert into the AIG
+ if ( !Abc_NtkToAig(pNtk) )
+ {
+ fprintf( stdout, "Converting to BDD has failed.\n" );
+ return 0;
+ }
+ assert( Abc_NtkHasAig(pNtk) );
+
+ // set the number of levels
+ Abc_NtkLevel( pNtk );
+ Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel );
+
+ // start the manager
+ p = Lpk_ManStart( pPars );
+ p->pNtk = pNtk;
+ p->nNodesTotal = Abc_NtkNodeNum(pNtk);
+ p->vLevels = Vec_VecStart( pNtk->LevelMax );
+ if ( p->pPars->fSatur )
+ p->vVisited = Vec_VecStart( 0 );
+ if ( pPars->fVerbose )
+ {
+ p->nTotalNets = Abc_NtkGetTotalFanins(pNtk);
+ p->nTotalNodes = Abc_NtkNodeNum(pNtk);
+ }
+
+ // iterate over the network
+ nNodesPrev = p->nNodesTotal;
+ for ( Iter = 1; ; Iter++ )
+ {
+ // expand storage for changed nodes
+ if ( p->pPars->fSatur )
+ Vec_VecExpand( p->vVisited, Abc_NtkObjNumMax(pNtk) + 1 );
+
+ // consider all nodes
+ nNodes = Abc_NtkObjNumMax(pNtk);
+ if ( !pPars->fVeryVerbose )
+ pProgress = Extra_ProgressBarStart( stdout, nNodes );
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ // skip all except the final node
+ if ( pPars->fFirst )
+ {
+ if ( !Abc_ObjIsCo(Abc_ObjFanout0(pObj)) )
+ continue;
+ }
+ if ( i >= nNodes )
+ break;
+ if ( !pPars->fVeryVerbose )
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ // skip the nodes that did not change
+ if ( p->pPars->fSatur && !Lpk_NodeHasChanged(p, pObj->Id) )
+ continue;
+ // resynthesize
+ p->pObj = pObj;
+ if ( p->pPars->fOldAlgo )
+ Lpk_ResynthesizeNode( p );
+ else
+ Lpk_ResynthesizeNodeNew( p );
+ }
+ if ( !pPars->fVeryVerbose )
+ Extra_ProgressBarStop( pProgress );
+
+ // check the increase
+ Delta = 100.00 * (nNodesPrev - Abc_NtkNodeNum(pNtk)) / p->nNodesTotal;
+ if ( Delta < 0.05 )
+ break;
+ nNodesPrev = Abc_NtkNodeNum(pNtk);
+ if ( !p->pPars->fSatur )
+ break;
+
+ if ( pPars->fFirst )
+ break;
+ }
+ Abc_NtkStopReverseLevels( pNtk );
+
+ if ( pPars->fVerbose )
+ {
+// Cloud_PrintInfo( p->pDsdMan->dd );
+ p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk);
+ p->nTotalNodes2 = Abc_NtkNodeNum(pNtk);
+ printf( "Node gain = %5d. (%.2f %%) ",
+ p->nTotalNodes-p->nTotalNodes2, 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes );
+ printf( "Edge gain = %5d. (%.2f %%) ",
+ p->nTotalNets-p->nTotalNets2, 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets );
+ printf( "Muxes = %4d. Dsds = %4d.", p->nMuxes, p->nDsds );
+ printf( "\n" );
+ printf( "Nodes = %5d (%3d) Cuts = %5d (%4d) Changes = %5d Iter = %2d Benefit = %d.\n",
+ p->nNodesTotal, p->nNodesOver, p->nCutsTotal, p->nCutsUseful, p->nChanges, Iter, p->nBenefited );
+
+ printf( "Non-DSD:" );
+ for ( i = 3; i <= pPars->nVarsMax; i++ )
+ if ( p->nBlocks[i] )
+ printf( " %d=%d", i, p->nBlocks[i] );
+ printf( "\n" );
+
+ p->timeTotal = clock() - clk;
+ p->timeEval = p->timeEval - p->timeMap;
+ p->timeOther = p->timeTotal - p->timeCuts - p->timeTruth - p->timeEval - p->timeMap;
+ PRTP( "Cuts ", p->timeCuts, p->timeTotal );
+ PRTP( "Truth ", p->timeTruth, p->timeTotal );
+ PRTP( "CSupps", p->timeSupps, p->timeTotal );
+ PRTP( "Eval ", p->timeEval, p->timeTotal );
+ PRTP( " MuxAn", p->timeEvalMuxAn, p->timeEval );
+ PRTP( " MuxSp", p->timeEvalMuxSp, p->timeEval );
+ PRTP( " DsdAn", p->timeEvalDsdAn, p->timeEval );
+ PRTP( " DsdSp", p->timeEvalDsdSp, p->timeEval );
+ PRTP( " Other", p->timeEval-p->timeEvalMuxAn-p->timeEvalMuxSp-p->timeEvalDsdAn-p->timeEvalDsdSp, p->timeEval );
+ PRTP( "Map ", p->timeMap, p->timeTotal );
+ PRTP( "Other ", p->timeOther, p->timeTotal );
+ PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ }
+
+ Lpk_ManStop( p );
+ // check the resulting network
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ printf( "Lpk_Resynthesize: The network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkCut.c b/src/opt/lpk/lpkCut.c
new file mode 100644
index 00000000..facd330b
--- /dev/null
+++ b/src/opt/lpk/lpkCut.c
@@ -0,0 +1,683 @@
+/**CFile****************************************************************
+
+ FileName [lpkCut.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+#include "cloud.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table of one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+CloudNode * Lpk_CutTruthBdd_rec( CloudManager * dd, Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars )
+{
+ CloudNode * pTruth, * pTruth0, * pTruth1;
+ assert( !Hop_IsComplement(pObj) );
+ if ( pObj->pData )
+ {
+ assert( ((unsigned)pObj->pData) & 0xffff0000 );
+ return pObj->pData;
+ }
+ // get the plan for a new truth table
+ if ( Hop_ObjIsConst1(pObj) )
+ pTruth = dd->one;
+ else
+ {
+ assert( Hop_ObjIsAnd(pObj) );
+ // compute the truth tables of the fanins
+ pTruth0 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin0(pObj), nVars );
+ pTruth1 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin1(pObj), nVars );
+ pTruth0 = Cloud_NotCond( pTruth0, Hop_ObjFaninC0(pObj) );
+ pTruth1 = Cloud_NotCond( pTruth1, Hop_ObjFaninC1(pObj) );
+ // creat the truth table of the node
+ pTruth = Cloud_bddAnd( dd, pTruth0, pTruth1 );
+ }
+ pObj->pData = pTruth;
+ return pTruth;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies that the factoring is correct.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+CloudNode * Lpk_CutTruthBdd( Lpk_Man_t * p, Lpk_Cut_t * pCut )
+{
+ CloudManager * dd = p->pDsdMan->dd;
+ Hop_Man_t * pManHop = p->pNtk->pManFunc;
+ Hop_Obj_t * pObjHop;
+ Abc_Obj_t * pObj, * pFanin;
+ CloudNode * pTruth;
+ int i, k, iCount = 0;
+
+// return NULL;
+// Lpk_NodePrintCut( p, pCut );
+ // initialize the leaves
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+ pObj->pCopy = (Abc_Obj_t *)dd->vars[pCut->nLeaves-1-i];
+
+ // construct truth table in the topological order
+ Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i )
+ {
+ // get the local AIG
+ pObjHop = Hop_Regular(pObj->pData);
+ // clean the data field of the nodes in the AIG subgraph
+ Hop_ObjCleanData_rec( pObjHop );
+ // set the initial truth tables at the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ assert( ((unsigned)pFanin->pCopy) & 0xffff0000 );
+ Hop_ManPi( pManHop, k )->pData = pFanin->pCopy;
+ }
+ // compute the truth table of internal nodes
+ pTruth = Lpk_CutTruthBdd_rec( dd, pManHop, pObjHop, pCut->nLeaves );
+ if ( Hop_IsComplement(pObj->pData) )
+ pTruth = Cloud_Not(pTruth);
+ // set the truth table at the node
+ pObj->pCopy = (Abc_Obj_t *)pTruth;
+
+ }
+
+// Cloud_bddPrint( dd, pTruth );
+// printf( "Bdd size = %d. Total nodes = %d.\n", Cloud_DagSize( dd, pTruth ), dd->nNodesCur-dd->nVars-1 );
+ return pTruth;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth table of one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Lpk_CutTruth_rec( Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars, Vec_Ptr_t * vTtNodes, int * piCount )
+{
+ unsigned * pTruth, * pTruth0, * pTruth1;
+ assert( !Hop_IsComplement(pObj) );
+ if ( pObj->pData )
+ {
+ assert( ((unsigned)pObj->pData) & 0xffff0000 );
+ return pObj->pData;
+ }
+ // get the plan for a new truth table
+ pTruth = Vec_PtrEntry( vTtNodes, (*piCount)++ );
+ if ( Hop_ObjIsConst1(pObj) )
+ Kit_TruthFill( pTruth, nVars );
+ else
+ {
+ assert( Hop_ObjIsAnd(pObj) );
+ // compute the truth tables of the fanins
+ pTruth0 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin0(pObj), nVars, vTtNodes, piCount );
+ pTruth1 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin1(pObj), nVars, vTtNodes, piCount );
+ // creat the truth table of the node
+ Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Hop_ObjFaninC0(pObj), Hop_ObjFaninC1(pObj) );
+ }
+ pObj->pData = pTruth;
+ return pTruth;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the truth able of one cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Lpk_CutTruth( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fInv )
+{
+ Hop_Man_t * pManHop = p->pNtk->pManFunc;
+ Hop_Obj_t * pObjHop;
+ Abc_Obj_t * pObj, * pFanin;
+ unsigned * pTruth;
+ int i, k, iCount = 0;
+// Lpk_NodePrintCut( p, pCut );
+ assert( pCut->nNodes > 0 );
+
+ // initialize the leaves
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+ pObj->pCopy = Vec_PtrEntry( p->vTtElems, fInv? pCut->nLeaves-1-i : i );
+
+ // construct truth table in the topological order
+ Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i )
+ {
+ // get the local AIG
+ pObjHop = Hop_Regular(pObj->pData);
+ // clean the data field of the nodes in the AIG subgraph
+ Hop_ObjCleanData_rec( pObjHop );
+ // set the initial truth tables at the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ assert( ((unsigned)pFanin->pCopy) & 0xffff0000 );
+ Hop_ManPi( pManHop, k )->pData = pFanin->pCopy;
+ }
+ // compute the truth table of internal nodes
+ pTruth = Lpk_CutTruth_rec( pManHop, pObjHop, pCut->nLeaves, p->vTtNodes, &iCount );
+ if ( Hop_IsComplement(pObj->pData) )
+ Kit_TruthNot( pTruth, pTruth, pCut->nLeaves );
+ // set the truth table at the node
+ pObj->pCopy = (Abc_Obj_t *)pTruth;
+ }
+
+ // make sure direct truth table is stored elsewhere (assuming the first call for direct truth!!!)
+ if ( fInv == 0 )
+ {
+ pTruth = Vec_PtrEntry( p->vTtNodes, iCount++ );
+ Kit_TruthCopy( pTruth, (unsigned *)pObj->pCopy, pCut->nLeaves );
+ }
+ assert( iCount <= Vec_PtrSize(p->vTtNodes) );
+ return pTruth;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if at least one entry has changed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_NodeRecordImpact( Lpk_Man_t * p )
+{
+ Lpk_Cut_t * pCut;
+ Vec_Ptr_t * vNodes = Vec_VecEntry( p->vVisited, p->pObj->Id );
+ Abc_Obj_t * pNode;
+ int i, k;
+ // collect the nodes that impact the given node
+ Vec_PtrClear( vNodes );
+ for ( i = 0; i < p->nCuts; i++ )
+ {
+ pCut = p->pCuts + i;
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ {
+ pNode = Abc_NtkObj( p->pNtk, pCut->pLeaves[k] );
+ if ( pNode->fMarkC )
+ continue;
+ pNode->fMarkC = 1;
+ Vec_PtrPush( vNodes, (void *)pNode->Id );
+ Vec_PtrPush( vNodes, (void *)Abc_ObjFanoutNum(pNode) );
+ }
+ }
+ // clear the marks
+ Vec_PtrForEachEntry( vNodes, pNode, i )
+ {
+ pNode = Abc_NtkObj( p->pNtk, (int)pNode );
+ pNode->fMarkC = 0;
+ i++;
+ }
+//printf( "%d ", Vec_PtrSize(vNodes) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the cut has structural DSD.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_NodeCutsCheckDsd( Lpk_Man_t * p, Lpk_Cut_t * pCut )
+{
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k, nCands, fLeavesOnly, RetValue;
+ assert( pCut->nLeaves > 0 );
+ // clear ref counters
+ memset( p->pRefs, 0, sizeof(int) * pCut->nLeaves );
+ // mark cut leaves
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+ {
+ assert( pObj->fMarkA == 0 );
+ pObj->fMarkA = 1;
+ pObj->pCopy = (void *)i;
+ }
+ // ref leaves pointed from the internal nodes
+ nCands = 0;
+ Lpk_CutForEachNode( p->pNtk, pCut, pObj, i )
+ {
+ fLeavesOnly = 1;
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ if ( pFanin->fMarkA )
+ p->pRefs[(int)pFanin->pCopy]++;
+ else
+ fLeavesOnly = 0;
+ if ( fLeavesOnly )
+ p->pCands[nCands++] = pObj->Id;
+ }
+ // look at the nodes that only point to the leaves
+ RetValue = 0;
+ for ( i = 0; i < nCands; i++ )
+ {
+ pObj = Abc_NtkObj( p->pNtk, p->pCands[i] );
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ assert( pFanin->fMarkA == 1 );
+ if ( p->pRefs[(int)pFanin->pCopy] > 1 )
+ break;
+ }
+ if ( k == Abc_ObjFaninNum(pObj) )
+ {
+ RetValue = 1;
+ break;
+ }
+ }
+ // unmark cut leaves
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+ pObj->fMarkA = 0;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pDom is contained in pCut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Lpk_NodeCutsOneDominance( Lpk_Cut_t * pDom, Lpk_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 [Check if the cut exists.]
+
+ Description [Returns 1 if the cut exists.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_NodeCutsOneFilter( Lpk_Cut_t * pCuts, int nCuts, Lpk_Cut_t * pCutNew )
+{
+ Lpk_Cut_t * pCut;
+ int i, k;
+ assert( pCutNew->uSign[0] || pCutNew->uSign[1] );
+ // try to find the cut
+ for ( i = 0; i < nCuts; i++ )
+ {
+ pCut = pCuts + i;
+ if ( pCut->nLeaves == 0 )
+ continue;
+ if ( pCut->nLeaves == pCutNew->nLeaves )
+ {
+ if ( pCut->uSign[0] == pCutNew->uSign[0] && pCut->uSign[1] == pCutNew->uSign[1] )
+ {
+ for ( k = 0; k < (int)pCutNew->nLeaves; k++ )
+ if ( pCut->pLeaves[k] != pCutNew->pLeaves[k] )
+ break;
+ if ( k == (int)pCutNew->nLeaves )
+ return 1;
+ }
+ continue;
+ }
+ if ( pCut->nLeaves < pCutNew->nLeaves )
+ {
+ // skip the non-contained cuts
+ if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCut->uSign[0] )
+ continue;
+ if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCut->uSign[1] )
+ continue;
+ // check containment seriously
+ if ( Lpk_NodeCutsOneDominance( pCut, pCutNew ) )
+ return 1;
+ continue;
+ }
+ // check potential containment of other cut
+
+ // skip the non-contained cuts
+ if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCutNew->uSign[0] )
+ continue;
+ if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCutNew->uSign[1] )
+ continue;
+ // check containment seriously
+ if ( Lpk_NodeCutsOneDominance( pCutNew, pCut ) )
+ pCut->nLeaves = 0; // removed
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the given cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_NodePrintCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fLeavesOnly )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ if ( !fLeavesOnly )
+ printf( "LEAVES:\n" );
+ Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
+ printf( "%d,", pObj->Id );
+ if ( !fLeavesOnly )
+ {
+ printf( "\nNODES:\n" );
+ Lpk_CutForEachNode( p->pNtk, pCut, pObj, i )
+ {
+ printf( "%d,", pObj->Id );
+ assert( Abc_ObjIsNode(pObj) );
+ }
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Set the cut signature.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_NodeCutSignature( Lpk_Cut_t * pCut )
+{
+ unsigned i;
+ pCut->uSign[0] = pCut->uSign[1] = 0;
+ for ( i = 0; i < pCut->nLeaves; i++ )
+ {
+ pCut->uSign[(pCut->pLeaves[i] & 32) > 0] |= (1 << (pCut->pLeaves[i] & 31));
+ if ( i != pCut->nLeaves - 1 )
+ assert( pCut->pLeaves[i] < pCut->pLeaves[i+1] );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes the set of all cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_NodeCutsOne( Lpk_Man_t * p, Lpk_Cut_t * pCut, int Node )
+{
+ Lpk_Cut_t * pCutNew;
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k, j, nLeavesNew;
+/*
+ printf( "Exploring cut " );
+ Lpk_NodePrintCut( p, pCut, 1 );
+ printf( "with node %d\n", Node );
+*/
+ // check if the cut can stand adding one more internal node
+ if ( pCut->nNodes == LPK_SIZE_MAX )
+ return;
+
+ // if the node is a PI, quit
+ pObj = Abc_NtkObj( p->pNtk, Node );
+ if ( Abc_ObjIsCi(pObj) )
+ return;
+ assert( Abc_ObjIsNode(pObj) );
+// assert( Abc_ObjFaninNum(pObj) <= p->pPars->nLutSize );
+
+ // if the node is not in the MFFC, check the limit
+ if ( !Abc_NodeIsTravIdCurrent(pObj) )
+ {
+ if ( (int)pCut->nNodesDup == p->pPars->nLutsOver )
+ return;
+ assert( (int)pCut->nNodesDup < p->pPars->nLutsOver );
+ }
+
+ // check the possibility of adding this node using the signature
+ nLeavesNew = pCut->nLeaves - 1;
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ {
+ if ( (pCut->uSign[(pFanin->Id & 32) > 0] & (1 << (pFanin->Id & 31))) )
+ continue;
+ if ( ++nLeavesNew > p->pPars->nVarsMax )
+ return;
+ }
+
+ // initialize the set of leaves to the nodes in the cut
+ assert( p->nCuts < LPK_CUTS_MAX );
+ pCutNew = p->pCuts + p->nCuts;
+ pCutNew->nLeaves = 0;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ if ( pCut->pLeaves[i] != Node )
+ pCutNew->pLeaves[pCutNew->nLeaves++] = pCut->pLeaves[i];
+
+ // add new nodes
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ {
+ // find the place where this node belongs
+ for ( k = 0; k < (int)pCutNew->nLeaves; k++ )
+ if ( pCutNew->pLeaves[k] >= pFanin->Id )
+ break;
+ if ( k < (int)pCutNew->nLeaves && pCutNew->pLeaves[k] == pFanin->Id )
+ continue;
+ // check if there is room
+ if ( (int)pCutNew->nLeaves == p->pPars->nVarsMax )
+ return;
+ // move all the nodes
+ for ( j = pCutNew->nLeaves; j > k; j-- )
+ pCutNew->pLeaves[j] = pCutNew->pLeaves[j-1];
+ pCutNew->pLeaves[k] = pFanin->Id;
+ pCutNew->nLeaves++;
+ assert( pCutNew->nLeaves <= LPK_SIZE_MAX );
+
+ }
+ // skip the contained cuts
+ Lpk_NodeCutSignature( pCutNew );
+ if ( Lpk_NodeCutsOneFilter( p->pCuts, p->nCuts, pCutNew ) )
+ return;
+
+ // update the set of internal nodes
+ assert( pCut->nNodes < LPK_SIZE_MAX );
+ memcpy( pCutNew->pNodes, pCut->pNodes, pCut->nNodes * sizeof(int) );
+ pCutNew->nNodes = pCut->nNodes;
+ pCutNew->nNodesDup = pCut->nNodesDup;
+
+ // check if the node is already there
+ // if so, move the node to be the last
+ for ( i = 0; i < (int)pCutNew->nNodes; i++ )
+ if ( pCutNew->pNodes[i] == Node )
+ {
+ for ( k = i; k < (int)pCutNew->nNodes - 1; k++ )
+ pCutNew->pNodes[k] = pCutNew->pNodes[k+1];
+ pCutNew->pNodes[k] = Node;
+ break;
+ }
+ if ( i == (int)pCutNew->nNodes ) // new node
+ {
+ pCutNew->pNodes[ pCutNew->nNodes++ ] = Node;
+ pCutNew->nNodesDup += !Abc_NodeIsTravIdCurrent(pObj);
+ }
+ // the number of nodes does not exceed MFFC plus duplications
+ assert( pCutNew->nNodes <= p->nMffc + pCutNew->nNodesDup );
+ // add the cut to storage
+ assert( p->nCuts < LPK_CUTS_MAX );
+ p->nCuts++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the set of all cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_NodeCuts( Lpk_Man_t * p )
+{
+ Lpk_Cut_t * pCut, * pCut2;
+ int i, k, Temp, nMffc, fChanges;
+
+ // mark the MFFC of the node with the current trav ID
+ nMffc = p->nMffc = Abc_NodeMffcLabel( p->pObj );
+ assert( nMffc > 0 );
+ if ( nMffc == 1 )
+ return 0;
+
+ // initialize the first cut
+ pCut = p->pCuts; p->nCuts = 1;
+ pCut->nNodes = 0;
+ pCut->nNodesDup = 0;
+ pCut->nLeaves = 1;
+ pCut->pLeaves[0] = p->pObj->Id;
+ // assign the signature
+ Lpk_NodeCutSignature( pCut );
+
+ // perform the cut computation
+ for ( i = 0; i < p->nCuts; i++ )
+ {
+ pCut = p->pCuts + i;
+ if ( pCut->nLeaves == 0 )
+ continue;
+
+ // try to expand the fanins of this cut
+ for ( k = 0; k < (int)pCut->nLeaves; k++ )
+ {
+ // create a new cut
+ Lpk_NodeCutsOne( p, pCut, pCut->pLeaves[k] );
+ // quit if the number of cuts has exceeded the limit
+ if ( p->nCuts == LPK_CUTS_MAX )
+ break;
+ }
+ if ( p->nCuts == LPK_CUTS_MAX )
+ break;
+ }
+ if ( p->nCuts == LPK_CUTS_MAX )
+ p->nNodesOver++;
+
+ // record the impact of this node
+ if ( p->pPars->fSatur )
+ Lpk_NodeRecordImpact( p );
+
+ // compress the cuts by removing empty ones, those with negative Weight, and decomposable ones
+ p->nEvals = 0;
+ for ( i = 0; i < p->nCuts; i++ )
+ {
+ pCut = p->pCuts + i;
+ if ( pCut->nLeaves < 2 )
+ continue;
+ // compute the minimum number of LUTs needed to implement this cut
+ // V = N * (K-1) + 1 ~~~~~ N = Ceiling[(V-1)/(K-1)] = (V-1)/(K-1) + [(V-1)%(K-1) > 0]
+ pCut->nLuts = Lpk_LutNumLuts( pCut->nLeaves, p->pPars->nLutSize );
+// pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup - 1) / pCut->nLuts; //p->pPars->nLutsMax;
+ pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup) / pCut->nLuts; //p->pPars->nLutsMax;
+ if ( pCut->Weight <= 1.001 )
+// if ( pCut->Weight <= 0.999 )
+ continue;
+ pCut->fHasDsd = Lpk_NodeCutsCheckDsd( p, pCut );
+ if ( pCut->fHasDsd )
+ continue;
+ p->pEvals[p->nEvals++] = i;
+ }
+ if ( p->nEvals == 0 )
+ return 0;
+
+ // sort the cuts by Weight
+ do {
+ fChanges = 0;
+ for ( i = 0; i < p->nEvals - 1; i++ )
+ {
+ pCut = p->pCuts + p->pEvals[i];
+ pCut2 = p->pCuts + p->pEvals[i+1];
+ if ( pCut->Weight >= pCut2->Weight - 0.001 )
+ continue;
+ Temp = p->pEvals[i];
+ p->pEvals[i] = p->pEvals[i+1];
+ p->pEvals[i+1] = Temp;
+ fChanges = 1;
+ }
+ } while ( fChanges );
+/*
+ for ( i = 0; i < p->nEvals; i++ )
+ {
+ pCut = p->pCuts + p->pEvals[i];
+ printf( "Cut %3d : W = %5.2f.\n", i, pCut->Weight );
+ }
+ printf( "\n" );
+*/
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkInt.h b/src/opt/lpk/lpkInt.h
new file mode 100644
index 00000000..960599e4
--- /dev/null
+++ b/src/opt/lpk/lpkInt.h
@@ -0,0 +1,246 @@
+/**CFile****************************************************************
+
+ FileName [lpkInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __LPK_INT_H__
+#define __LPK_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "abc.h"
+#include "kit.h"
+#include "if.h"
+#include "lpk.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+#define LPK_SIZE_MAX 24 // the largest size of the function
+#define LPK_CUTS_MAX 512 // the largest number of cuts considered
+
+typedef struct Lpk_Man_t_ Lpk_Man_t;
+typedef struct Lpk_Cut_t_ Lpk_Cut_t;
+
+struct Lpk_Cut_t_
+{
+ unsigned nLeaves : 6; // (L) the number of leaves
+ unsigned nNodes : 6; // (M) the number of nodes
+ unsigned nNodesDup : 6; // (Q) nodes outside of MFFC
+ unsigned nLuts : 6; // (N) the number of LUTs to try
+ unsigned unused : 6; // unused
+ unsigned fHasDsd : 1; // set to 1 if the cut has structural DSD (and so cannot be used)
+ unsigned fMark : 1; // multipurpose mark
+ unsigned uSign[2]; // the signature
+ float Weight; // the weight of the cut: (M - Q)/N(V) (the larger the better)
+ int Gain; // the gain achieved using this cut
+ int pLeaves[LPK_SIZE_MAX]; // the leaves of the cut
+ int pNodes[LPK_SIZE_MAX]; // the nodes of the cut
+};
+
+struct Lpk_Man_t_
+{
+ // parameters
+ Lpk_Par_t * pPars; // the set of parameters
+ // current representation
+ Abc_Ntk_t * pNtk; // the network
+ Abc_Obj_t * pObj; // the node to resynthesize
+ // cut representation
+ int nMffc; // the size of MFFC of the node
+ int nCuts; // the total number of cuts
+ int nCutsMax; // the largest possible number of cuts
+ int nEvals; // the number of good cuts
+ Lpk_Cut_t pCuts[LPK_CUTS_MAX]; // the storage for cuts
+ int pEvals[LPK_CUTS_MAX]; // the good cuts
+ // visited nodes
+ Vec_Vec_t * vVisited;
+ // mapping manager
+ If_Man_t * pIfMan;
+ Vec_Int_t * vCover;
+ Vec_Vec_t * vLevels;
+ // temporary variables
+ int fCofactoring; // working in the cofactoring mode
+ int fCalledOnce; // limits the depth of MUX cofactoring
+ int nCalledSRed; // the number of called to SRed
+ int pRefs[LPK_SIZE_MAX]; // fanin reference counters
+ int pCands[LPK_SIZE_MAX]; // internal nodes pointing only to the leaves
+ Vec_Ptr_t * vLeaves;
+ // truth table representation
+ Vec_Ptr_t * vTtElems; // elementary truth tables
+ Vec_Ptr_t * vTtNodes; // storage for temporary truth tables of the nodes
+ Vec_Int_t * vMemory;
+ Vec_Int_t * vBddDir;
+ Vec_Int_t * vBddInv;
+ unsigned puSupps[32]; // the supports of the cofactors
+ unsigned * ppTruths[5][16];
+ // variable sets
+ Vec_Int_t * vSets[8];
+ Kit_DsdMan_t* pDsdMan;
+ // statistics
+ int nNodesTotal; // total number of nodes
+ int nNodesOver; // nodes with cuts over the limit
+ int nCutsTotal; // total number of cuts
+ int nCutsUseful; // useful cuts
+ int nGainTotal; // the gain in LUTs
+ int nChanges; // the number of changed nodes
+ int nBenefited; // the number of gainful that benefited from decomposition
+ int nMuxes;
+ int nDsds;
+ int nTotalNets;
+ int nTotalNets2;
+ int nTotalNodes;
+ int nTotalNodes2;
+ // counter of non-DSD blocks
+ int nBlocks[17];
+ // runtime
+ int timeCuts;
+ int timeTruth;
+ int timeSupps;
+ int timeTruth2;
+ int timeTruth3;
+ int timeEval;
+ int timeMap;
+ int timeOther;
+ int timeTotal;
+ // runtime of eval
+ int timeEvalMuxAn;
+ int timeEvalMuxSp;
+ int timeEvalDsdAn;
+ int timeEvalDsdSp;
+
+};
+
+
+// internal representation of the function to be decomposed
+typedef struct Lpk_Fun_t_ Lpk_Fun_t;
+struct Lpk_Fun_t_
+{
+ Vec_Ptr_t * vNodes; // the array of leaves and decomposition nodes
+ unsigned Id : 7; // the ID of this node
+ unsigned nVars : 5; // the number of variables
+ unsigned nLutK : 4; // the number of LUT inputs
+ unsigned nAreaLim : 5; // the area limit (the largest allowed)
+ unsigned nDelayLim : 9; // the delay limit (the largest allowed)
+ unsigned fSupports : 1; // supports of cofactors were precomputed
+ unsigned fMark : 1; // marks the MUX-based dec
+ unsigned uSupp; // the support of this component
+ unsigned puSupps[32]; // the supports of the cofactors
+ char pDelays[16]; // the delays of the inputs
+ char pFanins[16]; // the fanins of this function
+ unsigned pTruth[0]; // the truth table (contains room for three truth tables)
+};
+
+// preliminary decomposition result
+typedef struct Lpk_Res_t_ Lpk_Res_t;
+struct Lpk_Res_t_
+{
+ int nBSVars; // the number of bound set variables
+ unsigned BSVars; // the bound set
+ int nCofVars; // the number of cofactoring variables
+ char pCofVars[4]; // the cofactoring variables
+ int nSuppSizeS; // support size of the smaller (decomposed) function
+ int nSuppSizeL; // support size of the larger (composition) function
+ int DelayEst; // estimated delay of the decomposition
+ int AreaEst; // estimated area of the decomposition
+ int Variable; // variable in MUX decomposition
+ int Polarity; // polarity in MUX decomposition
+};
+
+static inline int Lpk_LutNumVars( int nLutsLim, int nLutK ) { return nLutsLim * (nLutK - 1) + 1; }
+static inline int Lpk_LutNumLuts( int nVarsMax, int nLutK ) { return (nVarsMax - 1) / (nLutK - 1) + (int)((nVarsMax - 1) % (nLutK - 1) > 0); }
+static inline unsigned * Lpk_FunTruth( Lpk_Fun_t * p, int Num ) { assert( Num < 3 ); return p->pTruth + Kit_TruthWordNum(p->nVars) * Num; }
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+#define Lpk_CutForEachLeaf( pNtk, pCut, pObj, i ) \
+ for ( i = 0; (i < (int)(pCut)->nLeaves) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pLeaves[i])), 1); i++ )
+#define Lpk_CutForEachNode( pNtk, pCut, pObj, i ) \
+ for ( i = 0; (i < (int)(pCut)->nNodes) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pNodes[i])), 1); i++ )
+#define Lpk_CutForEachNodeReverse( pNtk, pCut, pObj, i ) \
+ for ( i = (int)(pCut)->nNodes - 1; (i >= 0) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pNodes[i])), 1); i-- )
+#define Lpk_SuppForEachVar( Supp, Var )\
+ for ( Var = 0; Var < 16; Var++ )\
+ if ( !(Supp & (1<<Var)) ) {} else
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== lpkAbcDec.c ============================================================*/
+extern Abc_Obj_t * Lpk_Decompose( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, unsigned * puSupps, int nLutK, int AreaLim, int DelayLim );
+/*=== lpkAbcDsd.c ============================================================*/
+extern Lpk_Res_t * Lpk_DsdAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p, int nShared );
+extern Lpk_Fun_t * Lpk_DsdSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, char * pCofVars, int nCofVars, unsigned uBoundSet );
+/*=== lpkAbcMux.c ============================================================*/
+extern Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p );
+extern Lpk_Fun_t * Lpk_MuxSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, int Var, int Pol );
+/*=== lpkAbcUtil.c ============================================================*/
+extern Lpk_Fun_t * Lpk_FunAlloc( int nVars );
+extern void Lpk_FunFree( Lpk_Fun_t * p );
+extern Lpk_Fun_t * Lpk_FunCreate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, int nLutK, int AreaLim, int DelayLim );
+extern Lpk_Fun_t * Lpk_FunDup( Lpk_Fun_t * p, unsigned * pTruth );
+extern int Lpk_FunSuppMinimize( Lpk_Fun_t * p );
+extern void Lpk_FunComputeCofSupps( Lpk_Fun_t * p );
+extern int Lpk_SuppDelay( unsigned uSupp, char * pDelays );
+extern int Lpk_SuppToVars( unsigned uBoundSet, char * pVars );
+
+
+/*=== lpkCut.c =========================================================*/
+extern unsigned * Lpk_CutTruth( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fInv );
+extern int Lpk_NodeCuts( Lpk_Man_t * p );
+/*=== lpkMap.c =========================================================*/
+extern Lpk_Man_t * Lpk_ManStart( Lpk_Par_t * pPars );
+extern void Lpk_ManStop( Lpk_Man_t * p );
+/*=== lpkMap.c =========================================================*/
+extern If_Obj_t * Lpk_MapPrime( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves );
+extern If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLeaves, int iLit, If_Obj_t * pResult );
+/*=== lpkMulti.c =======================================================*/
+extern If_Obj_t * Lpk_MapTreeMulti( Lpk_Man_t * p, unsigned * pTruth, int nLeaves, If_Obj_t ** ppLeaves );
+/*=== lpkMux.c =========================================================*/
+extern If_Obj_t * Lpk_MapTreeMux_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves );
+extern If_Obj_t * Lpk_MapSuppRedDec_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves );
+/*=== lpkSets.c =========================================================*/
+extern unsigned Lpk_MapSuppRedDecSelect( Lpk_Man_t * p, unsigned * pTruth, int nVars, int * piVar, int * piVarReused );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/opt/lpk/lpkMan.c b/src/opt/lpk/lpkMan.c
new file mode 100644
index 00000000..af6a5307
--- /dev/null
+++ b/src/opt/lpk/lpkMan.c
@@ -0,0 +1,122 @@
+/**CFile****************************************************************
+
+ FileName [lpkMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Lpk_Man_t * Lpk_ManStart( Lpk_Par_t * pPars )
+{
+ Lpk_Man_t * p;
+ int i, nWords;
+ assert( pPars->nLutsMax <= 16 );
+ assert( pPars->nVarsMax > 0 && pPars->nVarsMax <= 16 );
+ p = ALLOC( Lpk_Man_t, 1 );
+ memset( p, 0, sizeof(Lpk_Man_t) );
+ p->pPars = pPars;
+ p->nCutsMax = LPK_CUTS_MAX;
+ p->vTtElems = Vec_PtrAllocTruthTables( pPars->nVarsMax );
+ p->vTtNodes = Vec_PtrAllocSimInfo( 1024, Abc_TruthWordNum(pPars->nVarsMax) );
+ p->vCover = Vec_IntAlloc( 1 << 12 );
+ p->vLeaves = Vec_PtrAlloc( 32 );
+ for ( i = 0; i < 8; i++ )
+ p->vSets[i] = Vec_IntAlloc(100);
+ p->pDsdMan = Kit_DsdManAlloc( pPars->nVarsMax, 64 );
+ p->vMemory = Vec_IntAlloc( 1024 * 32 );
+ p->vBddDir = Vec_IntAlloc( 256 );
+ p->vBddInv = Vec_IntAlloc( 256 );
+ // allocate temporary storage for truth tables
+ nWords = Kit_TruthWordNum(pPars->nVarsMax);
+ p->ppTruths[0][0] = ALLOC( unsigned, 32 * nWords );
+ p->ppTruths[1][0] = p->ppTruths[0][0] + 1 * nWords;
+ for ( i = 1; i < 2; i++ )
+ p->ppTruths[1][i] = p->ppTruths[1][0] + i * nWords;
+ p->ppTruths[2][0] = p->ppTruths[1][0] + 2 * nWords;
+ for ( i = 1; i < 4; i++ )
+ p->ppTruths[2][i] = p->ppTruths[2][0] + i * nWords;
+ p->ppTruths[3][0] = p->ppTruths[2][0] + 4 * nWords;
+ for ( i = 1; i < 8; i++ )
+ p->ppTruths[3][i] = p->ppTruths[3][0] + i * nWords;
+ p->ppTruths[4][0] = p->ppTruths[3][0] + 8 * nWords;
+ for ( i = 1; i < 16; i++ )
+ p->ppTruths[4][i] = p->ppTruths[4][0] + i * nWords;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_ManStop( Lpk_Man_t * p )
+{
+ int i;
+ free( p->ppTruths[0][0] );
+ Vec_IntFree( p->vBddDir );
+ Vec_IntFree( p->vBddInv );
+ Vec_IntFree( p->vMemory );
+ Kit_DsdManFree( p->pDsdMan );
+ for ( i = 0; i < 8; i++ )
+ Vec_IntFree(p->vSets[i]);
+ if ( p->pIfMan )
+ {
+ void * pPars = p->pIfMan->pPars;
+ If_ManStop( p->pIfMan );
+ free( pPars );
+ }
+ if ( p->vLevels )
+ Vec_VecFree( p->vLevels );
+ if ( p->vVisited )
+ Vec_VecFree( p->vVisited );
+ Vec_PtrFree( p->vLeaves );
+ Vec_IntFree( p->vCover );
+ Vec_PtrFree( p->vTtElems );
+ Vec_PtrFree( p->vTtNodes );
+ free( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkMap.c b/src/opt/lpk/lpkMap.c
new file mode 100644
index 00000000..698aeea1
--- /dev/null
+++ b/src/opt/lpk/lpkMap.c
@@ -0,0 +1,205 @@
+/**CFile****************************************************************
+
+ FileName [lpkMap.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkMap.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Transforms the decomposition graph into the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapPrimeInternal( If_Man_t * pIfMan, Kit_Graph_t * pGraph )
+{
+ Kit_Node_t * pNode;
+ If_Obj_t * pAnd0, * pAnd1;
+ int i;
+ // check for constant function
+ if ( Kit_GraphIsConst(pGraph) )
+ return If_ManConst1(pIfMan);
+ // check for a literal
+ if ( Kit_GraphIsVar(pGraph) )
+ return Kit_GraphVar(pGraph)->pFunc;
+ // build the AIG nodes corresponding to the AND gates of the graph
+ Kit_GraphForEachNode( pGraph, pNode, i )
+ {
+ pAnd0 = Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc;
+ pAnd1 = Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc;
+ pNode->pFunc = If_ManCreateAnd( pIfMan,
+ If_NotCond( If_Regular(pAnd0), If_IsComplement(pAnd0) ^ pNode->eEdge0.fCompl ),
+ If_NotCond( If_Regular(pAnd1), If_IsComplement(pAnd1) ^ pNode->eEdge1.fCompl ) );
+ }
+ return pNode->pFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Strashes one logic node using its SOP.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapPrime( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves )
+{
+ Kit_Graph_t * pGraph;
+ Kit_Node_t * pNode;
+ If_Obj_t * pRes;
+ int i;
+ // derive the factored form
+ pGraph = Kit_TruthToGraph( pTruth, nVars, p->vCover );
+ if ( pGraph == NULL )
+ return NULL;
+ // collect the fanins
+ Kit_GraphForEachLeaf( pGraph, pNode, i )
+ pNode->pFunc = ppLeaves[i];
+ // perform strashing
+ pRes = Lpk_MapPrimeInternal( p->pIfMan, pGraph );
+ pRes = If_NotCond( pRes, Kit_GraphIsComplement(pGraph) );
+ Kit_GraphFree( pGraph );
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLeaves, int iLit, If_Obj_t * pResult )
+{
+ Kit_DsdObj_t * pObj;
+ If_Obj_t * pObjNew = NULL, * pObjNew2 = NULL, * pFansNew[16];
+ unsigned i, iLitFanin;
+
+ assert( iLit >= 0 );
+
+ // consider the case of a gate
+ pObj = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iLit) );
+ if ( pObj == NULL )
+ {
+ pObjNew = ppLeaves[Kit_DsdLit2Var(iLit)];
+ return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) );
+ }
+ if ( pObj->Type == KIT_DSD_CONST1 )
+ {
+ return If_NotCond( If_ManConst1(p->pIfMan), Kit_DsdLitIsCompl(iLit) );
+ }
+ if ( pObj->Type == KIT_DSD_VAR )
+ {
+ pObjNew = ppLeaves[Kit_DsdLit2Var(pObj->pFans[0])];
+ return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ^ Kit_DsdLitIsCompl(pObj->pFans[0]) );
+ }
+ if ( pObj->Type == KIT_DSD_AND )
+ {
+ assert( pObj->nFans == 2 );
+ pFansNew[0] = Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[0], NULL );
+ pFansNew[1] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[1], NULL );
+ if ( pFansNew[0] == NULL || pFansNew[1] == NULL )
+ return NULL;
+ pObjNew = If_ManCreateAnd( p->pIfMan, pFansNew[0], pFansNew[1] );
+ return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) );
+ }
+ if ( pObj->Type == KIT_DSD_XOR )
+ {
+ int fCompl = Kit_DsdLitIsCompl(iLit);
+ assert( pObj->nFans == 2 );
+ pFansNew[0] = Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[0], NULL );
+ pFansNew[1] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[1], NULL );
+ if ( pFansNew[0] == NULL || pFansNew[1] == NULL )
+ return NULL;
+ fCompl ^= If_IsComplement(pFansNew[0]) ^ If_IsComplement(pFansNew[1]);
+ pObjNew = If_ManCreateXor( p->pIfMan, If_Regular(pFansNew[0]), If_Regular(pFansNew[1]) );
+ return If_NotCond( pObjNew, fCompl );
+ }
+ assert( pObj->Type == KIT_DSD_PRIME );
+ p->nBlocks[pObj->nFans]++;
+
+ // solve for the inputs
+ Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i )
+ {
+ if ( i == 0 )
+ pFansNew[i] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, iLitFanin, NULL );
+ else
+ pFansNew[i] = Lpk_MapTree_rec( p, pNtk, ppLeaves, iLitFanin, NULL );
+ if ( pFansNew[i] == NULL )
+ return NULL;
+ }
+/*
+ if ( !p->fCofactoring && p->pPars->nVarsShared > 0 && (int)pObj->nFans > p->pPars->nLutSize )
+ {
+ pObjNew = Lpk_MapTreeMulti( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew );
+ return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) );
+ }
+*/
+/*
+ if ( (int)pObj->nFans > p->pPars->nLutSize )
+ {
+ pObjNew2 = Lpk_MapTreeMux_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew );
+// if ( pObjNew2 )
+// return If_NotCond( pObjNew2, Kit_DsdLitIsCompl(iLit) );
+ }
+*/
+
+ // find best cofactoring variable
+ if ( p->pPars->nVarsShared > 0 && (int)pObj->nFans > p->pPars->nLutSize )
+ {
+ pObjNew2 = Lpk_MapSuppRedDec_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew );
+ if ( pObjNew2 )
+ return If_NotCond( pObjNew2, Kit_DsdLitIsCompl(iLit) );
+ }
+
+ pObjNew = Lpk_MapPrime( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew );
+
+ // add choice
+ if ( pObjNew && pObjNew2 )
+ {
+ If_ObjSetChoice( If_Regular(pObjNew), If_Regular(pObjNew2) );
+ If_ManCreateChoice( p->pIfMan, If_Regular(pObjNew) );
+ }
+ return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkMulti.c b/src/opt/lpk/lpkMulti.c
new file mode 100644
index 00000000..82cf3578
--- /dev/null
+++ b/src/opt/lpk/lpkMulti.c
@@ -0,0 +1,495 @@
+/**CFile****************************************************************
+
+ FileName [lpkMulti.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkMulti.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Records variable order.]
+
+ Description [Increaments Order[x][y] by 1 if x should be above y in the DSD.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_CreateVarOrder( Kit_DsdNtk_t * pNtk, char pTable[][16] )
+{
+ Kit_DsdObj_t * pObj;
+ unsigned uSuppFanins, k;
+ int Above[16], Below[16];
+ int nAbove, nBelow, iFaninLit, i, x, y;
+ // iterate through the nodes
+ Kit_DsdNtkForEachObj( pNtk, pObj, i )
+ {
+ // collect fanin support of this node
+ nAbove = 0;
+ uSuppFanins = 0;
+ Kit_DsdObjForEachFanin( pNtk, pObj, iFaninLit, k )
+ {
+ if ( Kit_DsdLitIsLeaf( pNtk, iFaninLit ) )
+ Above[nAbove++] = Kit_DsdLit2Var(iFaninLit);
+ else
+ uSuppFanins |= Kit_DsdLitSupport( pNtk, iFaninLit );
+ }
+ // find the below variables
+ nBelow = 0;
+ for ( y = 0; y < 16; y++ )
+ if ( uSuppFanins & (1 << y) )
+ Below[nBelow++] = y;
+ // create all pairs
+ for ( x = 0; x < nAbove; x++ )
+ for ( y = 0; y < nBelow; y++ )
+ pTable[Above[x]][Below[y]]++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates commmon variable order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_CreateCommonOrder( char pTable[][16], int piCofVar[], int nCBars, int pPrios[], int nVars, int fVerbose )
+{
+ int Score[16] = {0}, pPres[16];
+ int i, y, x, iVarBest, ScoreMax, PrioCount;
+
+ // mark the present variables
+ for ( i = 0; i < nVars; i++ )
+ pPres[i] = 1;
+ // remove cofactored variables
+ for ( i = 0; i < nCBars; i++ )
+ pPres[piCofVar[i]] = 0;
+
+ // compute scores for each leaf
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( pPres[i] == 0 )
+ continue;
+ for ( y = 0; y < nVars; y++ )
+ Score[i] += pTable[i][y];
+ for ( x = 0; x < nVars; x++ )
+ Score[i] -= pTable[x][i];
+ }
+
+ // print the scores
+ if ( fVerbose )
+ {
+ printf( "Scores: " );
+ for ( i = 0; i < nVars; i++ )
+ printf( "%c=%d ", 'a'+i, Score[i] );
+ printf( " " );
+ printf( "Prios: " );
+ }
+
+ // derive variable priority
+ // variables with equal score receive the same priority
+ for ( i = 0; i < nVars; i++ )
+ pPrios[i] = 16;
+
+ // iterate until variables remain
+ for ( PrioCount = 1; ; PrioCount++ )
+ {
+ // find the present variable with the highest score
+ iVarBest = -1;
+ ScoreMax = -100000;
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( pPres[i] == 0 )
+ continue;
+ if ( ScoreMax < Score[i] )
+ {
+ ScoreMax = Score[i];
+ iVarBest = i;
+ }
+ }
+ if ( iVarBest == -1 )
+ break;
+ // give the next priority to all vars having this score
+ if ( fVerbose )
+ printf( "%d=", PrioCount );
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( pPres[i] == 0 )
+ continue;
+ if ( Score[i] == ScoreMax )
+ {
+ pPrios[i] = PrioCount;
+ pPres[i] = 0;
+ if ( fVerbose )
+ printf( "%c", 'a'+i );
+ }
+ }
+ if ( fVerbose )
+ printf( " " );
+ }
+ if ( fVerbose )
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds components with the highest priority.]
+
+ Description [Returns the number of components selected.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_FindHighest( Kit_DsdNtk_t ** ppNtks, int * piLits, int nSize, int * pPrio, int * pDecision )
+{
+ Kit_DsdObj_t * pObj;
+ unsigned uSupps[8], uSuppFanin, uSuppTotal, uSuppLarge;
+ int i, pTriv[8], PrioMin, iVarMax, nComps, fOneNonTriv;
+
+ // find individual support and total support
+ uSuppTotal = 0;
+ for ( i = 0; i < nSize; i++ )
+ {
+ pTriv[i] = 1;
+ if ( piLits[i] < 0 )
+ uSupps[i] = 0;
+ else if ( Kit_DsdLitIsLeaf(ppNtks[i], piLits[i]) )
+ uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] );
+ else
+ {
+ pObj = Kit_DsdNtkObj( ppNtks[i], Kit_DsdLit2Var(piLits[i]) );
+ if ( pObj->Type == KIT_DSD_PRIME )
+ {
+ pTriv[i] = 0;
+ uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[0] );
+ }
+ else
+ {
+ assert( pObj->nFans == 2 );
+ if ( !Kit_DsdLitIsLeaf(ppNtks[i], pObj->pFans[0]) )
+ pTriv[i] = 0;
+ uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[1] );
+ }
+ uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] ) & ~uSuppFanin;
+ }
+ assert( uSupps[i] <= 0xFFFF );
+ uSuppTotal |= uSupps[i];
+ }
+ if ( uSuppTotal == 0 )
+ return 0;
+
+ // find one support variable with the highest priority
+ PrioMin = ABC_INFINITY;
+ iVarMax = -1;
+ for ( i = 0; i < 16; i++ )
+ if ( uSuppTotal & (1 << i) )
+ if ( PrioMin > pPrio[i] )
+ {
+ PrioMin = pPrio[i];
+ iVarMax = i;
+ }
+ assert( iVarMax != -1 );
+
+ // select components, which have this variable
+ nComps = 0;
+ fOneNonTriv = 0;
+ uSuppLarge = 0;
+ for ( i = 0; i < nSize; i++ )
+ if ( uSupps[i] & (1<<iVarMax) )
+ {
+ if ( pTriv[i] || !fOneNonTriv )
+ {
+ if ( !pTriv[i] )
+ {
+ uSuppLarge = uSupps[i];
+ fOneNonTriv = 1;
+ }
+ pDecision[i] = 1;
+ nComps++;
+ }
+ else
+ pDecision[i] = 0;
+ }
+ else
+ pDecision[i] = 0;
+
+ // add other non-trivial not-taken components whose support is contained in the current large component support
+ if ( fOneNonTriv )
+ for ( i = 0; i < nSize; i++ )
+ if ( !pTriv[i] && pDecision[i] == 0 && (uSupps[i] & ~uSuppLarge) == 0 )
+ {
+ pDecision[i] = 1;
+ nComps++;
+ }
+
+ return nComps;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapTreeMulti_rec( Lpk_Man_t * p, Kit_DsdNtk_t ** ppNtks, int * piLits, int * piCofVar, int nCBars, If_Obj_t ** ppLeaves, int nLeaves, int * pPrio )
+{
+ Kit_DsdObj_t * pObj;
+ If_Obj_t * pObjsNew[4][8], * pResPrev;
+ int piLitsNew[8], pDecision[8];
+ int i, k, nComps, nSize;
+
+ // find which of the variables is highest in the order
+ nSize = (1 << nCBars);
+ nComps = Lpk_FindHighest( ppNtks, piLits, nSize, pPrio, pDecision );
+ if ( nComps == 0 )
+ return If_Not( If_ManConst1(p->pIfMan) );
+
+ // iterate over the nodes
+ if ( p->pPars->fVeryVerbose )
+ printf( "Decision: " );
+ for ( i = 0; i < nSize; i++ )
+ {
+ if ( pDecision[i] )
+ {
+ if ( p->pPars->fVeryVerbose )
+ printf( "%d ", i );
+ assert( piLits[i] >= 0 );
+ pObj = Kit_DsdNtkObj( ppNtks[i], Kit_DsdLit2Var(piLits[i]) );
+ if ( pObj == NULL )
+ piLitsNew[i] = -2;
+ else if ( pObj->Type == KIT_DSD_PRIME )
+ piLitsNew[i] = pObj->pFans[0];
+ else
+ piLitsNew[i] = pObj->pFans[1];
+ }
+ else
+ piLitsNew[i] = piLits[i];
+ }
+ if ( p->pPars->fVeryVerbose )
+ printf( "\n" );
+
+ // call again
+ pResPrev = Lpk_MapTreeMulti_rec( p, ppNtks, piLitsNew, piCofVar, nCBars, ppLeaves, nLeaves, pPrio );
+
+ // create new set of nodes
+ for ( i = 0; i < nSize; i++ )
+ {
+ if ( pDecision[i] )
+ pObjsNew[nCBars][i] = Lpk_MapTree_rec( p, ppNtks[i], ppLeaves, piLits[i], pResPrev );
+ else if ( piLits[i] == -1 )
+ pObjsNew[nCBars][i] = If_ManConst1(p->pIfMan);
+ else if ( piLits[i] == -2 )
+ pObjsNew[nCBars][i] = If_Not( If_ManConst1(p->pIfMan) );
+ else
+ pObjsNew[nCBars][i] = pResPrev;
+ }
+
+ // create MUX using these outputs
+ for ( k = nCBars; k > 0; k-- )
+ {
+ nSize /= 2;
+ for ( i = 0; i < nSize; i++ )
+ pObjsNew[k-1][i] = If_ManCreateMux( p->pIfMan, pObjsNew[k][2*i+0], pObjsNew[k][2*i+1], ppLeaves[piCofVar[k-1]] );
+ }
+ assert( nSize == 1 );
+ return pObjsNew[0][0];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapTreeMulti( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves )
+{
+ static Counter = 0;
+ If_Obj_t * pResult;
+ Kit_DsdNtk_t * ppNtks[8] = {0}, * pTemp;
+ Kit_DsdObj_t * pRoot;
+ int piCofVar[4], pPrios[16], pFreqs[16] = {0}, piLits[16];
+ int i, k, nCBars, nSize, nMemSize;
+ unsigned * ppCofs[4][8], uSupport;
+ char pTable[16][16] = {0};
+ int fVerbose = p->pPars->fVeryVerbose;
+
+ Counter++;
+// printf( "Run %d.\n", Counter );
+
+ // allocate storage for cofactors
+ nMemSize = Kit_TruthWordNum(nVars);
+ ppCofs[0][0] = ALLOC( unsigned, 32 * nMemSize );
+ nSize = 0;
+ for ( i = 0; i < 4; i++ )
+ for ( k = 0; k < 8; k++ )
+ ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++;
+ assert( nSize == 32 );
+
+ // find the best cofactoring variables
+ nCBars = Kit_DsdCofactoring( pTruth, nVars, piCofVar, p->pPars->nVarsShared, 0 );
+// nCBars = 2;
+// piCofVar[0] = 0;
+// piCofVar[1] = 1;
+
+
+ // copy the function
+ Kit_TruthCopy( ppCofs[0][0], pTruth, nVars );
+
+ // decompose w.r.t. these variables
+ for ( k = 0; k < nCBars; k++ )
+ {
+ nSize = (1 << k);
+ for ( i = 0; i < nSize; i++ )
+ {
+ Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] );
+ Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] );
+ }
+ }
+ nSize = (1 << nCBars);
+ // compute DSD networks
+ for ( i = 0; i < nSize; i++ )
+ {
+ ppNtks[i] = Kit_DsdDecompose( ppCofs[nCBars][i], nVars );
+ ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] );
+ Kit_DsdNtkFree( pTemp );
+ if ( fVerbose )
+ {
+ printf( "Cof%d%d: ", nCBars, i );
+ Kit_DsdPrint( stdout, ppNtks[i] );
+ }
+ }
+
+ // compute variable frequences
+ for ( i = 0; i < nSize; i++ )
+ {
+ uSupport = Kit_TruthSupport( ppCofs[nCBars][i], nVars );
+ for ( k = 0; k < nVars; k++ )
+ if ( uSupport & (1<<k) )
+ pFreqs[k]++;
+ }
+
+ // find common variable order
+ for ( i = 0; i < nSize; i++ )
+ {
+ Kit_DsdGetSupports( ppNtks[i] );
+ Lpk_CreateVarOrder( ppNtks[i], pTable );
+ }
+ Lpk_CreateCommonOrder( pTable, piCofVar, nCBars, pPrios, nVars, fVerbose );
+ // update priorities with frequences
+ for ( i = 0; i < nVars; i++ )
+ pPrios[i] = pPrios[i] * 256 + (16 - pFreqs[i]) * 16 + i;
+
+ if ( fVerbose )
+ printf( "After restructuring with priority:\n" );
+
+ if ( Counter == 1 )
+ {
+ int x = 0;
+ }
+ // transform all networks according to the variable order
+ for ( i = 0; i < nSize; i++ )
+ {
+ ppNtks[i] = Kit_DsdShrink( pTemp = ppNtks[i], pPrios );
+ Kit_DsdNtkFree( pTemp );
+ Kit_DsdGetSupports( ppNtks[i] );
+ assert( ppNtks[i]->pSupps[0] <= 0xFFFF );
+ // undec nodes should be rotated in such a way that the first input has as many shared inputs as possible
+ Kit_DsdRotate( ppNtks[i], pFreqs );
+ // print the resulting networks
+ if ( fVerbose )
+ {
+ printf( "Cof%d%d: ", nCBars, i );
+ Kit_DsdPrint( stdout, ppNtks[i] );
+ }
+ }
+
+ for ( i = 0; i < nSize; i++ )
+ {
+ // collect the roots
+ pRoot = Kit_DsdNtkRoot(ppNtks[i]);
+ if ( pRoot->Type == KIT_DSD_CONST1 )
+ piLits[i] = Kit_DsdLitIsCompl(ppNtks[i]->Root)? -2: -1;
+ else if ( pRoot->Type == KIT_DSD_VAR )
+ piLits[i] = Kit_DsdLitNotCond( pRoot->pFans[0], Kit_DsdLitIsCompl(ppNtks[i]->Root) );
+ else
+ piLits[i] = ppNtks[i]->Root;
+ }
+
+
+ // recursively construct AIG for mapping
+ p->fCofactoring = 1;
+ pResult = Lpk_MapTreeMulti_rec( p, ppNtks, piLits, piCofVar, nCBars, ppLeaves, nVars, pPrios );
+ p->fCofactoring = 0;
+
+ if ( fVerbose )
+ printf( "\n" );
+
+ // verify the transformations
+ nSize = (1 << nCBars);
+ for ( i = 0; i < nSize; i++ )
+ Kit_DsdTruth( ppNtks[i], ppCofs[nCBars][i] );
+ // mux the truth tables
+ for ( k = nCBars-1; k >= 0; k-- )
+ {
+ nSize = (1 << k);
+ for ( i = 0; i < nSize; i++ )
+ Kit_TruthMuxVar( ppCofs[k][i], ppCofs[k+1][2*i+0], ppCofs[k+1][2*i+1], nVars, piCofVar[k] );
+ }
+ if ( !Extra_TruthIsEqual( pTruth, ppCofs[0][0], nVars ) )
+ printf( "Verification failed.\n" );
+
+
+ // free the networks
+ for ( i = 0; i < 8; i++ )
+ if ( ppNtks[i] )
+ Kit_DsdNtkFree( ppNtks[i] );
+ free( ppCofs[0][0] );
+
+ return pResult;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkMux.c b/src/opt/lpk/lpkMux.c
new file mode 100644
index 00000000..ed046ad7
--- /dev/null
+++ b/src/opt/lpk/lpkMux.c
@@ -0,0 +1,247 @@
+/**CFile****************************************************************
+
+ FileName [lpkMux.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkMux.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Find the best cofactoring variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Lpk_MapTreeBestCofVar( Lpk_Man_t * p, unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 )
+{
+ int i, iBestVar, nSuppSizeCur0, nSuppSizeCur1, nSuppSizeCur, nSuppSizeMin;
+ // iterate through variables
+ iBestVar = -1;
+ nSuppSizeMin = KIT_INFINITY;
+ for ( i = 0; i < nVars; i++ )
+ {
+ // cofactor the functiona and get support sizes
+ Kit_TruthCofactor0New( pCof0, pTruth, nVars, i );
+ Kit_TruthCofactor1New( pCof1, pTruth, nVars, i );
+ nSuppSizeCur0 = Kit_TruthSupportSize( pCof0, nVars );
+ nSuppSizeCur1 = Kit_TruthSupportSize( pCof1, nVars );
+ nSuppSizeCur = nSuppSizeCur0 + nSuppSizeCur1;
+ // skip cofactoring that goes above the limit
+ if ( nSuppSizeCur0 > p->pPars->nLutSize || nSuppSizeCur1 > p->pPars->nLutSize )
+ continue;
+ // compare this variable with other variables
+ if ( nSuppSizeMin > nSuppSizeCur )
+ {
+ nSuppSizeMin = nSuppSizeCur;
+ iBestVar = i;
+ }
+ }
+ // cofactor w.r.t. this variable
+ if ( iBestVar != -1 )
+ {
+ Kit_TruthCofactor0New( pCof0, pTruth, nVars, iBestVar );
+ Kit_TruthCofactor1New( pCof1, pTruth, nVars, iBestVar );
+ }
+ return iBestVar;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Maps the function by the best cofactoring.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapTreeMux_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves )
+{
+ unsigned * pCof0 = Vec_PtrEntry( p->vTtNodes, 0 );
+ unsigned * pCof1 = Vec_PtrEntry( p->vTtNodes, 1 );
+ If_Obj_t * pObj0, * pObj1;
+ Kit_DsdNtk_t * ppNtks[2];
+ int iBestVar;
+ assert( nVars > 3 );
+ p->fCalledOnce = 1;
+ // cofactor w.r.t. the best variable
+ iBestVar = Lpk_MapTreeBestCofVar( p, pTruth, nVars, pCof0, pCof1 );
+ if ( iBestVar == -1 )
+ return NULL;
+ // decompose the functions
+ ppNtks[0] = Kit_DsdDecompose( pCof0, nVars );
+ ppNtks[1] = Kit_DsdDecompose( pCof1, nVars );
+ if ( p->pPars->fVeryVerbose )
+ {
+ printf( "Cofactoring w.r.t. var %c (%d -> %d+%d supp vars):\n",
+ 'a'+iBestVar, nVars, Kit_TruthSupportSize(pCof0, nVars), Kit_TruthSupportSize(pCof1, nVars) );
+ Kit_DsdPrintExpanded( ppNtks[0] );
+ Kit_DsdPrintExpanded( ppNtks[1] );
+ }
+ // map the DSD structures
+ pObj0 = Lpk_MapTree_rec( p, ppNtks[0], ppLeaves, ppNtks[0]->Root, NULL );
+ pObj1 = Lpk_MapTree_rec( p, ppNtks[1], ppLeaves, ppNtks[1]->Root, NULL );
+ Kit_DsdNtkFree( ppNtks[0] );
+ Kit_DsdNtkFree( ppNtks[1] );
+ return If_ManCreateMux( p->pIfMan, pObj0, pObj1, ppLeaves[iBestVar] );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Implements support-reducing decomposition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+If_Obj_t * Lpk_MapSuppRedDec_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves )
+{
+ Kit_DsdNtk_t * pNtkDec, * pNtkComp, * ppNtks[2], * pTemp;
+ If_Obj_t * pObjNew;
+ unsigned * pCof0 = Vec_PtrEntry( p->vTtNodes, 0 );
+ unsigned * pCof1 = Vec_PtrEntry( p->vTtNodes, 1 );
+ unsigned * pDec0 = Vec_PtrEntry( p->vTtNodes, 2 );
+ unsigned * pDec1 = Vec_PtrEntry( p->vTtNodes, 3 );
+ unsigned * pDec = Vec_PtrEntry( p->vTtNodes, 4 );
+ unsigned * pCo00 = Vec_PtrEntry( p->vTtNodes, 5 );
+ unsigned * pCo01 = Vec_PtrEntry( p->vTtNodes, 6 );
+ unsigned * pCo10 = Vec_PtrEntry( p->vTtNodes, 7 );
+ unsigned * pCo11 = Vec_PtrEntry( p->vTtNodes, 8 );
+ unsigned * pCo0 = Vec_PtrEntry( p->vTtNodes, 9 );
+ unsigned * pCo1 = Vec_PtrEntry( p->vTtNodes, 10 );
+ unsigned * pCo = Vec_PtrEntry( p->vTtNodes, 11 );
+ int TrueMint0, TrueMint1, FalseMint0, FalseMint1;
+ int uSubsets, uSubset0, uSubset1, iVar, iVarReused, i;
+
+ // determine if supp-red decomposition exists
+ uSubsets = Lpk_MapSuppRedDecSelect( p, pTruth, nVars, &iVar, &iVarReused );
+ if ( uSubsets == 0 )
+ return NULL;
+ p->nCalledSRed++;
+
+ // get the cofactors
+ Kit_TruthCofactor0New( pCof0, pTruth, nVars, iVar );
+ Kit_TruthCofactor1New( pCof1, pTruth, nVars, iVar );
+
+ // get the bound sets
+ uSubset0 = uSubsets & 0xFFFF;
+ uSubset1 = uSubsets >> 16;
+
+ // compute the decomposed functions
+ ppNtks[0] = Kit_DsdDecompose( pCof0, nVars );
+ ppNtks[1] = Kit_DsdDecompose( pCof1, nVars );
+ ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); Kit_DsdNtkFree( pTemp );
+ ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] ); Kit_DsdNtkFree( pTemp );
+ Kit_DsdTruthPartial( p->pDsdMan, ppNtks[0], pDec0, uSubset0 );
+ Kit_DsdTruthPartial( p->pDsdMan, ppNtks[1], pDec1, uSubset1 );
+// Kit_DsdTruthPartialTwo( p->pDsdMan, ppNtks[0], uSubset0, iVarReused, pCo0, pDec0 );
+// Kit_DsdTruthPartialTwo( p->pDsdMan, ppNtks[1], uSubset1, iVarReused, pCo1, pDec1 );
+ Kit_DsdNtkFree( ppNtks[0] );
+ Kit_DsdNtkFree( ppNtks[1] );
+//Kit_DsdPrintFromTruth( pDec0, nVars );
+//Kit_DsdPrintFromTruth( pDec1, nVars );
+ // get the decomposed function
+ Kit_TruthMuxVar( pDec, pDec0, pDec1, nVars, iVar );
+
+ // find any true assignments of the decomposed functions
+ TrueMint0 = Kit_TruthFindFirstBit( pDec0, nVars );
+ TrueMint1 = Kit_TruthFindFirstBit( pDec1, nVars );
+ assert( TrueMint0 >= 0 && TrueMint1 >= 0 );
+ // find any false assignments of the decomposed functions
+ FalseMint0 = Kit_TruthFindFirstZero( pDec0, nVars );
+ FalseMint1 = Kit_TruthFindFirstZero( pDec1, nVars );
+ assert( FalseMint0 >= 0 && FalseMint1 >= 0 );
+
+ // cofactor the cofactors according to these minterms
+ Kit_TruthCopy( pCo00, pCof0, nVars );
+ Kit_TruthCopy( pCo01, pCof0, nVars );
+ for ( i = 0; i < nVars; i++ )
+ if ( uSubset0 & (1 << i) )
+ {
+ if ( FalseMint0 & (1 << i) )
+ Kit_TruthCofactor1( pCo00, nVars, i );
+ else
+ Kit_TruthCofactor0( pCo00, nVars, i );
+ if ( TrueMint0 & (1 << i) )
+ Kit_TruthCofactor1( pCo01, nVars, i );
+ else
+ Kit_TruthCofactor0( pCo01, nVars, i );
+ }
+ Kit_TruthCopy( pCo10, pCof1, nVars );
+ Kit_TruthCopy( pCo11, pCof1, nVars );
+ for ( i = 0; i < nVars; i++ )
+ if ( uSubset1 & (1 << i) )
+ {
+ if ( FalseMint1 & (1 << i) )
+ Kit_TruthCofactor1( pCo10, nVars, i );
+ else
+ Kit_TruthCofactor0( pCo10, nVars, i );
+ if ( TrueMint1 & (1 << i) )
+ Kit_TruthCofactor1( pCo11, nVars, i );
+ else
+ Kit_TruthCofactor0( pCo11, nVars, i );
+ }
+
+ // derive the functions by composing them with the new variable (iVarReused)
+ Kit_TruthMuxVar( pCo0, pCo00, pCo01, nVars, iVarReused );
+ Kit_TruthMuxVar( pCo1, pCo10, pCo11, nVars, iVarReused );
+//Kit_DsdPrintFromTruth( pCo0, nVars );
+//Kit_DsdPrintFromTruth( pCo1, nVars );
+
+ // derive the composition function
+ Kit_TruthMuxVar( pCo , pCo0 , pCo1 , nVars, iVar );
+
+ // process the decomposed function
+ pNtkDec = Kit_DsdDecompose( pDec, nVars );
+ pNtkComp = Kit_DsdDecompose( pCo, nVars );
+//Kit_DsdPrint( stdout, pNtkDec );
+//Kit_DsdPrint( stdout, pNtkComp );
+//printf( "cofactored variable %c\n", 'a' + iVar );
+//printf( "reused variable %c\n", 'a' + iVarReused );
+
+ ppLeaves[iVarReused] = Lpk_MapTree_rec( p, pNtkDec, ppLeaves, pNtkDec->Root, NULL );
+ pObjNew = Lpk_MapTree_rec( p, pNtkComp, ppLeaves, pNtkComp->Root, NULL );
+
+ Kit_DsdNtkFree( pNtkDec );
+ Kit_DsdNtkFree( pNtkComp );
+ return pObjNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpkSets.c b/src/opt/lpk/lpkSets.c
new file mode 100644
index 00000000..90e46863
--- /dev/null
+++ b/src/opt/lpk/lpkSets.c
@@ -0,0 +1,440 @@
+/**CFile****************************************************************
+
+ FileName [lpkSets.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpkSets.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Lpk_Set_t_ Lpk_Set_t;
+struct Lpk_Set_t_
+{
+ char iVar; // the cofactoring variable
+ char Over; // the overlap in supports
+ char SRed; // the support reduction
+ char Size; // the size of the boundset
+ unsigned uSubset0; // the first subset (with removed)
+ unsigned uSubset1; // the second subset (with removed)
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes decomposable subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Lpk_ComputeSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets )
+{
+ unsigned i, iLitFanin, uSupport, uSuppCur;
+ Kit_DsdObj_t * pObj;
+ // consider the case of simple gate
+ pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) );
+ if ( pObj == NULL )
+ return (1 << Kit_DsdLit2Var(iLit));
+ if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR )
+ {
+ unsigned uSupps[16], Limit, s;
+ uSupport = 0;
+ Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+ {
+ uSupps[i] = Lpk_ComputeSets_rec( p, iLitFanin, vSets );
+ uSupport |= uSupps[i];
+ }
+ // create all subsets, except empty and full
+ Limit = (1 << pObj->nFans) - 1;
+ for ( s = 1; s < Limit; s++ )
+ {
+ uSuppCur = 0;
+ for ( i = 0; i < pObj->nFans; i++ )
+ if ( s & (1 << i) )
+ uSuppCur |= uSupps[i];
+ Vec_IntPush( vSets, uSuppCur );
+ }
+ return uSupport;
+ }
+ assert( pObj->Type == KIT_DSD_PRIME );
+ // get the cumulative support of all fanins
+ uSupport = 0;
+ Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i )
+ {
+ uSuppCur = Lpk_ComputeSets_rec( p, iLitFanin, vSets );
+ uSupport |= uSuppCur;
+ Vec_IntPush( vSets, uSuppCur );
+ }
+ return uSupport;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the set of subsets of decomposable variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Lpk_ComputeSets( Kit_DsdNtk_t * p, Vec_Int_t * vSets )
+{
+ unsigned uSupport, Entry;
+ int Number, i;
+ assert( p->nVars <= 16 );
+ Vec_IntClear( vSets );
+ Vec_IntPush( vSets, 0 );
+ if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 )
+ return 0;
+ if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR )
+ {
+ uSupport = ( 1 << Kit_DsdLit2Var(Kit_DsdNtkRoot(p)->pFans[0]) );
+ Vec_IntPush( vSets, uSupport );
+ return uSupport;
+ }
+ uSupport = Lpk_ComputeSets_rec( p, p->Root, vSets );
+ assert( (uSupport & 0xFFFF0000) == 0 );
+ Vec_IntPush( vSets, uSupport );
+ // set the remaining variables
+ Vec_IntForEachEntry( vSets, Number, i )
+ {
+ Entry = Number;
+ Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) );
+ }
+ return uSupport;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the sets of subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Lpk_PrintSetOne( int uSupport )
+{
+ unsigned k;
+ for ( k = 0; k < 16; k++ )
+ if ( uSupport & (1<<k) )
+ printf( "%c", 'a'+k );
+ printf( " " );
+}
+/**Function*************************************************************
+
+ Synopsis [Prints the sets of subsets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Lpk_PrintSets( Vec_Int_t * vSets )
+{
+ unsigned uSupport;
+ int Number, i;
+ printf( "Subsets(%d): ", Vec_IntSize(vSets) );
+ Vec_IntForEachEntry( vSets, Number, i )
+ {
+ uSupport = Number;
+ Lpk_PrintSetOne( uSupport );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes maximal support reducing bound-sets.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_ComposeSets( Vec_Int_t * vSets0, Vec_Int_t * vSets1, int nVars, int iCofVar,
+ Lpk_Set_t * pStore, int * pSize, int nSizeLimit )
+{
+ static int nTravId = 0; // the number of the times this is visited
+ static int TravId[1<<16] = {0}; // last visited
+ static char SRed[1<<16]; // best support reduction
+ static char Over[1<<16]; // best overlaps
+ static unsigned Parents[1<<16]; // best set of parents
+ static unsigned short Used[1<<16]; // storage for used subsets
+ int nSuppSize, nSuppOver, nSuppRed, nUsed, nMinOver, i, k, s;
+ unsigned Entry, Entry0, Entry1;
+ unsigned uSupp, uSupp0, uSupp1, uSuppTotal;
+ Lpk_Set_t * pEntry;
+
+ if ( nTravId == (1 << 30) )
+ memset( TravId, 0, sizeof(int) * (1 << 16) );
+
+ // collect support reducing subsets
+ nUsed = 0;
+ nTravId++;
+ uSuppTotal = Kit_BitMask(nVars) & ~(1<<iCofVar);
+ Vec_IntForEachEntry( vSets0, Entry0, i )
+ Vec_IntForEachEntry( vSets1, Entry1, k )
+ {
+ uSupp0 = (Entry0 & 0xFFFF);
+ uSupp1 = (Entry1 & 0xFFFF);
+ // skip trivial
+ if ( uSupp0 == 0 || uSupp1 == 0 || (uSupp0 | uSupp1) == uSuppTotal )
+ continue;
+ if ( Kit_WordHasOneBit(uSupp0) && Kit_WordHasOneBit(uSupp1) )
+ continue;
+ // get the entry
+ Entry = Entry0 | Entry1;
+ uSupp = Entry & 0xFFFF;
+ // set the bound set size
+ nSuppSize = Kit_WordCountOnes( uSupp );
+ // get the number of overlapping vars
+ nSuppOver = Kit_WordCountOnes( Entry & (Entry >> 16) );
+ // get the support reduction
+ nSuppRed = nSuppSize - 1 - nSuppOver;
+ // only consider support-reducing subsets
+ if ( nSuppRed <= 0 )
+ continue;
+ // check if this support is already used
+ if ( TravId[uSupp] < nTravId )
+ {
+ Used[nUsed++] = uSupp;
+
+ TravId[uSupp] = nTravId;
+ SRed[uSupp] = nSuppRed;
+ Over[uSupp] = nSuppOver;
+ Parents[uSupp] = (k << 16) | i;
+ }
+ else if ( TravId[uSupp] == nTravId && SRed[uSupp] < nSuppRed )
+ {
+ TravId[uSupp] = nTravId;
+ SRed[uSupp] = nSuppRed;
+ Over[uSupp] = nSuppOver;
+ Parents[uSupp] = (k << 16) | i;
+ }
+ }
+
+ // find the minimum overlap
+ nMinOver = 1000;
+ for ( s = 0; s < nUsed; s++ )
+ if ( nMinOver > Over[Used[s]] )
+ nMinOver = Over[Used[s]];
+
+
+ // collect the accumulated ones
+ for ( s = 0; s < nUsed; s++ )
+ if ( Over[Used[s]] == nMinOver )
+ {
+ // save the entry
+ if ( *pSize == nSizeLimit )
+ return;
+ pEntry = pStore + (*pSize)++;
+
+ i = Parents[Used[s]] & 0xFFFF;
+ k = Parents[Used[s]] >> 16;
+
+ pEntry->uSubset0 = Vec_IntEntry(vSets0, i);
+ pEntry->uSubset1 = Vec_IntEntry(vSets1, k);
+ Entry = pEntry->uSubset0 | pEntry->uSubset1;
+
+ // record the cofactoring variable
+ pEntry->iVar = iCofVar;
+ // set the bound set size
+ pEntry->Size = Kit_WordCountOnes( Entry & 0xFFFF );
+ // get the number of overlapping vars
+ pEntry->Over = Kit_WordCountOnes( Entry & (Entry >> 16) );
+ // get the support reduction
+ pEntry->SRed = pEntry->Size - 1 - pEntry->Over;
+ assert( pEntry->SRed > 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints one set.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lpk_MapSuppPrintSet( Lpk_Set_t * pSet, int i )
+{
+ unsigned Entry;
+ Entry = pSet->uSubset0 | pSet->uSubset1;
+ printf( "%2d : ", i );
+ printf( "Var = %c ", 'a' + pSet->iVar );
+ printf( "Size = %2d ", pSet->Size );
+ printf( "Over = %2d ", pSet->Over );
+ printf( "SRed = %2d ", pSet->SRed );
+ Lpk_PrintSetOne( Entry );
+ printf( " " );
+ Lpk_PrintSetOne( Entry >> 16 );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Evaluates the cofactors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Lpk_MapSuppRedDecSelect( Lpk_Man_t * p, unsigned * pTruth, int nVars, int * piVar, int * piVarReused )
+{
+ static int nStoreSize = 256;
+ static Lpk_Set_t pStore[256], * pSet, * pSetBest;
+ Kit_DsdNtk_t * ppNtks[2], * pTemp;
+ Vec_Int_t * vSets0 = p->vSets[0];
+ Vec_Int_t * vSets1 = p->vSets[1];
+ unsigned * pCof0 = Vec_PtrEntry( p->vTtNodes, 0 );
+ unsigned * pCof1 = Vec_PtrEntry( p->vTtNodes, 1 );
+ int nSets, i, SizeMax;//, SRedMax;
+ unsigned Entry;
+ int fVerbose = p->pPars->fVeryVerbose;
+// int fVerbose = 0;
+
+ // collect decomposable subsets for each pair of cofactors
+ if ( fVerbose )
+ {
+ printf( "\nExploring support-reducing bound-sets of function:\n" );
+ Kit_DsdPrintFromTruth( pTruth, nVars );
+ }
+ nSets = 0;
+ for ( i = 0; i < nVars; i++ )
+ {
+ if ( fVerbose )
+ printf( "Evaluating variable %c:\n", 'a'+i );
+ // evaluate the cofactor pair
+ Kit_TruthCofactor0New( pCof0, pTruth, nVars, i );
+ Kit_TruthCofactor1New( pCof1, pTruth, nVars, i );
+ // decompose and expand
+ ppNtks[0] = Kit_DsdDecompose( pCof0, nVars );
+ ppNtks[1] = Kit_DsdDecompose( pCof1, nVars );
+ ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); Kit_DsdNtkFree( pTemp );
+ ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] ); Kit_DsdNtkFree( pTemp );
+ if ( fVerbose )
+ Kit_DsdPrint( stdout, ppNtks[0] );
+ if ( fVerbose )
+ Kit_DsdPrint( stdout, ppNtks[1] );
+ // compute subsets
+ Lpk_ComputeSets( ppNtks[0], vSets0 );
+ Lpk_ComputeSets( ppNtks[1], vSets1 );
+ // print subsets
+ if ( fVerbose )
+ Lpk_PrintSets( vSets0 );
+ if ( fVerbose )
+ Lpk_PrintSets( vSets1 );
+ // free the networks
+ Kit_DsdNtkFree( ppNtks[0] );
+ Kit_DsdNtkFree( ppNtks[1] );
+ // evaluate the pair
+ Lpk_ComposeSets( vSets0, vSets1, nVars, i, pStore, &nSets, nStoreSize );
+ }
+
+ // print the results
+ if ( fVerbose )
+ printf( "\n" );
+ if ( fVerbose )
+ for ( i = 0; i < nSets; i++ )
+ Lpk_MapSuppPrintSet( pStore + i, i );
+
+ // choose the best subset
+ SizeMax = 0;
+ pSetBest = NULL;
+ for ( i = 0; i < nSets; i++ )
+ {
+ pSet = pStore + i;
+ if ( pSet->Size > p->pPars->nLutSize - 1 )
+ continue;
+ if ( SizeMax < pSet->Size )
+ {
+ pSetBest = pSet;
+ SizeMax = pSet->Size;
+ }
+ }
+/*
+ // if the best is not choosen, select the one with largest reduction
+ SRedMax = 0;
+ if ( pSetBest == NULL )
+ {
+ for ( i = 0; i < nSets; i++ )
+ {
+ pSet = pStore + i;
+ if ( SRedMax < pSet->SRed )
+ {
+ pSetBest = pSet;
+ SRedMax = pSet->SRed;
+ }
+ }
+ }
+*/
+ if ( pSetBest == NULL )
+ {
+ if ( fVerbose )
+ printf( "Could not select a subset.\n" );
+ return 0;
+ }
+ else
+ {
+ if ( fVerbose )
+ printf( "Selected the following subset:\n" );
+ if ( fVerbose )
+ Lpk_MapSuppPrintSet( pSetBest, pSetBest - pStore );
+ }
+
+ // prepare the return result
+ // get the remaining variables
+ Entry = ((pSetBest->uSubset0 >> 16) | (pSetBest->uSubset1 >> 16));
+ // get the variables to be removed
+ Entry = Kit_BitMask(nVars) & ~(1<<pSetBest->iVar) & ~Entry;
+ // make sure there are some - otherwise it is not supp-red
+ assert( Entry );
+ // remember the first such variable
+ *piVarReused = Kit_WordFindFirstBit( Entry );
+ *piVar = pSetBest->iVar;
+ return (pSetBest->uSubset1 << 16) | (pSetBest->uSubset0 & 0xFFFF);
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/lpk_.c b/src/opt/lpk/lpk_.c
new file mode 100644
index 00000000..d8555e08
--- /dev/null
+++ b/src/opt/lpk/lpk_.c
@@ -0,0 +1,48 @@
+/**CFile****************************************************************
+
+ FileName [lpk_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Fast Boolean matching for LUT structures.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: lpk_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "lpkInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/lpk/module.make b/src/opt/lpk/module.make
new file mode 100644
index 00000000..26a54894
--- /dev/null
+++ b/src/opt/lpk/module.make
@@ -0,0 +1,11 @@
+SRC += src/opt/lpk/lpkCore.c \
+ src/opt/lpk/lpkAbcDec.c \
+ src/opt/lpk/lpkAbcMux.c \
+ src/opt/lpk/lpkAbcDsd.c \
+ src/opt/lpk/lpkAbcUtil.c \
+ src/opt/lpk/lpkCut.c \
+ src/opt/lpk/lpkMan.c \
+ src/opt/lpk/lpkMap.c \
+ src/opt/lpk/lpkMulti.c \
+ src/opt/lpk/lpkMux.c \
+ src/opt/lpk/lpkSets.c
diff --git a/src/opt/res/module.make b/src/opt/res/module.make
new file mode 100644
index 00000000..52d8a315
--- /dev/null
+++ b/src/opt/res/module.make
@@ -0,0 +1,7 @@
+SRC += src/opt/res/resCore.c \
+ src/opt/res/resDivs.c \
+ src/opt/res/resFilter.c \
+ src/opt/res/resSat.c \
+ src/opt/res/resSim.c \
+ src/opt/res/resStrash.c \
+ src/opt/res/resWin.c
diff --git a/src/opt/res/res.h b/src/opt/res/res.h
new file mode 100644
index 00000000..3c3431bf
--- /dev/null
+++ b/src/opt/res/res.h
@@ -0,0 +1,75 @@
+/**CFile****************************************************************
+
+ FileName [res.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: res.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __RES_H__
+#define __RES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Res_Par_t_ Res_Par_t;
+struct Res_Par_t_
+{
+ // general parameters
+ int nWindow; // window size
+ int nGrowthLevel; // the maximum allowed growth in level after one iteration of resynthesis
+ int nSimWords; // the number of simulation words
+ int nCands; // the number of candidates to try
+ int fArea; // performs optimization for area
+ int fDelay; // performs optimization for delay
+ int fVerbose; // enable basic stats
+ int fVeryVerbose; // enable detailed stats
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== resCore.c ==========================================================*/
+extern int Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/opt/res/resCore.c b/src/opt/res/resCore.c
new file mode 100644
index 00000000..cb448fc0
--- /dev/null
+++ b/src/opt/res/resCore.c
@@ -0,0 +1,419 @@
+/**CFile****************************************************************
+
+ FileName [resCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Top-level resynthesis procedure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resCore.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+#include "kit.h"
+#include "satStore.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Res_Man_t_ Res_Man_t;
+struct Res_Man_t_
+{
+ // general parameters
+ Res_Par_t * pPars;
+ // specialized manager
+ Res_Win_t * pWin; // windowing manager
+ Abc_Ntk_t * pAig; // the strashed window
+ Res_Sim_t * pSim; // simulation manager
+ Sto_Man_t * pCnf; // the CNF of the SAT problem
+ Int_Man_t * pMan; // interpolation manager;
+ Vec_Int_t * vMem; // memory for intermediate SOPs
+ Vec_Vec_t * vResubs; // resubstitution candidates of the AIG
+ Vec_Vec_t * vResubsW; // resubstitution candidates of the window
+ Vec_Vec_t * vLevels; // levelized structure for updating
+ // statistics
+ int nWins; // the number of windows tried
+ int nWinNodes; // the total number of window nodes
+ int nDivNodes; // the total number of divisors
+ int nWinsTriv; // the total number of trivial windows
+ int nWinsUsed; // the total number of useful windows (with at least one candidate)
+ int nConstsUsed; // the total number of constant nodes under ODC
+ int nCandSets; // the total number of candidates
+ int nProvedSets; // the total number of proved groups
+ int nSimEmpty; // the empty simulation info
+ int nTotalNets; // the total number of nets
+ int nTotalNodes; // the total number of nodess
+ int nTotalNets2; // the total number of nets
+ int nTotalNodes2; // the total number of nodess
+ // runtime
+ int timeWin; // windowing
+ int timeDiv; // divisors
+ int timeAig; // strashing
+ int timeSim; // simulation
+ int timeCand; // resubstitution candidates
+ int timeSatTotal; // SAT solving total
+ int timeSatSat; // SAT solving (sat calls)
+ int timeSatUnsat; // SAT solving (unsat calls)
+ int timeSatSim; // SAT solving (simulation)
+ int timeInt; // interpolation
+ int timeUpd; // updating
+ int timeTotal; // total runtime
+};
+
+extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph );
+
+extern int s_ResynTime;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocate resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Res_Man_t * Res_ManAlloc( Res_Par_t * pPars )
+{
+ Res_Man_t * p;
+ p = ALLOC( Res_Man_t, 1 );
+ memset( p, 0, sizeof(Res_Man_t) );
+ assert( pPars->nWindow > 0 && pPars->nWindow < 100 );
+ assert( pPars->nCands > 0 && pPars->nCands < 100 );
+ p->pPars = pPars;
+ p->pWin = Res_WinAlloc();
+ p->pSim = Res_SimAlloc( pPars->nSimWords );
+ p->pMan = Int_ManAlloc();
+ p->vMem = Vec_IntAlloc( 0 );
+ p->vResubs = Vec_VecStart( pPars->nCands );
+ p->vResubsW = Vec_VecStart( pPars->nCands );
+ p->vLevels = Vec_VecStart( 32 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocate resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_ManFree( Res_Man_t * p )
+{
+ if ( p->pPars->fVerbose )
+ {
+ printf( "Reduction in nodes = %5d. (%.2f %%) ",
+ p->nTotalNodes-p->nTotalNodes2,
+ 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes );
+ printf( "Reduction in edges = %5d. (%.2f %%) ",
+ p->nTotalNets-p->nTotalNets2,
+ 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets );
+ printf( "\n" );
+
+ printf( "Winds = %d. ", p->nWins );
+ printf( "Nodes = %d. (Ave = %5.1f) ", p->nWinNodes, 1.0*p->nWinNodes/p->nWins );
+ printf( "Divs = %d. (Ave = %5.1f) ", p->nDivNodes, 1.0*p->nDivNodes/p->nWins );
+ printf( "\n" );
+ printf( "WinsTriv = %d. ", p->nWinsTriv );
+ printf( "SimsEmpt = %d. ", p->nSimEmpty );
+ printf( "Const = %d. ", p->nConstsUsed );
+ printf( "WindUsed = %d. ", p->nWinsUsed );
+ printf( "Cands = %d. ", p->nCandSets );
+ printf( "Proved = %d.", p->nProvedSets );
+ printf( "\n" );
+
+ PRTP( "Windowing ", p->timeWin, p->timeTotal );
+ PRTP( "Divisors ", p->timeDiv, p->timeTotal );
+ PRTP( "Strashing ", p->timeAig, p->timeTotal );
+ PRTP( "Simulation ", p->timeSim, p->timeTotal );
+ PRTP( "Candidates ", p->timeCand, p->timeTotal );
+ PRTP( "SAT solver ", p->timeSatTotal, p->timeTotal );
+ PRTP( " sat ", p->timeSatSat, p->timeTotal );
+ PRTP( " unsat ", p->timeSatUnsat, p->timeTotal );
+ PRTP( " simul ", p->timeSatSim, p->timeTotal );
+ PRTP( "Interpol ", p->timeInt, p->timeTotal );
+ PRTP( "Undating ", p->timeUpd, p->timeTotal );
+ PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ }
+ Res_WinFree( p->pWin );
+ if ( p->pAig ) Abc_NtkDelete( p->pAig );
+ Res_SimFree( p->pSim );
+ if ( p->pCnf ) Sto_ManFree( p->pCnf );
+ Int_ManFree( p->pMan );
+ Vec_IntFree( p->vMem );
+ Vec_VecFree( p->vResubs );
+ Vec_VecFree( p->vResubsW );
+ Vec_VecFree( p->vLevels );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Incrementally updates level of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels )
+{
+ Abc_Obj_t * pObjNew, * pFanin;
+ int k;
+ // create the new node
+ pObjNew = Abc_NtkCreateNode( pObj->pNtk );
+ pObjNew->pData = pFunc;
+ Vec_PtrForEachEntry( vFanins, pFanin, k )
+ Abc_ObjAddFanin( pObjNew, pFanin );
+ // replace the old node by the new node
+ // update the level of the node
+ Abc_NtkUpdate( pObj, pObjNew, vLevels );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Entrace into the resynthesis package.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars )
+{
+ ProgressBar * pProgress;
+ Res_Man_t * p;
+ Abc_Obj_t * pObj;
+ Hop_Obj_t * pFunc;
+ Kit_Graph_t * pGraph;
+ Vec_Ptr_t * vFanins;
+ unsigned * puTruth;
+ int i, k, RetValue, nNodesOld, nFanins, nFaninsMax;
+ int clk, clkTotal = clock();
+
+ // start the manager
+ p = Res_ManAlloc( pPars );
+ p->nTotalNets = Abc_NtkGetTotalFanins(pNtk);
+ p->nTotalNodes = Abc_NtkNodeNum(pNtk);
+ nFaninsMax = Abc_NtkGetFaninMax(pNtk);
+ if ( nFaninsMax > 8 )
+ nFaninsMax = 8;
+
+ // perform the network sweep
+ Abc_NtkSweep( pNtk, 0 );
+
+ // convert into the AIG
+ if ( !Abc_NtkToAig(pNtk) )
+ {
+ fprintf( stdout, "Converting to BDD has failed.\n" );
+ Res_ManFree( p );
+ return 0;
+ }
+ assert( Abc_NtkHasAig(pNtk) );
+
+ // set the number of levels
+ Abc_NtkLevel( pNtk );
+ Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel );
+
+ // try resynthesizing nodes in the topological order
+ nNodesOld = Abc_NtkObjNumMax(pNtk);
+ pProgress = Extra_ProgressBarStart( stdout, nNodesOld );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ Extra_ProgressBarUpdate( pProgress, i, NULL );
+ if ( !Abc_ObjIsNode(pObj) )
+ continue;
+ if ( Abc_ObjFaninNum(pObj) > 8 )
+ continue;
+ if ( pObj->Id > nNodesOld )
+ break;
+
+ // create the window for this node
+clk = clock();
+ RetValue = Res_WinCompute( pObj, p->pPars->nWindow/10, p->pPars->nWindow%10, p->pWin );
+p->timeWin += clock() - clk;
+ if ( !RetValue )
+ continue;
+ p->nWinsTriv += Res_WinIsTrivial( p->pWin );
+
+ if ( p->pPars->fVeryVerbose )
+ {
+ printf( "%5d (lev=%2d) : ", pObj->Id, pObj->Level );
+ printf( "Win = %3d/%3d/%4d/%3d ",
+ Vec_PtrSize(p->pWin->vLeaves),
+ Vec_PtrSize(p->pWin->vBranches),
+ Vec_PtrSize(p->pWin->vNodes),
+ Vec_PtrSize(p->pWin->vRoots) );
+ }
+
+ // collect the divisors
+clk = clock();
+ Res_WinDivisors( p->pWin, Abc_ObjRequiredLevel(pObj) - 1 );
+p->timeDiv += clock() - clk;
+
+ p->nWins++;
+ p->nWinNodes += Vec_PtrSize(p->pWin->vNodes);
+ p->nDivNodes += Vec_PtrSize( p->pWin->vDivs);
+
+ if ( p->pPars->fVeryVerbose )
+ {
+ printf( "D = %3d ", Vec_PtrSize(p->pWin->vDivs) );
+ printf( "D+ = %3d ", p->pWin->nDivsPlus );
+ }
+
+ // create the AIG for the window
+clk = clock();
+ if ( p->pAig ) Abc_NtkDelete( p->pAig );
+ p->pAig = Res_WndStrash( p->pWin );
+p->timeAig += clock() - clk;
+
+ if ( p->pPars->fVeryVerbose )
+ {
+ printf( "AIG = %4d ", Abc_NtkNodeNum(p->pAig) );
+ printf( "\n" );
+ }
+
+ // prepare simulation info
+clk = clock();
+ RetValue = Res_SimPrepare( p->pSim, p->pAig, Vec_PtrSize(p->pWin->vLeaves), 0 ); //p->pPars->fVerbose );
+p->timeSim += clock() - clk;
+ if ( !RetValue )
+ {
+ p->nSimEmpty++;
+ continue;
+ }
+
+ // consider the case of constant node
+ if ( p->pSim->fConst0 || p->pSim->fConst1 )
+ {
+ p->nConstsUsed++;
+
+ pFunc = p->pSim->fConst1? Hop_ManConst1(pNtk->pManFunc) : Hop_ManConst0(pNtk->pManFunc);
+ vFanins = Vec_VecEntry( p->vResubsW, 0 );
+ Vec_PtrClear( vFanins );
+ Res_UpdateNetwork( pObj, vFanins, pFunc, p->vLevels );
+ continue;
+ }
+
+// printf( " " );
+
+ // find resub candidates for the node
+clk = clock();
+ if ( p->pPars->fArea )
+ RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 1 );
+ else
+ RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 0 );
+p->timeCand += clock() - clk;
+ p->nCandSets += RetValue;
+ if ( RetValue == 0 )
+ continue;
+
+// printf( "%d(%d) ", Vec_PtrSize(p->pWin->vDivs), RetValue );
+
+ p->nWinsUsed++;
+
+ // iterate through candidate resubstitutions
+ Vec_VecForEachLevel( p->vResubs, vFanins, k )
+ {
+ if ( Vec_PtrSize(vFanins) == 0 )
+ break;
+
+ // solve the SAT problem and get clauses
+clk = clock();
+ if ( p->pCnf ) Sto_ManFree( p->pCnf );
+ p->pCnf = Res_SatProveUnsat( p->pAig, vFanins );
+ if ( p->pCnf == NULL )
+ {
+p->timeSatSat += clock() - clk;
+// printf( " Sat\n" );
+// printf( "-" );
+ continue;
+ }
+p->timeSatUnsat += clock() - clk;
+// printf( "+" );
+
+ p->nProvedSets++;
+// printf( " Unsat\n" );
+// continue;
+// printf( "Proved %d.\n", k );
+
+ // write it into a file
+// Sto_ManDumpClauses( p->pCnf, "trace.cnf" );
+
+ // interpolate the problem if it was UNSAT
+clk = clock();
+ nFanins = Int_ManInterpolate( p->pMan, p->pCnf, 0, &puTruth );
+p->timeInt += clock() - clk;
+ if ( nFanins != Vec_PtrSize(vFanins) - 2 )
+ continue;
+ assert( puTruth );
+// Extra_PrintBinary( stdout, puTruth, 1 << nFanins ); printf( "\n" );
+
+ // transform interpolant into the AIG
+ pGraph = Kit_TruthToGraph( puTruth, nFanins, p->vMem );
+
+ // derive the AIG for the decomposition tree
+ pFunc = Kit_GraphToHop( pNtk->pManFunc, pGraph );
+ Kit_GraphFree( pGraph );
+
+ // update the network
+clk = clock();
+ Res_UpdateNetwork( pObj, Vec_VecEntry(p->vResubsW, k), pFunc, p->vLevels );
+p->timeUpd += clock() - clk;
+ break;
+ }
+// printf( "\n" );
+ }
+ Extra_ProgressBarStop( pProgress );
+ Abc_NtkStopReverseLevels( pNtk );
+
+p->timeSatSim += p->pSim->timeSat;
+p->timeSatTotal = p->timeSatSat + p->timeSatUnsat + p->timeSatSim;
+
+ p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk);
+ p->nTotalNodes2 = Abc_NtkNodeNum(pNtk);
+
+ // quit resubstitution manager
+p->timeTotal = clock() - clkTotal;
+ Res_ManFree( p );
+
+s_ResynTime += clock() - clkTotal;
+ // check the resulting network
+ if ( !Abc_NtkCheck( pNtk ) )
+ {
+ fprintf( stdout, "Abc_NtkResynthesize(): Network check has failed.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resDivs.c b/src/opt/res/resDivs.c
new file mode 100644
index 00000000..cc75b90f
--- /dev/null
+++ b/src/opt/res/resDivs.c
@@ -0,0 +1,285 @@
+/**CFile****************************************************************
+
+ FileName [resDivs.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Collect divisors for the given window.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resDivs.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Res_WinMarkTfi( Res_Win_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Adds candidate divisors of the node to its window.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinDivisors( Res_Win_t * p, int nLevDivMax )
+{
+ Abc_Obj_t * pObj, * pFanout, * pFanin;
+ int k, f, m;
+
+ // set the maximum level of the divisors
+ p->nLevDivMax = nLevDivMax;
+
+ // mark the TFI with the current trav ID
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Res_WinMarkTfi( p );
+
+ // mark with the current trav ID those nodes that should not be divisors:
+ // (1) the node and its TFO
+ // (2) the MFFC of the node
+ // (3) the node's fanins (these are treated as a special case)
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Res_WinSweepLeafTfo_rec( p->pNode, p->nLevDivMax );
+ Res_WinVisitMffc( p->pNode );
+ Abc_ObjForEachFanin( p->pNode, pObj, k )
+ Abc_NodeSetTravIdCurrent( pObj );
+
+ // at this point the nodes are marked with two trav IDs:
+ // nodes to be collected as divisors are marked with previous trav ID
+ // nodes to be avoided as divisors are marked with current trav ID
+
+ // start collecting the divisors
+ Vec_PtrClear( p->vDivs );
+ Vec_PtrForEachEntry( p->vLeaves, pObj, k )
+ {
+ assert( (int)pObj->Level >= p->nLevLeafMin );
+ if ( !Abc_NodeIsTravIdPrevious(pObj) )
+ continue;
+ if ( (int)pObj->Level > p->nLevDivMax )
+ continue;
+ Vec_PtrPush( p->vDivs, pObj );
+ }
+ // add the internal nodes to the data structure
+ Vec_PtrForEachEntry( p->vNodes, pObj, k )
+ {
+ if ( !Abc_NodeIsTravIdPrevious(pObj) )
+ continue;
+ if ( (int)pObj->Level > p->nLevDivMax )
+ continue;
+ Vec_PtrPush( p->vDivs, pObj );
+ }
+
+ // explore the fanouts of already collected divisors
+ p->nDivsPlus = 0;
+ Vec_PtrForEachEntry( p->vDivs, pObj, k )
+ {
+ // consider fanouts of this node
+ Abc_ObjForEachFanout( pObj, pFanout, f )
+ {
+ // stop if there are too many fanouts
+ if ( f > 20 )
+ break;
+ // skip nodes that are already added
+ if ( Abc_NodeIsTravIdPrevious(pFanout) )
+ continue;
+ // skip nodes in the TFO or in the MFFC of node
+ if ( Abc_NodeIsTravIdCurrent(pFanout) )
+ continue;
+ // skip COs
+ if ( !Abc_ObjIsNode(pFanout) )
+ continue;
+ // skip nodes with large level
+ if ( (int)pFanout->Level >= p->nLevDivMax )
+ continue;
+ // skip nodes whose fanins are not divisors
+ Abc_ObjForEachFanin( pFanout, pFanin, m )
+ if ( !Abc_NodeIsTravIdPrevious(pFanin) )
+ break;
+ if ( m < Abc_ObjFaninNum(pFanout) )
+ continue;
+ // add the node to the divisors
+ Vec_PtrPush( p->vDivs, pFanout );
+ Vec_PtrPush( p->vNodes, pFanout );
+ Abc_NodeSetTravIdPrevious( pFanout );
+ p->nDivsPlus++;
+ }
+ }
+/*
+ printf( "Node level = %d. ", Abc_ObjLevel(p->pNode) );
+ Vec_PtrForEachEntryStart( p->vDivs, pObj, k, Vec_PtrSize(p->vDivs)-p->nDivsPlus )
+ printf( "%d ", Abc_ObjLevel(pObj) );
+ printf( "\n" );
+*/
+//printf( "%d ", p->nDivsPlus );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFI cone of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinMarkTfi_rec( Res_Win_t * p, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return;
+ Abc_NodeSetTravIdCurrent( pObj );
+ assert( Abc_ObjIsNode(pObj) );
+ // visit the fanins of the node
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Res_WinMarkTfi_rec( p, pFanin );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFI cone of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinMarkTfi( Res_Win_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // mark the leaves
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // start from the node
+ Res_WinMarkTfi_rec( p, p->pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFO of the collected nodes up to the given level.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit )
+ return;
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return;
+ Abc_NodeSetTravIdCurrent( pObj );
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ Res_WinSweepLeafTfo_rec( pFanout, nLevelLimit );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dereferences the node's MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_NodeDeref_rec( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ int i, Counter = 1;
+ if ( Abc_ObjIsCi(pNode) )
+ return 0;
+ Abc_NodeSetTravIdCurrent( pNode );
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ assert( pFanin->vFanouts.nSize > 0 );
+ if ( --pFanin->vFanouts.nSize == 0 )
+ Counter += Res_NodeDeref_rec( pFanin );
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [References the node's MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_NodeRef_rec( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ int i, Counter = 1;
+ if ( Abc_ObjIsCi(pNode) )
+ return 0;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( pFanin->vFanouts.nSize++ == 0 )
+ Counter += Res_NodeRef_rec( pFanin );
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Labels MFFC of the node with the current trav ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinVisitMffc( Abc_Obj_t * pNode )
+{
+ int Count1, Count2;
+ assert( Abc_ObjIsNode(pNode) );
+ // dereference the node (mark with the current trav ID)
+ Count1 = Res_NodeDeref_rec( pNode );
+ // reference it back
+ Count2 = Res_NodeRef_rec( pNode );
+ assert( Count1 == Count2 );
+ return Count1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resFilter.c b/src/opt/res/resFilter.c
new file mode 100644
index 00000000..f2ca41d3
--- /dev/null
+++ b/src/opt/res/resFilter.c
@@ -0,0 +1,434 @@
+/**CFile****************************************************************
+
+ FileName [resFilter.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Filtering resubstitution candidates.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resFilter.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static unsigned * Res_FilterCollectFaninInfo( Res_Win_t * pWin, Res_Sim_t * pSim, unsigned uMask );
+static int Res_FilterCriticalFanin( Abc_Obj_t * pNode );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Finds sets of feasible candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_FilterCandidates( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax, int fArea )
+{
+ Abc_Obj_t * pFanin, * pFanin2, * pFaninTemp;
+ unsigned * pInfo, * pInfoDiv, * pInfoDiv2;
+ int Counter, RetValue, i, i2, d, d2, iDiv, iDiv2, k;
+
+ // check that the info the node is one
+ pInfo = Vec_PtrEntry( pSim->vOuts, 1 );
+ RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+ if ( RetValue == 0 )
+ {
+// printf( "Failed 1!\n" );
+ return 0;
+ }
+
+ // collect the fanin info
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~0 );
+ RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+ if ( RetValue == 0 )
+ {
+// printf( "Failed 2!\n" );
+ return 0;
+ }
+
+ // try removing each fanin
+// printf( "Fanins: " );
+ Counter = 0;
+ Vec_VecClear( vResubs );
+ Vec_VecClear( vResubsW );
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+ {
+ if ( fArea && Abc_ObjFanoutNum(pFanin) > 1 )
+ continue;
+ // get simulation info without this fanin
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) );
+ RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+ if ( RetValue )
+ {
+// printf( "Node %4d. Candidate fanin %4d.\n", pWin->pNode->Id, pFanin->Id );
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k )
+ {
+ if ( k != i )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFaninTemp );
+ }
+ }
+ Counter++;
+ if ( Counter == Vec_VecSize(vResubs) )
+ return Counter;
+ }
+ }
+
+ // try replacing each critical fanin by a non-critical fanin
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+ {
+ if ( Abc_ObjFanoutNum(pFanin) > 1 )
+ continue;
+ // get simulation info without this fanin
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) );
+ // go over the set of divisors
+ for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+ {
+ pInfoDiv = Vec_PtrEntry( pSim->vOuts, d );
+ iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+ if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) )
+ continue;
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ // collect the remaning fanins and the divisor
+ Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k )
+ {
+ if ( k != i )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFaninTemp );
+ }
+ }
+ // collect the divisor
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+ Counter++;
+ if ( Counter == Vec_VecSize(vResubs) )
+ return Counter;
+ }
+ }
+
+ // consider the case when two fanins can be added instead of one
+ if ( Abc_ObjFaninNum(pWin->pNode) < nFaninsMax )
+ {
+ // try to replace each critical fanin by two non-critical fanins
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+ {
+ if ( Abc_ObjFanoutNum(pFanin) > 1 )
+ continue;
+ // get simulation info without this fanin
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) );
+ // go over the set of divisors
+ for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+ {
+ pInfoDiv = Vec_PtrEntry( pSim->vOuts, d );
+ iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+ // go through the second divisor
+ for ( d2 = d + 1; d2 < Abc_NtkPoNum(pAig); d2++ )
+ {
+ pInfoDiv2 = Vec_PtrEntry( pSim->vOuts, d2 );
+ iDiv2 = d2 - (Abc_ObjFaninNum(pWin->pNode) + 2);
+ if ( !Abc_InfoIsOrOne3( pInfo, pInfoDiv, pInfoDiv2, pSim->nWordsOut ) )
+ continue;
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ // collect the remaning fanins and the divisor
+ Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k )
+ {
+ if ( k != i )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFaninTemp );
+ }
+ }
+ // collect the divisor
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d2) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv2) );
+ Counter++;
+ if ( Counter == Vec_VecSize(vResubs) )
+ return Counter;
+ }
+ }
+ }
+ }
+
+ // try to replace two nets by one
+ if ( !fArea )
+ {
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+ {
+ for ( i2 = i + 1; i2 < Abc_ObjFaninNum(pWin->pNode); i2++ )
+ {
+ pFanin2 = Abc_ObjFanin(pWin->pNode, i2);
+ // get simulation info without these fanins
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, (~(1 << i)) & (~(1 << i2)) );
+ // go over the set of divisors
+ for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+ {
+ pInfoDiv = Vec_PtrEntry( pSim->vOuts, d );
+ iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+ if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) )
+ continue;
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ // collect the remaning fanins and the divisor
+ Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k )
+ {
+ if ( k != i && k != i2 )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFaninTemp );
+ }
+ }
+ // collect the divisor
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+ Counter++;
+ if ( Counter == Vec_VecSize(vResubs) )
+ return Counter;
+ }
+ }
+ }
+ }
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds sets of feasible candidates.]
+
+ Description [This procedure is a special case of the above.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_FilterCandidatesArea( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax )
+{
+ Abc_Obj_t * pFanin;
+ unsigned * pInfo, * pInfoDiv, * pInfoDiv2;
+ int Counter, RetValue, d, d2, k, iDiv, iDiv2, iBest;
+
+ // check that the info the node is one
+ pInfo = Vec_PtrEntry( pSim->vOuts, 1 );
+ RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+ if ( RetValue == 0 )
+ {
+// printf( "Failed 1!\n" );
+ return 0;
+ }
+
+ // collect the fanin info
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~0 );
+ RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+ if ( RetValue == 0 )
+ {
+// printf( "Failed 2!\n" );
+ return 0;
+ }
+
+ // try removing fanins
+// printf( "Fanins: " );
+ Counter = 0;
+ Vec_VecClear( vResubs );
+ Vec_VecClear( vResubsW );
+ // get the best fanins
+ iBest = Res_FilterCriticalFanin( pWin->pNode );
+ if ( iBest == -1 )
+ return 0;
+
+ // get the info without the critical fanin
+ pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << iBest) );
+ RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut );
+ if ( RetValue )
+ {
+// printf( "Can be done without one!\n" );
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, k )
+ {
+ if ( k != iBest )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFanin );
+ }
+ }
+ Counter++;
+// printf( "*" );
+ return Counter;
+ }
+
+ // go through the divisors
+ for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+ {
+ pInfoDiv = Vec_PtrEntry( pSim->vOuts, d );
+ iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+ if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) )
+ continue;
+//if ( Abc_ObjLevel(pWin->pNode) <= Abc_ObjLevel( Vec_PtrEntry(pWin->vDivs, iDiv) ) )
+// printf( "Node level = %d. Divisor level = %d.\n", Abc_ObjLevel(pWin->pNode), Abc_ObjLevel( Vec_PtrEntry(pWin->vDivs, iDiv) ) );
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ // collect the remaning fanins and the divisor
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, k )
+ {
+ if ( k != iBest )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFanin );
+ }
+ }
+ // collect the divisor
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+ Counter++;
+
+ if ( Counter == Vec_VecSize(vResubs) )
+ break;
+ }
+
+ if ( Counter > 0 || Abc_ObjFaninNum(pWin->pNode) >= nFaninsMax )
+ return Counter;
+
+ // try to find the node pairs
+ for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ )
+ {
+ pInfoDiv = Vec_PtrEntry( pSim->vOuts, d );
+ iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2);
+ // go through the second divisor
+ for ( d2 = d + 1; d2 < Abc_NtkPoNum(pAig); d2++ )
+ {
+ pInfoDiv2 = Vec_PtrEntry( pSim->vOuts, d2 );
+ iDiv2 = d2 - (Abc_ObjFaninNum(pWin->pNode) + 2);
+
+ if ( !Abc_InfoIsOrOne3( pInfo, pInfoDiv, pInfoDiv2, pSim->nWordsOut ) )
+ continue;
+ // collect the nodes
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) );
+ // collect the remaning fanins and the divisor
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, k )
+ {
+ if ( k != iBest )
+ {
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) );
+ Vec_VecPush( vResubsW, Counter, pFanin );
+ }
+ }
+ // collect the divisor
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) );
+ Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d2) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) );
+ Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv2) );
+ Counter++;
+
+ if ( Counter == Vec_VecSize(vResubs) )
+ break;
+ }
+ if ( Counter == Vec_VecSize(vResubs) )
+ break;
+ }
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds sets of feasible candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Res_FilterCollectFaninInfo( Res_Win_t * pWin, Res_Sim_t * pSim, unsigned uMask )
+{
+ Abc_Obj_t * pFanin;
+ unsigned * pInfo;
+ int i;
+ pInfo = Vec_PtrEntry( pSim->vOuts, 0 );
+ Abc_InfoClear( pInfo, pSim->nWordsOut );
+ Abc_ObjForEachFanin( pWin->pNode, pFanin, i )
+ {
+ if ( uMask & (1 << i) )
+ Abc_InfoOr( pInfo, Vec_PtrEntry(pSim->vOuts, 2+i), pSim->nWordsOut );
+ }
+ return pInfo;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the index of the most critical fanin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_FilterCriticalFanin( Abc_Obj_t * pNode )
+{
+ Abc_Obj_t * pFanin;
+ int i, iBest = -1, CostMax = 0, CostCur;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ {
+ if ( !Abc_ObjIsNode(pFanin) )
+ continue;
+ if ( Abc_ObjFanoutNum(pFanin) > 1 )
+ continue;
+ CostCur = Res_WinVisitMffc( pFanin );
+ if ( CostMax < CostCur )
+ {
+ CostMax = CostCur;
+ iBest = i;
+ }
+ }
+// if ( CostMax > 0 )
+// printf( "<%d>", CostMax );
+ return iBest;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resInt.h b/src/opt/res/resInt.h
new file mode 100644
index 00000000..5aae46cc
--- /dev/null
+++ b/src/opt/res/resInt.h
@@ -0,0 +1,137 @@
+/**CFile****************************************************************
+
+ FileName [resInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resInt.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __RES_INT_H__
+#define __RES_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "res.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Res_Win_t_ Res_Win_t;
+struct Res_Win_t_
+{
+ // windowing parameters
+ Abc_Obj_t * pNode; // the node in the center
+ int nWinTfiMax; // the fanin levels
+ int nWinTfoMax; // the fanout levels
+ int nLevDivMax; // the maximum divisor level
+ // internal windowing parameters
+ int nFanoutLimit; // the limit on the fanout count of a TFO node (if more, the node is treated as a root)
+ int nLevTfiMinus; // the number of additional levels to search from TFO below the level of leaves
+ // derived windowing parameters
+ int nLevLeafMin; // the minimum level of a leaf
+ int nLevTravMin; // the minimum level to search from TFO
+ int nDivsPlus; // the number of additional divisors
+ // the window data
+ Vec_Ptr_t * vRoots; // outputs of the window
+ Vec_Ptr_t * vLeaves; // inputs of the window
+ Vec_Ptr_t * vBranches; // side nodes of the window
+ Vec_Ptr_t * vNodes; // internal nodes of the window
+ Vec_Ptr_t * vDivs; // candidate divisors of the node
+ // temporary data
+ Vec_Vec_t * vMatrix; // TFI nodes below the given node
+};
+
+typedef struct Res_Sim_t_ Res_Sim_t;
+struct Res_Sim_t_
+{
+ Abc_Ntk_t * pAig; // AIG for simulation
+ int nTruePis; // the number of true PIs of the window
+ int fConst0; // the node can be replaced by constant 0
+ int fConst1; // the node can be replaced by constant 0
+ // simulation parameters
+ int nWords; // the number of simulation words
+ int nPats; // the number of patterns
+ int nWordsIn; // the number of simulation words in the input patterns
+ int nPatsIn; // the number of patterns in the input patterns
+ int nBytesIn; // the number of bytes in the input patterns
+ int nWordsOut; // the number of simulation words in the output patterns
+ int nPatsOut; // the number of patterns in the output patterns
+ // simulation info
+ Vec_Ptr_t * vPats; // input simulation patterns
+ Vec_Ptr_t * vPats0; // input simulation patterns
+ Vec_Ptr_t * vPats1; // input simulation patterns
+ Vec_Ptr_t * vOuts; // output simulation info
+ int nPats0; // the number of 0-patterns accumulated
+ int nPats1; // the number of 1-patterns accumulated
+ // resub candidates
+ Vec_Vec_t * vCands; // resubstitution candidates
+ // statistics
+ int timeSat;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== resDivs.c ==========================================================*/
+extern void Res_WinDivisors( Res_Win_t * p, int nLevDivMax );
+extern void Res_WinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit );
+extern int Res_WinVisitMffc( Abc_Obj_t * pNode );
+/*=== resFilter.c ==========================================================*/
+extern int Res_FilterCandidates( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax, int fArea );
+extern int Res_FilterCandidatesArea( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax );
+/*=== resSat.c ==========================================================*/
+extern void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins );
+extern int Res_SatSimulate( Res_Sim_t * p, int nPats, int fOnSet );
+/*=== resSim.c ==========================================================*/
+extern Res_Sim_t * Res_SimAlloc( int nWords );
+extern void Res_SimFree( Res_Sim_t * p );
+extern int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose );
+/*=== resStrash.c ==========================================================*/
+extern Abc_Ntk_t * Res_WndStrash( Res_Win_t * p );
+/*=== resWnd.c ==========================================================*/
+extern void Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels );
+/*=== resWnd.c ==========================================================*/
+extern Res_Win_t * Res_WinAlloc();
+extern void Res_WinFree( Res_Win_t * p );
+extern int Res_WinIsTrivial( Res_Win_t * p );
+extern int Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/opt/res/resSat.c b/src/opt/res/resSat.c
new file mode 100644
index 00000000..dd0e7a23
--- /dev/null
+++ b/src/opt/res/resSat.c
@@ -0,0 +1,407 @@
+/**CFile****************************************************************
+
+ FileName [resSat.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Interface with the SAT solver.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resSat.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+#include "hop.h"
+#include "satSolver.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl );
+extern int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl );
+extern int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Loads AIG into the SAT solver for checking resubstitution.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins )
+{
+ void * pCnf = NULL;
+ sat_solver * pSat;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i, nNodes, status;
+
+ // make sure fanins contain POs of the AIG
+ pObj = Vec_PtrEntry( vFanins, 0 );
+ assert( pObj->pNtk == pAig && Abc_ObjIsPo(pObj) );
+
+ // collect reachable nodes
+ vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize );
+
+ // assign unique numbers to each node
+ nNodes = 0;
+ Abc_AigConst1(pAig)->pCopy = (void *)nNodes++;
+ Abc_NtkForEachPi( pAig, pObj, i )
+ pObj->pCopy = (void *)nNodes++;
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->pCopy = (void *)nNodes++;
+ Vec_PtrForEachEntry( vFanins, pObj, i ) // useful POs
+ pObj->pCopy = (void *)nNodes++;
+
+ // start the solver
+ pSat = sat_solver_new();
+ sat_solver_store_alloc( pSat );
+
+ // add clause for the constant node
+ Res_SatAddConst1( pSat, (int)Abc_AigConst1(pAig)->pCopy, 0 );
+ // add clauses for AND gates
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ Res_SatAddAnd( pSat, (int)pObj->pCopy,
+ (int)Abc_ObjFanin0(pObj)->pCopy, (int)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ Vec_PtrFree( vNodes );
+ // add clauses for POs
+ Vec_PtrForEachEntry( vFanins, pObj, i )
+ Res_SatAddEqual( pSat, (int)pObj->pCopy,
+ (int)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
+ // add trivial clauses
+ pObj = Vec_PtrEntry(vFanins, 0);
+ Res_SatAddConst1( pSat, (int)pObj->pCopy, 0 ); // care-set
+ pObj = Vec_PtrEntry(vFanins, 1);
+ Res_SatAddConst1( pSat, (int)pObj->pCopy, 0 ); // on-set
+
+ // bookmark the clauses of A
+ sat_solver_store_mark_clauses_a( pSat );
+
+ // duplicate the clauses
+ pObj = Vec_PtrEntry(vFanins, 1);
+ Sat_SolverDoubleClauses( pSat, (int)pObj->pCopy );
+ // add the equality constraints
+ Vec_PtrForEachEntryStart( vFanins, pObj, i, 2 )
+ Res_SatAddEqual( pSat, (int)pObj->pCopy, ((int)pObj->pCopy) + nNodes, 0 );
+
+ // bookmark the roots
+ sat_solver_store_mark_roots( pSat );
+
+ // solve the problem
+ status = sat_solver_solve( pSat, NULL, NULL, (sint64)10000, (sint64)0, (sint64)0, (sint64)0 );
+ if ( status == l_False )
+ {
+ pCnf = sat_solver_store_release( pSat );
+// printf( "unsat\n" );
+ }
+ else if ( status == l_True )
+ {
+// printf( "sat\n" );
+ }
+ else
+ {
+// printf( "undef\n" );
+ }
+ sat_solver_delete( pSat );
+ return pCnf;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Loads AIG into the SAT solver for constrained simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Res_SatSimulateConstr( Abc_Ntk_t * pAig, int fOnSet )
+{
+ sat_solver * pSat;
+ Vec_Ptr_t * vFanins;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i, nNodes;
+
+ // start the array
+ vFanins = Vec_PtrAlloc( 2 );
+ pObj = Abc_NtkPo( pAig, 0 );
+ Vec_PtrPush( vFanins, pObj );
+ pObj = Abc_NtkPo( pAig, 1 );
+ Vec_PtrPush( vFanins, pObj );
+
+ // collect reachable nodes
+ vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize );
+
+ // assign unique numbers to each node
+ nNodes = 0;
+ Abc_AigConst1(pAig)->pCopy = (void *)nNodes++;
+ Abc_NtkForEachPi( pAig, pObj, i )
+ pObj->pCopy = (void *)nNodes++;
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->pCopy = (void *)nNodes++;
+ Vec_PtrForEachEntry( vFanins, pObj, i ) // useful POs
+ pObj->pCopy = (void *)nNodes++;
+
+ // start the solver
+ pSat = sat_solver_new();
+
+ // add clause for the constant node
+ Res_SatAddConst1( pSat, (int)Abc_AigConst1(pAig)->pCopy, 0 );
+ // add clauses for AND gates
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ Res_SatAddAnd( pSat, (int)pObj->pCopy,
+ (int)Abc_ObjFanin0(pObj)->pCopy, (int)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
+ Vec_PtrFree( vNodes );
+ // add clauses for the first PO
+ pObj = Abc_NtkPo( pAig, 0 );
+ Res_SatAddEqual( pSat, (int)pObj->pCopy,
+ (int)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
+ // add clauses for the second PO
+ pObj = Abc_NtkPo( pAig, 1 );
+ Res_SatAddEqual( pSat, (int)pObj->pCopy,
+ (int)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
+
+ // add trivial clauses
+ pObj = Abc_NtkPo( pAig, 0 );
+ Res_SatAddConst1( pSat, (int)pObj->pCopy, 0 ); // care-set
+
+ pObj = Abc_NtkPo( pAig, 1 );
+ Res_SatAddConst1( pSat, (int)pObj->pCopy, !fOnSet ); // on-set
+
+ Vec_PtrFree( vFanins );
+ return pSat;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Loads AIG into the SAT solver for constrained simulation.]
+
+ Description [Returns 1 if the required number of patterns are found.
+ Returns 0 if the solver ran out of time or proved a constant.
+ In the latter, case one of the flags, fConst0 or fConst1, are set to 1.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SatSimulate( Res_Sim_t * p, int nPatsLimit, int fOnSet )
+{
+ Vec_Int_t * vLits;
+ Vec_Ptr_t * vPats;
+ sat_solver * pSat;
+ int RetValue, i, k, value, status, Lit, Var, iPat;
+ int clk = clock();
+
+//printf( "Looking for %s: ", fOnSet? "onset " : "offset" );
+
+ // decide what problem should be solved
+ Lit = toLitCond( (int)Abc_NtkPo(p->pAig,1)->pCopy, !fOnSet );
+ if ( fOnSet )
+ {
+ iPat = p->nPats1;
+ vPats = p->vPats1;
+ }
+ else
+ {
+ iPat = p->nPats0;
+ vPats = p->vPats0;
+ }
+ assert( iPat < nPatsLimit );
+
+ // derive the SAT solver
+ pSat = Res_SatSimulateConstr( p->pAig, fOnSet );
+ pSat->fSkipSimplify = 1;
+ status = sat_solver_simplify( pSat );
+ if ( status == 0 )
+ {
+ if ( iPat == 0 )
+ {
+// if ( fOnSet )
+// p->fConst0 = 1;
+// else
+// p->fConst1 = 1;
+ RetValue = 0;
+ }
+ goto finish;
+ }
+
+ // enumerate through the SAT assignments
+ RetValue = 1;
+ vLits = Vec_IntAlloc( 32 );
+ for ( k = iPat; k < nPatsLimit; k++ )
+ {
+ // solve with the assumption
+// status = sat_solver_solve( pSat, &Lit, &Lit + 1, (sint64)10000, (sint64)0, (sint64)0, (sint64)0 );
+ status = sat_solver_solve( pSat, NULL, NULL, (sint64)10000, (sint64)0, (sint64)0, (sint64)0 );
+ if ( status == l_False )
+ {
+//printf( "Const %d\n", !fOnSet );
+ if ( k == 0 )
+ {
+ if ( fOnSet )
+ p->fConst0 = 1;
+ else
+ p->fConst1 = 1;
+ RetValue = 0;
+ }
+ break;
+ }
+ else if ( status == l_True )
+ {
+ // save the pattern
+ Vec_IntClear( vLits );
+ for ( i = 0; i < p->nTruePis; i++ )
+ {
+ Var = (int)Abc_NtkPi(p->pAig,i)->pCopy;
+ value = (int)(pSat->model.ptr[Var] == l_True);
+ if ( value )
+ Abc_InfoSetBit( Vec_PtrEntry(vPats, i), k );
+ Lit = toLitCond( Var, value );
+ Vec_IntPush( vLits, Lit );
+// printf( "%d", value );
+ }
+// printf( "\n" );
+
+ status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+ if ( status == 0 )
+ {
+ k++;
+ RetValue = 1;
+ break;
+ }
+ }
+ else
+ {
+//printf( "Undecided\n" );
+ if ( k == 0 )
+ RetValue = 0;
+ else
+ RetValue = 1;
+ break;
+ }
+ }
+ Vec_IntFree( vLits );
+//printf( "Found %d patterns\n", k - iPat );
+
+ // set the new number of patterns
+ if ( fOnSet )
+ p->nPats1 = k;
+ else
+ p->nPats0 = k;
+
+finish:
+
+ sat_solver_delete( pSat );
+p->timeSat += clock() - clk;
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Asserts equality of the variable to a constant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl )
+{
+ lit Lit = toLitCond( iVar, fCompl );
+ if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Asserts equality of two variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl )
+{
+ lit Lits[2];
+
+ Lits[0] = toLitCond( iVar0, 0 );
+ Lits[1] = toLitCond( iVar1, !fCompl );
+ if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+ return 0;
+
+ Lits[0] = toLitCond( iVar0, 1 );
+ Lits[1] = toLitCond( iVar1, fCompl );
+ if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+ return 0;
+
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds constraints for the two-input AND-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 )
+{
+ lit Lits[3];
+
+ Lits[0] = toLitCond( iVar, 1 );
+ Lits[1] = toLitCond( iVar0, fCompl0 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+ return 0;
+
+ Lits[0] = toLitCond( iVar, 1 );
+ Lits[1] = toLitCond( iVar1, fCompl1 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
+ return 0;
+
+ Lits[0] = toLitCond( iVar, 0 );
+ Lits[1] = toLitCond( iVar0, !fCompl0 );
+ Lits[2] = toLitCond( iVar1, !fCompl1 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
+ return 0;
+
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resSim.c b/src/opt/res/resSim.c
new file mode 100644
index 00000000..5c1dd2b6
--- /dev/null
+++ b/src/opt/res/resSim.c
@@ -0,0 +1,790 @@
+/**CFile****************************************************************
+
+ FileName [resSim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Simulation engine.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocate simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Res_Sim_t * Res_SimAlloc( int nWords )
+{
+ Res_Sim_t * p;
+ p = ALLOC( Res_Sim_t, 1 );
+ memset( p, 0, sizeof(Res_Sim_t) );
+ // simulation parameters
+ p->nWords = nWords;
+ p->nPats = p->nWords * 8 * sizeof(unsigned);
+ p->nWordsIn = p->nPats;
+ p->nBytesIn = p->nPats * sizeof(unsigned);
+ p->nPatsIn = p->nPats * 8 * sizeof(unsigned);
+ p->nWordsOut = p->nPats * p->nWords;
+ p->nPatsOut = p->nPats * p->nPats;
+ // simulation info
+ p->vPats = Vec_PtrAllocSimInfo( 1024, p->nWordsIn );
+ p->vPats0 = Vec_PtrAllocSimInfo( 128, p->nWords );
+ p->vPats1 = Vec_PtrAllocSimInfo( 128, p->nWords );
+ p->vOuts = Vec_PtrAllocSimInfo( 128, p->nWordsOut );
+ // resub candidates
+ p->vCands = Vec_VecStart( 16 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocate simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis )
+{
+ srand( 0xABC );
+
+ assert( Abc_NtkIsStrash(pAig) );
+ p->pAig = pAig;
+ p->nTruePis = nTruePis;
+ if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 )
+ {
+ Vec_PtrFree( p->vPats );
+ p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWordsIn );
+ }
+ if ( Vec_PtrSize(p->vPats0) < nTruePis )
+ {
+ Vec_PtrFree( p->vPats0 );
+ p->vPats0 = Vec_PtrAllocSimInfo( nTruePis, p->nWords );
+ }
+ if ( Vec_PtrSize(p->vPats1) < nTruePis )
+ {
+ Vec_PtrFree( p->vPats1 );
+ p->vPats1 = Vec_PtrAllocSimInfo( nTruePis, p->nWords );
+ }
+ if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) )
+ {
+ Vec_PtrFree( p->vOuts );
+ p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut );
+ }
+ // clean storage info for patterns
+ Abc_InfoClear( Vec_PtrEntry(p->vPats0,0), p->nWords * nTruePis );
+ Abc_InfoClear( Vec_PtrEntry(p->vPats1,0), p->nWords * nTruePis );
+ p->nPats0 = 0;
+ p->nPats1 = 0;
+ p->fConst0 = 0;
+ p->fConst1 = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Free simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimFree( Res_Sim_t * p )
+{
+ Vec_PtrFree( p->vPats );
+ Vec_PtrFree( p->vPats0 );
+ Vec_PtrFree( p->vPats1 );
+ Vec_PtrFree( p->vOuts );
+ Vec_VecFree( p->vCands );
+ free( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets random PI simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_InfoRandomBytes( unsigned * p, int nWords )
+{
+ int i, Num;
+ for ( i = nWords - 1; i >= 0; i-- )
+ {
+ Num = rand();
+ p[i] = (Num & 1)? 0xff : 0;
+ p[i] = (p[i] << 8) | ((Num & 2)? 0xff : 0);
+ p[i] = (p[i] << 8) | ((Num & 4)? 0xff : 0);
+ p[i] = (p[i] << 8) | ((Num & 8)? 0xff : 0);
+ }
+// Extra_PrintBinary( stdout, p, 32 ); printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets random PI simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimSetRandomBytes( Res_Sim_t * p )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo;
+ int i;
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ if ( i < p->nTruePis )
+ Abc_InfoRandomBytes( pInfo, p->nWordsIn );
+ else
+ Abc_InfoRandom( pInfo, p->nWordsIn );
+ }
+/*
+ // double-check that all are byte-patterns
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfoC = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ for ( k = 0; k < p->nBytesIn; k++ )
+ assert( pInfoC[k] == 0 || pInfoC[k] == 0xff );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets random PI simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimSetDerivedBytes( Res_Sim_t * p, int fUseWalk )
+{
+ Vec_Ptr_t * vPatsSource[2];
+ int nPatsSource[2];
+ Abc_Obj_t * pObj;
+ unsigned char * pInfo;
+ int i, k, z, s, nPats;
+
+ // set several random patterns
+ assert( p->nBytesIn % 32 == 0 );
+ nPats = p->nBytesIn/8;
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ Abc_InfoRandomBytes( Vec_PtrEntry(p->vPats, pObj->Id), nPats/4 );
+ }
+
+ // set special patterns
+ if ( fUseWalk )
+ {
+ for ( z = 0; z < 2; z++ )
+ {
+ // set the zero pattern
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo[nPats] = z ? 0xff : 0;
+ }
+ if ( ++nPats == p->nBytesIn )
+ return;
+ // set the walking zero pattern
+ for ( k = 0; k < p->nTruePis; k++ )
+ {
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo[nPats] = ((i == k) ^ z) ? 0xff : 0;
+ }
+ if ( ++nPats == p->nBytesIn )
+ return;
+ }
+ }
+ }
+
+ // decide what patterns to set first
+ if ( p->nPats0 < p->nPats1 )
+ {
+ nPatsSource[0] = p->nPats0;
+ vPatsSource[0] = p->vPats0;
+ nPatsSource[1] = p->nPats1;
+ vPatsSource[1] = p->vPats1;
+ }
+ else
+ {
+ nPatsSource[0] = p->nPats1;
+ vPatsSource[0] = p->vPats1;
+ nPatsSource[1] = p->nPats0;
+ vPatsSource[1] = p->vPats0;
+ }
+ for ( z = 0; z < 2; z++ )
+ {
+ for ( s = nPatsSource[z] - 1; s >= 0; s-- )
+ {
+// if ( s == 0 )
+// printf( "Patterns:\n" );
+ // set the given source pattern
+ for ( k = 0; k < p->nTruePis; k++ )
+ {
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ if ( (i == k) ^ Abc_InfoHasBit( Vec_PtrEntry(vPatsSource[z], i), s ) )
+ {
+ pInfo[nPats] = 0xff;
+// if ( s == 0 )
+// printf( "1" );
+ }
+ else
+ {
+ pInfo[nPats] = 0;
+// if ( s == 0 )
+// printf( "0" );
+ }
+ }
+// if ( s == 0 )
+// printf( "\n" );
+ if ( ++nPats == p->nBytesIn )
+ return;
+ }
+ }
+ }
+ // clean the rest
+ for ( z = nPats; z < p->nBytesIn; z++ )
+ {
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ memset( pInfo + nPats, 0, p->nBytesIn - nPats );
+ }
+ }
+/*
+ // double-check that all are byte-patterns
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ for ( k = 0; k < p->nBytesIn; k++ )
+ assert( pInfo[k] == 0 || pInfo[k] == 0xff );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets given PI simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo, * pInfo2;
+ int i, w;
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo2 = Vec_PtrEntry( vInfo, i );
+ for ( w = 0; w < p->nWords; w++ )
+ pInfo[w] = pInfo2[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+{
+ unsigned * pInfo, * pInfo1, * pInfo2;
+ int k, fComp1, fComp2;
+ // simulate the internal nodes
+ assert( Abc_ObjIsNode(pNode) );
+ pInfo = Vec_PtrEntry(vSimInfo, pNode->Id);
+ pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+ pInfo2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode));
+ fComp1 = Abc_ObjFaninC0(pNode);
+ fComp2 = Abc_ObjFaninC1(pNode);
+ if ( fComp1 && fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = ~pInfo1[k] & ~pInfo2[k];
+ else if ( fComp1 && !fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = ~pInfo1[k] & pInfo2[k];
+ else if ( !fComp1 && fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = pInfo1[k] & ~pInfo2[k];
+ else // if ( fComp1 && fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = pInfo1[k] & pInfo2[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one CO node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+{
+ unsigned * pInfo, * pInfo1;
+ int k, fComp1;
+ // simulate the internal nodes
+ assert( Abc_ObjIsCo(pNode) );
+ pInfo = Vec_PtrEntry(vSimInfo, pNode->Id);
+ pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+ fComp1 = Abc_ObjFaninC0(pNode);
+ if ( fComp1 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = ~pInfo1[k];
+ else
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = pInfo1[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one round of simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPerformRound( Res_Sim_t * p, int nWords )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_InfoFill( Vec_PtrEntry(p->vPats,0), nWords );
+ Abc_AigForEachAnd( p->pAig, pObj, i )
+ Res_SimPerformOne( pObj, p->vPats, nWords );
+ Abc_NtkForEachPo( p->pAig, pObj, i )
+ Res_SimTransferOne( pObj, p->vPats, nWords );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Pads the extra space with duplicated simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords )
+{
+ unsigned * pInfo;
+ int i, w, iWords;
+ assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) );
+ // pad the first word
+ if ( nPats < 8 * sizeof(unsigned) )
+ {
+ Vec_PtrForEachEntry( vPats, pInfo, i )
+ if ( pInfo[0] & 1 )
+ pInfo[0] |= ((~0) << nPats);
+ nPats = 8 * sizeof(unsigned);
+ }
+ // pad the empty words
+ iWords = nPats / (8 * sizeof(unsigned));
+ Vec_PtrForEachEntry( vPats, pInfo, i )
+ {
+ for ( w = iWords; w < nWords; w++ )
+ pInfo[w] = pInfo[0];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the simulation info to fill the space.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimDeriveInfoReplicate( Res_Sim_t * p )
+{
+ unsigned * pInfo, * pInfo2;
+ Abc_Obj_t * pObj;
+ int i, j, w;
+ Abc_NtkForEachPo( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo2 = Vec_PtrEntry( p->vOuts, i );
+ for ( j = 0; j < p->nPats; j++ )
+ for ( w = 0; w < p->nWords; w++ )
+ *pInfo2++ = pInfo[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Complement the simulation info if necessary.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimDeriveInfoComplement( Res_Sim_t * p )
+{
+ unsigned * pInfo, * pInfo2;
+ Abc_Obj_t * pObj;
+ int i, j, w;
+ Abc_NtkForEachPo( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo2 = Vec_PtrEntry( p->vOuts, i );
+ for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords )
+ if ( Abc_InfoHasBit( pInfo, j ) )
+ for ( w = 0; w < p->nWords; w++ )
+ pInfo2[w] = ~pInfo2[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints output patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo2;
+ int i;
+ Abc_NtkForEachPo( pAig, pObj, i )
+ {
+ pInfo2 = Vec_PtrEntry( p->vOuts, i );
+ Extra_PrintBinary( stdout, pInfo2, p->nPatsOut );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints output patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPrintNodePatterns( Res_Sim_t * p, Abc_Ntk_t * pAig )
+{
+ unsigned * pInfo;
+ pInfo = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+ Extra_PrintBinary( stdout, pInfo, p->nPats );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of patters of different type.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimCountResults( Res_Sim_t * p, int * pnDcs, int * pnOnes, int * pnZeros, int fVerbose )
+{
+ unsigned char * pInfoCare, * pInfoNode;
+ int i, nTotal = 0;
+ pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
+ pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+ for ( i = 0; i < p->nBytesIn; i++ )
+ {
+ if ( !pInfoCare[i] )
+ (*pnDcs)++;
+ else if ( !pInfoNode[i] )
+ (*pnZeros)++;
+ else
+ (*pnOnes)++;
+ }
+ nTotal += *pnDcs;
+ nTotal += *pnZeros;
+ nTotal += *pnOnes;
+ if ( fVerbose )
+ {
+ printf( "Dc = %7.2f %% ", 100.0*(*pnDcs) /nTotal );
+ printf( "On = %7.2f %% ", 100.0*(*pnOnes) /nTotal );
+ printf( "Off = %7.2f %% ", 100.0*(*pnZeros)/nTotal );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of patters of different type.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimCollectPatterns( Res_Sim_t * p, int fVerbose )
+{
+ Abc_Obj_t * pObj;
+ unsigned char * pInfoCare, * pInfoNode, * pInfo;
+ int i, j;
+ pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
+ pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+ for ( i = 0; i < p->nBytesIn; i++ )
+ {
+ // skip don't-care patterns
+ if ( !pInfoCare[i] )
+ continue;
+ // separate offset and onset patterns
+ assert( pInfoNode[i] == 0 || pInfoNode[i] == 0xff );
+ if ( !pInfoNode[i] )
+ {
+ if ( p->nPats0 >= p->nPats )
+ continue;
+ Abc_NtkForEachPi( p->pAig, pObj, j )
+ {
+ if ( j == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ assert( pInfo[i] == 0 || pInfo[i] == 0xff );
+ if ( pInfo[i] )
+ Abc_InfoSetBit( Vec_PtrEntry(p->vPats0, j), p->nPats0 );
+ }
+ p->nPats0++;
+ }
+ else
+ {
+ if ( p->nPats1 >= p->nPats )
+ continue;
+ Abc_NtkForEachPi( p->pAig, pObj, j )
+ {
+ if ( j == p->nTruePis )
+ break;
+ pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
+ assert( pInfo[i] == 0 || pInfo[i] == 0xff );
+ if ( pInfo[i] )
+ Abc_InfoSetBit( Vec_PtrEntry(p->vPats1, j), p->nPats1 );
+ }
+ p->nPats1++;
+ }
+ if ( p->nPats0 >= p->nPats && p->nPats1 >= p->nPats )
+ break;
+ }
+ if ( fVerbose )
+ {
+ printf( "| " );
+ printf( "On = %3d ", p->nPats1 );
+ printf( "Off = %3d ", p->nPats0 );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the last pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SimVerifyValue( Res_Sim_t * p, int fOnSet )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo, * pInfo2;
+ int i, value;
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ if ( i == p->nTruePis )
+ break;
+ if ( fOnSet )
+ {
+ pInfo2 = Vec_PtrEntry( p->vPats1, i );
+ value = Abc_InfoHasBit( pInfo2, p->nPats1 - 1 );
+ }
+ else
+ {
+ pInfo2 = Vec_PtrEntry( p->vPats0, i );
+ value = Abc_InfoHasBit( pInfo2, p->nPats0 - 1 );
+ }
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo[0] = value ? ~0 : 0;
+ }
+ Res_SimPerformRound( p, 1 );
+ pObj = Abc_NtkPo( p->pAig, 1 );
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ assert( pInfo[0] == 0 || pInfo[0] == ~0 );
+ return pInfo[0] > 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares simulation info for candidate filtering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose )
+{
+ int i, nOnes = 0, nZeros = 0, nDcs = 0;
+ if ( fVerbose )
+ printf( "\n" );
+ // prepare the manager
+ Res_SimAdjust( p, pAig, nTruePis );
+ // estimate the number of patterns
+ Res_SimSetRandomBytes( p );
+ Res_SimPerformRound( p, p->nWordsIn );
+ Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose );
+ // collect the patterns
+ Res_SimCollectPatterns( p, fVerbose );
+ // add more patterns using constraint simulation
+ if ( p->nPats0 < 8 )
+ {
+ if ( !Res_SatSimulate( p, 16, 0 ) )
+ return p->fConst0 || p->fConst1;
+// return 0;
+// printf( "Value0 = %d\n", Res_SimVerifyValue( p, 0 ) );
+ }
+ if ( p->nPats1 < 8 )
+ {
+ if ( !Res_SatSimulate( p, 16, 1 ) )
+ return p->fConst0 || p->fConst1;
+// return 0;
+// printf( "Value1 = %d\n", Res_SimVerifyValue( p, 1 ) );
+ }
+ // generate additional patterns
+ for ( i = 0; i < 2; i++ )
+ {
+ if ( p->nPats0 > p->nPats*7/8 && p->nPats1 > p->nPats*7/8 )
+ break;
+ Res_SimSetDerivedBytes( p, i==0 );
+ Res_SimPerformRound( p, p->nWordsIn );
+ Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose );
+ Res_SimCollectPatterns( p, fVerbose );
+ }
+ // create bit-matrix info
+ if ( p->nPats0 < p->nPats )
+ Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords );
+ if ( p->nPats1 < p->nPats )
+ Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords );
+ // resimulate 0-patterns
+ Res_SimSetGiven( p, p->vPats0 );
+ Res_SimPerformRound( p, p->nWords );
+//Res_SimPrintNodePatterns( p, pAig );
+ Res_SimDeriveInfoReplicate( p );
+ // resimulate 1-patterns
+ Res_SimSetGiven( p, p->vPats1 );
+ Res_SimPerformRound( p, p->nWords );
+//Res_SimPrintNodePatterns( p, pAig );
+ Res_SimDeriveInfoComplement( p );
+ // print output patterns
+// Res_SimPrintOutPatterns( p, pAig );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resSim_old.c b/src/opt/res/resSim_old.c
new file mode 100644
index 00000000..23ce29e4
--- /dev/null
+++ b/src/opt/res/resSim_old.c
@@ -0,0 +1,521 @@
+/**CFile****************************************************************
+
+ FileName [resSim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Simulation engine.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocate simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Res_Sim_t * Res_SimAlloc( int nWords )
+{
+ Res_Sim_t * p;
+ p = ALLOC( Res_Sim_t, 1 );
+ memset( p, 0, sizeof(Res_Sim_t) );
+ // simulation parameters
+ p->nWords = nWords;
+ p->nPats = 8 * sizeof(unsigned) * p->nWords;
+ p->nWordsOut = p->nPats * p->nWords;
+ p->nPatsOut = p->nPats * p->nPats;
+ // simulation info
+ p->vPats = Vec_PtrAllocSimInfo( 1024, p->nWords );
+ p->vPats0 = Vec_PtrAllocSimInfo( 128, p->nWords );
+ p->vPats1 = Vec_PtrAllocSimInfo( 128, p->nWords );
+ p->vOuts = Vec_PtrAllocSimInfo( 128, p->nWordsOut );
+ // resub candidates
+ p->vCands = Vec_VecStart( 16 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocate simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig )
+{
+ srand( 0xABC );
+
+ assert( Abc_NtkIsStrash(pAig) );
+ p->pAig = pAig;
+ if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 )
+ {
+ Vec_PtrFree( p->vPats );
+ p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWords );
+ }
+ if ( Vec_PtrSize(p->vPats0) < Abc_NtkPiNum(pAig) )
+ {
+ Vec_PtrFree( p->vPats0 );
+ p->vPats0 = Vec_PtrAllocSimInfo( Abc_NtkPiNum(pAig), p->nWords );
+ }
+ if ( Vec_PtrSize(p->vPats1) < Abc_NtkPiNum(pAig) )
+ {
+ Vec_PtrFree( p->vPats1 );
+ p->vPats1 = Vec_PtrAllocSimInfo( Abc_NtkPiNum(pAig), p->nWords );
+ }
+ if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) )
+ {
+ Vec_PtrFree( p->vOuts );
+ p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut );
+ }
+ // clean storage info for patterns
+ Abc_InfoClear( Vec_PtrEntry(p->vPats0,0), p->nWords * Abc_NtkPiNum(pAig) );
+ Abc_InfoClear( Vec_PtrEntry(p->vPats1,0), p->nWords * Abc_NtkPiNum(pAig) );
+ p->nPats0 = 0;
+ p->nPats1 = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Free simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimFree( Res_Sim_t * p )
+{
+ Vec_PtrFree( p->vPats );
+ Vec_PtrFree( p->vPats0 );
+ Vec_PtrFree( p->vPats1 );
+ Vec_PtrFree( p->vOuts );
+ Vec_VecFree( p->vCands );
+ free( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets random PI simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimSetRandom( Res_Sim_t * p )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo;
+ int i;
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ Abc_InfoRandom( pInfo, p->nWords );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets given PI simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo, * pInfo2;
+ int i, w;
+ Abc_NtkForEachPi( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo2 = Vec_PtrEntry( vInfo, i );
+ for ( w = 0; w < p->nWords; w++ )
+ pInfo[w] = pInfo2[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+{
+ unsigned * pInfo, * pInfo1, * pInfo2;
+ int k, fComp1, fComp2;
+ // simulate the internal nodes
+ assert( Abc_ObjIsNode(pNode) );
+ pInfo = Vec_PtrEntry(vSimInfo, pNode->Id);
+ pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+ pInfo2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode));
+ fComp1 = Abc_ObjFaninC0(pNode);
+ fComp2 = Abc_ObjFaninC1(pNode);
+ if ( fComp1 && fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = ~pInfo1[k] & ~pInfo2[k];
+ else if ( fComp1 && !fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = ~pInfo1[k] & pInfo2[k];
+ else if ( !fComp1 && fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = pInfo1[k] & ~pInfo2[k];
+ else // if ( fComp1 && fComp2 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = pInfo1[k] & pInfo2[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one CO node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+{
+ unsigned * pInfo, * pInfo1;
+ int k, fComp1;
+ // simulate the internal nodes
+ assert( Abc_ObjIsCo(pNode) );
+ pInfo = Vec_PtrEntry(vSimInfo, pNode->Id);
+ pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+ fComp1 = Abc_ObjFaninC0(pNode);
+ if ( fComp1 )
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = ~pInfo1[k];
+ else
+ for ( k = 0; k < nSimWords; k++ )
+ pInfo[k] = pInfo1[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one round of simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPerformRound( Res_Sim_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_InfoFill( Vec_PtrEntry(p->vPats,0), p->nWords );
+ Abc_AigForEachAnd( p->pAig, pObj, i )
+ Res_SimPerformOne( pObj, p->vPats, p->nWords );
+ Abc_NtkForEachPo( p->pAig, pObj, i )
+ Res_SimTransferOne( pObj, p->vPats, p->nWords );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Processes simulation patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimProcessPats( Res_Sim_t * p )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfoCare, * pInfoNode;
+ int i, j, nDcs = 0;
+ pInfoCare = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
+ pInfoNode = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+ for ( i = 0; i < p->nPats; i++ )
+ {
+ // skip don't-care patterns
+ if ( !Abc_InfoHasBit(pInfoCare, i) )
+ {
+ nDcs++;
+ continue;
+ }
+ // separate offset and onset patterns
+ if ( !Abc_InfoHasBit(pInfoNode, i) )
+ {
+ if ( p->nPats0 >= p->nPats )
+ continue;
+ Abc_NtkForEachPi( p->pAig, pObj, j )
+ if ( Abc_InfoHasBit( Vec_PtrEntry(p->vPats, pObj->Id), i ) )
+ Abc_InfoSetBit( Vec_PtrEntry(p->vPats0, j), p->nPats0 );
+ p->nPats0++;
+ }
+ else
+ {
+ if ( p->nPats1 >= p->nPats )
+ continue;
+ Abc_NtkForEachPi( p->pAig, pObj, j )
+ if ( Abc_InfoHasBit( Vec_PtrEntry(p->vPats, pObj->Id), i ) )
+ Abc_InfoSetBit( Vec_PtrEntry(p->vPats1, j), p->nPats1 );
+ p->nPats1++;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Pads the extra space with duplicated simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords )
+{
+ unsigned * pInfo;
+ int i, w, iWords;
+ assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) );
+ // pad the first word
+ if ( nPats < 8 * sizeof(unsigned) )
+ {
+ Vec_PtrForEachEntry( vPats, pInfo, i )
+ if ( pInfo[0] & 1 )
+ pInfo[0] |= ((~0) << nPats);
+ nPats = 8 * sizeof(unsigned);
+ }
+ // pad the empty words
+ iWords = nPats / (8 * sizeof(unsigned));
+ Vec_PtrForEachEntry( vPats, pInfo, i )
+ {
+ for ( w = iWords; w < nWords; w++ )
+ pInfo[w] = pInfo[0];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the simulation info to fill the space.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimDeriveInfoReplicate( Res_Sim_t * p )
+{
+ unsigned * pInfo, * pInfo2;
+ Abc_Obj_t * pObj;
+ int i, j, w;
+ Abc_NtkForEachPo( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo2 = Vec_PtrEntry( p->vOuts, i );
+ for ( j = 0; j < p->nPats; j++ )
+ for ( w = 0; w < p->nWords; w++ )
+ *pInfo2++ = pInfo[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Complement the simulation info if necessary.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimDeriveInfoComplement( Res_Sim_t * p )
+{
+ unsigned * pInfo, * pInfo2;
+ Abc_Obj_t * pObj;
+ int i, j, w;
+ Abc_NtkForEachPo( p->pAig, pObj, i )
+ {
+ pInfo = Vec_PtrEntry( p->vPats, pObj->Id );
+ pInfo2 = Vec_PtrEntry( p->vOuts, i );
+ for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords )
+ if ( Abc_InfoHasBit( pInfo, j ) )
+ for ( w = 0; w < p->nWords; w++ )
+ pInfo2[w] = ~pInfo2[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Free simulation engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimReportOne( Res_Sim_t * p )
+{
+ unsigned * pInfoCare, * pInfoNode;
+ int i, nDcs, nOnes, nZeros;
+ pInfoCare = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
+ pInfoNode = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
+ nDcs = nOnes = nZeros = 0;
+ for ( i = 0; i < p->nPats; i++ )
+ {
+ // skip don't-care patterns
+ if ( !Abc_InfoHasBit(pInfoCare, i) )
+ {
+ nDcs++;
+ continue;
+ }
+ // separate offset and onset patterns
+ if ( !Abc_InfoHasBit(pInfoNode, i) )
+ nZeros++;
+ else
+ nOnes++;
+ }
+ printf( "On = %3d (%7.2f %%) ", nOnes, 100.0*nOnes/p->nPats );
+ printf( "Off = %3d (%7.2f %%) ", nZeros, 100.0*nZeros/p->nPats );
+ printf( "Dc = %3d (%7.2f %%) ", nDcs, 100.0*nDcs/p->nPats );
+ printf( "P0 = %3d ", p->nPats0 );
+ printf( "P1 = %3d ", p->nPats1 );
+ if ( p->nPats0 < 4 || p->nPats1 < 4 )
+ printf( "*" );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints output patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig )
+{
+ Abc_Obj_t * pObj;
+ unsigned * pInfo2;
+ int i;
+ Abc_NtkForEachPo( pAig, pObj, i )
+ {
+ pInfo2 = Vec_PtrEntry( p->vOuts, i );
+ Extra_PrintBinary( stdout, pInfo2, p->nPatsOut );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares simulation info for candidate filtering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose )
+{
+ int Limit;
+ // prepare the manager
+ Res_SimAdjust( p, pAig );
+ // collect 0/1 simulation info
+ for ( Limit = 0; Limit < 10; Limit++ )
+ {
+ Res_SimSetRandom( p );
+ Res_SimPerformRound( p );
+ Res_SimProcessPats( p );
+ if ( !(p->nPats0 < p->nPats || p->nPats1 < p->nPats) )
+ break;
+ }
+// printf( "%d ", Limit );
+ // report the last set of patterns
+// Res_SimReportOne( p );
+// printf( "\n" );
+ // quit if there is not enough
+// if ( p->nPats0 < 4 || p->nPats1 < 4 )
+ if ( p->nPats0 < 4 || p->nPats1 < 4 )
+ {
+// Res_SimReportOne( p );
+ return 0;
+ }
+ // create bit-matrix info
+ if ( p->nPats0 < p->nPats )
+ Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords );
+ if ( p->nPats1 < p->nPats )
+ Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords );
+ // resimulate 0-patterns
+ Res_SimSetGiven( p, p->vPats0 );
+ Res_SimPerformRound( p );
+ Res_SimDeriveInfoReplicate( p );
+ // resimulate 1-patterns
+ Res_SimSetGiven( p, p->vPats1 );
+ Res_SimPerformRound( p );
+ Res_SimDeriveInfoComplement( p );
+ // print output patterns
+// Res_SimPrintOutPatterns( p, pAig );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resStrash.c b/src/opt/res/resStrash.c
new file mode 100644
index 00000000..fde842a4
--- /dev/null
+++ b/src/opt/res/resStrash.c
@@ -0,0 +1,117 @@
+/**CFile****************************************************************
+
+ FileName [resStrash.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Structural hashing of the nodes in the window.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resStrash.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pAig, Abc_Obj_t * pObjOld );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Structurally hashes the given window.]
+
+ Description [The first PO is the observability condition. The second
+ is the node's function. The remaining POs are the candidate divisors.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Res_WndStrash( Res_Win_t * p )
+{
+ Vec_Ptr_t * vPairs;
+ Abc_Ntk_t * pAig;
+ Abc_Obj_t * pObj, * pMiter;
+ int i;
+ assert( Abc_NtkHasAig(p->pNode->pNtk) );
+// Abc_NtkCleanCopy( p->pNode->pNtk );
+ // create the network
+ pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
+ pAig->pName = Extra_UtilStrsav( "window" );
+ // create the inputs
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ pObj->pCopy = Abc_NtkCreatePi( pAig );
+ Vec_PtrForEachEntry( p->vBranches, pObj, i )
+ pObj->pCopy = Abc_NtkCreatePi( pAig );
+ // go through the nodes in the topological order
+ Vec_PtrForEachEntry( p->vNodes, pObj, i )
+ {
+ pObj->pCopy = Abc_ConvertAigToAig( pAig, pObj );
+ if ( pObj == p->pNode )
+ pObj->pCopy = Abc_ObjNot( pObj->pCopy );
+ }
+ // collect the POs
+ vPairs = Vec_PtrAlloc( 2 * Vec_PtrSize(p->vRoots) );
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ {
+ Vec_PtrPush( vPairs, pObj->pCopy );
+ Vec_PtrPush( vPairs, NULL );
+ }
+ // mark the TFO of the node
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Res_WinSweepLeafTfo_rec( p->pNode, (int)p->pNode->Level + p->nWinTfoMax );
+ // update strashing of the node
+ p->pNode->pCopy = Abc_ObjNot( p->pNode->pCopy );
+ Abc_NodeSetTravIdPrevious( p->pNode );
+ // redo strashing in the TFO
+ Vec_PtrForEachEntry( p->vNodes, pObj, i )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ pObj->pCopy = Abc_ConvertAigToAig( pAig, pObj );
+ }
+ // collect the POs
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ Vec_PtrWriteEntry( vPairs, 2 * i + 1, pObj->pCopy );
+ // add the miter
+ pMiter = Abc_AigMiter( pAig->pManFunc, vPairs );
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pMiter );
+ Vec_PtrFree( vPairs );
+ // add the node
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), p->pNode->pCopy );
+ // add the fanins
+ Abc_ObjForEachFanin( p->pNode, pObj, i )
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pObj->pCopy );
+ // add the divisors
+ Vec_PtrForEachEntry( p->vDivs, pObj, i )
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pObj->pCopy );
+ // add the names
+ Abc_NtkAddDummyPiNames( pAig );
+ Abc_NtkAddDummyPoNames( pAig );
+ // check the resulting network
+ if ( !Abc_NtkCheck( pAig ) )
+ fprintf( stdout, "Res_WndStrash(): Network check has failed.\n" );
+ return pAig;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/resWin.c b/src/opt/res/resWin.c
new file mode 100644
index 00000000..a3648925
--- /dev/null
+++ b/src/opt/res/resWin.c
@@ -0,0 +1,485 @@
+/**CFile****************************************************************
+
+ FileName [resWin.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis [Windowing algorithm.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: resWin.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "resInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the window.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Res_Win_t * Res_WinAlloc()
+{
+ Res_Win_t * p;
+ // start the manager
+ p = ALLOC( Res_Win_t, 1 );
+ memset( p, 0, sizeof(Res_Win_t) );
+ // set internal parameters
+ p->nFanoutLimit = 10;
+ p->nLevTfiMinus = 3;
+ // allocate storage
+ p->vRoots = Vec_PtrAlloc( 256 );
+ p->vLeaves = Vec_PtrAlloc( 256 );
+ p->vBranches = Vec_PtrAlloc( 256 );
+ p->vNodes = Vec_PtrAlloc( 256 );
+ p->vDivs = Vec_PtrAlloc( 256 );
+ p->vMatrix = Vec_VecStart( 128 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the window.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinFree( Res_Win_t * p )
+{
+ Vec_PtrFree( p->vRoots );
+ Vec_PtrFree( p->vLeaves );
+ Vec_PtrFree( p->vBranches );
+ Vec_PtrFree( p->vNodes );
+ Vec_PtrFree( p->vDivs );
+ Vec_VecFree( p->vMatrix );
+ free( p );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Collect the limited TFI cone of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinCollectLeavesAndNodes( Res_Win_t * p )
+{
+ Vec_Ptr_t * vFront;
+ Abc_Obj_t * pObj, * pTemp;
+ int i, k, m;
+
+ assert( p->nWinTfiMax > 0 );
+ assert( Vec_VecSize(p->vMatrix) > p->nWinTfiMax );
+
+ // start matrix with the node
+ Vec_VecClear( p->vMatrix );
+ Vec_VecPush( p->vMatrix, 0, p->pNode );
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Abc_NodeSetTravIdCurrent( p->pNode );
+
+ // collect the leaves (nodes pTemp such that "p->pNode->Level - pTemp->Level > p->nWinTfiMax")
+ Vec_PtrClear( p->vLeaves );
+ Vec_VecForEachLevelStartStop( p->vMatrix, vFront, i, 0, p->nWinTfiMax )
+ {
+ Vec_PtrForEachEntry( vFront, pObj, k )
+ {
+ Abc_ObjForEachFanin( pObj, pTemp, m )
+ {
+ if ( Abc_NodeIsTravIdCurrent( pTemp ) )
+ continue;
+ Abc_NodeSetTravIdCurrent( pTemp );
+ if ( Abc_ObjIsCi(pTemp) || (int)(p->pNode->Level - pTemp->Level) > p->nWinTfiMax )
+ Vec_PtrPush( p->vLeaves, pTemp );
+ else
+ Vec_VecPush( p->vMatrix, p->pNode->Level - pTemp->Level, pTemp );
+ }
+ }
+ }
+ if ( Vec_PtrSize(p->vLeaves) == 0 )
+ return 0;
+
+ // collect the nodes in the reverse order
+ Vec_PtrClear( p->vNodes );
+ Vec_VecForEachLevelReverseStartStop( p->vMatrix, vFront, i, p->nWinTfiMax, 0 )
+ {
+ Vec_PtrForEachEntry( vFront, pObj, k )
+ Vec_PtrPush( p->vNodes, pObj );
+ Vec_PtrClear( vFront );
+ }
+
+ // get the lowest leaf level
+ p->nLevLeafMin = ABC_INFINITY;
+ Vec_PtrForEachEntry( p->vLeaves, pObj, k )
+ p->nLevLeafMin = ABC_MIN( p->nLevLeafMin, (int)pObj->Level );
+
+ // set minimum traversal level
+ p->nLevTravMin = ABC_MAX( ((int)p->pNode->Level) - p->nWinTfiMax - p->nLevTfiMinus, p->nLevLeafMin );
+ assert( p->nLevTravMin >= 0 );
+ return 1;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the node should be a root.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Res_WinComputeRootsCheck( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ // the node is the root if one of the following is true:
+ // (1) the node has more than fanouts than the limit
+ if ( Abc_ObjFanoutNum(pNode) > nFanoutLimit )
+ return 1;
+ // (2) the node has CO fanouts
+ // (3) the node has fanouts above the cutoff level
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ if ( Abc_ObjIsCo(pFanout) || (int)pFanout->Level > nLevelMax )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively collects the root candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinComputeRoots_rec( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit, Vec_Ptr_t * vRoots )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ assert( Abc_ObjIsNode(pNode) );
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return;
+ Abc_NodeSetTravIdCurrent( pNode );
+ // check if the node should be the root
+ if ( Res_WinComputeRootsCheck( pNode, nLevelMax, nFanoutLimit ) )
+ Vec_PtrPush( vRoots, pNode );
+ else // if not, explore its fanouts
+ Abc_ObjForEachFanout( pNode, pFanout, i )
+ Res_WinComputeRoots_rec( pFanout, nLevelMax, nFanoutLimit, vRoots );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively collects the root candidates.]
+
+ Description [Returns 1 if the only root is this node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinComputeRoots( Res_Win_t * p )
+{
+ Vec_PtrClear( p->vRoots );
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Res_WinComputeRoots_rec( p->pNode, p->pNode->Level + p->nWinTfoMax, p->nFanoutLimit, p->vRoots );
+ assert( Vec_PtrSize(p->vRoots) > 0 );
+ if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode )
+ return 0;
+ return 1;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Marks the paths from the roots to the leaves.]
+
+ Description [Returns 1 if the the node can reach a leaf.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinMarkPaths_rec( Abc_Obj_t * pNode, Abc_Obj_t * pPivot, int nLevelMin )
+{
+ Abc_Obj_t * pFanin;
+ int i, RetValue;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return 1;
+ if ( Abc_NodeIsTravIdPrevious(pNode) )
+ return 0;
+ // assume that the node does not have access to the leaves
+ Abc_NodeSetTravIdPrevious( pNode );
+ // skip nodes below the given level
+ if ( pNode == pPivot || (int)pNode->Level <= nLevelMin )
+ return 0;
+ assert( Abc_ObjIsNode(pNode) );
+ // check if the fanins have access to the leaves
+ RetValue = 0;
+ Abc_ObjForEachFanin( pNode, pFanin, i )
+ RetValue |= Res_WinMarkPaths_rec( pFanin, pPivot, nLevelMin );
+ // relabel the node if it has access to the leaves
+ if ( RetValue )
+ Abc_NodeSetTravIdCurrent( pNode );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the paths from the roots to the leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinMarkPaths( Res_Win_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // mark the leaves
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // traverse from the roots and mark the nodes that can reach leaves
+ // the nodes that do not reach leaves have previous trav ID
+ // the nodes that reach leaves have current trav ID
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ Res_WinMarkPaths_rec( pObj, p->pNode, p->nLevTravMin );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Recursively collects the roots.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinFinalizeRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ assert( Abc_ObjIsNode(pObj) );
+ assert( Abc_NodeIsTravIdCurrent(pObj) );
+ // check if the node has all fanouts marked
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ if ( !Abc_NodeIsTravIdCurrent(pFanout) )
+ break;
+ // if some of the fanouts are unmarked, add the node to the roots
+ if ( i < Abc_ObjFanoutNum(pObj) )
+ Vec_PtrPushUnique( vRoots, pObj );
+ else // otherwise, call recursively
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ Res_WinFinalizeRoots_rec( pFanout, vRoots );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finalizes the roots of the window.]
+
+ Description [Roots of the window are the nodes that have at least
+ one fanout that it not in the TFO of the leaves.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinFinalizeRoots( Res_Win_t * p )
+{
+ assert( !Abc_NodeIsTravIdCurrent(p->pNode) );
+ // mark the node with the old traversal ID
+ Abc_NodeSetTravIdCurrent( p->pNode );
+ // recollect the roots
+ Vec_PtrClear( p->vRoots );
+ Res_WinFinalizeRoots_rec( p->pNode, p->vRoots );
+ assert( Vec_PtrSize(p->vRoots) > 0 );
+ if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode )
+ return 0;
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Recursively adds missing nodes and leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinAddMissing_rec( Res_Win_t * p, Abc_Obj_t * pObj, int nLevTravMin )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // skip the already collected leaves, nodes, and branches
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return;
+ // if this is not an internal node - make it a new branch
+ if ( !Abc_NodeIsTravIdPrevious(pObj) )
+ {
+ assert( Vec_PtrFind(p->vLeaves, pObj) == -1 );
+ Abc_NodeSetTravIdCurrent( pObj );
+ Vec_PtrPush( p->vBranches, pObj );
+ return;
+ }
+ assert( Abc_ObjIsNode(pObj) ); // if this is a CI, then the window is incorrect!
+ Abc_NodeSetTravIdCurrent( pObj );
+ // visit the fanins of the node
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Res_WinAddMissing_rec( p, pFanin, nLevTravMin );
+ // collect the node
+ Vec_PtrPush( p->vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds to the window nodes and leaves in the TFI of the roots.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Res_WinAddMissing( Res_Win_t * p )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // mark the leaves
+ Abc_NtkIncrementTravId( p->pNode->pNtk );
+ Vec_PtrForEachEntry( p->vLeaves, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // mark the already collected nodes
+ Vec_PtrForEachEntry( p->vNodes, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // explore from the roots
+ Vec_PtrClear( p->vBranches );
+ Vec_PtrForEachEntry( p->vRoots, pObj, i )
+ Res_WinAddMissing_rec( p, pObj, p->nLevTravMin );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the window is trivial (without TFO).]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinIsTrivial( Res_Win_t * p )
+{
+ return Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the window.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p )
+{
+ assert( Abc_ObjIsNode(pNode) );
+ assert( nWinTfiMax > 0 && nWinTfiMax < 10 );
+ assert( nWinTfoMax >= 0 && nWinTfoMax < 10 );
+
+ // initialize the window
+ p->pNode = pNode;
+ p->nWinTfiMax = nWinTfiMax;
+ p->nWinTfoMax = nWinTfoMax;
+
+ Vec_PtrClear( p->vBranches );
+ Vec_PtrClear( p->vDivs );
+ Vec_PtrClear( p->vRoots );
+ Vec_PtrPush( p->vRoots, pNode );
+
+ // compute the leaves
+ if ( !Res_WinCollectLeavesAndNodes( p ) )
+ return 0;
+
+ // compute the candidate roots
+ if ( p->nWinTfoMax > 0 && Res_WinComputeRoots(p) )
+ {
+ // mark the paths from the roots to the leaves
+ Res_WinMarkPaths( p );
+ // refine the roots and add branches and missing nodes
+ if ( Res_WinFinalizeRoots( p ) )
+ Res_WinAddMissing( p );
+ }
+
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/res/res_.c b/src/opt/res/res_.c
new file mode 100644
index 00000000..a50affd7
--- /dev/null
+++ b/src/opt/res/res_.c
@@ -0,0 +1,50 @@
+/**CFile****************************************************************
+
+ FileName [res_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Resynthesis package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 15, 2007.]
+
+ Revision [$Id: res_.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "res.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/module.make b/src/opt/ret/module.make
new file mode 100644
index 00000000..4b14365e
--- /dev/null
+++ b/src/opt/ret/module.make
@@ -0,0 +1,8 @@
+SRC += src/opt/ret/retArea.c \
+ src/opt/ret/retCore.c \
+ src/opt/ret/retDelay.c \
+ src/opt/ret/retFlow.c \
+ src/opt/ret/retIncrem.c \
+ src/opt/ret/retInit.c \
+ src/opt/ret/retLvalue.c
+
diff --git a/src/opt/ret/retArea.c b/src/opt/ret/retArea.c
new file mode 100644
index 00000000..5eec8e80
--- /dev/null
+++ b/src/opt/ret/retArea.c
@@ -0,0 +1,540 @@
+/**CFile****************************************************************
+
+ FileName [retArea.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [Min-area retiming.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retArea.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fVerbose );
+static void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward );
+static void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut );
+static Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut );
+static void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward );
+
+extern Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs min-area retiming.]
+
+ Description [Returns the number of latches reduced.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, int fVerbose )
+{
+ Abc_Ntk_t * pNtkTotal = NULL, * pNtkBottom;
+ Vec_Int_t * vValuesNew = NULL, * vValues;
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ int fOneFrame = 0;
+ assert( !fForwardOnly || !fBackwardOnly );
+ // there should not be black boxes
+ assert( Abc_NtkIsSopLogic(pNtk) );
+ assert( Abc_NtkLatchNum(pNtk) == Vec_PtrSize(pNtk->vBoxes) );
+ // reorder CI/CO/latch inputs
+ Abc_NtkOrderCisCos( pNtk );
+ // perform forward retiming
+ if ( !fBackwardOnly )
+ {
+ if ( fOneFrame )
+ Abc_NtkRetimeMinAreaOne( pNtk, 1, fVerbose );
+ else
+ while ( Abc_NtkRetimeMinAreaOne( pNtk, 1, fVerbose ) );
+ }
+ // remember initial values
+ vValues = Abc_NtkCollectLatchValues( pNtk );
+ // perform backward retiming
+ if ( !fForwardOnly )
+ {
+ if ( fOneFrame )
+ pNtkTotal = Abc_NtkRetimeMinAreaOne( pNtk, 0, fVerbose );
+ else
+ while ( pNtkBottom = Abc_NtkRetimeMinAreaOne( pNtk, 0, fVerbose ) )
+ pNtkTotal = Abc_NtkAttachBottom( pNtkTotal, pNtkBottom );
+ }
+ // compute initial values
+ vValuesNew = Abc_NtkRetimeInitialValues( pNtkTotal, vValues, fVerbose );
+ if ( pNtkTotal ) Abc_NtkDelete( pNtkTotal );
+ // insert new initial values
+ Abc_NtkInsertLatchValues( pNtk, vValuesNew );
+ if ( vValuesNew ) Vec_IntFree( vValuesNew );
+ if ( vValues ) Vec_IntFree( vValues );
+ // fix the COs (this changes the circuit structure)
+// Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+ // check for correctness
+ if ( !Abc_NtkCheck( pNtk ) )
+ fprintf( stdout, "Abc_NtkRetimeMinArea(): Network check has failed.\n" );
+ // return the number of latches saved
+ return nLatches - Abc_NtkLatchNum(pNtk);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs min-area retiming backward.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fVerbose )
+{
+ Abc_Ntk_t * pNtkNew = NULL;
+ Vec_Ptr_t * vMinCut;
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ // mark current latches and TFI(POs)
+ Abc_NtkRetimeMinAreaPrepare( pNtk, fForward );
+ // run the maximum forward flow
+ vMinCut = Abc_NtkMaxFlow( pNtk, fForward, fVerbose );
+// assert( Vec_PtrSize(vMinCut) <= Abc_NtkLatchNum(pNtk) );
+ // create new latch boundary if there is improvement
+ if ( Vec_PtrSize(vMinCut) < Abc_NtkLatchNum(pNtk) )
+ {
+ pNtkNew = (Abc_Ntk_t *)1;
+ if ( fForward )
+ Abc_NtkRetimeMinAreaInitValues( pNtk, vMinCut );
+ else
+ pNtkNew = Abc_NtkRetimeMinAreaConstructNtk( pNtk, vMinCut );
+ Abc_NtkRetimeMinAreaUpdateLatches( pNtk, vMinCut, fForward );
+ }
+ // clean up
+ Vec_PtrFree( vMinCut );
+ Abc_NtkCleanMarkA( pNtk );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the cone with MarkA.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ if ( pObj->fMarkA )
+ return;
+ pObj->fMarkA = 1;
+ if ( fForward )
+ {
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ Abc_NtkMarkCone_rec( pNext, fForward );
+ }
+ else
+ {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ Abc_NtkMarkCone_rec( pNext, fForward );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the cone with MarkA.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkUnmarkCone_rec( Abc_Obj_t * pObj, int fForward )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ if ( !pObj->fMarkA || Abc_ObjIsLatch(pObj) )
+ return;
+ pObj->fMarkA = 0;
+ if ( fForward )
+ {
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ Abc_NtkUnmarkCone_rec( pNext, fForward );
+ }
+ else
+ {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ Abc_NtkUnmarkCone_rec( pNext, fForward );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the network for running MaxFlow.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k;
+ if ( fForward )
+ {
+ // mark the frontier
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ pObj->fMarkA = 1;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pObj->fMarkA = 1;
+ Abc_ObjFanin0(pObj)->fMarkA = 1;
+ }
+ // mark the nodes reachable from the PIs
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ Abc_NtkMarkCone_rec( pObj, fForward );
+ // collect the unmarked fanins of the marked nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( pObj->fMarkA )
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ if ( !pFanin->fMarkA )
+ Vec_PtrPush( vNodes, pFanin );
+ // mark these nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->fMarkA = 1;
+ Vec_PtrFree( vNodes );
+ }
+ else
+ {
+ // mark the frontier
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->fMarkA = 1;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pObj->fMarkA = 1;
+ Abc_ObjFanout0(pObj)->fMarkA = 1;
+ }
+ // mark the nodes reachable from the POs
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ Abc_NtkMarkCone_rec( pObj, fForward );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute initial values.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeMinAreaInitValues_rec( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return (int)pObj->pCopy;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // consider the case of a latch output
+ if ( Abc_ObjIsBo(pObj) )
+ {
+ assert( Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) );
+ pObj->pCopy = (void *)Abc_NtkRetimeMinAreaInitValues_rec( Abc_ObjFanin0(pObj) );
+ return (int)pObj->pCopy;
+ }
+ assert( Abc_ObjIsNode(pObj) );
+ // visit the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Abc_NtkRetimeMinAreaInitValues_rec( pFanin );
+ // compute the value of the node
+ pObj->pCopy = (void *)Abc_ObjSopSimulate(pObj);
+ return (int)pObj->pCopy;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute initial values.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // transfer initial values to pCopy and mark the latches
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pObj->pCopy = (void *)Abc_LatchIsInit1(pObj);
+ Abc_NodeSetTravIdCurrent( pObj );
+ }
+ // propagate initial values
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ Abc_NtkRetimeMinAreaInitValues_rec( pObj );
+ // unmark the latches
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_NodeSetTravIdPrevious( pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs min-area retiming backward.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_NtkRetimeMinAreaConstructNtk_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return pObj->pCopy;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // consider the case of a latch output
+ if ( Abc_ObjIsBi(pObj) )
+ {
+ pObj->pCopy = Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, Abc_ObjFanin0(pObj) );
+ return pObj->pCopy;
+ }
+ assert( Abc_ObjIsNode(pObj) );
+ // visit the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, pFanin );
+ // compute the value of the node
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
+ return pObj->pCopy;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the network from computing initial state.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj, * pObjNew;
+ int i;
+ // create new network
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+ // map new latches into PIs of the new network
+ Abc_NtkIncrementTravId(pNtk);
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ {
+ pObj->pCopy = Abc_NtkCreatePi(pNtkNew);
+ Abc_NodeSetTravIdCurrent( pObj );
+ }
+ // construct the network recursively
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ pObjNew = Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, Abc_ObjFanin0(pObj) );
+ Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObjNew );
+ }
+ // unmark the nodes in the cut
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ Abc_NodeSetTravIdPrevious( pObj );
+ // unmark the latches
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_NodeSetTravIdPrevious( pObj );
+ // assign dummy node names
+ Abc_NtkAddDummyPiNames( pNtkNew );
+ Abc_NtkAddDummyPoNames( pNtkNew );
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkRetimeMinAreaConstructNtk(): Network check has failed.\n" );
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the network after backward retiming.]
+
+ Description [Assumes that fMarkA denotes all nodes reachabe from
+ the latches toward the cut.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward )
+{
+ Vec_Ptr_t * vCis, * vCos, * vBoxes, * vBoxesNew, * vNodes, * vBuffers;
+ Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut, * pNext, * pBuffer;
+ int i, k;
+ // create new latches
+ Vec_PtrShrink( pNtk->vCis, Abc_NtkCiNum(pNtk) - Abc_NtkLatchNum(pNtk) );
+ Vec_PtrShrink( pNtk->vCos, Abc_NtkCoNum(pNtk) - Abc_NtkLatchNum(pNtk) );
+ vCis = pNtk->vCis; pNtk->vCis = NULL;
+ vCos = pNtk->vCos; pNtk->vCos = NULL;
+ vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL;
+ // transfer boxes
+ vBoxesNew = Vec_PtrAlloc(100);
+ Vec_PtrForEachEntry( vBoxes, pObj, i )
+ if ( !Abc_ObjIsLatch(pObj) )
+ Vec_PtrPush( vBoxesNew, pObj );
+ // create or reuse latches
+ vNodes = Vec_PtrAlloc( 100 );
+ vBuffers = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ {
+ if ( Abc_ObjIsCi(pObj) && fForward )
+ {
+ pLatchOut = pObj;
+ pLatch = Abc_ObjFanin0(pLatchOut);
+ pLatchIn = Abc_ObjFanin0(pLatch);
+ assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) );
+ // mark the latch as reused
+ Abc_NodeSetTravIdCurrent( pLatch );
+
+ // check if there are marked fanouts
+ // (these are fanouts to be connected to the latch input)
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ if ( pNext->fMarkA )
+ break;
+ if ( k < Abc_ObjFanoutNum(pObj) )
+ {
+ // add the buffer
+ pBuffer = Abc_NtkCreateNodeBuf( pNtk, Abc_ObjFanin0(pLatchIn) );
+ Abc_ObjPatchFanin( pLatchIn, Abc_ObjFanin0(pLatchIn), pBuffer );
+ Vec_PtrPush( vBuffers, pBuffer );
+ // redirect edges to the unvisited fanouts of the node
+ Abc_NodeCollectFanouts( pObj, vNodes );
+ Vec_PtrForEachEntry( vNodes, pNext, k )
+ if ( pNext->fMarkA )
+ Abc_ObjPatchFanin( pNext, pObj, pBuffer );
+ }
+ assert( Abc_ObjFanoutNum(pObj) > 0 );
+// if ( Abc_ObjFanoutNum(pObj) == 0 )
+// Abc_NtkDeleteObj_rec( pObj, 0 );
+ }
+ else if ( Abc_ObjIsCo(pObj) && !fForward )
+ {
+ pLatchIn = pObj;
+ pLatch = Abc_ObjFanout0(pLatchIn);
+ pLatchOut = Abc_ObjFanout0(pLatch);
+ assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) );
+ // mark the latch as reused
+ Abc_NodeSetTravIdCurrent( pLatch );
+ assert( !Abc_ObjFanin0(pLatchIn)->fMarkA );
+ }
+ else
+ {
+ pLatchOut = Abc_NtkCreateBo(pNtk);
+ pLatch = Abc_NtkCreateLatch(pNtk);
+ pLatchIn = Abc_NtkCreateBi(pNtk);
+ Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" );
+ Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_in" );
+ // connect
+ Abc_ObjAddFanin( pLatchOut, pLatch );
+ Abc_ObjAddFanin( pLatch, pLatchIn );
+ if ( fForward )
+ {
+ pLatch->pData = (void *)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO);
+ // redirect edges to the unvisited fanouts of the node
+ Abc_NodeCollectFanouts( pObj, vNodes );
+ Vec_PtrForEachEntry( vNodes, pNext, k )
+ if ( !pNext->fMarkA )
+ Abc_ObjPatchFanin( pNext, pObj, pLatchOut );
+ }
+ else
+ {
+ // redirect edges to the visited fanouts of the node
+ Abc_NodeCollectFanouts( pObj, vNodes );
+ Vec_PtrForEachEntry( vNodes, pNext, k )
+ if ( pNext->fMarkA )
+ Abc_ObjPatchFanin( pNext, pObj, pLatchOut );
+ }
+ // connect latch to the node
+ Abc_ObjAddFanin( pLatchIn, pObj );
+ }
+ Vec_PtrPush( vCis, pLatchOut );
+ Vec_PtrPush( vBoxesNew, pLatch );
+ Vec_PtrPush( vCos, pLatchIn );
+ }
+ Vec_PtrFree( vNodes );
+ // remove buffers
+ Vec_PtrForEachEntry( vBuffers, pObj, i )
+ {
+ Abc_ObjTransferFanout( pObj, Abc_ObjFanin0(pObj) );
+ Abc_NtkDeleteObj( pObj );
+ }
+ Vec_PtrFree( vBuffers );
+ // remove useless latches
+ Vec_PtrForEachEntry( vBoxes, pObj, i )
+ {
+ if ( !Abc_ObjIsLatch(pObj) )
+ continue;
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ continue;
+ pLatchOut = Abc_ObjFanout0(pObj);
+ pLatch = pObj;
+ pLatchIn = Abc_ObjFanin0(pObj);
+ if ( Abc_ObjFanoutNum(pLatchOut) > 0 )
+ Abc_ObjTransferFanout( pLatchOut, Abc_ObjFanin0(pLatchIn) );
+ Abc_NtkDeleteObj( pLatchOut );
+ Abc_NtkDeleteObj( pObj );
+ Abc_NtkDeleteObj( pLatchIn );
+ }
+ // set the arrays
+ pNtk->vCis = vCis;
+ pNtk->vCos = vCos;
+ pNtk->vBoxes = vBoxesNew;
+ Vec_PtrFree( vBoxes );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retCore.c b/src/opt/ret/retCore.c
new file mode 100644
index 00000000..47b2cbbc
--- /dev/null
+++ b/src/opt/ret/retCore.c
@@ -0,0 +1,132 @@
+/**CFile****************************************************************
+
+ FileName [retCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [The core retiming procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retCore.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+int timeRetime = 0;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Implementation of retiming.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose )
+{
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ int nLevels = Abc_NtkLevel(pNtk);
+ int RetValue = 0, clkTotal = clock();
+ int nNodesOld, nLatchesOld;
+ assert( Mode > 0 && Mode < 7 );
+ assert( !fForwardOnly || !fBackwardOnly );
+
+ // cleanup the network
+ nNodesOld = Abc_NtkNodeNum(pNtk);
+ nLatchesOld = Abc_NtkLatchNum(pNtk);
+ Abc_NtkCleanupSeq(pNtk, 0, 0, 0);
+ if ( nNodesOld > Abc_NtkNodeNum(pNtk) || nLatchesOld > Abc_NtkLatchNum(pNtk) )
+ printf( "Cleanup before retiming removed %d dangling nodes and %d dangling latches.\n",
+ nNodesOld - Abc_NtkNodeNum(pNtk), nLatchesOld - Abc_NtkLatchNum(pNtk) );
+
+ // perform retiming
+ switch ( Mode )
+ {
+ case 1: // forward
+ RetValue = Abc_NtkRetimeIncremental( pNtk, 1, 0, 0, fVerbose );
+ break;
+ case 2: // backward
+ RetValue = Abc_NtkRetimeIncremental( pNtk, 0, 0, 0, fVerbose );
+ break;
+ case 3: // min-area
+ RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fVerbose );
+ break;
+ case 4: // min-delay
+ if ( !fBackwardOnly )
+ RetValue += Abc_NtkRetimeIncremental( pNtk, 1, 1, fOneStep, fVerbose );
+ if ( !fForwardOnly )
+ RetValue += Abc_NtkRetimeIncremental( pNtk, 0, 1, fOneStep, fVerbose );
+ break;
+ case 5: // min-area + min-delay
+ RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fVerbose );
+ if ( !fBackwardOnly )
+ RetValue += Abc_NtkRetimeIncremental( pNtk, 1, 1, 0, fVerbose );
+ if ( !fForwardOnly )
+ RetValue += Abc_NtkRetimeIncremental( pNtk, 0, 1, 0, fVerbose );
+ break;
+ case 6: // Pan's algorithm
+ RetValue = Abc_NtkRetimeLValue( pNtk, 500, fVerbose );
+ break;
+ default:
+ printf( "Unknown retiming option.\n" );
+ break;
+ }
+ if ( fVerbose )
+ {
+ printf( "Reduction in area = %3d. Reduction in delay = %3d. ",
+ nLatches - Abc_NtkLatchNum(pNtk), nLevels - Abc_NtkLevel(pNtk) );
+ PRT( "Total runtime", clock() - clkTotal );
+ }
+ timeRetime = clock() - clkTotal;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Used for automated debugging.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk )
+{
+ extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose );
+ Abc_Ntk_t * pNtkRet;
+ assert( Abc_NtkIsLogic(pNtk) );
+ Abc_NtkToSop( pNtk, 0 );
+// if ( !Abc_NtkCheck( pNtk ) )
+// fprintf( stdout, "Abc_NtkRetimeDebug(): Network check has failed.\n" );
+// Io_WriteBlifLogic( pNtk, "debug_temp.blif", 1 );
+ pNtkRet = Abc_NtkDup( pNtk );
+ Abc_NtkRetime( pNtkRet, 3, 0, 1, 0, 0 ); // debugging backward flow
+ return !Abc_NtkSecFraig( pNtk, pNtkRet, 10000, 3, 0 );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retDelay.c b/src/opt/ret/retDelay.c
new file mode 100644
index 00000000..bcfe3a2e
--- /dev/null
+++ b/src/opt/ret/retDelay.c
@@ -0,0 +1,305 @@
+/**CFile****************************************************************
+
+ FileName [retDelay.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [Incremental retiming for optimum delay.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retDelay.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose );
+static int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical );
+static int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Retimes incrementally for minimum delay.]
+
+ Description [This procedure cannot be called in the application code
+ because it assumes that the network is preprocessed by removing LIs/LOs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nIterLimit, int fForward, int fVerbose )
+{
+ int IterBest, DelayBest;
+ int IterBest2, DelayBest2;
+ // try to find the best delay iteration on a copy
+ DelayBest = Abc_NtkRetimeMinDelayTry( pNtkCopy, fForward, 0, nIterLimit, &IterBest, fVerbose );
+ if ( IterBest == 0 )
+ return 1;
+ // perform the given number of iterations on the original network
+ DelayBest2 = Abc_NtkRetimeMinDelayTry( pNtk, fForward, 1, IterBest, &IterBest2, fVerbose );
+ assert( DelayBest == DelayBest2 );
+ assert( IterBest == IterBest2 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the best delay and the number of best iteration.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose )
+{
+ Abc_Ntk_t * pNtkNew = NULL;
+ Vec_Ptr_t * vCritical;
+ Vec_Int_t * vValues;
+ Abc_Obj_t * pObj;
+ int i, k, IterBest, DelayCur, DelayBest, DelayStart, LatchesBest;
+ // transfer intitial values
+ if ( fInitial )
+ {
+ if ( fForward )
+ Abc_NtkRetimeTranferToCopy( pNtk );
+ else
+ {
+ // save initial value of the latches
+ vValues = Abc_NtkRetimeCollectLatchValues( pNtk );
+ // start the network for initial value computation
+ pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk );
+ }
+ }
+
+if ( fVerbose && !fInitial )
+ printf( "Performing analysis:\n" );
+ // find the best iteration
+ DelayBest = ABC_INFINITY; IterBest = 0; LatchesBest = Abc_NtkLatchNum(pNtk);
+ vCritical = Vec_PtrAlloc( 100 );
+ for ( i = 0; ; i++ )
+ {
+ // perform moves for the timing-critical nodes
+ DelayCur = Abc_NtkRetimeTiming( pNtk, fForward, vCritical );
+ if ( i == 0 )
+ DelayStart = DelayCur;
+ // record this position if it has the best delay
+ if ( DelayBest > DelayCur )
+ {
+if ( fVerbose && !fInitial )
+ printf( "%s Iter = %3d. Delay = %3d. Latches = %5d. Delta = %6.2f. Ratio = %4.2f %%\n",
+ fForward ? "Fwd": "Bwd", i, DelayCur, Abc_NtkLatchNum(pNtk),
+ 1.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/(DelayBest-DelayCur),
+ 100.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/Abc_NtkLatchNum(pNtk)/(DelayBest-DelayCur) );
+
+ DelayBest = DelayCur;
+ IterBest = i;
+ LatchesBest = Abc_NtkLatchNum(pNtk);
+ }
+ // quit after timing analysis
+ if ( i == nIterLimit )
+ break;
+ // skip if 10 interations did not give improvement
+ if ( i - IterBest > 20 )
+ break;
+ // try retiming to improve the delay
+ Vec_PtrForEachEntry( vCritical, pObj, k )
+ if ( Abc_NtkRetimeNodeIsEnabled(pObj, fForward) )
+ Abc_NtkRetimeNode( pObj, fForward, fInitial );
+ // share latches
+ if ( !fForward )
+ Abc_NtkRetimeShareLatches( pNtk, fInitial );
+ }
+ Vec_PtrFree( vCritical );
+ // transfer the initial state back to the latches
+ if ( fInitial )
+ {
+ if ( fForward )
+ Abc_NtkRetimeTranferFromCopy( pNtk );
+ else
+ {
+ Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose );
+ Abc_NtkDelete( pNtkNew );
+ Vec_IntFree( vValues );
+ }
+ }
+if ( fVerbose && !fInitial )
+ printf( "%s : Starting delay = %3d. Final delay = %3d. IterBest = %2d (out of %2d).\n",
+ fForward? "Forward " : "Backward", DelayStart, DelayBest, IterBest, nIterLimit );
+ *pIterBest = (nIterLimit == 1) ? 1 : IterBest;
+ return DelayBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the set of timing-critical nodes.]
+
+ Description [Performs static timing analysis on the network. Uses
+ unit-delay model.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical )
+{
+ Vec_Ptr_t * vLatches;
+ Abc_Obj_t * pObj, * pNext;
+ int i, k, LevelCur, LevelMax = 0;
+ // mark all objects except nodes
+ Abc_NtkIncrementTravId(pNtk);
+ vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( Abc_ObjIsLatch(pObj) )
+ Vec_PtrPush( vLatches, pObj );
+ if ( Abc_ObjIsNode(pObj) )
+ continue;
+ pObj->Level = 0;
+ Abc_NodeSetTravIdCurrent( pObj );
+ }
+ // perform analysis from CIs/COs
+ if ( fForward )
+ {
+ Vec_PtrForEachEntry( vLatches, pObj, i )
+ {
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ {
+ LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ }
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ {
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ {
+ LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ }
+ }
+ else
+ {
+ Vec_PtrForEachEntry( vLatches, pObj, i )
+ {
+ LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ {
+ LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ }
+ // collect timing critical nodes, which should be retimed forward/backward
+ Vec_PtrClear( vCritical );
+ Abc_NtkIncrementTravId(pNtk);
+ if ( fForward )
+ {
+ Vec_PtrForEachEntry( vLatches, pObj, i )
+ {
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pNext) )
+ continue;
+ if ( LevelMax != (int)pNext->Level )
+ continue;
+ // new critical node
+ Vec_PtrPush( vCritical, pNext );
+ Abc_NodeSetTravIdCurrent( pNext );
+ }
+ }
+ }
+ else
+ {
+ Vec_PtrForEachEntry( vLatches, pObj, i )
+ {
+ Abc_ObjForEachFanin( pObj, pNext, k )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pNext) )
+ continue;
+ if ( LevelMax != (int)pNext->Level )
+ continue;
+ // new critical node
+ Vec_PtrPush( vCritical, pNext );
+ Abc_NodeSetTravIdCurrent( pNext );
+ }
+ }
+ }
+ Vec_PtrFree( vLatches );
+ return LevelMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively performs timing analysis.]
+
+ Description [Performs static timing analysis on the network. Uses
+ unit-delay model.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward )
+{
+ Abc_Obj_t * pNext;
+ int i, LevelCur, LevelMax = 0;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return pObj->Level;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // visit the next nodes
+ if ( fForward )
+ {
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ {
+ LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ }
+ else
+ {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ {
+ LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ }
+// printf( "Node %3d -> Level %3d.\n", pObj->Id, LevelMax + 1 );
+ pObj->Level = LevelMax + 1;
+ return pObj->Level;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retFlow.c b/src/opt/ret/retFlow.c
new file mode 100644
index 00000000..47ee8516
--- /dev/null
+++ b/src/opt/ret/retFlow.c
@@ -0,0 +1,783 @@
+/**CFile****************************************************************
+
+ FileName [retFlow.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Implementation of maximum flow (min-area retiming).]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retFlow.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Abc_ObjSetPath( Abc_Obj_t * pObj, Abc_Obj_t * pNext ) { pObj->pCopy = pNext; return 1; }
+static inline Abc_Obj_t * Abc_ObjGetPath( Abc_Obj_t * pObj ) { return pObj->pCopy; }
+static inline Abc_Obj_t * Abc_ObjGetFanoutPath( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ assert( Abc_ObjGetPath(pObj) );
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ if ( Abc_ObjGetPath(pFanout) == pObj )
+ return pFanout;
+ return NULL;
+}
+static inline Abc_Obj_t * Abc_ObjGetFaninPath( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanin;
+ int i;
+ assert( Abc_ObjGetPath(pObj) );
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ if ( Abc_ObjGetPath(pFanin) == pObj )
+ return pFanin;
+ return NULL;
+}
+static inline Abc_Obj_t * Abc_ObjGetPredecessorBwd( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if ( Abc_ObjGetPath(pNext) == pObj )
+ return pNext;
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if ( Abc_ObjGetPath(pNext) == pObj )
+ return pNext;
+ return NULL;
+}
+static inline Abc_Obj_t * Abc_ObjGetPredecessorFwd( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if ( Abc_ObjGetPath(pNext) == pObj )
+ return pNext;
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if ( Abc_ObjGetPath(pNext) == pObj )
+ return pNext;
+ return NULL;
+}
+
+static int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj );
+static int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj );
+static int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj );
+static int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj );
+//static int Abc_NtkMaxFlowBwdPath3_rec( Abc_Obj_t * pObj );
+static int Abc_NtkMaxFlowFwdPath3_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPrev, int fFanin );
+static Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward );
+static void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward );
+static int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward );
+static void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut );
+static void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Test-bench for the max-flow computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vMinCut;
+ Abc_Obj_t * pObj;
+ int i;
+
+ // forward flow
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ pObj->fMarkA = 1;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->fMarkA = Abc_ObjFanin0(pObj)->fMarkA = 1;
+// Abc_ObjFanin0(pObj)->fMarkA = 1;
+ vMinCut = Abc_NtkMaxFlow( pNtk, 1, 1 );
+ Vec_PtrFree( vMinCut );
+ Abc_NtkCleanMarkA( pNtk );
+
+ // backward flow
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->fMarkA = 1;
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->fMarkA = Abc_ObjFanout0(pObj)->fMarkA = 1;
+// Abc_ObjFanout0(pObj)->fMarkA = 1;
+ vMinCut = Abc_NtkMaxFlow( pNtk, 0, 1 );
+ Vec_PtrFree( vMinCut );
+ Abc_NtkCleanMarkA( pNtk );
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implementation of max-flow/min-cut computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose )
+{
+ Vec_Ptr_t * vMinCut;
+ Abc_Obj_t * pLatch;
+ int Flow, FlowCur, RetValue, i;
+ int clk = clock();
+ int fUseDirectedFlow = 1;
+
+ // find the max-flow
+ Abc_NtkCleanCopy( pNtk );
+ Flow = 0;
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if ( fForward )
+ {
+// assert( !Abc_ObjFanout0(pLatch)->fMarkA );
+ FlowCur = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) );
+// FlowCur = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 );
+ Flow += FlowCur;
+ }
+ else
+ {
+ assert( !Abc_ObjFanin0(pLatch)->fMarkA );
+ FlowCur = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) );
+ Flow += FlowCur;
+ }
+ if ( FlowCur )
+ Abc_NtkIncrementTravId(pNtk);
+ }
+
+ if ( !fUseDirectedFlow )
+ {
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if ( fForward )
+ {
+ // assert( !Abc_ObjFanout0(pLatch)->fMarkA );
+ FlowCur = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) );
+ Flow += FlowCur;
+ }
+ else
+ {
+ assert( !Abc_ObjFanin0(pLatch)->fMarkA );
+ FlowCur = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) );
+ Flow += FlowCur;
+ }
+ if ( FlowCur )
+ Abc_NtkIncrementTravId(pNtk);
+ }
+ }
+// Abc_NtkMaxFlowPrintFlow( pNtk, fForward );
+
+ // mark the nodes reachable from the latches
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ if ( fForward )
+ {
+// assert( !Abc_ObjFanout0(pLatch)->fMarkA );
+ if ( fUseDirectedFlow )
+ RetValue = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) );
+// RetValue = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 );
+ else
+ RetValue = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) );
+ }
+ else
+ {
+ assert( !Abc_ObjFanin0(pLatch)->fMarkA );
+ if ( fUseDirectedFlow )
+ RetValue = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) );
+ else
+ RetValue = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) );
+ }
+ assert( RetValue == 0 );
+ }
+
+ // find the min-cut with the smallest volume
+ vMinCut = Abc_NtkMaxFlowMinCut( pNtk, fForward );
+ // verify the cut
+ if ( !Abc_NtkMaxFlowVerifyCut(pNtk, vMinCut, fForward) )
+ printf( "Abc_NtkMaxFlow() error! The computed min-cut is not a cut!\n" );
+ // make the cut retimable
+ Abc_NtkMaxFlowMinCutUpdate( pNtk, vMinCut, fForward );
+
+ // report the results
+ if ( fVerbose )
+ {
+ printf( "L = %6d. %s max-flow = %6d. Min-cut = %6d. ",
+ Abc_NtkLatchNum(pNtk), fForward? "Forward " : "Backward", Flow, Vec_PtrSize(vMinCut) );
+PRT( "Time", clock() - clk );
+ }
+
+// Abc_NtkMaxFlowPrintCut( pNtk, vMinCut );
+ return vMinCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find an augmenting path originating in this node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pNext, * pPred;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // get the predecessor
+ pPred = Abc_ObjGetPredecessorBwd( pObj );
+ // process node without flow
+ if ( !Abc_ObjGetPath(pObj) )
+ {
+ // start the path if we reached a terminal node
+ if ( pObj->fMarkA )
+ return Abc_ObjSetPath( pObj, (void *)1 );
+ // explore the fanins
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) )
+ return Abc_ObjSetPath( pObj, pNext );
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) )
+ return Abc_ObjSetPath( pObj, pNext );
+ return 0;
+ }
+ // pObj has flow - find the fanout with flow
+ if ( pPred == NULL )
+ return 0;
+ // go through the successors of the predecessor
+ Abc_ObjForEachFanin( pPred, pNext, i )
+ if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) )
+ return Abc_ObjSetPath( pPred, pNext );
+ Abc_ObjForEachFanout( pPred, pNext, i )
+ if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) )
+ return Abc_ObjSetPath( pPred, pNext );
+ // try the fanout
+ if ( Abc_NtkMaxFlowBwdPath_rec( pPred ) )
+ return Abc_ObjSetPath( pPred, NULL );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find an augmenting path originating in this node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pNext, * pPred;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // get the predecessor
+ pPred = Abc_ObjGetPredecessorFwd( pObj );
+ // process node without flow
+ if ( !Abc_ObjGetPath(pObj) )
+ {
+ // start the path if we reached a terminal node
+ if ( pObj->fMarkA )
+ return Abc_ObjSetPath( pObj, (void *)1 );
+ // explore the fanins
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) )
+ return Abc_ObjSetPath( pObj, pNext );
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) )
+ return Abc_ObjSetPath( pObj, pNext );
+ return 0;
+ }
+ // pObj has flow - find the fanout with flow
+ if ( pPred == NULL )
+ return 0;
+ // go through the successors of the predecessor
+ Abc_ObjForEachFanout( pPred, pNext, i )
+ if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) )
+ return Abc_ObjSetPath( pPred, pNext );
+ Abc_ObjForEachFanin( pPred, pNext, i )
+ if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) )
+ return Abc_ObjSetPath( pPred, pNext );
+ // try the fanout
+ if ( Abc_NtkMaxFlowFwdPath_rec( pPred ) )
+ return Abc_ObjSetPath( pPred, NULL );
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find an augmenting path originating in this edge.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowFwdPath3_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPrev, int fFanin )
+{
+ Abc_Obj_t * pFanin, * pFanout;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // skip the fanin which already has flow
+ if ( fFanin && Abc_ObjGetPath(pPrev) )
+ return 0;
+ // if the node has no flow, try to push through the fanouts
+ if ( !Abc_ObjGetPath(pObj) )
+ {
+ // start the path if we reached a terminal node
+ if ( pObj->fMarkA )
+ return Abc_ObjSetPath( pObj, (void *)1 );
+ // try to push flow through the fanouts
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ if ( Abc_NtkMaxFlowFwdPath3_rec(pFanout, pObj, 1) )
+ return fFanin? Abc_ObjSetPath(pPrev, pObj) : 1;
+ }
+ // try to push through the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ if ( !Abc_ObjIsLatch(pFanin) && Abc_NtkMaxFlowFwdPath3_rec(pFanin, pObj, 0) )
+ return Abc_ObjSetPath( pFanin, NULL );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find an augmenting path originating in this node.]
+
+ Description [This procedure works for directed graphs only!]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout, * pFanin;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // process node without flow
+ if ( !Abc_ObjGetPath(pObj) )
+ {
+ // start the path if we reached a terminal node
+ if ( pObj->fMarkA )
+ return Abc_ObjSetPath( pObj, (void *)1 );
+ // explore the fanins
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) )
+ return Abc_ObjSetPath( pObj, pFanin );
+ return 0;
+ }
+ // pObj has flow - find the fanout with flow
+ pFanout = Abc_ObjGetFanoutPath( pObj );
+ if ( pFanout == NULL )
+ return 0;
+ // go through the fanins of the fanout with flow
+ Abc_ObjForEachFanin( pFanout, pFanin, i )
+ if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) )
+ return Abc_ObjSetPath( pFanout, pFanin );
+ // try the fanout
+ if ( Abc_NtkMaxFlowBwdPath2_rec( pFanout ) )
+ return Abc_ObjSetPath( pFanout, NULL );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find an augmenting path originating in this node.]
+
+ Description [This procedure works for directed graphs only!]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout, * pFanin;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 0;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // process node without flow
+ if ( !Abc_ObjGetPath(pObj) )
+ {
+ // start the path if we reached a terminal node
+ if ( pObj->fMarkA )
+ return Abc_ObjSetPath( pObj, (void *)1 );
+ // explore the fanins
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ if ( Abc_NtkMaxFlowFwdPath2_rec(pFanout) )
+ return Abc_ObjSetPath( pObj, pFanout );
+ return 0;
+ }
+ // pObj has flow - find the fanout with flow
+ pFanin = Abc_ObjGetFaninPath( pObj );
+ if ( pFanin == NULL )
+ return 0;
+ // go through the fanins of the fanout with flow
+ Abc_ObjForEachFanout( pFanin, pFanout, i )
+ if ( Abc_NtkMaxFlowFwdPath2_rec( pFanout ) )
+ return Abc_ObjSetPath( pFanin, pFanout );
+ // try the fanout
+ if ( Abc_NtkMaxFlowFwdPath2_rec( pFanin ) )
+ return Abc_ObjSetPath( pFanin, NULL );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find minimum-volume minumum cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward )
+{
+ Vec_Ptr_t * vMinCut;
+ Abc_Obj_t * pObj;
+ int i;
+ // collect the cut nodes
+ vMinCut = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ // node without flow is not a cut node
+ if ( !Abc_ObjGetPath(pObj) )
+ continue;
+ // unvisited node is below the cut
+ if ( !Abc_NodeIsTravIdCurrent(pObj) )
+ continue;
+ // add terminal with flow or node whose path is not visited
+ if ( pObj->fMarkA || !Abc_NodeIsTravIdCurrent( Abc_ObjGetPath(pObj) ) )
+ Vec_PtrPush( vMinCut, pObj );
+ }
+ return vMinCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFI cone with MarkA.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMaxFlowMarkCut_rec( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ if ( pObj->fMarkA )
+ return;
+ pObj->fMarkA = 1;
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ Abc_NtkMaxFlowMarkCut_rec( pNext );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Visits the TFI up to marked nodes and collects marked nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMaxFlowCollectCut_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return;
+ Abc_NodeSetTravIdCurrent(pObj);
+ if ( pObj->fMarkA )
+ {
+ Vec_PtrPush( vNodes, pObj );
+ return;
+ }
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ Abc_NtkMaxFlowCollectCut_rec( pNext, vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the minimum cut to be retimable.]
+
+ Description [This procedure also labels the nodes reachable from
+ the latches to the cut with fMarkA.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward )
+{
+ Abc_Obj_t * pObj, * pNext;
+ int i, k;
+ // clean marks
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->fMarkA = 0;
+ // set latch outputs
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjFanout0(pObj)->fMarkA = 1;
+ // traverse from cut nodes
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ Abc_NtkMaxFlowMarkCut_rec( pObj );
+ if ( fForward )
+ {
+ // change mincut to be nodes with unmarked fanouts
+ Vec_PtrClear( vMinCut );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( !pObj->fMarkA )
+ continue;
+ Abc_ObjForEachFanout( pObj, pNext, k )
+ {
+ if ( pNext->fMarkA )
+ continue;
+ Vec_PtrPush( vMinCut, pObj );
+ break;
+ }
+ }
+ }
+ else
+ {
+ // change mincut to be marked fanins of the unmarked nodes
+ Vec_PtrClear( vMinCut );
+ Abc_NtkIncrementTravId(pNtk);
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_NtkMaxFlowCollectCut_rec( Abc_ObjFanin0(pObj), vMinCut );
+ // transfer the attribute
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ pObj->fMarkA = Abc_NodeIsTravIdCurrent(pObj);
+ // unmark the cut nodes
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ pObj->fMarkA = 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the min-cut is indeed a cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowVerifyCut_rec( Abc_Obj_t * pObj, int fForward )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ // skip visited nodes
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return 1;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // visit the node
+ if ( fForward )
+ {
+ if ( Abc_ObjIsCo(pObj) )
+ return 0;
+ // explore the fanouts
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if ( !Abc_NtkMaxFlowVerifyCut_rec(pNext, fForward) )
+ return 0;
+ }
+ else
+ {
+ if ( Abc_ObjIsCi(pObj) )
+ return 0;
+ // explore the fanins
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if ( !Abc_NtkMaxFlowVerifyCut_rec(pNext, fForward) )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the min-cut is indeed a cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ // mark the cut with the current traversal ID
+ Abc_NtkIncrementTravId(pNtk);
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // search from the latches for a path to the COs/CIs
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ {
+ if ( fForward )
+ {
+ if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanout0(pObj), fForward ) )
+ return 0;
+ }
+ else
+ {
+ if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanin0(pObj), fForward ) )
+ return 0;
+ }
+ }
+/*
+ {
+ // count the volume of the cut
+ int Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ Counter += Abc_NodeIsTravIdCurrent( pObj );
+ printf( "Volume = %d.\n", Counter );
+ }
+*/
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the flows.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward )
+{
+ Abc_Obj_t * pLatch, * pNext, * pPrev;
+ int i;
+ if ( fForward )
+ {
+ Vec_PtrForEachEntry( pNtk->vBoxes, pLatch, i )
+ {
+ assert( !Abc_ObjFanout0(pLatch)->fMarkA );
+ if ( Abc_ObjGetPath(Abc_ObjFanout0(pLatch)) == NULL ) // no flow through this latch
+ continue;
+ printf( "Path = " );
+ for ( pNext = Abc_ObjFanout0(pLatch); pNext != (void *)1; pNext = Abc_ObjGetPath(pNext) )
+ {
+ printf( "%s(%d) ", Abc_ObjName(pNext), pNext->Id );
+ pPrev = pNext;
+ }
+ if ( !Abc_ObjIsPo(pPrev) )
+ printf( "%s(%d) ", Abc_ObjName(Abc_ObjFanout0(pPrev)), Abc_ObjFanout0(pPrev)->Id );
+ printf( "\n" );
+ }
+ }
+ else
+ {
+ Vec_PtrForEachEntry( pNtk->vBoxes, pLatch, i )
+ {
+ assert( !Abc_ObjFanin0(pLatch)->fMarkA );
+ if ( Abc_ObjGetPath(Abc_ObjFanin0(pLatch)) == NULL ) // no flow through this latch
+ continue;
+ printf( "Path = " );
+ for ( pNext = Abc_ObjFanin0(pLatch); pNext != (void *)1; pNext = Abc_ObjGetPath(pNext) )
+ {
+ printf( "%s(%d) ", Abc_ObjName(pNext), pNext->Id );
+ pPrev = pNext;
+ }
+ if ( !Abc_ObjIsPi(pPrev) )
+ printf( "%s(%d) ", Abc_ObjName(Abc_ObjFanin0(pPrev)), Abc_ObjFanin0(pPrev)->Id );
+ printf( "\n" );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the min-cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ printf( "Min-cut: " );
+ Vec_PtrForEachEntry( vMinCut, pObj, i )
+ printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id );
+ printf( "\n" );
+ printf( "Marked nodes: " );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( pObj->fMarkA )
+ printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id );
+ printf( "\n" );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retIncrem.c b/src/opt/ret/retIncrem.c
new file mode 100644
index 00000000..ba8104be
--- /dev/null
+++ b/src/opt/ret/retIncrem.c
@@ -0,0 +1,464 @@
+/**CFile****************************************************************
+
+ FileName [retIncrem.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [Incremental retiming in one direction.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retIncrem.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs retiming in one direction.]
+
+ Description [Currently does not retime over black boxes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int fForward, int fMinDelay, int fOneStep, int fVerbose )
+{
+ Abc_Ntk_t * pNtkCopy = NULL;
+ Vec_Ptr_t * vBoxes;
+ st_table * tLatches;
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ int nIdMaxStart = Abc_NtkObjNumMax(pNtk);
+ int RetValue, nIterLimit;
+ if ( Abc_NtkNodeNum(pNtk) == 0 )
+ return 0;
+ // reorder CI/CO/latch inputs
+ Abc_NtkOrderCisCos( pNtk );
+ if ( fMinDelay )
+ {
+ nIterLimit = fOneStep? 1 : 2 * Abc_NtkLevel(pNtk);
+ pNtkCopy = Abc_NtkDup( pNtk );
+ tLatches = Abc_NtkRetimePrepareLatches( pNtkCopy );
+ st_free_table( tLatches );
+ }
+ // collect latches and remove CIs/COs
+ tLatches = Abc_NtkRetimePrepareLatches( pNtk );
+ // share the latches
+ Abc_NtkRetimeShareLatches( pNtk, 0 );
+ // save boxes
+ vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL;
+ // perform the retiming
+ if ( fMinDelay )
+ Abc_NtkRetimeMinDelay( pNtk, pNtkCopy, nIterLimit, fForward, fVerbose );
+ else
+ Abc_NtkRetimeOneWay( pNtk, fForward, fVerbose );
+ if ( fMinDelay )
+ Abc_NtkDelete( pNtkCopy );
+ // share the latches
+ Abc_NtkRetimeShareLatches( pNtk, 0 );
+ // restore boxes
+ pNtk->vBoxes = vBoxes;
+ // finalize the latches
+ RetValue = Abc_NtkRetimeFinalizeLatches( pNtk, tLatches, nIdMaxStart );
+ st_free_table( tLatches );
+ if ( RetValue == 0 )
+ return 0;
+ // fix the COs
+// Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+ // check for correctness
+ if ( !Abc_NtkCheck( pNtk ) )
+ fprintf( stdout, "Abc_NtkRetimeForward(): Network check has failed.\n" );
+ // return the number of latches saved
+ return nLatches - Abc_NtkLatchNum(pNtk);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the network for retiming.]
+
+ Description [Hash latches into their number in the original network.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+st_table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk )
+{
+ st_table * tLatches;
+ Abc_Obj_t * pLatch, * pLatchIn, * pLatchOut, * pFanin;
+ int i, nOffSet = Abc_NtkBoxNum(pNtk) - Abc_NtkLatchNum(pNtk);
+ // collect latches and remove CIs/COs
+ tLatches = st_init_table( st_ptrcmp, st_ptrhash );
+ Abc_NtkForEachLatch( pNtk, pLatch, i )
+ {
+ // map latch into its true number
+ st_insert( tLatches, (void *)pLatch, (void *)(i-nOffSet) );
+ // disconnect LI
+ pLatchIn = Abc_ObjFanin0(pLatch);
+ pFanin = Abc_ObjFanin0(pLatchIn);
+ Abc_ObjTransferFanout( pLatchIn, pFanin );
+ Abc_ObjDeleteFanin( pLatchIn, pFanin );
+ // disconnect LO
+ pLatchOut = Abc_ObjFanout0(pLatch);
+ pFanin = Abc_ObjFanin0(pLatchOut);
+ if ( Abc_ObjFanoutNum(pLatchOut) > 0 )
+ Abc_ObjTransferFanout( pLatchOut, pFanin );
+ Abc_ObjDeleteFanin( pLatchOut, pFanin );
+ }
+ return tLatches;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finalizes the latches after retiming.]
+
+ Description [Reuses the LIs/LOs for old latches.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st_table * tLatches, int nIdMaxStart )
+{
+ Vec_Ptr_t * vCisOld, * vCosOld, * vBoxesOld, * vCisNew, * vCosNew, * vBoxesNew;
+ Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut;
+ int i, Index;
+ // create new arrays
+ vCisOld = pNtk->vCis; pNtk->vCis = NULL; vCisNew = Vec_PtrAlloc( 100 );
+ vCosOld = pNtk->vCos; pNtk->vCos = NULL; vCosNew = Vec_PtrAlloc( 100 );
+ vBoxesOld = pNtk->vBoxes; pNtk->vBoxes = NULL; vBoxesNew = Vec_PtrAlloc( 100 );
+ // copy boxes and their CIs/COs
+ Vec_PtrForEachEntryStop( vCisOld, pObj, i, Vec_PtrSize(vCisOld) - st_count(tLatches) )
+ Vec_PtrPush( vCisNew, pObj );
+ Vec_PtrForEachEntryStop( vCosOld, pObj, i, Vec_PtrSize(vCosOld) - st_count(tLatches) )
+ Vec_PtrPush( vCosNew, pObj );
+ Vec_PtrForEachEntryStop( vBoxesOld, pObj, i, Vec_PtrSize(vBoxesOld) - st_count(tLatches) )
+ Vec_PtrPush( vBoxesNew, pObj );
+ // go through the latches
+ Abc_NtkForEachObj( pNtk, pLatch, i )
+ {
+ if ( !Abc_ObjIsLatch(pLatch) )
+ continue;
+ if ( Abc_ObjId(pLatch) >= (unsigned)nIdMaxStart )
+ {
+ // this is a new latch
+ pLatchIn = Abc_NtkCreateBi(pNtk);
+ pLatchOut = Abc_NtkCreateBo(pNtk);
+ Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" );
+ Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_in" );
+ }
+ else
+ {
+ // this is an old latch
+ // get its number in the original order
+ if ( !st_lookup( tLatches, (char *)pLatch, (char **)&Index ) )
+ {
+ printf( "Abc_NtkRetimeFinalizeLatches(): Internal error.\n" );
+ return 0;
+ }
+ assert( pLatch == Vec_PtrEntry(vBoxesOld, Vec_PtrSize(vBoxesOld) - st_count(tLatches) + Index) );
+ // reconnect with the old LIs/LOs
+ pLatchIn = Vec_PtrEntry( vCosOld, Vec_PtrSize(vCosOld) - st_count(tLatches) + Index );
+ pLatchOut = Vec_PtrEntry( vCisOld, Vec_PtrSize(vCisOld) - st_count(tLatches) + Index );
+ }
+ // connect
+ Abc_ObjAddFanin( pLatchIn, Abc_ObjFanin0(pLatch) );
+ Abc_ObjPatchFanin( pLatch, Abc_ObjFanin0(pLatch), pLatchIn );
+ if ( Abc_ObjFanoutNum(pLatch) > 0 )
+ Abc_ObjTransferFanout( pLatch, pLatchOut );
+ Abc_ObjAddFanin( pLatchOut, pLatch );
+ // add to the arrays
+ Vec_PtrPush( vCisNew, pLatchOut );
+ Vec_PtrPush( vCosNew, pLatchIn );
+ Vec_PtrPush( vBoxesNew, pLatch );
+ }
+ // free useless Cis/Cos
+ Vec_PtrForEachEntry( vCisOld, pObj, i )
+ if ( !Abc_ObjIsPi(pObj) && Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 )
+ Abc_NtkDeleteObj(pObj);
+ Vec_PtrForEachEntry( vCosOld, pObj, i )
+ if ( !Abc_ObjIsPo(pObj) && Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 )
+ Abc_NtkDeleteObj(pObj);
+ // set the new arrays
+ pNtk->vCis = vCisNew; Vec_PtrFree( vCisOld );
+ pNtk->vCos = vCosNew; Vec_PtrFree( vCosOld );
+ pNtk->vBoxes = vBoxesNew; Vec_PtrFree( vBoxesOld );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs retiming one way, forward or backward.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose )
+{
+ Abc_Ntk_t * pNtkNew;
+ Vec_Int_t * vValues;
+ Abc_Obj_t * pObj;
+ int i, fChanges, nTotalMoves = 0, nTotalMovesLimit = 10000;
+ if ( fForward )
+ Abc_NtkRetimeTranferToCopy( pNtk );
+ else
+ {
+ // save initial values of the latches
+ vValues = Abc_NtkRetimeCollectLatchValues( pNtk );
+ // start the network for initial value computation
+ pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk );
+ }
+ // try to move latches forward whenever possible
+ do {
+ fChanges = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ {
+ if ( !Abc_ObjIsNode(pObj) )
+ continue;
+ if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) )
+ {
+ Abc_NtkRetimeNode( pObj, fForward, 1 );
+ fChanges = 1;
+ nTotalMoves++;
+ if ( nTotalMoves >= nTotalMovesLimit )
+ {
+ printf( "Stopped after %d latch moves.\n", nTotalMoves );
+ break;
+ }
+ }
+ }
+ } while ( fChanges && nTotalMoves < nTotalMovesLimit );
+ // transfer the initial state back to the latches
+ if ( fForward )
+ Abc_NtkRetimeTranferFromCopy( pNtk );
+ else
+ {
+ Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose );
+ Abc_NtkDelete( pNtkNew );
+ Vec_IntFree( vValues );
+ }
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if retiming forward/backward is possible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward )
+{
+ Abc_Obj_t * pNext;
+ int i;
+ assert( Abc_ObjIsNode(pObj) );
+ if ( fForward )
+ {
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ if ( !Abc_ObjIsLatch(pNext) )
+ return 0;
+ }
+ else
+ {
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ if ( !Abc_ObjIsLatch(pNext) )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Retimes the node backward or forward.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial )
+{
+ Abc_Ntk_t * pNtkNew = NULL;
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pNext, * pLatch;
+ int i;
+ vNodes = Vec_PtrAlloc( 10 );
+ if ( fForward )
+ {
+ // compute the initial value
+ if ( fInitial )
+ pObj->pCopy = (void *)Abc_ObjSopSimulate( pObj );
+ // collect fanins
+ Abc_NodeCollectFanins( pObj, vNodes );
+ // make the node point to the fanins fanins
+ Vec_PtrForEachEntry( vNodes, pNext, i )
+ {
+ assert( Abc_ObjIsLatch(pNext) );
+ Abc_ObjPatchFanin( pObj, pNext, Abc_ObjFanin0(pNext) );
+ if ( Abc_ObjFanoutNum(pNext) == 0 )
+ Abc_NtkDeleteObj(pNext);
+ }
+ // add a new latch on top
+ pNext = Abc_NtkCreateLatch(pObj->pNtk);
+ if ( Abc_ObjFanoutNum(pObj) > 0 )
+ Abc_ObjTransferFanout( pObj, pNext );
+ Abc_ObjAddFanin( pNext, pObj );
+ // set the initial value
+ if ( fInitial )
+ pNext->pCopy = pObj->pCopy;
+ }
+ else
+ {
+ // compute the initial value
+ if ( fInitial )
+ {
+ pNtkNew = Abc_ObjFanout0(pObj)->pCopy->pNtk;
+ Abc_NtkDupObj( pNtkNew, pObj, 0 );
+ Abc_ObjForEachFanout( pObj, pNext, i )
+ {
+ assert( Abc_ObjFaninNum(pNext->pCopy) == 0 );
+ Abc_ObjAddFanin( pNext->pCopy, pObj->pCopy );
+ }
+ }
+ // collect fanouts
+ Abc_NodeCollectFanouts( pObj, vNodes );
+ // make the fanouts fanouts point to the node
+ Vec_PtrForEachEntry( vNodes, pNext, i )
+ {
+ assert( Abc_ObjIsLatch(pNext) );
+ Abc_ObjTransferFanout( pNext, pObj );
+ Abc_NtkDeleteObj( pNext );
+ }
+ // add new latches to the fanins
+ Abc_ObjForEachFanin( pObj, pNext, i )
+ {
+ pLatch = Abc_NtkCreateLatch(pObj->pNtk);
+ Abc_ObjPatchFanin( pObj, pNext, pLatch );
+ Abc_ObjAddFanin( pLatch, pNext );
+ // create buffer isomorphic to this latch
+ if ( fInitial )
+ {
+ pLatch->pCopy = Abc_NtkCreateNodeBuf( pNtkNew, NULL );
+ Abc_ObjAddFanin( pObj->pCopy, pLatch->pCopy );
+ }
+ }
+ }
+ Vec_PtrFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of compatible fanout latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeCheckCompatibleLatchFanouts( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int i, nLatches = 0, Init = -1;
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ if ( !Abc_ObjIsLatch(pFanout) )
+ continue;
+ if ( Init == -1 )
+ {
+ Init = (int)pObj->pData;
+ nLatches++;
+ }
+ else if ( Init == (int)pObj->pData )
+ nLatches++;
+ }
+ return nLatches;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Retimes the node backward or forward.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pFanin, * pLatchTop, * pLatchCur;
+ int i, k;
+ vNodes = Vec_PtrAlloc( 10 );
+ // consider latch fanins
+ Abc_NtkForEachObj( pNtk, pFanin, i )
+ {
+ if ( Abc_NtkRetimeCheckCompatibleLatchFanouts(pFanin) <= 1 )
+ continue;
+ // get the first latch
+ pLatchTop = NULL;
+ Abc_ObjForEachFanout( pFanin, pLatchTop, k )
+ if ( Abc_ObjIsLatch(pLatchTop) )
+ break;
+ assert( pLatchTop && Abc_ObjIsLatch(pLatchTop) );
+ // redirect compatible fanout latches to the first latch
+ Abc_NodeCollectFanouts( pFanin, vNodes );
+ Vec_PtrForEachEntry( vNodes, pLatchCur, k )
+ {
+ if ( !Abc_ObjIsLatch(pLatchCur) )
+ continue;
+ if ( pLatchCur == pLatchTop )
+ continue;
+ if ( pLatchCur->pData != pLatchTop->pData )
+ continue;
+ // connect the initial state
+ if ( fInitial )
+ Abc_ObjAddFanin( pLatchCur->pCopy, pLatchTop->pCopy );
+ // redirect the fanouts
+ Abc_ObjTransferFanout( pLatchCur, pLatchTop );
+ Abc_NtkDeleteObj(pLatchCur);
+ }
+ }
+ Vec_PtrFree( vNodes );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retInit.c b/src/opt/ret/retInit.c
new file mode 100644
index 00000000..dcb71c60
--- /dev/null
+++ b/src/opt/ret/retInit.c
@@ -0,0 +1,349 @@
+/**CFile****************************************************************
+
+ FileName [retInit.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [Initial state computation for backward retiming.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retInit.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes initial values of the new latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int fVerbose )
+{
+ Vec_Int_t * vSolution;
+ Abc_Ntk_t * pNtkMiter, * pNtkLogic;
+ int RetValue, clk;
+ if ( pNtkCone == NULL )
+ return Vec_IntDup( vValues );
+ // convert the target network to AIG
+ pNtkLogic = Abc_NtkDup( pNtkCone );
+ Abc_NtkToAig( pNtkLogic );
+ // get the miter
+ pNtkMiter = Abc_NtkCreateTarget( pNtkLogic, pNtkLogic->vCos, vValues );
+ if ( fVerbose )
+ printf( "The miter for initial state computation has %d AIG nodes. ", Abc_NtkNodeNum(pNtkMiter) );
+ // solve the miter
+ clk = clock();
+ RetValue = Abc_NtkMiterSat( pNtkMiter, (sint64)500000, (sint64)50000000, 0, NULL, NULL );
+ if ( fVerbose )
+ { PRT( "SAT solving time", clock() - clk ); }
+ // analyze the result
+ if ( RetValue == 1 )
+ printf( "Abc_NtkRetimeInitialValues(): The problem is unsatisfiable. DC latch values are used.\n" );
+ else if ( RetValue == -1 )
+ printf( "Abc_NtkRetimeInitialValues(): The SAT problem timed out. DC latch values are used.\n" );
+ else if ( !Abc_NtkRetimeVerifyModel( pNtkCone, vValues, pNtkMiter->pModel ) )
+ printf( "Abc_NtkRetimeInitialValues(): The computed counter-example is incorrect.\n" );
+ // set the values of the latches
+ vSolution = RetValue? NULL : Vec_IntAllocArray( pNtkMiter->pModel, Abc_NtkPiNum(pNtkLogic) );
+ pNtkMiter->pModel = NULL;
+ Abc_NtkDelete( pNtkMiter );
+ Abc_NtkDelete( pNtkLogic );
+ return vSolution;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the results of simulating one node.]
+
+ Description [Assumes that fanins have pCopy set to the input values.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ObjSopSimulate( Abc_Obj_t * pObj )
+{
+ char * pCube, * pSop = pObj->pData;
+ int nVars, Value, v, ResOr, ResAnd, ResVar;
+ assert( pSop && !Abc_SopIsExorType(pSop) );
+ // simulate the SOP of the node
+ ResOr = 0;
+ nVars = Abc_SopGetVarNum(pSop);
+ Abc_SopForEachCube( pSop, nVars, pCube )
+ {
+ ResAnd = 1;
+ Abc_CubeForEachVar( pCube, Value, v )
+ {
+ if ( Value == '0' )
+ ResVar = 1 ^ ((int)Abc_ObjFanin(pObj, v)->pCopy);
+ else if ( Value == '1' )
+ ResVar = (int)Abc_ObjFanin(pObj, v)->pCopy;
+ else
+ continue;
+ ResAnd &= ResVar;
+ }
+ ResOr |= ResAnd;
+ }
+ // complement the result if necessary
+ if ( !Abc_SopGetPhase(pSop) )
+ ResOr ^= 1;
+ return ResOr;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i, Counter = 0;
+ assert( Abc_NtkIsSopLogic(pNtkCone) );
+ // set the PIs
+ Abc_NtkForEachPi( pNtkCone, pObj, i )
+ pObj->pCopy = (void *)pModel[i];
+ // simulate the internal nodes
+ vNodes = Abc_NtkDfs( pNtkCone, 0 );
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->pCopy = (void *)Abc_ObjSopSimulate( pObj );
+ Vec_PtrFree( vNodes );
+ // compare the outputs
+ Abc_NtkForEachPo( pNtkCone, pObj, i )
+ pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+ Abc_NtkForEachPo( pNtkCone, pObj, i )
+ Counter += (Vec_IntEntry(vValues, i) != (int)pObj->pCopy);
+ if ( Counter > 0 )
+ printf( "%d outputs (out of %d) have a value mismatch.\n", Counter, Abc_NtkPoNum(pNtkCone) );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfer latch initial values to pCopy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ pObj->pCopy = (void *)Abc_LatchIsInit1(pObj);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfer latch initial values from pCopy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ pObj->pData = (void *)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfer latch initial values to pCopy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk )
+{
+ Vec_Int_t * vValues;
+ Abc_Obj_t * pObj;
+ int i;
+ vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ Vec_IntPush( vValues, Abc_LatchIsInit1(pObj) );
+ return vValues;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfer latch initial values from pCopy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues )
+{
+ Abc_Obj_t * pObj;
+ int i, Counter = 0;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ pObj->pCopy = (void *)Counter++;
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ pObj->pData = (void *)(vValues? (Vec_IntEntry(vValues,(int)pObj->pCopy)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfer latch initial values to pCopy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk )
+{
+ Abc_Ntk_t * pNtkNew;
+ Abc_Obj_t * pObj;
+ int i;
+ // create the network used for the initial state computation
+ pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 );
+ // create POs corresponding to the initial values
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ pObj->pCopy = Abc_NtkCreatePo(pNtkNew);
+ return pNtkNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfer latch initial values to pCopy.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose )
+{
+ Vec_Int_t * vValuesNew;
+ Abc_Obj_t * pObj;
+ int i;
+ // create PIs corresponding to the initial values
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjIsLatch(pObj) )
+ Abc_ObjAddFanin( pObj->pCopy, Abc_NtkCreatePi(pNtkNew) );
+ // assign dummy node names
+ Abc_NtkAddDummyPiNames( pNtkNew );
+ Abc_NtkAddDummyPoNames( pNtkNew );
+ // check the network
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkRetimeBackwardInitialFinish(): Network check has failed.\n" );
+ // derive new initial values
+ vValuesNew = Abc_NtkRetimeInitialValues( pNtkNew, vValuesOld, fVerbose );
+ // insert new initial values
+ Abc_NtkRetimeInsertLatchValues( pNtk, vValuesNew );
+ if ( vValuesNew ) Vec_IntFree( vValuesNew );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Cycles the circuit to create a new initial state.]
+
+ Description [Simulates the circuit with random input for the given
+ number of timeframes to get a better initial state.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose )
+{
+ Vec_Ptr_t * vNodes;
+ Abc_Obj_t * pObj;
+ int i, f;
+ assert( Abc_NtkIsSopLogic(pNtk) );
+ srand( 0x12341234 );
+ // initialize the values
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->pCopy = (void *)(rand() & 1);
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->pCopy = (void *)Abc_LatchIsInit1(pObj);
+ // simulate for the given number of timeframes
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // simulate internal nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->pCopy = (void *)Abc_ObjSopSimulate( pObj );
+ // bring the results to the COs
+ Abc_NtkForEachCo( pNtk, pObj, i )
+ pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+ // assign PI values
+ Abc_NtkForEachPi( pNtk, pObj, i )
+ pObj->pCopy = (void *)(rand() & 1);
+ // transfer the latch values
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ObjFanout0(pObj)->pCopy = Abc_ObjFanin0(pObj)->pCopy;
+ }
+ Vec_PtrFree( vNodes );
+ // set the final values
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ pObj->pData = (void *)(Abc_ObjFanout0(pObj)->pCopy ? ABC_INIT_ONE : ABC_INIT_ZERO);
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retInt.h b/src/opt/ret/retInt.h
new file mode 100644
index 00000000..51428bce
--- /dev/null
+++ b/src/opt/ret/retInt.h
@@ -0,0 +1,80 @@
+/**CFile****************************************************************
+
+ FileName [retInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retInt.h,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef __RET_INT_H__
+#define __RET_INT_H__
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "abc.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== retArea.c ========================================================*/
+extern int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, int fVerbose );
+/*=== retCore.c ========================================================*/
+extern int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose );
+/*=== retDelay.c ========================================================*/
+extern int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nIterLimit, int fForward, int fVerbose );
+/*=== retDirect.c ========================================================*/
+extern int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int fForward, int fMinDelay, int fOneStep, int fVerbose );
+extern void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial );
+extern int Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward );
+extern void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial );
+extern st_table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk );
+extern int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st_table * tLatches, int nIdMaxStart );
+/*=== retFlow.c ========================================================*/
+extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk );
+extern Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose );
+/*=== retInit.c ========================================================*/
+extern Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkSat, Vec_Int_t * vValues, int fVerbose );
+extern int Abc_ObjSopSimulate( Abc_Obj_t * pObj );
+extern void Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk );
+extern void Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk );
+extern Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk );
+extern void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues );
+extern Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk );
+extern void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose );
+/*=== retLvalue.c ========================================================*/
+extern int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose );
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/retLvalue.c b/src/opt/ret/retLvalue.c
new file mode 100644
index 00000000..b4d9e946
--- /dev/null
+++ b/src/opt/ret/retLvalue.c
@@ -0,0 +1,395 @@
+/**CFile****************************************************************
+
+ FileName [retLvalue.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis [Implementation of Pan's retiming algorithm.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: retLvalue.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// node status after updating its arrival time
+enum { ABC_RET_UPDATE_FAIL, ABC_RET_UPDATE_NO, ABC_RET_UPDATE_YES };
+
+// the internal procedures
+static Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose );
+static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose );
+static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose );
+static int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi );
+static int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi );
+static Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk );
+static int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose );
+
+static inline int Abc_NodeComputeLag( int LValue, int Fi ) { return (LValue + (1<<16)*Fi)/Fi - (1<<16) - (int)(LValue % Fi == 0); }
+static inline int Abc_NodeGetLValue( Abc_Obj_t * pNode ) { return (int)pNode->pCopy; }
+static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { pNode->pCopy = (void *)Value; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Implements Pan's retiming algorithm.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose )
+{
+ Vec_Int_t * vLags;
+ int nLatches = Abc_NtkLatchNum(pNtk);
+ assert( Abc_NtkIsLogic( pNtk ) );
+ // get the lags
+ vLags = Abc_NtkRetimeGetLags( pNtk, nIterLimit, fVerbose );
+ // compute the retiming
+// Abc_NtkRetimeUsingLags( pNtk, vLags, fVerbose );
+ Vec_IntFree( vLags );
+ // fix the COs
+// Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
+ // check for correctness
+ if ( !Abc_NtkCheck( pNtk ) )
+ fprintf( stdout, "Abc_NtkRetimeLValue(): Network check has failed.\n" );
+ // return the number of latches saved
+ return nLatches - Abc_NtkLatchNum(pNtk);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the retiming lags.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose )
+{
+ Vec_Int_t * vLags;
+ Vec_Ptr_t * vNodes, * vLatches;
+ Abc_Obj_t * pNode;
+ int i, FiMax, FiBest, RetValue, clk, clkIter;
+ char NodeLag;
+
+ // get the upper bound on the clock period
+ FiMax = Abc_NtkLevel(pNtk);
+
+ // make sure this clock period is feasible
+ vNodes = Abc_NtkDfs( pNtk, 0 );
+ vLatches = Abc_ManCollectLatches( pNtk );
+ if ( !Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiMax, nIterLimit, fVerbose ) )
+ {
+ Vec_PtrFree( vNodes );
+ printf( "Abc_NtkRetimeGetLags() error: The upper bound on the clock period cannot be computed.\n" );
+ return Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+ }
+
+ // search for the optimal clock period between 0 and nLevelMax
+clk = clock();
+ FiBest = Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, 0, FiMax, nIterLimit, fVerbose );
+clkIter = clock() - clk;
+
+ // recompute the best l-values
+ RetValue = Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiBest, nIterLimit, fVerbose );
+ assert( RetValue );
+
+ // fix the problem with non-converged delays
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ if ( Abc_NodeGetLValue(pNode) < -ABC_INFINITY/2 )
+ Abc_NodeSetLValue( pNode, 0 );
+
+ // write the retiming lags
+ vLags = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ {
+ NodeLag = Abc_NodeComputeLag( Abc_NodeGetLValue(pNode), FiBest );
+ Vec_IntWriteEntry( vLags, pNode->Id, NodeLag );
+ }
+/*
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ printf( "%d ", Abc_NodeGetLValue(Abc_ObjFanin0(pNode)) );
+ printf( "\n" );
+ Abc_NtkForEachLatch( pNtk, pNode, i )
+ printf( "%d/%d ", Abc_NodeGetLValue(Abc_ObjFanout0(pNode)), Abc_NodeGetLValue(Abc_ObjFanout0(pNode)) + FiBest );
+ printf( "\n" );
+*/
+
+ // print the result
+// if ( fVerbose )
+ printf( "The best clock period is %3d. (Currently, network is not modified.)\n", FiBest );
+/*
+ {
+ FILE * pTable;
+ pTable = fopen( "iscas/seqmap__stats2.txt", "a+" );
+ fprintf( pTable, "%d ", FiBest );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+ Vec_PtrFree( vNodes );
+ Vec_PtrFree( vLatches );
+ return vLags;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs binary search for the optimal clock period.]
+
+ Description [Assumes that FiMin is infeasible while FiMax is feasible.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose )
+{
+ int Median;
+ assert( FiMin < FiMax );
+ if ( FiMin + 1 == FiMax )
+ return FiMax;
+ Median = FiMin + (FiMax - FiMin)/2;
+ if ( Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, Median, nMaxIters, fVerbose ) )
+ return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, FiMin, Median, nMaxIters, fVerbose ); // Median is feasible
+ else
+ return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, Median, FiMax, nMaxIters, fVerbose ); // Median is infeasible
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if retiming with this clock period is feasible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose )
+{
+ Abc_Obj_t * pObj;
+ int c, i, fConverged;
+ // set l-values of all nodes to be minus infinity, except PIs and constants
+ Abc_NtkForEachObj( pNtk, pObj, i )
+ if ( Abc_ObjFaninNum(pObj) == 0 )
+ Abc_NodeSetLValue( pObj, 0 );
+ else
+ Abc_NodeSetLValue( pObj, -ABC_INFINITY );
+ // update all values iteratively
+ fConverged = 0;
+ for ( c = 1; c <= nMaxIters; c++ )
+ {
+ if ( !Abc_NtkRetimeUpdateLValue( pNtk, vNodes, vLatches, Fi ) )
+ {
+ fConverged = 1;
+ break;
+ }
+ if ( Abc_NtkRetimePosOverLimit(pNtk, Fi) )
+ break;
+ }
+ // report the results
+ if ( fVerbose )
+ {
+ if ( !fConverged )
+ printf( "Period = %3d. Iterations = %3d. Infeasible %s\n", Fi, c, (c > nMaxIters)? "(timeout)" : "" );
+ else
+ printf( "Period = %3d. Iterations = %3d. Feasible\n", Fi, c );
+ }
+/*
+ // check if any AND gates have infinite delay
+ Counter = 0;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ Counter += (Abc_NodeGetLValue(pObj) < -ABC_INFINITY/2);
+ if ( Counter > 0 )
+ printf( "Warning: %d internal nodes have wrong l-values!\n", Counter );
+*/
+ return fConverged;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one iteration of l-value computation for the nodes.]
+
+ Description [Experimentally it was found that checking POs changes
+ is not enough to detect the convergence of l-values in the network.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi )
+{
+ Abc_Obj_t * pObj, * pFanin;
+ int i, k, lValueNew, fChange;
+ // go through the nodes and detect change
+ fChange = 0;
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ assert( Abc_ObjIsNode(pObj) );
+ lValueNew = -ABC_INFINITY;
+ Abc_ObjForEachFanin( pObj, pFanin, k )
+ {
+ if ( lValueNew < Abc_NodeGetLValue(pFanin) )
+ lValueNew = Abc_NodeGetLValue(pFanin);
+ }
+ lValueNew++;
+ if ( Abc_NodeGetLValue(pObj) < lValueNew )
+ {
+ Abc_NodeSetLValue( pObj, lValueNew );
+ fChange = 1;
+ }
+ }
+ // propagate values through the latches
+ Vec_PtrForEachEntry( vLatches, pObj, i )
+ Abc_NodeSetLValue( Abc_ObjFanout0(pObj), Abc_NodeGetLValue(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) - Fi );
+ return fChange;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Detects the case when l-values exceeded the limit.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi )
+{
+ Abc_Obj_t * pObj;
+ int i;
+ Abc_NtkForEachPo( pNtk, pObj, i )
+ if ( Abc_NodeGetLValue(Abc_ObjFanin0(pObj)) > Fi )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects latches in the topological order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ManCollectLatches_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLatches )
+{
+ Abc_Obj_t * pDriver;
+ if ( !Abc_ObjIsLatch(pObj) )
+ return;
+ // skip already collected latches
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ return;
+ Abc_NodeSetTravIdCurrent(pObj);
+ // get the driver node feeding into the latch
+ pDriver = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
+ // call recursively if the driver looks like a latch output
+ if ( Abc_ObjIsBo(pDriver) )
+ Abc_ManCollectLatches_rec( Abc_ObjFanin0(pDriver), vLatches );
+ // collect the latch
+ Vec_PtrPush( vLatches, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects latches in the topological order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk )
+{
+ Vec_Ptr_t * vLatches;
+ Abc_Obj_t * pObj;
+ int i;
+ vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
+ Abc_NtkIncrementTravId( pNtk );
+ Abc_NtkForEachLatch( pNtk, pObj, i )
+ Abc_ManCollectLatches_rec( pObj, vLatches );
+ assert( Vec_PtrSize(vLatches) == Abc_NtkLatchNum(pNtk) );
+ return vLatches;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implements the retiming given as the array of retiming lags.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose )
+{
+ Abc_Obj_t * pObj;
+ int fChanges, fForward, nTotalMoves, Lag, Counter, i;
+ // iterate over the nodes
+ nTotalMoves = 0;
+ do {
+ fChanges = 0;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ {
+ Lag = Vec_IntEntry( vLags, pObj->Id );
+ if ( !Lag )
+ continue;
+ fForward = (Lag < 0);
+ if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) )
+ {
+ Abc_NtkRetimeNode( pObj, fForward, 0 );
+ fChanges = 1;
+ nTotalMoves++;
+ Vec_IntAddToEntry( vLags, pObj->Id, fForward? 1 : -1 );
+ }
+ }
+ } while ( fChanges );
+ if ( fVerbose )
+ printf( "Total latch moves = %d.\n", nTotalMoves );
+ // check if there are remaining lags
+ Counter = 0;
+ Abc_NtkForEachNode( pNtk, pObj, i )
+ Counter += (Vec_IntEntry( vLags, pObj->Id ) != 0);
+ if ( Counter )
+ printf( "Warning! The number of nodes with unrealized lag = %d.\n", Counter );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/ret/ret_.c b/src/opt/ret/ret_.c
new file mode 100644
index 00000000..89625e17
--- /dev/null
+++ b/src/opt/ret/ret_.c
@@ -0,0 +1,48 @@
+/**CFile****************************************************************
+
+ FileName [ret_.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Retiming package.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - Oct 31, 2006.]
+
+ Revision [$Id: ret_.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "retInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/rwr/rwr.h b/src/opt/rwr/rwr.h
index 6d1a6c06..f24f9535 100644
--- a/src/opt/rwr/rwr.h
+++ b/src/opt/rwr/rwr.h
@@ -21,6 +21,10 @@
#ifndef __RWR_H__
#define __RWR_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
@@ -49,6 +53,7 @@ struct Rwr_Man_t_
char * pPhases; // canonical phases
char * pPerms; // canonical permutations
unsigned char * pMap; // mapping of functions into class numbers
+ unsigned short * pMapInv; // mapping of classes into functions
char * pPractical; // practical NPN classes
char ** pPerms4; // four-var permutations
// node space
@@ -63,14 +68,17 @@ struct Rwr_Man_t_
int nClasses; // the number of NN classes
// the result of resynthesis
int fCompl; // indicates if the output of FF should be complemented
- void * pGraph; // the decomposition tree (temporary)
+ void * pGraph; // the decomposition tree (temporary)
Vec_Ptr_t * vFanins; // the fanins array (temporary)
Vec_Ptr_t * vFaninsCur; // the fanins array (temporary)
Vec_Int_t * vLevNums; // the array of levels (temporary)
+ Vec_Ptr_t * vNodesTemp; // the nodes in MFFC (temporary)
// node statistics
int nNodesConsidered;
int nNodesRewritten;
int nNodesGained;
+ int nNodesBeg;
+ int nNodesEnd;
int nScores[222];
int nCutsGood;
int nCutsBad;
@@ -80,6 +88,8 @@ struct Rwr_Man_t_
int timeCut;
int timeRes;
int timeEval;
+ int timeMffc;
+ int timeUpdate;
int timeTotal;
};
@@ -87,6 +97,9 @@ struct Rwr_Node_t_ // 24 bytes
{
int Id; // ID
int TravId; // traversal ID
+ short nScore;
+ short nGain;
+ short nAdded;
unsigned uTruth : 16; // truth table
unsigned Volume : 8; // volume
unsigned Level : 6; // level
@@ -98,13 +111,13 @@ struct Rwr_Node_t_ // 24 bytes
};
// manipulation of complemented attributes
-static inline bool Rwr_IsComplement( Rwr_Node_t * p ) { return (bool)(((unsigned)p) & 01); }
-static inline Rwr_Node_t * Rwr_Regular( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned)(p) & ~01); }
-static inline Rwr_Node_t * Rwr_Not( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned)(p) ^ 01); }
-static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c ) { return (Rwr_Node_t *)((unsigned)(p) ^ (c)); }
+static inline bool Rwr_IsComplement( Rwr_Node_t * p ) { return (bool)(((unsigned long)p) & 01); }
+static inline Rwr_Node_t * Rwr_Regular( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned long)(p) & ~01); }
+static inline Rwr_Node_t * Rwr_Not( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned long)(p) ^ 01); }
+static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c ) { return (Rwr_Node_t *)((unsigned long)(p) ^ (c)); }
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@@ -114,7 +127,9 @@ static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c ) { return (Rwr_N
/*=== rwrDec.c ========================================================*/
extern void Rwr_ManPreprocess( Rwr_Man_t * p );
/*=== rwrEva.c ========================================================*/
-extern int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUseZeros );
+extern int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable );
+extern void Rwr_ScoresClean( Rwr_Man_t * p );
+extern void Rwr_ScoresReport( Rwr_Man_t * p );
/*=== rwrLib.c ========================================================*/
extern void Rwr_ManPrecompute( Rwr_Man_t * p );
extern Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute );
@@ -125,9 +140,12 @@ extern void Rwr_ManIncTravId( Rwr_Man_t * p );
extern Rwr_Man_t * Rwr_ManStart( bool fPrecompute );
extern void Rwr_ManStop( Rwr_Man_t * p );
extern void Rwr_ManPrintStats( Rwr_Man_t * p );
+extern void Rwr_ManPrintStatsFile( Rwr_Man_t * p );
extern void * Rwr_ManReadDecs( Rwr_Man_t * p );
+extern Vec_Ptr_t * Rwr_ManReadLeaves( Rwr_Man_t * p );
extern int Rwr_ManReadCompl( Rwr_Man_t * p );
extern void Rwr_ManAddTimeCuts( Rwr_Man_t * p, int Time );
+extern void Rwr_ManAddTimeUpdate( Rwr_Man_t * p, int Time );
extern void Rwr_ManAddTimeTotal( Rwr_Man_t * p, int Time );
/*=== rwrPrint.c ========================================================*/
extern void Rwr_ManPrint( Rwr_Man_t * p );
@@ -139,9 +157,13 @@ extern void Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName );
extern void Rwr_ListAddToTail( Rwr_Node_t ** ppList, Rwr_Node_t * pNode );
extern char * Rwr_ManGetPractical( Rwr_Man_t * p );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/rwr/rwrDec.c b/src/opt/rwr/rwrDec.c
index d072879d..ef7af34f 100644
--- a/src/opt/rwr/rwrDec.c
+++ b/src/opt/rwr/rwrDec.c
@@ -29,7 +29,7 @@ static Dec_Graph_t * Rwr_NodePreprocess( Rwr_Man_t * p, Rwr_Node_t * pNode );
static Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t * pGraph );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -49,6 +49,8 @@ void Rwr_ManPreprocess( Rwr_Man_t * p )
Rwr_Node_t * pNode;
int i, k;
// put the nodes into the structure
+ p->pMapInv = ALLOC( unsigned short, 222 );
+ memset( p->pMapInv, 0, sizeof(unsigned short) * 222 );
p->vClasses = Vec_VecStart( 222 );
for ( i = 0; i < p->nFuncs; i++ )
{
@@ -60,6 +62,7 @@ void Rwr_ManPreprocess( Rwr_Man_t * p )
assert( pNode->uTruth == p->pTable[i]->uTruth );
assert( p->pMap[pNode->uTruth] >= 0 && p->pMap[pNode->uTruth] < 222 );
Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode );
+ p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth];
}
}
// compute decomposition forms for each node and verify them
@@ -132,7 +135,7 @@ Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t *
eNode1.fCompl = !eNode1.fCompl;
// create the decomposition node(s)
if ( pNode->fExor )
- eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1 );
+ eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 );
else
eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
// save the result
diff --git a/src/opt/rwr/rwrEva.c b/src/opt/rwr/rwrEva.c
index c934dfd8..396a659c 100644
--- a/src/opt/rwr/rwrEva.c
+++ b/src/opt/rwr/rwrEva.c
@@ -25,10 +25,13 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-static Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest );
+static Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable );
+static int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves );
+static int Rwr_CutCountNumNodes( Abc_Obj_t * pObj, Cut_Cut_t * pCut );
+static int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -49,27 +52,35 @@ static Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_
SeeAlso []
***********************************************************************/
-int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUseZeros )
+int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable )
{
int fVeryVerbose = 0;
Dec_Graph_t * pGraph;
- Cut_Cut_t * pCut;
+ Cut_Cut_t * pCut;//, * pTemp;
Abc_Obj_t * pFanin;
- unsigned uPhase, uTruthBest;
+ unsigned uPhase, uTruthBest, uTruth;
char * pPerm;
- int Required, nNodesSaved;
+ int Required, nNodesSaved, nNodesSaveCur;
int i, GainCur, GainBest = -1;
- int clk, clk2;
+ int clk, clk2;//, Counter;
p->nNodesConsidered++;
// get the required times
- Required = Abc_NodeReadRequiredLevel( pNode );
+ Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY;
+
// get the node's cuts
clk = clock();
- pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode );
+ pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 );
assert( pCut != NULL );
p->timeCut += clock() - clk;
+//printf( " %d", Rwr_CutCountNumNodes(pNode, pCut) );
+/*
+ Counter = 0;
+ for ( pTemp = pCut->pNext; pTemp; pTemp = pTemp->pNext )
+ Counter++;
+ printf( "%d ", Counter );
+*/
// go through the cuts
clk = clock();
for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext )
@@ -77,9 +88,12 @@ clk = clock();
// consider only 4-input cuts
if ( pCut->nLeaves < 4 )
continue;
+// Cut_CutPrint( pCut, 0 ), printf( "\n" );
+
// get the fanin permutation
- pPerm = p->pPerms4[ p->pPerms[pCut->uTruth] ];
- uPhase = p->pPhases[pCut->uTruth];
+ uTruth = 0xFFFF & *Cut_CutReadTruth(pCut);
+ pPerm = p->pPerms4[ p->pPerms[uTruth] ];
+ uPhase = p->pPhases[uTruth];
// collect fanins with the corresponding permutation/phase
Vec_PtrClear( p->vFaninsCur );
Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 );
@@ -98,29 +112,48 @@ clk = clock();
}
p->nCutsGood++;
+ {
+ int Counter = 0;
+ Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
+ if ( Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) == 1 )
+ Counter++;
+ if ( Counter > 2 )
+ continue;
+ }
+
+clk2 = clock();
+/*
+ printf( "Considering: (" );
+ Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
+ printf( "%d ", Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) );
+ printf( ")\n" );
+*/
// mark the fanin boundary
Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
Abc_ObjRegular(pFanin)->vFanouts.nSize++;
+
// label MFFC with current ID
Abc_NtkIncrementTravId( pNode->pNtk );
- nNodesSaved = Abc_NodeMffcLabel( pNode );
+ nNodesSaved = Abc_NodeMffcLabelAig( pNode );
// unmark the fanin boundary
Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
Abc_ObjRegular(pFanin)->vFanouts.nSize--;
+p->timeMffc += clock() - clk2;
// evaluate the cut
clk2 = clock();
- pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur );
+ pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur, fPlaceEnable );
p->timeEval += clock() - clk2;
// check if the cut is better than the current best one
if ( pGraph != NULL && GainBest < GainCur )
{
// save this form
+ nNodesSaveCur = nNodesSaved;
GainBest = GainCur;
p->pGraph = pGraph;
p->fCompl = ((uPhase & (1<<4)) > 0);
- uTruthBest = pCut->uTruth;
+ uTruthBest = 0xFFFF & *Cut_CutReadTruth(pCut);
// collect fanins in the
Vec_PtrClear( p->vFanins );
Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i )
@@ -131,22 +164,69 @@ p->timeRes += clock() - clk;
if ( GainBest == -1 )
return -1;
+/*
+ if ( GainBest > 0 )
+ {
+ printf( "Class %d ", p->pMap[uTruthBest] );
+ printf( "Gain = %d. Node %d : ", GainBest, pNode->Id );
+ Vec_PtrForEachEntry( p->vFanins, pFanin, i )
+ printf( "%d ", Abc_ObjRegular(pFanin)->Id );
+ Dec_GraphPrint( stdout, p->pGraph, NULL, NULL );
+ printf( "\n" );
+ }
+*/
+
+// printf( "%d", nNodesSaveCur - GainBest );
+/*
+ if ( GainBest > 0 )
+ {
+ if ( Rwr_CutIsBoolean( pNode, p->vFanins ) )
+ printf( "b" );
+ else
+ {
+ printf( "Node %d : ", pNode->Id );
+ Vec_PtrForEachEntry( p->vFanins, pFanin, i )
+ printf( "%d ", Abc_ObjRegular(pFanin)->Id );
+ printf( "a" );
+ }
+ }
+*/
+/*
+ if ( GainBest > 0 )
+ if ( p->fCompl )
+ printf( "c" );
+ else
+ printf( "." );
+*/
// copy the leaves
Vec_PtrForEachEntry( p->vFanins, pFanin, i )
Dec_GraphNode(p->pGraph, i)->pFunc = pFanin;
+/*
+ printf( "(" );
+ Vec_PtrForEachEntry( p->vFanins, pFanin, i )
+ printf( " %d", Abc_ObjRegular(pFanin)->vFanouts.nSize - 1 );
+ printf( " ) " );
+*/
+// printf( "%d ", Rwr_NodeGetDepth_rec( pNode, p->vFanins ) );
p->nScores[p->pMap[uTruthBest]]++;
- p->nNodesRewritten++;
p->nNodesGained += GainBest;
+ if ( fUseZeros || GainBest > 0 )
+ {
+ p->nNodesRewritten++;
+ }
// report the progress
- if ( fVeryVerbose )
+ if ( fVeryVerbose && GainBest > 0 )
{
printf( "Node %6s : ", Abc_ObjName(pNode) );
printf( "Fanins = %d. ", p->vFanins->nSize );
- printf( "Cone = %2d. ", Dec_GraphNodeNum(p->pGraph) );
- printf( "GAIN = %2d. ", GainBest );
+ printf( "Save = %d. ", nNodesSaveCur );
+ printf( "Add = %d. ", nNodesSaveCur-GainBest );
+ printf( "GAIN = %d. ", GainBest );
+ printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 );
+ printf( "Class = %d. ", p->pMap[uTruthBest] );
printf( "\n" );
}
return GainBest;
@@ -163,17 +243,22 @@ p->timeRes += clock() - clk;
SeeAlso []
***********************************************************************/
-Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest )
+Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable )
{
+ extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
Vec_Ptr_t * vSubgraphs;
Dec_Graph_t * pGraphBest, * pGraphCur;
Rwr_Node_t * pNode, * pFanin;
int nNodesAdded, GainBest, i, k;
+ unsigned uTruth;
+ float CostBest;//, CostCur;
// find the matching class of subgraphs
- vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[pCut->uTruth] );
+ uTruth = 0xFFFF & *Cut_CutReadTruth(pCut);
+ vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] );
p->nSubgraphs += vSubgraphs->nSize;
// determine the best subgraph
GainBest = -1;
+ CostBest = ABC_INFINITY;
Vec_PtrForEachEntry( vSubgraphs, pNode, i )
{
// get the current graph
@@ -186,11 +271,58 @@ Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCu
if ( nNodesAdded == -1 )
continue;
assert( nNodesSaved >= nNodesAdded );
- // count the gain at this node
- if ( GainBest < nNodesSaved - nNodesAdded )
+/*
+ // evaluate the cut
+ if ( fPlaceEnable )
+ {
+ extern float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins );
+
+ float Alpha = 0.5; // ???
+ float PlaceCost;
+
+ // get the placement cost of the cut
+ PlaceCost = Abc_PlaceEvaluateCut( pRoot, vFaninsCur );
+
+ // get the weigted cost of the cut
+ CostCur = nNodesSaved - nNodesAdded + Alpha * PlaceCost;
+
+ // do not allow uphill moves
+ if ( nNodesSaved - nNodesAdded < 0 )
+ continue;
+
+ // decide what cut to use
+ if ( CostBest > CostCur )
+ {
+ GainBest = nNodesSaved - nNodesAdded; // pure node cost
+ CostBest = CostCur; // cost with placement
+ pGraphBest = pGraphCur; // subgraph to be used for rewriting
+
+ // score the graph
+ if ( nNodesSaved - nNodesAdded > 0 )
+ {
+ pNode->nScore++;
+ pNode->nGain += GainBest;
+ pNode->nAdded += nNodesAdded;
+ }
+ }
+ }
+ else
+*/
{
- GainBest = nNodesSaved - nNodesAdded;
- pGraphBest = pGraphCur;
+ // count the gain at this node
+ if ( GainBest < nNodesSaved - nNodesAdded )
+ {
+ GainBest = nNodesSaved - nNodesAdded;
+ pGraphBest = pGraphCur;
+
+ // score the graph
+ if ( nNodesSaved - nNodesAdded > 0 )
+ {
+ pNode->nScore++;
+ pNode->nGain += GainBest;
+ pNode->nAdded += nNodesAdded;
+ }
+ }
}
}
if ( GainBest == -1 )
@@ -199,6 +331,257 @@ Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCu
return pGraphBest;
}
+/**Function*************************************************************
+
+ Synopsis [Checks the type of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwr_CutIsBoolean_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, int fMarkA )
+{
+ if ( Vec_PtrFind(vLeaves, pObj) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pObj)) >= 0 )
+ {
+ if ( fMarkA )
+ pObj->fMarkA = 1;
+ else
+ pObj->fMarkB = 1;
+ return;
+ }
+ assert( !Abc_ObjIsCi(pObj) );
+ Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, fMarkA );
+ Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, fMarkA );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks the type of the cut.]
+
+ Description [Returns 1(0) if the cut is Boolean (algebraic).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pTemp;
+ int i, RetValue;
+ Vec_PtrForEachEntry( vLeaves, pTemp, i )
+ {
+ pTemp = Abc_ObjRegular(pTemp);
+ assert( !pTemp->fMarkA && !pTemp->fMarkB );
+ }
+ Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, 1 );
+ Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, 0 );
+ RetValue = 0;
+ Vec_PtrForEachEntry( vLeaves, pTemp, i )
+ {
+ pTemp = Abc_ObjRegular(pTemp);
+ RetValue |= pTemp->fMarkA && pTemp->fMarkB;
+ pTemp->fMarkA = pTemp->fMarkB = 0;
+ }
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Count the nodes in the cut space of a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwr_CutCountNumNodes_rec( Abc_Obj_t * pObj, Cut_Cut_t * pCut, Vec_Ptr_t * vNodes )
+{
+ int i;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ if ( pCut->pLeaves[i] == pObj->Id )
+ {
+ // check if the node is collected
+ if ( pObj->fMarkC == 0 )
+ {
+ pObj->fMarkC = 1;
+ Vec_PtrPush( vNodes, pObj );
+ }
+ return;
+ }
+ assert( Abc_ObjIsNode(pObj) );
+ // check if the node is collected
+ if ( pObj->fMarkC == 0 )
+ {
+ pObj->fMarkC = 1;
+ Vec_PtrPush( vNodes, pObj );
+ }
+ // traverse the fanins
+ Rwr_CutCountNumNodes_rec( Abc_ObjFanin0(pObj), pCut, vNodes );
+ Rwr_CutCountNumNodes_rec( Abc_ObjFanin1(pObj), pCut, vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count the nodes in the cut space of a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwr_CutCountNumNodes( Abc_Obj_t * pObj, Cut_Cut_t * pCut )
+{
+ Vec_Ptr_t * vNodes;
+ int i, Counter;
+ // collect all nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext )
+ Rwr_CutCountNumNodes_rec( pObj, pCut, vNodes );
+ // clean all nodes
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ pObj->fMarkC = 0;
+ // delete and return
+ Counter = Vec_PtrSize(vNodes);
+ Vec_PtrFree( vNodes );
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns depth of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pLeaf;
+ int i, Depth0, Depth1;
+ if ( Abc_ObjIsCi(pObj) )
+ return 0;
+ Vec_PtrForEachEntry( vLeaves, pLeaf, i )
+ if ( pObj == Abc_ObjRegular(pLeaf) )
+ return 0;
+ Depth0 = Rwr_NodeGetDepth_rec( Abc_ObjFanin0(pObj), vLeaves );
+ Depth1 = Rwr_NodeGetDepth_rec( Abc_ObjFanin1(pObj), vLeaves );
+ return 1 + ABC_MAX( Depth0, Depth1 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwr_ScoresClean( Rwr_Man_t * p )
+{
+ Vec_Ptr_t * vSubgraphs;
+ Rwr_Node_t * pNode;
+ int i, k;
+ for ( i = 0; i < p->vClasses->nSize; i++ )
+ {
+ vSubgraphs = Vec_VecEntry( p->vClasses, i );
+ Vec_PtrForEachEntry( vSubgraphs, pNode, k )
+ pNode->nScore = pNode->nGain = pNode->nAdded = 0;
+ }
+}
+
+static int Gains[222];
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwr_ScoresCompare( int * pNum1, int * pNum2 )
+{
+ if ( Gains[*pNum1] > Gains[*pNum2] )
+ return -1;
+ if ( Gains[*pNum1] < Gains[*pNum2] )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwr_ScoresReport( Rwr_Man_t * p )
+{
+ extern void Ivy_TruthDsdComputePrint( unsigned uTruth );
+ int Perm[222];
+ Vec_Ptr_t * vSubgraphs;
+ Rwr_Node_t * pNode;
+ int i, iNew, k;
+ unsigned uTruth;
+ // collect total gains
+ assert( p->vClasses->nSize == 222 );
+ for ( i = 0; i < p->vClasses->nSize; i++ )
+ {
+ Perm[i] = i;
+ Gains[i] = 0;
+ vSubgraphs = Vec_VecEntry( p->vClasses, i );
+ Vec_PtrForEachEntry( vSubgraphs, pNode, k )
+ Gains[i] += pNode->nGain;
+ }
+ // sort the gains
+ qsort( Perm, 222, sizeof(int), (int (*)(const void *, const void *))Rwr_ScoresCompare );
+
+ // print classes
+ for ( i = 0; i < p->vClasses->nSize; i++ )
+ {
+ iNew = Perm[i];
+ if ( Gains[iNew] == 0 )
+ break;
+ vSubgraphs = Vec_VecEntry( p->vClasses, iNew );
+ printf( "CLASS %3d: Subgr = %3d. Total gain = %6d. ", iNew, Vec_PtrSize(vSubgraphs), Gains[iNew] );
+ uTruth = (unsigned)p->pMapInv[iNew];
+ Extra_PrintBinary( stdout, &uTruth, 16 );
+ printf( " " );
+ Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[iNew] | ((unsigned)p->pMapInv[iNew] << 16) );
+ Vec_PtrForEachEntry( vSubgraphs, pNode, k )
+ {
+ if ( pNode->nScore == 0 )
+ continue;
+ printf( " %2d: S=%5d. A=%5d. G=%6d. ", k, pNode->nScore, pNode->nAdded, pNode->nGain );
+ Dec_GraphPrint( stdout, (Dec_Graph_t *)pNode->pNext, NULL, NULL );
+ }
+ }
+}
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/opt/rwr/rwrExp.c b/src/opt/rwr/rwrExp.c
index e93a2611..2d00bb1c 100644
--- a/src/opt/rwr/rwrExp.c
+++ b/src/opt/rwr/rwrExp.c
@@ -47,7 +47,7 @@ static Rwr_Man4_t * s_pManRwrExp4 = NULL;
static Rwr_Man5_t * s_pManRwrExp5 = NULL;
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/rwr/rwrLib.c b/src/opt/rwr/rwrLib.c
index fbcb8916..1cdf350e 100644
--- a/src/opt/rwr/rwrLib.c
+++ b/src/opt/rwr/rwrLib.c
@@ -28,7 +28,7 @@ static Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_N
static void Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/rwr/rwrMan.c b/src/opt/rwr/rwrMan.c
index a21dd520..87a080c7 100644
--- a/src/opt/rwr/rwrMan.c
+++ b/src/opt/rwr/rwrMan.c
@@ -27,7 +27,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -50,7 +50,7 @@ clk = clock();
p = ALLOC( Rwr_Man_t, 1 );
memset( p, 0, sizeof(Rwr_Man_t) );
p->nFuncs = (1<<16);
- pManDec = Abc_FrameReadManDec(Abc_FrameGetGlobalFrame());
+ pManDec = Abc_FrameReadManDec();
p->puCanons = pManDec->puCanons;
p->pPhases = pManDec->pPhases;
p->pPerms = pManDec->pPerms;
@@ -75,6 +75,7 @@ clk = clock();
p->vLevNums = Vec_IntAlloc( 50 );
p->vFanins = Vec_PtrAlloc( 50 );
p->vFaninsCur = Vec_PtrAlloc( 50 );
+ p->vNodesTemp = Vec_PtrAlloc( 50 );
if ( fPrecompute )
{ // precompute subgraphs
Rwr_ManPrecompute( p );
@@ -112,11 +113,13 @@ void Rwr_ManStop( Rwr_Man_t * p )
Dec_GraphFree( (Dec_Graph_t *)pNode->pNext );
}
if ( p->vClasses ) Vec_VecFree( p->vClasses );
+ Vec_PtrFree( p->vNodesTemp );
Vec_PtrFree( p->vForest );
Vec_IntFree( p->vLevNums );
Vec_PtrFree( p->vFanins );
Vec_PtrFree( p->vFaninsCur );
- Extra_MmFixedStop( p->pMmNode, 0 );
+ Extra_MmFixedStop( p->pMmNode );
+ FREE( p->pMapInv );
free( p->pTable );
free( p->pPractical );
free( p->pPerms4 );
@@ -147,20 +150,50 @@ void Rwr_ManPrintStats( Rwr_Man_t * p )
printf( "Used NPN classes = %8d.\n", Counter );
printf( "Nodes considered = %8d.\n", p->nNodesConsidered );
printf( "Nodes rewritten = %8d.\n", p->nNodesRewritten );
- printf( "Calculated gain = %8d.\n", p->nNodesGained );
+ printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg );
PRT( "Start ", p->timeStart );
PRT( "Cuts ", p->timeCut );
PRT( "Resynthesis ", p->timeRes );
+ PRT( " Mffc ", p->timeMffc );
PRT( " Eval ", p->timeEval );
+ PRT( "Update ", p->timeUpdate );
PRT( "TOTAL ", p->timeTotal );
/*
- printf( "The scores are : " );
+ printf( "The scores are:\n" );
for ( i = 0; i < 222; i++ )
if ( p->nScores[i] > 0 )
- printf( "%d=%d ", i, p->nScores[i] );
- printf( "\n" );
+ {
+ extern void Ivy_TruthDsdComputePrint( unsigned uTruth );
+ printf( "%3d = %8d canon = %5d ", i, p->nScores[i], p->pMapInv[i] );
+ Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) );
+ }
*/
+ printf( "\n" );
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwr_ManPrintStatsFile( Rwr_Man_t * p )
+{
+ FILE * pTable;
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%d ", p->nCutsGood );
+ fprintf( pTable, "%d ", p->nSubgraphs );
+ fprintf( pTable, "%d ", p->nNodesRewritten );
+ fprintf( pTable, "%d", p->nNodesGained );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
}
/**Function*************************************************************
@@ -190,6 +223,22 @@ void * Rwr_ManReadDecs( Rwr_Man_t * p )
SeeAlso []
***********************************************************************/
+Vec_Ptr_t * Rwr_ManReadLeaves( Rwr_Man_t * p )
+{
+ return p->vFanins;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Rwr_ManReadCompl( Rwr_Man_t * p )
{
return p->fCompl;
@@ -222,6 +271,22 @@ void Rwr_ManAddTimeCuts( Rwr_Man_t * p, int Time )
SeeAlso []
***********************************************************************/
+void Rwr_ManAddTimeUpdate( Rwr_Man_t * p, int Time )
+{
+ p->timeUpdate += Time;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the resynthesis manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
void Rwr_ManAddTimeTotal( Rwr_Man_t * p, int Time )
{
p->timeTotal += Time;
diff --git a/src/opt/rwr/rwrPrint.c b/src/opt/rwr/rwrPrint.c
index 30c99f00..82ad2a90 100644
--- a/src/opt/rwr/rwrPrint.c
+++ b/src/opt/rwr/rwrPrint.c
@@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -79,6 +79,33 @@ void Rwr_GetBushVolume( Rwr_Man_t * p, int Entry, int * pVolume, int * pnFuncs )
/**Function*************************************************************
+ Synopsis [Adds the node to the end of the list.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwr_GetBushSumOfVolumes( Rwr_Man_t * p, int Entry )
+{
+ Rwr_Node_t * pNode;
+ int Volume, VolumeTotal = 0;
+ for ( pNode = p->pTable[Entry]; pNode; pNode = pNode->pNext )
+ {
+ if ( pNode->uTruth != p->puCanons[pNode->uTruth] )
+ continue;
+ Volume = 0;
+ Rwr_ManIncTravId( p );
+ Rwr_Trav2_rec( p, pNode, &Volume );
+ VolumeTotal += Volume;
+ }
+ return VolumeTotal;
+}
+
+/**Function*************************************************************
+
Synopsis [Prints one rwr node.]
Description []
@@ -219,9 +246,9 @@ void Rwr_ManPrint( Rwr_Man_t * p )
continue;
if ( i != p->puCanons[i] )
continue;
- fprintf( pFile, "\nClass %3d. Func %6d. ", p->pMap[i], Counter++ );
+ fprintf( pFile, "\nClass %3d. Func %6d. ", p->pMap[i], Counter++ );
Rwr_GetBushVolume( p, i, &Volume, &nFuncs );
- fprintf( pFile, "Functions = %2d. Volume = %2d. ", nFuncs, Volume );
+ fprintf( pFile, "Roots = %3d. Vol = %3d. Sum = %3d. ", nFuncs, Volume, Rwr_GetBushSumOfVolumes(p, i) );
uTruth = i;
Extra_PrintBinary( pFile, &uTruth, 16 );
fprintf( pFile, "\n" );
diff --git a/src/opt/rwr/rwrTemp.c b/src/opt/rwr/rwrTemp.c
new file mode 100644
index 00000000..3ffbd408
--- /dev/null
+++ b/src/opt/rwr/rwrTemp.c
@@ -0,0 +1,121 @@
+/**CFile****************************************************************
+
+ FileName [rwrCut.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [DAG-aware AIG rewriting package.]
+
+ Synopsis [Cut computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: rwrCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "rwr.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int pTruths[13719];
+static int pFreqs[13719];
+static int pPerm[13719];
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rwr_TempCompare( int * pNum1, int * pNum2 )
+{
+ int Freq1 = pFreqs[*pNum1];
+ int Freq2 = pFreqs[*pNum2];
+ if ( Freq1 < Freq2 )
+ return 1;
+ if ( Freq1 > Freq2 )
+ return -1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rwr_Temp()
+{
+ char Buffer[32];
+ int nFuncs = 13719;
+ int nEntries = 100;
+ unsigned uTruth;
+ int i, k;
+ FILE * pFile;
+
+ pFile = fopen( "nnclass_stats5.txt", "r" );
+ for ( i = 0; i < 13719; i++ )
+ {
+ fscanf( pFile, "%s%d", Buffer, &pFreqs[i] );
+ Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 );
+ pTruths[i] = uTruth;
+ }
+ fclose( pFile );
+
+ for ( i = 0; i < 13719; i++ )
+ pPerm[i] = i;
+
+ qsort( (void *)pPerm, 13719, sizeof(int),
+ (int (*)(const void *, const void *)) Rwr_TempCompare );
+
+
+ pFile = fopen( "5npn_100.blif", "w" );
+ fprintf( pFile, "# Most frequent NPN classes of 5 vars.\n" );
+ fprintf( pFile, ".model 5npn\n" );
+ fprintf( pFile, ".inputs a b c d e\n" );
+ fprintf( pFile, ".outputs" );
+ for ( i = 0; i < nEntries; i++ )
+ fprintf( pFile, " %02d", i );
+ fprintf( pFile, "\n" );
+
+ for ( i = 0; i < nEntries; i++ )
+ {
+ fprintf( pFile, ".names a b c d e %02d\n", i );
+ uTruth = pTruths[pPerm[i]];
+ for ( k = 0; k < 32; k++ )
+ if ( uTruth & (1 << k) )
+ {
+ Extra_PrintBinary( pFile, &k, 5 );
+ fprintf( pFile, " 1\n" );
+ }
+ }
+ fprintf( pFile, ".end\n" );
+ fclose( pFile );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/rwr/rwrUtil.c b/src/opt/rwr/rwrUtil.c
index 65b2bd6f..b2add2bf 100644
--- a/src/opt/rwr/rwrUtil.c
+++ b/src/opt/rwr/rwrUtil.c
@@ -34,7 +34,7 @@ static unsigned short s_RwtAigSubgraphs[];
#endif
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/sim/module.make b/src/opt/sim/module.make
index 43d0a125..54058402 100644
--- a/src/opt/sim/module.make
+++ b/src/opt/sim/module.make
@@ -1,5 +1,6 @@
SRC += src/opt/sim/simMan.c \
src/opt/sim/simSat.c \
+ src/opt/sim/simSeq.c \
src/opt/sim/simSupp.c \
src/opt/sim/simSwitch.c \
src/opt/sim/simSym.c \
diff --git a/src/opt/sim/sim.h b/src/opt/sim/sim.h
index afed7190..7fcf5ae6 100644
--- a/src/opt/sim/sim.h
+++ b/src/opt/sim/sim.h
@@ -17,10 +17,14 @@
Revision [$Id: sim.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
-
+
#ifndef __SIM_H__
#define __SIM_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
The ideas realized in this package are described in the paper:
"Detecting Symmetries in Boolean Functions using Circuit Representation,
@@ -98,6 +102,7 @@ struct Sim_Man_t_
Abc_Ntk_t * pNtk;
int nInputs;
int nOutputs;
+ int fLightweight;
// internal simulation information
int nSimBits; // the number of bits in simulation info
int nSimWords; // the number of words in simulation info
@@ -135,11 +140,11 @@ struct Sim_Pat_t_
};
////////////////////////////////////////////////////////////////////////
-/// MACRO DEFITIONS ///
+/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
-#define SIM_NUM_WORDS(n) ((n)/32 + (((n)%32) > 0))
-#define SIM_LAST_BITS(n) ((((n)%32) > 0)? (n)%32 : 32)
+#define SIM_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0))
+#define SIM_LAST_BITS(n) ((((n)&31) > 0)? (n)&31 : 32)
#define SIM_MASK_FULL (0xFFFFFFFF)
#define SIM_MASK_BEG(n) (SIM_MASK_FULL >> (32-n))
@@ -162,6 +167,7 @@ struct Sim_Pat_t_
#define Sim_SuppFunHasVar(vSupps,Output,v) Sim_HasBit((unsigned*)(vSupps)->pArray[Output],(v))
#define Sim_SimInfoSetVar(vSupps,pNode,v) Sim_SetBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v))
#define Sim_SimInfoHasVar(vSupps,pNode,v) Sim_HasBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v))
+#define Sim_SimInfoGet(vInfo,pNode) ((unsigned *)((vInfo)->pArray[(pNode)->Id]))
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
@@ -171,11 +177,14 @@ struct Sim_Pat_t_
extern Sym_Man_t * Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose );
extern void Sym_ManStop( Sym_Man_t * p );
extern void Sym_ManPrintStats( Sym_Man_t * p );
-extern Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk );
+extern Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight );
extern void Sim_ManStop( Sim_Man_t * p );
extern void Sim_ManPrintStats( Sim_Man_t * p );
extern Sim_Pat_t * Sim_ManPatAlloc( Sim_Man_t * p );
extern void Sim_ManPatFree( Sim_Man_t * p, Sim_Pat_t * pPat );
+/*=== simSeq.c ==========================================================*/
+extern Vec_Ptr_t * Sim_SimulateSeqRandom( Abc_Ntk_t * pNtk, int nFrames, int nWords );
+extern Vec_Ptr_t * Sim_SimulateSeqModel( Abc_Ntk_t * pNtk, int nFrames, int * pModel );
/*=== simSupp.c ==========================================================*/
extern Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk );
extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose );
@@ -197,17 +206,28 @@ extern void Sim_UtilInfoFlip( Sim_Man_t * p, Abc_Obj_t * pNode );
extern bool Sim_UtilInfoCompare( Sim_Man_t * p, Abc_Obj_t * pNode );
extern void Sim_UtilSimulate( Sim_Man_t * p, bool fFirst );
extern void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, bool fType, bool fType1, bool fType2 );
-extern void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords );
+extern void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset );
+extern void Sim_UtilTransferNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset, int fShift );
extern int Sim_UtilCountSuppSizes( Sim_Man_t * p, int fStruct );
extern int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords );
-extern void Sim_UtilGetRandom( unsigned * pPatRand, int nSimWords );
+extern Vec_Int_t * Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords );
+extern void Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords );
+extern void Sim_UtilSetCompl( unsigned * pPatRand, int nSimWords );
+extern void Sim_UtilSetConst( unsigned * pPatRand, int nSimWords, int fConst1 );
+extern int Sim_UtilInfoIsEqual( unsigned * pPats1, unsigned * pPats2, int nSimWords );
+extern int Sim_UtilInfoIsImp( unsigned * pPats1, unsigned * pPats2, int nSimWords );
+extern int Sim_UtilInfoIsClause( unsigned * pPats1, unsigned * pPats2, int nSimWords );
extern int Sim_UtilCountAllPairs( Vec_Ptr_t * vSuppFun, int nSimWords, Vec_Int_t * vCounters );
extern void Sim_UtilCountPairsAll( Sym_Man_t * p );
extern int Sim_UtilMatrsAreDisjoint( Sym_Man_t * p );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
-#endif
-
diff --git a/src/opt/sim/simMan.c b/src/opt/sim/simMan.c
index 780ecfd8..3b50ad84 100644
--- a/src/opt/sim/simMan.c
+++ b/src/opt/sim/simMan.c
@@ -26,12 +26,12 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
- Synopsis [Starts the simulatin manager.]
+ Synopsis [Starts the simulation manager.]
Description []
@@ -83,7 +83,7 @@ Sym_Man_t * Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose )
/**Function*************************************************************
- Synopsis [Stops the simulatin manager.]
+ Synopsis [Stops the simulation manager.]
Description []
@@ -149,11 +149,9 @@ void Sym_ManPrintStats( Sym_Man_t * p )
}
-
-
/**Function*************************************************************
- Synopsis [Starts the simulatin manager.]
+ Synopsis [Starts the simulation manager.]
Description []
@@ -162,7 +160,7 @@ void Sym_ManPrintStats( Sym_Man_t * p )
SeeAlso []
***********************************************************************/
-Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk )
+Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight )
{
Sim_Man_t * p;
// start the manager
@@ -175,24 +173,27 @@ Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk )
p->nSimBits = 2048;
p->nSimWords = SIM_NUM_WORDS(p->nSimBits);
p->vSim0 = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 );
- p->vSim1 = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 );
- // support information
- p->nSuppBits = Abc_NtkCiNum(pNtk);
- p->nSuppWords = SIM_NUM_WORDS(p->nSuppBits);
- p->vSuppStr = Sim_ComputeStrSupp( pNtk );
- p->vSuppFun = Sim_UtilInfoAlloc( Abc_NtkCoNum(p->pNtk), p->nSuppWords, 1 );
- // other data
- p->pMmPat = Extra_MmFixedStart( sizeof(Sim_Pat_t) + p->nSuppWords * sizeof(unsigned) );
- p->vFifo = Vec_PtrAlloc( 100 );
- p->vDiffs = Vec_IntAlloc( 100 );
- // allocate support targets (array of unresolved outputs for each input)
- p->vSuppTargs = Vec_VecStart( p->nInputs );
+ p->fLightweight = fLightweight;
+ if (!p->fLightweight) {
+ p->vSim1 = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 );
+ // support information
+ p->nSuppBits = Abc_NtkCiNum(pNtk);
+ p->nSuppWords = SIM_NUM_WORDS(p->nSuppBits);
+ p->vSuppStr = Sim_ComputeStrSupp( pNtk );
+ p->vSuppFun = Sim_UtilInfoAlloc( Abc_NtkCoNum(p->pNtk), p->nSuppWords, 1 );
+ // other data
+ p->pMmPat = Extra_MmFixedStart( sizeof(Sim_Pat_t) + p->nSuppWords * sizeof(unsigned) );
+ p->vFifo = Vec_PtrAlloc( 100 );
+ p->vDiffs = Vec_IntAlloc( 100 );
+ // allocate support targets (array of unresolved outputs for each input)
+ p->vSuppTargs = Vec_VecStart( p->nInputs );
+ }
return p;
}
/**Function*************************************************************
- Synopsis [Stops the simulatin manager.]
+ Synopsis [Stops the simulation manager.]
Description []
@@ -209,7 +210,7 @@ void Sim_ManStop( Sim_Man_t * p )
if ( p->vSuppStr ) Sim_UtilInfoFree( p->vSuppStr );
// if ( p->vSuppFun ) Sim_UtilInfoFree( p->vSuppFun );
if ( p->vSuppTargs ) Vec_VecFree( p->vSuppTargs );
- if ( p->pMmPat ) Extra_MmFixedStop( p->pMmPat, 0 );
+ if ( p->pMmPat ) Extra_MmFixedStop( p->pMmPat );
if ( p->vFifo ) Vec_PtrFree( p->vFifo );
if ( p->vDiffs ) Vec_IntFree( p->vDiffs );
free( p );
diff --git a/src/opt/sim/simSat.c b/src/opt/sim/simSat.c
index b4e080fe..d514f7f2 100644
--- a/src/opt/sim/simSat.c
+++ b/src/opt/sim/simSat.c
@@ -26,7 +26,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
diff --git a/src/opt/sim/simSeq.c b/src/opt/sim/simSeq.c
new file mode 100644
index 00000000..49fb939f
--- /dev/null
+++ b/src/opt/sim/simSeq.c
@@ -0,0 +1,171 @@
+/**CFile****************************************************************
+
+ FileName [simSeq.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Simulation for sequential circuits.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: simUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "sim.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Sim_SimulateSeqFrame( Vec_Ptr_t * vInfo, Abc_Ntk_t * pNtk, int iFrames, int nWords, int fTransfer );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Simulates sequential circuit.]
+
+ Description [Takes sequential circuit (pNtk). Simulates the given number
+ (nFrames) of the circuit with the given number of machine words (nWords)
+ of random simulation data, starting from the initial state. If the initial
+ state of some latches is a don't-care, uses random input for that latch.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Sim_SimulateSeqRandom( Abc_Ntk_t * pNtk, int nFrames, int nWords )
+{
+ Vec_Ptr_t * vInfo;
+ Abc_Obj_t * pNode;
+ int i;
+ assert( Abc_NtkIsStrash(pNtk) );
+ vInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nWords * nFrames, 0 );
+ // set the constant data
+ pNode = Abc_AigConst1(pNtk);
+ Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords * nFrames, 1 );
+ // set the random PI data
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ Sim_UtilSetRandom( Sim_SimInfoGet(vInfo,pNode), nWords * nFrames );
+ // set the initial state data
+ Abc_NtkForEachLatch( pNtk, pNode, i )
+ if ( Abc_LatchIsInit0(pNode) )
+ Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords, 0 );
+ else if ( Abc_LatchIsInit1(pNode) )
+ Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords, 1 );
+ else
+ Sim_UtilSetRandom( Sim_SimInfoGet(vInfo,pNode), nWords );
+ // simulate the nodes for the given number of timeframes
+ for ( i = 0; i < nFrames; i++ )
+ Sim_SimulateSeqFrame( vInfo, pNtk, i, nWords, (int)(i < nFrames-1) );
+ return vInfo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates sequential circuit.]
+
+ Description [Takes sequential circuit (pNtk). Simulates the given number
+ (nFrames) of the circuit with the given model. The model is assumed to
+ contain values of PIs for each frame. The latches are initialized to
+ the initial state. One word of data is simulated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Sim_SimulateSeqModel( Abc_Ntk_t * pNtk, int nFrames, int * pModel )
+{
+ Vec_Ptr_t * vInfo;
+ Abc_Obj_t * pNode;
+ unsigned * pUnsigned;
+ int i, k;
+ vInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nFrames, 0 );
+ // set the constant data
+ pNode = Abc_AigConst1(pNtk);
+ Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nFrames, 1 );
+ // set the random PI data
+ Abc_NtkForEachPi( pNtk, pNode, i )
+ {
+ pUnsigned = Sim_SimInfoGet(vInfo,pNode);
+ for ( k = 0; k < nFrames; k++ )
+ pUnsigned[k] = pModel[k * Abc_NtkPiNum(pNtk) + i] ? ~((unsigned)0) : 0;
+ }
+ // set the initial state data
+ Abc_NtkForEachLatch( pNtk, pNode, i )
+ {
+ pUnsigned = Sim_SimInfoGet(vInfo,pNode);
+ if ( Abc_LatchIsInit0(pNode) )
+ pUnsigned[0] = 0;
+ else if ( Abc_LatchIsInit1(pNode) )
+ pUnsigned[0] = ~((unsigned)0);
+ else
+ pUnsigned[0] = SIM_RANDOM_UNSIGNED;
+ }
+ // simulate the nodes for the given number of timeframes
+ for ( i = 0; i < nFrames; i++ )
+ Sim_SimulateSeqFrame( vInfo, pNtk, i, 1, (int)(i < nFrames-1) );
+/*
+ // print the simulated values
+ for ( i = 0; i < nFrames; i++ )
+ {
+ printf( "Frame %d : ", i+1 );
+ Abc_NtkForEachPi( pNtk, pNode, k )
+ printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 );
+ printf( " " );
+ Abc_NtkForEachLatch( pNtk, pNode, k )
+ printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 );
+ printf( " " );
+ Abc_NtkForEachPo( pNtk, pNode, k )
+ printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 );
+ printf( "\n" );
+ }
+ printf( "\n" );
+*/
+ return vInfo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one frame of sequential circuit.]
+
+ Description [Assumes that the latches and POs are already initialized.
+ In the end transfers the data to the latches of the next frame.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_SimulateSeqFrame( Vec_Ptr_t * vInfo, Abc_Ntk_t * pNtk, int iFrames, int nWords, int fTransfer )
+{
+ Abc_Obj_t * pNode;
+ int i;
+ Abc_NtkForEachNode( pNtk, pNode, i )
+ Sim_UtilSimulateNodeOne( pNode, vInfo, nWords, iFrames * nWords );
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ Sim_UtilTransferNodeOne( pNode, vInfo, nWords, iFrames * nWords, 0 );
+ if ( !fTransfer )
+ return;
+ Abc_NtkForEachLatch( pNtk, pNode, i )
+ Sim_UtilTransferNodeOne( pNode, vInfo, nWords, iFrames * nWords, 1 );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/opt/sim/simSupp.c b/src/opt/sim/simSupp.c
index 576e19cc..f7048f4a 100644
--- a/src/opt/sim/simSupp.c
+++ b/src/opt/sim/simSupp.c
@@ -35,10 +35,8 @@ static void Sim_UtilAssignFromFifo( Sim_Man_t * p );
static void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int nCounters );
static int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Output );
-extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes );
-
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -68,8 +66,8 @@ Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk )
// derive the structural supports of the internal nodes
Abc_NtkForEachNode( pNtk, pNode, i )
{
- if ( Abc_NodeIsConst(pNode) )
- continue;
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
pSimmNode = vSuppStr->pArray[ pNode->Id ];
pSimmNode1 = vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ];
pSimmNode2 = vSuppStr->pArray[ Abc_ObjFaninId1(pNode) ];
@@ -108,7 +106,7 @@ Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose )
srand( 0xABC );
// start the simulation manager
- p = Sim_ManStart( pNtk );
+ p = Sim_ManStart( pNtk, 0 );
// compute functional support using one round of random simulation
Sim_UtilAssignRandom( p );
@@ -469,9 +467,10 @@ void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int Limit )
// transform the miter into a fraig
Fraig_ParamsSetDefault( &Params );
+ Params.nSeconds = ABC_INFINITY;
Params.fInternal = 1;
clk = clock();
- pMan = Abc_NtkToFraig( pMiter, &Params, 0 );
+ pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 );
p->timeFraig += clock() - clk;
clk = clock();
Fraig_ManProveMiter( pMan );
@@ -587,10 +586,6 @@ int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Out
}
// perform the traversal
RetValue = 3 & Sim_NtkSimTwoPats_rec( Abc_ObjFanin0( Abc_NtkCo(pNtk,Output) ) );
- if ( RetValue == 0 || RetValue == 3 )
- {
- int x = 0;
- }
// assert( RetValue == 1 || RetValue == 2 );
return RetValue == 1 || RetValue == 2;
}
diff --git a/src/opt/sim/simSwitch.c b/src/opt/sim/simSwitch.c
index b43597f3..218d4d59 100644
--- a/src/opt/sim/simSwitch.c
+++ b/src/opt/sim/simSwitch.c
@@ -29,7 +29,7 @@ static void Sim_NodeSimulate( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimW
static float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -65,7 +65,7 @@ Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns )
Abc_NtkForEachCi( pNtk, pNode, i )
{
pSimInfo = Vec_PtrEntry(vSimInfo, pNode->Id);
- Sim_UtilGetRandom( pSimInfo, nSimWords );
+ Sim_UtilSetRandom( pSimInfo, nSimWords );
pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords );
}
// simulate the internal nodes
@@ -73,7 +73,7 @@ Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns )
Vec_PtrForEachEntry( vNodes, pNode, i )
{
pSimInfo = Vec_PtrEntry(vSimInfo, pNode->Id);
- Sim_UtilSimulateNodeOne( pNode, vSimInfo, nSimWords );
+ Sim_UtilSimulateNodeOne( pNode, vSimInfo, nSimWords, 0 );
pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords );
}
Vec_PtrFree( vNodes );
diff --git a/src/opt/sim/simSym.c b/src/opt/sim/simSym.c
index c452bb1b..71de5b05 100644
--- a/src/opt/sim/simSym.c
+++ b/src/opt/sim/simSym.c
@@ -26,7 +26,7 @@
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -71,7 +71,7 @@ p->timeStruct = clock() - clk;
for ( i = 1; i <= 1000; i++ )
{
// simulate this pattern
- Sim_UtilGetRandom( p->uPatRand, p->nSimWords );
+ Sim_UtilSetRandom( p->uPatRand, p->nSimWords );
Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms );
if ( i % 50 != 0 )
continue;
@@ -125,6 +125,7 @@ p->timeStruct = clock() - clk;
if ( fVerbose )
printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n",
p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem );
+// Sim_UtilCountPairsAllPrint( p );
Result = p->nPairsSymm;
vResult = p->vMatrSymms;
diff --git a/src/opt/sim/simSymSat.c b/src/opt/sim/simSymSat.c
index db9917b3..7690a891 100644
--- a/src/opt/sim/simSymSat.c
+++ b/src/opt/sim/simSymSat.c
@@ -26,11 +26,10 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-extern int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern );
-extern Fraig_Man_t * Abc_NtkToFraig( Abc_Ntk_t * pNtk, Fraig_Params_t * pParams, int fAllNodes );
+static int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -145,9 +144,10 @@ int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned *
Params.fInternal = 1;
Params.nPatsRand = 512;
Params.nPatsDyna = 512;
+ Params.nSeconds = ABC_INFINITY;
clk = clock();
- pMan = Abc_NtkToFraig( pMiter, &Params, 0 );
+ pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 );
p->timeFraig += clock() - clk;
clk = clock();
Fraig_ManProveMiter( pMan );
diff --git a/src/opt/sim/simSymSim.c b/src/opt/sim/simSymSim.c
index 94028c47..2282825b 100644
--- a/src/opt/sim/simSymSim.c
+++ b/src/opt/sim/simSymSim.c
@@ -29,7 +29,7 @@ static void Sim_SymmsCreateSquare( Sym_Man_t * p, unsigned * pPat );
static void Sim_SymmsDeriveInfo( Sym_Man_t * p, unsigned * pPat, Abc_Obj_t * pNode, Vec_Ptr_t * vMatrsNonSym, int Output );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -55,9 +55,9 @@ void Sim_SymmsSimulate( Sym_Man_t * p, unsigned * pPat, Vec_Ptr_t * vMatrsNonSym
clk = clock();
Vec_PtrForEachEntry( p->vNodes, pNode, i )
{
- if ( Abc_NodeIsConst(pNode) )
- continue;
- Sim_UtilSimulateNodeOne( pNode, p->vSim, p->nSimWords );
+// if ( Abc_NodeIsConst(pNode) )
+// continue;
+ Sim_UtilSimulateNodeOne( pNode, p->vSim, p->nSimWords, 0 );
}
p->timeSim += clock() - clk;
// collect info into the CO matrices
@@ -65,8 +65,8 @@ clk = clock();
Abc_NtkForEachCo( p->pNtk, pNode, i )
{
pNode = Abc_ObjFanin0(pNode);
- if ( Abc_ObjIsCi(pNode) || Abc_NodeIsConst(pNode) )
- continue;
+// if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) )
+// continue;
nPairsTotal = Vec_IntEntry(p->vPairsTotal, i);
nPairsSym = Vec_IntEntry(p->vPairsSym, i);
nPairsNonSym = Vec_IntEntry(p->vPairsNonSym,i);
diff --git a/src/opt/sim/simSymStr.c b/src/opt/sim/simSymStr.c
index ed7e93bf..d52c4328 100644
--- a/src/opt/sim/simSymStr.c
+++ b/src/opt/sim/simSymStr.c
@@ -41,7 +41,7 @@ static void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * v
static int * Sim_SymmsCreateMap( Abc_Ntk_t * pNtk );
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -74,15 +74,16 @@ void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * v
vNodes = Abc_NtkDfs( pNtk, 0 );
Vec_PtrForEachEntry( vNodes, pTemp, i )
{
- if ( Abc_NodeIsConst(pTemp) )
- continue;
+// if ( Abc_NodeIsConst(pTemp) )
+// continue;
Sim_SymmsStructComputeOne( pNtk, pTemp, pMap );
}
// collect the results for the COs;
Abc_NtkForEachCo( pNtk, pTemp, i )
{
+//printf( "Output %d:\n", i );
pTemp = Abc_ObjFanin0(pTemp);
- if ( Abc_ObjIsCi(pTemp) || Abc_NodeIsConst(pTemp) )
+ if ( Abc_ObjIsCi(pTemp) || Abc_AigNodeIsConst(pTemp) )
continue;
Sim_SymmsTransferToMatrix( Vec_PtrEntry(vMatrs, i), SIM_READ_SYMMS(pTemp), Vec_PtrEntry(vSuppFun, i) );
}
@@ -92,7 +93,7 @@ void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * v
Abc_NtkForEachCi( pNtk, pTemp, i )
Vec_IntFree( SIM_READ_SYMMS(pTemp) );
Vec_PtrForEachEntry( vNodes, pTemp, i )
- if ( !Abc_NodeIsConst(pTemp) )
+// if ( !Abc_NodeIsConst(pTemp) )
Vec_IntFree( SIM_READ_SYMMS(pTemp) );
Vec_PtrFree( vNodes );
free( pMap );
@@ -444,6 +445,7 @@ void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * vSymms, u
uSymm = (unsigned)vSymms->pArray[i];
Ind1 = (uSymm & 0xffff);
Ind2 = (uSymm >> 16);
+//printf( "%d,%d ", Ind1, Ind2 );
// skip variables that are not in the true support
assert( Sim_HasBit(pSupport, Ind1) == Sim_HasBit(pSupport, Ind2) );
if ( !Sim_HasBit(pSupport, Ind1) || !Sim_HasBit(pSupport, Ind2) )
diff --git a/src/opt/sim/simUtils.c b/src/opt/sim/simUtils.c
index 4b89c650..b0660001 100644
--- a/src/opt/sim/simUtils.c
+++ b/src/opt/sim/simUtils.c
@@ -37,7 +37,7 @@ static int bit_count[256] = {
};
////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFITIONS ///
+/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
@@ -232,9 +232,6 @@ void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, bool fType, bool fT
// simulate the internal nodes
if ( Abc_ObjIsNode(pNode) )
{
- if ( Abc_NodeIsConst(pNode) )
- return;
-
if ( fType )
pSimmNode = p->vSim1->pArray[ pNode->Id ];
else
@@ -299,17 +296,18 @@ void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, bool fType, bool fT
SeeAlso []
***********************************************************************/
-void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
+void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset )
{
unsigned * pSimmNode, * pSimmNode1, * pSimmNode2;
int k, fComp1, fComp2;
// simulate the internal nodes
assert( Abc_ObjIsNode(pNode) );
- if ( Abc_NodeIsConst(pNode) )
- return;
pSimmNode = Vec_PtrEntry(vSimInfo, pNode->Id);
pSimmNode1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
pSimmNode2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode));
+ pSimmNode += nOffset;
+ pSimmNode1 += nOffset;
+ pSimmNode2 += nOffset;
fComp1 = Abc_ObjFaninC0(pNode);
fComp2 = Abc_ObjFaninC1(pNode);
if ( fComp1 && fComp2 )
@@ -328,6 +326,36 @@ void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimW
/**Function*************************************************************
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_UtilTransferNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset, int fShift )
+{
+ unsigned * pSimmNode, * pSimmNode1;
+ int k, fComp1;
+ // simulate the internal nodes
+ assert( Abc_ObjIsCo(pNode) );
+ pSimmNode = Vec_PtrEntry(vSimInfo, pNode->Id);
+ pSimmNode1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
+ pSimmNode += nOffset + (fShift > 0)*nSimWords;
+ pSimmNode1 += nOffset;
+ fComp1 = Abc_ObjFaninC0(pNode);
+ if ( fComp1 )
+ for ( k = 0; k < nSimWords; k++ )
+ pSimmNode[k] = ~pSimmNode1[k];
+ else
+ for ( k = 0; k < nSimWords; k++ )
+ pSimmNode[k] = pSimmNode1[k];
+}
+
+/**Function*************************************************************
+
Synopsis [Returns 1 if the simulation infos are equal.]
Description []
@@ -380,10 +408,31 @@ int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords )
return nOnes;
}
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1's in the bitstring.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords )
+{
+ Vec_Int_t * vCounters;
+ unsigned * pSimInfo;
+ int i;
+ vCounters = Vec_IntStart( Vec_PtrSize(vInfo) );
+ Vec_PtrForEachEntry( vInfo, pSimInfo, i )
+ Vec_IntWriteEntry( vCounters, i, Sim_UtilCountOnes(pSimInfo, nSimWords) );
+ return vCounters;
+}
/**Function*************************************************************
- Synopsis [Returns the random pattern.]
+ Synopsis [Returns random patterns.]
Description []
@@ -392,7 +441,7 @@ int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords )
SeeAlso []
***********************************************************************/
-void Sim_UtilGetRandom( unsigned * pPatRand, int nSimWords )
+void Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords )
{
int k;
for ( k = 0; k < nSimWords; k++ )
@@ -401,6 +450,104 @@ void Sim_UtilGetRandom( unsigned * pPatRand, int nSimWords )
/**Function*************************************************************
+ Synopsis [Returns complemented patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_UtilSetCompl( unsigned * pPatRand, int nSimWords )
+{
+ int k;
+ for ( k = 0; k < nSimWords; k++ )
+ pPatRand[k] = ~pPatRand[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns constant patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_UtilSetConst( unsigned * pPatRand, int nSimWords, int fConst1 )
+{
+ int k;
+ for ( k = 0; k < nSimWords; k++ )
+ pPatRand[k] = 0;
+ if ( fConst1 )
+ Sim_UtilSetCompl( pPatRand, nSimWords );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if equal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Sim_UtilInfoIsEqual( unsigned * pPats1, unsigned * pPats2, int nSimWords )
+{
+ int k;
+ for ( k = 0; k < nSimWords; k++ )
+ if ( pPats1[k] != pPats2[k] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if Node1 implies Node2.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Sim_UtilInfoIsImp( unsigned * pPats1, unsigned * pPats2, int nSimWords )
+{
+ int k;
+ for ( k = 0; k < nSimWords; k++ )
+ if ( pPats1[k] & ~pPats2[k] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if Node1 v Node2 is always true.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Sim_UtilInfoIsClause( unsigned * pPats1, unsigned * pPats2, int nSimWords )
+{
+ int k;
+ for ( k = 0; k < nSimWords; k++ )
+ if ( ~pPats1[k] & ~pPats2[k] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
Synopsis [Counts the total number of pairs.]
Description []
@@ -460,6 +607,51 @@ int Sim_UtilCountPairsOne( Extra_BitMat_t * pMat, Vec_Int_t * vSupport )
SeeAlso []
***********************************************************************/
+int Sim_UtilCountPairsOnePrint( Extra_BitMat_t * pMat, Vec_Int_t * vSupport )
+{
+ int i, k, Index1, Index2;
+ Vec_IntForEachEntry( vSupport, i, Index1 )
+ Vec_IntForEachEntryStart( vSupport, k, Index2, Index1+1 )
+ if ( Extra_BitMatrixLookup1( pMat, i, k ) )
+ printf( "(%d,%d) ", i, k );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of entries in the array of matrices.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Sim_UtilCountPairsAllPrint( Sym_Man_t * p )
+{
+ int i, clk;
+clk = clock();
+ for ( i = 0; i < p->nOutputs; i++ )
+ {
+ printf( "Output %2d :", i );
+ Sim_UtilCountPairsOnePrint( Vec_PtrEntry(p->vMatrSymms, i), Vec_VecEntry(p->vSupports, i) );
+ printf( "\n" );
+ }
+p->timeCount += clock() - clk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of entries in the array of matrices.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
void Sim_UtilCountPairsAll( Sym_Man_t * p )
{
int nPairsTotal, nPairsSym, nPairsNonSym, i, clk;