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.

1389 lines
43 KiB

  1. /**CFile***********************************************************************
  2. FileName [cuddExport.c]
  3. PackageName [cudd]
  4. Synopsis [Export functions.]
  5. Description [External procedures included in this module:
  6. <ul>
  7. <li> Cudd_DumpBlif()
  8. <li> Cudd_DumpBlifBody()
  9. <li> Cudd_DumpDot()
  10. <li> Cudd_DumpDaVinci()
  11. <li> Cudd_DumpDDcal()
  12. <li> Cudd_DumpFactoredForm()
  13. </ul>
  14. Internal procedures included in this module:
  15. <ul>
  16. </ul>
  17. Static procedures included in this module:
  18. <ul>
  19. <li> ddDoDumpBlif()
  20. <li> ddDoDumpDaVinci()
  21. <li> ddDoDumpDDcal()
  22. <li> ddDoDumpFactoredForm()
  23. </ul>]
  24. Author [Fabio Somenzi]
  25. Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
  26. All rights reserved.
  27. Redistribution and use in source and binary forms, with or without
  28. modification, are permitted provided that the following conditions
  29. are met:
  30. Redistributions of source code must retain the above copyright
  31. notice, this list of conditions and the following disclaimer.
  32. Redistributions in binary form must reproduce the above copyright
  33. notice, this list of conditions and the following disclaimer in the
  34. documentation and/or other materials provided with the distribution.
  35. Neither the name of the University of Colorado nor the names of its
  36. contributors may be used to endorse or promote products derived from
  37. this software without specific prior written permission.
  38. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  39. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  40. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  41. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  42. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  43. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  44. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  45. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  46. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  47. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  48. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  49. POSSIBILITY OF SUCH DAMAGE.]
  50. ******************************************************************************/
  51. #include "util.h"
  52. #include "cuddInt.h"
  53. /*---------------------------------------------------------------------------*/
  54. /* Constant declarations */
  55. /*---------------------------------------------------------------------------*/
  56. /*---------------------------------------------------------------------------*/
  57. /* Stucture declarations */
  58. /*---------------------------------------------------------------------------*/
  59. /*---------------------------------------------------------------------------*/
  60. /* Type declarations */
  61. /*---------------------------------------------------------------------------*/
  62. /*---------------------------------------------------------------------------*/
  63. /* Variable declarations */
  64. /*---------------------------------------------------------------------------*/
  65. #ifndef lint
  66. static char rcsid[] DD_UNUSED = "$Id: cuddExport.c,v 1.23 2012/02/05 01:07:18 fabio Exp $";
  67. #endif
  68. /*---------------------------------------------------------------------------*/
  69. /* Macro declarations */
  70. /*---------------------------------------------------------------------------*/
  71. /**AutomaticStart*************************************************************/
  72. /*---------------------------------------------------------------------------*/
  73. /* Static function prototypes */
  74. /*---------------------------------------------------------------------------*/
  75. static int ddDoDumpBlif (DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, int mv);
  76. static int ddDoDumpDaVinci (DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, ptruint mask);
  77. static int ddDoDumpDDcal (DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, ptruint mask);
  78. static int ddDoDumpFactoredForm (DdManager *dd, DdNode *f, FILE *fp, char **names);
  79. /**AutomaticEnd***************************************************************/
  80. /*---------------------------------------------------------------------------*/
  81. /* Definition of exported functions */
  82. /*---------------------------------------------------------------------------*/
  83. /**Function********************************************************************
  84. Synopsis [Writes a blif file representing the argument BDDs.]
  85. Description [Writes a blif file representing the argument BDDs as a
  86. network of multiplexers. One multiplexer is written for each BDD
  87. node. It returns 1 in case of success; 0 otherwise (e.g.,
  88. out-of-memory, file system full, or an ADD with constants different
  89. from 0 and 1). Cudd_DumpBlif does not close the file: This is the
  90. caller responsibility. Cudd_DumpBlif uses a minimal unique subset of
  91. the hexadecimal address of a node as name for it. If the argument
  92. inames is non-null, it is assumed to hold the pointers to the names
  93. of the inputs. Similarly for onames.]
  94. SideEffects [None]
  95. SeeAlso [Cudd_DumpBlifBody Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal
  96. Cudd_DumpDaVinci Cudd_DumpFactoredForm]
  97. ******************************************************************************/
  98. int
  99. Cudd_DumpBlif(
  100. DdManager * dd /* manager */,
  101. int n /* number of output nodes to be dumped */,
  102. DdNode ** f /* array of output nodes to be dumped */,
  103. char ** inames /* array of input names (or NULL) */,
  104. char ** onames /* array of output names (or NULL) */,
  105. char * mname /* model name (or NULL) */,
  106. FILE * fp /* pointer to the dump file */,
  107. int mv /* 0: blif, 1: blif-MV */)
  108. {
  109. DdNode *support = NULL;
  110. DdNode *scan;
  111. int *sorted = NULL;
  112. int nvars = dd->size;
  113. int retval;
  114. int i;
  115. /* Build a bit array with the support of f. */
  116. sorted = ALLOC(int,nvars);
  117. if (sorted == NULL) {
  118. dd->errorCode = CUDD_MEMORY_OUT;
  119. goto failure;
  120. }
  121. for (i = 0; i < nvars; i++) sorted[i] = 0;
  122. /* Take the union of the supports of each output function. */
  123. support = Cudd_VectorSupport(dd,f,n);
  124. if (support == NULL) goto failure;
  125. cuddRef(support);
  126. scan = support;
  127. while (!cuddIsConstant(scan)) {
  128. sorted[scan->index] = 1;
  129. scan = cuddT(scan);
  130. }
  131. Cudd_RecursiveDeref(dd,support);
  132. support = NULL; /* so that we do not try to free it in case of failure */
  133. /* Write the header (.model .inputs .outputs). */
  134. if (mname == NULL) {
  135. retval = fprintf(fp,".model DD\n.inputs");
  136. } else {
  137. retval = fprintf(fp,".model %s\n.inputs",mname);
  138. }
  139. if (retval == EOF) {
  140. FREE(sorted);
  141. return(0);
  142. }
  143. /* Write the input list by scanning the support array. */
  144. for (i = 0; i < nvars; i++) {
  145. if (sorted[i]) {
  146. if (inames == NULL) {
  147. retval = fprintf(fp," %d", i);
  148. } else {
  149. retval = fprintf(fp," %s", inames[i]);
  150. }
  151. if (retval == EOF) goto failure;
  152. }
  153. }
  154. FREE(sorted);
  155. sorted = NULL;
  156. /* Write the .output line. */
  157. retval = fprintf(fp,"\n.outputs");
  158. if (retval == EOF) goto failure;
  159. for (i = 0; i < n; i++) {
  160. if (onames == NULL) {
  161. retval = fprintf(fp," f%d", i);
  162. } else {
  163. retval = fprintf(fp," %s", onames[i]);
  164. }
  165. if (retval == EOF) goto failure;
  166. }
  167. retval = fprintf(fp,"\n");
  168. if (retval == EOF) goto failure;
  169. retval = Cudd_DumpBlifBody(dd, n, f, inames, onames, fp, mv);
  170. if (retval == 0) goto failure;
  171. /* Write trailer and return. */
  172. retval = fprintf(fp,".end\n");
  173. if (retval == EOF) goto failure;
  174. return(1);
  175. failure:
  176. if (sorted != NULL) FREE(sorted);
  177. if (support != NULL) Cudd_RecursiveDeref(dd,support);
  178. return(0);
  179. } /* end of Cudd_DumpBlif */
  180. /**Function********************************************************************
  181. Synopsis [Writes a blif body representing the argument BDDs.]
  182. Description [Writes a blif body representing the argument BDDs as a
  183. network of multiplexers. No header (.model, .inputs, and .outputs) and
  184. footer (.end) are produced by this function. One multiplexer is written
  185. for each BDD node. It returns 1 in case of success; 0 otherwise (e.g.,
  186. out-of-memory, file system full, or an ADD with constants different
  187. from 0 and 1). Cudd_DumpBlifBody does not close the file: This is the
  188. caller responsibility. Cudd_DumpBlifBody uses a minimal unique subset of
  189. the hexadecimal address of a node as name for it. If the argument
  190. inames is non-null, it is assumed to hold the pointers to the names
  191. of the inputs. Similarly for onames. This function prints out only
  192. .names part.]
  193. SideEffects [None]
  194. SeeAlso [Cudd_DumpBlif Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal
  195. Cudd_DumpDaVinci Cudd_DumpFactoredForm]
  196. ******************************************************************************/
  197. int
  198. Cudd_DumpBlifBody(
  199. DdManager * dd /* manager */,
  200. int n /* number of output nodes to be dumped */,
  201. DdNode ** f /* array of output nodes to be dumped */,
  202. char ** inames /* array of input names (or NULL) */,
  203. char ** onames /* array of output names (or NULL) */,
  204. FILE * fp /* pointer to the dump file */,
  205. int mv /* 0: blif, 1: blif-MV */)
  206. {
  207. st_table *visited = NULL;
  208. int retval;
  209. int i;
  210. /* Initialize symbol table for visited nodes. */
  211. visited = st_init_table(st_ptrcmp, st_ptrhash);
  212. if (visited == NULL) goto failure;
  213. /* Call the function that really gets the job done. */
  214. for (i = 0; i < n; i++) {
  215. retval = ddDoDumpBlif(dd,Cudd_Regular(f[i]),fp,visited,inames,mv);
  216. if (retval == 0) goto failure;
  217. }
  218. /* To account for the possible complement on the root,
  219. ** we put either a buffer or an inverter at the output of
  220. ** the multiplexer representing the top node.
  221. */
  222. for (i = 0; i < n; i++) {
  223. if (onames == NULL) {
  224. retval = fprintf(fp,
  225. #if SIZEOF_VOID_P == 8
  226. ".names %lx f%d\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), i);
  227. #else
  228. ".names %x f%d\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), i);
  229. #endif
  230. } else {
  231. retval = fprintf(fp,
  232. #if SIZEOF_VOID_P == 8
  233. ".names %lx %s\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), onames[i]);
  234. #else
  235. ".names %x %s\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), onames[i]);
  236. #endif
  237. }
  238. if (retval == EOF) goto failure;
  239. if (Cudd_IsComplement(f[i])) {
  240. retval = fprintf(fp,"%s0 1\n", mv ? ".def 0\n" : "");
  241. } else {
  242. retval = fprintf(fp,"%s1 1\n", mv ? ".def 0\n" : "");
  243. }
  244. if (retval == EOF) goto failure;
  245. }
  246. st_free_table(visited);
  247. return(1);
  248. failure:
  249. if (visited != NULL) st_free_table(visited);
  250. return(0);
  251. } /* end of Cudd_DumpBlifBody */
  252. /**Function********************************************************************
  253. Synopsis [Writes a dot file representing the argument DDs.]
  254. Description [Writes a file representing the argument DDs in a format
  255. suitable for the graph drawing program dot.
  256. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory,
  257. file system full).
  258. Cudd_DumpDot does not close the file: This is the caller
  259. responsibility. Cudd_DumpDot uses a minimal unique subset of the
  260. hexadecimal address of a node as name for it.
  261. If the argument inames is non-null, it is assumed to hold the pointers
  262. to the names of the inputs. Similarly for onames.
  263. Cudd_DumpDot uses the following convention to draw arcs:
  264. <ul>
  265. <li> solid line: THEN arcs;
  266. <li> dotted line: complement arcs;
  267. <li> dashed line: regular ELSE arcs.
  268. </ul>
  269. The dot options are chosen so that the drawing fits on a letter-size
  270. sheet.
  271. ]
  272. SideEffects [None]
  273. SeeAlso [Cudd_DumpBlif Cudd_PrintDebug Cudd_DumpDDcal
  274. Cudd_DumpDaVinci Cudd_DumpFactoredForm]
  275. ******************************************************************************/
  276. int
  277. Cudd_DumpDot(
  278. DdManager * dd /* manager */,
  279. int n /* number of output nodes to be dumped */,
  280. DdNode ** f /* array of output nodes to be dumped */,
  281. char ** inames /* array of input names (or NULL) */,
  282. char ** onames /* array of output names (or NULL) */,
  283. FILE * fp /* pointer to the dump file */)
  284. {
  285. DdNode *support = NULL;
  286. DdNode *scan;
  287. int *sorted = NULL;
  288. int nvars = dd->size;
  289. st_table *visited = NULL;
  290. st_generator *gen = NULL;
  291. int retval;
  292. int i, j;
  293. int slots;
  294. DdNodePtr *nodelist;
  295. long refAddr, diff, mask;
  296. /* Build a bit array with the support of f. */
  297. sorted = ALLOC(int,nvars);
  298. if (sorted == NULL) {
  299. dd->errorCode = CUDD_MEMORY_OUT;
  300. goto failure;
  301. }
  302. for (i = 0; i < nvars; i++) sorted[i] = 0;
  303. /* Take the union of the supports of each output function. */
  304. support = Cudd_VectorSupport(dd,f,n);
  305. if (support == NULL) goto failure;
  306. cuddRef(support);
  307. scan = support;
  308. while (!cuddIsConstant(scan)) {
  309. sorted[scan->index] = 1;
  310. scan = cuddT(scan);
  311. }
  312. Cudd_RecursiveDeref(dd,support);
  313. support = NULL; /* so that we do not try to free it in case of failure */
  314. /* Initialize symbol table for visited nodes. */
  315. visited = st_init_table(st_ptrcmp, st_ptrhash);
  316. if (visited == NULL) goto failure;
  317. /* Collect all the nodes of this DD in the symbol table. */
  318. for (i = 0; i < n; i++) {
  319. retval = cuddCollectNodes(Cudd_Regular(f[i]),visited);
  320. if (retval == 0) goto failure;
  321. }
  322. /* Find how many most significant hex digits are identical
  323. ** in the addresses of all the nodes. Build a mask based
  324. ** on this knowledge, so that digits that carry no information
  325. ** will not be printed. This is done in two steps.
  326. ** 1. We scan the symbol table to find the bits that differ
  327. ** in at least 2 addresses.
  328. ** 2. We choose one of the possible masks. There are 8 possible
  329. ** masks for 32-bit integer, and 16 possible masks for 64-bit
  330. ** integers.
  331. */
  332. /* Find the bits that are different. */
  333. refAddr = (long) Cudd_Regular(f[0]);
  334. diff = 0;
  335. gen = st_init_gen(visited);
  336. if (gen == NULL) goto failure;
  337. while (st_gen(gen, &scan, NULL)) {
  338. diff |= refAddr ^ (long) scan;
  339. }
  340. st_free_gen(gen); gen = NULL;
  341. /* Choose the mask. */
  342. for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) {
  343. mask = (1 << i) - 1;
  344. if (diff <= mask) break;
  345. }
  346. /* Write the header and the global attributes. */
  347. retval = fprintf(fp,"digraph \"DD\" {\n");
  348. if (retval == EOF) return(0);
  349. retval = fprintf(fp,
  350. "size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n");
  351. if (retval == EOF) return(0);
  352. /* Write the input name subgraph by scanning the support array. */
  353. retval = fprintf(fp,"{ node [shape = plaintext];\n");
  354. if (retval == EOF) goto failure;
  355. retval = fprintf(fp," edge [style = invis];\n");
  356. if (retval == EOF) goto failure;
  357. /* We use a name ("CONST NODES") with an embedded blank, because
  358. ** it is unlikely to appear as an input name.
  359. */
  360. retval = fprintf(fp," \"CONST NODES\" [style = invis];\n");
  361. if (retval == EOF) goto failure;
  362. for (i = 0; i < nvars; i++) {
  363. if (sorted[dd->invperm[i]]) {
  364. if (inames == NULL || inames[dd->invperm[i]] == NULL) {
  365. retval = fprintf(fp,"\" %d \" -> ", dd->invperm[i]);
  366. } else {
  367. retval = fprintf(fp,"\" %s \" -> ", inames[dd->invperm[i]]);
  368. }
  369. if (retval == EOF) goto failure;
  370. }
  371. }
  372. retval = fprintf(fp,"\"CONST NODES\"; \n}\n");
  373. if (retval == EOF) goto failure;
  374. /* Write the output node subgraph. */
  375. retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n");
  376. if (retval == EOF) goto failure;
  377. for (i = 0; i < n; i++) {
  378. if (onames == NULL) {
  379. retval = fprintf(fp,"\"F%d\"", i);
  380. } else {
  381. retval = fprintf(fp,"\" %s \"", onames[i]);
  382. }
  383. if (retval == EOF) goto failure;
  384. if (i == n - 1) {
  385. retval = fprintf(fp,"; }\n");
  386. } else {
  387. retval = fprintf(fp," -> ");
  388. }
  389. if (retval == EOF) goto failure;
  390. }
  391. /* Write rank info: All nodes with the same index have the same rank. */
  392. for (i = 0; i < nvars; i++) {
  393. if (sorted[dd->invperm[i]]) {
  394. retval = fprintf(fp,"{ rank = same; ");
  395. if (retval == EOF) goto failure;
  396. if (inames == NULL || inames[dd->invperm[i]] == NULL) {
  397. retval = fprintf(fp,"\" %d \";\n", dd->invperm[i]);
  398. } else {
  399. retval = fprintf(fp,"\" %s \";\n", inames[dd->invperm[i]]);
  400. }
  401. if (retval == EOF) goto failure;
  402. nodelist = dd->subtables[i].nodelist;
  403. slots = dd->subtables[i].slots;
  404. for (j = 0; j < slots; j++) {
  405. scan = nodelist[j];
  406. while (scan != NULL) {
  407. if (st_is_member(visited,(char *) scan)) {
  408. retval = fprintf(fp,"\"%p\";\n",
  409. (void *) ((mask & (ptrint) scan) /
  410. sizeof(DdNode)));
  411. if (retval == EOF) goto failure;
  412. }
  413. scan = scan->next;
  414. }
  415. }
  416. retval = fprintf(fp,"}\n");
  417. if (retval == EOF) goto failure;
  418. }
  419. }
  420. /* All constants have the same rank. */
  421. retval = fprintf(fp,
  422. "{ rank = same; \"CONST NODES\";\n{ node [shape = box]; ");
  423. if (retval == EOF) goto failure;
  424. nodelist = dd->constants.nodelist;
  425. slots = dd->constants.slots;
  426. for (j = 0; j < slots; j++) {
  427. scan = nodelist[j];
  428. while (scan != NULL) {
  429. if (st_is_member(visited,(char *) scan)) {
  430. retval = fprintf(fp,"\"%p\";\n",
  431. (void *) ((mask & (ptrint) scan) / sizeof(DdNode)));
  432. if (retval == EOF) goto failure;
  433. }
  434. scan = scan->next;
  435. }
  436. }
  437. retval = fprintf(fp,"}\n}\n");
  438. if (retval == EOF) goto failure;
  439. /* Write edge info. */
  440. /* Edges from the output nodes. */
  441. for (i = 0; i < n; i++) {
  442. if (onames == NULL) {
  443. retval = fprintf(fp,"\"F%d\"", i);
  444. } else {
  445. retval = fprintf(fp,"\" %s \"", onames[i]);
  446. }
  447. if (retval == EOF) goto failure;
  448. /* Account for the possible complement on the root. */
  449. if (Cudd_IsComplement(f[i])) {
  450. retval = fprintf(fp," -> \"%p\" [style = dotted];\n",
  451. (void *) ((mask & (ptrint) f[i]) / sizeof(DdNode)));
  452. } else {
  453. retval = fprintf(fp," -> \"%p\" [style = solid];\n",
  454. (void *) ((mask & (ptrint) f[i]) / sizeof(DdNode)));
  455. }
  456. if (retval == EOF) goto failure;
  457. }
  458. /* Edges from internal nodes. */
  459. for (i = 0; i < nvars; i++) {
  460. if (sorted[dd->invperm[i]]) {
  461. nodelist = dd->subtables[i].nodelist;
  462. slots = dd->subtables[i].slots;
  463. for (j = 0; j < slots; j++) {
  464. scan = nodelist[j];
  465. while (scan != NULL) {
  466. if (st_is_member(visited,(char *) scan)) {
  467. retval = fprintf(fp,
  468. "\"%p\" -> \"%p\";\n",
  469. (void *) ((mask & (ptrint) scan) /
  470. sizeof(DdNode)),
  471. (void *) ((mask & (ptrint) cuddT(scan)) /
  472. sizeof(DdNode)));
  473. if (retval == EOF) goto failure;
  474. if (Cudd_IsComplement(cuddE(scan))) {
  475. retval = fprintf(fp,
  476. "\"%p\" -> \"%p\" [style = dotted];\n",
  477. (void *) ((mask & (ptrint) scan) /
  478. sizeof(DdNode)),
  479. (void *) ((mask & (ptrint) cuddE(scan)) /
  480. sizeof(DdNode)));
  481. } else {
  482. retval = fprintf(fp,
  483. "\"%p\" -> \"%p\" [style = dashed];\n",
  484. (void *) ((mask & (ptrint) scan) /
  485. sizeof(DdNode)),
  486. (void *) ((mask & (ptrint) cuddE(scan)) /
  487. sizeof(DdNode)));
  488. }
  489. if (retval == EOF) goto failure;
  490. }
  491. scan = scan->next;
  492. }
  493. }
  494. }
  495. }
  496. /* Write constant labels. */
  497. nodelist = dd->constants.nodelist;
  498. slots = dd->constants.slots;
  499. for (j = 0; j < slots; j++) {
  500. scan = nodelist[j];
  501. while (scan != NULL) {
  502. if (st_is_member(visited,(char *) scan)) {
  503. retval = fprintf(fp,"\"%p\" [label = \"%g\"];\n",
  504. (void *) ((mask & (ptrint) scan) / sizeof(DdNode)),
  505. cuddV(scan));
  506. if (retval == EOF) goto failure;
  507. }
  508. scan = scan->next;
  509. }
  510. }
  511. /* Write trailer and return. */
  512. retval = fprintf(fp,"}\n");
  513. if (retval == EOF) goto failure;
  514. st_free_table(visited);
  515. FREE(sorted);
  516. return(1);
  517. failure:
  518. if (sorted != NULL) FREE(sorted);
  519. if (support != NULL) Cudd_RecursiveDeref(dd,support);
  520. if (visited != NULL) st_free_table(visited);
  521. return(0);
  522. } /* end of Cudd_DumpDot */
  523. /**Function********************************************************************
  524. Synopsis [Writes a daVinci file representing the argument BDDs.]
  525. Description [Writes a daVinci file representing the argument BDDs.
  526. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or
  527. file system full). Cudd_DumpDaVinci does not close the file: This
  528. is the caller responsibility. Cudd_DumpDaVinci uses a minimal unique
  529. subset of the hexadecimal address of a node as name for it. If the
  530. argument inames is non-null, it is assumed to hold the pointers to
  531. the names of the inputs. Similarly for onames.]
  532. SideEffects [None]
  533. SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDDcal
  534. Cudd_DumpFactoredForm]
  535. ******************************************************************************/
  536. int
  537. Cudd_DumpDaVinci(
  538. DdManager * dd /* manager */,
  539. int n /* number of output nodes to be dumped */,
  540. DdNode ** f /* array of output nodes to be dumped */,
  541. char ** inames /* array of input names (or NULL) */,
  542. char ** onames /* array of output names (or NULL) */,
  543. FILE * fp /* pointer to the dump file */)
  544. {
  545. DdNode *support = NULL;
  546. DdNode *scan;
  547. st_table *visited = NULL;
  548. int retval;
  549. int i;
  550. st_generator *gen;
  551. ptruint refAddr, diff, mask;
  552. /* Initialize symbol table for visited nodes. */
  553. visited = st_init_table(st_ptrcmp, st_ptrhash);
  554. if (visited == NULL) goto failure;
  555. /* Collect all the nodes of this DD in the symbol table. */
  556. for (i = 0; i < n; i++) {
  557. retval = cuddCollectNodes(Cudd_Regular(f[i]),visited);
  558. if (retval == 0) goto failure;
  559. }
  560. /* Find how many most significant hex digits are identical
  561. ** in the addresses of all the nodes. Build a mask based
  562. ** on this knowledge, so that digits that carry no information
  563. ** will not be printed. This is done in two steps.
  564. ** 1. We scan the symbol table to find the bits that differ
  565. ** in at least 2 addresses.
  566. ** 2. We choose one of the possible masks. There are 8 possible
  567. ** masks for 32-bit integer, and 16 possible masks for 64-bit
  568. ** integers.
  569. */
  570. /* Find the bits that are different. */
  571. refAddr = (ptruint) Cudd_Regular(f[0]);
  572. diff = 0;
  573. gen = st_init_gen(visited);
  574. while (st_gen(gen, &scan, NULL)) {
  575. diff |= refAddr ^ (ptruint) scan;
  576. }
  577. st_free_gen(gen);
  578. /* Choose the mask. */
  579. for (i = 0; (unsigned) i < 8 * sizeof(ptruint); i += 4) {
  580. mask = (1 << i) - 1;
  581. if (diff <= mask) break;
  582. }
  583. st_free_table(visited);
  584. /* Initialize symbol table for visited nodes. */
  585. visited = st_init_table(st_ptrcmp, st_ptrhash);
  586. if (visited == NULL) goto failure;
  587. retval = fprintf(fp, "[");
  588. if (retval == EOF) goto failure;
  589. /* Call the function that really gets the job done. */
  590. for (i = 0; i < n; i++) {
  591. if (onames == NULL) {
  592. retval = fprintf(fp,
  593. "l(\"f%d\",n(\"root\",[a(\"OBJECT\",\"f%d\")],",
  594. i,i);
  595. } else {
  596. retval = fprintf(fp,
  597. "l(\"%s\",n(\"root\",[a(\"OBJECT\",\"%s\")],",
  598. onames[i], onames[i]);
  599. }
  600. if (retval == EOF) goto failure;
  601. retval = fprintf(fp, "[e(\"edge\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],",
  602. Cudd_IsComplement(f[i]) ? "red" : "blue");
  603. if (retval == EOF) goto failure;
  604. retval = ddDoDumpDaVinci(dd,Cudd_Regular(f[i]),fp,visited,inames,mask);
  605. if (retval == 0) goto failure;
  606. retval = fprintf(fp, ")]))%s", i == n-1 ? "" : ",");
  607. if (retval == EOF) goto failure;
  608. }
  609. /* Write trailer and return. */
  610. retval = fprintf(fp, "]\n");
  611. if (retval == EOF) goto failure;
  612. st_free_table(visited);
  613. return(1);
  614. failure:
  615. if (support != NULL) Cudd_RecursiveDeref(dd,support);
  616. if (visited != NULL) st_free_table(visited);
  617. return(0);
  618. } /* end of Cudd_DumpDaVinci */
  619. /**Function********************************************************************
  620. Synopsis [Writes a DDcal file representing the argument BDDs.]
  621. Description [Writes a DDcal file representing the argument BDDs.
  622. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or
  623. file system full). Cudd_DumpDDcal does not close the file: This
  624. is the caller responsibility. Cudd_DumpDDcal uses a minimal unique
  625. subset of the hexadecimal address of a node as name for it. If the
  626. argument inames is non-null, it is assumed to hold the pointers to
  627. the names of the inputs. Similarly for onames.]
  628. SideEffects [None]
  629. SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci
  630. Cudd_DumpFactoredForm]
  631. ******************************************************************************/
  632. int
  633. Cudd_DumpDDcal(
  634. DdManager * dd /* manager */,
  635. int n /* number of output nodes to be dumped */,
  636. DdNode ** f /* array of output nodes to be dumped */,
  637. char ** inames /* array of input names (or NULL) */,
  638. char ** onames /* array of output names (or NULL) */,
  639. FILE * fp /* pointer to the dump file */)
  640. {
  641. DdNode *support = NULL;
  642. DdNode *scan;
  643. int *sorted = NULL;
  644. int nvars = dd->size;
  645. st_table *visited = NULL;
  646. int retval;
  647. int i;
  648. st_generator *gen;
  649. ptruint refAddr, diff, mask;
  650. /* Initialize symbol table for visited nodes. */
  651. visited = st_init_table(st_ptrcmp, st_ptrhash);
  652. if (visited == NULL) goto failure;
  653. /* Collect all the nodes of this DD in the symbol table. */
  654. for (i = 0; i < n; i++) {
  655. retval = cuddCollectNodes(Cudd_Regular(f[i]),visited);
  656. if (retval == 0) goto failure;
  657. }
  658. /* Find how many most significant hex digits are identical
  659. ** in the addresses of all the nodes. Build a mask based
  660. ** on this knowledge, so that digits that carry no information
  661. ** will not be printed. This is done in two steps.
  662. ** 1. We scan the symbol table to find the bits that differ
  663. ** in at least 2 addresses.
  664. ** 2. We choose one of the possible masks. There are 8 possible
  665. ** masks for 32-bit integer, and 16 possible masks for 64-bit
  666. ** integers.
  667. */
  668. /* Find the bits that are different. */
  669. refAddr = (ptruint) Cudd_Regular(f[0]);
  670. diff = 0;
  671. gen = st_init_gen(visited);
  672. while (st_gen(gen, &scan, NULL)) {
  673. diff |= refAddr ^ (ptruint) scan;
  674. }
  675. st_free_gen(gen);
  676. /* Choose the mask. */
  677. for (i = 0; (unsigned) i < 8 * sizeof(ptruint); i += 4) {
  678. mask = (1 << i) - 1;
  679. if (diff <= mask) break;
  680. }
  681. st_free_table(visited);
  682. /* Build a bit array with the support of f. */
  683. sorted = ALLOC(int,nvars);
  684. if (sorted == NULL) {
  685. dd->errorCode = CUDD_MEMORY_OUT;
  686. goto failure;
  687. }
  688. for (i = 0; i < nvars; i++) sorted[i] = 0;
  689. /* Take the union of the supports of each output function. */
  690. support = Cudd_VectorSupport(dd,f,n);
  691. if (support == NULL) goto failure;
  692. cuddRef(support);
  693. scan = support;
  694. while (!cuddIsConstant(scan)) {
  695. sorted[scan->index] = 1;
  696. scan = cuddT(scan);
  697. }
  698. Cudd_RecursiveDeref(dd,support);
  699. support = NULL; /* so that we do not try to free it in case of failure */
  700. for (i = 0; i < nvars; i++) {
  701. if (sorted[dd->invperm[i]]) {
  702. if (inames == NULL || inames[dd->invperm[i]] == NULL) {
  703. retval = fprintf(fp,"v%d", dd->invperm[i]);
  704. } else {
  705. retval = fprintf(fp,"%s", inames[dd->invperm[i]]);
  706. }
  707. if (retval == EOF) goto failure;
  708. }
  709. retval = fprintf(fp,"%s", i == nvars - 1 ? "\n" : " * ");
  710. if (retval == EOF) goto failure;
  711. }
  712. FREE(sorted);
  713. sorted = NULL;
  714. /* Initialize symbol table for visited nodes. */
  715. visited = st_init_table(st_ptrcmp, st_ptrhash);
  716. if (visited == NULL) goto failure;
  717. /* Call the function that really gets the job done. */
  718. for (i = 0; i < n; i++) {
  719. retval = ddDoDumpDDcal(dd,Cudd_Regular(f[i]),fp,visited,inames,mask);
  720. if (retval == 0) goto failure;
  721. if (onames == NULL) {
  722. retval = fprintf(fp, "f%d = ", i);
  723. } else {
  724. retval = fprintf(fp, "%s = ", onames[i]);
  725. }
  726. if (retval == EOF) goto failure;
  727. retval = fprintf(fp, "n%p%s\n",
  728. (void *) (((ptruint) f[i] & mask) /
  729. (ptruint) sizeof(DdNode)),
  730. Cudd_IsComplement(f[i]) ? "'" : "");
  731. if (retval == EOF) goto failure;
  732. }
  733. /* Write trailer and return. */
  734. retval = fprintf(fp, "[");
  735. if (retval == EOF) goto failure;
  736. for (i = 0; i < n; i++) {
  737. if (onames == NULL) {
  738. retval = fprintf(fp, "f%d", i);
  739. } else {
  740. retval = fprintf(fp, "%s", onames[i]);
  741. }
  742. retval = fprintf(fp, "%s", i == n-1 ? "" : " ");
  743. if (retval == EOF) goto failure;
  744. }
  745. retval = fprintf(fp, "]\n");
  746. if (retval == EOF) goto failure;
  747. st_free_table(visited);
  748. return(1);
  749. failure:
  750. if (sorted != NULL) FREE(sorted);
  751. if (support != NULL) Cudd_RecursiveDeref(dd,support);
  752. if (visited != NULL) st_free_table(visited);
  753. return(0);
  754. } /* end of Cudd_DumpDDcal */
  755. /**Function********************************************************************
  756. Synopsis [Writes factored forms representing the argument BDDs.]
  757. Description [Writes factored forms representing the argument BDDs.
  758. The format of the factored form is the one used in the genlib files
  759. for technology mapping in sis. It returns 1 in case of success; 0
  760. otherwise (e.g., file system full). Cudd_DumpFactoredForm does not
  761. close the file: This is the caller responsibility. Caution must be
  762. exercised because a factored form may be exponentially larger than
  763. the argument BDD. If the argument inames is non-null, it is assumed
  764. to hold the pointers to the names of the inputs. Similarly for
  765. onames.]
  766. SideEffects [None]
  767. SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci
  768. Cudd_DumpDDcal]
  769. ******************************************************************************/
  770. int
  771. Cudd_DumpFactoredForm(
  772. DdManager * dd /* manager */,
  773. int n /* number of output nodes to be dumped */,
  774. DdNode ** f /* array of output nodes to be dumped */,
  775. char ** inames /* array of input names (or NULL) */,
  776. char ** onames /* array of output names (or NULL) */,
  777. FILE * fp /* pointer to the dump file */)
  778. {
  779. int retval;
  780. int i;
  781. /* Call the function that really gets the job done. */
  782. for (i = 0; i < n; i++) {
  783. if (onames == NULL) {
  784. retval = fprintf(fp, "f%d = ", i);
  785. } else {
  786. retval = fprintf(fp, "%s = ", onames[i]);
  787. }
  788. if (retval == EOF) return(0);
  789. if (f[i] == DD_ONE(dd)) {
  790. retval = fprintf(fp, "CONST1");
  791. if (retval == EOF) return(0);
  792. } else if (f[i] == Cudd_Not(DD_ONE(dd)) || f[i] == DD_ZERO(dd)) {
  793. retval = fprintf(fp, "CONST0");
  794. if (retval == EOF) return(0);
  795. } else {
  796. retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? "!(" : "");
  797. if (retval == EOF) return(0);
  798. retval = ddDoDumpFactoredForm(dd,Cudd_Regular(f[i]),fp,inames);
  799. if (retval == 0) return(0);
  800. retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? ")" : "");
  801. if (retval == EOF) return(0);
  802. }
  803. retval = fprintf(fp, "%s", i == n-1 ? "" : "\n");
  804. if (retval == EOF) return(0);
  805. }
  806. return(1);
  807. } /* end of Cudd_DumpFactoredForm */
  808. /*---------------------------------------------------------------------------*/
  809. /* Definition of internal functions */
  810. /*---------------------------------------------------------------------------*/
  811. /*---------------------------------------------------------------------------*/
  812. /* Definition of static functions */
  813. /*---------------------------------------------------------------------------*/
  814. /**Function********************************************************************
  815. Synopsis [Performs the recursive step of Cudd_DumpBlif.]
  816. Description [Performs the recursive step of Cudd_DumpBlif. Traverses
  817. the BDD f and writes a multiplexer-network description to the file
  818. pointed by fp in blif format. f is assumed to be a regular pointer
  819. and ddDoDumpBlif guarantees this assumption in the recursive calls.]
  820. SideEffects [None]
  821. SeeAlso []
  822. ******************************************************************************/
  823. static int
  824. ddDoDumpBlif(
  825. DdManager * dd,
  826. DdNode * f,
  827. FILE * fp,
  828. st_table * visited,
  829. char ** names,
  830. int mv)
  831. {
  832. DdNode *T, *E;
  833. int retval;
  834. #ifdef DD_DEBUG
  835. assert(!Cudd_IsComplement(f));
  836. #endif
  837. /* If already visited, nothing to do. */
  838. if (st_is_member(visited, (char *) f) == 1)
  839. return(1);
  840. /* Check for abnormal condition that should never happen. */
  841. if (f == NULL)
  842. return(0);
  843. /* Mark node as visited. */
  844. if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM)
  845. return(0);
  846. /* Check for special case: If constant node, generate constant 1. */
  847. if (f == DD_ONE(dd)) {
  848. #if SIZEOF_VOID_P == 8
  849. retval = fprintf(fp, ".names %lx\n1\n",(ptruint) f / (ptruint) sizeof(DdNode));
  850. #else
  851. retval = fprintf(fp, ".names %x\n1\n",(ptruint) f / (ptruint) sizeof(DdNode));
  852. #endif
  853. if (retval == EOF) {
  854. return(0);
  855. } else {
  856. return(1);
  857. }
  858. }
  859. /* Check whether this is an ADD. We deal with 0-1 ADDs, but not
  860. ** with the general case.
  861. */
  862. if (f == DD_ZERO(dd)) {
  863. #if SIZEOF_VOID_P == 8
  864. retval = fprintf(fp, ".names %lx\n%s",
  865. (ptruint) f / (ptruint) sizeof(DdNode),
  866. mv ? "0\n" : "");
  867. #else
  868. retval = fprintf(fp, ".names %x\n%s",
  869. (ptruint) f / (ptruint) sizeof(DdNode),
  870. mv ? "0\n" : "");
  871. #endif
  872. if (retval == EOF) {
  873. return(0);
  874. } else {
  875. return(1);
  876. }
  877. }
  878. if (cuddIsConstant(f))
  879. return(0);
  880. /* Recursive calls. */
  881. T = cuddT(f);
  882. retval = ddDoDumpBlif(dd,T,fp,visited,names,mv);
  883. if (retval != 1) return(retval);
  884. E = Cudd_Regular(cuddE(f));
  885. retval = ddDoDumpBlif(dd,E,fp,visited,names,mv);
  886. if (retval != 1) return(retval);
  887. /* Write multiplexer taking complement arc into account. */
  888. if (names != NULL) {
  889. retval = fprintf(fp,".names %s", names[f->index]);
  890. } else {
  891. #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
  892. retval = fprintf(fp,".names %u", f->index);
  893. #else
  894. retval = fprintf(fp,".names %hu", f->index);
  895. #endif
  896. }
  897. if (retval == EOF)
  898. return(0);
  899. #if SIZEOF_VOID_P == 8
  900. if (mv) {
  901. if (Cudd_IsComplement(cuddE(f))) {
  902. retval = fprintf(fp," %lx %lx %lx\n.def 0\n1 1 - 1\n0 - 0 1\n",
  903. (ptruint) T / (ptruint) sizeof(DdNode),
  904. (ptruint) E / (ptruint) sizeof(DdNode),
  905. (ptruint) f / (ptruint) sizeof(DdNode));
  906. } else {
  907. retval = fprintf(fp," %lx %lx %lx\n.def 0\n1 1 - 1\n0 - 1 1\n",
  908. (ptruint) T / (ptruint) sizeof(DdNode),
  909. (ptruint) E / (ptruint) sizeof(DdNode),
  910. (ptruint) f / (ptruint) sizeof(DdNode));
  911. }
  912. } else {
  913. if (Cudd_IsComplement(cuddE(f))) {
  914. retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-0 1\n",
  915. (ptruint) T / (ptruint) sizeof(DdNode),
  916. (ptruint) E / (ptruint) sizeof(DdNode),
  917. (ptruint) f / (ptruint) sizeof(DdNode));
  918. } else {
  919. retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-1 1\n",
  920. (ptruint) T / (ptruint) sizeof(DdNode),
  921. (ptruint) E / (ptruint) sizeof(DdNode),
  922. (ptruint) f / (ptruint) sizeof(DdNode));
  923. }
  924. }
  925. #else
  926. if (mv) {
  927. if (Cudd_IsComplement(cuddE(f))) {
  928. retval = fprintf(fp," %x %x %x\n.def 0\n1 1 - 1\n0 - 0 1\n",
  929. (ptruint) T / (ptruint) sizeof(DdNode),
  930. (ptruint) E / (ptruint) sizeof(DdNode),
  931. (ptruint) f / (ptruint) sizeof(DdNode));
  932. } else {
  933. retval = fprintf(fp," %x %x %x\n.def 0\n1 1 - 1\n0 - 1 1\n",
  934. (ptruint) T / (ptruint) sizeof(DdNode),
  935. (ptruint) E / (ptruint) sizeof(DdNode),
  936. (ptruint) f / (ptruint) sizeof(DdNode));
  937. }
  938. } else {
  939. if (Cudd_IsComplement(cuddE(f))) {
  940. retval = fprintf(fp," %x %x %x\n11- 1\n0-0 1\n",
  941. (ptruint) T / (ptruint) sizeof(DdNode),
  942. (ptruint) E / (ptruint) sizeof(DdNode),
  943. (ptruint) f / (ptruint) sizeof(DdNode));
  944. } else {
  945. retval = fprintf(fp," %x %x %x\n11- 1\n0-1 1\n",
  946. (ptruint) T / (ptruint) sizeof(DdNode),
  947. (ptruint) E / (ptruint) sizeof(DdNode),
  948. (ptruint) f / (ptruint) sizeof(DdNode));
  949. }
  950. }
  951. #endif
  952. if (retval == EOF) {
  953. return(0);
  954. } else {
  955. return(1);
  956. }
  957. } /* end of ddDoDumpBlif */
  958. /**Function********************************************************************
  959. Synopsis [Performs the recursive step of Cudd_DumpDaVinci.]
  960. Description [Performs the recursive step of Cudd_DumpDaVinci. Traverses
  961. the BDD f and writes a term expression to the file
  962. pointed by fp in daVinci format. f is assumed to be a regular pointer
  963. and ddDoDumpDaVinci guarantees this assumption in the recursive calls.]
  964. SideEffects [None]
  965. SeeAlso []
  966. ******************************************************************************/
  967. static int
  968. ddDoDumpDaVinci(
  969. DdManager * dd,
  970. DdNode * f,
  971. FILE * fp,
  972. st_table * visited,
  973. char ** names,
  974. ptruint mask)
  975. {
  976. DdNode *T, *E;
  977. int retval;
  978. ptruint id;
  979. #ifdef DD_DEBUG
  980. assert(!Cudd_IsComplement(f));
  981. #endif
  982. id = ((ptruint) f & mask) / sizeof(DdNode);
  983. /* If already visited, insert a reference. */
  984. if (st_is_member(visited, (char *) f) == 1) {
  985. retval = fprintf(fp,"r(\"%p\")", (void *) id);
  986. if (retval == EOF) {
  987. return(0);
  988. } else {
  989. return(1);
  990. }
  991. }
  992. /* Check for abnormal condition that should never happen. */
  993. if (f == NULL)
  994. return(0);
  995. /* Mark node as visited. */
  996. if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM)
  997. return(0);
  998. /* Check for special case: If constant node, generate constant 1. */
  999. if (Cudd_IsConstant(f)) {
  1000. retval = fprintf(fp,
  1001. "l(\"%p\",n(\"constant\",[a(\"OBJECT\",\"%g\")],[]))",
  1002. (void *) id, cuddV(f));
  1003. if (retval == EOF) {
  1004. return(0);
  1005. } else {
  1006. return(1);
  1007. }
  1008. }
  1009. /* Recursive calls. */
  1010. if (names != NULL) {
  1011. retval = fprintf(fp,
  1012. "l(\"%p\",n(\"internal\",[a(\"OBJECT\",\"%s\"),",
  1013. (void *) id, names[f->index]);
  1014. } else {
  1015. retval = fprintf(fp,
  1016. #if SIZEOF_VOID_P == 8
  1017. "l(\"%p\",n(\"internal\",[a(\"OBJECT\",\"%u\"),",
  1018. #else
  1019. "l(\"%p\",n(\"internal\",[a(\"OBJECT\",\"%hu\"),",
  1020. #endif
  1021. (void *) id, f->index);
  1022. }
  1023. retval = fprintf(fp, "a(\"_GO\",\"ellipse\")],[e(\"then\",[a(\"EDGECOLOR\",\"blue\"),a(\"_DIR\",\"none\")],");
  1024. if (retval == EOF) return(0);
  1025. T = cuddT(f);
  1026. retval = ddDoDumpDaVinci(dd,T,fp,visited,names,mask);
  1027. if (retval != 1) return(retval);
  1028. retval = fprintf(fp, "),e(\"else\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],",
  1029. Cudd_IsComplement(cuddE(f)) ? "red" : "green");
  1030. if (retval == EOF) return(0);
  1031. E = Cudd_Regular(cuddE(f));
  1032. retval = ddDoDumpDaVinci(dd,E,fp,visited,names,mask);
  1033. if (retval != 1) return(retval);
  1034. retval = fprintf(fp,")]))");
  1035. if (retval == EOF) {
  1036. return(0);
  1037. } else {
  1038. return(1);
  1039. }
  1040. } /* end of ddDoDumpDaVinci */
  1041. /**Function********************************************************************
  1042. Synopsis [Performs the recursive step of Cudd_DumpDDcal.]
  1043. Description [Performs the recursive step of Cudd_DumpDDcal. Traverses
  1044. the BDD f and writes a line for each node to the file
  1045. pointed by fp in DDcal format. f is assumed to be a regular pointer
  1046. and ddDoDumpDDcal guarantees this assumption in the recursive calls.]
  1047. SideEffects [None]
  1048. SeeAlso []
  1049. ******************************************************************************/
  1050. static int
  1051. ddDoDumpDDcal(
  1052. DdManager * dd,
  1053. DdNode * f,
  1054. FILE * fp,
  1055. st_table * visited,
  1056. char ** names,
  1057. ptruint mask)
  1058. {
  1059. DdNode *T, *E;
  1060. int retval;
  1061. ptruint id, idT, idE;
  1062. #ifdef DD_DEBUG
  1063. assert(!Cudd_IsComplement(f));
  1064. #endif
  1065. id = ((ptruint) f & mask) / sizeof(DdNode);
  1066. /* If already visited, do nothing. */
  1067. if (st_is_member(visited, (char *) f) == 1) {
  1068. return(1);
  1069. }
  1070. /* Check for abnormal condition that should never happen. */
  1071. if (f == NULL)
  1072. return(0);
  1073. /* Mark node as visited. */
  1074. if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM)
  1075. return(0);
  1076. /* Check for special case: If constant node, assign constant. */
  1077. if (Cudd_IsConstant(f)) {
  1078. if (f != DD_ONE(dd) && f != DD_ZERO(dd))
  1079. return(0);
  1080. retval = fprintf(fp, "n%p = %g\n", (void *) id, cuddV(f));
  1081. if (retval == EOF) {
  1082. return(0);
  1083. } else {
  1084. return(1);
  1085. }
  1086. }
  1087. /* Recursive calls. */
  1088. T = cuddT(f);
  1089. retval = ddDoDumpDDcal(dd,T,fp,visited,names,mask);
  1090. if (retval != 1) return(retval);
  1091. E = Cudd_Regular(cuddE(f));
  1092. retval = ddDoDumpDDcal(dd,E,fp,visited,names,mask);
  1093. if (retval != 1) return(retval);
  1094. idT = ((ptruint) T & mask) / sizeof(DdNode);
  1095. idE = ((ptruint) E & mask) / sizeof(DdNode);
  1096. if (names != NULL) {
  1097. retval = fprintf(fp, "n%p = %s * n%p + %s' * n%p%s\n",
  1098. (void *) id, names[f->index],
  1099. (void *) idT, names[f->index],
  1100. (void *) idE, Cudd_IsComplement(cuddE(f)) ? "'" : "");
  1101. } else {
  1102. #if SIZEOF_VOID_P == 8
  1103. retval = fprintf(fp, "n%p = v%u * n%p + v%u' * n%p%s\n",
  1104. #else
  1105. retval = fprintf(fp, "n%p = v%hu * n%p + v%hu' * n%p%s\n",
  1106. #endif
  1107. (void *) id, f->index,
  1108. (void *) idT, f->index,
  1109. (void *) idE, Cudd_IsComplement(cuddE(f)) ? "'" : "");
  1110. }
  1111. if (retval == EOF) {
  1112. return(0);
  1113. } else {
  1114. return(1);
  1115. }
  1116. } /* end of ddDoDumpDDcal */
  1117. /**Function********************************************************************
  1118. Synopsis [Performs the recursive step of Cudd_DumpFactoredForm.]
  1119. Description [Performs the recursive step of
  1120. Cudd_DumpFactoredForm. Traverses the BDD f and writes a factored
  1121. form for each node to the file pointed by fp in terms of the
  1122. factored forms of the children. Constants are propagated, and
  1123. absorption is applied. f is assumed to be a regular pointer and
  1124. ddDoDumpFActoredForm guarantees this assumption in the recursive
  1125. calls.]
  1126. SideEffects [None]
  1127. SeeAlso [Cudd_DumpFactoredForm]
  1128. ******************************************************************************/
  1129. static int
  1130. ddDoDumpFactoredForm(
  1131. DdManager * dd,
  1132. DdNode * f,
  1133. FILE * fp,
  1134. char ** names)
  1135. {
  1136. DdNode *T, *E;
  1137. int retval;
  1138. #ifdef DD_DEBUG
  1139. assert(!Cudd_IsComplement(f));
  1140. assert(!Cudd_IsConstant(f));
  1141. #endif
  1142. /* Check for abnormal condition that should never happen. */
  1143. if (f == NULL)
  1144. return(0);
  1145. /* Recursive calls. */
  1146. T = cuddT(f);
  1147. E = cuddE(f);
  1148. if (T != DD_ZERO(dd)) {
  1149. if (E != DD_ONE(dd)) {
  1150. if (names != NULL) {
  1151. retval = fprintf(fp, "%s", names[f->index]);
  1152. } else {
  1153. #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
  1154. retval = fprintf(fp, "x%u", f->index);
  1155. #else
  1156. retval = fprintf(fp, "x%hu", f->index);
  1157. #endif
  1158. }
  1159. if (retval == EOF) return(0);
  1160. }
  1161. if (T != DD_ONE(dd)) {
  1162. retval = fprintf(fp, "%s(", E != DD_ONE(dd) ? " * " : "");
  1163. if (retval == EOF) return(0);
  1164. retval = ddDoDumpFactoredForm(dd,T,fp,names);
  1165. if (retval != 1) return(retval);
  1166. retval = fprintf(fp, ")");
  1167. if (retval == EOF) return(0);
  1168. }
  1169. if (E == Cudd_Not(DD_ONE(dd)) || E == DD_ZERO(dd)) return(1);
  1170. retval = fprintf(fp, " + ");
  1171. if (retval == EOF) return(0);
  1172. }
  1173. E = Cudd_Regular(E);
  1174. if (T != DD_ONE(dd)) {
  1175. if (names != NULL) {
  1176. retval = fprintf(fp, "!%s", names[f->index]);
  1177. } else {
  1178. #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
  1179. retval = fprintf(fp, "!x%u", f->index);
  1180. #else
  1181. retval = fprintf(fp, "!x%hu", f->index);
  1182. #endif
  1183. }
  1184. if (retval == EOF) return(0);
  1185. }
  1186. if (E != DD_ONE(dd)) {
  1187. retval = fprintf(fp, "%s%s(", T != DD_ONE(dd) ? " * " : "",
  1188. E != cuddE(f) ? "!" : "");
  1189. if (retval == EOF) return(0);
  1190. retval = ddDoDumpFactoredForm(dd,E,fp,names);
  1191. if (retval != 1) return(retval);
  1192. retval = fprintf(fp, ")");
  1193. if (retval == EOF) return(0);
  1194. }
  1195. return(1);
  1196. } /* end of ddDoDumpFactoredForm */