PageRenderTime 38ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/src/proof/dch/dchChoice.c

https://bitbucket.org/alanmi/abc/
C | 552 lines | 343 code | 22 blank | 187 comment | 96 complexity | a382ddd00f34d534c5d0f502d61d4ef9 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /**CFile****************************************************************
  2. FileName [dchChoice.c]
  3. SystemName [ABC: Logic synthesis and verification system.]
  4. PackageName [Choice computation for tech-mapping.]
  5. Synopsis [Contrustion of choices.]
  6. Author [Alan Mishchenko]
  7. Affiliation [UC Berkeley]
  8. Date [Ver. 1.0. Started - June 29, 2008.]
  9. Revision [$Id: dchChoice.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
  10. ***********************************************************************/
  11. #include "dchInt.h"
  12. ABC_NAMESPACE_IMPL_START
  13. ////////////////////////////////////////////////////////////////////////
  14. /// DECLARATIONS ///
  15. ////////////////////////////////////////////////////////////////////////
  16. ////////////////////////////////////////////////////////////////////////
  17. /// FUNCTION DEFINITIONS ///
  18. ////////////////////////////////////////////////////////////////////////
  19. /**Function*************************************************************
  20. Synopsis [Counts support nodes.]
  21. Description []
  22. SideEffects []
  23. SeeAlso []
  24. ***********************************************************************/
  25. int Dch_ObjCountSupp_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
  26. {
  27. int Count;
  28. if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
  29. return 0;
  30. Aig_ObjSetTravIdCurrent( p, pObj );
  31. if ( Aig_ObjIsCi(pObj) )
  32. return 1;
  33. assert( Aig_ObjIsNode(pObj) );
  34. Count = Dch_ObjCountSupp_rec( p, Aig_ObjFanin0(pObj) );
  35. Count += Dch_ObjCountSupp_rec( p, Aig_ObjFanin1(pObj) );
  36. return Count;
  37. }
  38. int Dch_ObjCountSupp( Aig_Man_t * p, Aig_Obj_t * pObj )
  39. {
  40. Aig_ManIncrementTravId( p );
  41. return Dch_ObjCountSupp_rec( p, pObj );
  42. }
  43. /**Function*************************************************************
  44. Synopsis [Counts the number of representatives.]
  45. Description []
  46. SideEffects []
  47. SeeAlso []
  48. ***********************************************************************/
  49. int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig )
  50. {
  51. Aig_Obj_t * pObj, * pRepr;
  52. int i, nReprs = 0;
  53. Aig_ManForEachObj( pAig, pObj, i )
  54. {
  55. pRepr = Aig_ObjRepr( pAig, pObj );
  56. if ( pRepr == NULL )
  57. continue;
  58. assert( pRepr->Id < pObj->Id );
  59. nReprs++;
  60. }
  61. return nReprs;
  62. }
  63. int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig )
  64. {
  65. Aig_Obj_t * pObj, * pEquiv;
  66. int i, nEquivs = 0;
  67. Aig_ManForEachObj( pAig, pObj, i )
  68. {
  69. pEquiv = Aig_ObjEquiv( pAig, pObj );
  70. if ( pEquiv == NULL )
  71. continue;
  72. assert( pEquiv->Id < pObj->Id );
  73. nEquivs++;
  74. }
  75. return nEquivs;
  76. }
  77. /**Function*************************************************************
  78. Synopsis [Marks the TFI of the node.]
  79. Description [Returns 1 if there is a CI not marked with previous ID.]
  80. SideEffects []
  81. SeeAlso []
  82. ***********************************************************************/
  83. int Dch_ObjMarkTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
  84. {
  85. int RetValue;
  86. if ( pObj == NULL )
  87. return 0;
  88. if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
  89. return 0;
  90. if ( Aig_ObjIsCi(pObj) )
  91. {
  92. RetValue = !Aig_ObjIsTravIdPrevious( p, pObj );
  93. Aig_ObjSetTravIdCurrent( p, pObj );
  94. return RetValue;
  95. }
  96. assert( Aig_ObjIsNode(pObj) );
  97. Aig_ObjSetTravIdCurrent( p, pObj );
  98. RetValue = Dch_ObjMarkTfi_rec( p, Aig_ObjFanin0(pObj) );
  99. RetValue += Dch_ObjMarkTfi_rec( p, Aig_ObjFanin1(pObj) );
  100. // RetValue += Dch_ObjMarkTfi_rec( p, Aig_ObjEquiv(p, pObj) );
  101. return (RetValue > 0);
  102. }
  103. int Dch_ObjCheckSuppRed( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
  104. {
  105. // mark support of the representative node (pRepr)
  106. Aig_ManIncrementTravId( p );
  107. Dch_ObjMarkTfi_rec( p, pRepr );
  108. // detect if the new node (pObj) depends on additional variables
  109. Aig_ManIncrementTravId( p );
  110. if ( Dch_ObjMarkTfi_rec( p, pObj ) )
  111. return 1;//, printf( "1" );
  112. // detect if the representative node (pRepr) depends on additional variables
  113. Aig_ManIncrementTravId( p );
  114. if ( Dch_ObjMarkTfi_rec( p, pRepr ) )
  115. return 1;//, printf( "2" );
  116. // skip the choice if this is what is happening
  117. return 0;
  118. }
  119. /**Function*************************************************************
  120. Synopsis [Make sure reprsentative nodes do not have representatives.]
  121. Description []
  122. SideEffects []
  123. SeeAlso []
  124. ***********************************************************************/
  125. void Aig_ManCheckReprs( Aig_Man_t * p )
  126. {
  127. int fPrintConst = 0;
  128. Aig_Obj_t * pObj;
  129. int i, fProb = 0;
  130. int Class0 = 0, ClassCi = 0;
  131. Aig_ManForEachObj( p, pObj, i )
  132. {
  133. if ( Aig_ObjRepr(p, pObj) == NULL )
  134. continue;
  135. if ( !Aig_ObjIsNode(pObj) )
  136. printf( "Obj %d is not an AND but it has a repr %d.\n", i, Aig_ObjId(Aig_ObjRepr(p, pObj)) ), fProb = 1;
  137. else if ( Aig_ObjRepr(p, Aig_ObjRepr(p, pObj)) )
  138. printf( "Obj %d has repr %d with a repr %d.\n", i, Aig_ObjId(Aig_ObjRepr(p, pObj)), Aig_ObjId(Aig_ObjRepr(p, Aig_ObjRepr(p, pObj))) ), fProb = 1;
  139. }
  140. if ( !fProb )
  141. printf( "Representive verification successful.\n" );
  142. else
  143. printf( "Representive verification FAILED.\n" );
  144. if ( !fPrintConst )
  145. return;
  146. // count how many representatives are const0 or a CI
  147. Aig_ManForEachObj( p, pObj, i )
  148. {
  149. if ( Aig_ObjRepr(p, pObj) == Aig_ManConst1(p) )
  150. Class0++;
  151. if ( Aig_ObjRepr(p, pObj) && Aig_ObjIsCi(Aig_ObjRepr(p, pObj)) )
  152. ClassCi++;
  153. }
  154. printf( "Const0 nodes = %d. ConstCI nodes = %d.\n", Class0, ClassCi );
  155. }
  156. /**Function*************************************************************
  157. Synopsis [Verify correctness of choices.]
  158. Description []
  159. SideEffects []
  160. SeeAlso []
  161. ***********************************************************************/
  162. void Dch_CheckChoices( Aig_Man_t * p, int fSkipRedSupps )
  163. {
  164. Aig_Obj_t * pObj;
  165. int i, fProb = 0;
  166. Aig_ManCleanMarkA( p );
  167. Aig_ManForEachNode( p, pObj, i )
  168. {
  169. if ( p->pEquivs[i] != NULL )
  170. {
  171. if ( pObj->fMarkA == 1 )
  172. printf( "node %d participates in more than one choice class\n", i ), fProb = 1;
  173. pObj->fMarkA = 1;
  174. // check redundancy
  175. if ( fSkipRedSupps && Dch_ObjCheckSuppRed( p, pObj, p->pEquivs[i]) )
  176. printf( "node %d and repr %d have diff supports\n", pObj->Id, p->pEquivs[i]->Id );
  177. // consider the next one
  178. pObj = p->pEquivs[i];
  179. if ( p->pEquivs[Aig_ObjId(pObj)] == NULL )
  180. {
  181. if ( pObj->fMarkA == 1 )
  182. printf( "repr %d has final node %d participates in more than one choice class\n", i, pObj->Id ), fProb = 1;
  183. pObj->fMarkA = 1;
  184. }
  185. // consider the non-head ones
  186. if ( pObj->nRefs > 0 )
  187. printf( "node %d belonging to choice has fanout %d\n", pObj->Id, pObj->nRefs );
  188. }
  189. if ( p->pReprs && p->pReprs[i] != NULL )
  190. {
  191. if ( pObj->nRefs > 0 )
  192. printf( "node %d has representative %d and fanout count %d\n", pObj->Id, p->pReprs[i]->Id, pObj->nRefs ), fProb = 1;
  193. }
  194. }
  195. Aig_ManCleanMarkA( p );
  196. if ( !fProb )
  197. printf( "Verification of choice AIG succeeded.\n" );
  198. else
  199. printf( "Verification of choice AIG FAILED.\n" );
  200. }
  201. /**Function*************************************************************
  202. Synopsis [Checks for combinational loops in the AIG.]
  203. Description [Returns 1 if combinational loop is detected.]
  204. SideEffects []
  205. SeeAlso []
  206. ***********************************************************************/
  207. int Aig_ManCheckAcyclic_rec( Aig_Man_t * p, Aig_Obj_t * pNode, int fVerbose )
  208. {
  209. Aig_Obj_t * pFanin;
  210. int fAcyclic;
  211. if ( Aig_ObjIsCi(pNode) || Aig_ObjIsConst1(pNode) )
  212. return 1;
  213. assert( Aig_ObjIsNode(pNode) );
  214. // make sure the node is not visited
  215. assert( !Aig_ObjIsTravIdPrevious(p, pNode) );
  216. // check if the node is part of the combinational loop
  217. if ( Aig_ObjIsTravIdCurrent(p, pNode) )
  218. {
  219. if ( fVerbose )
  220. Abc_Print( 1, "Network \"%s\" contains combinational loop!\n", p->pSpec? p->pSpec : NULL );
  221. if ( fVerbose )
  222. Abc_Print( 1, "Node \"%d\" is encountered twice on the following path to the COs:\n", Aig_ObjId(pNode) );
  223. return 0;
  224. }
  225. // mark this node as a node on the current path
  226. Aig_ObjSetTravIdCurrent( p, pNode );
  227. // visit the transitive fanin
  228. pFanin = Aig_ObjFanin0(pNode);
  229. // check if the fanin is visited
  230. if ( !Aig_ObjIsTravIdPrevious(p, pFanin) )
  231. {
  232. // traverse the fanin's cone searching for the loop
  233. if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) )
  234. {
  235. // return as soon as the loop is detected
  236. if ( fVerbose )
  237. Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) );
  238. return 0;
  239. }
  240. }
  241. // visit the transitive fanin
  242. pFanin = Aig_ObjFanin1(pNode);
  243. // check if the fanin is visited
  244. if ( !Aig_ObjIsTravIdPrevious(p, pFanin) )
  245. {
  246. // traverse the fanin's cone searching for the loop
  247. if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) )
  248. {
  249. // return as soon as the loop is detected
  250. if ( fVerbose )
  251. Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) );
  252. return 0;
  253. }
  254. }
  255. // visit choices
  256. if ( Aig_ObjRepr(p, pNode) == NULL && Aig_ObjEquiv(p, pNode) != NULL )
  257. {
  258. for ( pFanin = Aig_ObjEquiv(p, pNode); pFanin; pFanin = Aig_ObjEquiv(p, pFanin) )
  259. {
  260. // check if the fanin is visited
  261. if ( Aig_ObjIsTravIdPrevious(p, pFanin) )
  262. continue;
  263. // traverse the fanin's cone searching for the loop
  264. if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) )
  265. continue;
  266. // return as soon as the loop is detected
  267. if ( fVerbose )
  268. Abc_Print( 1, " %d", Aig_ObjId(pFanin) );
  269. if ( fVerbose )
  270. Abc_Print( 1, " (choice of %d) -> ", Aig_ObjId(pNode) );
  271. return 0;
  272. }
  273. }
  274. // mark this node as a visited node
  275. Aig_ObjSetTravIdPrevious( p, pNode );
  276. return 1;
  277. }
  278. int Aig_ManCheckAcyclic( Aig_Man_t * p, int fVerbose )
  279. {
  280. Aig_Obj_t * pNode;
  281. int fAcyclic;
  282. int i;
  283. // set the traversal ID for this DFS ordering
  284. Aig_ManIncrementTravId( p );
  285. Aig_ManIncrementTravId( p );
  286. // pNode->TravId == pNet->nTravIds means "pNode is on the path"
  287. // pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path"
  288. // pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited"
  289. // traverse the network to detect cycles
  290. fAcyclic = 1;
  291. Aig_ManForEachCo( p, pNode, i )
  292. {
  293. pNode = Aig_ObjFanin0(pNode);
  294. if ( Aig_ObjIsTravIdPrevious(p, pNode) )
  295. continue;
  296. // traverse the output logic cone
  297. if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pNode, fVerbose)) )
  298. continue;
  299. // stop as soon as the first loop is detected
  300. if ( fVerbose )
  301. Abc_Print( 1, " CO %d\n", i );
  302. break;
  303. }
  304. return fAcyclic;
  305. }
  306. /**Function*************************************************************
  307. Synopsis [Returns 1 if the choice node of pRepr is in the TFI of pObj.]
  308. Description []
  309. SideEffects []
  310. SeeAlso []
  311. ***********************************************************************/
  312. int Dch_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
  313. {
  314. // check the trivial cases
  315. if ( pObj == NULL )
  316. return 0;
  317. if ( Aig_ObjIsCi(pObj) )
  318. return 0;
  319. if ( pObj->fMarkA )
  320. return 1;
  321. // skip the visited node
  322. if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
  323. return 0;
  324. Aig_ObjSetTravIdCurrent( p, pObj );
  325. // check the children
  326. if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin0(pObj) ) )
  327. return 1;
  328. if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin1(pObj) ) )
  329. return 1;
  330. // check equivalent nodes
  331. return Dch_ObjCheckTfi_rec( p, Aig_ObjEquiv(p, pObj) );
  332. }
  333. int Dch_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
  334. {
  335. Aig_Obj_t * pTemp;
  336. int RetValue;
  337. assert( !Aig_IsComplement(pObj) );
  338. assert( !Aig_IsComplement(pRepr) );
  339. // mark nodes of the choice node
  340. for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) )
  341. pTemp->fMarkA = 1;
  342. // traverse the new node
  343. Aig_ManIncrementTravId( p );
  344. RetValue = Dch_ObjCheckTfi_rec( p, pObj );
  345. // unmark nodes of the choice node
  346. for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) )
  347. pTemp->fMarkA = 0;
  348. return RetValue;
  349. }
  350. /**Function*************************************************************
  351. Synopsis [Returns representatives of fanin in approapriate polarity.]
  352. Description []
  353. SideEffects []
  354. SeeAlso []
  355. ***********************************************************************/
  356. static inline Aig_Obj_t * Aig_ObjGetRepr( Aig_Man_t * p, Aig_Obj_t * pObj )
  357. {
  358. Aig_Obj_t * pRepr;
  359. if ( (pRepr = Aig_ObjRepr(p, Aig_Regular(pObj))) )
  360. return Aig_NotCond( pRepr, Aig_Regular(pObj)->fPhase ^ pRepr->fPhase ^ Aig_IsComplement(pObj) );
  361. return pObj;
  362. }
  363. static inline Aig_Obj_t * Aig_ObjChild0CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild0Copy(pObj) ); }
  364. static inline Aig_Obj_t * Aig_ObjChild1CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild1Copy(pObj) ); }
  365. /**Function*************************************************************
  366. Synopsis [Derives the AIG with choices from representatives.]
  367. Description []
  368. SideEffects []
  369. SeeAlso []
  370. ***********************************************************************/
  371. void Dch_DeriveChoiceAigNode( Aig_Man_t * pAigNew, Aig_Man_t * pAigOld, Aig_Obj_t * pObj, int fSkipRedSupps )
  372. {
  373. Aig_Obj_t * pRepr, * pObjNew, * pReprNew;
  374. assert( !Aig_IsComplement(pObj) );
  375. // get the representative
  376. pRepr = Aig_ObjRepr( pAigOld, pObj );
  377. if ( pRepr != NULL && (Aig_ObjIsConst1(pRepr) || Aig_ObjIsCi(pRepr)) )
  378. {
  379. assert( pRepr->pData != NULL );
  380. pObj->pData = Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pObj->fPhase ^ pRepr->fPhase );
  381. return;
  382. }
  383. // get the new node
  384. pObjNew = Aig_And( pAigNew,
  385. Aig_ObjChild0CopyRepr(pAigNew, pObj),
  386. Aig_ObjChild1CopyRepr(pAigNew, pObj) );
  387. // pObjNew = Aig_ObjGetRepr( pAigNew, pObjNew );
  388. while ( 1 )
  389. {
  390. Aig_Obj_t * pObjNew2 = pObjNew;
  391. pObjNew = Aig_ObjGetRepr( pAigNew, pObjNew2 );
  392. if ( pObjNew == pObjNew2 )
  393. break;
  394. }
  395. // assert( Aig_ObjRepr( pAigNew, pObjNew ) == NULL );
  396. // assign the copy
  397. assert( pObj->pData == NULL );
  398. pObj->pData = pObjNew;
  399. // skip those without reprs
  400. if ( pRepr == NULL )
  401. return;
  402. assert( pRepr->Id < pObj->Id );
  403. assert( Aig_ObjIsNode(pRepr) );
  404. // get the corresponding new nodes
  405. pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData);
  406. pReprNew = Aig_Regular((Aig_Obj_t *)pRepr->pData);
  407. // skip earlier nodes
  408. if ( pReprNew->Id >= pObjNew->Id )
  409. return;
  410. assert( pReprNew->Id < pObjNew->Id );
  411. // set the representatives
  412. Aig_ObjSetRepr( pAigNew, pObjNew, pReprNew );
  413. // skip used nodes
  414. if ( pObjNew->nRefs > 0 )
  415. return;
  416. assert( pObjNew->nRefs == 0 );
  417. // skip choices that can lead to combo loops
  418. if ( Dch_ObjCheckTfi( pAigNew, pObjNew, pReprNew ) )
  419. return;
  420. // don't add choice if structural support of pObjNew and pReprNew differ
  421. if ( fSkipRedSupps && Dch_ObjCheckSuppRed(pAigNew, pObjNew, pReprNew) )
  422. return;
  423. // add choice to the end of the list
  424. while ( pAigNew->pEquivs[pReprNew->Id] != NULL )
  425. pReprNew = pAigNew->pEquivs[pReprNew->Id];
  426. assert( pAigNew->pEquivs[pReprNew->Id] == NULL );
  427. pAigNew->pEquivs[pReprNew->Id] = pObjNew;
  428. }
  429. Aig_Man_t * Dch_DeriveChoiceAigInt( Aig_Man_t * pAig, int fSkipRedSupps )
  430. {
  431. Aig_Man_t * pChoices;
  432. Aig_Obj_t * pObj;
  433. int i;
  434. // start recording equivalences
  435. pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) );
  436. pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
  437. pChoices->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
  438. // map constants and PIs
  439. Aig_ManCleanData( pAig );
  440. Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices);
  441. Aig_ManForEachCi( pAig, pObj, i )
  442. pObj->pData = Aig_ObjCreateCi( pChoices );
  443. // construct choices for the internal nodes
  444. assert( pAig->pReprs != NULL );
  445. Aig_ManForEachNode( pAig, pObj, i )
  446. Dch_DeriveChoiceAigNode( pChoices, pAig, pObj, fSkipRedSupps );
  447. Aig_ManForEachCo( pAig, pObj, i )
  448. Aig_ObjCreateCo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) );
  449. Aig_ManSetRegNum( pChoices, Aig_ManRegNum(pAig) );
  450. return pChoices;
  451. }
  452. Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig, int fSkipRedSupps )
  453. {
  454. int fCheck = 0;
  455. Aig_Man_t * pChoices, * pTemp;
  456. // verify
  457. if ( fCheck )
  458. Aig_ManCheckReprs( pAig );
  459. // compute choices
  460. pChoices = Dch_DeriveChoiceAigInt( pAig, fSkipRedSupps );
  461. ABC_FREE( pChoices->pReprs );
  462. // verify
  463. if ( fCheck )
  464. Dch_CheckChoices( pChoices, fSkipRedSupps );
  465. // find correct topo order with choices
  466. pChoices = Aig_ManDupDfs( pTemp = pChoices );
  467. Aig_ManStop( pTemp );
  468. // verify
  469. if ( fCheck )
  470. Dch_CheckChoices( pChoices, fSkipRedSupps );
  471. return pChoices;
  472. }
  473. ////////////////////////////////////////////////////////////////////////
  474. /// END OF FILE ///
  475. ////////////////////////////////////////////////////////////////////////
  476. ABC_NAMESPACE_IMPL_END