You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

451 lines
12 KiB

  1. /**CFile**********************************************************************
  2. FileName [dddmpNodeAdd.c]
  3. PackageName [dddmp]
  4. Synopsis [Functions to handle ADD node infos and numbering]
  5. Description [Functions to handle ADD node infos and numbering.
  6. ]
  7. Author [Gianpiero Cabodi and Stefano Quer]
  8. Copyright [
  9. Copyright (c) 2004 by Politecnico di Torino.
  10. All Rights Reserved. This software is for educational purposes only.
  11. Permission is given to academic institutions to use, copy, and modify
  12. this software and its documentation provided that this introductory
  13. message is not removed, that this software and its documentation is
  14. used for the institutions' internal research and educational purposes,
  15. and that no monies are exchanged. No guarantee is expressed or implied
  16. by the distribution of this code.
  17. Send bug-reports and/or questions to:
  18. {gianpiero.cabodi,stefano.quer}@polito.it.
  19. ]
  20. ******************************************************************************/
  21. #include "dddmpInt.h"
  22. /*---------------------------------------------------------------------------*/
  23. /* Stucture declarations */
  24. /*---------------------------------------------------------------------------*/
  25. /*---------------------------------------------------------------------------*/
  26. /* Type declarations */
  27. /*---------------------------------------------------------------------------*/
  28. /*---------------------------------------------------------------------------*/
  29. /* Variable declarations */
  30. /*---------------------------------------------------------------------------*/
  31. /*---------------------------------------------------------------------------*/
  32. /* Macro declarations */
  33. /*---------------------------------------------------------------------------*/
  34. /**AutomaticStart*************************************************************/
  35. /*---------------------------------------------------------------------------*/
  36. /* Static function prototypes */
  37. /*---------------------------------------------------------------------------*/
  38. static int NumberNodeRecurAdd(DdNode *f, int id);
  39. static void RemoveFromUniqueRecurAdd(DdManager *ddMgr, DdNode *f);
  40. static void RestoreInUniqueRecurAdd(DdManager *ddMgr, DdNode *f);
  41. /**AutomaticEnd***************************************************************/
  42. /*---------------------------------------------------------------------------*/
  43. /* Definition of exported functions */
  44. /*---------------------------------------------------------------------------*/
  45. /*---------------------------------------------------------------------------*/
  46. /* Definition of internal functions */
  47. /*---------------------------------------------------------------------------*/
  48. /**Function********************************************************************
  49. Synopsis [Removes nodes from unique table and number them]
  50. Description [Node numbering is required to convert pointers to integers.
  51. Since nodes are removed from unique table, no new nodes should
  52. be generated before re-inserting nodes in the unique table
  53. (DddmpUnnumberDdNodes()).
  54. ]
  55. SideEffects [Nodes are temporarily removed from unique table]
  56. SeeAlso [RemoveFromUniqueRecurAdd (), NumberNodeRecurAdd (),
  57. DddmpUnnumberDdNodesAdd ()]
  58. ******************************************************************************/
  59. int
  60. DddmpNumberAddNodes (
  61. DdManager *ddMgr /* IN: DD Manager */,
  62. DdNode **f /* IN: array of BDDs */,
  63. int n /* IN: number of BDD roots in the array of BDDs */
  64. )
  65. {
  66. int id=0, i;
  67. for (i=0; i<n; i++) {
  68. RemoveFromUniqueRecurAdd (ddMgr, f[i]);
  69. }
  70. for (i=0; i<n; i++) {
  71. id = NumberNodeRecurAdd (f[i], id);
  72. }
  73. return (id);
  74. }
  75. /**Function********************************************************************
  76. Synopsis [Restores nodes in unique table, loosing numbering]
  77. Description [Node indexes are no more needed. Nodes are re-linked in the
  78. unique table.
  79. ]
  80. SideEffects [None]
  81. SeeAlso [DddmpNumberDdNodeAdd ()]
  82. ******************************************************************************/
  83. void
  84. DddmpUnnumberAddNodes (
  85. DdManager *ddMgr /* IN: DD Manager */,
  86. DdNode **f /* IN: array of BDDs */,
  87. int n /* IN: number of BDD roots in the array of BDDs */
  88. )
  89. {
  90. int i;
  91. for (i=0; i<n; i++) {
  92. RestoreInUniqueRecurAdd (ddMgr, f[i]);
  93. }
  94. return;
  95. }
  96. /**Function********************************************************************
  97. Synopsis [Write index to node]
  98. Description [The index of the node is written in the "next" field of
  99. a DdNode struct. LSB is not used (set to 0). It is used as
  100. "visited" flag in DD traversals.
  101. ]
  102. SideEffects [None]
  103. SeeAlso [DddmpReadNodeIndexAdd (), DddmpSetVisitedAdd (),
  104. DddmpVisitedAdd ()]
  105. ******************************************************************************/
  106. void
  107. DddmpWriteNodeIndexAdd (
  108. DdNode *f /* IN: BDD node */,
  109. int id /* IN: index to be written */
  110. )
  111. {
  112. if (1 || !Cudd_IsConstant (f)) {
  113. f->next = (struct DdNode *)((ptruint)id<<1);
  114. }
  115. return;
  116. }
  117. /**Function********************************************************************
  118. Synopsis [Reads the index of a node]
  119. Description [Reads the index of a node. LSB is skipped (used as visited
  120. flag).
  121. ]
  122. SideEffects [None]
  123. SeeAlso [DddmpWriteNodeIndexAdd (), DddmpSetVisitedAdd (),
  124. DddmpVisitedAdd ()]
  125. ******************************************************************************/
  126. int
  127. DddmpReadNodeIndexAdd (
  128. DdNode *f /* IN: BDD node */
  129. )
  130. {
  131. if (1 || !Cudd_IsConstant (f)) {
  132. return ((int)(((ptruint)(f->next))>>1));
  133. } else {
  134. return (1);
  135. }
  136. }
  137. /**Function********************************************************************
  138. Synopsis [Returns true if node is visited]
  139. Description [Returns true if node is visited]
  140. SideEffects [None]
  141. SeeAlso [DddmpSetVisitedAdd (), DddmpClearVisitedAdd ()]
  142. ******************************************************************************/
  143. int
  144. DddmpVisitedAdd (
  145. DdNode *f /* IN: BDD node to be tested */
  146. )
  147. {
  148. f = Cudd_Regular(f);
  149. return ((int)((ptruint)(f->next)) & (01));
  150. }
  151. /**Function********************************************************************
  152. Synopsis [Marks a node as visited]
  153. Description [Marks a node as visited]
  154. SideEffects [None]
  155. SeeAlso [DddmpVisitedAdd (), DddmpClearVisitedAdd ()]
  156. ******************************************************************************/
  157. void
  158. DddmpSetVisitedAdd (
  159. DdNode *f /* IN: BDD node to be marked (as visited) */
  160. )
  161. {
  162. f = Cudd_Regular(f);
  163. f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next))|01);
  164. return;
  165. }
  166. /**Function********************************************************************
  167. Synopsis [Marks a node as not visited]
  168. Description [Marks a node as not visited]
  169. SideEffects [None]
  170. SeeAlso [DddmpVisitedAdd (), DddmpSetVisitedAdd ()]
  171. ******************************************************************************/
  172. void
  173. DddmpClearVisitedAdd (
  174. DdNode *f /* IN: BDD node to be marked (as not visited) */
  175. )
  176. {
  177. f = Cudd_Regular (f);
  178. f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next)) & (~01));
  179. return;
  180. }
  181. /*---------------------------------------------------------------------------*/
  182. /* Definition of static functions */
  183. /*---------------------------------------------------------------------------*/
  184. /**Function********************************************************************
  185. Synopsis [Number nodes recursively in post-order]
  186. Description [Number nodes recursively in post-order.
  187. The "visited" flag is used with inverse polarity, because all nodes
  188. were set "visited" when removing them from unique.
  189. ]
  190. SideEffects ["visited" flags are reset.]
  191. SeeAlso []
  192. ******************************************************************************/
  193. static int
  194. NumberNodeRecurAdd (
  195. DdNode *f /* IN: root of the BDD to be numbered */,
  196. int id /* IN/OUT: index to be assigned to the node */
  197. )
  198. {
  199. f = Cudd_Regular(f);
  200. if (!DddmpVisitedAdd (f)) {
  201. return (id);
  202. }
  203. if (!cuddIsConstant (f)) {
  204. id = NumberNodeRecurAdd (cuddT (f), id);
  205. id = NumberNodeRecurAdd (cuddE (f), id);
  206. }
  207. DddmpWriteNodeIndexAdd (f, ++id);
  208. DddmpClearVisitedAdd (f);
  209. return (id);
  210. }
  211. /**Function********************************************************************
  212. Synopsis [Removes a node from unique table]
  213. Description [Removes a node from the unique table by locating the proper
  214. subtable and unlinking the node from it. It recurs on the
  215. children of the node. Constants remain untouched.
  216. ]
  217. SideEffects [Nodes are left with the "visited" flag true.]
  218. SeeAlso [RestoreInUniqueRecurAdd ()]
  219. ******************************************************************************/
  220. static void
  221. RemoveFromUniqueRecurAdd (
  222. DdManager *ddMgr /* IN: DD Manager */,
  223. DdNode *f /* IN: root of the BDD to be extracted */
  224. )
  225. {
  226. DdNode *node, *last, *next;
  227. DdNode *sentinel = &(ddMgr->sentinel);
  228. DdNodePtr *nodelist;
  229. DdSubtable *subtable;
  230. int pos, level;
  231. f = Cudd_Regular (f);
  232. if (DddmpVisitedAdd (f)) {
  233. return;
  234. }
  235. if (!cuddIsConstant (f)) {
  236. RemoveFromUniqueRecurAdd (ddMgr, cuddT (f));
  237. RemoveFromUniqueRecurAdd (ddMgr, cuddE (f));
  238. level = ddMgr->perm[f->index];
  239. subtable = &(ddMgr->subtables[level]);
  240. nodelist = subtable->nodelist;
  241. pos = ddHash (cuddT (f), cuddE (f), subtable->shift);
  242. node = nodelist[pos];
  243. last = NULL;
  244. while (node != sentinel) {
  245. next = node->next;
  246. if (node == f) {
  247. if (last != NULL)
  248. last->next = next;
  249. else
  250. nodelist[pos] = next;
  251. break;
  252. } else {
  253. last = node;
  254. node = next;
  255. }
  256. }
  257. f->next = NULL;
  258. }
  259. DddmpSetVisitedAdd (f);
  260. return;
  261. }
  262. /**Function********************************************************************
  263. Synopsis [Restores a node in unique table]
  264. Description [Restores a node in unique table (recursively)]
  265. SideEffects [Nodes are not restored in the same order as before removal]
  266. SeeAlso [RemoveFromUniqueAdd ()]
  267. ******************************************************************************/
  268. static void
  269. RestoreInUniqueRecurAdd (
  270. DdManager *ddMgr /* IN: DD Manager */,
  271. DdNode *f /* IN: root of the BDD to be restored */
  272. )
  273. {
  274. DdNodePtr *nodelist;
  275. DdNode *T, *E, *looking;
  276. DdNodePtr *previousP;
  277. DdSubtable *subtable;
  278. int pos, level;
  279. #ifdef DDDMP_DEBUG
  280. DdNode *node;
  281. DdNode *sentinel = &(ddMgr->sentinel);
  282. #endif
  283. f = Cudd_Regular(f);
  284. if (!Cudd_IsComplement (f->next)) {
  285. return;
  286. }
  287. if (cuddIsConstant (f)) {
  288. /* StQ 11.02.2004:
  289. Bug fixed --> restore NULL within the next field */
  290. /*DddmpClearVisitedAdd (f);*/
  291. f->next = NULL;
  292. return;
  293. }
  294. RestoreInUniqueRecurAdd (ddMgr, cuddT (f));
  295. RestoreInUniqueRecurAdd (ddMgr, cuddE (f));
  296. level = ddMgr->perm[f->index];
  297. subtable = &(ddMgr->subtables[level]);
  298. nodelist = subtable->nodelist;
  299. pos = ddHash (cuddT (f), cuddE (f), subtable->shift);
  300. #ifdef DDDMP_DEBUG
  301. /* verify uniqueness to avoid duplicate nodes in unique table */
  302. for (node=nodelist[pos]; node != sentinel; node=node->next)
  303. assert(node!=f);
  304. #endif
  305. T = cuddT (f);
  306. E = cuddE (f);
  307. previousP = &(nodelist[pos]);
  308. looking = *previousP;
  309. while (T < cuddT (looking)) {
  310. previousP = &(looking->next);
  311. looking = *previousP;
  312. }
  313. while (T == cuddT (looking) && E < cuddE (looking)) {
  314. previousP = &(looking->next);
  315. looking = *previousP;
  316. }
  317. f->next = *previousP;
  318. *previousP = f;
  319. return;
  320. }