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.

944 lines
28 KiB

  1. /**CFile**********************************************************************
  2. FileName [dddmpStoreAdd.c]
  3. PackageName [dddmp]
  4. Synopsis [Functions to write ADDs to file.]
  5. Description [Functions to write ADDs to file.
  6. ADDs are represended on file either in text or binary format under the
  7. following rules. A file contains a forest of ADDs (a vector of
  8. Boolean functions). ADD nodes are numbered with contiguous numbers,
  9. from 1 to NNodes (total number of nodes on a file). 0 is not used to
  10. allow negative node indexes for complemented edges. A file contains
  11. a header, including information about variables and roots to ADD
  12. functions, followed by the list of nodes.
  13. ADD nodes are listed according to their numbering, and in the present
  14. implementation numbering follows a post-order strategy, in such a way
  15. that a node is never listed before its Then/Else children.
  16. ]
  17. Author [Gianpiero Cabodi and Stefano Quer]
  18. Copyright [
  19. Copyright (c) 2004 by Politecnico di Torino.
  20. All Rights Reserved. This software is for educational purposes only.
  21. Permission is given to academic institutions to use, copy, and modify
  22. this software and its documentation provided that this introductory
  23. message is not removed, that this software and its documentation is
  24. used for the institutions' internal research and educational purposes,
  25. and that no monies are exchanged. No guarantee is expressed or implied
  26. by the distribution of this code.
  27. Send bug-reports and/or questions to:
  28. {gianpiero.cabodi,stefano.quer}@polito.it.
  29. ]
  30. ******************************************************************************/
  31. #include "dddmpInt.h"
  32. /*---------------------------------------------------------------------------*/
  33. /* Stucture declarations */
  34. /*---------------------------------------------------------------------------*/
  35. /*---------------------------------------------------------------------------*/
  36. /* Type declarations */
  37. /*---------------------------------------------------------------------------*/
  38. /*---------------------------------------------------------------------------*/
  39. /* Variable declarations */
  40. /*---------------------------------------------------------------------------*/
  41. /*---------------------------------------------------------------------------*/
  42. /* Macro declarations */
  43. /*---------------------------------------------------------------------------*/
  44. /**AutomaticStart*************************************************************/
  45. /*---------------------------------------------------------------------------*/
  46. /* Static function prototypes */
  47. /*---------------------------------------------------------------------------*/
  48. static int NodeStoreRecurAdd(DdManager *ddMgr, DdNode *f, int mode, int *supportids, char **varnames, int *outids, FILE *fp);
  49. static int NodeTextStoreAdd(DdManager *ddMgr, DdNode *f, int mode, int *supportids, char **varnames, int *outids, FILE *fp, int idf, int vf, int idT, int idE);
  50. /**AutomaticEnd***************************************************************/
  51. /*---------------------------------------------------------------------------*/
  52. /* Definition of exported functions */
  53. /*---------------------------------------------------------------------------*/
  54. /**Function********************************************************************
  55. Synopsis [Writes a dump file representing the argument ADD.]
  56. Description [Dumps the argument ADD to file. Dumping is done through
  57. Dddmp_cuddAddArrayStore, And a dummy array of 1 ADD root is
  58. used for this purpose.
  59. ]
  60. SideEffects [Nodes are temporarily removed from unique hash. They are
  61. re-linked after the store operation in a modified order.]
  62. SeeAlso [Dddmp_cuddAddLoad Dddmp_cuddAddArrayLoad]
  63. ******************************************************************************/
  64. int
  65. Dddmp_cuddAddStore (
  66. DdManager *ddMgr /* IN: DD Manager */,
  67. char *ddname /* IN: DD name (or NULL) */,
  68. DdNode *f /* IN: ADD root to be stored */,
  69. char **varnames /* IN: array of variable names (or NULL) */,
  70. int *auxids /* IN: array of converted var ids */,
  71. int mode /* IN: storing mode selector */,
  72. Dddmp_VarInfoType varinfo /* IN: extra info for variables in text mode */,
  73. char *fname /* IN: File name */,
  74. FILE *fp /* IN: File pointer to the store file */
  75. )
  76. {
  77. int retValue;
  78. DdNode *tmpArray[1];
  79. tmpArray[0] = f;
  80. retValue = Dddmp_cuddAddArrayStore (ddMgr, ddname, 1, tmpArray, NULL,
  81. varnames, auxids, mode, varinfo, fname, fp);
  82. return (retValue);
  83. }
  84. /**Function********************************************************************
  85. Synopsis [Writes a dump file representing the argument Array of ADDs.]
  86. Description [Dumps the argument array of ADDs to file. Dumping is
  87. either in text or binary form. see the corresponding BDD dump
  88. function for further details.
  89. ]
  90. SideEffects [Nodes are temporarily removed from the unique hash
  91. table. They are re-linked after the store operation in a
  92. modified order.
  93. ]
  94. SeeAlso [Dddmp_cuddAddStore, Dddmp_cuddAddLoad,
  95. Dddmp_cuddAddArrayLoad]
  96. ******************************************************************************/
  97. int
  98. Dddmp_cuddAddArrayStore (
  99. DdManager *ddMgr /* IN: DD Manager */,
  100. char *ddname /* IN: DD name (or NULL) */,
  101. int nRoots /* IN: number of output BDD roots to be stored */,
  102. DdNode **f /* IN: array of ADD roots to be stored */,
  103. char **rootnames /* IN: array of root names (or NULL) */,
  104. char **varnames /* IN: array of variable names (or NULL) */,
  105. int *auxids /* IN: array of converted var IDs */,
  106. int mode /* IN: storing mode selector */,
  107. Dddmp_VarInfoType varinfo /* IN: extra info for variables in text mode */,
  108. char *fname /* IN: File name */,
  109. FILE *fp /* IN: File pointer to the store file */
  110. )
  111. {
  112. int retValue;
  113. #if 0
  114. #ifdef DDDMP_DEBUG
  115. #ifndef __alpha__
  116. int retValueBis;
  117. retValueBis = Cudd_DebugCheck (ddMgr);
  118. if (retValueBis == 1) {
  119. fprintf (stderr, "Inconsistency Found During ADD Store.\n");
  120. fflush (stderr);
  121. } else {
  122. if (retValueBis == CUDD_OUT_OF_MEM) {
  123. fprintf (stderr, "Out of Memory During ADD Store.\n");
  124. fflush (stderr);
  125. }
  126. }
  127. #endif
  128. #endif
  129. #endif
  130. retValue = DddmpCuddDdArrayStoreBdd (DDDMP_ADD, ddMgr, ddname, nRoots, f,
  131. rootnames, varnames, auxids, mode, varinfo, fname, fp);
  132. #if 0
  133. #ifdef DDDMP_DEBUG
  134. #ifndef __alpha__
  135. retValueBis = Cudd_DebugCheck (ddMgr);
  136. if (retValueBis == 1) {
  137. fprintf (stderr, "Inconsistency Found During ADD Store.\n");
  138. fflush (stderr);
  139. } else {
  140. if (retValueBis == CUDD_OUT_OF_MEM) {
  141. fprintf (stderr, "Out of Memory During ADD Store.\n");
  142. fflush (stderr);
  143. }
  144. }
  145. #endif
  146. #endif
  147. #endif
  148. return (retValue);
  149. }
  150. /*---------------------------------------------------------------------------*/
  151. /* Definition of internal functions */
  152. /*---------------------------------------------------------------------------*/
  153. /**Function********************************************************************
  154. Synopsis [Writes a dump file representing the argument Array of
  155. BDDs/ADDs.
  156. ]
  157. Description [Dumps the argument array of BDDs/ADDs to file. Internal
  158. function doing inner steps of store for BDDs and ADDs.
  159. ADD store is presently supported only with the text format.
  160. ]
  161. SideEffects [Nodes are temporarily removed from the unique hash
  162. table. They are re-linked after the store operation in a
  163. modified order.
  164. ]
  165. SeeAlso [Dddmp_cuddBddStore, Dddmp_cuddBddLoad,
  166. Dddmp_cuddBddArrayLoad
  167. ]
  168. ******************************************************************************/
  169. int
  170. DddmpCuddDdArrayStoreBdd (
  171. Dddmp_DecompType ddType /* IN: Selects the decomp type: BDD or ADD */,
  172. DdManager *ddMgr /* IN: DD Manager */,
  173. char *ddname /* IN: DD name (or NULL) */,
  174. int nRoots /* IN: number of output BDD roots to be stored */,
  175. DdNode **f /* IN: array of DD roots to be stored */,
  176. char **rootnames /* IN: array of root names (or NULL) */,
  177. char **varnames /* IN: array of variable names (or NULL) */,
  178. int *auxids /* IN: array of converted var IDs */,
  179. int mode /* IN: storing mode selector */,
  180. Dddmp_VarInfoType varinfo /* IN: extra info for variables in text mode */,
  181. char *fname /* IN: File name */,
  182. FILE *fp /* IN: File pointer to the store file */
  183. )
  184. {
  185. DdNode *support = NULL;
  186. DdNode *scan;
  187. int *ids = NULL;
  188. int *permids = NULL;
  189. int *invpermids = NULL;
  190. int *supportids = NULL;
  191. int *outids = NULL;
  192. char **outvarnames = NULL;
  193. int nVars = ddMgr->size;
  194. int nnodes;
  195. int retValue;
  196. int i, var;
  197. int fileToClose = 0;
  198. /*
  199. * Check DD Type and Mode
  200. */
  201. Dddmp_CheckAndGotoLabel (ddType==DDDMP_BDD,
  202. "Error writing to file: BDD Type.", failure);
  203. Dddmp_CheckAndGotoLabel (mode==DDDMP_MODE_BINARY,
  204. "Error writing to file: ADD Type with Binary Mode.", failure);
  205. /*
  206. * Check if File needs to be opened in the proper mode.
  207. */
  208. if (fp == NULL) {
  209. fp = fopen (fname, "w");
  210. Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.",
  211. failure);
  212. fileToClose = 1;
  213. }
  214. /*
  215. * Force binary mode if automatic.
  216. */
  217. switch (mode) {
  218. case DDDMP_MODE_TEXT:
  219. case DDDMP_MODE_BINARY:
  220. break;
  221. case DDDMP_MODE_DEFAULT:
  222. mode = DDDMP_MODE_BINARY;
  223. break;
  224. default:
  225. mode = DDDMP_MODE_BINARY;
  226. break;
  227. }
  228. /*
  229. * Alloc vectors for variable IDs, perm IDs and support IDs.
  230. * +1 to include a slot for terminals.
  231. */
  232. ids = DDDMP_ALLOC (int, nVars);
  233. Dddmp_CheckAndGotoLabel (ids==NULL, "Error allocating memory.", failure);
  234. permids = DDDMP_ALLOC (int, nVars);
  235. Dddmp_CheckAndGotoLabel (permids==NULL, "Error allocating memory.", failure);
  236. invpermids = DDDMP_ALLOC (int, nVars);
  237. Dddmp_CheckAndGotoLabel (invpermids==NULL, "Error allocating memory.",
  238. failure);
  239. supportids = DDDMP_ALLOC (int, nVars+1);
  240. Dddmp_CheckAndGotoLabel (supportids==NULL, "Error allocating memory.",
  241. failure);
  242. for (i=0; i<nVars; i++) {
  243. ids[i] = permids[i] = invpermids[i] = supportids[i] = (-1);
  244. }
  245. /* StQ */
  246. supportids[nVars] = -1;
  247. /*
  248. * Take the union of the supports of each output function.
  249. * skip NULL functions.
  250. * Set permids and invpermids of support variables to the proper values.
  251. */
  252. for (i=0; i<nRoots; i++) {
  253. if (f[i] == NULL) {
  254. continue;
  255. }
  256. support = Cudd_Support (ddMgr, f[i]);
  257. Dddmp_CheckAndGotoLabel (support==NULL, "NULL support returned.",
  258. failure);
  259. cuddRef (support);
  260. scan = support;
  261. while (!cuddIsConstant(scan)) {
  262. ids[scan->index] = scan->index;
  263. permids[scan->index] = ddMgr->perm[scan->index];
  264. invpermids[ddMgr->perm[scan->index]] = scan->index;
  265. scan = cuddT (scan);
  266. }
  267. Cudd_RecursiveDeref (ddMgr, support);
  268. }
  269. /* so that we do not try to free it in case of failure */
  270. support = NULL;
  271. /*
  272. * Set supportids to incremental (shrinked) values following the ordering.
  273. */
  274. for (i=0, var=0; i<nVars; i++) {
  275. if (invpermids[i] >= 0) {
  276. supportids[invpermids[i]] = var++;
  277. }
  278. }
  279. /* set a dummy id for terminal nodes */
  280. supportids[nVars] = var;
  281. /*
  282. * Select conversion array for extra var info
  283. */
  284. switch (mode) {
  285. case DDDMP_MODE_TEXT:
  286. switch (varinfo) {
  287. case DDDMP_VARIDS:
  288. outids = ids;
  289. break;
  290. case DDDMP_VARPERMIDS:
  291. outids = permids;
  292. break;
  293. case DDDMP_VARAUXIDS:
  294. outids = auxids;
  295. break;
  296. case DDDMP_VARNAMES:
  297. outvarnames = varnames;
  298. break;
  299. case DDDMP_VARDEFAULT:
  300. break;
  301. }
  302. break;
  303. case DDDMP_MODE_BINARY:
  304. outids = NULL;
  305. break;
  306. }
  307. /*
  308. * Number dd nodes and count them (numbering is from 1 to nnodes)
  309. */
  310. nnodes = DddmpNumberAddNodes (ddMgr, f, nRoots);
  311. /*
  312. * Start Header
  313. */
  314. #ifdef DDDMP_VERSION
  315. retValue = fprintf (fp, ".ver %s\n", DDDMP_VERSION);
  316. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  317. failure);
  318. #endif
  319. retValue = fprintf (fp, ".add\n");
  320. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  321. failure);
  322. retValue = fprintf (fp, ".mode %c\n", mode);
  323. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  324. failure);
  325. if (mode == DDDMP_MODE_TEXT) {
  326. retValue = fprintf (fp, ".varinfo %d\n", varinfo);
  327. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  328. failure);
  329. }
  330. if (ddname != NULL) {
  331. retValue = fprintf (fp, ".dd %s\n",ddname);
  332. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  333. failure);
  334. }
  335. retValue = fprintf (fp, ".nnodes %d\n", nnodes);
  336. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  337. failure);
  338. retValue = fprintf (fp, ".nvars %d\n", nVars);
  339. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  340. failure);
  341. retValue = fprintf (fp, ".nsuppvars %d\n", var);
  342. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  343. failure);
  344. /*------------ Write the Var Names by scanning the ids array -------------*/
  345. if (varnames != NULL) {
  346. retValue = fprintf (fp, ".suppvarnames");
  347. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  348. failure);
  349. for (i=0; i<nVars; i++) {
  350. if (ids[i] >= 0) {
  351. if (varnames[ids[i]] == NULL) {
  352. (void) fprintf (stderr,
  353. "DdStore Warning: null variable name. DUMMY%d generated\n", i);
  354. fflush (stderr);
  355. varnames[ids[i]] = DDDMP_ALLOC (char, 10);
  356. Dddmp_CheckAndGotoLabel (varnames[ids[i]] == NULL,
  357. "Error allocating memory.", failure);
  358. sprintf (varnames[ids[i]], "DUMMY%d", i);
  359. }
  360. retValue = fprintf (fp, " %s", varnames[ids[i]]);
  361. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  362. failure);
  363. }
  364. }
  365. retValue = fprintf (fp, "\n");
  366. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  367. failure);
  368. }
  369. /*--------- Write the Var SUPPORT Names by scanning the ids array ---------*/
  370. if (varnames != NULL) {
  371. retValue = fprintf (fp, ".orderedvarnames");
  372. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  373. failure);
  374. for (i=0; i<nVars; i++) {
  375. if (varnames[ddMgr->invperm[i]] == NULL) {
  376. (void) fprintf (stderr,
  377. "DdStore Warning: null variable name. DUMMY%d generated\n", i);
  378. fflush (stderr);
  379. varnames[ddMgr->invperm[i]] = DDDMP_ALLOC (char, 10);
  380. Dddmp_CheckAndGotoLabel (varnames[ddMgr->invperm[i]] == NULL,
  381. "Error allocating memory.", failure);
  382. sprintf (varnames[ddMgr->invperm[i]], "DUMMY%d", i);
  383. }
  384. retValue = fprintf (fp, " %s", varnames[ddMgr->invperm[i]]);
  385. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  386. failure);
  387. }
  388. retValue = fprintf (fp, "\n");
  389. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  390. failure);
  391. }
  392. /*------------ Write the var ids by scanning the ids array ---------------*/
  393. retValue = fprintf (fp, ".ids");
  394. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  395. failure);
  396. for (i=0; i<nVars; i++) {
  397. if (ids[i] >= 0) {
  398. retValue = fprintf (fp, " %d", i);
  399. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  400. failure);
  401. }
  402. }
  403. retValue = fprintf (fp, "\n");
  404. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  405. failure);
  406. /*
  407. * Write the var permids by scanning the permids array.
  408. */
  409. retValue = fprintf (fp, ".permids");
  410. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  411. failure);
  412. for (i = 0; i < nVars; i++) {
  413. if (permids[i] >= 0) {
  414. retValue = fprintf (fp, " %d", permids[i]);
  415. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  416. failure);
  417. }
  418. }
  419. retValue = fprintf (fp, "\n");
  420. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  421. failure);
  422. if (auxids != NULL) {
  423. /*
  424. * Write the var auxids by scanning the ids array.
  425. */
  426. retValue = fprintf (fp, ".auxids");
  427. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  428. failure);
  429. for (i = 0; i < nVars; i++) {
  430. if (ids[i] >= 0) {
  431. retValue = fprintf (fp, " %d", auxids[i]);
  432. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  433. failure);
  434. }
  435. }
  436. retValue = fprintf (fp, "\n");
  437. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  438. failure);
  439. }
  440. /*
  441. * Write the roots info.
  442. */
  443. retValue = fprintf (fp, ".nroots %d\n", nRoots);
  444. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  445. failure);
  446. if (rootnames != NULL) {
  447. /*
  448. * Write the root names.
  449. */
  450. retValue = fprintf (fp, ".rootnames");
  451. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  452. failure);
  453. for (i = 0; i < nRoots; i++) {
  454. if (rootnames[i] == NULL) {
  455. (void) fprintf (stderr,
  456. "DdStore Warning: null variable name. ROOT%d generated\n",i);
  457. fflush (stderr);
  458. rootnames[i] = DDDMP_ALLOC(char,10);
  459. Dddmp_CheckAndGotoLabel (rootnames[i]==NULL,
  460. "Error writing to file.", failure);
  461. sprintf(rootnames[ids[i]], "ROOT%d",i);
  462. }
  463. retValue = fprintf (fp, " %s", rootnames[i]);
  464. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  465. failure);
  466. }
  467. retValue = fprintf (fp, "\n");
  468. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  469. failure);
  470. }
  471. retValue = fprintf (fp, ".rootids");
  472. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  473. failure);
  474. /*
  475. * Write BDD indexes of function roots.
  476. * Use negative integers for complemented edges.
  477. */
  478. for (i = 0; i < nRoots; i++) {
  479. if (f[i] == NULL) {
  480. (void) fprintf (stderr, "DdStore Warning: %d-th root is NULL\n",i);
  481. fflush (stderr);
  482. retValue = fprintf (fp, " 0");
  483. }
  484. if (Cudd_IsComplement(f[i])) {
  485. retValue = fprintf (fp, " -%d",
  486. DddmpReadNodeIndexAdd (Cudd_Regular (f[i])));
  487. } else {
  488. retValue = fprintf (fp, " %d",
  489. DddmpReadNodeIndexAdd (Cudd_Regular (f[i])));
  490. }
  491. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  492. failure);
  493. }
  494. retValue = fprintf (fp, "\n");
  495. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  496. failure);
  497. retValue = fprintf (fp, ".nodes\n");
  498. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  499. failure);
  500. /*
  501. * END HEADER
  502. */
  503. /*
  504. * Call the function that really gets the job done.
  505. */
  506. for (i = 0; i < nRoots; i++) {
  507. if (f[i] != NULL) {
  508. retValue = NodeStoreRecurAdd (ddMgr, Cudd_Regular(f[i]),
  509. mode, supportids, outvarnames, outids, fp);
  510. Dddmp_CheckAndGotoLabel (retValue==DDDMP_FAILURE,
  511. "Error writing to file.", failure);
  512. }
  513. }
  514. /*
  515. * Write trailer and return.
  516. */
  517. retValue = fprintf (fp, ".end\n");
  518. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  519. failure);
  520. if (fileToClose) {
  521. fclose (fp);
  522. }
  523. DddmpUnnumberAddNodes (ddMgr, f, nRoots);
  524. DDDMP_FREE (ids);
  525. DDDMP_FREE (permids);
  526. DDDMP_FREE (invpermids);
  527. DDDMP_FREE (supportids);
  528. return (DDDMP_SUCCESS);
  529. failure:
  530. if (ids != NULL) {
  531. DDDMP_FREE (ids);
  532. }
  533. if (permids != NULL) {
  534. DDDMP_FREE (permids);
  535. }
  536. if (invpermids != NULL) {
  537. DDDMP_FREE (invpermids);
  538. }
  539. if (supportids != NULL) {
  540. DDDMP_FREE (supportids);
  541. }
  542. if (support != NULL) {
  543. Cudd_RecursiveDeref (ddMgr, support);
  544. }
  545. return (DDDMP_FAILURE);
  546. }
  547. /*---------------------------------------------------------------------------*/
  548. /* Definition of static functions */
  549. /*---------------------------------------------------------------------------*/
  550. /**Function********************************************************************
  551. Synopsis [Performs the recursive step of Dddmp_bddStore.]
  552. Description [Stores a node to file in either test or binary mode.<l>
  553. In text mode a node is represented (on a text line basis) as
  554. <UL>
  555. <LI> node-index \[var-extrainfo\] var-index Then-index Else-index
  556. </UL>
  557. where all indexes are integer numbers and var-extrainfo
  558. (optional redundant field) is either an integer or a string
  559. (variable name). Node-index is redundant (due to the node
  560. ordering) but we keep it for readability.<p>
  561. In binary mode nodes are represented as a sequence of bytes,
  562. representing var-index, Then-index, and Else-index in an
  563. optimized way. Only the first byte (code) is mandatory.
  564. Integer indexes are represented in absolute or relative mode,
  565. where relative means offset wrt. a Then/Else node info.
  566. Suppose Var(NodeId), Then(NodeId) and Else(NodeId) represent
  567. infos about a given node.<p>
  568. The generic "NodeId" node is stored as
  569. <UL>
  570. <LI> code-byte
  571. <LI> \[var-info\]
  572. <LI> \[Then-info\]
  573. <LI> \[Else-info\]
  574. </UL>
  575. where code-byte contains bit fields
  576. <UL>
  577. <LI>Unused : 1 bit
  578. <LI>Variable: 2 bits, one of the following codes
  579. <UL>
  580. <LI>DDDMP_ABSOLUTE_ID var-info = Var(NodeId) follows
  581. <LI>DDDMP_RELATIVE_ID Var(NodeId) is represented in relative form as
  582. var-info = Min(Var(Then(NodeId)),Var(Else(NodeId))) -Var(NodeId)
  583. <LI>DDDMP_RELATIVE_1 No var-info follows, because
  584. Var(NodeId) = Min(Var(Then(NodeId)),Var(Else(NodeId)))-1
  585. <LI>DDDMP_TERMINAL Node is a terminal, no var info required
  586. </UL>
  587. <LI>T : 2 bits, with codes similar to V
  588. <UL>
  589. <LI>DDDMP_ABSOLUTE_ID Then-info = Then(NodeId) follows
  590. <LI>DDDMP_RELATIVE_ID Then(NodeId) is represented in relative form as
  591. Then-info = Nodeid-Then(NodeId)
  592. <LI>DDDMP_RELATIVE_1 No info on Then(NodeId) follows, because
  593. Then(NodeId) = NodeId-1
  594. <LI>DDDMP_TERMINAL Then Node is a terminal, no info required (for BDDs)
  595. </UL>
  596. <LI>Ecompl : 1 bit, if 1 means complemented edge
  597. <LI>E : 2 bits, with codes and meanings as for the Then edge
  598. </UL>
  599. var-info, Then-info, Else-info (if required) are represented as unsigned
  600. integer values on a sufficient set of bytes (MSByte first).
  601. ]
  602. SideEffects [None]
  603. SeeAlso []
  604. ******************************************************************************/
  605. static int
  606. NodeStoreRecurAdd (
  607. DdManager *ddMgr /* IN: DD Manager */,
  608. DdNode *f /* IN: DD node to be stored */,
  609. int mode /* IN: store mode */,
  610. int *supportids /* IN: internal ids for variables */,
  611. char **varnames /* IN: names of variables: to be stored with nodes */,
  612. int *outids /* IN: output ids for variables */,
  613. FILE *fp /* IN: store file */
  614. )
  615. {
  616. DdNode *T = NULL;
  617. DdNode *E = NULL;
  618. int idf = (-1);
  619. int idT = (-1);
  620. int idE = (-1);
  621. int vf = (-1);
  622. int retValue;
  623. T = E = NULL;
  624. idf = idT = idE = (-1);
  625. #ifdef DDDMP_DEBUG
  626. assert(!Cudd_IsComplement(f));
  627. assert(f!=NULL);
  628. assert(supportids!=NULL);
  629. #endif
  630. /* If already visited, nothing to do. */
  631. if (DddmpVisitedAdd (f)) {
  632. return (DDDMP_SUCCESS);
  633. }
  634. /* Mark node as visited. */
  635. DddmpSetVisitedAdd (f);
  636. if (Cudd_IsConstant(f)) {
  637. /* Check for special case: don't recur */
  638. idf = DddmpReadNodeIndexAdd (f);
  639. } else {
  640. #ifdef DDDMP_DEBUG
  641. /* BDDs! Only one constant supported */
  642. assert (!cuddIsConstant(f));
  643. #endif
  644. /*
  645. * Recursive call for Then edge
  646. */
  647. T = cuddT(f);
  648. #ifdef DDDMP_DEBUG
  649. /* ROBDDs! No complemented Then edge */
  650. assert (!Cudd_IsComplement(T));
  651. #endif
  652. /* recur */
  653. retValue = NodeStoreRecurAdd (ddMgr, T, mode, supportids, varnames, outids,
  654. fp);
  655. if (retValue != DDDMP_SUCCESS) {
  656. return (retValue);
  657. }
  658. /*
  659. * Recursive call for Else edge
  660. */
  661. E = Cudd_Regular (cuddE (f));
  662. retValue = NodeStoreRecurAdd (ddMgr, E, mode, supportids, varnames, outids,
  663. fp);
  664. if (retValue != DDDMP_SUCCESS) {
  665. return (retValue);
  666. }
  667. /*
  668. * Obtain nodeids and variable ids of f, T, E
  669. */
  670. idf = DddmpReadNodeIndexAdd (f);
  671. vf = f->index;
  672. idT = DddmpReadNodeIndexAdd (T);
  673. idE = DddmpReadNodeIndexAdd (E);
  674. }
  675. retValue = NodeTextStoreAdd (ddMgr, f, mode, supportids, varnames,
  676. outids, fp, idf, vf, idT, idE);
  677. return (retValue);
  678. }
  679. /**Function********************************************************************
  680. Synopsis [Store One Single Node in Text Format.]
  681. Description [Store 1 0 0 for the terminal node.
  682. Store id, left child pointer, right pointer for all the other nodes.
  683. ]
  684. SideEffects [None]
  685. SeeAlso [NodeBinaryStore]
  686. ******************************************************************************/
  687. static int
  688. NodeTextStoreAdd (
  689. DdManager *ddMgr /* IN: DD Manager */,
  690. DdNode *f /* IN: DD node to be stored */,
  691. int mode /* IN: store mode */,
  692. int *supportids /* IN: internal ids for variables */,
  693. char **varnames /* IN: names of variables: to be stored with nodes */,
  694. int *outids /* IN: output ids for variables */,
  695. FILE *fp /* IN: Store file */,
  696. int idf /* IN: index of the current node */,
  697. int vf /* IN: variable of the current node */,
  698. int idT /* IN: index of the Then node */,
  699. int idE /* IN: index of the Else node */
  700. )
  701. {
  702. int retValue;
  703. (void) mode; /* avoid warning */
  704. /*
  705. * Check for Constant
  706. */
  707. if (Cudd_IsConstant(f)) {
  708. if (f == Cudd_ReadOne(ddMgr)) {
  709. if ((varnames != NULL) || (outids != NULL)) {
  710. retValue = fprintf (fp, "%d T 1 0 0\n", idf);
  711. } else {
  712. retValue = fprintf (fp, "%d 1 0 0\n", idf);
  713. }
  714. if (retValue == EOF) {
  715. return (DDDMP_FAILURE);
  716. } else {
  717. return (DDDMP_SUCCESS);
  718. }
  719. }
  720. if (f == Cudd_ReadZero(ddMgr)) {
  721. if ((varnames != NULL) || (outids != NULL)) {
  722. retValue = fprintf (fp, "%d T 0 0 0\n", idf);
  723. } else {
  724. retValue = fprintf (fp, "%d 0 0 0\n", idf);
  725. }
  726. if (retValue == EOF) {
  727. return (DDDMP_FAILURE);
  728. } else {
  729. return (DDDMP_SUCCESS);
  730. }
  731. }
  732. /*
  733. * A constant node different from 1: an ADD constant
  734. */
  735. if ((varnames != NULL) || (outids != NULL)) {
  736. retValue = fprintf (fp, "%d T %g 0 0\n",idf,Cudd_V(f));
  737. } else {
  738. retValue = fprintf (fp, "%d %g 0 0\n",idf, Cudd_V(f));
  739. }
  740. if (retValue == EOF) {
  741. return (DDDMP_FAILURE);
  742. } else {
  743. return (DDDMP_SUCCESS);
  744. }
  745. }
  746. /*
  747. * ... Not A Constant
  748. */
  749. if (Cudd_IsComplement (cuddE(f))) {
  750. idE = -idE;
  751. }
  752. if (varnames != NULL) {
  753. retValue = fprintf (fp, "%d %s %d %d %d\n",
  754. idf, varnames[vf], supportids[vf], idT, idE);
  755. if (retValue == EOF) {
  756. return (DDDMP_FAILURE);
  757. } else {
  758. return (DDDMP_SUCCESS);
  759. }
  760. }
  761. if (outids != NULL) {
  762. retValue = fprintf (fp, "%d %d %d %d %d\n",
  763. idf, outids[vf], supportids[vf], idT, idE);
  764. if (retValue == EOF) {
  765. return (DDDMP_FAILURE);
  766. } else {
  767. return (DDDMP_SUCCESS);
  768. }
  769. }
  770. retValue = fprintf (fp, "%d %d %d %d\n",
  771. idf, supportids[vf], idT, idE);
  772. if (retValue == EOF) {
  773. return (DDDMP_FAILURE);
  774. } else {
  775. return (DDDMP_SUCCESS);
  776. }
  777. }