1 /**CFile***********************************************************************
7 Synopsis [Functions to read in a boolean network.]
13 Author [Fabio Somenzi]
15 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
19 Redistribution and use in source and binary forms, with or without
20 modification, are permitted provided that the following conditions
23 Redistributions of source code must retain the above copyright
24 notice, this list of conditions and the following disclaimer.
26 Redistributions in binary form must reproduce the above copyright
27 notice, this list of conditions and the following disclaimer in the
28 documentation and/or other materials provided with the distribution.
30 Neither the name of the University of Colorado nor the names of its
31 contributors may be used to endorse or promote products derived from
32 this software without specific prior written permission.
34 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
37 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
38 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
39 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
40 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
41 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
42 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
44 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45 POSSIBILITY OF SUCH DAMAGE.]
47 ******************************************************************************/
51 /*---------------------------------------------------------------------------*/
52 /* Constant declarations */
53 /*---------------------------------------------------------------------------*/
55 #define MAXLENGTH 131072
57 /*---------------------------------------------------------------------------*/
58 /* Stucture declarations */
59 /*---------------------------------------------------------------------------*/
61 /*---------------------------------------------------------------------------*/
62 /* Type declarations */
63 /*---------------------------------------------------------------------------*/
65 /*---------------------------------------------------------------------------*/
66 /* Variable declarations */
67 /*---------------------------------------------------------------------------*/
70 static char rcsid
[] UTIL_UNUSED
= "$Id: bnet.c,v 1.25 2009/02/21 06:00:31 fabio Exp fabio $";
73 static char BuffLine
[MAXLENGTH
];
75 static int newNameNumber
= 0;
77 /*---------------------------------------------------------------------------*/
78 /* Macro declarations */
79 /*---------------------------------------------------------------------------*/
81 /**AutomaticStart*************************************************************/
83 /*---------------------------------------------------------------------------*/
84 /* Static function prototypes */
85 /*---------------------------------------------------------------------------*/
87 static char * readString (FILE *fp
);
88 static char ** readList (FILE *fp
, int *n
);
89 static void printList (char **list
, int n
);
90 static char ** bnetGenerateNewNames (st_table
*hash
, int n
);
91 static int bnetDumpReencodingLogic (DdManager
*dd
, char *mname
, int noutputs
, DdNode
**outputs
, char **inames
, char **altnames
, char **onames
, FILE *fp
);
93 static int bnetBlifXnorTable (FILE *fp
, int n
);
95 static int bnetBlifWriteReencode (DdManager
*dd
, char *mname
, char **inames
, char **altnames
, int *support
, FILE *fp
);
96 static int * bnetFindVectorSupport (DdManager
*dd
, DdNode
**list
, int n
);
97 static int buildExorBDD (DdManager
*dd
, BnetNode
*nd
, st_table
*hash
, int params
, int nodrop
);
98 static int buildMuxBDD (DdManager
* dd
, BnetNode
* nd
, st_table
* hash
, int params
, int nodrop
);
99 static int bnetSetLevel (BnetNetwork
*net
);
100 static int bnetLevelDFS (BnetNetwork
*net
, BnetNode
*node
);
101 static BnetNode
** bnetOrderRoots (BnetNetwork
*net
, int *nroots
);
102 static int bnetLevelCompare (BnetNode
**x
, BnetNode
**y
);
103 static int bnetDfsOrder (DdManager
*dd
, BnetNetwork
*net
, BnetNode
*node
);
105 /**AutomaticEnd***************************************************************/
107 /*---------------------------------------------------------------------------*/
108 /* Definition of exported functions */
109 /*---------------------------------------------------------------------------*/
112 /**Function********************************************************************
114 Synopsis [Reads boolean network from blif file.]
116 Description [Reads a boolean network from a blif file. A very restricted
117 subset of blif is supported. Specifically:
119 <li> The only directives recognized are:
127 <li> .wire_load_slope
130 <li> Latches must have an initial values and no other parameters
132 <li> Lines must not exceed MAXLENGTH-1 characters, and individual names must
133 not exceed 1023 characters.
135 Caveat emptor: There may be other limitations as well. One should
136 check the syntax of the blif file with some other tool before relying
137 on this parser. Bnet_ReadNetwork returns a pointer to the network if
138 successful; NULL otherwise.
143 SeeAlso [Bnet_PrintNetwork Bnet_FreeNetwork]
145 ******************************************************************************/
148 FILE * fp
/* pointer to the blif file */,
149 int pr
/* verbosity level */)
156 BnetNode
*lastnode
= NULL
;
157 BnetTabline
*newline
;
158 BnetTabline
*lastline
;
159 char ***latches
= NULL
;
165 /* Allocate network object and initialize symbol table. */
166 net
= ALLOC(BnetNetwork
,1);
167 if (net
== NULL
) goto failure
;
168 memset((char *) net
, 0, sizeof(BnetNetwork
));
169 net
->hash
= st_init_table(strcmp
,st_strhash
);
170 if (net
->hash
== NULL
) goto failure
;
172 savestring
= readString(fp
);
173 if (savestring
== NULL
) goto failure
;
175 while (strcmp(savestring
, ".model") == 0 ||
176 strcmp(savestring
, ".inputs") == 0 ||
177 strcmp(savestring
, ".outputs") == 0 ||
178 strcmp(savestring
, ".latch") == 0 ||
179 strcmp(savestring
, ".wire_load_slope") == 0 ||
180 strcmp(savestring
, ".exdc") == 0 ||
181 strcmp(savestring
, ".names") == 0 || strcmp(savestring
,".end") == 0) {
182 if (strcmp(savestring
, ".model") == 0) {
183 /* Read .model directive. */
185 /* Read network name. */
186 savestring
= readString(fp
);
187 if (savestring
== NULL
) goto failure
;
188 net
->name
= savestring
;
189 } else if (strcmp(savestring
, ".inputs") == 0) {
190 /* Read .inputs directive. */
192 /* Read input names. */
193 list
= readList(fp
,&n
);
194 if (list
== NULL
) goto failure
;
195 if (pr
> 2) printList(list
,n
);
196 /* Expect at least one input. */
198 (void) fprintf(stdout
,"Empty input list.\n");
202 for (i
= 0; i
< n
; i
++)
205 savestring
= readString(fp
);
206 if (savestring
== NULL
) goto failure
;
210 net
->inputs
= REALLOC(char *, net
->inputs
,
211 (net
->ninputs
+ n
) * sizeof(char *));
212 for (i
= 0; i
< n
; i
++)
213 net
->inputs
[net
->ninputs
+ i
] = list
[i
];
217 /* Create a node for each primary input. */
218 for (i
= 0; i
< n
; i
++) {
219 newnode
= ALLOC(BnetNode
,1);
220 memset((char *) newnode
, 0, sizeof(BnetNode
));
221 if (newnode
== NULL
) goto failure
;
222 newnode
->name
= list
[i
];
223 newnode
->inputs
= NULL
;
224 newnode
->type
= BNET_INPUT_NODE
;
225 newnode
->active
= FALSE
;
229 newnode
->polarity
= 0;
231 newnode
->next
= NULL
;
232 if (lastnode
== NULL
) {
233 net
->nodes
= newnode
;
235 lastnode
->next
= newnode
;
241 } else if (strcmp(savestring
, ".outputs") == 0) {
242 /* Read .outputs directive. We do not create nodes for the primary
243 ** outputs, because the nodes will be created when the same names
244 ** appear as outputs of some gates.
247 /* Read output names. */
248 list
= readList(fp
,&n
);
249 if (list
== NULL
) goto failure
;
250 if (pr
> 2) printList(list
,n
);
252 (void) fprintf(stdout
,"Empty .outputs list.\n");
256 for (i
= 0; i
< n
; i
++)
259 savestring
= readString(fp
);
260 if (savestring
== NULL
) goto failure
;
264 net
->outputs
= REALLOC(char *, net
->outputs
,
265 (net
->noutputs
+ n
) * sizeof(char *));
266 for (i
= 0; i
< n
; i
++)
267 net
->outputs
[net
->noutputs
+ i
] = list
[i
];
273 } else if (strcmp(savestring
,".wire_load_slope") == 0) {
275 savestring
= readString(fp
);
276 net
->slope
= savestring
;
277 } else if (strcmp(savestring
,".latch") == 0) {
279 newnode
= ALLOC(BnetNode
,1);
280 if (newnode
== NULL
) goto failure
;
281 memset((char *) newnode
, 0, sizeof(BnetNode
));
282 newnode
->type
= BNET_PRESENT_STATE_NODE
;
283 list
= readList(fp
,&n
);
284 if (list
== NULL
) goto failure
;
285 if (pr
> 2) printList(list
,n
);
286 /* Expect three names. */
288 (void) fprintf(stdout
,
289 ".latch not followed by three tokens.\n");
292 newnode
->name
= list
[1];
293 newnode
->inputs
= NULL
;
296 newnode
->active
= FALSE
;
298 newnode
->polarity
= 0;
300 newnode
->next
= NULL
;
301 if (lastnode
== NULL
) {
302 net
->nodes
= newnode
;
304 lastnode
->next
= newnode
;
307 /* Add next state variable to list. */
308 if (maxlatches
== 0) {
310 latches
= ALLOC(char **,maxlatches
);
311 } else if (maxlatches
<= net
->nlatches
) {
313 latches
= REALLOC(char **,latches
,maxlatches
);
315 latches
[net
->nlatches
] = list
;
317 savestring
= readString(fp
);
318 if (savestring
== NULL
) goto failure
;
319 } else if (strcmp(savestring
,".names") == 0) {
321 newnode
= ALLOC(BnetNode
,1);
322 memset((char *) newnode
, 0, sizeof(BnetNode
));
323 if (newnode
== NULL
) goto failure
;
324 list
= readList(fp
,&n
);
325 if (list
== NULL
) goto failure
;
326 if (pr
> 2) printList(list
,n
);
327 /* Expect at least one name (the node output). */
329 (void) fprintf(stdout
,"Missing output name.\n");
332 newnode
->name
= list
[n
-1];
333 newnode
->inputs
= list
;
335 newnode
->active
= FALSE
;
337 newnode
->polarity
= 0;
338 if (newnode
->ninp
> 0) {
339 newnode
->type
= BNET_INTERNAL_NODE
;
340 for (i
= 0; i
< net
->noutputs
; i
++) {
341 if (strcmp(net
->outputs
[i
], newnode
->name
) == 0) {
342 newnode
->type
= BNET_OUTPUT_NODE
;
347 newnode
->type
= BNET_CONSTANT_NODE
;
350 newnode
->next
= NULL
;
351 if (lastnode
== NULL
) {
352 net
->nodes
= newnode
;
354 lastnode
->next
= newnode
;
357 /* Read node function. */
360 newnode
->exdc_flag
= 1;
363 if (node
->type
== BNET_OUTPUT_NODE
&&
364 strcmp(node
->name
, newnode
->name
) == 0) {
365 node
->exdc
= newnode
;
371 savestring
= readString(fp
);
372 if (savestring
== NULL
) goto failure
;
374 while (savestring
[0] != '.') {
375 /* Reading a table line. */
376 newline
= ALLOC(BnetTabline
,1);
377 if (newline
== NULL
) goto failure
;
378 newline
->next
= NULL
;
379 if (lastline
== NULL
) {
380 newnode
->f
= newline
;
382 lastline
->next
= newline
;
385 if (newnode
->type
== BNET_INTERNAL_NODE
||
386 newnode
->type
== BNET_OUTPUT_NODE
) {
387 newline
->values
= savestring
;
388 /* Read output 1 or 0. */
389 savestring
= readString(fp
);
390 if (savestring
== NULL
) goto failure
;
392 newline
->values
= NULL
;
394 if (savestring
[0] == '0') newnode
->polarity
= 1;
396 savestring
= readString(fp
);
397 if (savestring
== NULL
) goto failure
;
399 } else if (strcmp(savestring
,".exdc") == 0) {
402 } else if (strcmp(savestring
,".end") == 0) {
406 if ((!savestring
) || savestring
[0] != '.')
407 savestring
= readString(fp
);
408 if (savestring
== NULL
) goto failure
;
411 /* Put nodes in symbol table. */
412 newnode
= net
->nodes
;
413 while (newnode
!= NULL
) {
414 int retval
= st_insert(net
->hash
,newnode
->name
,(char *) newnode
);
415 if (retval
== ST_OUT_OF_MEM
) {
417 } else if (retval
== 1) {
418 printf("Error: Multiple drivers for node %s\n", newnode
->name
);
421 if (pr
> 2) printf("Inserted %s\n",newnode
->name
);
423 newnode
= newnode
->next
;
427 net
->latches
= latches
;
430 net
->outputs
= REALLOC(char *, net
->outputs
,
431 (net
->noutputs
+ net
->nlatches
) * sizeof(char *));
432 for (i
= 0; i
< net
->nlatches
; i
++) {
433 for (j
= 0; j
< net
->noutputs
; j
++) {
434 if (strcmp(latches
[i
][0], net
->outputs
[j
]) == 0)
437 if (j
< net
->noutputs
)
439 savestring
= ALLOC(char, strlen(latches
[i
][0]) + 1);
440 strcpy(savestring
, latches
[i
][0]);
441 net
->outputs
[net
->noutputs
+ count
] = savestring
;
443 if (st_lookup(net
->hash
, savestring
, &node
)) {
444 if (node
->type
== BNET_INTERNAL_NODE
) {
445 node
->type
= BNET_OUTPUT_NODE
;
449 net
->noutputs
+= count
;
451 net
->inputs
= REALLOC(char *, net
->inputs
,
452 (net
->ninputs
+ net
->nlatches
) * sizeof(char *));
453 for (i
= 0; i
< net
->nlatches
; i
++) {
454 savestring
= ALLOC(char, strlen(latches
[i
][1]) + 1);
455 strcpy(savestring
, latches
[i
][1]);
456 net
->inputs
[net
->ninputs
+ i
] = savestring
;
458 net
->ninputs
+= net
->nlatches
;
461 /* Compute fanout counts. For each node in the linked list, fetch
462 ** all its fanins using the symbol table, and increment the fanout of
465 newnode
= net
->nodes
;
466 while (newnode
!= NULL
) {
468 for (i
= 0; i
< newnode
->ninp
; i
++) {
469 if (!st_lookup(net
->hash
,newnode
->inputs
[i
],&auxnd
)) {
470 (void) fprintf(stdout
,"%s not driven\n", newnode
->inputs
[i
]);
475 newnode
= newnode
->next
;
478 if (!bnetSetLevel(net
)) goto failure
;
483 /* Here we should clean up the mess. */
484 (void) fprintf(stdout
,"Error in reading network from file.\n");
487 } /* end of Bnet_ReadNetwork */
490 /**Function********************************************************************
492 Synopsis [Prints a boolean network created by readNetwork.]
494 Description [Prints to the standard output a boolean network created
495 by Bnet_ReadNetwork. Uses the blif format; this way, one can verify the
496 equivalence of the input and the output with, say, sis.]
500 SeeAlso [Bnet_ReadNetwork]
502 ******************************************************************************/
505 BnetNetwork
* net
/* boolean network */)
511 if (net
== NULL
) return;
513 (void) fprintf(stdout
,".model %s\n", net
->name
);
514 (void) fprintf(stdout
,".inputs");
515 printList(net
->inputs
,net
->npis
);
516 (void) fprintf(stdout
,".outputs");
517 printList(net
->outputs
,net
->npos
);
518 for (i
= 0; i
< net
->nlatches
; i
++) {
519 (void) fprintf(stdout
,".latch");
520 printList(net
->latches
[i
],3);
524 if (nd
->type
!= BNET_INPUT_NODE
&& nd
->type
!= BNET_PRESENT_STATE_NODE
) {
525 (void) fprintf(stdout
,".names");
526 for (i
= 0; i
< nd
->ninp
; i
++) {
527 (void) fprintf(stdout
," %s",nd
->inputs
[i
]);
529 (void) fprintf(stdout
," %s\n",nd
->name
);
532 if (tl
->values
!= NULL
) {
533 (void) fprintf(stdout
,"%s %d\n",tl
->values
,
536 (void) fprintf(stdout
,"%d\n", 1 - nd
->polarity
);
543 (void) fprintf(stdout
,".end\n");
545 } /* end of Bnet_PrintNetwork */
548 /**Function********************************************************************
550 Synopsis [Frees a boolean network created by Bnet_ReadNetwork.]
556 SeeAlso [Bnet_ReadNetwork]
558 ******************************************************************************/
563 BnetNode
*node
, *nextnode
;
564 BnetTabline
*line
, *nextline
;
568 /* The input name strings are already pointed by the input nodes.
569 ** Here we only need to free the latch names and the array that
572 for (i
= 0; i
< net
->nlatches
; i
++) {
573 FREE(net
->inputs
[net
->npis
+ i
]);
576 /* Free the output name strings and then the array pointing to them. */
577 for (i
= 0; i
< net
->noutputs
; i
++) {
578 FREE(net
->outputs
[i
]);
582 for (i
= 0; i
< net
->nlatches
; i
++) {
583 FREE(net
->latches
[i
][0]);
584 FREE(net
->latches
[i
][1]);
585 FREE(net
->latches
[i
][2]);
586 FREE(net
->latches
[i
]);
588 if (net
->nlatches
) FREE(net
->latches
);
590 while (node
!= NULL
) {
591 nextnode
= node
->next
;
592 if (node
->type
!= BNET_PRESENT_STATE_NODE
)
594 for (i
= 0; i
< node
->ninp
; i
++) {
595 FREE(node
->inputs
[i
]);
597 if (node
->inputs
!= NULL
) {
600 /* Free the function table. */
602 while (line
!= NULL
) {
603 nextline
= line
->next
;
611 st_free_table(net
->hash
);
612 if (net
->slope
!= NULL
) FREE(net
->slope
);
615 } /* end of Bnet_FreeNetwork */
618 /**Function********************************************************************
620 Synopsis [Builds the BDD for the function of a node.]
622 Description [Builds the BDD for the function of a node and stores a
623 pointer to it in the dd field of the node itself. The reference count
624 of the BDD is incremented. If params is BNET_LOCAL_DD, then the BDD is
625 built in terms of the local inputs to the node; otherwise, if params
626 is BNET_GLOBAL_DD, the BDD is built in terms of the network primary
627 inputs. To build the global BDD of a node, the BDDs for its local
628 inputs must exist. If that is not the case, Bnet_BuildNodeBDD
629 recursively builds them. Likewise, to create the local BDD for a node,
630 the local inputs must have variables assigned to them. If that is not
631 the case, Bnet_BuildNodeBDD recursively assigns variables to nodes.
632 Bnet_BuildNodeBDD returns 1 in case of success; 0 otherwise.]
634 SideEffects [Sets the dd field of the node.]
638 ******************************************************************************/
641 DdManager
* dd
/* DD manager */,
642 BnetNode
* nd
/* node of the boolean network */,
643 st_table
* hash
/* symbol table of the boolean network */,
644 int params
/* type of DD to be built */,
645 int nodrop
/* retain the intermediate node DDs until the end */)
654 if (nd
->dd
!= NULL
) return(1);
656 if (nd
->type
== BNET_CONSTANT_NODE
) {
657 if (nd
->f
== NULL
) { /* constant 0 */
658 func
= Cudd_ReadLogicZero(dd
);
659 } else { /* either constant depending on the polarity */
660 func
= Cudd_ReadOne(dd
);
663 } else if (nd
->type
== BNET_INPUT_NODE
||
664 nd
->type
== BNET_PRESENT_STATE_NODE
) {
665 if (nd
->active
== TRUE
) { /* a variable is already associated: use it */
666 func
= Cudd_ReadVars(dd
,nd
->var
);
667 if (func
== NULL
) goto failure
;
668 } else { /* no variable associated: get a new one */
669 func
= Cudd_bddNewVar(dd
);
670 if (func
== NULL
) goto failure
;
671 nd
->var
= func
->index
;
675 } else if (buildExorBDD(dd
,nd
,hash
,params
,nodrop
)) {
677 } else if (buildMuxBDD(dd
,nd
,hash
,params
,nodrop
)) {
679 } else { /* type == BNET_INTERNAL_NODE or BNET_OUTPUT_NODE */
680 /* Initialize the sum to logical 0. */
681 func
= Cudd_ReadLogicZero(dd
);
684 /* Build a term for each line of the table and add it to the
685 ** accumulator (func).
688 while (line
!= NULL
) {
690 (void) fprintf(stdout
,"line = %s\n", line
->values
);
692 /* Initialize the product to logical 1. */
693 prod
= Cudd_ReadOne(dd
);
695 /* Scan the table line. */
696 for (i
= 0; i
< nd
->ninp
; i
++) {
697 if (line
->values
[i
] == '-') continue;
698 if (!st_lookup(hash
,nd
->inputs
[i
],&auxnd
)) {
701 if (params
== BNET_LOCAL_DD
) {
702 if (auxnd
->active
== FALSE
) {
703 if (!Bnet_BuildNodeBDD(dd
,auxnd
,hash
,params
,nodrop
)) {
707 var
= Cudd_ReadVars(dd
,auxnd
->var
);
708 if (var
== NULL
) goto failure
;
710 if (line
->values
[i
] == '0') {
713 } else { /* params == BNET_GLOBAL_DD */
714 if (auxnd
->dd
== NULL
) {
715 if (!Bnet_BuildNodeBDD(dd
,auxnd
,hash
,params
,nodrop
)) {
719 if (line
->values
[i
] == '1') {
721 } else { /* line->values[i] == '0' */
722 var
= Cudd_Not(auxnd
->dd
);
725 tmp
= Cudd_bddAnd(dd
,prod
,var
);
726 if (tmp
== NULL
) goto failure
;
728 Cudd_IterDerefBdd(dd
,prod
);
729 if (params
== BNET_LOCAL_DD
) {
730 Cudd_IterDerefBdd(dd
,var
);
734 tmp
= Cudd_bddOr(dd
,func
,prod
);
735 if (tmp
== NULL
) goto failure
;
737 Cudd_IterDerefBdd(dd
,func
);
738 Cudd_IterDerefBdd(dd
,prod
);
742 /* Associate a variable to this node if local BDDs are being
743 ** built. This is done at the end, so that the primary inputs tend
744 ** to get lower indices.
746 if (params
== BNET_LOCAL_DD
&& nd
->active
== FALSE
) {
747 DdNode
*auxfunc
= Cudd_bddNewVar(dd
);
748 if (auxfunc
== NULL
) goto failure
;
750 nd
->var
= auxfunc
->index
;
752 Cudd_IterDerefBdd(dd
,auxfunc
);
755 if (nd
->polarity
== 1) {
756 nd
->dd
= Cudd_Not(func
);
761 if (params
== BNET_GLOBAL_DD
&& nodrop
== FALSE
) {
762 /* Decrease counters for all faninis.
763 ** When count reaches 0, the DD is freed.
765 for (i
= 0; i
< nd
->ninp
; i
++) {
766 if (!st_lookup(hash
,nd
->inputs
[i
],&auxnd
)) {
770 if (auxnd
->count
== 0) {
771 Cudd_IterDerefBdd(dd
,auxnd
->dd
);
772 if (auxnd
->type
== BNET_INTERNAL_NODE
||
773 auxnd
->type
== BNET_CONSTANT_NODE
) auxnd
->dd
= NULL
;
780 /* Here we should clean up the mess. */
783 } /* end of Bnet_BuildNodeBDD */
786 /**Function********************************************************************
788 Synopsis [Orders the BDD variables by DFS.]
790 Description [Orders the BDD variables by DFS. Returns 1 in case of
791 success; 0 otherwise.]
793 SideEffects [Uses the visited flags of the nodes.]
797 ******************************************************************************/
799 Bnet_DfsVariableOrder(
808 roots
= bnetOrderRoots(net
,&nroots
);
809 if (roots
== NULL
) return(0);
810 for (i
= 0; i
< nroots
; i
++) {
811 if (!bnetDfsOrder(dd
,net
,roots
[i
])) {
816 /* Clear visited flags. */
818 while (node
!= NULL
) {
825 } /* end of Bnet_DfsVariableOrder */
828 /**Function********************************************************************
830 Synopsis [Writes the network BDDs to a file in dot, blif, or daVinci
833 Description [Writes the network BDDs to a file in dot, blif, or daVinci
834 format. If "-" is passed as file name, the BDDs are dumped to the
835 standard output. Returns 1 in case of success; 0 otherwise.]
841 ******************************************************************************/
844 DdManager
* dd
/* DD manager */,
845 BnetNetwork
* network
/* network whose BDDs should be dumped */,
846 char * dfile
/* file name */,
847 int dumpFmt
/* 0 -> dot */,
848 int reencoded
/* whether variables have been reencoded */)
852 DdNode
**outputs
= NULL
;
853 char **inames
= NULL
;
854 char **onames
= NULL
;
855 char **altnames
= NULL
;
858 int retval
= 0; /* 0 -> failure; 1 -> success */
860 /* Open dump file. */
861 if (strcmp(dfile
, "-") == 0) {
864 dfp
= fopen(dfile
,"w");
866 if (dfp
== NULL
) goto endgame
;
868 /* Initialize data structures. */
869 noutputs
= network
->noutputs
;
870 outputs
= ALLOC(DdNode
*,noutputs
);
871 if (outputs
== NULL
) goto endgame
;
872 onames
= ALLOC(char *,noutputs
);
873 if (onames
== NULL
) goto endgame
;
874 inames
= ALLOC(char *,Cudd_ReadSize(dd
));
875 if (inames
== NULL
) goto endgame
;
877 /* Find outputs and their names. */
878 for (i
= 0; i
< network
->nlatches
; i
++) {
879 onames
[i
] = network
->latches
[i
][0];
880 if (!st_lookup(network
->hash
,network
->latches
[i
][0],&node
)) {
883 outputs
[i
] = node
->dd
;
885 for (i
= 0; i
< network
->npos
; i
++) {
886 onames
[i
+ network
->nlatches
] = network
->outputs
[i
];
887 if (!st_lookup(network
->hash
,network
->outputs
[i
],&node
)) {
890 outputs
[i
+ network
->nlatches
] = node
->dd
;
893 /* Find the input names. */
894 for (i
= 0; i
< network
->ninputs
; i
++) {
895 if (!st_lookup(network
->hash
,network
->inputs
[i
],&node
)) {
898 inames
[node
->var
] = network
->inputs
[i
];
900 for (i
= 0; i
< network
->nlatches
; i
++) {
901 if (!st_lookup(network
->hash
,network
->latches
[i
][1],&node
)) {
904 inames
[node
->var
] = network
->latches
[i
][1];
907 if (reencoded
== 1 && dumpFmt
== 1) {
908 altnames
= bnetGenerateNewNames(network
->hash
,network
->ninputs
);
909 if (altnames
== NULL
) {
913 retval
= bnetDumpReencodingLogic(dd
,network
->name
,noutputs
,outputs
,
914 inames
,altnames
,onames
,dfp
);
915 for (i
= 0; i
< network
->ninputs
; i
++) {
919 if (retval
== 0) goto endgame
;
924 retval
= Cudd_DumpBlif(dd
,noutputs
,outputs
,inames
,onames
,
925 network
->name
,dfp
,0);
926 } else if (dumpFmt
== 2) {
927 retval
= Cudd_DumpDaVinci(dd
,noutputs
,outputs
,inames
,onames
,dfp
);
928 } else if (dumpFmt
== 3) {
929 retval
= Cudd_DumpDDcal(dd
,noutputs
,outputs
,inames
,onames
,dfp
);
930 } else if (dumpFmt
== 4) {
931 retval
= Cudd_DumpFactoredForm(dd
,noutputs
,outputs
,inames
,onames
,dfp
);
932 } else if (dumpFmt
== 5) {
933 retval
= Cudd_DumpBlif(dd
,noutputs
,outputs
,inames
,onames
,
934 network
->name
,dfp
,1);
936 retval
= Cudd_DumpDot(dd
,noutputs
,outputs
,inames
,onames
,dfp
);
940 if (dfp
!= stdout
&& dfp
!= NULL
) {
941 if (fclose(dfp
) == EOF
) retval
= 0;
943 if (outputs
!= NULL
) FREE(outputs
);
944 if (onames
!= NULL
) FREE(onames
);
945 if (inames
!= NULL
) FREE(inames
);
949 } /* end of Bnet_bddDump */
952 /**Function********************************************************************
954 Synopsis [Writes an array of BDDs to a file in dot, blif, DDcal,
955 factored-form, daVinci, or blif-MV format.]
957 Description [Writes an array of BDDs to a file in dot, blif, DDcal,
958 factored-form, daVinci, or blif-MV format. The BDDs and their names
959 are passed as arguments. The inputs and their names are taken from
960 the network. If "-" is passed as file name, the BDDs are dumped to
961 the standard output. Returns 1 in case of success; 0 otherwise.]
967 ******************************************************************************/
970 DdManager
* dd
/* DD manager */,
971 BnetNetwork
* network
/* network whose BDDs should be dumped */,
972 char * dfile
/* file name */,
973 DdNode
** outputs
/* BDDs to be dumped */,
974 char ** onames
/* names of the BDDs to be dumped */,
975 int noutputs
/* number of BDDs to be dumped */,
976 int dumpFmt
/* 0 -> dot */)
979 char **inames
= NULL
;
982 int retval
= 0; /* 0 -> failure; 1 -> success */
984 /* Open dump file. */
985 if (strcmp(dfile
, "-") == 0) {
988 dfp
= fopen(dfile
,"w");
990 if (dfp
== NULL
) goto endgame
;
992 /* Initialize data structures. */
993 inames
= ALLOC(char *,Cudd_ReadSize(dd
));
994 if (inames
== NULL
) goto endgame
;
995 for (i
= 0; i
< Cudd_ReadSize(dd
); i
++) {
999 /* Find the input names. */
1000 for (i
= 0; i
< network
->ninputs
; i
++) {
1001 if (!st_lookup(network
->hash
,network
->inputs
[i
],&node
)) {
1004 inames
[node
->var
] = network
->inputs
[i
];
1006 for (i
= 0; i
< network
->nlatches
; i
++) {
1007 if (!st_lookup(network
->hash
,network
->latches
[i
][1],&node
)) {
1010 inames
[node
->var
] = network
->latches
[i
][1];
1013 /* Dump the BDDs. */
1015 retval
= Cudd_DumpBlif(dd
,noutputs
,outputs
,inames
,onames
,
1016 network
->name
,dfp
,0);
1017 } else if (dumpFmt
== 2) {
1018 retval
= Cudd_DumpDaVinci(dd
,noutputs
,outputs
,inames
,onames
,dfp
);
1019 } else if (dumpFmt
== 3) {
1020 retval
= Cudd_DumpDDcal(dd
,noutputs
,outputs
,inames
,onames
,dfp
);
1021 } else if (dumpFmt
== 4) {
1022 retval
= Cudd_DumpFactoredForm(dd
,noutputs
,outputs
,inames
,onames
,dfp
);
1023 } else if (dumpFmt
== 5) {
1024 retval
= Cudd_DumpBlif(dd
,noutputs
,outputs
,inames
,onames
,
1025 network
->name
,dfp
,1);
1027 retval
= Cudd_DumpDot(dd
,noutputs
,outputs
,inames
,onames
,dfp
);
1031 if (dfp
!= stdout
&& dfp
!= NULL
) {
1032 if (fclose(dfp
) == EOF
) retval
= 0;
1034 if (inames
!= NULL
) FREE(inames
);
1038 } /* end of Bnet_bddArrayDump */
1041 /**Function********************************************************************
1043 Synopsis [Reads the variable order from a file.]
1045 Description [Reads the variable order from a file.
1046 Returns 1 if successful; 0 otherwise.]
1048 SideEffects [The BDDs for the primary inputs and present state variables
1053 *****************************************************************************/
1066 char name
[MAXLENGTH
];
1068 if (ordFile
== NULL
) {
1072 dict
= st_init_table(strcmp
,st_strhash
);
1077 if ((fp
= fopen(ordFile
,"r")) == NULL
) {
1078 (void) fprintf(stderr
,"Unable to open %s\n",ordFile
);
1079 st_free_table(dict
);
1084 result
= fscanf(fp
, "%s", name
);
1085 if (result
== EOF
) {
1087 } else if (result
!= 1) {
1088 st_free_table(dict
);
1090 } else if (strlen(name
) > MAXLENGTH
) {
1091 st_free_table(dict
);
1094 /* There should be a node named "name" in the network. */
1095 if (!st_lookup(net
->hash
,name
,&node
)) {
1096 (void) fprintf(stderr
,"Unknown name in order file (%s)\n", name
);
1097 st_free_table(dict
);
1100 /* A name should not appear more than once in the order. */
1101 if (st_is_member(dict
,name
)) {
1102 (void) fprintf(stderr
,"Duplicate name in order file (%s)\n", name
);
1103 st_free_table(dict
);
1106 /* The name should correspond to a primary input or present state. */
1107 if (node
->type
!= BNET_INPUT_NODE
&&
1108 node
->type
!= BNET_PRESENT_STATE_NODE
) {
1109 (void) fprintf(stderr
,"%s has the wrong type (%d)\n", name
,
1111 st_free_table(dict
);
1114 /* Insert in table. Use node->name rather than name, because the
1115 ** latter gets overwritten.
1117 if (st_insert(dict
,node
->name
,NULL
) == ST_OUT_OF_MEM
) {
1118 (void) fprintf(stderr
,"Out of memory in Bnet_ReadOrder\n");
1119 st_free_table(dict
);
1122 result
= Bnet_BuildNodeBDD(dd
,node
,net
->hash
,locGlob
,nodrop
);
1124 (void) fprintf(stderr
,"Construction of BDD failed\n");
1125 st_free_table(dict
);
1128 } /* while (!feof(fp)) */
1129 result
= fclose(fp
);
1130 if (result
== EOF
) {
1131 (void) fprintf(stderr
,"Error closing order file %s\n", ordFile
);
1132 st_free_table(dict
);
1136 /* The number of names in the order file should match exactly the
1137 ** number of primary inputs and present states.
1139 if (st_count(dict
) != net
->ninputs
) {
1140 (void) fprintf(stderr
,"Order incomplete: %d names instead of %d\n",
1141 st_count(dict
), net
->ninputs
);
1142 st_free_table(dict
);
1146 st_free_table(dict
);
1149 } /* end of Bnet_ReadOrder */
1152 /**Function********************************************************************
1154 Synopsis [Prints the order of the DD variables of a network.]
1156 Description [Prints the order of the DD variables of a network.
1157 Only primary inputs and present states are printed.
1158 Returns 1 if successful; 0 otherwise.]
1164 *****************************************************************************/
1170 char **names
; /* array used to print variable orders */
1171 int level
; /* position of a variable in current order */
1172 BnetNode
*node
; /* auxiliary pointer to network node */
1177 nvars
= Cudd_ReadSize(dd
);
1178 names
= ALLOC(char *, nvars
);
1179 if (names
== NULL
) return(0);
1180 for (i
= 0; i
< nvars
; i
++) {
1183 for (i
= 0; i
< net
->npis
; i
++) {
1184 if (!st_lookup(net
->hash
,net
->inputs
[i
],&node
)) {
1188 if (node
->dd
== NULL
) {
1192 level
= Cudd_ReadPerm(dd
,node
->var
);
1193 names
[level
] = node
->name
;
1195 for (i
= 0; i
< net
->nlatches
; i
++) {
1196 if (!st_lookup(net
->hash
,net
->latches
[i
][1],&node
)) {
1200 if (node
->dd
== NULL
) {
1204 level
= Cudd_ReadPerm(dd
,node
->var
);
1205 names
[level
] = node
->name
;
1207 for (i
= 0, j
= 0; i
< nvars
; i
++) {
1208 if (names
[i
] == NULL
) continue;
1209 if ((j
%8 == 0)&&j
) {
1210 retval
= printf("\n");
1211 if (retval
== EOF
) {
1216 retval
= printf("%s ",names
[i
]);
1217 if (retval
== EOF
) {
1224 retval
= printf("\n");
1225 if (retval
== EOF
) {
1230 } /* end of Bnet_PrintOrder */
1233 /*---------------------------------------------------------------------------*/
1234 /* Definition of internal functions */
1235 /*---------------------------------------------------------------------------*/
1237 /*---------------------------------------------------------------------------*/
1238 /* Definition of static functions */
1239 /*---------------------------------------------------------------------------*/
1242 /**Function********************************************************************
1244 Synopsis [Reads a string from a file.]
1246 Description [Reads a string from a file. The string can be MAXLENGTH-1
1247 characters at most. readString allocates memory to hold the string and
1248 returns a pointer to the result if successful. It returns NULL
1255 ******************************************************************************/
1258 FILE * fp
/* pointer to the file from which the string is read */)
1264 if (!fgets(BuffLine
, MAXLENGTH
, fp
))
1266 BuffLine
[strlen(BuffLine
) - 1] = '\0';
1267 CurPos
= strtok(BuffLine
, " \t");
1268 if (CurPos
&& CurPos
[0] == '#') CurPos
= (char *)NULL
;
1270 length
= strlen(CurPos
);
1271 savestring
= ALLOC(char,length
+1);
1272 if (savestring
== NULL
)
1274 strcpy(savestring
,CurPos
);
1275 CurPos
= strtok(NULL
, " \t");
1278 } /* end of readString */
1281 /**Function********************************************************************
1283 Synopsis [Reads a list of strings from a file.]
1285 Description [Reads a list of strings from a line of a file.
1286 The strings are sequences of characters separated by spaces or tabs.
1287 The total length of the list, white space included, must not exceed
1288 MAXLENGTH-1 characters. readList allocates memory for the strings and
1289 creates an array of pointers to the individual lists. Only two pieces
1290 of memory are allocated by readList: One to hold all the strings,
1291 and one to hold the pointers to them. Therefore, when freeing the
1292 memory allocated by readList, only the pointer to the list of
1293 pointers, and the pointer to the beginning of the first string should
1294 be freed. readList returns the pointer to the list of pointers if
1295 successful; NULL otherwise.]
1297 SideEffects [n is set to the number of strings in the list.]
1299 SeeAlso [readString printList]
1301 ******************************************************************************/
1304 FILE * fp
/* pointer to the file from which the list is read */,
1305 int * n
/* on return, number of strings in the list */)
1314 if (strcmp(CurPos
, "\\") == 0) {
1315 CurPos
= (char *)NULL
;
1317 if (!fgets(BuffLine
, MAXLENGTH
, fp
)) return(NULL
);
1318 BuffLine
[strlen(BuffLine
) - 1] = '\0';
1319 CurPos
= strtok(BuffLine
, " \t");
1322 length
= strlen(CurPos
);
1323 savestring
= ALLOC(char,length
+1);
1324 if (savestring
== NULL
) return(NULL
);
1325 strcpy(savestring
,CurPos
);
1326 stack
[count
] = savestring
;
1328 CurPos
= strtok(NULL
, " \t");
1330 list
= ALLOC(char *, count
);
1331 for (i
= 0; i
< count
; i
++)
1336 } /* end of readList */
1339 /**Function********************************************************************
1341 Synopsis [Prints a list of strings to the standard output.]
1343 Description [Prints a list of strings to the standard output. The list
1344 is in the format created by readList.]
1348 SeeAlso [readList Bnet_PrintNetwork]
1350 ******************************************************************************/
1353 char ** list
/* list of pointers to strings */,
1354 int n
/* length of the list */)
1358 for (i
= 0; i
< n
; i
++) {
1359 (void) fprintf(stdout
," %s",list
[i
]);
1361 (void) fprintf(stdout
,"\n");
1363 } /* end of printList */
1366 /**Function********************************************************************
1368 Synopsis [Generates names not currently in a symbol table.]
1370 Description [Generates n names not currently in the symbol table hash.
1371 The pointer to the symbol table may be NULL, in which case no test is
1372 made. The names generated by the procedure are unique. So, if there is
1373 no possibility of conflict with pre-existing names, NULL can be passed
1374 for the hash table. Returns an array of names if succesful; NULL
1381 ******************************************************************************/
1383 bnetGenerateNewNames(
1384 st_table
* hash
/* table of existing names (or NULL) */,
1385 int n
/* number of names to be generated */)
1391 if (n
< 1) return(NULL
);
1393 list
= ALLOC(char *,n
);
1394 if (list
== NULL
) return(NULL
);
1395 for (i
= 0; i
< n
; i
++) {
1397 sprintf(name
, "var%d", newNameNumber
);
1399 } while (hash
!= NULL
&& st_is_member(hash
,name
));
1400 list
[i
] = util_strsav(name
);
1405 } /* bnetGenerateNewNames */
1408 /**Function********************************************************************
1410 Synopsis [Writes blif for the reencoding logic.]
1418 ******************************************************************************/
1420 bnetDumpReencodingLogic(
1421 DdManager
* dd
/* DD manager */,
1422 char * mname
/* model name */,
1423 int noutputs
/* number of outputs */,
1424 DdNode
** outputs
/* array of network outputs */,
1425 char ** inames
/* array of network input names */,
1426 char ** altnames
/* array of names of reencoded inputs */,
1427 char ** onames
/* array of network output names */,
1428 FILE * fp
/* file pointer */)
1432 int nvars
= Cudd_ReadSize(dd
);
1433 int *support
= NULL
;
1435 support
= bnetFindVectorSupport(dd
,outputs
,noutputs
);
1436 if (support
== NULL
) return(0);
1438 /* Write the header (.model .inputs .outputs). */
1439 retval
= fprintf(fp
,".model %s.global\n.inputs",mname
);
1440 if (retval
== EOF
) goto failure
;
1442 for (i
= 0; i
< nvars
; i
++) {
1443 if ((i
%8 == 0)&&i
) {
1444 retval
= fprintf(fp
," \\\n");
1445 if (retval
== EOF
) goto failure
;
1447 retval
= fprintf(fp
," %s", inames
[i
]);
1448 if (retval
== EOF
) goto failure
;
1451 /* Write the .output line. */
1452 retval
= fprintf(fp
,"\n.outputs");
1453 if (retval
== EOF
) goto failure
;
1454 for (i
= 0; i
< noutputs
; i
++) {
1455 if ((i
%8 == 0)&&i
) {
1456 retval
= fprintf(fp
," \\\n");
1457 if (retval
== EOF
) goto failure
;
1459 retval
= fprintf(fp
," %s", onames
[i
]);
1460 if (retval
== EOF
) goto failure
;
1462 retval
= fprintf(fp
,"\n");
1463 if (retval
== EOF
) goto failure
;
1465 /* Instantiate main subcircuit. */
1466 retval
= fprintf(fp
,"\n.subckt %s", mname
);
1467 if (retval
== EOF
) goto failure
;
1468 for (i
= 0; i
< nvars
; i
++) {
1469 if ((i
%8 == 0)&&i
) {
1470 retval
= fprintf(fp
," \\\n");
1471 if (retval
== EOF
) goto failure
;
1473 if (support
[i
] == 1) {
1474 retval
= fprintf(fp
," %s=%s", inames
[i
], altnames
[i
]);
1475 if (retval
== EOF
) goto failure
;
1478 for (i
= 0; i
< noutputs
; i
++) {
1479 if ((i
%8 == 0)&&i
) {
1480 retval
= fprintf(fp
," \\\n");
1481 if (retval
== EOF
) goto failure
;
1483 retval
= fprintf(fp
," %s=%s", onames
[i
], onames
[i
]);
1484 if (retval
== EOF
) goto failure
;
1486 retval
= fprintf(fp
,"\n");
1487 if (retval
== EOF
) goto failure
;
1489 /* Instantiate reencoding subcircuit. */
1490 retval
= fprintf(fp
,"\n.subckt %s.reencode",mname
);
1491 if (retval
== EOF
) goto failure
;
1492 for (i
= 0; i
< nvars
; i
++) {
1493 if ((i
%8 == 0)&&i
) {
1494 retval
= fprintf(fp
," \\\n");
1495 if (retval
== EOF
) goto failure
;
1497 retval
= fprintf(fp
," %s=%s", inames
[i
], inames
[i
]);
1498 if (retval
== EOF
) goto failure
;
1500 retval
= fprintf(fp
," \\\n");
1501 if (retval
== EOF
) goto failure
;
1502 for (i
= 0; i
< nvars
; i
++) {
1503 if ((i
%8 == 0)&&i
) {
1504 retval
= fprintf(fp
," \\\n");
1505 if (retval
== EOF
) goto failure
;
1507 if (support
[i
] == 1) {
1508 retval
= fprintf(fp
," %s=%s", altnames
[i
],altnames
[i
]);
1509 if (retval
== EOF
) goto failure
;
1512 retval
= fprintf(fp
,"\n");
1513 if (retval
== EOF
) goto failure
;
1515 /* Write trailer. */
1516 retval
= fprintf(fp
,".end\n\n");
1517 if (retval
== EOF
) goto failure
;
1519 /* Write reencoding subcircuit. */
1520 retval
= bnetBlifWriteReencode(dd
,mname
,inames
,altnames
,support
,fp
);
1521 if (retval
== EOF
) goto failure
;
1527 if (support
!= NULL
) FREE(support
);
1530 } /* end of bnetDumpReencodingLogic */
1533 /**Function********************************************************************
1535 Synopsis [Writes blif for the truth table of an n-input xnor.]
1537 Description [Writes blif for the truth table of an n-input
1538 xnor. Returns 1 if successful; 0 otherwise.]
1544 ******************************************************************************/
1548 FILE * fp
/* file pointer */,
1549 int n
/* number of inputs */)
1551 int power
; /* 2 to the power n */
1557 line
= ALLOC(char,n
+1);
1558 if (line
== NULL
) return(0);
1561 for (i
= 0, power
= 1; i
< n
; i
++) {
1565 for (i
= 0; i
< power
; i
++) {
1568 for (j
= 0; j
< n
; j
++) {
1577 if ((nzeroes
& 1) == 0) {
1578 retval
= fprintf(fp
,"%s 1\n",line
);
1579 if (retval
== 0) return(0);
1584 } /* end of bnetBlifXnorTable */
1588 /**Function********************************************************************
1590 Synopsis [Writes blif for the reencoding logic.]
1592 Description [Writes blif for the reencoding logic. Exclusive NORs
1593 with more than two inputs are decomposed into cascaded two-input
1594 gates. Returns 1 if successful; 0 otherwise.]
1600 ******************************************************************************/
1602 bnetBlifWriteReencode(
1611 int nvars
= Cudd_ReadSize(dd
);
1615 /* Write the header (.model .inputs .outputs). */
1616 retval
= fprintf(fp
,".model %s.reencode\n.inputs",mname
);
1617 if (retval
== EOF
) return(0);
1619 for (i
= 0; i
< nvars
; i
++) {
1620 if ((i
%8 == 0)&&i
) {
1621 retval
= fprintf(fp
," \\\n");
1622 if (retval
== EOF
) goto failure
;
1624 retval
= fprintf(fp
," %s", inames
[i
]);
1625 if (retval
== EOF
) goto failure
;
1628 /* Write the .output line. */
1629 retval
= fprintf(fp
,"\n.outputs");
1630 if (retval
== EOF
) goto failure
;
1631 for (i
= 0; i
< nvars
; i
++) {
1632 if ((i
%8 == 0)&&i
) {
1633 retval
= fprintf(fp
," \\\n");
1634 if (retval
== EOF
) goto failure
;
1636 if (support
[i
] == 1) {
1637 retval
= fprintf(fp
," %s", altnames
[i
]);
1638 if (retval
== EOF
) goto failure
;
1641 retval
= fprintf(fp
,"\n");
1642 if (retval
== EOF
) goto failure
;
1644 /* Instantiate exclusive nors. */
1645 for (i
= 0; i
< nvars
; i
++) {
1649 if (support
[i
] == 0) continue;
1651 for (j
= 0; j
< nvars
; j
++) {
1652 if (Cudd_ReadLinear(dd
,i
,j
)) {
1663 oname
= bnetGenerateNewNames(NULL
,1);
1664 retval
= fprintf(fp
,".names %s %s %s\n11 1\n00 1\n",
1665 in1
, in2
, oname
[0]);
1666 if (retval
== EOF
) goto failure
;
1678 retval
= fprintf(fp
,".names %s %s\n1 1\n", in1
, altnames
[i
]);
1679 if (retval
== EOF
) goto failure
;
1682 retval
= fprintf(fp
,".names %s %s %s\n11 1\n00 1\n",
1683 in1
, in2
, altnames
[i
]);
1684 if (retval
== EOF
) goto failure
;
1691 /* Write trailer. */
1692 retval
= fprintf(fp
,"\n.end\n\n");
1693 if (retval
== EOF
) goto failure
;
1700 } /* end of bnetBlifWriteReencode */
1703 /**Function********************************************************************
1705 Synopsis [Finds the support of a list of DDs.]
1713 ******************************************************************************/
1715 bnetFindVectorSupport(
1720 DdNode
*support
= NULL
;
1723 int nvars
= Cudd_ReadSize(dd
);
1726 /* Build an array with the support of the functions in list. */
1727 array
= ALLOC(int,nvars
);
1728 if (array
== NULL
) return(NULL
);
1729 for (i
= 0; i
< nvars
; i
++) {
1733 /* Take the union of the supports of each output function. */
1734 for (i
= 0; i
< n
; i
++) {
1735 support
= Cudd_Support(dd
,list
[i
]);
1736 if (support
== NULL
) {
1742 while (!Cudd_IsConstant(scan
)) {
1743 array
[scan
->index
] = 1;
1744 scan
= Cudd_T(scan
);
1746 Cudd_IterDerefBdd(dd
,support
);
1751 } /* end of bnetFindVectorSupport */
1754 /**Function********************************************************************
1756 Synopsis [Builds BDD for a XOR function.]
1758 Description [Checks whether a function is a XOR with 2 or 3 inputs. If so,
1759 it builds the BDD. Returns 1 if the BDD has been built; 0 otherwise.]
1765 ******************************************************************************/
1778 DdNode
*func
, *var
, *tmp
;
1781 if (nd
->ninp
< 2 || nd
->ninp
> 3) return(0);
1783 nlines
= 1 << (nd
->ninp
- 1);
1784 for (i
= 0; i
< 8; i
++) check
[i
] = 0;
1786 while (line
!= NULL
) {
1790 for (i
= 0; i
< nd
->ninp
; i
++) {
1792 if (line
->values
[i
] == '-') {
1794 } else if (line
->values
[i
] == '1') {
1799 if ((count
& 1) == 0) return(0);
1800 if (check
[num
]) return(0);
1803 if (nlines
!= 0) return(0);
1805 /* Initialize the exclusive sum to logical 0. */
1806 func
= Cudd_ReadLogicZero(dd
);
1809 /* Scan the inputs. */
1810 for (i
= 0; i
< nd
->ninp
; i
++) {
1811 if (!st_lookup(hash
, nd
->inputs
[i
], &auxnd
)) {
1814 if (params
== BNET_LOCAL_DD
) {
1815 if (auxnd
->active
== FALSE
) {
1816 if (!Bnet_BuildNodeBDD(dd
,auxnd
,hash
,params
,nodrop
)) {
1820 var
= Cudd_ReadVars(dd
,auxnd
->var
);
1821 if (var
== NULL
) goto failure
;
1823 } else { /* params == BNET_GLOBAL_DD */
1824 if (auxnd
->dd
== NULL
) {
1825 if (!Bnet_BuildNodeBDD(dd
,auxnd
,hash
,params
,nodrop
)) {
1831 tmp
= Cudd_bddXor(dd
,func
,var
);
1832 if (tmp
== NULL
) goto failure
;
1834 Cudd_IterDerefBdd(dd
,func
);
1835 if (params
== BNET_LOCAL_DD
) {
1836 Cudd_IterDerefBdd(dd
,var
);
1842 /* Associate a variable to this node if local BDDs are being
1843 ** built. This is done at the end, so that the primary inputs tend
1844 ** to get lower indices.
1846 if (params
== BNET_LOCAL_DD
&& nd
->active
== FALSE
) {
1847 DdNode
*auxfunc
= Cudd_bddNewVar(dd
);
1848 if (auxfunc
== NULL
) goto failure
;
1850 nd
->var
= auxfunc
->index
;
1852 Cudd_IterDerefBdd(dd
,auxfunc
);
1859 } /* end of buildExorBDD */
1862 /**Function********************************************************************
1864 Synopsis [Builds BDD for a multiplexer.]
1866 Description [Checks whether a function is a 2-to-1 multiplexer. If so,
1867 it builds the BDD. Returns 1 if the BDD has been built; 0 otherwise.]
1873 ******************************************************************************/
1890 DdNode
*func
, *f
, *g
, *h
;
1893 if (nd
->ninp
!= 3) return(0);
1895 for (line
= nd
->f
; line
!= NULL
; line
= line
->next
) {
1897 if (nlines
> 1) return(0);
1898 values
[nlines
] = line
->values
;
1899 for (j
= 0; j
< 3; j
++) {
1900 if (values
[nlines
][j
] == '-') {
1908 /* At this point we know we have:
1911 ** 1 dash in each line
1912 ** If the two dashes are not in the same column, then there is
1913 ** exaclty one column without dashes: the control column.
1915 for (j
= 0; j
< 3; j
++) {
1916 if (values
[0][j
] == '-' && values
[1][j
] == '-') return(0);
1917 if (values
[0][j
] != '-' && values
[1][j
] != '-') {
1918 if (values
[0][j
] == values
[1][j
]) return(0);
1920 controlR
= values
[0][j
] == '0';
1923 assert(controlC
!= -1 && controlR
!= -1);
1924 /* At this point we know that there is indeed no column with two
1925 ** dashes. The control column has been identified, and we know that
1926 ** its two elelments are different. */
1927 for (j
= 0; j
< 3; j
++) {
1928 if (j
== controlC
) continue;
1929 if (values
[controlR
][j
] == '1') {
1932 } else if (values
[controlR
][j
] == '0') {
1935 } else if (values
[1-controlR
][j
] == '1') {
1938 } else if (values
[1-controlR
][j
] == '0') {
1944 /* Get the inputs. */
1945 if (!st_lookup(hash
, nd
->inputs
[controlC
], &auxnd
)) {
1948 if (params
== BNET_LOCAL_DD
) {
1949 if (auxnd
->active
== FALSE
) {
1950 if (!Bnet_BuildNodeBDD(dd
,auxnd
,hash
,params
,nodrop
)) {
1954 f
= Cudd_ReadVars(dd
,auxnd
->var
);
1955 if (f
== NULL
) goto failure
;
1957 } else { /* params == BNET_GLOBAL_DD */
1958 if (auxnd
->dd
== NULL
) {
1959 if (!Bnet_BuildNodeBDD(dd
,auxnd
,hash
,params
,nodrop
)) {
1965 if (!st_lookup(hash
, nd
->inputs
[mux
[0]], &auxnd
)) {
1968 if (params
== BNET_LOCAL_DD
) {
1969 if (auxnd
->active
== FALSE
) {
1970 if (!Bnet_BuildNodeBDD(dd
,auxnd
,hash
,params
,nodrop
)) {
1974 g
= Cudd_ReadVars(dd
,auxnd
->var
);
1975 if (g
== NULL
) goto failure
;
1977 } else { /* params == BNET_GLOBAL_DD */
1978 if (auxnd
->dd
== NULL
) {
1979 if (!Bnet_BuildNodeBDD(dd
,auxnd
,hash
,params
,nodrop
)) {
1985 g
= Cudd_NotCond(g
,phase
[0]);
1986 if (!st_lookup(hash
, nd
->inputs
[mux
[1]], &auxnd
)) {
1989 if (params
== BNET_LOCAL_DD
) {
1990 if (auxnd
->active
== FALSE
) {
1991 if (!Bnet_BuildNodeBDD(dd
,auxnd
,hash
,params
,nodrop
)) {
1995 h
= Cudd_ReadVars(dd
,auxnd
->var
);
1996 if (h
== NULL
) goto failure
;
1998 } else { /* params == BNET_GLOBAL_DD */
1999 if (auxnd
->dd
== NULL
) {
2000 if (!Bnet_BuildNodeBDD(dd
,auxnd
,hash
,params
,nodrop
)) {
2006 h
= Cudd_NotCond(h
,phase
[1]);
2007 func
= Cudd_bddIte(dd
,f
,g
,h
);
2008 if (func
== NULL
) goto failure
;
2010 if (params
== BNET_LOCAL_DD
) {
2011 Cudd_IterDerefBdd(dd
,f
);
2012 Cudd_IterDerefBdd(dd
,g
);
2013 Cudd_IterDerefBdd(dd
,h
);
2017 /* Associate a variable to this node if local BDDs are being
2018 ** built. This is done at the end, so that the primary inputs tend
2019 ** to get lower indices.
2021 if (params
== BNET_LOCAL_DD
&& nd
->active
== FALSE
) {
2022 DdNode
*auxfunc
= Cudd_bddNewVar(dd
);
2023 if (auxfunc
== NULL
) goto failure
;
2025 nd
->var
= auxfunc
->index
;
2027 Cudd_IterDerefBdd(dd
,auxfunc
);
2034 } /* end of buildExorBDD */
2037 /**Function********************************************************************
2039 Synopsis [Sets the level of each node.]
2041 Description [Sets the level of each node. Returns 1 if successful; 0
2044 SideEffects [Changes the level and visited fields of the nodes it
2047 SeeAlso [bnetLevelDFS]
2049 ******************************************************************************/
2056 /* Recursively visit nodes. This is pretty inefficient, because we
2057 ** visit all nodes in this loop, and most of them in the recursive
2058 ** calls to bnetLevelDFS. However, this approach guarantees that
2059 ** all nodes will be reached ven if there are dangling outputs. */
2061 while (node
!= NULL
) {
2062 if (!bnetLevelDFS(net
,node
)) return(0);
2066 /* Clear visited flags. */
2068 while (node
!= NULL
) {
2074 } /* end of bnetSetLevel */
2077 /**Function********************************************************************
2079 Synopsis [Does a DFS from a node setting the level field.]
2081 Description [Does a DFS from a node setting the level field. Returns
2082 1 if successful; 0 otherwise.]
2084 SideEffects [Changes the level and visited fields of the nodes it
2087 SeeAlso [bnetSetLevel]
2089 ******************************************************************************/
2098 if (node
->visited
== 1) {
2104 /* Graphical sources have level 0. This is the final value if the
2105 ** node has no fan-ins. Otherwise the successive loop will
2106 ** increase the level. */
2108 for (i
= 0; i
< node
->ninp
; i
++) {
2109 if (!st_lookup(net
->hash
, node
->inputs
[i
], &auxnd
)) {
2112 if (!bnetLevelDFS(net
,auxnd
)) {
2115 if (auxnd
->level
>= node
->level
) node
->level
= 1 + auxnd
->level
;
2119 } /* end of bnetLevelDFS */
2122 /**Function********************************************************************
2124 Synopsis [Orders network roots for variable ordering.]
2126 Description [Orders network roots for variable ordering. Returns
2127 an array with the ordered outputs and next state variables if
2128 successful; NULL otherwise.]
2134 ******************************************************************************/
2142 BnetNode
**nodes
= NULL
;
2144 /* Initialize data structures. */
2145 noutputs
= net
->noutputs
;
2146 nodes
= ALLOC(BnetNode
*, noutputs
);
2147 if (nodes
== NULL
) goto endgame
;
2149 /* Find output names and levels. */
2150 for (i
= 0; i
< net
->noutputs
; i
++) {
2151 if (!st_lookup(net
->hash
,net
->outputs
[i
],&node
)) {
2157 qsort((void *)nodes
, noutputs
, sizeof(BnetNode
*),
2158 (DD_QSFP
)bnetLevelCompare
);
2163 if (nodes
!= NULL
) FREE(nodes
);
2166 } /* end of bnetOrderRoots */
2169 /**Function********************************************************************
2171 Synopsis [Comparison function used by qsort.]
2173 Description [Comparison function used by qsort to order the
2174 variables according to the number of keys in the subtables.
2175 Returns the difference in number of keys between the two
2176 variables being compared.]
2180 ******************************************************************************/
2186 return((*y
)->level
- (*x
)->level
);
2188 } /* end of bnetLevelCompare */
2191 /**Function********************************************************************
2193 Synopsis [Does a DFS from a node ordering the inputs.]
2195 Description [Does a DFS from a node ordering the inputs. Returns
2196 1 if successful; 0 otherwise.]
2198 SideEffects [Changes visited fields of the nodes it visits.]
2200 SeeAlso [Bnet_DfsVariableOrder]
2202 ******************************************************************************/
2213 if (node
->visited
== 1) {
2218 if (node
->type
== BNET_INPUT_NODE
||
2219 node
->type
== BNET_PRESENT_STATE_NODE
) {
2220 node
->dd
= Cudd_bddNewVar(dd
);
2221 if (node
->dd
== NULL
) return(0);
2223 node
->active
= TRUE
;
2224 node
->var
= node
->dd
->index
;
2228 fanins
= ALLOC(BnetNode
*, node
->ninp
);
2229 if (fanins
== NULL
) return(0);
2231 for (i
= 0; i
< node
->ninp
; i
++) {
2232 if (!st_lookup(net
->hash
, node
->inputs
[i
], &auxnd
)) {
2239 qsort((void *)fanins
, node
->ninp
, sizeof(BnetNode
*),
2240 (DD_QSFP
)bnetLevelCompare
);
2241 for (i
= 0; i
< node
->ninp
; i
++) {
2242 /* for (i = node->ninp - 1; i >= 0; i--) { */
2243 int res
= bnetDfsOrder(dd
,net
,fanins
[i
]);
2252 } /* end of bnetLevelDFS */