PageRenderTime 23ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/aig/nwk/nwkSpeedup.c

https://bitbucket.org/alanmi/abc/
C | 382 lines | 259 code | 23 blank | 100 comment | 60 complexity | 11dd4cd3ce8b71f6876354f4da56c3af MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /**CFile****************************************************************
  2. FileName [nwkSpeedup.c]
  3. SystemName [ABC: Logic synthesis and verification system.]
  4. PackageName [Netlist representation.]
  5. Synopsis [Global delay optimization using structural choices.]
  6. Author [Alan Mishchenko]
  7. Affiliation [UC Berkeley]
  8. Date [Ver. 1.0. Started - June 20, 2005.]
  9. Revision [$Id: nwkSpeedup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
  10. ***********************************************************************/
  11. #include "nwk.h"
  12. ABC_NAMESPACE_IMPL_START
  13. ////////////////////////////////////////////////////////////////////////
  14. /// DECLARATIONS ///
  15. ////////////////////////////////////////////////////////////////////////
  16. ////////////////////////////////////////////////////////////////////////
  17. /// FUNCTION DEFINITIONS ///
  18. ////////////////////////////////////////////////////////////////////////
  19. /**Function*************************************************************
  20. Synopsis [Adds strashed nodes for one node.]
  21. Description []
  22. SideEffects []
  23. SeeAlso []
  24. ***********************************************************************/
  25. int Aig_ManSpeedupNode_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, Vec_Ptr_t * vNodes )
  26. {
  27. if ( Aig_ObjIsTravIdCurrent(pAig, pNode) )
  28. return 1;
  29. if ( Aig_ObjIsPi(pNode) )
  30. return 0;
  31. assert( Aig_ObjIsNode(pNode) );
  32. Aig_ObjSetTravIdCurrent( pAig, pNode );
  33. if ( !Aig_ManSpeedupNode_rec( pAig, Aig_ObjFanin0(pNode), vNodes ) )
  34. return 0;
  35. if ( !Aig_ManSpeedupNode_rec( pAig, Aig_ObjFanin1(pNode), vNodes ) )
  36. return 0;
  37. Vec_PtrPush( vNodes, pNode );
  38. return 1;
  39. }
  40. /**Function*************************************************************
  41. Synopsis [Adds strashed nodes for one node.]
  42. Description []
  43. SideEffects []
  44. SeeAlso []
  45. ***********************************************************************/
  46. void Aig_ManSpeedupNode( Nwk_Man_t * pNtk, Aig_Man_t * pAig, Nwk_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vTimes )
  47. {
  48. Vec_Ptr_t * vNodes;
  49. Nwk_Obj_t * pObj, * pObj2;
  50. Aig_Obj_t * ppCofs[32], * pAnd, * pTemp;
  51. int nCofs, i, k, nSkip;
  52. // quit of regulars are the same
  53. Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, i )
  54. Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj2, k )
  55. if ( i != k && Aig_Regular((Aig_Obj_t *)pObj->pCopy) == Aig_Regular((Aig_Obj_t *)pObj2->pCopy) )
  56. {
  57. // printf( "Identical after structural hashing!!!\n" );
  58. return;
  59. }
  60. // collect the AIG nodes
  61. vNodes = Vec_PtrAlloc( 100 );
  62. Aig_ManIncrementTravId( pAig );
  63. Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
  64. Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, i )
  65. {
  66. pAnd = (Aig_Obj_t *)pObj->pCopy;
  67. Aig_ObjSetTravIdCurrent( pAig, Aig_Regular(pAnd) );
  68. }
  69. // traverse from the root node
  70. pAnd = (Aig_Obj_t *)pNode->pCopy;
  71. if ( !Aig_ManSpeedupNode_rec( pAig, Aig_Regular(pAnd), vNodes ) )
  72. {
  73. // printf( "Bad node!!!\n" );
  74. Vec_PtrFree( vNodes );
  75. return;
  76. }
  77. // derive cofactors
  78. nCofs = (1 << Vec_PtrSize(vTimes));
  79. for ( i = 0; i < nCofs; i++ )
  80. {
  81. Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, k )
  82. {
  83. pAnd = (Aig_Obj_t *)pObj->pCopy;
  84. Aig_Regular(pAnd)->pData = Aig_Regular(pAnd);
  85. }
  86. Vec_PtrForEachEntry( Nwk_Obj_t *, vTimes, pObj, k )
  87. {
  88. pAnd = (Aig_Obj_t *)pObj->pCopy;
  89. Aig_Regular(pAnd)->pData = Aig_NotCond( Aig_ManConst1(pAig), ((i & (1<<k)) == 0) );
  90. }
  91. Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pTemp, k )
  92. pTemp->pData = Aig_And( pAig, Aig_ObjChild0Copy(pTemp), Aig_ObjChild1Copy(pTemp) );
  93. // save the result
  94. pAnd = (Aig_Obj_t *)pNode->pCopy;
  95. ppCofs[i] = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pAnd)->pData, Aig_IsComplement(pAnd) );
  96. }
  97. Vec_PtrFree( vNodes );
  98. //Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[0] );
  99. //Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[1] );
  100. // collect the resulting tree
  101. Vec_PtrForEachEntry( Nwk_Obj_t *, vTimes, pObj, k )
  102. for ( nSkip = (1<<k), i = 0; i < nCofs; i += 2*nSkip )
  103. {
  104. pAnd = (Aig_Obj_t *)pObj->pCopy;
  105. ppCofs[i] = Aig_Mux( pAig, Aig_Regular(pAnd), ppCofs[i+nSkip], ppCofs[i] );
  106. }
  107. //Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[0] );
  108. // create choice node
  109. pAnd = Aig_Regular((Aig_Obj_t *)pNode->pCopy); // repr
  110. pTemp = Aig_Regular(ppCofs[0]); // new
  111. if ( Aig_ObjEquiv(pAig, pAnd) == NULL && Aig_ObjEquiv(pAig, pTemp) == NULL && !Aig_ObjCheckTfi(pAig, pTemp, pAnd) )
  112. pAig->pEquivs[pAnd->Id] = pTemp;
  113. }
  114. /**Function*************************************************************
  115. Synopsis [Determines timing-critical edges of the node.]
  116. Description []
  117. SideEffects []
  118. SeeAlso []
  119. ***********************************************************************/
  120. unsigned Nwk_ManDelayTraceTCEdges( Nwk_Man_t * pNtk, Nwk_Obj_t * pNode, float tDelta, int fUseLutLib )
  121. {
  122. int pPinPerm[32];
  123. float pPinDelays[32];
  124. If_Lib_t * pLutLib = fUseLutLib? pNtk->pLutLib : NULL;
  125. Nwk_Obj_t * pFanin;
  126. unsigned uResult = 0;
  127. float tRequired, * pDelays;
  128. int k;
  129. tRequired = Nwk_ObjRequired(pNode);
  130. if ( pLutLib == NULL )
  131. {
  132. Nwk_ObjForEachFanin( pNode, pFanin, k )
  133. if ( tRequired < Nwk_ObjArrival(pFanin) + 1.0 + tDelta )
  134. uResult |= (1 << k);
  135. }
  136. else if ( !pLutLib->fVarPinDelays )
  137. {
  138. pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pNode)];
  139. Nwk_ObjForEachFanin( pNode, pFanin, k )
  140. if ( tRequired < Nwk_ObjArrival(pFanin) + pDelays[0] + tDelta )
  141. uResult |= (1 << k);
  142. }
  143. else
  144. {
  145. pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pNode)];
  146. Nwk_ManDelayTraceSortPins( pNode, pPinPerm, pPinDelays );
  147. Nwk_ObjForEachFanin( pNode, pFanin, k )
  148. if ( tRequired < Nwk_ObjArrival(Nwk_ObjFanin(pNode,pPinPerm[k])) + pDelays[k] + tDelta )
  149. uResult |= (1 << pPinPerm[k]);
  150. }
  151. return uResult;
  152. }
  153. /**Function*************************************************************
  154. Synopsis [Adds choices to speed up the network by the given percentage.]
  155. Description []
  156. SideEffects []
  157. SeeAlso []
  158. ***********************************************************************/
  159. Aig_Man_t * Nwk_ManSpeedup( Nwk_Man_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose )
  160. {
  161. Aig_Man_t * pAig, * pTemp;
  162. Vec_Ptr_t * vTimeCries, * vTimeFanins;
  163. Nwk_Obj_t * pNode, * pFanin, * pFanin2;
  164. Aig_Obj_t * pAnd;
  165. If_Lib_t * pTempLib = pNtk->pLutLib;
  166. Tim_Man_t * pTempTim = NULL;
  167. float tDelta, tArrival;
  168. int i, k, k2, Counter, CounterRes, nTimeCris;
  169. unsigned * puTCEdges;
  170. // perform delay trace
  171. if ( !fUseLutLib )
  172. {
  173. pNtk->pLutLib = NULL;
  174. if ( pNtk->pManTime )
  175. {
  176. pTempTim = pNtk->pManTime;
  177. pNtk->pManTime = Tim_ManDup( pTempTim, 1 );
  178. }
  179. }
  180. tArrival = Nwk_ManDelayTraceLut( pNtk );
  181. tDelta = fUseLutLib ? tArrival*Percentage/100.0 : 1.0;
  182. if ( fVerbose )
  183. {
  184. printf( "Max delay = %.2f. Delta = %.2f. ", tArrival, tDelta );
  185. printf( "Using %s model. ", fUseLutLib? "LUT library" : "unit-delay" );
  186. if ( fUseLutLib )
  187. printf( "Percentage = %d. ", Percentage );
  188. printf( "\n" );
  189. }
  190. // mark the timing critical nodes and edges
  191. puTCEdges = ABC_ALLOC( unsigned, Nwk_ManObjNumMax(pNtk) );
  192. memset( puTCEdges, 0, sizeof(unsigned) * Nwk_ManObjNumMax(pNtk) );
  193. Nwk_ManForEachNode( pNtk, pNode, i )
  194. {
  195. if ( Nwk_ObjSlack(pNode) >= tDelta )
  196. continue;
  197. puTCEdges[pNode->Id] = Nwk_ManDelayTraceTCEdges( pNtk, pNode, tDelta, fUseLutLib );
  198. }
  199. if ( fVerbose )
  200. {
  201. Counter = CounterRes = 0;
  202. Nwk_ManForEachNode( pNtk, pNode, i )
  203. {
  204. Nwk_ObjForEachFanin( pNode, pFanin, k )
  205. if ( !Nwk_ObjIsCi(pFanin) && Nwk_ObjSlack(pFanin) < tDelta )
  206. Counter++;
  207. CounterRes += Aig_WordCountOnes( puTCEdges[pNode->Id] );
  208. }
  209. printf( "Edges: Total = %7d. 0-slack = %7d. Critical = %7d. Ratio = %4.2f\n",
  210. Nwk_ManGetTotalFanins(pNtk), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 );
  211. }
  212. // start the resulting network
  213. pAig = Nwk_ManStrash( pNtk );
  214. pAig->pEquivs = ABC_ALLOC( Aig_Obj_t *, 3 * Aig_ManObjNumMax(pAig) );
  215. memset( pAig->pEquivs, 0, sizeof(Aig_Obj_t *) * 3 * Aig_ManObjNumMax(pAig) );
  216. // collect nodes to be used for resynthesis
  217. Counter = CounterRes = 0;
  218. vTimeCries = Vec_PtrAlloc( 16 );
  219. vTimeFanins = Vec_PtrAlloc( 16 );
  220. Nwk_ManForEachNode( pNtk, pNode, i )
  221. {
  222. if ( Nwk_ObjSlack(pNode) >= tDelta )
  223. continue;
  224. // count the number of non-PI timing-critical nodes
  225. nTimeCris = 0;
  226. Nwk_ObjForEachFanin( pNode, pFanin, k )
  227. if ( !Nwk_ObjIsCi(pFanin) && (puTCEdges[pNode->Id] & (1<<k)) )
  228. nTimeCris++;
  229. if ( !fVeryVerbose && nTimeCris == 0 )
  230. continue;
  231. Counter++;
  232. // count the total number of timing critical second-generation nodes
  233. Vec_PtrClear( vTimeCries );
  234. if ( nTimeCris )
  235. {
  236. Nwk_ObjForEachFanin( pNode, pFanin, k )
  237. if ( !Nwk_ObjIsCi(pFanin) && (puTCEdges[pNode->Id] & (1<<k)) )
  238. Nwk_ObjForEachFanin( pFanin, pFanin2, k2 )
  239. if ( puTCEdges[pFanin->Id] & (1<<k2) )
  240. Vec_PtrPushUnique( vTimeCries, pFanin2 );
  241. }
  242. // if ( !fVeryVerbose && (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) )
  243. if ( (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) )
  244. continue;
  245. CounterRes++;
  246. // collect second generation nodes
  247. Vec_PtrClear( vTimeFanins );
  248. Nwk_ObjForEachFanin( pNode, pFanin, k )
  249. {
  250. if ( Nwk_ObjIsCi(pFanin) )
  251. Vec_PtrPushUnique( vTimeFanins, pFanin );
  252. else
  253. Nwk_ObjForEachFanin( pFanin, pFanin2, k2 )
  254. Vec_PtrPushUnique( vTimeFanins, pFanin2 );
  255. }
  256. // print the results
  257. if ( fVeryVerbose )
  258. {
  259. printf( "%5d Node %5d : %d %2d %2d ", Counter, pNode->Id,
  260. nTimeCris, Vec_PtrSize(vTimeCries), Vec_PtrSize(vTimeFanins) );
  261. Nwk_ObjForEachFanin( pNode, pFanin, k )
  262. printf( "%d(%.2f)%s ", pFanin->Id, Nwk_ObjSlack(pFanin), (puTCEdges[pNode->Id] & (1<<k))? "*":"" );
  263. printf( "\n" );
  264. }
  265. // add the node to choices
  266. if ( Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree )
  267. continue;
  268. // order the fanins in the increasing order of criticalily
  269. if ( Vec_PtrSize(vTimeCries) > 1 )
  270. {
  271. pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 0 );
  272. pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 );
  273. if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) )
  274. {
  275. Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 );
  276. Vec_PtrWriteEntry( vTimeCries, 1, pFanin );
  277. }
  278. }
  279. if ( Vec_PtrSize(vTimeCries) > 2 )
  280. {
  281. pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 );
  282. pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 2 );
  283. if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) )
  284. {
  285. Vec_PtrWriteEntry( vTimeCries, 1, pFanin2 );
  286. Vec_PtrWriteEntry( vTimeCries, 2, pFanin );
  287. }
  288. pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 0 );
  289. pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 );
  290. if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) )
  291. {
  292. Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 );
  293. Vec_PtrWriteEntry( vTimeCries, 1, pFanin );
  294. }
  295. }
  296. // add choice
  297. Aig_ManSpeedupNode( pNtk, pAig, pNode, vTimeFanins, vTimeCries );
  298. }
  299. Vec_PtrFree( vTimeCries );
  300. Vec_PtrFree( vTimeFanins );
  301. ABC_FREE( puTCEdges );
  302. if ( fVerbose )
  303. printf( "Nodes: Total = %7d. 0-slack = %7d. Workable = %7d. Ratio = %4.2f\n",
  304. Nwk_ManNodeNum(pNtk), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 );
  305. // remove invalid choice nodes
  306. Aig_ManForEachNode( pAig, pAnd, i )
  307. if ( Aig_ObjEquiv(pAig, pAnd) )
  308. {
  309. if ( Aig_ObjRefs(Aig_ObjEquiv(pAig, pAnd)) > 0 )
  310. pAig->pEquivs[pAnd->Id] = NULL;
  311. }
  312. // put back the library
  313. if ( !fUseLutLib )
  314. pNtk->pLutLib = pTempLib;
  315. if ( pTempTim )
  316. {
  317. Tim_ManStop( pNtk->pManTime );
  318. pNtk->pManTime = pTempTim;
  319. }
  320. // reconstruct the network
  321. pAig = Aig_ManDupDfs( pTemp = pAig );
  322. Aig_ManStop( pTemp );
  323. // reset levels
  324. Aig_ManChoiceLevel( pAig );
  325. return pAig;
  326. }
  327. ////////////////////////////////////////////////////////////////////////
  328. /// END OF FILE ///
  329. ////////////////////////////////////////////////////////////////////////
  330. ABC_NAMESPACE_IMPL_END