/* "NETCMP", an simple netlist comparator, Copyright (C) 1985, 1990 California Institute of Technology. Original author: Massimo Sivilotti Unix Port Maintainer: John Lazzaro Maintainers's address: lazzaro@csvax.caltech.edu; CB 425 CU Boulder/Boulder CO 91125. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation (any version). This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Output from P2C, the Pascal-to-C translator */ /* p2c: datastruct.text, line 1: Note: Range checking is OFF */ /* From input file "datastruct.text" */ #include #include #include #include #ifdef linux #include #endif #include "datastruct.h" static long line_position; /* where are we on the line */ static char tmp_str[81]; /* generic string */ static long junk; /* generic strwrite integer */ static long allocated_nodes, garbage_nodes, allocated_trans, garbage_trans, allocated_tequiv, garbage_tequiv, allocated_nequiv, garbage_nequiv, allocated_names, allocated_equiv_list, garbage_equiv_list, memavail_init; static nequivtype *nequiv_garbage; /* garbage list */ static tequivtype *tequiv_garbage; /* garbage list */ static trantype *tranGarbage; /* garbage list */ static tran_list_type *nodeTranGarbage; /* garbage list */ static nodetype *nodeGarbage; /* garbage list */ static nametype *nameGarbage; /* garbage list */ static equiv_list_type *equiv_list_garbage; static void my_write(s) char *s; { line_position += strlen(s); fputs(s, outfyle); } static void my_writeln() { putc('\n', outfyle); line_position = 0; } static void write_string(string1, string2) char *string1, *string2; { if (line_position + strlen(string1) <= max_line_width) { /* force a line feed, and indent by string2 */ my_write(string1); return; } my_writeln(); my_write(string2); my_write(string1); } long memavail() { return(1000000); } void initialize_data_structure() { nequiv = NULL; tequiv = NULL; nequiv_garbage = NULL; /* garbage list */ tequiv_garbage = NULL; /* garbage list */ equiv_list_garbage = NULL; tranGarbage = NULL; nodeTranGarbage = NULL; nodeGarbage = NULL; nameGarbage = NULL; allocated_nodes = 0; allocated_trans = 0; allocated_nequiv = 0; allocated_tequiv = 0; allocated_equiv_list = 0; garbage_nodes = 0; garbage_trans = 0; garbage_nequiv = 0; garbage_tequiv = 0; garbage_equiv_list = 0; memavail_init = memavail(); } char *name_list(Result, names) char *Result; nametype *names; { char namestr[256]; *namestr = '\0'; while (names != NULL) { sprintf(namestr + strlen(namestr), " %s", names->name); names = names->next; } return strcpy(Result, namestr); } void print_names(names, verbose) nametype *names; char verbose; { char STR3[256]; if (verbose) { my_write("Dumping name list:"); my_writeln(); my_write("List Element -> Name Next"); my_writeln(); while (names != NULL) { sprintf(tmp_str, "%12ld -> %s%12ld", (long)names, names->name, (long)names->next); my_write(tmp_str); my_writeln(); names = names->next; } return; } strcpy(tmp_str, name_list(STR3, names)); my_write(tmp_str); my_writeln(); } void print_all_names(node) nodetype *node; { nametype *name_scan; name_scan = node->names; while (name_scan != NULL) { print_names(name_scan, 0); name_scan = name_scan->next; } } void print_tran_equiv(t) tequivtype *t; { if (t == NULL) return; fprintf(outfyle, "Transistor class: "); if (dbug) fprintf(outfyle, "(%ld): ", (long)t); fprintf(outfyle, "count = %ld; good = %s", t->count, t->good ? "TRUE" : "FALSE"); if (dbug) fprintf(outfyle, " gate^ = %ld s1^ = %ld s2^ = %ld", (long)t->gate, (long)t->s1, (long)t->s2); putc('\n', outfyle); } static char *transistor_types_NAMES[] = { "N", "P", "D", "I", "X" } ; void print_transistor(t) trantype *t; { char STR3[82]; if (t == NULL) return; sprintf(tmp_str, "%s ", transistor_types_NAMES[(long)t->t_type]); my_write(tmp_str); write_string(t->gate->names->name, " "); sprintf(STR3, " %s", t->s1->names->name); write_string(STR3, " "); sprintf(STR3, " %s", t->s2->names->name); write_string(STR3, " "); /* write (outfyle, ord(t):0,' ',t_type:1,' ', my_circuit:1,' g:',name_list(gate^.names), ' s1:',name_list(s1^.names),' s2:',name_list(s2^.names)); */ if (dbug) fprintf(outfyle, " addr = %ld class^ = %ld", (long)t, (long)t->my_equiv_class); my_writeln(); if (!dbug) return; printf("Gate: %12ld ", (long)t->gate); print_names(t->gate->names, 1); printf("S1: %12ld ", (long)t->s1); print_names(t->s1->names, 1); printf("S2: %12ld ", (long)t->s2); print_names(t->s2->names, 1); /*,my_circuit:1,' ' strength ??*/ } void print_tran_equiv_class(t_scan) tequivtype *t_scan; { trantype *tran_scan; print_tran_equiv(t_scan); tran_scan = t_scan->transistors; while (tran_scan != NULL) { fprintf(outfyle, " "); print_transistor(tran_scan); tran_scan = tran_scan->next; } } void print_transistor_list(n) tran_list_type *n; { while (n != NULL) { fprintf(outfyle, " "); print_transistor(n->tran); n = n->next; } } void print_node_equiv(n_scan) nequivtype *n_scan; { if (n_scan == NULL) return; fprintf(outfyle, "Node equivalence: count = %ld good = %s", n_scan->count, n_scan->good ? "TRUE" : "FALSE"); if (dbug) fprintf(outfyle, " addr = %ld", (long)n_scan); putc('\n', outfyle); } void print_node(n) nodetype *n; { char tmp_str[81]; if (n == NULL) return; sprintf(tmp_str, " Node: %s", n->names->name); my_write(tmp_str); /*' circuit: ',my_circuit:0, */ sprintf(tmp_str, " fanout: pg=%ld ng=%ld ps=%ld ns=%ld", n->pg, n->ng, n->ps, n->ns); write_string(tmp_str, " "); if (dbug) fprintf(outfyle, " class=%ld", (long)n->my_equiv_class); if (dbug) fprintf(outfyle, " clone = %ld", (long)n->clone); my_writeln(); } void print_node_equiv_class(head) nequivtype *head; { nodetype *node_scan; print_node_equiv(head); node_scan = head->nodes; while (node_scan != NULL) { print_node(node_scan); print_transistor_list(node_scan->trans); node_scan = node_scan->next; } } void dump_data_structure() { /* traverses all the transistor equivalence classes, printing nodes */ /* traverses all the node equivalence classes, printing fanouts */ tequivtype *t_scan; nequivtype *n_scan; t_scan = tequiv; fprintf(outfyle, "TRANSISTOR EQUIVALENCE CLASSES ---\n"); while (t_scan != NULL) { print_tran_equiv_class(t_scan); t_scan = t_scan->next; } fprintf(outfyle, "NODE EQUIVALENCE CLASSES ---\n"); n_scan = nequiv; while (n_scan != NULL) { print_node_equiv_class(n_scan); n_scan = n_scan->next; } } equiv_list_type *getEquivList() { equiv_list_type *Result, *tmp; if (equiv_list_garbage == NULL) { tmp = (equiv_list_type *)malloc(sizeof(equiv_list_type)); return tmp; } Result = equiv_list_garbage; equiv_list_garbage = equiv_list_garbage->next; /*$if ACCOUNTING$ garbage_equiv_list := garbage_equiv_list - 1; $end$*/ return Result; /*$if ACCOUNTING$ allocated_equiv_list := allocated_equiv_list + 1; $end$*/ } void reclaimEquivList(head) equiv_list_type **head; { equiv_list_type *scan; if (*head == NULL) return; scan = *head; while (scan->next != NULL) { /*$if ACCOUNTING$ garbage_equiv_list := garbage_equiv_list + 1; $end$*/ scan = scan->next; } /* pre-append whole list to garbage_equiv_list */ scan->next = equiv_list_garbage; /*$if ACCOUNTING$ garbage_equiv_list := garbage_equiv_list + 1; $end$*/ equiv_list_garbage = *head; *head = NULL; } tequivtype *getTEquiv() { tequivtype *tequivp; if (tequiv_garbage != NULL) { tequivp = tequiv_garbage; tequiv_garbage = tequiv_garbage->next; /*$if ACCOUNTING$ garbage_tequiv := garbage_tequiv - 1; $end$*/ } else tequivp = (tequivtype *)malloc(sizeof(tequivtype)); tequivp->count = 0; tequivp->gate = NULL; tequivp->s1 = NULL; tequivp->s2 = NULL; tequivp->egate = NULL; tequivp->es1 = NULL; tequivp->es2 = NULL; tequivp->transistors = NULL; tequivp->next = NULL; tequivp->good = 1; return tequivp; /*$if ACCOUNTING$ allocated_tequiv := allocated_tequiv + 1; $end$*/ } void reclaim_tran_class(scan) tequivtype **scan; { /* reclaim the trans used */ (*scan)->next = tequiv_garbage; tequiv_garbage = *scan; /*$if ACCOUNTING$ garbage_tequiv := garbage_tequiv + 1; $end$*/ *scan = NULL; } nequivtype *getNEquiv() { nequivtype *nequivp; if (nequiv_garbage != NULL) { nequivp = nequiv_garbage; nequiv_garbage = nequiv_garbage->next; /*$if ACCOUNTING$ garbage_nequiv := garbage_nequiv - 1; $end$*/ } else { nequivp = (nequivtype *)malloc(sizeof(nequivtype)); /*$if ACCOUNTING$ allocated_nequiv := allocated_nequiv + 1; $end$*/ } nequivp->count = 0; nequivp->nodes = NULL; nequivp->next = NULL; nequivp->good = 1; nequivp->equiv_list = NULL; return nequivp; } void reclaim_node_class(scan) nequivtype **scan; { /* reclaim the trans used */ (*scan)->next = nequiv_garbage; nequiv_garbage = *scan; /*$if ACCOUNTING$ garbage_nequiv := garbage_nequiv + 1; $end$*/ /* NO!! if scan^.equiv_list <> nil then reclaimEquivList (scan^.equiv_list); */ /* MAS */ *scan = NULL; } trantype *find_tran(head, name) tequivtype *head; char *name; { tequivtype *scan; trantype *tran_scan; char found; scan = head; found = 0; while (scan != NULL && !found) { tran_scan = scan->transistors; /* while (tran_scan <> nil) and not found do if tran_scan^.name = name then found := 1 else tran_scan := tran_scan^.next; we do not know how to search for transistors !!!!!!!! */ scan = scan->next; } if (found) return tran_scan; else return NULL; } trantype *getTran() { trantype *tran; if (tranGarbage != NULL) { tran = tranGarbage; tranGarbage = tranGarbage->next; /*$if ACCOUNTING$ garbage_trans := garbage_trans - 1; $end$*/ } else { tran = (trantype *)malloc(sizeof(trantype)); /*$if ACCOUNTING$ allocated_trans := allocated_trans + 1; $end$*/ } tran->strength = 0; tran->gate = NULL; tran->s1 = NULL; tran->s2 = NULL; tran->t_type = X; tran->next = NULL; tran->clone = NULL; tran->my_equiv_class = NULL; tran->my_circuit = 1; return tran; } void reclaimTran(tran) trantype **tran; { /* reclaim the transistor used */ (*tran)->next = tranGarbage; tranGarbage = *tran; /*$if ACCOUNTING$ garbage_trans := garbage_trans + 1; $end$*/ *tran = NULL; } void reclaimTranList(tran) trantype **tran; { /* reclaim the list of transistor used */ trantype *next; while (*tran != NULL) { next = (*tran)->next; reclaimTran(tran); *tran = next; } } /* Get an element in a list of transistor pointers. Used by nodes. */ tran_list_type *getNodeTran() { tran_list_type *nodeTran; if (nodeTranGarbage != NULL) { nodeTran = nodeTranGarbage; nodeTranGarbage = nodeTranGarbage->next; } else nodeTran = (tran_list_type *)malloc(sizeof(tran_list_type)); nodeTran->tran = NULL; nodeTran->next = NULL; return nodeTran; } /* reclaim the nodes list of transistor pointers */ void reclaimNodeTran(nodeTran) tran_list_type **nodeTran; { (*nodeTran)->next = nodeTranGarbage; nodeTranGarbage = *nodeTran; *nodeTran = NULL; } /* reclaim the nodes list of transistor pointers */ void reclaimNodeTranList(nodeTran) tran_list_type **nodeTran; { tran_list_type *next; while (*nodeTran != NULL) { next = (*nodeTran)->next; reclaimNodeTran(nodeTran); *nodeTran = next; } } nametype *getName() { nametype *Result, *name; if (nameGarbage != NULL) { name = nameGarbage; nameGarbage = nameGarbage->next; } else { name = (nametype *)malloc(sizeof(nametype)); /*$if ACCOUNTING$ allocated_names := allocated_names + 1; $end$*/ } Result = name; #if 1 name->name = NULL; #else *name->name = '\0'; #endif name->next = NULL; return Result; } void reclaimName(name) nametype **name; { (*name)->next = nameGarbage; #if 1 free((*name)->name); #endif nameGarbage = *name; *name = NULL; } void reclaimNameList(names) nametype **names; { nametype *next; while (*names != NULL) { next = (*names)->next; reclaimName(names); *names = next; } } nodetype *find_node(head, name) nequivtype *head; char *name; { nequivtype *scan; nodetype *node_scan; nametype *name_scan; char found; scan = head; found = 0; while (scan != NULL && !found) { node_scan = scan->nodes; while (node_scan != NULL && !found) { name_scan = node_scan->names; while (name_scan != NULL && !found) { if (!strcmp(name_scan->name, name)) found = 1; name_scan = name_scan->next; } if (!found) node_scan = node_scan->next; } scan = scan->next; } if (found) return node_scan; else return NULL; } nodetype *getNode() { nodetype *nodep; /* if nodeGarbage <> NIL then begin nodep := nodeGarbage; nodeGarbage := nodeGarbage^.next; end else new(nodep); */ /*$if ACCOUNTING$ allocated_nodes := allocated_nodes + 1; $end$*/ nodep = (nodetype *)malloc(sizeof(nodetype)); nodep->strength = 0; nodep->names = NULL; nodep->trans = NULL; nodep->next = NULL; nodep->clone = NULL; nodep->pg = 0; nodep->ng = 0; nodep->ps = 0; nodep->ns = 0; nodep->my_equiv_class = NULL; nodep->equiv_list = NULL; nodep->my_circuit = 1; return nodep; } void reclaimNode(node) nodetype **node; { /* reclaim the node used */ reclaimNameList(&(*node)->names); reclaimNodeTranList(&(*node)->trans); (*node)->next = nodeGarbage; nodeGarbage = *node; *node = NULL; /*$if ACCOUNTING$ garbage_nodes := garbage_nodes + 1; $end$*/ } void reclaimNodeList(node) nodetype **node; { /* reclaim the list of nodes used */ nodetype *next; while (*node != NULL) { next = (*node)->next; reclaimNode(node); *node = next; } } long number_of_tran_classes(head) tequivtype *head; { tequivtype *scan; long count; scan = head; count = 0; while (scan != NULL) { scan = scan->next; count++; } return count; } long number_of_trans_in_class(head) tequivtype *head; { trantype *scan; long count; count = 0; scan = head->transistors; while (scan != NULL) { scan = scan->next; count++; } return count; } void remove_tran_class_from_list(scan, head) tequivtype *scan, **head; { /* removes a transistor class from a list, updating the list head as required */ tequivtype *tmp; if (*head == scan) { *head = scan->next; scan->next = NULL; return; } tmp = *head; while (tmp->next != scan) tmp = tmp->next; tmp->next = scan->next; scan->next = NULL; /* must find it first */ } void add_tclass_to_list(tclass, head) tequivtype *tclass, **head; { /* add the transistor equivalence class to the head of the list of tran equiv. classes */ tclass->next = *head; *head = tclass; tclass->count = number_of_trans_in_class(tclass); /* optional at vers 1.01 */ } void add_tran_to_class(tran, class_) trantype *tran; tequivtype **class_; { /* add the node to the equivalence class pointed to by class */ if (*class_ == NULL) { *class_ = getTEquiv(); tran->next = NULL; (*class_)->transistors = tran; tran->my_equiv_class = *class_; return; } tran->next = (*class_)->transistors; (*class_)->transistors = tran; tran->my_equiv_class = *class_; } char valid_tran_class(scan) tequivtype *scan; { /* returns TRUE if the transistor class is valid (i.e. equal numbers of elements from each circuit ) */ long count1, count2; trantype *scan1; count1 = 0; count2 = 0; scan1 = scan->transistors; while (scan1 != NULL) { if (scan1->my_circuit == 1) count1++; if (scan1->my_circuit == 2) count2++; scan1 = scan1->next; } scan->good = (count1 == count2); if (count1 == count2) return 1; else return 0; } long number_of_node_classes(head) nequivtype *head; { nequivtype *scan; long count; scan = head; count = 0; while (scan != NULL) { scan = scan->next; count++; } return count; } long number_of_nodes_in_class(head) nequivtype *head; { nodetype *scan; long count; count = 0; scan = head->nodes; while (scan != NULL) { scan = scan->next; count++; } return count; } char valid_node_class(scan) nequivtype *scan; { /* returns TRUE if the node class is valid (i.e. equal numbers of elements from each circuit ) */ long count1, count2; nodetype *scan1; count1 = 0; count2 = 0; scan1 = scan->nodes; while (scan1 != NULL) { if (scan1->my_circuit == 1) count1++; if (scan1->my_circuit == 2) count2++; scan1 = scan1->next; } scan->good = (count1 == count2); if (count1 == count2) return 1; else return 0; } void remove_from_list(scan, head) nequivtype *scan, **head; { /* removes a class from a list, updating the list head as required */ nequivtype *tmp; if (*head == scan) { *head = scan->next; scan->next = NULL; return; } tmp = *head; while (tmp->next != scan) tmp = tmp->next; tmp->next = scan->next; scan->next = NULL; /* must find it first */ } void add_nclass_to_list(nclass, head) nequivtype *nclass, **head; { /* add the node equivalence class to the head of the list of node equiv. classes */ nclass->next = *head; *head = nclass; nclass->count = number_of_nodes_in_class(nclass); /* optional at vers 1.01 */ } void add_node_to_class(node, class_) nodetype *node; nequivtype **class_; { /* add the node to the equivalence class pointed to by class */ if (*class_ == NULL) { *class_ = getNEquiv(); node->next = NULL; (*class_)->nodes = node; node->my_equiv_class = *class_; return; } node->next = (*class_)->nodes; (*class_)->nodes = node; node->my_equiv_class = *class_; } void print_memory() { return; printf(" Memory left = %ldK; used = %ldK\n\n", memavail() / 1024, (memavail_init - memavail()) / 1024); /*$if ACCOUNTING$ writeln (' TYPE SIZE ALLOCATED GARBAGE TOTAL'); writeln (' nodes: ',sizeof(nodetype):10, allocated_nodes:10, garbage_nodes:10, allocated_nodes*sizeof(nodetype):10); writeln (' trans: ',sizeof(trantype):10, allocated_trans:10, garbage_trans:10, allocated_trans*sizeof(trantype):10); writeln (' nequiv: ',sizeof(nequivtype):10, allocated_nequiv:10, garbage_nequiv:10, allocated_nequiv*sizeof(nequivtype):10); writeln (' tequiv: ',sizeof(tequivtype):10, allocated_tequiv:10, garbage_tequiv:10, allocated_tequiv*sizeof(tequivtype):10); writeln (' names: ',sizeof(nametype):10, allocated_names:10, 0:10, allocated_names*sizeof(nametype):10); writeln (' equiv: ',sizeof(equiv_list_type):10, allocated_equiv_list:10, garbage_equiv_list:10, allocated_equiv_list*sizeof(equiv_list_type):10); writeln (' TOTAL = ', allocated_nodes*sizeof(nodetype) + allocated_trans*sizeof(trantype) + allocated_nequiv*sizeof(nequivtype) + allocated_tequiv*sizeof(tequivtype) + allocated_equiv_list*sizeof(equiv_list_type) + allocated_names*sizeof(nametype):10 ); $end$*/ } void print_results(nclass, tclass, print_automorphisms) nequivtype *nclass; tequivtype *tclass; char print_automorphisms; { nodetype *node_scan; trantype *tran_scan; long errors; nequivtype *node_class; tequivtype *tran_class; long automorphisms; if (long_results) /* ask for extended result summary */ dbug = 1; putc('\n', outfyle); errors = 0; node_class = nclass; while (node_class != NULL) { if (!node_class->good) { /* error condition exists, so report it */ fprintf(outfyle, "-----------------------------------------------\n"); node_scan = node_class->nodes; while (node_scan != NULL) { fprintf(outfyle, " (%d)", node_scan->my_circuit); print_node(node_scan); node_scan = node_scan->next; } errors++; } node_class = node_class->next; } tran_class = tclass; while (tran_class != NULL) { if (!tran_class->good) { /* error condition exists, so report it */ fprintf(outfyle, "-----------------------------------------------\n"); tran_scan = tran_class->transistors; while (tran_scan != NULL) { fprintf(outfyle, " (%d) Tran: ", tran_scan->my_circuit); print_transistor(tran_scan); tran_scan = tran_scan->next; } errors++; } tran_class = tran_class->next; } putc('\n', outfyle); if (errors == 0) fprintf(outfyle, "No differences found.\n"); else { if (errors == 1) fprintf(outfyle, "1 difference found.\n"); else fprintf(outfyle, "%ld differences found.\n", errors); } if (errors == 0) printf("No differences found.\n"); else { if (errors == 1) printf("1 difference found.\n"); else printf("%ld differences found.\n", errors); } if (!print_automorphisms) return; automorphisms = 0; node_class = nclass; while (node_class != NULL) { if (node_class->good & (number_of_nodes_in_class(node_class) != 2)) { /* automorphism */ fprintf(outfyle, "-----automorphism------------------------------\n"); node_scan = node_class->nodes; while (node_scan != NULL) { fprintf(outfyle, " (%d)", node_scan->my_circuit); print_node(node_scan); node_scan = node_scan->next; } automorphisms++; } node_class = node_class->next; } tran_class = tclass; while (tran_class != NULL) { if (tran_class->good & (number_of_trans_in_class(tran_class) != 2)) { /* automorphism */ fprintf(outfyle, "-----automorphism------------------------------\n"); tran_scan = tran_class->transistors; while (tran_scan != NULL) { fprintf(outfyle, " (%d) Tran: ", tran_scan->my_circuit); print_transistor(tran_scan); tran_scan = tran_scan->next; } automorphisms++; } tran_class = tran_class->next; } putc('\n', outfyle); if (errors == 1) fprintf(outfyle, "1 difference found.\n"); if (errors > 1) fprintf(outfyle, "%ld differences found.\n", errors); if (automorphisms == 0) fprintf(outfyle, "No automorphisms found.\n"); else { if (automorphisms == 1) fprintf(outfyle, "1 automorphism found.\n"); else fprintf(outfyle, "%ld automorphisms found.\n", automorphisms); } if (automorphisms == 0) { printf("No automorphisms found.\n"); return; } if (automorphisms == 1) printf("1 automorphism found.\n"); else printf("%ld automorphisms found.\n", automorphisms); } /* End. */