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
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							1389 lines
						
					
					
						
							43 KiB
						
					
					
				| /**CFile*********************************************************************** | |
|  | |
|   FileName    [cuddExport.c] | |
|  | |
|   PackageName [cudd] | |
|  | |
|   Synopsis    [Export functions.] | |
|  | |
|   Description [External procedures included in this module: | |
| 		<ul> | |
| 		<li> Cudd_DumpBlif() | |
| 		<li> Cudd_DumpBlifBody() | |
| 		<li> Cudd_DumpDot() | |
| 		<li> Cudd_DumpDaVinci() | |
| 		<li> Cudd_DumpDDcal() | |
| 		<li> Cudd_DumpFactoredForm() | |
| 		</ul> | |
| 	Internal procedures included in this module: | |
| 		<ul> | |
| 		</ul> | |
| 	Static procedures included in this module: | |
| 		<ul> | |
| 		<li> ddDoDumpBlif() | |
| 		<li> ddDoDumpDaVinci() | |
| 		<li> ddDoDumpDDcal() | |
| 		<li> ddDoDumpFactoredForm() | |
| 		</ul>] | |
|  | |
|   Author      [Fabio Somenzi] | |
|  | |
|   Copyright   [Copyright (c) 1995-2012, Regents of the University of Colorado | |
|  | |
|   All rights reserved. | |
|  | |
|   Redistribution and use in source and binary forms, with or without | |
|   modification, are permitted provided that the following conditions | |
|   are met: | |
|  | |
|   Redistributions of source code must retain the above copyright | |
|   notice, this list of conditions and the following disclaimer. | |
|  | |
|   Redistributions in binary form must reproduce the above copyright | |
|   notice, this list of conditions and the following disclaimer in the | |
|   documentation and/or other materials provided with the distribution. | |
|  | |
|   Neither the name of the University of Colorado nor the names of its | |
|   contributors may be used to endorse or promote products derived from | |
|   this software without specific prior written permission. | |
|  | |
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
|   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
|   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
|   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
|   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
|   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
|   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
|   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
|   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
|   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
|   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
|   POSSIBILITY OF SUCH DAMAGE.] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| #include "util.h" | |
| #include "cuddInt.h" | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Constant declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Stucture declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Type declarations                                                         */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Variable declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| #ifndef lint | |
| static char rcsid[] DD_UNUSED = "$Id: cuddExport.c,v 1.23 2012/02/05 01:07:18 fabio Exp $"; | |
| #endif | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Macro declarations                                                        */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /**AutomaticStart*************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Static function prototypes                                                */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| static int ddDoDumpBlif (DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, int mv); | |
| static int ddDoDumpDaVinci (DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, ptruint mask); | |
| static int ddDoDumpDDcal (DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, ptruint mask); | |
| static int ddDoDumpFactoredForm (DdManager *dd, DdNode *f, FILE *fp, char **names); | |
| 
 | |
| /**AutomaticEnd***************************************************************/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of exported functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Writes a blif file representing the argument BDDs.] | |
|  | |
|   Description [Writes a blif file representing the argument BDDs as a | |
|   network of multiplexers. One multiplexer is written for each BDD | |
|   node. It returns 1 in case of success; 0 otherwise (e.g., | |
|   out-of-memory, file system full, or an ADD with constants different | |
|   from 0 and 1).  Cudd_DumpBlif does not close the file: This is the | |
|   caller responsibility. Cudd_DumpBlif uses a minimal unique subset of | |
|   the hexadecimal address of a node as name for it.  If the argument | |
|   inames is non-null, it is assumed to hold the pointers to the names | |
|   of the inputs. Similarly for onames.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_DumpBlifBody Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal | |
|   Cudd_DumpDaVinci Cudd_DumpFactoredForm] | |
|  | |
| ******************************************************************************/ | |
| int | |
| Cudd_DumpBlif( | |
|   DdManager * dd /* manager */, | |
|   int  n /* number of output nodes to be dumped */, | |
|   DdNode ** f /* array of output nodes to be dumped */, | |
|   char ** inames /* array of input names (or NULL) */, | |
|   char ** onames /* array of output names (or NULL) */, | |
|   char * mname /* model name (or NULL) */, | |
|   FILE * fp /* pointer to the dump file */, | |
|   int mv /* 0: blif, 1: blif-MV */) | |
| { | |
|     DdNode	*support = NULL; | |
|     DdNode	*scan; | |
|     int		*sorted = NULL; | |
|     int		nvars = dd->size; | |
|     int		retval; | |
|     int		i; | |
| 
 | |
|     /* Build a bit array with the support of f. */ | |
|     sorted = ALLOC(int,nvars); | |
|     if (sorted == NULL) { | |
| 	dd->errorCode = CUDD_MEMORY_OUT; | |
| 	goto failure; | |
|     } | |
|     for (i = 0; i < nvars; i++) sorted[i] = 0; | |
| 
 | |
|     /* Take the union of the supports of each output function. */ | |
|     support = Cudd_VectorSupport(dd,f,n); | |
|     if (support == NULL) goto failure; | |
|     cuddRef(support); | |
|     scan = support; | |
|     while (!cuddIsConstant(scan)) { | |
| 	sorted[scan->index] = 1; | |
| 	scan = cuddT(scan); | |
|     } | |
|     Cudd_RecursiveDeref(dd,support); | |
|     support = NULL; /* so that we do not try to free it in case of failure */ | |
| 
 | |
|     /* Write the header (.model .inputs .outputs). */ | |
|     if (mname == NULL) { | |
| 	retval = fprintf(fp,".model DD\n.inputs"); | |
|     } else { | |
| 	retval = fprintf(fp,".model %s\n.inputs",mname); | |
|     } | |
|     if (retval == EOF) { | |
| 	FREE(sorted); | |
| 	return(0); | |
|     } | |
| 
 | |
|     /* Write the input list by scanning the support array. */ | |
|     for (i = 0; i < nvars; i++) { | |
| 	if (sorted[i]) { | |
| 	    if (inames == NULL) { | |
| 		retval = fprintf(fp," %d", i); | |
| 	    } else { | |
| 		retval = fprintf(fp," %s", inames[i]); | |
| 	    } | |
| 	    if (retval == EOF) goto failure; | |
| 	} | |
|     } | |
|     FREE(sorted); | |
|     sorted = NULL; | |
| 
 | |
|     /* Write the .output line. */ | |
|     retval = fprintf(fp,"\n.outputs"); | |
|     if (retval == EOF) goto failure; | |
|     for (i = 0; i < n; i++) { | |
| 	if (onames == NULL) { | |
| 	    retval = fprintf(fp," f%d", i); | |
| 	} else { | |
| 	    retval = fprintf(fp," %s", onames[i]); | |
| 	} | |
| 	if (retval == EOF) goto failure; | |
|     } | |
|     retval = fprintf(fp,"\n"); | |
|     if (retval == EOF) goto failure; | |
| 
 | |
|     retval = Cudd_DumpBlifBody(dd, n, f, inames, onames, fp, mv); | |
|     if (retval == 0) goto failure; | |
| 
 | |
|     /* Write trailer and return. */ | |
|     retval = fprintf(fp,".end\n"); | |
|     if (retval == EOF) goto failure; | |
| 
 | |
|     return(1); | |
| 
 | |
| failure: | |
|     if (sorted != NULL) FREE(sorted); | |
|     if (support != NULL) Cudd_RecursiveDeref(dd,support); | |
|     return(0); | |
| 
 | |
| } /* end of Cudd_DumpBlif */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Writes a blif body representing the argument BDDs.] | |
|  | |
|   Description [Writes a blif body representing the argument BDDs as a | |
|   network of multiplexers.  No header (.model, .inputs, and .outputs) and | |
|   footer (.end) are produced by this function.  One multiplexer is written | |
|   for each BDD node. It returns 1 in case of success; 0 otherwise (e.g., | |
|   out-of-memory, file system full, or an ADD with constants different | |
|   from 0 and 1).  Cudd_DumpBlifBody does not close the file: This is the | |
|   caller responsibility. Cudd_DumpBlifBody uses a minimal unique subset of | |
|   the hexadecimal address of a node as name for it.  If the argument | |
|   inames is non-null, it is assumed to hold the pointers to the names | |
|   of the inputs. Similarly for onames. This function prints out only | |
|   .names part.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_DumpBlif Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal | |
|   Cudd_DumpDaVinci Cudd_DumpFactoredForm] | |
|  | |
| ******************************************************************************/ | |
| int | |
| Cudd_DumpBlifBody( | |
|   DdManager * dd /* manager */, | |
|   int  n /* number of output nodes to be dumped */, | |
|   DdNode ** f /* array of output nodes to be dumped */, | |
|   char ** inames /* array of input names (or NULL) */, | |
|   char ** onames /* array of output names (or NULL) */, | |
|   FILE * fp /* pointer to the dump file */, | |
|   int mv /* 0: blif, 1: blif-MV */) | |
| { | |
|     st_table	*visited = NULL; | |
|     int		retval; | |
|     int		i; | |
| 
 | |
|     /* Initialize symbol table for visited nodes. */ | |
|     visited = st_init_table(st_ptrcmp, st_ptrhash); | |
|     if (visited == NULL) goto failure; | |
| 
 | |
|     /* Call the function that really gets the job done. */ | |
|     for (i = 0; i < n; i++) { | |
| 	retval = ddDoDumpBlif(dd,Cudd_Regular(f[i]),fp,visited,inames,mv); | |
| 	if (retval == 0) goto failure; | |
|     } | |
| 
 | |
|     /* To account for the possible complement on the root, | |
|     ** we put either a buffer or an inverter at the output of | |
|     ** the multiplexer representing the top node. | |
|     */ | |
|     for (i = 0; i < n; i++) { | |
| 	if (onames == NULL) { | |
| 	    retval = fprintf(fp, | |
| #if SIZEOF_VOID_P == 8 | |
| 		".names %lx f%d\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), i); | |
| #else | |
| 		".names %x f%d\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), i); | |
| #endif | |
| 	} else { | |
| 	    retval = fprintf(fp, | |
| #if SIZEOF_VOID_P == 8 | |
| 		".names %lx %s\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), onames[i]); | |
| #else | |
| 		".names %x %s\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), onames[i]); | |
| #endif | |
| 	} | |
| 	if (retval == EOF) goto failure; | |
| 	if (Cudd_IsComplement(f[i])) { | |
| 	    retval = fprintf(fp,"%s0 1\n", mv ? ".def 0\n" : ""); | |
| 	} else { | |
| 	    retval = fprintf(fp,"%s1 1\n", mv ? ".def 0\n" : ""); | |
| 	} | |
| 	if (retval == EOF) goto failure; | |
|     } | |
| 
 | |
|     st_free_table(visited); | |
|     return(1); | |
| 
 | |
| failure: | |
|     if (visited != NULL) st_free_table(visited); | |
|     return(0); | |
| 
 | |
| } /* end of Cudd_DumpBlifBody */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Writes a dot file representing the argument DDs.] | |
|  | |
|   Description [Writes a file representing the argument DDs in a format | |
|   suitable for the graph drawing program dot. | |
|   It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, | |
|   file system full). | |
|   Cudd_DumpDot does not close the file: This is the caller | |
|   responsibility. Cudd_DumpDot uses a minimal unique subset of the | |
|   hexadecimal address of a node as name for it. | |
|   If the argument inames is non-null, it is assumed to hold the pointers | |
|   to the names of the inputs. Similarly for onames. | |
|   Cudd_DumpDot uses the following convention to draw arcs: | |
|     <ul> | |
|     <li> solid line: THEN arcs; | |
|     <li> dotted line: complement arcs; | |
|     <li> dashed line: regular ELSE arcs. | |
|     </ul> | |
|   The dot options are chosen so that the drawing fits on a letter-size | |
|   sheet. | |
|   ] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_DumpBlif Cudd_PrintDebug Cudd_DumpDDcal | |
|   Cudd_DumpDaVinci Cudd_DumpFactoredForm] | |
|  | |
| ******************************************************************************/ | |
| int | |
| Cudd_DumpDot( | |
|   DdManager * dd /* manager */, | |
|   int  n /* number of output nodes to be dumped */, | |
|   DdNode ** f /* array of output nodes to be dumped */, | |
|   char ** inames /* array of input names (or NULL) */, | |
|   char ** onames /* array of output names (or NULL) */, | |
|   FILE * fp /* pointer to the dump file */) | |
| { | |
|     DdNode	*support = NULL; | |
|     DdNode	*scan; | |
|     int		*sorted = NULL; | |
|     int		nvars = dd->size; | |
|     st_table	*visited = NULL; | |
|     st_generator *gen = NULL; | |
|     int		retval; | |
|     int		i, j; | |
|     int		slots; | |
|     DdNodePtr	*nodelist; | |
|     long	refAddr, diff, mask; | |
| 
 | |
|     /* Build a bit array with the support of f. */ | |
|     sorted = ALLOC(int,nvars); | |
|     if (sorted == NULL) { | |
| 	dd->errorCode = CUDD_MEMORY_OUT; | |
| 	goto failure; | |
|     } | |
|     for (i = 0; i < nvars; i++) sorted[i] = 0; | |
| 
 | |
|     /* Take the union of the supports of each output function. */ | |
|     support = Cudd_VectorSupport(dd,f,n); | |
|     if (support == NULL) goto failure; | |
|     cuddRef(support); | |
|     scan = support; | |
|     while (!cuddIsConstant(scan)) { | |
| 	sorted[scan->index] = 1; | |
| 	scan = cuddT(scan); | |
|     } | |
|     Cudd_RecursiveDeref(dd,support); | |
|     support = NULL; /* so that we do not try to free it in case of failure */ | |
| 
 | |
|     /* Initialize symbol table for visited nodes. */ | |
|     visited = st_init_table(st_ptrcmp, st_ptrhash); | |
|     if (visited == NULL) goto failure; | |
| 
 | |
|     /* Collect all the nodes of this DD in the symbol table. */ | |
|     for (i = 0; i < n; i++) { | |
| 	retval = cuddCollectNodes(Cudd_Regular(f[i]),visited); | |
| 	if (retval == 0) goto failure; | |
|     } | |
| 
 | |
|     /* Find how many most significant hex digits are identical | |
|     ** in the addresses of all the nodes. Build a mask based | |
|     ** on this knowledge, so that digits that carry no information | |
|     ** will not be printed. This is done in two steps. | |
|     **  1. We scan the symbol table to find the bits that differ | |
|     **     in at least 2 addresses. | |
|     **  2. We choose one of the possible masks. There are 8 possible | |
|     **     masks for 32-bit integer, and 16 possible masks for 64-bit | |
|     **     integers. | |
|     */ | |
| 
 | |
|     /* Find the bits that are different. */ | |
|     refAddr = (long) Cudd_Regular(f[0]); | |
|     diff = 0; | |
|     gen = st_init_gen(visited); | |
|     if (gen == NULL) goto failure; | |
|     while (st_gen(gen, &scan, NULL)) { | |
| 	diff |= refAddr ^ (long) scan; | |
|     } | |
|     st_free_gen(gen); gen = NULL; | |
| 
 | |
|     /* Choose the mask. */ | |
|     for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) { | |
| 	mask = (1 << i) - 1; | |
| 	if (diff <= mask) break; | |
|     } | |
| 
 | |
|     /* Write the header and the global attributes. */ | |
|     retval = fprintf(fp,"digraph \"DD\" {\n"); | |
|     if (retval == EOF) return(0); | |
|     retval = fprintf(fp, | |
| 	"size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n"); | |
|     if (retval == EOF) return(0); | |
| 
 | |
|     /* Write the input name subgraph by scanning the support array. */ | |
|     retval = fprintf(fp,"{ node [shape = plaintext];\n"); | |
|     if (retval == EOF) goto failure; | |
|     retval = fprintf(fp,"  edge [style = invis];\n"); | |
|     if (retval == EOF) goto failure; | |
|     /* We use a name ("CONST NODES") with an embedded blank, because | |
|     ** it is unlikely to appear as an input name. | |
|     */ | |
|     retval = fprintf(fp,"  \"CONST NODES\" [style = invis];\n"); | |
|     if (retval == EOF) goto failure; | |
|     for (i = 0; i < nvars; i++) { | |
| 	if (sorted[dd->invperm[i]]) { | |
| 	    if (inames == NULL || inames[dd->invperm[i]] == NULL) { | |
| 		retval = fprintf(fp,"\" %d \" -> ", dd->invperm[i]); | |
| 	    } else { | |
| 		retval = fprintf(fp,"\" %s \" -> ", inames[dd->invperm[i]]); | |
| 	    } | |
| 	    if (retval == EOF) goto failure; | |
| 	} | |
|     } | |
|     retval = fprintf(fp,"\"CONST NODES\"; \n}\n"); | |
|     if (retval == EOF) goto failure; | |
| 
 | |
|     /* Write the output node subgraph. */ | |
|     retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n"); | |
|     if (retval == EOF) goto failure; | |
|     for (i = 0; i < n; i++) { | |
| 	if (onames == NULL) { | |
| 	    retval = fprintf(fp,"\"F%d\"", i); | |
| 	} else { | |
| 	    retval = fprintf(fp,"\"  %s  \"", onames[i]); | |
| 	} | |
| 	if (retval == EOF) goto failure; | |
| 	if (i == n - 1) { | |
| 	    retval = fprintf(fp,"; }\n"); | |
| 	} else { | |
| 	    retval = fprintf(fp," -> "); | |
| 	} | |
| 	if (retval == EOF) goto failure; | |
|     } | |
| 
 | |
|     /* Write rank info: All nodes with the same index have the same rank. */ | |
|     for (i = 0; i < nvars; i++) { | |
| 	if (sorted[dd->invperm[i]]) { | |
| 	    retval = fprintf(fp,"{ rank = same; "); | |
| 	    if (retval == EOF) goto failure; | |
| 	    if (inames == NULL || inames[dd->invperm[i]] == NULL) { | |
| 		retval = fprintf(fp,"\" %d \";\n", dd->invperm[i]); | |
| 	    } else { | |
| 		retval = fprintf(fp,"\" %s \";\n", inames[dd->invperm[i]]); | |
| 	    } | |
| 	    if (retval == EOF) goto failure; | |
| 	    nodelist = dd->subtables[i].nodelist; | |
| 	    slots = dd->subtables[i].slots; | |
| 	    for (j = 0; j < slots; j++) { | |
| 		scan = nodelist[j]; | |
| 		while (scan != NULL) { | |
| 		    if (st_is_member(visited,(char *) scan)) { | |
| 			retval = fprintf(fp,"\"%p\";\n", | |
| 			    (void *) ((mask & (ptrint) scan) / | |
| 			    sizeof(DdNode))); | |
| 			if (retval == EOF) goto failure; | |
| 		    } | |
| 		    scan = scan->next; | |
| 		} | |
| 	    } | |
| 	    retval = fprintf(fp,"}\n"); | |
| 	    if (retval == EOF) goto failure; | |
| 	} | |
|     } | |
| 
 | |
|     /* All constants have the same rank. */ | |
|     retval = fprintf(fp, | |
| 	"{ rank = same; \"CONST NODES\";\n{ node [shape = box]; "); | |
|     if (retval == EOF) goto failure; | |
|     nodelist = dd->constants.nodelist; | |
|     slots = dd->constants.slots; | |
|     for (j = 0; j < slots; j++) { | |
| 	scan = nodelist[j]; | |
| 	while (scan != NULL) { | |
| 	    if (st_is_member(visited,(char *) scan)) { | |
| 		retval = fprintf(fp,"\"%p\";\n", | |
| 		    (void *) ((mask & (ptrint) scan) / sizeof(DdNode))); | |
| 		if (retval == EOF) goto failure; | |
| 	    } | |
| 	    scan = scan->next; | |
| 	} | |
|     } | |
|     retval = fprintf(fp,"}\n}\n"); | |
|     if (retval == EOF) goto failure; | |
| 
 | |
|     /* Write edge info. */ | |
|     /* Edges from the output nodes. */ | |
|     for (i = 0; i < n; i++) { | |
| 	if (onames == NULL) { | |
| 	    retval = fprintf(fp,"\"F%d\"", i); | |
| 	} else { | |
| 	    retval = fprintf(fp,"\"  %s  \"", onames[i]); | |
| 	} | |
| 	if (retval == EOF) goto failure; | |
| 	/* Account for the possible complement on the root. */ | |
| 	if (Cudd_IsComplement(f[i])) { | |
| 	    retval = fprintf(fp," -> \"%p\" [style = dotted];\n", | |
| 		(void *) ((mask & (ptrint) f[i]) / sizeof(DdNode))); | |
| 	} else { | |
| 	    retval = fprintf(fp," -> \"%p\" [style = solid];\n", | |
| 		(void *) ((mask & (ptrint) f[i]) / sizeof(DdNode))); | |
| 	} | |
| 	if (retval == EOF) goto failure; | |
|     } | |
| 
 | |
|     /* Edges from internal nodes. */ | |
|     for (i = 0; i < nvars; i++) { | |
| 	if (sorted[dd->invperm[i]]) { | |
| 	    nodelist = dd->subtables[i].nodelist; | |
| 	    slots = dd->subtables[i].slots; | |
| 	    for (j = 0; j < slots; j++) { | |
| 		scan = nodelist[j]; | |
| 		while (scan != NULL) { | |
| 		    if (st_is_member(visited,(char *) scan)) { | |
| 			retval = fprintf(fp, | |
| 			    "\"%p\" -> \"%p\";\n", | |
| 			    (void *) ((mask & (ptrint) scan) / | |
| 			    sizeof(DdNode)), | |
| 			    (void *) ((mask & (ptrint) cuddT(scan)) / | |
| 			    sizeof(DdNode))); | |
| 			if (retval == EOF) goto failure; | |
| 			if (Cudd_IsComplement(cuddE(scan))) { | |
| 			    retval = fprintf(fp, | |
| 				"\"%p\" -> \"%p\" [style = dotted];\n", | |
| 				(void *) ((mask & (ptrint) scan) / | |
| 				sizeof(DdNode)), | |
| 				(void *) ((mask & (ptrint) cuddE(scan)) / | |
| 				sizeof(DdNode))); | |
| 			} else { | |
| 			    retval = fprintf(fp, | |
| 				"\"%p\" -> \"%p\" [style = dashed];\n", | |
| 				(void *) ((mask & (ptrint) scan) / | |
| 				sizeof(DdNode)), | |
| 				(void *) ((mask & (ptrint) cuddE(scan)) / | |
| 				sizeof(DdNode))); | |
| 			} | |
| 			if (retval == EOF) goto failure; | |
| 		    } | |
| 		    scan = scan->next; | |
| 		} | |
| 	    } | |
| 	} | |
|     } | |
| 
 | |
|     /* Write constant labels. */ | |
|     nodelist = dd->constants.nodelist; | |
|     slots = dd->constants.slots; | |
|     for (j = 0; j < slots; j++) { | |
| 	scan = nodelist[j]; | |
| 	while (scan != NULL) { | |
| 	    if (st_is_member(visited,(char *) scan)) { | |
| 		retval = fprintf(fp,"\"%p\" [label = \"%g\"];\n", | |
| 		    (void *) ((mask & (ptrint) scan) / sizeof(DdNode)), | |
| 		    cuddV(scan)); | |
| 		if (retval == EOF) goto failure; | |
| 	    } | |
| 	    scan = scan->next; | |
| 	} | |
|     } | |
| 
 | |
|     /* Write trailer and return. */ | |
|     retval = fprintf(fp,"}\n"); | |
|     if (retval == EOF) goto failure; | |
| 
 | |
|     st_free_table(visited); | |
|     FREE(sorted); | |
|     return(1); | |
| 
 | |
| failure: | |
|     if (sorted != NULL) FREE(sorted); | |
|     if (support != NULL) Cudd_RecursiveDeref(dd,support); | |
|     if (visited != NULL) st_free_table(visited); | |
|     return(0); | |
| 
 | |
| } /* end of Cudd_DumpDot */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Writes a daVinci file representing the argument BDDs.] | |
|  | |
|   Description [Writes a daVinci file representing the argument BDDs. | |
|   It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or | |
|   file system full).  Cudd_DumpDaVinci does not close the file: This | |
|   is the caller responsibility. Cudd_DumpDaVinci uses a minimal unique | |
|   subset of the hexadecimal address of a node as name for it.  If the | |
|   argument inames is non-null, it is assumed to hold the pointers to | |
|   the names of the inputs. Similarly for onames.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDDcal | |
|   Cudd_DumpFactoredForm] | |
|  | |
| ******************************************************************************/ | |
| int | |
| Cudd_DumpDaVinci( | |
|   DdManager * dd /* manager */, | |
|   int  n /* number of output nodes to be dumped */, | |
|   DdNode ** f /* array of output nodes to be dumped */, | |
|   char ** inames /* array of input names (or NULL) */, | |
|   char ** onames /* array of output names (or NULL) */, | |
|   FILE * fp /* pointer to the dump file */) | |
| { | |
|     DdNode	  *support = NULL; | |
|     DdNode	  *scan; | |
|     st_table	  *visited = NULL; | |
|     int		  retval; | |
|     int		  i; | |
|     st_generator  *gen; | |
|     ptruint       refAddr, diff, mask; | |
| 
 | |
|     /* Initialize symbol table for visited nodes. */ | |
|     visited = st_init_table(st_ptrcmp, st_ptrhash); | |
|     if (visited == NULL) goto failure; | |
| 
 | |
|     /* Collect all the nodes of this DD in the symbol table. */ | |
|     for (i = 0; i < n; i++) { | |
| 	retval = cuddCollectNodes(Cudd_Regular(f[i]),visited); | |
| 	if (retval == 0) goto failure; | |
|     } | |
| 
 | |
|     /* Find how many most significant hex digits are identical | |
|     ** in the addresses of all the nodes. Build a mask based | |
|     ** on this knowledge, so that digits that carry no information | |
|     ** will not be printed. This is done in two steps. | |
|     **  1. We scan the symbol table to find the bits that differ | |
|     **     in at least 2 addresses. | |
|     **  2. We choose one of the possible masks. There are 8 possible | |
|     **     masks for 32-bit integer, and 16 possible masks for 64-bit | |
|     **     integers. | |
|     */ | |
| 
 | |
|     /* Find the bits that are different. */ | |
|     refAddr = (ptruint) Cudd_Regular(f[0]); | |
|     diff = 0; | |
|     gen = st_init_gen(visited); | |
|     while (st_gen(gen, &scan, NULL)) { | |
| 	diff |= refAddr ^ (ptruint) scan; | |
|     } | |
|     st_free_gen(gen); | |
| 
 | |
|     /* Choose the mask. */ | |
|     for (i = 0; (unsigned) i < 8 * sizeof(ptruint); i += 4) { | |
| 	mask = (1 << i) - 1; | |
| 	if (diff <= mask) break; | |
|     } | |
|     st_free_table(visited); | |
| 
 | |
|     /* Initialize symbol table for visited nodes. */ | |
|     visited = st_init_table(st_ptrcmp, st_ptrhash); | |
|     if (visited == NULL) goto failure; | |
| 
 | |
|     retval = fprintf(fp, "["); | |
|     if (retval == EOF) goto failure; | |
|     /* Call the function that really gets the job done. */ | |
|     for (i = 0; i < n; i++) { | |
| 	if (onames == NULL) { | |
| 	    retval = fprintf(fp, | |
| 			     "l(\"f%d\",n(\"root\",[a(\"OBJECT\",\"f%d\")],", | |
| 			     i,i); | |
| 	} else { | |
| 	    retval = fprintf(fp, | |
| 			     "l(\"%s\",n(\"root\",[a(\"OBJECT\",\"%s\")],", | |
| 			     onames[i], onames[i]); | |
| 	} | |
| 	if (retval == EOF) goto failure; | |
| 	retval = fprintf(fp, "[e(\"edge\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],", | |
| 			 Cudd_IsComplement(f[i]) ? "red" : "blue"); | |
| 	if (retval == EOF) goto failure; | |
| 	retval = ddDoDumpDaVinci(dd,Cudd_Regular(f[i]),fp,visited,inames,mask); | |
| 	if (retval == 0) goto failure; | |
| 	retval = fprintf(fp, ")]))%s", i == n-1 ? "" : ","); | |
| 	if (retval == EOF) goto failure; | |
|     } | |
| 
 | |
|     /* Write trailer and return. */ | |
|     retval = fprintf(fp, "]\n"); | |
|     if (retval == EOF) goto failure; | |
| 
 | |
|     st_free_table(visited); | |
|     return(1); | |
| 
 | |
| failure: | |
|     if (support != NULL) Cudd_RecursiveDeref(dd,support); | |
|     if (visited != NULL) st_free_table(visited); | |
|     return(0); | |
| 
 | |
| } /* end of Cudd_DumpDaVinci */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Writes a DDcal file representing the argument BDDs.] | |
|  | |
|   Description [Writes a DDcal file representing the argument BDDs. | |
|   It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or | |
|   file system full).  Cudd_DumpDDcal does not close the file: This | |
|   is the caller responsibility. Cudd_DumpDDcal uses a minimal unique | |
|   subset of the hexadecimal address of a node as name for it.  If the | |
|   argument inames is non-null, it is assumed to hold the pointers to | |
|   the names of the inputs. Similarly for onames.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci | |
|   Cudd_DumpFactoredForm] | |
|  | |
| ******************************************************************************/ | |
| int | |
| Cudd_DumpDDcal( | |
|   DdManager * dd /* manager */, | |
|   int  n /* number of output nodes to be dumped */, | |
|   DdNode ** f /* array of output nodes to be dumped */, | |
|   char ** inames /* array of input names (or NULL) */, | |
|   char ** onames /* array of output names (or NULL) */, | |
|   FILE * fp /* pointer to the dump file */) | |
| { | |
|     DdNode	  *support = NULL; | |
|     DdNode	  *scan; | |
|     int		  *sorted = NULL; | |
|     int		  nvars = dd->size; | |
|     st_table	  *visited = NULL; | |
|     int		  retval; | |
|     int		  i; | |
|     st_generator  *gen; | |
|     ptruint       refAddr, diff, mask; | |
| 
 | |
|     /* Initialize symbol table for visited nodes. */ | |
|     visited = st_init_table(st_ptrcmp, st_ptrhash); | |
|     if (visited == NULL) goto failure; | |
| 
 | |
|     /* Collect all the nodes of this DD in the symbol table. */ | |
|     for (i = 0; i < n; i++) { | |
| 	retval = cuddCollectNodes(Cudd_Regular(f[i]),visited); | |
| 	if (retval == 0) goto failure; | |
|     } | |
| 
 | |
|     /* Find how many most significant hex digits are identical | |
|     ** in the addresses of all the nodes. Build a mask based | |
|     ** on this knowledge, so that digits that carry no information | |
|     ** will not be printed. This is done in two steps. | |
|     **  1. We scan the symbol table to find the bits that differ | |
|     **     in at least 2 addresses. | |
|     **  2. We choose one of the possible masks. There are 8 possible | |
|     **     masks for 32-bit integer, and 16 possible masks for 64-bit | |
|     **     integers. | |
|     */ | |
| 
 | |
|     /* Find the bits that are different. */ | |
|     refAddr = (ptruint) Cudd_Regular(f[0]); | |
|     diff = 0; | |
|     gen = st_init_gen(visited); | |
|     while (st_gen(gen, &scan, NULL)) { | |
| 	diff |= refAddr ^ (ptruint) scan; | |
|     } | |
|     st_free_gen(gen); | |
| 
 | |
|     /* Choose the mask. */ | |
|     for (i = 0; (unsigned) i < 8 * sizeof(ptruint); i += 4) { | |
| 	mask = (1 << i) - 1; | |
| 	if (diff <= mask) break; | |
|     } | |
|     st_free_table(visited); | |
| 
 | |
|     /* Build a bit array with the support of f. */ | |
|     sorted = ALLOC(int,nvars); | |
|     if (sorted == NULL) { | |
| 	dd->errorCode = CUDD_MEMORY_OUT; | |
| 	goto failure; | |
|     } | |
|     for (i = 0; i < nvars; i++) sorted[i] = 0; | |
| 
 | |
|     /* Take the union of the supports of each output function. */ | |
|     support = Cudd_VectorSupport(dd,f,n); | |
|     if (support == NULL) goto failure; | |
|     cuddRef(support); | |
|     scan = support; | |
|     while (!cuddIsConstant(scan)) { | |
| 	sorted[scan->index] = 1; | |
| 	scan = cuddT(scan); | |
|     } | |
|     Cudd_RecursiveDeref(dd,support); | |
|     support = NULL; /* so that we do not try to free it in case of failure */ | |
|     for (i = 0; i < nvars; i++) { | |
| 	if (sorted[dd->invperm[i]]) { | |
| 	    if (inames == NULL || inames[dd->invperm[i]] == NULL) { | |
| 		retval = fprintf(fp,"v%d", dd->invperm[i]); | |
| 	    } else { | |
| 		retval = fprintf(fp,"%s", inames[dd->invperm[i]]); | |
| 	    } | |
| 	    if (retval == EOF) goto failure; | |
| 	} | |
| 	retval = fprintf(fp,"%s", i == nvars - 1 ? "\n" : " * "); | |
| 	if (retval == EOF) goto failure; | |
|     } | |
|     FREE(sorted); | |
|     sorted = NULL; | |
| 
 | |
|     /* Initialize symbol table for visited nodes. */ | |
|     visited = st_init_table(st_ptrcmp, st_ptrhash); | |
|     if (visited == NULL) goto failure; | |
| 
 | |
|     /* Call the function that really gets the job done. */ | |
|     for (i = 0; i < n; i++) { | |
| 	retval = ddDoDumpDDcal(dd,Cudd_Regular(f[i]),fp,visited,inames,mask); | |
| 	if (retval == 0) goto failure; | |
| 	if (onames == NULL) { | |
| 	    retval = fprintf(fp, "f%d = ", i); | |
| 	} else { | |
| 	    retval = fprintf(fp, "%s = ", onames[i]); | |
| 	} | |
| 	if (retval == EOF) goto failure; | |
| 	retval = fprintf(fp, "n%p%s\n", | |
| 			 (void *) (((ptruint) f[i] & mask) / | |
| 			 (ptruint) sizeof(DdNode)), | |
| 			 Cudd_IsComplement(f[i]) ? "'" : ""); | |
| 	if (retval == EOF) goto failure; | |
|     } | |
| 
 | |
|     /* Write trailer and return. */ | |
|     retval = fprintf(fp, "["); | |
|     if (retval == EOF) goto failure; | |
|     for (i = 0; i < n; i++) { | |
| 	if (onames == NULL) { | |
| 	    retval = fprintf(fp, "f%d", i); | |
| 	} else { | |
| 	    retval = fprintf(fp, "%s", onames[i]); | |
| 	} | |
| 	retval = fprintf(fp, "%s", i == n-1 ? "" : " "); | |
| 	if (retval == EOF) goto failure; | |
|     } | |
|     retval = fprintf(fp, "]\n"); | |
|     if (retval == EOF) goto failure; | |
| 
 | |
|     st_free_table(visited); | |
|     return(1); | |
| 
 | |
| failure: | |
|     if (sorted != NULL) FREE(sorted); | |
|     if (support != NULL) Cudd_RecursiveDeref(dd,support); | |
|     if (visited != NULL) st_free_table(visited); | |
|     return(0); | |
| 
 | |
| } /* end of Cudd_DumpDDcal */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Writes factored forms representing the argument BDDs.] | |
|  | |
|   Description [Writes factored forms representing the argument BDDs. | |
|   The format of the factored form is the one used in the genlib files | |
|   for technology mapping in sis.  It returns 1 in case of success; 0 | |
|   otherwise (e.g., file system full).  Cudd_DumpFactoredForm does not | |
|   close the file: This is the caller responsibility. Caution must be | |
|   exercised because a factored form may be exponentially larger than | |
|   the argument BDD.  If the argument inames is non-null, it is assumed | |
|   to hold the pointers to the names of the inputs. Similarly for | |
|   onames.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci | |
|   Cudd_DumpDDcal] | |
|  | |
| ******************************************************************************/ | |
| int | |
| Cudd_DumpFactoredForm( | |
|   DdManager * dd /* manager */, | |
|   int  n /* number of output nodes to be dumped */, | |
|   DdNode ** f /* array of output nodes to be dumped */, | |
|   char ** inames /* array of input names (or NULL) */, | |
|   char ** onames /* array of output names (or NULL) */, | |
|   FILE * fp /* pointer to the dump file */) | |
| { | |
|     int		retval; | |
|     int		i; | |
| 
 | |
|     /* Call the function that really gets the job done. */ | |
|     for (i = 0; i < n; i++) { | |
| 	if (onames == NULL) { | |
| 	    retval = fprintf(fp, "f%d = ", i); | |
| 	} else { | |
| 	    retval = fprintf(fp, "%s = ", onames[i]); | |
| 	} | |
| 	if (retval == EOF) return(0); | |
| 	if (f[i] == DD_ONE(dd)) { | |
| 	    retval = fprintf(fp, "CONST1"); | |
| 	    if (retval == EOF) return(0); | |
| 	} else if (f[i] == Cudd_Not(DD_ONE(dd)) || f[i] == DD_ZERO(dd)) { | |
| 	    retval = fprintf(fp, "CONST0"); | |
| 	    if (retval == EOF) return(0); | |
| 	} else { | |
| 	    retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? "!(" : ""); | |
| 	    if (retval == EOF) return(0); | |
| 	    retval = ddDoDumpFactoredForm(dd,Cudd_Regular(f[i]),fp,inames); | |
| 	    if (retval == 0) return(0); | |
| 	    retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? ")" : ""); | |
| 	    if (retval == EOF) return(0); | |
| 	} | |
| 	retval = fprintf(fp, "%s", i == n-1 ? "" : "\n"); | |
| 	if (retval == EOF) return(0); | |
|     } | |
| 
 | |
|     return(1); | |
| 
 | |
| } /* end of Cudd_DumpFactoredForm */ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of internal functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of static functions                                            */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Performs the recursive step of Cudd_DumpBlif.] | |
|  | |
|   Description [Performs the recursive step of Cudd_DumpBlif. Traverses | |
|   the BDD f and writes a multiplexer-network description to the file | |
|   pointed by fp in blif format. f is assumed to be a regular pointer | |
|   and ddDoDumpBlif guarantees this assumption in the recursive calls.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static int | |
| ddDoDumpBlif( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   FILE * fp, | |
|   st_table * visited, | |
|   char ** names, | |
|   int mv) | |
| { | |
|     DdNode	*T, *E; | |
|     int		retval; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(!Cudd_IsComplement(f)); | |
| #endif | |
|  | |
|     /* If already visited, nothing to do. */ | |
|     if (st_is_member(visited, (char *) f) == 1) | |
| 	return(1); | |
| 
 | |
|     /* Check for abnormal condition that should never happen. */ | |
|     if (f == NULL) | |
| 	return(0); | |
| 
 | |
|     /* Mark node as visited. */ | |
|     if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM) | |
| 	return(0); | |
| 
 | |
|     /* Check for special case: If constant node, generate constant 1. */ | |
|     if (f == DD_ONE(dd)) { | |
| #if SIZEOF_VOID_P == 8 | |
| 	retval = fprintf(fp, ".names %lx\n1\n",(ptruint) f / (ptruint) sizeof(DdNode)); | |
| #else | |
| 	retval = fprintf(fp, ".names %x\n1\n",(ptruint) f / (ptruint) sizeof(DdNode)); | |
| #endif | |
| 	if (retval == EOF) { | |
| 	    return(0); | |
| 	} else { | |
| 	    return(1); | |
| 	} | |
|     } | |
| 
 | |
|     /* Check whether this is an ADD. We deal with 0-1 ADDs, but not | |
|     ** with the general case. | |
|     */ | |
|     if (f == DD_ZERO(dd)) { | |
| #if SIZEOF_VOID_P == 8 | |
| 	retval = fprintf(fp, ".names %lx\n%s", | |
| 			 (ptruint) f / (ptruint) sizeof(DdNode), | |
| 			 mv ? "0\n" : ""); | |
| #else | |
| 	retval = fprintf(fp, ".names %x\n%s", | |
| 			 (ptruint) f / (ptruint) sizeof(DdNode), | |
| 			 mv ? "0\n" : ""); | |
| #endif | |
| 	if (retval == EOF) { | |
| 	    return(0); | |
| 	} else { | |
| 	    return(1); | |
| 	} | |
|     } | |
|     if (cuddIsConstant(f)) | |
| 	return(0); | |
| 
 | |
|     /* Recursive calls. */ | |
|     T = cuddT(f); | |
|     retval = ddDoDumpBlif(dd,T,fp,visited,names,mv); | |
|     if (retval != 1) return(retval); | |
|     E = Cudd_Regular(cuddE(f)); | |
|     retval = ddDoDumpBlif(dd,E,fp,visited,names,mv); | |
|     if (retval != 1) return(retval); | |
| 
 | |
|     /* Write multiplexer taking complement arc into account. */ | |
|     if (names != NULL) { | |
| 	retval = fprintf(fp,".names %s", names[f->index]); | |
|     } else { | |
| #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 | |
| 	retval = fprintf(fp,".names %u", f->index); | |
| #else | |
| 	retval = fprintf(fp,".names %hu", f->index); | |
| #endif | |
|     } | |
|     if (retval == EOF) | |
| 	return(0); | |
| 
 | |
| #if SIZEOF_VOID_P == 8 | |
|     if (mv) { | |
| 	if (Cudd_IsComplement(cuddE(f))) { | |
| 	    retval = fprintf(fp," %lx %lx %lx\n.def 0\n1 1 - 1\n0 - 0 1\n", | |
| 		(ptruint) T / (ptruint) sizeof(DdNode), | |
| 		(ptruint) E / (ptruint) sizeof(DdNode), | |
| 		(ptruint) f / (ptruint) sizeof(DdNode)); | |
| 	} else { | |
| 	    retval = fprintf(fp," %lx %lx %lx\n.def 0\n1 1 - 1\n0 - 1 1\n", | |
| 		(ptruint) T / (ptruint) sizeof(DdNode), | |
| 		(ptruint) E / (ptruint) sizeof(DdNode), | |
| 		(ptruint) f / (ptruint) sizeof(DdNode)); | |
| 	} | |
|     } else { | |
| 	if (Cudd_IsComplement(cuddE(f))) { | |
| 	    retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-0 1\n", | |
| 		(ptruint) T / (ptruint) sizeof(DdNode), | |
| 		(ptruint) E / (ptruint) sizeof(DdNode), | |
| 		(ptruint) f / (ptruint) sizeof(DdNode)); | |
| 	} else { | |
| 	    retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-1 1\n", | |
| 		(ptruint) T / (ptruint) sizeof(DdNode), | |
| 		(ptruint) E / (ptruint) sizeof(DdNode), | |
| 		(ptruint) f / (ptruint) sizeof(DdNode)); | |
| 	} | |
|     } | |
| #else | |
|     if (mv) { | |
| 	if (Cudd_IsComplement(cuddE(f))) { | |
| 	    retval = fprintf(fp," %x %x %x\n.def 0\n1 1 - 1\n0 - 0 1\n", | |
| 		(ptruint) T / (ptruint) sizeof(DdNode), | |
| 		(ptruint) E / (ptruint) sizeof(DdNode), | |
| 		(ptruint) f / (ptruint) sizeof(DdNode)); | |
| 	} else { | |
| 	    retval = fprintf(fp," %x %x %x\n.def 0\n1 1 - 1\n0 - 1 1\n", | |
| 		(ptruint) T / (ptruint) sizeof(DdNode), | |
| 		(ptruint) E / (ptruint) sizeof(DdNode), | |
| 		(ptruint) f / (ptruint) sizeof(DdNode)); | |
| 	} | |
|     } else { | |
| 	if (Cudd_IsComplement(cuddE(f))) { | |
| 	    retval = fprintf(fp," %x %x %x\n11- 1\n0-0 1\n", | |
| 		(ptruint) T / (ptruint) sizeof(DdNode), | |
| 		(ptruint) E / (ptruint) sizeof(DdNode), | |
| 		(ptruint) f / (ptruint) sizeof(DdNode)); | |
| 	} else { | |
| 	    retval = fprintf(fp," %x %x %x\n11- 1\n0-1 1\n", | |
| 		(ptruint) T / (ptruint) sizeof(DdNode), | |
| 		(ptruint) E / (ptruint) sizeof(DdNode), | |
| 		(ptruint) f / (ptruint) sizeof(DdNode)); | |
| 	} | |
|     } | |
| #endif | |
|     if (retval == EOF) { | |
| 	return(0); | |
|     } else { | |
| 	return(1); | |
|     } | |
| 
 | |
| } /* end of ddDoDumpBlif */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Performs the recursive step of Cudd_DumpDaVinci.] | |
|  | |
|   Description [Performs the recursive step of Cudd_DumpDaVinci. Traverses | |
|   the BDD f and writes a term expression to the file | |
|   pointed by fp in daVinci format. f is assumed to be a regular pointer | |
|   and ddDoDumpDaVinci guarantees this assumption in the recursive calls.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static int | |
| ddDoDumpDaVinci( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   FILE * fp, | |
|   st_table * visited, | |
|   char ** names, | |
|   ptruint mask) | |
| { | |
|     DdNode  *T, *E; | |
|     int	    retval; | |
|     ptruint id; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(!Cudd_IsComplement(f)); | |
| #endif | |
|  | |
|     id = ((ptruint) f & mask) / sizeof(DdNode); | |
| 
 | |
|     /* If already visited, insert a reference. */ | |
|     if (st_is_member(visited, (char *) f) == 1) { | |
| 	retval = fprintf(fp,"r(\"%p\")", (void *) id); | |
| 	if (retval == EOF) { | |
| 	    return(0); | |
| 	} else { | |
| 	    return(1); | |
| 	} | |
|     } | |
| 
 | |
|     /* Check for abnormal condition that should never happen. */ | |
|     if (f == NULL) | |
| 	return(0); | |
| 
 | |
|     /* Mark node as visited. */ | |
|     if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM) | |
| 	return(0); | |
| 
 | |
|     /* Check for special case: If constant node, generate constant 1. */ | |
|     if (Cudd_IsConstant(f)) { | |
| 	retval = fprintf(fp, | |
| 			 "l(\"%p\",n(\"constant\",[a(\"OBJECT\",\"%g\")],[]))", | |
| 			 (void *) id, cuddV(f)); | |
| 	if (retval == EOF) { | |
| 	    return(0); | |
| 	} else { | |
| 	    return(1); | |
| 	} | |
|     } | |
| 
 | |
|     /* Recursive calls. */ | |
|     if (names != NULL) { | |
| 	retval = fprintf(fp, | |
| 			 "l(\"%p\",n(\"internal\",[a(\"OBJECT\",\"%s\"),", | |
| 			 (void *) id, names[f->index]); | |
|     } else { | |
| 	retval = fprintf(fp, | |
| #if SIZEOF_VOID_P == 8 | |
| 			 "l(\"%p\",n(\"internal\",[a(\"OBJECT\",\"%u\"),", | |
| #else | |
| 			 "l(\"%p\",n(\"internal\",[a(\"OBJECT\",\"%hu\"),", | |
| #endif | |
| 			 (void *) id, f->index); | |
|     } | |
|     retval = fprintf(fp, "a(\"_GO\",\"ellipse\")],[e(\"then\",[a(\"EDGECOLOR\",\"blue\"),a(\"_DIR\",\"none\")],"); | |
|     if (retval == EOF) return(0); | |
|     T = cuddT(f); | |
|     retval = ddDoDumpDaVinci(dd,T,fp,visited,names,mask); | |
|     if (retval != 1) return(retval); | |
|     retval = fprintf(fp, "),e(\"else\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],", | |
| 		     Cudd_IsComplement(cuddE(f)) ? "red" : "green"); | |
|     if (retval == EOF) return(0); | |
|     E = Cudd_Regular(cuddE(f)); | |
|     retval = ddDoDumpDaVinci(dd,E,fp,visited,names,mask); | |
|     if (retval != 1) return(retval); | |
| 
 | |
|     retval = fprintf(fp,")]))"); | |
|     if (retval == EOF) { | |
| 	return(0); | |
|     } else { | |
| 	return(1); | |
|     } | |
| 
 | |
| } /* end of ddDoDumpDaVinci */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Performs the recursive step of Cudd_DumpDDcal.] | |
|  | |
|   Description [Performs the recursive step of Cudd_DumpDDcal. Traverses | |
|   the BDD f and writes a line for each node to the file | |
|   pointed by fp in DDcal format. f is assumed to be a regular pointer | |
|   and ddDoDumpDDcal guarantees this assumption in the recursive calls.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static int | |
| ddDoDumpDDcal( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   FILE * fp, | |
|   st_table * visited, | |
|   char ** names, | |
|   ptruint mask) | |
| { | |
|     DdNode  *T, *E; | |
|     int	    retval; | |
|     ptruint id, idT, idE; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(!Cudd_IsComplement(f)); | |
| #endif | |
|  | |
|     id = ((ptruint) f & mask) / sizeof(DdNode); | |
| 
 | |
|     /* If already visited, do nothing. */ | |
|     if (st_is_member(visited, (char *) f) == 1) { | |
| 	return(1); | |
|     } | |
| 
 | |
|     /* Check for abnormal condition that should never happen. */ | |
|     if (f == NULL) | |
| 	return(0); | |
| 
 | |
|     /* Mark node as visited. */ | |
|     if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM) | |
| 	return(0); | |
| 
 | |
|     /* Check for special case: If constant node, assign constant. */ | |
|     if (Cudd_IsConstant(f)) { | |
| 	if (f != DD_ONE(dd) && f != DD_ZERO(dd)) | |
| 	    return(0); | |
| 	retval = fprintf(fp, "n%p = %g\n", (void *) id, cuddV(f)); | |
| 	if (retval == EOF) { | |
| 	    return(0); | |
| 	} else { | |
| 	    return(1); | |
| 	} | |
|     } | |
| 
 | |
|     /* Recursive calls. */ | |
|     T = cuddT(f); | |
|     retval = ddDoDumpDDcal(dd,T,fp,visited,names,mask); | |
|     if (retval != 1) return(retval); | |
|     E = Cudd_Regular(cuddE(f)); | |
|     retval = ddDoDumpDDcal(dd,E,fp,visited,names,mask); | |
|     if (retval != 1) return(retval); | |
|     idT = ((ptruint) T & mask) / sizeof(DdNode); | |
|     idE = ((ptruint) E & mask) / sizeof(DdNode); | |
|     if (names != NULL) { | |
| 	retval = fprintf(fp, "n%p = %s * n%p + %s' * n%p%s\n", | |
| 			 (void *) id, names[f->index], | |
| 			 (void *) idT, names[f->index], | |
| 			 (void *) idE, Cudd_IsComplement(cuddE(f)) ? "'" : ""); | |
|     } else { | |
| #if SIZEOF_VOID_P == 8 | |
| 	retval = fprintf(fp, "n%p = v%u * n%p + v%u' * n%p%s\n", | |
| #else | |
| 	retval = fprintf(fp, "n%p = v%hu * n%p + v%hu' * n%p%s\n", | |
| #endif | |
| 			 (void *) id, f->index, | |
| 			 (void *) idT, f->index, | |
| 			 (void *) idE, Cudd_IsComplement(cuddE(f)) ? "'" : ""); | |
|     } | |
|     if (retval == EOF) { | |
| 	return(0); | |
|     } else { | |
| 	return(1); | |
|     } | |
| 
 | |
| } /* end of ddDoDumpDDcal */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Performs the recursive step of Cudd_DumpFactoredForm.] | |
|  | |
|   Description [Performs the recursive step of | |
|   Cudd_DumpFactoredForm. Traverses the BDD f and writes a factored | |
|   form for each node to the file pointed by fp in terms of the | |
|   factored forms of the children. Constants are propagated, and | |
|   absorption is applied.  f is assumed to be a regular pointer and | |
|   ddDoDumpFActoredForm guarantees this assumption in the recursive | |
|   calls.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_DumpFactoredForm] | |
|  | |
| ******************************************************************************/ | |
| static int | |
| ddDoDumpFactoredForm( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   FILE * fp, | |
|   char ** names) | |
| { | |
|     DdNode	*T, *E; | |
|     int		retval; | |
| 
 | |
| #ifdef DD_DEBUG | |
|     assert(!Cudd_IsComplement(f)); | |
|     assert(!Cudd_IsConstant(f)); | |
| #endif | |
|  | |
|     /* Check for abnormal condition that should never happen. */ | |
|     if (f == NULL) | |
| 	return(0); | |
| 
 | |
|     /* Recursive calls. */ | |
|     T = cuddT(f); | |
|     E = cuddE(f); | |
|     if (T != DD_ZERO(dd)) { | |
| 	if (E != DD_ONE(dd)) { | |
| 	    if (names != NULL) { | |
| 		retval = fprintf(fp, "%s", names[f->index]); | |
| 	    } else { | |
| #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 | |
| 		retval = fprintf(fp, "x%u", f->index); | |
| #else | |
| 		retval = fprintf(fp, "x%hu", f->index); | |
| #endif | |
| 	    } | |
| 	    if (retval == EOF) return(0); | |
| 	} | |
| 	if (T != DD_ONE(dd)) { | |
| 	    retval = fprintf(fp, "%s(", E != DD_ONE(dd) ? " * " : ""); | |
| 	    if (retval == EOF) return(0); | |
| 	    retval = ddDoDumpFactoredForm(dd,T,fp,names); | |
| 	    if (retval != 1) return(retval); | |
| 	    retval = fprintf(fp, ")"); | |
| 	    if (retval == EOF) return(0); | |
| 	} | |
| 	if (E == Cudd_Not(DD_ONE(dd)) || E == DD_ZERO(dd)) return(1); | |
| 	retval = fprintf(fp, " + "); | |
| 	if (retval == EOF) return(0); | |
|     } | |
|     E = Cudd_Regular(E); | |
|     if (T != DD_ONE(dd)) { | |
| 	if (names != NULL) { | |
| 	    retval = fprintf(fp, "!%s", names[f->index]); | |
| 	} else { | |
| #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 | |
| 	    retval = fprintf(fp, "!x%u", f->index); | |
| #else | |
| 	    retval = fprintf(fp, "!x%hu", f->index); | |
| #endif | |
| 	} | |
| 	if (retval == EOF) return(0); | |
|     } | |
|     if (E != DD_ONE(dd)) { | |
| 	retval = fprintf(fp, "%s%s(", T != DD_ONE(dd) ? " * " : "", | |
| 			 E != cuddE(f) ? "!" : ""); | |
| 	if (retval == EOF) return(0); | |
| 	retval = ddDoDumpFactoredForm(dd,E,fp,names); | |
| 	if (retval != 1) return(retval); | |
| 	retval = fprintf(fp, ")"); | |
| 	if (retval == EOF) return(0); | |
|     } | |
|     return(1); | |
| 
 | |
| } /* end of ddDoDumpFactoredForm */
 |