The source code and dockerfile for the GSW2024 AI Lab.
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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 
 
 

1522 lines
44 KiB

/**CFile**********************************************************************
FileName [dddmpStoreMisc.c]
PackageName [dddmp]
Synopsis [Functions to write out bdds to file in prefixed
and in Blif form.]
Description [Functions to write out bdds to file.
BDDs are represended on file in text format.
Each node is stored as a multiplexer in a prefix notation format for
the prefix notation file or in PLA format for the blif file.
]
Author [Gianpiero Cabodi and Stefano Quer]
Copyright [
Copyright (c) 2004 by Politecnico di Torino.
All Rights Reserved. This software is for educational purposes only.
Permission is given to academic institutions to use, copy, and modify
this software and its documentation provided that this introductory
message is not removed, that this software and its documentation is
used for the institutions' internal research and educational purposes,
and that no monies are exchanged. No guarantee is expressed or implied
by the distribution of this code.
Send bug-reports and/or questions to:
{gianpiero.cabodi,stefano.quer}@polito.it.
]
******************************************************************************/
#include "dddmpInt.h"
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static int DddmpCuddDdArrayStorePrefix(DdManager *ddMgr, int n, DdNode **f, char **inputNames, char **outputNames, char *modelName, FILE *fp);
static int DddmpCuddDdArrayStorePrefixBody(DdManager *ddMgr, int n, DdNode **f, char **inputNames, char **outputNames, FILE *fp);
static int DddmpCuddDdArrayStorePrefixStep(DdManager * ddMgr, DdNode * f, FILE * fp, st_table * visited, char ** names);
static int DddmpCuddDdArrayStoreBlif(DdManager *ddMgr, int n, DdNode **f, char **inputNames, char **outputNames, char *modelName, FILE *fp);
static int DddmpCuddDdArrayStoreBlifBody(DdManager *ddMgr, int n, DdNode **f, char **inputNames, char **outputNames, FILE *fp);
static int DddmpCuddDdArrayStoreBlifStep(DdManager *ddMgr, DdNode *f, FILE *fp, st_table *visited, char **names);
static int DddmpCuddDdArrayStoreSmv(DdManager *ddMgr, int n, DdNode **f, char **inputNames, char **outputNames, char *modelName, FILE *fp);
static int DddmpCuddDdArrayStoreSmvBody(DdManager *ddMgr, int n, DdNode **f, char **inputNames, char **outputNames, FILE *fp);
static int DddmpCuddDdArrayStoreSmvStep(DdManager * ddMgr, DdNode * f, FILE * fp, st_table * visited, char ** names);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Writes a dump file representing the argument BDD in
a prefix notation.]
Description [Dumps the argument BDD to file.
Dumping is done through Dddmp_cuddBddArrayStorePrefix.
A dummy array of 1 BDD root is used for this purpose.
]
SideEffects []
SeeAlso [Dddmp_cuddBddStore]
******************************************************************************/
int
Dddmp_cuddBddStorePrefix (
DdManager *ddMgr /* IN: DD Manager */,
int nRoots /* IN: Number of BDD roots */,
DdNode *f /* IN: BDD root to be stored */,
char **inputNames /* IN: Array of variable names */,
char **outputNames /* IN: Array of root names */,
char *modelName /* IN: Model Name */,
char *fileName /* IN: File name */,
FILE *fp /* IN: File pointer to the store file */
)
{
int retValue;
DdNode *tmpArray[1];
(void) nRoots; /* avoid warning */
tmpArray[0] = f;
retValue = Dddmp_cuddBddArrayStorePrefix (ddMgr, 1, tmpArray,
inputNames, outputNames, modelName, fileName, fp);
return (retValue);
}
/**Function********************************************************************
Synopsis [Writes a dump file representing the argument BDD in
a prefix notation.]
Description [Dumps the argument BDD to file.
Dumping is done through Dddmp_cuddBddArrayStorePrefix.
A dummy array of 1 BDD root is used for this purpose.
]
SideEffects []
SeeAlso [Dddmp_cuddBddArrayStore]
******************************************************************************/
int
Dddmp_cuddBddArrayStorePrefix (
DdManager *ddMgr /* IN: DD Manager */,
int nroots /* IN: number of output BDD roots to be stored */,
DdNode **f /* IN: array of BDD roots to be stored */,
char **inputNames /* IN: array of variable names (or NULL) */,
char **outputNames /* IN: array of root names (or NULL) */,
char *modelName /* IN: Model Name */,
char *fname /* IN: File name */,
FILE *fp /* IN: File pointer to the store file */
)
{
int retValue;
int fileToClose = 0;
#ifdef DDDMP_DEBUG
#ifndef __alpha__
int retValueBis;
retValueBis = Cudd_DebugCheck (ddMgr);
if (retValueBis == 1) {
fprintf (stderr, "Inconsistency Found During BDD Store.\n");
fflush (stderr);
} else {
if (retValueBis == CUDD_OUT_OF_MEM) {
fprintf (stderr, "Out of Memory During BDD Store.\n");
fflush (stderr);
}
}
#endif
#endif
/*
* Check if File needs to be opened in the proper mode.
*/
if (fp == NULL) {
fp = fopen (fname, "w");
Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.",
failure);
fileToClose = 1;
}
retValue = DddmpCuddDdArrayStorePrefix (ddMgr, nroots, f,
inputNames, outputNames, modelName, fp);
if (fileToClose) {
fclose (fp);
}
#ifdef DDDMP_DEBUG
#ifndef __alpha__
retValueBis = Cudd_DebugCheck (ddMgr);
if (retValueBis == 1) {
fprintf (stderr, "Inconsistency Found During BDD Store.\n");
fflush (stderr);
} else {
if (retValueBis == CUDD_OUT_OF_MEM) {
fprintf (stderr, "Out of Memory During BDD Store.\n");
fflush (stderr);
}
}
#endif
#endif
return (retValue);
failure:
return (DDDMP_FAILURE);
}
/**Function********************************************************************
Synopsis [Writes a dump file representing the argument BDD in
a Blif/Exlif notation.]
Description [Dumps the argument BDD to file.
Dumping is done through Dddmp_cuddBddArrayStoreBlif.
A dummy array of 1 BDD root is used for this purpose.
]
SideEffects []
SeeAlso [Dddmp_cuddBddStorePrefix]
******************************************************************************/
int
Dddmp_cuddBddStoreBlif (
DdManager *ddMgr /* IN: DD Manager */,
int nRoots /* IN: Number of BDD roots */,
DdNode *f /* IN: BDD root to be stored */,
char **inputNames /* IN: Array of variable names */,
char **outputNames /* IN: Array of root names */,
char *modelName /* IN: Model Name */,
char *fileName /* IN: File name */,
FILE *fp /* IN: File pointer to the store file */
)
{
int retValue;
DdNode *tmpArray[1];
(void) nRoots; /* avoid warning */
tmpArray[0] = f;
retValue = Dddmp_cuddBddArrayStoreBlif (ddMgr, 1, tmpArray,
inputNames, outputNames, modelName, fileName, fp);
return (retValue);
}
/**Function********************************************************************
Synopsis [Writes a dump file representing the argument BDD in
a Blif/Exlif notation.]
Description [Dumps the argument BDD to file.
Dumping is done through Dddmp_cuddBddArrayStoreBLif.
A dummy array of 1 BDD root is used for this purpose.
]
SideEffects []
SeeAlso [Dddmp_cuddBddArrayStorePrefix]
******************************************************************************/
int
Dddmp_cuddBddArrayStoreBlif (
DdManager *ddMgr /* IN: DD Manager */,
int nroots /* IN: number of output BDD roots to be stored */,
DdNode **f /* IN: array of BDD roots to be stored */,
char **inputNames /* IN: array of variable names (or NULL) */,
char **outputNames /* IN: array of root names (or NULL) */,
char *modelName /* IN: Model Name */,
char *fname /* IN: File name */,
FILE *fp /* IN: File pointer to the store file */
)
{
int retValue;
int fileToClose = 0;
#ifdef DDDMP_DEBUG
#ifndef __alpha__
int retValueBis;
retValueBis = Cudd_DebugCheck (ddMgr);
if (retValueBis == 1) {
fprintf (stderr, "Inconsistency Found During BDD Store.\n");
fflush (stderr);
} else {
if (retValueBis == CUDD_OUT_OF_MEM) {
fprintf (stderr, "Out of Memory During BDD Store.\n");
fflush (stderr);
}
}
#endif
#endif
/*
* Check if File needs to be opened in the proper mode.
*/
if (fp == NULL) {
fp = fopen (fname, "w");
Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.",
failure);
fileToClose = 1;
}
retValue = DddmpCuddDdArrayStoreBlif (ddMgr, nroots, f,
inputNames, outputNames, modelName, fp);
if (fileToClose) {
fclose (fp);
}
#ifdef DDDMP_DEBUG
#ifndef __alpha__
retValueBis = Cudd_DebugCheck (ddMgr);
if (retValueBis == 1) {
fprintf (stderr, "Inconsistency Found During BDD Store.\n");
fflush (stderr);
} else {
if (retValueBis == CUDD_OUT_OF_MEM) {
fprintf (stderr, "Out of Memory During BDD Store.\n");
fflush (stderr);
}
}
#endif
#endif
return (retValue);
failure:
return (DDDMP_FAILURE);
}
/**Function********************************************************************
Synopsis [Writes a dump file representing the argument BDD in
a prefix notation.]
Description [Dumps the argument BDD to file.
Dumping is done through Dddmp_cuddBddArrayStorePrefix.
A dummy array of 1 BDD root is used for this purpose.
]
SideEffects []
SeeAlso [Dddmp_cuddBddStore]
******************************************************************************/
int
Dddmp_cuddBddStoreSmv (
DdManager *ddMgr /* IN: DD Manager */,
int nRoots /* IN: Number of BDD roots */,
DdNode *f /* IN: BDD root to be stored */,
char **inputNames /* IN: Array of variable names */,
char **outputNames /* IN: Array of root names */,
char *modelName /* IN: Model Name */,
char *fileName /* IN: File name */,
FILE *fp /* IN: File pointer to the store file */
)
{
int retValue;
DdNode *tmpArray[1];
(void) nRoots; /* avoid warning */
tmpArray[0] = f;
retValue = Dddmp_cuddBddArrayStoreSmv (ddMgr, 1, tmpArray,
inputNames, outputNames, modelName, fileName, fp);
return (retValue);
}
/**Function********************************************************************
Synopsis [Writes a dump file representing the argument BDD in
a prefix notation.]
Description [Dumps the argument BDD to file.
Dumping is done through Dddmp_cuddBddArrayStorePrefix.
A dummy array of 1 BDD root is used for this purpose.
]
SideEffects []
SeeAlso [Dddmp_cuddBddArrayStore]
******************************************************************************/
int
Dddmp_cuddBddArrayStoreSmv (
DdManager *ddMgr /* IN: DD Manager */,
int nroots /* IN: number of output BDD roots to be stored */,
DdNode **f /* IN: array of BDD roots to be stored */,
char **inputNames /* IN: array of variable names (or NULL) */,
char **outputNames /* IN: array of root names (or NULL) */,
char *modelName /* IN: Model Name */,
char *fname /* IN: File name */,
FILE *fp /* IN: File pointer to the store file */
)
{
int retValue;
int fileToClose = 0;
#ifdef DDDMP_DEBUG
#ifndef __alpha__
int retValueBis;
retValueBis = Cudd_DebugCheck (ddMgr);
if (retValueBis == 1) {
fprintf (stderr, "Inconsistency Found During BDD Store.\n");
fflush (stderr);
} else {
if (retValueBis == CUDD_OUT_OF_MEM) {
fprintf (stderr, "Out of Memory During BDD Store.\n");
fflush (stderr);
}
}
#endif
#endif
/*
* Check if File needs to be opened in the proper mode.
*/
if (fp == NULL) {
fp = fopen (fname, "w");
Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.",
failure);
fileToClose = 1;
}
retValue = DddmpCuddDdArrayStoreSmv (ddMgr, nroots, f,
inputNames, outputNames, modelName, fp);
if (fileToClose) {
fclose (fp);
}
#ifdef DDDMP_DEBUG
#ifndef __alpha__
retValueBis = Cudd_DebugCheck (ddMgr);
if (retValueBis == 1) {
fprintf (stderr, "Inconsistency Found During BDD Store.\n");
fflush (stderr);
} else {
if (retValueBis == CUDD_OUT_OF_MEM) {
fprintf (stderr, "Out of Memory During BDD Store.\n");
fflush (stderr);
}
}
#endif
#endif
return (retValue);
failure:
return (DDDMP_FAILURE);
}
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Internal function to writes a dump file representing the
argument BDD in a prefix notation.]
Description [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).
It does not close the file: This is the caller responsibility.
It uses a minimal unique subset of the hexadecimal address of a node as
name for it.
If the argument inputNames is non-null, it is assumed to hold the
pointers to the names of the inputs. Similarly for outputNames.
For each BDD node of function f, variable v, then child T, and else
child E it stores:
f = v * T + v' * E
that is
(OR f (AND v T) (AND (NOT v) E))
If E is a complemented child this results in the following
(OR f (AND v T) (AND (NOT v) (NOT E)))
Comments (COMMENT) are added at the beginning of the description to
describe inputs and outputs of the design.
A buffer (BUF) is add on the output to cope with complemented functions.
]
SideEffects [None]
SeeAlso [DddmpCuddDdArrayStoreBlif]
******************************************************************************/
static int
DddmpCuddDdArrayStorePrefix (
DdManager *ddMgr /* IN: Manager */,
int n /* IN: Number of output nodes to be dumped */,
DdNode **f /* IN: Array of output nodes to be dumped */,
char **inputNames /* IN: Array of input names (or NULL) */,
char **outputNames /* IN: Array of output names (or NULL) */,
char *modelName /* IN: Model name (or NULL) */,
FILE *fp /* IN: Pointer to the dump file */
)
{
DdNode *support = NULL;
DdNode *scan;
int *sorted = NULL;
int nVars = ddMgr->size;
int retValue;
int i;
/* Build a bit array with the support of f. */
sorted = ALLOC(int, nVars);
if (sorted == NULL) {
ddMgr->errorCode = CUDD_MEMORY_OUT;
Dddmp_CheckAndGotoLabel (1, "Allocation Error.", failure);
}
for (i = 0; i < nVars; i++) {
sorted[i] = 0;
}
/* Take the union of the supports of each output function. */
support = Cudd_VectorSupport(ddMgr,f,n);
Dddmp_CheckAndGotoLabel (support==NULL,
"Error in function Cudd_VectorSupport.", failure);
cuddRef(support);
scan = support;
while (!cuddIsConstant(scan)) {
sorted[scan->index] = 1;
scan = cuddT(scan);
}
Cudd_RecursiveDeref(ddMgr,support);
/* so that we do not try to free it in case of failure */
support = NULL;
/* Write the header (.model .inputs .outputs). */
if (modelName == NULL) {
retValue = fprintf (fp, "(COMMENT - model name: Unknown )\n");
} else {
retValue = fprintf (fp, "(COMMENT - model name: %s )\n", modelName);
}
if (retValue == EOF) {
return(0);
}
retValue = fprintf(fp, "(COMMENT - input names: ");
if (retValue == EOF) {
return(0);
}
/* Write the input list by scanning the support array. */
for (i = 0; i < nVars; i++) {
if (sorted[i]) {
if (inputNames == NULL) {
retValue = fprintf(fp," inNode%d", i);
} else {
retValue = fprintf(fp," %s", inputNames[i]);
}
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
}
}
FREE(sorted);
sorted = NULL;
retValue = fprintf(fp, " )\n");
if (retValue == EOF) {
return(0);
}
/* Write the .output line. */
retValue = fprintf(fp,"(COMMENT - output names: ");
if (retValue == EOF) {
return(0);
}
for (i = 0; i < n; i++) {
if (outputNames == NULL) {
retValue = fprintf (fp," outNode%d", i);
} else {
retValue = fprintf (fp," %s", outputNames[i]);
}
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
}
retValue = fprintf(fp, " )\n");
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
retValue = DddmpCuddDdArrayStorePrefixBody (ddMgr, n, f, inputNames,
outputNames, fp);
Dddmp_CheckAndGotoLabel (retValue==0,
"Error in function DddmpCuddDdArrayStorePrefixBody.", failure);
return(1);
failure:
if (sorted != NULL) {
FREE(sorted);
}
if (support != NULL) {
Cudd_RecursiveDeref(ddMgr,support);
}
return(0);
}
/**Function********************************************************************
Synopsis [Internal function to writes a dump file representing the
argument BDD in a prefix notation. Writes the body of the file.]
Description [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).
It does not close the file: This is the caller responsibility.
It uses a minimal unique subset of the hexadecimal address of a node as
name for it.
If the argument inputNames is non-null, it is assumed to hold the
pointers to the names of the inputs. Similarly for outputNames.
For each BDD node of function f, variable v, then child T, and else
child E it stores:
f = v * T + v' * E
that is
(OR f (AND v T) (AND (NOT v) E))
If E is a complemented child this results in the following
(OR f (AND v T) (AND (NOT v) (NOT E)))
]
SideEffects [None]
SeeAlso [DddmpCuddDdArrayStoreBlif]
******************************************************************************/
static int
DddmpCuddDdArrayStorePrefixBody (
DdManager *ddMgr /* IN: Manager */,
int n /* IN: Number of output nodes to be dumped */,
DdNode **f /* IN: Array of output nodes to be dumped */,
char **inputNames /* IN: Array of input names (or NULL) */,
char **outputNames /* IN: Array of output names (or NULL) */,
FILE *fp /* IN: Pointer to the dump file */
)
{
st_table *visited = NULL;
int retValue;
int i;
/* Initialize symbol table for visited nodes. */
visited = st_init_table(st_ptrcmp, st_ptrhash);
Dddmp_CheckAndGotoLabel (visited==NULL,
"Error if function st_init_table.", failure);
/* Call the function that really gets the job done. */
for (i = 0; i < n; i++) {
retValue = DddmpCuddDdArrayStorePrefixStep (ddMgr, Cudd_Regular(f[i]),
fp, visited, inputNames);
Dddmp_CheckAndGotoLabel (retValue==0,
"Error if function DddmpCuddDdArrayStorePrefixStep.", 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 (outputNames == NULL) {
retValue = fprintf (fp, "(BUF outNode%d ", i);
} else {
retValue = fprintf (fp, "(BUF %s ", outputNames[i]);
}
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
if (Cudd_IsComplement(f[i])) {
retValue = fprintf (fp, "(NOT node%" PRIxPTR "))\n",
(ptruint) f[i] / sizeof(DdNode));
} else {
retValue = fprintf (fp, "node%" PRIxPTR ")\n",
(ptruint) f[i] / sizeof(DdNode));
}
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
}
st_free_table (visited);
return(1);
failure:
if (visited != NULL) st_free_table(visited);
return(0);
}
/**Function********************************************************************
Synopsis [Performs the recursive step of
DddmpCuddDdArrayStorePrefixBody.]
Description [Performs the recursive step of
DddmpCuddDdArrayStorePrefixBody.
Traverses the BDD f and writes a multiplexer-network description to the
file pointed by fp.
For each BDD node of function f, variable v, then child T, and else
child E it stores:
f = v * T + v' * E
that is
(OR f (AND v T) (AND (NOT v) E))
If E is a complemented child this results in the following
(OR f (AND v T) (AND (NOT v) (NOT E)))
f is assumed to be a regular pointer and the function guarantees this
assumption in the recursive calls.
]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
DddmpCuddDdArrayStorePrefixStep (
DdManager * ddMgr,
DdNode * f,
FILE * fp,
st_table * visited,
char ** names
)
{
DdNode *T, *E;
int retValue;
#ifdef DDDMP_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 (ddMgr)) {
retValue = fprintf (fp, "(OR node%" PRIxPTR " vss vdd)\n",
(ptruint) f / sizeof(DdNode));
if (retValue == 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(ddMgr)) {
retValue = fprintf (fp, "(AND node%" PRIxPTR " vss vdd)\n",
(ptruint) f / sizeof(DdNode));
if (retValue == EOF) {
return(0);
} else {
return(1);
}
}
if (cuddIsConstant(f)) {
return(0);
}
/* Recursive calls. */
T = cuddT(f);
retValue = DddmpCuddDdArrayStorePrefixStep (ddMgr,T,fp,visited,names);
if (retValue != 1) {
return(retValue);
}
E = Cudd_Regular(cuddE(f));
retValue = DddmpCuddDdArrayStorePrefixStep (ddMgr,E,fp,visited,names);
if (retValue != 1) {
return(retValue);
}
/* Write multiplexer taking complement arc into account. */
retValue = fprintf (fp, "(OR node%" PRIxPTR " (AND ",
(ptruint) f / sizeof(DdNode));
if (retValue == EOF) {
return(0);
}
if (names != NULL) {
retValue = fprintf(fp, "%s ", names[f->index]);
} else {
retValue = fprintf(fp, "inNode%d ", f->index);
}
if (retValue == EOF) {
return(0);
}
retValue = fprintf (fp, "node%" PRIxPTR ") (AND (NOT ",
(ptruint) T / sizeof(DdNode));
if (retValue == EOF) {
return(0);
}
if (names != NULL) {
retValue = fprintf (fp, "%s", names[f->index]);
} else {
retValue = fprintf (fp, "inNode%d", f->index);
}
if (retValue == EOF) {
return(0);
}
if (Cudd_IsComplement(cuddE(f))) {
retValue = fprintf (fp, ") (NOT node%" PRIxPTR ")))\n",
(ptruint) E / sizeof(DdNode));
} else {
retValue = fprintf (fp, ") node%" PRIxPTR "))\n",
(ptruint) E / sizeof(DdNode));
}
if (retValue == EOF) {
return(0);
} else {
return(1);
}
}
/**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).
DddmpCuddDdArrayStoreBlif does not close the file: This is the
caller responsibility.
DddmpCuddDdArrayStoreBlif 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 outputNames.
It prefixes the string "NODE" to each nome to have "regular" names
for each elements.
]
SideEffects [None]
SeeAlso [DddmpCuddDdArrayStoreBlifBody,Cudd_DumpBlif]
******************************************************************************/
static int
DddmpCuddDdArrayStoreBlif (
DdManager *ddMgr /* IN: Manager */,
int n /* IN: Number of output nodes to be dumped */,
DdNode **f /* IN: Array of output nodes to be dumped */,
char **inputNames /* IN: Array of input names (or NULL) */,
char **outputNames /* IN: Array of output names (or NULL) */,
char *modelName /* IN: Model name (or NULL) */,
FILE *fp /* IN: Pointer to the dump file */
)
{
DdNode *support = NULL;
DdNode *scan;
int *sorted = NULL;
int nVars = ddMgr->size;
int retValue;
int i;
/* Build a bit array with the support of f. */
sorted = ALLOC (int, nVars);
if (sorted == NULL) {
ddMgr->errorCode = CUDD_MEMORY_OUT;
Dddmp_CheckAndGotoLabel (1, "Allocation Error.", failure);
}
for (i = 0; i < nVars; i++) {
sorted[i] = 0;
}
/* Take the union of the supports of each output function. */
support = Cudd_VectorSupport(ddMgr,f,n);
Dddmp_CheckAndGotoLabel (support==NULL,
"Error in function Cudd_VectorSupport.", failure);
cuddRef(support);
scan = support;
while (!cuddIsConstant(scan)) {
sorted[scan->index] = 1;
scan = cuddT(scan);
}
Cudd_RecursiveDeref(ddMgr,support);
support = NULL;
/* so that we do not try to free it in case of failure */
/* Write the header (.model .inputs .outputs). */
if (modelName == NULL) {
retValue = fprintf(fp,".model DD\n.inputs");
} else {
retValue = fprintf(fp,".model %s\n.inputs", modelName);
}
if (retValue == EOF) {
return(0);
}
/* Write the input list by scanning the support array. */
for (i = 0; i < nVars; i++) {
if (sorted[i]) {
if (inputNames == NULL || (inputNames[i] == NULL)) {
retValue = fprintf(fp," inNode%d", i);
} else {
retValue = fprintf(fp," %s", inputNames[i]);
}
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
}
}
FREE(sorted);
sorted = NULL;
/* Write the .output line. */
retValue = fprintf(fp,"\n.outputs");
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
for (i = 0; i < n; i++) {
if (outputNames == NULL || (outputNames[i] == NULL)) {
retValue = fprintf(fp," outNode%d", i);
} else {
retValue = fprintf(fp," %s", outputNames[i]);
}
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
}
retValue = fprintf(fp,"\n");
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
retValue = DddmpCuddDdArrayStoreBlifBody(ddMgr, n, f, inputNames,
outputNames, fp);
Dddmp_CheckAndGotoLabel (retValue==0,
"Error if function DddmpCuddDdArrayStoreBlifBody.", failure);
/* Write trailer and return. */
retValue = fprintf (fp, ".end\n");
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
return(1);
failure:
if (sorted != NULL) {
FREE(sorted);
}
if (support != NULL) {
Cudd_RecursiveDeref(ddMgr,support);
}
return(0);
}
/**Function********************************************************************
Synopsis [Writes a blif body representing the argument BDDs.]
Description [Writes a blif body 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).
DddmpCuddDdArrayStoreBlif does not close the file: This is the
caller responsibility.
DddmpCuddDdArrayStoreBlif uses a minimal unique subset of
the hexadecimal address of a node as name for it. If the argument
inputNames is non-null, it is assumed to hold the pointers to the names
of the inputs. Similarly for outputNames. This function prints out only
.names part.
]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
DddmpCuddDdArrayStoreBlifBody (
DdManager *ddMgr /* IN: Manager */,
int n /* IN: Number of output nodes to be dumped */,
DdNode **f /* IN: Array of output nodes to be dumped */,
char **inputNames /* IN: Array of input names (or NULL) */,
char **outputNames /* IN: Array of output names (or NULL) */,
FILE *fp /* IN: Pointer to the dump file */
)
{
st_table *visited = NULL;
int retValue;
int i;
/* Initialize symbol table for visited nodes. */
visited = st_init_table(st_ptrcmp, st_ptrhash);
Dddmp_CheckAndGotoLabel (visited==NULL,
"Error if function st_init_table.", failure);
/* Call the function that really gets the job done. */
for (i = 0; i < n; i++) {
retValue = DddmpCuddDdArrayStoreBlifStep (ddMgr, Cudd_Regular(f[i]),
fp, visited, inputNames);
Dddmp_CheckAndGotoLabel (retValue==0,
"Error if function DddmpCuddDdArrayStoreBlifStep.", 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 (outputNames == NULL) {
retValue = fprintf(fp, ".names node%" PRIxPTR " outNode%d\n",
(ptruint) f[i] / sizeof(DdNode), i);
} else {
retValue = fprintf(fp, ".names node%" PRIxPTR " %s\n",
(ptruint) f[i] / sizeof(DdNode), outputNames[i]);
}
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
if (Cudd_IsComplement(f[i])) {
retValue = fprintf(fp,"0 1\n");
} else {
retValue = fprintf(fp,"1 1\n");
}
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
}
st_free_table(visited);
return(1);
failure:
if (visited != NULL) {
st_free_table(visited);
}
return(0);
}
/**Function********************************************************************
Synopsis [Performs the recursive step of DddmpCuddDdArrayStoreBlif.]
Description [Performs the recursive step of DddmpCuddDdArrayStoreBlif.
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 DddmpCuddDdArrayStoreBlifStep
guarantees this assumption in the recursive calls.
]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
DddmpCuddDdArrayStoreBlifStep (
DdManager *ddMgr,
DdNode *f,
FILE *fp,
st_table *visited,
char **names
)
{
DdNode *T, *E;
int retValue;
#ifdef DDDMP_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(ddMgr)) {
retValue = fprintf(fp, ".names node%" PRIxPTR "\n1\n",
(ptruint) f / sizeof(DdNode));
if (retValue == 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(ddMgr)) {
retValue = fprintf(fp, ".names node%" PRIxPTR "\n",
(ptruint) f / sizeof(DdNode));
if (retValue == EOF) {
return(0);
} else {
return(1);
}
}
if (cuddIsConstant(f)) {
return(0);
}
/* Recursive calls. */
T = cuddT(f);
retValue = DddmpCuddDdArrayStoreBlifStep(ddMgr,T,fp,visited,names);
if (retValue != 1) return(retValue);
E = Cudd_Regular(cuddE(f));
retValue = DddmpCuddDdArrayStoreBlifStep(ddMgr,E,fp,visited,names);
if (retValue != 1) return(retValue);
/* Write multiplexer taking complement arc into account. */
if (names != NULL) {
retValue = fprintf(fp,".names %s", names[f->index]);
} else {
retValue = fprintf(fp,".names inNode%d", f->index);
}
if (retValue == EOF) {
return(0);
}
if (Cudd_IsComplement(cuddE(f))) {
retValue = fprintf(fp,
" node%" PRIxPTR " node%" PRIxPTR " node%" PRIxPTR "\n11- 1\n0-0 1\n",
(ptruint) T / sizeof(DdNode),
(ptruint) E / sizeof(DdNode),
(ptruint) f / sizeof(DdNode));
} else {
retValue = fprintf(fp,
" node%" PRIxPTR " node%" PRIxPTR " node%" PRIxPTR "\n11- 1\n0-1 1\n",
(ptruint) T / sizeof(DdNode),
(ptruint) E / sizeof(DdNode),
(ptruint) f / sizeof(DdNode));
}
if (retValue == EOF) {
return(0);
} else {
return(1);
}
}
/**Function********************************************************************
Synopsis [Internal function to writes a dump file representing the
argument BDD in a SMV notation.]
Description [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).
It does not close the file: This is the caller responsibility.
It uses a minimal unique subset of the hexadecimal address of a node as
name for it.
If the argument inputNames is non-null, it is assumed to hold the
pointers to the names of the inputs. Similarly for outputNames.
For each BDD node of function f, variable v, then child T, and else
child E it stores:
f = v * T + v' * E
that is
(OR f (AND v T) (AND (NOT v) E))
If E is a complemented child this results in the following
(OR f (AND v T) (AND (NOT v) (NOT E)))
Comments (COMMENT) are added at the beginning of the description to
describe inputs and outputs of the design.
A buffer (BUF) is add on the output to cope with complemented functions.
]
SideEffects [None]
SeeAlso [DddmpCuddDdArrayStoreBlif]
******************************************************************************/
static int
DddmpCuddDdArrayStoreSmv (
DdManager *ddMgr /* IN: Manager */,
int n /* IN: Number of output nodes to be dumped */,
DdNode **f /* IN: Array of output nodes to be dumped */,
char **inputNames /* IN: Array of input names (or NULL) */,
char **outputNames /* IN: Array of output names (or NULL) */,
char *modelName /* IN: Model name (or NULL) */,
FILE *fp /* IN: Pointer to the dump file */
)
{
DdNode *support = NULL;
DdNode *scan;
int *sorted = NULL;
int nVars = ddMgr->size;
int retValue;
int i;
/* Build a bit array with the support of f. */
sorted = ALLOC(int, nVars);
if (sorted == NULL) {
ddMgr->errorCode = CUDD_MEMORY_OUT;
Dddmp_CheckAndGotoLabel (1, "Allocation Error.", failure);
}
for (i = 0; i < nVars; i++) {
sorted[i] = 0;
}
/* Take the union of the supports of each output function. */
support = Cudd_VectorSupport(ddMgr,f,n);
Dddmp_CheckAndGotoLabel (support==NULL,
"Error in function Cudd_VectorSupport.", failure);
cuddRef(support);
scan = support;
while (!cuddIsConstant(scan)) {
sorted[scan->index] = 1;
scan = cuddT(scan);
}
Cudd_RecursiveDeref(ddMgr,support);
/* so that we do not try to free it in case of failure */
support = NULL;
/* Write the header */
if (modelName == NULL) {
retValue = fprintf (fp, "MODULE main -- Unknown\n");
} else {
retValue = fprintf (fp, "MODULE main -- %s\n", modelName);
}
if (retValue == EOF) {
return(0);
}
retValue = fprintf(fp, "IVAR\n");
if (retValue == EOF) {
return(0);
}
/* Write the input list by scanning the support array. */
for (i=0; i<nVars; i++) {
if (sorted[i]) {
if (inputNames == NULL) {
retValue = fprintf (fp, " inNode%d : boolean;\n", i);
} else {
retValue = fprintf (fp, " %s : boolean;\n", inputNames[i]);
}
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
}
}
FREE(sorted);
sorted = NULL;
retValue = fprintf (fp, "\nDEFINE\n");
retValue = DddmpCuddDdArrayStoreSmvBody (ddMgr, n, f, inputNames,
outputNames, fp);
Dddmp_CheckAndGotoLabel (retValue==0,
"Error in function DddmpCuddDdArrayStoreSmvBody.", failure);
return(1);
failure:
if (sorted != NULL) {
FREE(sorted);
}
if (support != NULL) {
Cudd_RecursiveDeref(ddMgr,support);
}
return(0);
}
/**Function********************************************************************
Synopsis [Internal function to writes a dump file representing the
argument BDD in a SMV notation. Writes the body of the file.]
Description [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).
It does not close the file: This is the caller responsibility.
It uses a minimal unique subset of the hexadecimal address of a node as
name for it.
If the argument inputNames is non-null, it is assumed to hold the
pointers to the names of the inputs. Similarly for outputNames.
For each BDD node of function f, variable v, then child T, and else
child E it stores:
f = v * T + v' * E
that is
(OR f (AND v T) (AND (NOT v) E))
If E is a complemented child this results in the following
(OR f (AND v T) (AND (NOT v) (NOT E)))
]
SideEffects [None]
SeeAlso [DddmpCuddDdArrayStoreBlif]
******************************************************************************/
static int
DddmpCuddDdArrayStoreSmvBody (
DdManager *ddMgr /* IN: Manager */,
int n /* IN: Number of output nodes to be dumped */,
DdNode **f /* IN: Array of output nodes to be dumped */,
char **inputNames /* IN: Array of input names (or NULL) */,
char **outputNames /* IN: Array of output names (or NULL) */,
FILE *fp /* IN: Pointer to the dump file */
)
{
st_table *visited = NULL;
int retValue;
int i;
/* Initialize symbol table for visited nodes. */
visited = st_init_table(st_ptrcmp, st_ptrhash);
Dddmp_CheckAndGotoLabel (visited==NULL,
"Error if function st_init_table.", failure);
/* Call the function that really gets the job done. */
for (i = 0; i < n; i++) {
retValue = DddmpCuddDdArrayStoreSmvStep (ddMgr, Cudd_Regular(f[i]),
fp, visited, inputNames);
Dddmp_CheckAndGotoLabel (retValue==0,
"Error if function DddmpCuddDdArrayStoreSmvStep.", 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 (outputNames == NULL) {
retValue = fprintf (fp, "outNode%d := ", i);
} else {
retValue = fprintf (fp, "%s := ", outputNames[i]);
}
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
if (Cudd_IsComplement(f[i])) {
retValue = fprintf (fp, "!node%" PRIxPTR "\n",
(ptruint) f[i] / sizeof(DdNode));
} else {
retValue = fprintf (fp, "node%" PRIxPTR "\n",
(ptruint) f[i] / sizeof(DdNode));
}
Dddmp_CheckAndGotoLabel (retValue==EOF,
"Error during file store.", failure);
}
st_free_table (visited);
return(1);
failure:
if (visited != NULL) st_free_table(visited);
return(0);
}
/**Function********************************************************************
Synopsis [Performs the recursive step of
DddmpCuddDdArrayStoreSmvBody.]
Description [Performs the recursive step of
DddmpCuddDdArrayStoreSmvBody.
Traverses the BDD f and writes a multiplexer-network description to the
file pointed by fp.
For each BDD node of function f, variable v, then child T, and else
child E it stores:
f = v * T + v' * E
that is
(OR f (AND v T) (AND (NOT v) E))
If E is a complemented child this results in the following
(OR f (AND v T) (AND (NOT v) (NOT E)))
f is assumed to be a regular pointer and the function guarantees this
assumption in the recursive calls.
]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
DddmpCuddDdArrayStoreSmvStep (
DdManager * ddMgr,
DdNode * f,
FILE * fp,
st_table * visited,
char ** names
)
{
DdNode *T, *E;
int retValue;
#ifdef DDDMP_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 (ddMgr)) {
retValue = fprintf (fp, "node%" PRIxPTR " := 1;\n",
(ptruint) f / sizeof(DdNode));
if (retValue == 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(ddMgr)) {
retValue = fprintf (fp, "node%" PRIxPTR " := 0;\n",
(ptruint) f / sizeof(DdNode));
if (retValue == EOF) {
return(0);
} else {
return(1);
}
}
if (cuddIsConstant(f)) {
return(0);
}
/* Recursive calls. */
T = cuddT(f);
retValue = DddmpCuddDdArrayStoreSmvStep (ddMgr,T,fp,visited,names);
if (retValue != 1) {
return(retValue);
}
E = Cudd_Regular(cuddE(f));
retValue = DddmpCuddDdArrayStoreSmvStep (ddMgr,E,fp,visited,names);
if (retValue != 1) {
return(retValue);
}
/* Write multiplexer taking complement arc into account. */
retValue = fprintf (fp, "node%" PRIxPTR " := ",
(ptruint) f / sizeof(DdNode));
if (retValue == EOF) {
return(0);
}
if (names != NULL) {
retValue = fprintf(fp, "%s ", names[f->index]);
} else {
retValue = fprintf(fp, "inNode%d ", f->index);
}
if (retValue == EOF) {
return(0);
}
retValue = fprintf (fp, "& node%" PRIxPTR " | ",
(ptruint) T / sizeof(DdNode));
if (retValue == EOF) {
return(0);
}
if (names != NULL) {
retValue = fprintf (fp, "!%s ", names[f->index]);
} else {
retValue = fprintf (fp, "!inNode%d ", f->index);
}
if (retValue == EOF) {
return(0);
}
if (Cudd_IsComplement(cuddE(f))) {
retValue = fprintf (fp, "& !node%" PRIxPTR "\n",
(ptruint) E / sizeof(DdNode));
} else {
retValue = fprintf (fp, "& node%" PRIxPTR "\n",
(ptruint) E / sizeof(DdNode));
}
if (retValue == EOF) {
return(0);
} else {
return(1);
}
}