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