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 */
							 |