1 /**CFile****************************************************************
2 
3   FileName    [abcIf.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Network and node package.]
8 
9   Synopsis    [Interface with the FPGA mapping package.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - November 21, 2006.]
16 
17   Revision    [$Id: abcIf.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "base/abc/abc.h"
22 #include "base/main/main.h"
23 #include "map/if/if.h"
24 #include "bool/kit/kit.h"
25 #include "aig/aig/aig.h"
26 #include "map/mio/mio.h"
27 
28 ABC_NAMESPACE_IMPL_START
29 
30 
31 ////////////////////////////////////////////////////////////////////////
32 ///                        DECLARATIONS                              ///
33 ////////////////////////////////////////////////////////////////////////
34 
35 extern If_Man_t *  Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
36 static Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk );
37 extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover );
38 static Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj );
39 static Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk );
40 
41 extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose );
42 extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose );
43 
44 ////////////////////////////////////////////////////////////////////////
45 ///                     FUNCTION DEFINITIONS                         ///
46 ////////////////////////////////////////////////////////////////////////
47 
48 /**Function*************************************************************
49 
50   Synopsis    [Interface with the FPGA mapping package.]
51 
52   Description []
53 
54   SideEffects []
55 
56   SeeAlso     []
57 
58 ***********************************************************************/
If_ManComputeSwitching(If_Man_t * pIfMan)59 void If_ManComputeSwitching( If_Man_t * pIfMan )
60 {
61     abctime clk = Abc_Clock();
62     Gia_Man_t * pNew;
63     Vec_Int_t * vCopy;
64     If_Obj_t * pIfObj;
65     int i;
66     assert( pIfMan->vSwitching == NULL );
67     // create the new manager
68     pNew = Gia_ManStart( If_ManObjNum(pIfMan) );
69     vCopy = Vec_IntAlloc( If_ManObjNum(pIfMan) );
70     // constant and inputs
71     Vec_IntPush( vCopy, 1 );
72     If_ManForEachCi( pIfMan, pIfObj, i )
73         Vec_IntPush( vCopy, Gia_ManAppendCi(pNew) );
74     // internal nodes
75     If_ManForEachNode( pIfMan, pIfObj, i )
76     {
77         int iLit0 = Abc_LitNotCond( Vec_IntEntry(vCopy, If_ObjFanin0(pIfObj)->Id), If_ObjFaninC0(pIfObj) );
78         int iLit1 = Abc_LitNotCond( Vec_IntEntry(vCopy, If_ObjFanin1(pIfObj)->Id), If_ObjFaninC1(pIfObj) );
79         Vec_IntPush( vCopy, Gia_ManAppendAnd(pNew, iLit0, iLit1) );
80     }
81     // outputs
82     If_ManForEachCo( pIfMan, pIfObj, i )
83     {
84         int iLit0 = Abc_LitNotCond( Vec_IntEntry(vCopy, If_ObjFanin0(pIfObj)->Id), If_ObjFaninC0(pIfObj) );
85         Vec_IntPush( vCopy, Gia_ManAppendCo(pNew, iLit0) );
86     }
87     assert( Vec_IntSize(vCopy) == If_ManObjNum(pIfMan) );
88     Vec_IntFree( vCopy );
89     // compute switching activity
90     pIfMan->vSwitching = Gia_ManComputeSwitchProbs( pNew, 48, 16, 0 );
91     Gia_ManStop( pNew );
92     if ( pIfMan->pPars->fVerbose )
93         Abc_PrintTime( 1, "Computing switching activity", Abc_Clock() - clk );
94 }
95 
96 /**Function*************************************************************
97 
98   Synopsis    [Interface with the FPGA mapping package.]
99 
100   Description []
101 
102   SideEffects []
103 
104   SeeAlso     []
105 
106 ***********************************************************************/
Abc_NtkIf(Abc_Ntk_t * pNtk,If_Par_t * pPars)107 Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
108 {
109     Abc_Ntk_t * pNtkNew, * pTemp;
110     If_Man_t * pIfMan;
111 
112     assert( Abc_NtkIsStrash(pNtk) );
113 
114     // get timing information
115     pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk);
116     pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk);
117 
118     // update timing info to reflect logic level
119     if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib) && pNtk->pManTime )
120     {
121         int c;
122         if ( pNtk->AndGateDelay == 0.0 )
123         {
124             if ( Abc_FrameReadLibGen() )
125                 pNtk->AndGateDelay = Mio_LibraryReadDelayAigNode((Mio_Library_t *)Abc_FrameReadLibGen());
126             if ( pNtk->AndGateDelay == 0.0 )
127             {
128                 pNtk->AndGateDelay = 1.0;
129                 printf( "The AIG-node delay is not set. Assuming unit-delay.\n" );
130             }
131         }
132         for ( c = 0; c < Abc_NtkCiNum(pNtk); c++ )
133             pPars->pTimesArr[c] /= pNtk->AndGateDelay;
134         for ( c = 0; c < Abc_NtkCoNum(pNtk); c++ )
135             pPars->pTimesReq[c] /= pNtk->AndGateDelay;
136     }
137 
138     // set the latch paths
139     if ( pPars->fLatchPaths && pPars->pTimesArr )
140     {
141         int c;
142         for ( c = 0; c < Abc_NtkPiNum(pNtk); c++ )
143             pPars->pTimesArr[c] = -ABC_INFINITY;
144     }
145 
146     // create FPGA mapper
147     pIfMan = Abc_NtkToIf( pNtk, pPars );
148     if ( pIfMan == NULL )
149         return NULL;
150     if ( pPars->fPower )
151         If_ManComputeSwitching( pIfMan );
152 
153     // create DSD manager
154     if ( pPars->fUseDsd )
155     {
156         If_DsdMan_t * p = (If_DsdMan_t *)Abc_FrameReadManDsd();
157         assert( pPars->nLutSize <= If_DsdManVarNum(p) );
158         assert( (pPars->pLutStruct == NULL && If_DsdManLutSize(p) == 0) || (pPars->pLutStruct && pPars->pLutStruct[0] - '0' == If_DsdManLutSize(p)) );
159         pIfMan->pIfDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd();
160         if ( pPars->fDsdBalance )
161             If_DsdManAllocIsops( pIfMan->pIfDsdMan, pPars->nLutSize );
162     }
163 
164     // perform FPGA mapping
165     if ( !If_ManPerformMapping( pIfMan ) )
166     {
167         If_ManStop( pIfMan );
168         return NULL;
169     }
170 
171     // transform the result of mapping into the new network
172     pNtkNew = Abc_NtkFromIf( pIfMan, pNtk );
173     if ( pNtkNew == NULL )
174         return NULL;
175     If_ManStop( pIfMan );
176     if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib )
177     {
178         pNtkNew = Abc_NtkStrash( pTemp = pNtkNew, 0, 0, 0 );
179         Abc_NtkDelete( pTemp );
180     }
181     else if ( pPars->fBidec && pPars->nLutSize <= 8 )
182         Abc_NtkBidecResyn( pNtkNew, 0 );
183 
184     // duplicate EXDC
185     if ( pNtk->pExdc )
186         pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
187     // make sure that everything is okay
188     if ( !Abc_NtkCheck( pNtkNew ) )
189     {
190         printf( "Abc_NtkIf: The network check has failed.\n" );
191         Abc_NtkDelete( pNtkNew );
192         return NULL;
193     }
194     return pNtkNew;
195 }
196 
197 /**Function*************************************************************
198 
199   Synopsis    [Load the network into FPGA manager.]
200 
201   Description []
202 
203   SideEffects []
204 
205   SeeAlso     []
206 
207 ***********************************************************************/
Abc_ObjIfCopy(Abc_Obj_t * pNode)208 static inline If_Obj_t * Abc_ObjIfCopy( Abc_Obj_t * pNode ) { return (If_Obj_t *)pNode->pCopy; }
Abc_NtkToIf(Abc_Ntk_t * pNtk,If_Par_t * pPars)209 If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
210 {
211     ProgressBar * pProgress;
212     If_Man_t * pIfMan;
213     Vec_Ptr_t * vNodes;
214     Abc_Obj_t * pNode, * pPrev;
215     int i;
216 
217     assert( Abc_NtkIsStrash(pNtk) );
218 
219     // start the mapping manager and set its parameters
220     pIfMan = If_ManStart( pPars );
221     pIfMan->pName = Abc_UtilStrsav( Abc_NtkName(pNtk) );
222 
223     // print warning about excessive memory usage
224     if ( 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30) > 1.0 )
225         printf( "Warning: The mapper will allocate %.1f GB for to represent the subject graph with %d AIG nodes.\n",
226             1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30), Abc_NtkObjNum(pNtk) );
227 
228     // create PIs and remember them in the old nodes
229     Abc_NtkCleanCopy( pNtk );
230     Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan );
231     Abc_NtkForEachCi( pNtk, pNode, i )
232     {
233         pNode->pCopy = (Abc_Obj_t *)If_ManCreateCi( pIfMan );
234         // transfer logic level information
235         Abc_ObjIfCopy(pNode)->Level = pNode->Level;
236     }
237 
238     // load the AIG into the mapper
239     pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) );
240     vNodes = Abc_AigDfs( pNtk, 0, 0 );
241     Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
242     {
243         Extra_ProgressBarUpdate( pProgress, i, "Initial" );
244         // add the node to the mapper
245         pNode->pCopy = (Abc_Obj_t *)If_ManCreateAnd( pIfMan,
246             If_NotCond( Abc_ObjIfCopy(Abc_ObjFanin0(pNode)), Abc_ObjFaninC0(pNode) ),
247             If_NotCond( Abc_ObjIfCopy(Abc_ObjFanin1(pNode)), Abc_ObjFaninC1(pNode) ) );
248         // set up the choice node
249         if ( Abc_AigNodeIsChoice( pNode ) )
250         {
251             Abc_Obj_t * pEquiv;
252 //            int Counter = 0;
253             assert( If_ObjId(Abc_ObjIfCopy(pNode)) > If_ObjId(Abc_ObjIfCopy(Abc_ObjEquiv(pNode))) );
254             for ( pPrev = pNode, pEquiv = Abc_ObjEquiv(pPrev); pEquiv; pPrev = pEquiv, pEquiv = Abc_ObjEquiv(pPrev) )
255                 If_ObjSetChoice( Abc_ObjIfCopy(pPrev), Abc_ObjIfCopy(pEquiv) );//, Counter++;
256 //            printf( "%d ", Counter );
257             If_ManCreateChoice( pIfMan, Abc_ObjIfCopy(pNode) );
258         }
259     }
260     Extra_ProgressBarStop( pProgress );
261     Vec_PtrFree( vNodes );
262 
263     // set the primary outputs without copying the phase
264     Abc_NtkForEachCo( pNtk, pNode, i )
265         pNode->pCopy = (Abc_Obj_t *)If_ManCreateCo( pIfMan, If_NotCond( Abc_ObjIfCopy(Abc_ObjFanin0(pNode)), Abc_ObjFaninC0(pNode) ) );
266     return pIfMan;
267 }
268 
269 
270 /**Function*************************************************************
271 
272   Synopsis    [Box mapping procedures.]
273 
274   Description []
275 
276   SideEffects []
277 
278   SeeAlso     []
279 
280 ***********************************************************************/
Abc_MapBoxSetPrevNext(Vec_Ptr_t * vDrivers,Vec_Int_t * vMapIn,Vec_Int_t * vMapOut,int Id)281 static inline void Abc_MapBoxSetPrevNext( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id )
282 {
283     Abc_Obj_t * pNode;
284     pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+2);
285     Vec_IntWriteEntry( vMapIn, Abc_ObjId(Abc_ObjFanin0(pNode)), Id );
286     pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+4);
287     Vec_IntWriteEntry( vMapOut, Abc_ObjId(Abc_ObjFanin0(pNode)), Id );
288 }
Abc_MapBox2Next(Vec_Ptr_t * vDrivers,Vec_Int_t * vMapIn,Vec_Int_t * vMapOut,int Id)289 static inline int Abc_MapBox2Next( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id )
290 {
291     Abc_Obj_t * pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+4);
292     return Vec_IntEntry( vMapIn, Abc_ObjId(Abc_ObjFanin0(pNode)) );
293 }
Abc_MapBox2Prev(Vec_Ptr_t * vDrivers,Vec_Int_t * vMapIn,Vec_Int_t * vMapOut,int Id)294 static inline int Abc_MapBox2Prev( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id )
295 {
296     Abc_Obj_t * pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+2);
297     return Vec_IntEntry( vMapOut, Abc_ObjId(Abc_ObjFanin0(pNode)) );
298 }
299 
300 /**Function*************************************************************
301 
302   Synopsis    [Creates the mapped network.]
303 
304   Description [Assuming the copy field of the mapped nodes are NULL.]
305 
306   SideEffects []
307 
308   SeeAlso     []
309 
310 ***********************************************************************/
Abc_NtkFromIf(If_Man_t * pIfMan,Abc_Ntk_t * pNtk)311 Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk )
312 {
313     ProgressBar * pProgress;
314     Abc_Ntk_t * pNtkNew;
315     Abc_Obj_t * pNode, * pNodeNew;
316     Vec_Int_t * vCover;
317     int i, nDupGates;
318     // create the new network
319     if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
320         pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
321     else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->fUserSesLib || pIfMan->pPars->nGateSize > 0 )
322         pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
323     else
324         pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG );
325     // prepare the mapping manager
326     If_ManCleanNodeCopy( pIfMan );
327     If_ManCleanCutData( pIfMan );
328     // make the mapper point to the new network
329     If_ObjSetCopy( If_ManConst1(pIfMan), Abc_NtkCreateNodeConst1(pNtkNew) );
330     Abc_NtkForEachCi( pNtk, pNode, i )
331         If_ObjSetCopy( If_ManCi(pIfMan, i), pNode->pCopy );
332 
333     // process the nodes in topological order
334     vCover = Vec_IntAlloc( 1 << 16 );
335     pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
336     Abc_NtkForEachCo( pNtk, pNode, i )
337     {
338         Extra_ProgressBarUpdate( pProgress, i, "Final" );
339         pNodeNew = Abc_NodeFromIf_rec( pNtkNew, pIfMan, If_ObjFanin0(If_ManCo(pIfMan, i)), vCover );
340         pNodeNew = Abc_ObjNotCond( pNodeNew, If_ObjFaninC0(If_ManCo(pIfMan, i)) );
341         Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
342     }
343     Extra_ProgressBarStop( pProgress );
344     Vec_IntFree( vCover );
345 
346     // remove the constant node if not used
347     pNodeNew = (Abc_Obj_t *)If_ObjCopy( If_ManConst1(pIfMan) );
348     if ( Abc_ObjFanoutNum(pNodeNew) == 0 && !Abc_ObjIsNone(pNodeNew) )
349         Abc_NtkDeleteObj( pNodeNew );
350     // minimize the node
351     if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
352         Abc_NtkSweep( pNtkNew, 0 );
353     if ( pIfMan->pPars->fUseBdds )
354         Abc_NtkBddReorder( pNtkNew, 0 );
355     // decouple the PO driver nodes to reduce the number of levels
356     nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, !pIfMan->pPars->fUseBuffs );
357     if ( nDupGates && pIfMan->pPars->fVerbose && !Abc_FrameReadFlag("silentmode") )
358     {
359         if ( pIfMan->pPars->fUseBuffs )
360             printf( "Added %d buffers/inverters to decouple the CO drivers.\n", nDupGates );
361         else
362             printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates );
363     }
364     return pNtkNew;
365 }
366 
367 /**Function*************************************************************
368 
369   Synopsis    [Rebuilds GIA from mini AIG.]
370 
371   Description []
372 
373   SideEffects []
374 
375   SeeAlso     []
376 
377 ***********************************************************************/
Abc_NodeBuildFromMiniInt(Hop_Man_t * pMan,Vec_Int_t * vAig,int nLeaves)378 Hop_Obj_t * Abc_NodeBuildFromMiniInt( Hop_Man_t * pMan, Vec_Int_t * vAig, int nLeaves )
379 {
380     assert( Vec_IntSize(vAig) > 0 );
381     assert( Vec_IntEntryLast(vAig) < 2 );
382     if ( Vec_IntSize(vAig) == 1 ) // const
383     {
384         assert( nLeaves == 0 );
385         return Hop_NotCond( Hop_ManConst0(pMan), Vec_IntEntry(vAig, 0) );
386     }
387     if ( Vec_IntSize(vAig) == 2 ) // variable
388     {
389         assert( Vec_IntEntry(vAig, 0) == 0 );
390         assert( nLeaves == 1 );
391         return Hop_NotCond( Hop_IthVar(pMan, 0), Vec_IntEntry(vAig, 1) );
392     }
393     else
394     {
395         int i, iVar0, iVar1, iLit0, iLit1;
396         Hop_Obj_t * piLit0, * piLit1, * piLit = NULL;
397         assert( Vec_IntSize(vAig) & 1 );
398         Vec_IntForEachEntryDouble( vAig, iLit0, iLit1, i )
399         {
400             iVar0 = Abc_Lit2Var( iLit0 );
401             iVar1 = Abc_Lit2Var( iLit1 );
402             piLit0 = Hop_NotCond( iVar0 < nLeaves ? Hop_IthVar(pMan, iVar0) : (Hop_Obj_t *)Vec_PtrEntry((Vec_Ptr_t *)vAig, iVar0 - nLeaves), Abc_LitIsCompl(iLit0) );
403             piLit1 = Hop_NotCond( iVar1 < nLeaves ? Hop_IthVar(pMan, iVar1) : (Hop_Obj_t *)Vec_PtrEntry((Vec_Ptr_t *)vAig, iVar1 - nLeaves), Abc_LitIsCompl(iLit1) );
404             piLit  = Hop_And( pMan, piLit0, piLit1 );
405             assert( (i & 1) == 0 );
406             Vec_PtrWriteEntry( (Vec_Ptr_t *)vAig, Abc_Lit2Var(i), piLit );  // overwriting entries
407         }
408         assert( i == Vec_IntSize(vAig) - 1 );
409         piLit = Hop_NotCond( piLit, Vec_IntEntry(vAig, i) );
410         Vec_IntClear( vAig ); // useless
411         return piLit;
412     }
413 }
Abc_NodeBuildFromMini(Hop_Man_t * pMan,If_Man_t * p,If_Cut_t * pCut,int fUseDsd)414 Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pCut, int fUseDsd )
415 {
416     int Delay;
417     if ( fUseDsd )
418         Delay = If_CutDsdBalanceEval( p, pCut, p->vArray );
419     else
420         Delay = If_CutSopBalanceEval( p, pCut, p->vArray );
421     assert( Delay >= 0 );
422     return Abc_NodeBuildFromMiniInt( pMan, p->vArray, If_CutLeaveNum(pCut) );
423 }
424 
425 /**Function*************************************************************
426 
427   Synopsis    [Derive one node after FPGA mapping.]
428 
429   Description []
430 
431   SideEffects []
432 
433   SeeAlso     []
434 
435 ***********************************************************************/
Abc_NodeFromIf_rec(Abc_Ntk_t * pNtkNew,If_Man_t * pIfMan,If_Obj_t * pIfObj,Vec_Int_t * vCover)436 Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover )
437 {
438     Abc_Obj_t * pNodeNew;
439     If_Cut_t * pCutBest;
440     If_Obj_t * pIfLeaf;
441     int i;
442     // return if the result if known
443     pNodeNew = (Abc_Obj_t *)If_ObjCopy( pIfObj );
444     if ( pNodeNew )
445         return pNodeNew;
446     assert( pIfObj->Type == IF_AND );
447     // get the parameters of the best cut
448     pCutBest = If_ObjCutBest( pIfObj );
449     if ( pIfMan->pPars->fUserSesLib )
450     {
451         // create the subgraph composed of Abc_Obj_t nodes based on the given cut
452         Abc_Obj_t * pFanins[IF_MAX_FUNC_LUTSIZE];
453         If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i )
454             pFanins[i] = Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover);
455         pNodeNew = Abc_ExactBuildNode( If_CutTruthW(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), If_CutArrTimeProfile(pIfMan, pCutBest), pFanins, pNtkNew );
456         If_ObjSetCopy( pIfObj, pNodeNew );
457         return pNodeNew;
458     }
459     // create a new node
460     pNodeNew = Abc_NtkCreateNode( pNtkNew );
461 //    if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays )
462     if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm &&
463          !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize )
464         If_CutRotatePins( pIfMan, pCutBest );
465     if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
466     {
467         If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i )
468             Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) );
469     }
470     else
471     {
472         If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i )
473             Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) );
474     }
475     // set the level of the new node
476     pNodeNew->Level = Abc_ObjLevelNew( pNodeNew );
477     // derive the function of this node
478     if ( pIfMan->pPars->fTruth )
479     {
480         if ( pIfMan->pPars->fUseBdds )
481         {
482             // transform truth table into the BDD
483 #ifdef ABC_USE_CUDD
484             pNodeNew->pData = Kit_TruthToBdd( (DdManager *)pNtkNew->pManFunc, If_CutTruth(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), 0 );  Cudd_Ref((DdNode *)pNodeNew->pData);
485 #endif
486         }
487         else if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
488         {
489             // transform truth table into the BDD
490 #ifdef ABC_USE_CUDD
491             pNodeNew->pData = Kit_TruthToBdd( (DdManager *)pNtkNew->pManFunc, If_CutTruth(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), 1 );  Cudd_Ref((DdNode *)pNodeNew->pData);
492 #endif
493         }
494         else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->nGateSize > 0 )
495         {
496             // transform truth table into the SOP
497             int RetValue = Kit_TruthIsop( If_CutTruth(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), vCover, 1 );
498             assert( RetValue == 0 || RetValue == 1 );
499             // check the case of constant cover
500             if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) )
501             {
502                 assert( RetValue == 0 );
503                 pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), NULL );
504                 pNodeNew = (Vec_IntSize(vCover) == 0) ? Abc_NtkCreateNodeConst0(pNtkNew) : Abc_NtkCreateNodeConst1(pNtkNew);
505             }
506             else
507             {
508                 // derive the AIG for that tree
509                 pNodeNew->pData = Abc_SopCreateFromIsop( (Mem_Flex_t *)pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), vCover );
510                 if ( RetValue )
511                     Abc_SopComplement( (char *)pNodeNew->pData );
512             }
513         }
514         else if ( pIfMan->pPars->fDelayOpt )
515             pNodeNew->pData = Abc_NodeBuildFromMini( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, 0 );
516         else if ( pIfMan->pPars->fDsdBalance )
517             pNodeNew->pData = Abc_NodeBuildFromMini( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, 1 );
518         else if ( pIfMan->pPars->fUserRecLib )
519         {
520             extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj );
521             pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj );
522         }
523         else
524         {
525             extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
526             word * pTruth = If_CutTruthW(pIfMan, pCutBest);
527             if ( pIfMan->pPars->fUseTtPerm )
528                 for ( i = 0; i < (int)pCutBest->nLeaves; i++ )
529                     if ( If_CutLeafBit(pCutBest, i) )
530                         Abc_TtFlip( pTruth, Abc_TtWordNum(pCutBest->nLeaves), i );
531             pNodeNew->pData = Kit_TruthToHop( (Hop_Man_t *)pNtkNew->pManFunc, (unsigned *)pTruth, If_CutLeaveNum(pCutBest), vCover );
532 //            if ( pIfMan->pPars->fUseBat )
533 //                Bat_ManFuncPrintCell( *pTruth );
534         }
535         // complement the node if the cut was complemented
536         if ( pCutBest->fCompl && !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDsdBalance )
537             Abc_NodeComplement( pNodeNew );
538     }
539     else
540     {
541         pNodeNew->pData = Abc_NodeIfToHop( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pIfObj );
542     }
543     If_ObjSetCopy( pIfObj, pNodeNew );
544     return pNodeNew;
545 }
546 
547 /**Function*************************************************************
548 
549   Synopsis    [Recursively derives the truth table for the cut.]
550 
551   Description []
552 
553   SideEffects []
554 
555   SeeAlso     []
556 
557 ***********************************************************************/
Abc_NodeIfToHop_rec(Hop_Man_t * pHopMan,If_Man_t * pIfMan,If_Obj_t * pIfObj,Vec_Ptr_t * vVisited)558 Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited )
559 {
560     If_Cut_t * pCut;
561     Hop_Obj_t * gFunc, * gFunc0, * gFunc1;
562     // get the best cut
563     pCut = If_ObjCutBest(pIfObj);
564     // if the cut is visited, return the result
565     if ( If_CutData(pCut) )
566         return (Hop_Obj_t *)If_CutData(pCut);
567     // compute the functions of the children
568     gFunc0 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin0, vVisited );
569     gFunc1 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin1, vVisited );
570     // get the function of the cut
571     gFunc  = Hop_And( pHopMan, Hop_NotCond(gFunc0, pIfObj->fCompl0), Hop_NotCond(gFunc1, pIfObj->fCompl1) );
572     assert( If_CutData(pCut) == NULL );
573     If_CutSetData( pCut, gFunc );
574     // add this cut to the visited list
575     Vec_PtrPush( vVisited, pCut );
576     return gFunc;
577 }
578 
579 
580 /**Function*************************************************************
581 
582   Synopsis    [Recursively derives the truth table for the cut.]
583 
584   Description []
585 
586   SideEffects []
587 
588   SeeAlso     []
589 
590 ***********************************************************************/
Abc_NodeIfToHop2_rec(Hop_Man_t * pHopMan,If_Man_t * pIfMan,If_Obj_t * pIfObj,Vec_Ptr_t * vVisited)591 Hop_Obj_t * Abc_NodeIfToHop2_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited )
592 {
593     If_Cut_t * pCut;
594     If_Obj_t * pTemp;
595     Hop_Obj_t * gFunc, * gFunc0, * gFunc1;
596     // get the best cut
597     pCut = If_ObjCutBest(pIfObj);
598     // if the cut is visited, return the result
599     if ( If_CutData(pCut) )
600         return (Hop_Obj_t *)If_CutData(pCut);
601     // mark the node as visited
602     Vec_PtrPush( vVisited, pCut );
603     // insert the worst case
604     If_CutSetData( pCut, (void *)1 );
605     // skip in case of primary input
606     if ( If_ObjIsCi(pIfObj) )
607         return (Hop_Obj_t *)If_CutData(pCut);
608     // compute the functions of the children
609     for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv )
610     {
611         gFunc0 = Abc_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin0, vVisited );
612         if ( gFunc0 == (void *)1 )
613             continue;
614         gFunc1 = Abc_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin1, vVisited );
615         if ( gFunc1 == (void *)1 )
616             continue;
617         // both branches are solved
618         gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pTemp->fCompl0), Hop_NotCond(gFunc1, pTemp->fCompl1) );
619         if ( pTemp->fPhase != pIfObj->fPhase )
620             gFunc = Hop_Not(gFunc);
621         If_CutSetData( pCut, gFunc );
622         break;
623     }
624     return (Hop_Obj_t *)If_CutData(pCut);
625 }
626 
627 /**Function*************************************************************
628 
629   Synopsis    [Derives the truth table for one cut.]
630 
631   Description []
632 
633   SideEffects []
634 
635   SeeAlso     []
636 
637 ***********************************************************************/
Abc_NodeIfToHop(Hop_Man_t * pHopMan,If_Man_t * pIfMan,If_Obj_t * pIfObj)638 Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj )
639 {
640     If_Cut_t * pCut;
641     Hop_Obj_t * gFunc;
642     If_Obj_t * pLeaf;
643     int i;
644     // get the best cut
645     pCut = If_ObjCutBest(pIfObj);
646     assert( pCut->nLeaves > 1 );
647     // set the leaf variables
648     If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
649         If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) );
650     // recursively compute the function while collecting visited cuts
651     Vec_PtrClear( pIfMan->vTemp );
652     gFunc = Abc_NodeIfToHop2_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp );
653     if ( gFunc == (void *)1 )
654     {
655         printf( "Abc_NodeIfToHop(): Computing local AIG has failed.\n" );
656         return NULL;
657     }
658     // clean the cuts
659     If_CutForEachLeaf( pIfMan, pCut, pLeaf, i )
660         If_CutSetData( If_ObjCutBest(pLeaf), NULL );
661     Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i )
662         If_CutSetData( pCut, NULL );
663     return gFunc;
664 }
665 
666 
667 /**Function*************************************************************
668 
669   Synopsis    [Comparison for two nodes with the flow.]
670 
671   Description []
672 
673   SideEffects []
674 
675   SeeAlso     []
676 
677 ***********************************************************************/
Abc_ObjCompareFlow(Abc_Obj_t ** ppNode0,Abc_Obj_t ** ppNode1)678 int Abc_ObjCompareFlow( Abc_Obj_t ** ppNode0, Abc_Obj_t ** ppNode1 )
679 {
680     float Flow0 = Abc_Int2Float((int)(ABC_PTRINT_T)(*ppNode0)->pCopy);
681     float Flow1 = Abc_Int2Float((int)(ABC_PTRINT_T)(*ppNode1)->pCopy);
682     if ( Flow0 > Flow1 )
683         return -1;
684     if ( Flow0 < Flow1 )
685         return 1;
686     return 0;
687 }
688 
689 /**Function*************************************************************
690 
691   Synopsis    [Orders AIG nodes so that nodes from larger cones go first.]
692 
693   Description []
694 
695   SideEffects []
696 
697   SeeAlso     []
698 
699 ***********************************************************************/
Abc_NtkFindGoodOrder_rec(Abc_Obj_t * pNode,Vec_Ptr_t * vNodes)700 void Abc_NtkFindGoodOrder_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
701 {
702     if ( !Abc_ObjIsNode(pNode) )
703         return;
704     assert( Abc_ObjIsNode( pNode ) );
705     // if this node is already visited, skip
706     if ( Abc_NodeIsTravIdCurrent( pNode ) )
707         return;
708     // mark the node as visited
709     Abc_NodeSetTravIdCurrent( pNode );
710     // visit the transitive fanin of the node
711     Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes );
712     Abc_NtkFindGoodOrder_rec( Abc_ObjFanin1(pNode), vNodes );
713     // add the node after the fanins have been added
714     Vec_PtrPush( vNodes, pNode );
715 }
716 
717 /**Function*************************************************************
718 
719   Synopsis    [Orders AIG nodes so that nodes from larger cones go first.]
720 
721   Description []
722 
723   SideEffects []
724 
725   SeeAlso     []
726 
727 ***********************************************************************/
Abc_NtkFindGoodOrder(Abc_Ntk_t * pNtk)728 Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk )
729 {
730     Vec_Ptr_t * vNodes, * vCos;
731     Abc_Obj_t * pNode, * pFanin0, * pFanin1;
732     float Flow0, Flow1;
733     int i;
734 
735     // initialize the flow
736     Abc_AigConst1(pNtk)->pCopy = NULL;
737     Abc_NtkForEachCi( pNtk, pNode, i )
738         pNode->pCopy = NULL;
739     // compute the flow
740     Abc_AigForEachAnd( pNtk, pNode, i )
741     {
742         pFanin0 = Abc_ObjFanin0(pNode);
743         pFanin1 = Abc_ObjFanin1(pNode);
744         Flow0 = Abc_Int2Float((int)(ABC_PTRINT_T)pFanin0->pCopy)/Abc_ObjFanoutNum(pFanin0);
745         Flow1 = Abc_Int2Float((int)(ABC_PTRINT_T)pFanin1->pCopy)/Abc_ObjFanoutNum(pFanin1);
746         pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Abc_Float2Int(Flow0 + Flow1+(float)1.0);
747     }
748     // find the flow of the COs
749     vCos = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
750     Abc_NtkForEachCo( pNtk, pNode, i )
751     {
752         pNode->pCopy = Abc_ObjFanin0(pNode)->pCopy;
753 //        pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int((float)Abc_ObjFanin0(pNode)->Level);
754         Vec_PtrPush( vCos, pNode );
755     }
756 
757     // sort nodes in the increasing order of the flow
758     qsort( (Abc_Obj_t **)Vec_PtrArray(vCos), (size_t)Abc_NtkCoNum(pNtk),
759         sizeof(Abc_Obj_t *), (int (*)(const void *, const void *))Abc_ObjCompareFlow );
760     // verify sorting
761     pFanin0 = (Abc_Obj_t *)Vec_PtrEntry(vCos, 0);
762     pFanin1 = (Abc_Obj_t *)Vec_PtrEntryLast(vCos);
763     assert( Abc_Int2Float((int)(ABC_PTRINT_T)pFanin0->pCopy) >= Abc_Int2Float((int)(ABC_PTRINT_T)pFanin1->pCopy) );
764 
765     // collect the nodes in the topological order from the new array
766     Abc_NtkIncrementTravId( pNtk );
767     vNodes = Vec_PtrAlloc( 100 );
768     Vec_PtrForEachEntry( Abc_Obj_t *, vCos, pNode, i )
769         Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes );
770     Vec_PtrFree( vCos );
771     return vNodes;
772 }
773 
774 
775 /**Function*************************************************************
776 
777   Synopsis    [Sets PO drivers.]
778 
779   Description []
780 
781   SideEffects []
782 
783   SeeAlso     []
784 
785 ***********************************************************************/
Abc_NtkMarkMux(Abc_Obj_t * pDriver,Abc_Obj_t ** ppNode1,Abc_Obj_t ** ppNode2)786 void Abc_NtkMarkMux( Abc_Obj_t * pDriver, Abc_Obj_t ** ppNode1, Abc_Obj_t ** ppNode2 )
787 {
788     Abc_Obj_t * pNodeC, * pNodeT, * pNodeE;
789     If_Obj_t * pIfObj;
790 
791     *ppNode1 = NULL;
792     *ppNode2 = NULL;
793     if ( pDriver == NULL )
794         return;
795     if ( !Abc_NodeIsMuxType(pDriver) )
796         return;
797 
798     pNodeC = Abc_NodeRecognizeMux( pDriver, &pNodeT, &pNodeE );
799 
800     pIfObj = If_Regular( (If_Obj_t *)Abc_ObjFanin0(pDriver)->pCopy );
801     if ( If_ObjIsAnd(pIfObj) )
802         pIfObj->fSkipCut = 1;
803     pIfObj = If_Regular( (If_Obj_t *)Abc_ObjFanin1(pDriver)->pCopy );
804     if ( If_ObjIsAnd(pIfObj) )
805         pIfObj->fSkipCut = 1;
806 
807     pIfObj = If_Regular( (If_Obj_t *)Abc_ObjRegular(pNodeC)->pCopy );
808     if ( If_ObjIsAnd(pIfObj) )
809         pIfObj->fSkipCut = 1;
810 
811 /*
812     pIfObj = If_Regular( (If_Obj_t *)Abc_ObjRegular(pNodeT)->pCopy );
813     if ( If_ObjIsAnd(pIfObj) )
814         pIfObj->fSkipCut = 1;
815     pIfObj = If_Regular( (If_Obj_t *)Abc_ObjRegular(pNodeE)->pCopy );
816     if ( If_ObjIsAnd(pIfObj) )
817         pIfObj->fSkipCut = 1;
818 */
819     *ppNode1 = Abc_ObjRegular(pNodeC);
820     *ppNode2 = Abc_ObjRegular(pNodeT);
821 }
822 
823 
824 ////////////////////////////////////////////////////////////////////////
825 ///                       END OF FILE                                ///
826 ////////////////////////////////////////////////////////////////////////
827 
828 
829 ABC_NAMESPACE_IMPL_END
830 
831