PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/src/opt/lpk/lpkCut.c

https://bitbucket.org/alanmi/abc/
C | 689 lines | 398 code | 47 blank | 244 comment | 104 complexity | 64c8815244cfff11e903cb984cf41d71 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /**CFile****************************************************************
  2. FileName [lpkCut.c]
  3. SystemName [ABC: Logic synthesis and verification system.]
  4. PackageName [Fast Boolean matching for LUT structures.]
  5. Synopsis []
  6. Author [Alan Mishchenko]
  7. Affiliation [UC Berkeley]
  8. Date [Ver. 1.0. Started - April 28, 2007.]
  9. Revision [$Id: lpkCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
  10. ***********************************************************************/
  11. #include "lpkInt.h"
  12. #include "bool/kit/cloud.h"
  13. ABC_NAMESPACE_IMPL_START
  14. ////////////////////////////////////////////////////////////////////////
  15. /// DECLARATIONS ///
  16. ////////////////////////////////////////////////////////////////////////
  17. ////////////////////////////////////////////////////////////////////////
  18. /// FUNCTION DEFINITIONS ///
  19. ////////////////////////////////////////////////////////////////////////
  20. /**Function*************************************************************
  21. Synopsis [Computes the truth table of one cut.]
  22. Description []
  23. SideEffects []
  24. SeeAlso []
  25. ***********************************************************************/
  26. CloudNode * Lpk_CutTruthBdd_rec( CloudManager * dd, Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars )
  27. {
  28. CloudNode * pTruth, * pTruth0, * pTruth1;
  29. assert( !Hop_IsComplement(pObj) );
  30. if ( pObj->pData )
  31. {
  32. assert( ((unsigned)(ABC_PTRUINT_T)pObj->pData) & 0xffff0000 );
  33. return (CloudNode *)pObj->pData;
  34. }
  35. // get the plan for a new truth table
  36. if ( Hop_ObjIsConst1(pObj) )
  37. pTruth = dd->one;
  38. else
  39. {
  40. assert( Hop_ObjIsAnd(pObj) );
  41. // compute the truth tables of the fanins
  42. pTruth0 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin0(pObj), nVars );
  43. pTruth1 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin1(pObj), nVars );
  44. pTruth0 = Cloud_NotCond( pTruth0, Hop_ObjFaninC0(pObj) );
  45. pTruth1 = Cloud_NotCond( pTruth1, Hop_ObjFaninC1(pObj) );
  46. // creat the truth table of the node
  47. pTruth = Cloud_bddAnd( dd, pTruth0, pTruth1 );
  48. }
  49. pObj->pData = pTruth;
  50. return pTruth;
  51. }
  52. /**Function*************************************************************
  53. Synopsis [Verifies that the factoring is correct.]
  54. Description []
  55. SideEffects []
  56. SeeAlso []
  57. ***********************************************************************/
  58. CloudNode * Lpk_CutTruthBdd( Lpk_Man_t * p, Lpk_Cut_t * pCut )
  59. {
  60. CloudManager * dd = p->pDsdMan->dd;
  61. Hop_Man_t * pManHop = (Hop_Man_t *)p->pNtk->pManFunc;
  62. Hop_Obj_t * pObjHop;
  63. Abc_Obj_t * pObj, * pFanin;
  64. CloudNode * pTruth = NULL; // Suppress "might be used uninitialized"
  65. int i, k;
  66. // return NULL;
  67. // Lpk_NodePrintCut( p, pCut );
  68. // initialize the leaves
  69. Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
  70. pObj->pCopy = (Abc_Obj_t *)dd->vars[pCut->nLeaves-1-i];
  71. // construct truth table in the topological order
  72. Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i )
  73. {
  74. // get the local AIG
  75. pObjHop = Hop_Regular((Hop_Obj_t *)pObj->pData);
  76. // clean the data field of the nodes in the AIG subgraph
  77. Hop_ObjCleanData_rec( pObjHop );
  78. // set the initial truth tables at the fanins
  79. Abc_ObjForEachFanin( pObj, pFanin, k )
  80. {
  81. assert( ((unsigned)(ABC_PTRUINT_T)pFanin->pCopy) & 0xffff0000 );
  82. Hop_ManPi( pManHop, k )->pData = pFanin->pCopy;
  83. }
  84. // compute the truth table of internal nodes
  85. pTruth = Lpk_CutTruthBdd_rec( dd, pManHop, pObjHop, pCut->nLeaves );
  86. if ( Hop_IsComplement((Hop_Obj_t *)pObj->pData) )
  87. pTruth = Cloud_Not(pTruth);
  88. // set the truth table at the node
  89. pObj->pCopy = (Abc_Obj_t *)pTruth;
  90. }
  91. // Cloud_bddPrint( dd, pTruth );
  92. // printf( "Bdd size = %d. Total nodes = %d.\n", Cloud_DagSize( dd, pTruth ), dd->nNodesCur-dd->nVars-1 );
  93. return pTruth;
  94. }
  95. /**Function*************************************************************
  96. Synopsis [Computes the truth table of one cut.]
  97. Description []
  98. SideEffects []
  99. SeeAlso []
  100. ***********************************************************************/
  101. unsigned * Lpk_CutTruth_rec( Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars, Vec_Ptr_t * vTtNodes, int * piCount )
  102. {
  103. unsigned * pTruth, * pTruth0, * pTruth1;
  104. assert( !Hop_IsComplement(pObj) );
  105. if ( pObj->pData )
  106. {
  107. assert( ((unsigned)(ABC_PTRUINT_T)pObj->pData) & 0xffff0000 );
  108. return (unsigned *)pObj->pData;
  109. }
  110. // get the plan for a new truth table
  111. pTruth = (unsigned *)Vec_PtrEntry( vTtNodes, (*piCount)++ );
  112. if ( Hop_ObjIsConst1(pObj) )
  113. Kit_TruthFill( pTruth, nVars );
  114. else
  115. {
  116. assert( Hop_ObjIsAnd(pObj) );
  117. // compute the truth tables of the fanins
  118. pTruth0 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin0(pObj), nVars, vTtNodes, piCount );
  119. pTruth1 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin1(pObj), nVars, vTtNodes, piCount );
  120. // creat the truth table of the node
  121. Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Hop_ObjFaninC0(pObj), Hop_ObjFaninC1(pObj) );
  122. }
  123. pObj->pData = pTruth;
  124. return pTruth;
  125. }
  126. /**Function*************************************************************
  127. Synopsis [Computes the truth able of one cut.]
  128. Description []
  129. SideEffects []
  130. SeeAlso []
  131. ***********************************************************************/
  132. unsigned * Lpk_CutTruth( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fInv )
  133. {
  134. Hop_Man_t * pManHop = (Hop_Man_t *)p->pNtk->pManFunc;
  135. Hop_Obj_t * pObjHop;
  136. Abc_Obj_t * pObj = NULL; // Suppress "might be used uninitialized"
  137. Abc_Obj_t * pFanin;
  138. unsigned * pTruth = NULL; // Suppress "might be used uninitialized"
  139. int i, k, iCount = 0;
  140. // Lpk_NodePrintCut( p, pCut );
  141. assert( pCut->nNodes > 0 );
  142. // initialize the leaves
  143. Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
  144. pObj->pCopy = (Abc_Obj_t *)Vec_PtrEntry( p->vTtElems, fInv? pCut->nLeaves-1-i : i );
  145. // construct truth table in the topological order
  146. Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i )
  147. {
  148. // get the local AIG
  149. pObjHop = Hop_Regular((Hop_Obj_t *)pObj->pData);
  150. // clean the data field of the nodes in the AIG subgraph
  151. Hop_ObjCleanData_rec( pObjHop );
  152. // set the initial truth tables at the fanins
  153. Abc_ObjForEachFanin( pObj, pFanin, k )
  154. {
  155. assert( ((unsigned)(ABC_PTRUINT_T)pFanin->pCopy) & 0xffff0000 );
  156. Hop_ManPi( pManHop, k )->pData = pFanin->pCopy;
  157. }
  158. // compute the truth table of internal nodes
  159. pTruth = Lpk_CutTruth_rec( pManHop, pObjHop, pCut->nLeaves, p->vTtNodes, &iCount );
  160. if ( Hop_IsComplement((Hop_Obj_t *)pObj->pData) )
  161. Kit_TruthNot( pTruth, pTruth, pCut->nLeaves );
  162. // set the truth table at the node
  163. pObj->pCopy = (Abc_Obj_t *)pTruth;
  164. }
  165. // make sure direct truth table is stored elsewhere (assuming the first call for direct truth!!!)
  166. if ( fInv == 0 )
  167. {
  168. pTruth = (unsigned *)Vec_PtrEntry( p->vTtNodes, iCount++ );
  169. Kit_TruthCopy( pTruth, (unsigned *)(ABC_PTRUINT_T)pObj->pCopy, pCut->nLeaves );
  170. }
  171. assert( iCount <= Vec_PtrSize(p->vTtNodes) );
  172. return pTruth;
  173. }
  174. /**Function*************************************************************
  175. Synopsis [Returns 1 if at least one entry has changed.]
  176. Description []
  177. SideEffects []
  178. SeeAlso []
  179. ***********************************************************************/
  180. void Lpk_NodeRecordImpact( Lpk_Man_t * p )
  181. {
  182. Lpk_Cut_t * pCut;
  183. Vec_Ptr_t * vNodes = Vec_VecEntry( p->vVisited, p->pObj->Id );
  184. Abc_Obj_t * pNode;
  185. int i, k;
  186. // collect the nodes that impact the given node
  187. Vec_PtrClear( vNodes );
  188. for ( i = 0; i < p->nCuts; i++ )
  189. {
  190. pCut = p->pCuts + i;
  191. for ( k = 0; k < (int)pCut->nLeaves; k++ )
  192. {
  193. pNode = Abc_NtkObj( p->pNtk, pCut->pLeaves[k] );
  194. if ( pNode->fMarkC )
  195. continue;
  196. pNode->fMarkC = 1;
  197. Vec_PtrPush( vNodes, (void *)(ABC_PTRUINT_T)pNode->Id );
  198. Vec_PtrPush( vNodes, (void *)(ABC_PTRUINT_T)Abc_ObjFanoutNum(pNode) );
  199. }
  200. }
  201. // clear the marks
  202. Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
  203. {
  204. pNode = Abc_NtkObj( p->pNtk, (int)(ABC_PTRUINT_T)pNode );
  205. pNode->fMarkC = 0;
  206. i++;
  207. }
  208. //printf( "%d ", Vec_PtrSize(vNodes) );
  209. }
  210. /**Function*************************************************************
  211. Synopsis [Returns 1 if the cut has structural DSD.]
  212. Description []
  213. SideEffects []
  214. SeeAlso []
  215. ***********************************************************************/
  216. int Lpk_NodeCutsCheckDsd( Lpk_Man_t * p, Lpk_Cut_t * pCut )
  217. {
  218. Abc_Obj_t * pObj, * pFanin;
  219. int i, k, nCands, fLeavesOnly, RetValue;
  220. assert( pCut->nLeaves > 0 );
  221. // clear ref counters
  222. memset( p->pRefs, 0, sizeof(int) * pCut->nLeaves );
  223. // mark cut leaves
  224. Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
  225. {
  226. assert( pObj->fMarkA == 0 );
  227. pObj->fMarkA = 1;
  228. pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)i;
  229. }
  230. // ref leaves pointed from the internal nodes
  231. nCands = 0;
  232. Lpk_CutForEachNode( p->pNtk, pCut, pObj, i )
  233. {
  234. fLeavesOnly = 1;
  235. Abc_ObjForEachFanin( pObj, pFanin, k )
  236. if ( pFanin->fMarkA )
  237. p->pRefs[(int)(ABC_PTRUINT_T)pFanin->pCopy]++;
  238. else
  239. fLeavesOnly = 0;
  240. if ( fLeavesOnly )
  241. p->pCands[nCands++] = pObj->Id;
  242. }
  243. // look at the nodes that only point to the leaves
  244. RetValue = 0;
  245. for ( i = 0; i < nCands; i++ )
  246. {
  247. pObj = Abc_NtkObj( p->pNtk, p->pCands[i] );
  248. Abc_ObjForEachFanin( pObj, pFanin, k )
  249. {
  250. assert( pFanin->fMarkA == 1 );
  251. if ( p->pRefs[(int)(ABC_PTRUINT_T)pFanin->pCopy] > 1 )
  252. break;
  253. }
  254. if ( k == Abc_ObjFaninNum(pObj) )
  255. {
  256. RetValue = 1;
  257. break;
  258. }
  259. }
  260. // unmark cut leaves
  261. Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
  262. pObj->fMarkA = 0;
  263. return RetValue;
  264. }
  265. /**Function*************************************************************
  266. Synopsis [Returns 1 if pDom is contained in pCut.]
  267. Description []
  268. SideEffects []
  269. SeeAlso []
  270. ***********************************************************************/
  271. static inline int Lpk_NodeCutsOneDominance( Lpk_Cut_t * pDom, Lpk_Cut_t * pCut )
  272. {
  273. int i, k;
  274. for ( i = 0; i < (int)pDom->nLeaves; i++ )
  275. {
  276. for ( k = 0; k < (int)pCut->nLeaves; k++ )
  277. if ( pDom->pLeaves[i] == pCut->pLeaves[k] )
  278. break;
  279. if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut
  280. return 0;
  281. }
  282. // every node in pDom is contained in pCut
  283. return 1;
  284. }
  285. /**Function*************************************************************
  286. Synopsis [Check if the cut exists.]
  287. Description [Returns 1 if the cut exists.]
  288. SideEffects []
  289. SeeAlso []
  290. ***********************************************************************/
  291. int Lpk_NodeCutsOneFilter( Lpk_Cut_t * pCuts, int nCuts, Lpk_Cut_t * pCutNew )
  292. {
  293. Lpk_Cut_t * pCut;
  294. int i, k;
  295. assert( pCutNew->uSign[0] || pCutNew->uSign[1] );
  296. // try to find the cut
  297. for ( i = 0; i < nCuts; i++ )
  298. {
  299. pCut = pCuts + i;
  300. if ( pCut->nLeaves == 0 )
  301. continue;
  302. if ( pCut->nLeaves == pCutNew->nLeaves )
  303. {
  304. if ( pCut->uSign[0] == pCutNew->uSign[0] && pCut->uSign[1] == pCutNew->uSign[1] )
  305. {
  306. for ( k = 0; k < (int)pCutNew->nLeaves; k++ )
  307. if ( pCut->pLeaves[k] != pCutNew->pLeaves[k] )
  308. break;
  309. if ( k == (int)pCutNew->nLeaves )
  310. return 1;
  311. }
  312. continue;
  313. }
  314. if ( pCut->nLeaves < pCutNew->nLeaves )
  315. {
  316. // skip the non-contained cuts
  317. if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCut->uSign[0] )
  318. continue;
  319. if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCut->uSign[1] )
  320. continue;
  321. // check containment seriously
  322. if ( Lpk_NodeCutsOneDominance( pCut, pCutNew ) )
  323. return 1;
  324. continue;
  325. }
  326. // check potential containment of other cut
  327. // skip the non-contained cuts
  328. if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCutNew->uSign[0] )
  329. continue;
  330. if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCutNew->uSign[1] )
  331. continue;
  332. // check containment seriously
  333. if ( Lpk_NodeCutsOneDominance( pCutNew, pCut ) )
  334. pCut->nLeaves = 0; // removed
  335. }
  336. return 0;
  337. }
  338. /**Function*************************************************************
  339. Synopsis [Prints the given cut.]
  340. Description []
  341. SideEffects []
  342. SeeAlso []
  343. ***********************************************************************/
  344. void Lpk_NodePrintCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fLeavesOnly )
  345. {
  346. Abc_Obj_t * pObj;
  347. int i;
  348. if ( !fLeavesOnly )
  349. printf( "LEAVES:\n" );
  350. Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i )
  351. printf( "%d,", pObj->Id );
  352. if ( !fLeavesOnly )
  353. {
  354. printf( "\nNODES:\n" );
  355. Lpk_CutForEachNode( p->pNtk, pCut, pObj, i )
  356. {
  357. printf( "%d,", pObj->Id );
  358. assert( Abc_ObjIsNode(pObj) );
  359. }
  360. printf( "\n" );
  361. }
  362. }
  363. /**Function*************************************************************
  364. Synopsis [Set the cut signature.]
  365. Description []
  366. SideEffects []
  367. SeeAlso []
  368. ***********************************************************************/
  369. void Lpk_NodeCutSignature( Lpk_Cut_t * pCut )
  370. {
  371. unsigned i;
  372. pCut->uSign[0] = pCut->uSign[1] = 0;
  373. for ( i = 0; i < pCut->nLeaves; i++ )
  374. {
  375. pCut->uSign[(pCut->pLeaves[i] & 32) > 0] |= (1 << (pCut->pLeaves[i] & 31));
  376. if ( i != pCut->nLeaves - 1 )
  377. assert( pCut->pLeaves[i] < pCut->pLeaves[i+1] );
  378. }
  379. }
  380. /**Function*************************************************************
  381. Synopsis [Computes the set of all cuts.]
  382. Description []
  383. SideEffects []
  384. SeeAlso []
  385. ***********************************************************************/
  386. void Lpk_NodeCutsOne( Lpk_Man_t * p, Lpk_Cut_t * pCut, int Node )
  387. {
  388. Lpk_Cut_t * pCutNew;
  389. Abc_Obj_t * pObj, * pFanin;
  390. int i, k, j, nLeavesNew;
  391. /*
  392. printf( "Exploring cut " );
  393. Lpk_NodePrintCut( p, pCut, 1 );
  394. printf( "with node %d\n", Node );
  395. */
  396. // check if the cut can stand adding one more internal node
  397. if ( pCut->nNodes == LPK_SIZE_MAX )
  398. return;
  399. // if the node is a PI, quit
  400. pObj = Abc_NtkObj( p->pNtk, Node );
  401. if ( Abc_ObjIsCi(pObj) )
  402. return;
  403. assert( Abc_ObjIsNode(pObj) );
  404. // assert( Abc_ObjFaninNum(pObj) <= p->pPars->nLutSize );
  405. // if the node is not in the MFFC, check the limit
  406. if ( !Abc_NodeIsTravIdCurrent(pObj) )
  407. {
  408. if ( (int)pCut->nNodesDup == p->pPars->nLutsOver )
  409. return;
  410. assert( (int)pCut->nNodesDup < p->pPars->nLutsOver );
  411. }
  412. // check the possibility of adding this node using the signature
  413. nLeavesNew = pCut->nLeaves - 1;
  414. Abc_ObjForEachFanin( pObj, pFanin, i )
  415. {
  416. if ( (pCut->uSign[(pFanin->Id & 32) > 0] & (1 << (pFanin->Id & 31))) )
  417. continue;
  418. if ( ++nLeavesNew > p->pPars->nVarsMax )
  419. return;
  420. }
  421. // initialize the set of leaves to the nodes in the cut
  422. assert( p->nCuts < LPK_CUTS_MAX );
  423. pCutNew = p->pCuts + p->nCuts;
  424. pCutNew->nLeaves = 0;
  425. for ( i = 0; i < (int)pCut->nLeaves; i++ )
  426. if ( pCut->pLeaves[i] != Node )
  427. pCutNew->pLeaves[pCutNew->nLeaves++] = pCut->pLeaves[i];
  428. // add new nodes
  429. Abc_ObjForEachFanin( pObj, pFanin, i )
  430. {
  431. // find the place where this node belongs
  432. for ( k = 0; k < (int)pCutNew->nLeaves; k++ )
  433. if ( pCutNew->pLeaves[k] >= pFanin->Id )
  434. break;
  435. if ( k < (int)pCutNew->nLeaves && pCutNew->pLeaves[k] == pFanin->Id )
  436. continue;
  437. // check if there is room
  438. if ( (int)pCutNew->nLeaves == p->pPars->nVarsMax )
  439. return;
  440. // move all the nodes
  441. for ( j = pCutNew->nLeaves; j > k; j-- )
  442. pCutNew->pLeaves[j] = pCutNew->pLeaves[j-1];
  443. pCutNew->pLeaves[k] = pFanin->Id;
  444. pCutNew->nLeaves++;
  445. assert( pCutNew->nLeaves <= LPK_SIZE_MAX );
  446. }
  447. // skip the contained cuts
  448. Lpk_NodeCutSignature( pCutNew );
  449. if ( Lpk_NodeCutsOneFilter( p->pCuts, p->nCuts, pCutNew ) )
  450. return;
  451. // update the set of internal nodes
  452. assert( pCut->nNodes < LPK_SIZE_MAX );
  453. memcpy( pCutNew->pNodes, pCut->pNodes, pCut->nNodes * sizeof(int) );
  454. pCutNew->nNodes = pCut->nNodes;
  455. pCutNew->nNodesDup = pCut->nNodesDup;
  456. // check if the node is already there
  457. // if so, move the node to be the last
  458. for ( i = 0; i < (int)pCutNew->nNodes; i++ )
  459. if ( pCutNew->pNodes[i] == Node )
  460. {
  461. for ( k = i; k < (int)pCutNew->nNodes - 1; k++ )
  462. pCutNew->pNodes[k] = pCutNew->pNodes[k+1];
  463. pCutNew->pNodes[k] = Node;
  464. break;
  465. }
  466. if ( i == (int)pCutNew->nNodes ) // new node
  467. {
  468. pCutNew->pNodes[ pCutNew->nNodes++ ] = Node;
  469. pCutNew->nNodesDup += !Abc_NodeIsTravIdCurrent(pObj);
  470. }
  471. // the number of nodes does not exceed MFFC plus duplications
  472. assert( pCutNew->nNodes <= p->nMffc + pCutNew->nNodesDup );
  473. // add the cut to storage
  474. assert( p->nCuts < LPK_CUTS_MAX );
  475. p->nCuts++;
  476. }
  477. /**Function*************************************************************
  478. Synopsis [Computes the set of all cuts.]
  479. Description []
  480. SideEffects []
  481. SeeAlso []
  482. ***********************************************************************/
  483. int Lpk_NodeCuts( Lpk_Man_t * p )
  484. {
  485. Lpk_Cut_t * pCut, * pCut2;
  486. int i, k, Temp, nMffc, fChanges;
  487. // mark the MFFC of the node with the current trav ID
  488. nMffc = p->nMffc = Abc_NodeMffcLabel( p->pObj );
  489. assert( nMffc > 0 );
  490. if ( nMffc == 1 )
  491. return 0;
  492. // initialize the first cut
  493. pCut = p->pCuts; p->nCuts = 1;
  494. pCut->nNodes = 0;
  495. pCut->nNodesDup = 0;
  496. pCut->nLeaves = 1;
  497. pCut->pLeaves[0] = p->pObj->Id;
  498. // assign the signature
  499. Lpk_NodeCutSignature( pCut );
  500. // perform the cut computation
  501. for ( i = 0; i < p->nCuts; i++ )
  502. {
  503. pCut = p->pCuts + i;
  504. if ( pCut->nLeaves == 0 )
  505. continue;
  506. // try to expand the fanins of this cut
  507. for ( k = 0; k < (int)pCut->nLeaves; k++ )
  508. {
  509. // create a new cut
  510. Lpk_NodeCutsOne( p, pCut, pCut->pLeaves[k] );
  511. // quit if the number of cuts has exceeded the limit
  512. if ( p->nCuts == LPK_CUTS_MAX )
  513. break;
  514. }
  515. if ( p->nCuts == LPK_CUTS_MAX )
  516. break;
  517. }
  518. if ( p->nCuts == LPK_CUTS_MAX )
  519. p->nNodesOver++;
  520. // record the impact of this node
  521. if ( p->pPars->fSatur )
  522. Lpk_NodeRecordImpact( p );
  523. // compress the cuts by removing empty ones, those with negative Weight, and decomposable ones
  524. p->nEvals = 0;
  525. for ( i = 0; i < p->nCuts; i++ )
  526. {
  527. pCut = p->pCuts + i;
  528. if ( pCut->nLeaves < 2 )
  529. continue;
  530. // compute the minimum number of LUTs needed to implement this cut
  531. // V = N * (K-1) + 1 ~~~~~ N = Ceiling[(V-1)/(K-1)] = (V-1)/(K-1) + [(V-1)%(K-1) > 0]
  532. pCut->nLuts = Lpk_LutNumLuts( pCut->nLeaves, p->pPars->nLutSize );
  533. // pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup - 1) / pCut->nLuts; //p->pPars->nLutsMax;
  534. pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup) / pCut->nLuts; //p->pPars->nLutsMax;
  535. if ( pCut->Weight <= 1.001 )
  536. // if ( pCut->Weight <= 0.999 )
  537. continue;
  538. pCut->fHasDsd = Lpk_NodeCutsCheckDsd( p, pCut );
  539. if ( pCut->fHasDsd )
  540. continue;
  541. p->pEvals[p->nEvals++] = i;
  542. }
  543. if ( p->nEvals == 0 )
  544. return 0;
  545. // sort the cuts by Weight
  546. do {
  547. fChanges = 0;
  548. for ( i = 0; i < p->nEvals - 1; i++ )
  549. {
  550. pCut = p->pCuts + p->pEvals[i];
  551. pCut2 = p->pCuts + p->pEvals[i+1];
  552. if ( pCut->Weight >= pCut2->Weight - 0.001 )
  553. continue;
  554. Temp = p->pEvals[i];
  555. p->pEvals[i] = p->pEvals[i+1];
  556. p->pEvals[i+1] = Temp;
  557. fChanges = 1;
  558. }
  559. } while ( fChanges );
  560. /*
  561. for ( i = 0; i < p->nEvals; i++ )
  562. {
  563. pCut = p->pCuts + p->pEvals[i];
  564. printf( "Cut %3d : W = %5.2f.\n", i, pCut->Weight );
  565. }
  566. printf( "\n" );
  567. */
  568. return 1;
  569. }
  570. ////////////////////////////////////////////////////////////////////////
  571. /// END OF FILE ///
  572. ////////////////////////////////////////////////////////////////////////
  573. ABC_NAMESPACE_IMPL_END