Compare commits

..

156 Commits

Author SHA1 Message Date
Tim Edwards f5f1240073 Merge branch 'master' into netgen-1.5 2023-07-12 02:00:03 -04:00
Tim Edwards 02d7a1bd01 Merge branch 'master' into netgen-1.5 2023-06-13 02:00:02 -04:00
Tim Edwards 7878b3cfbc Merge branch 'master' into netgen-1.5 2023-04-15 02:00:01 -04:00
Tim Edwards 7f727e6674 Merge branch 'master' into netgen-1.5 2023-04-14 02:00:01 -04:00
Tim Edwards d111fa0a3b Merge branch 'master' into netgen-1.5 2023-03-30 02:00:02 -04:00
Tim Edwards 178b172c06 Merge branch 'master' into netgen-1.5 2023-03-08 02:00:03 -05:00
Tim Edwards 7870538ec9 Merge branch 'master' into netgen-1.5 2023-03-07 02:00:02 -05:00
Tim Edwards ee4e1e087f Merge branch 'master' into netgen-1.5 2023-03-05 02:00:01 -05:00
Tim Edwards 7a8b5e835b Merge branch 'master' into netgen-1.5 2023-03-01 02:00:03 -05:00
Tim Edwards 77f7a773e3 Merge branch 'master' into netgen-1.5 2023-02-28 02:00:03 -05:00
Tim Edwards 9a48a59f68 Merge branch 'master' into netgen-1.5 2023-02-25 02:00:03 -05:00
Tim Edwards 535b8285e9 Merge branch 'master' into netgen-1.5 2022-12-20 02:00:03 -05:00
Tim Edwards 1e1d506697 Merge branch 'master' into netgen-1.5 2022-12-16 02:00:03 -05:00
Tim Edwards 4edaf0813d Merge branch 'master' into netgen-1.5 2022-11-17 02:00:01 -05:00
Tim Edwards a4ae5ed989 Merge branch 'master' into netgen-1.5 2022-11-05 02:00:01 -04:00
Tim Edwards d850586a14 Merge branch 'master' into netgen-1.5 2022-11-03 02:00:03 -04:00
Tim Edwards 4b5b117100 Merge branch 'master' into netgen-1.5 2022-11-02 02:00:02 -04:00
Tim Edwards 935e54abe6 Merge branch 'master' into netgen-1.5 2022-11-01 02:00:02 -04:00
Tim Edwards 49ccf1949a Merge branch 'master' into netgen-1.5 2022-10-30 02:00:03 -04:00
Tim Edwards 9b84776374 Merge branch 'master' into netgen-1.5 2022-10-26 02:00:01 -04:00
Tim Edwards 2af3f2a3f7 Merge branch 'master' into netgen-1.5 2022-10-25 02:00:01 -04:00
Tim Edwards 738abbdad9 Merge branch 'master' into netgen-1.5 2022-10-01 02:00:01 -04:00
Tim Edwards 8d7569e9a3 Merge branch 'master' into netgen-1.5 2022-09-24 02:00:02 -04:00
Tim Edwards d9425163e1 Merge branch 'master' into netgen-1.5 2022-09-18 02:00:02 -04:00
Tim Edwards 9ba1dfe814 Merge branch 'master' into netgen-1.5 2022-09-17 02:00:02 -04:00
Tim Edwards fadd0ae2fc Merge branch 'master' into netgen-1.5 2022-09-16 02:00:02 -04:00
Tim Edwards 153ce0e2b3 Merge branch 'master' into netgen-1.5 2022-09-14 02:00:02 -04:00
Tim Edwards bfdacab28c Merge branch 'master' into netgen-1.5 2022-09-13 02:00:02 -04:00
Tim Edwards 7e9bd9f2a0 Merge branch 'master' into netgen-1.5 2022-06-28 02:00:02 -04:00
Tim Edwards ee92d880d7 Merge branch 'master' into netgen-1.5 2022-06-27 02:00:01 -04:00
Tim Edwards d3407b3e56 Merge branch 'master' into netgen-1.5 2022-06-15 02:00:50 -04:00
Tim Edwards 0a94bec191 Merge branch 'master' into netgen-1.5 2022-06-13 02:00:18 -04:00
Tim Edwards 4a7b6bf22a Merge branch 'master' into netgen-1.5 2022-06-09 02:00:52 -04:00
Tim Edwards 661c9ee854 Merge branch 'master' into netgen-1.5 2022-04-16 02:00:16 -04:00
Tim Edwards 5b21c1be3a Merge branch 'master' into netgen-1.5 2022-04-15 02:00:16 -04:00
Tim Edwards e11dbac384 Merge branch 'master' into netgen-1.5 2022-01-17 03:00:14 -05:00
Tim Edwards 0535128421 Merge branch 'master' into netgen-1.5 2022-01-16 03:00:18 -05:00
Tim Edwards afe0e9f758 Merge branch 'master' into netgen-1.5 2022-01-01 03:00:43 -05:00
Tim Edwards e487890641 Merge branch 'master' into netgen-1.5 2021-12-31 03:00:42 -05:00
Tim Edwards bb44d3f827 Merge branch 'master' into netgen-1.5 2021-12-30 03:00:43 -05:00
Tim Edwards c25c4e1160 Merge branch 'master' into netgen-1.5 2021-12-27 03:00:18 -05:00
Tim Edwards 8ed4e3cf38 Merge branch 'master' into netgen-1.5 2021-12-20 03:00:02 -05:00
Tim Edwards 69838d79e4 Merge branch 'master' into netgen-1.5 2021-12-16 03:00:06 -05:00
Tim Edwards fc7c9371e8 Merge branch 'master' into netgen-1.5 2021-12-08 03:00:14 -05:00
Tim Edwards 0d19868145 Merge branch 'master' into netgen-1.5 2021-11-18 03:00:10 -05:00
Tim Edwards 6b4eb01ee8 Merge branch 'master' into netgen-1.5 2021-11-12 03:00:29 -05:00
Tim Edwards 737b2a73bf Merge branch 'master' into netgen-1.5 2021-10-30 03:00:02 -04:00
Tim Edwards 6b8c6d1718 Merge branch 'master' into netgen-1.5 2021-10-29 03:00:32 -04:00
Tim Edwards 610eebb758 Merge branch 'master' into netgen-1.5 2021-10-24 03:00:12 -04:00
Tim Edwards 97058c5017 Merge branch 'master' into netgen-1.5 2021-10-16 03:00:13 -04:00
Tim Edwards aa120460d0 Merge branch 'master' into netgen-1.5 2021-10-15 03:00:03 -04:00
Tim Edwards ea5cbacf1c Merge branch 'master' into netgen-1.5 2021-10-06 03:00:12 -04:00
Tim Edwards cdd768addc Merge branch 'master' into netgen-1.5 2021-09-08 03:00:04 -04:00
Tim Edwards 66cf2b82d9 Merge branch 'master' into netgen-1.5 2021-08-30 03:00:02 -04:00
Tim Edwards bc4192496b Merge branch 'master' into netgen-1.5 2021-08-28 13:15:58 -04:00
Tim Edwards 168e5502a1 Merge branch 'master' into netgen-1.5 2021-08-06 11:38:38 -04:00
Tim Edwards 8d4b621b7d Merge branch 'master' into netgen-1.5 2021-08-06 11:25:01 -04:00
Tim Edwards ba3e862552 Merge branch 'master' into netgen-1.5 2021-07-30 03:00:29 -04:00
Tim Edwards cf6dd2a638 Merge branch 'master' into netgen-1.5 2021-07-16 03:00:11 -04:00
Tim Edwards b6d896e73f Merge branch 'master' into netgen-1.5 2021-07-12 03:00:10 -04:00
Tim Edwards 9251ce2a48 Merge branch 'master' into netgen-1.5 2021-07-11 03:00:33 -04:00
Tim Edwards aa82164c08 Merge branch 'master' into netgen-1.5 2021-07-09 03:00:34 -04:00
Tim Edwards fb7876c7a6 Merge branch 'master' into netgen-1.5 2021-07-03 03:00:13 -04:00
Tim Edwards e31caa3500 Merge branch 'master' into netgen-1.5 2021-06-26 03:00:10 -04:00
Tim Edwards c1355bee45 Merge branch 'master' into netgen-1.5 2021-06-25 03:00:10 -04:00
Tim Edwards 4fb8b59a2f Merge branch 'master' into netgen-1.5 2021-06-19 03:00:10 -04:00
Tim Edwards 626faf22f9 Merge branch 'master' into netgen-1.5 2021-06-17 03:00:10 -04:00
Tim Edwards 550234dce5 Merge branch 'master' into netgen-1.5 2021-06-15 03:00:36 -04:00
Tim Edwards a4c0028706 Merge branch 'master' into netgen-1.5 2021-06-13 03:00:32 -04:00
Tim Edwards e7ae84bbc8 Merge branch 'master' into netgen-1.5 2021-06-10 03:00:09 -04:00
Tim Edwards 43c018f3bc Merge branch 'master' into netgen-1.5 2021-06-09 03:00:10 -04:00
Tim Edwards ca119edc0a Merge branch 'master' into netgen-1.5 2021-06-04 03:00:10 -04:00
Tim Edwards 84348d2fe1 Merge branch 'master' into netgen-1.5 2021-05-31 03:00:10 -04:00
Tim Edwards 813b29cdc4 Merge branch 'master' into netgen-1.5 2021-05-29 03:00:10 -04:00
Tim Edwards ccf4a0a900 Merge branch 'master' into netgen-1.5 2021-05-27 03:00:32 -04:00
Tim Edwards e34166fdb9 Merge branch 'master' into netgen-1.5 2021-05-26 03:00:32 -04:00
Tim Edwards a13491e358 Merge branch 'master' into netgen-1.5 2021-05-25 03:00:09 -04:00
Tim Edwards 1d05b8b676 Merge branch 'master' into netgen-1.5 2021-05-20 03:00:31 -04:00
Tim Edwards e97d6f1aeb Merge branch 'master' into netgen-1.5 2021-05-14 03:00:10 -04:00
Tim Edwards fb4759a8cd Merge branch 'master' into netgen-1.5 2021-05-04 03:00:10 -04:00
Tim Edwards 45d4004d43 Merge branch 'master' into netgen-1.5 2021-05-02 03:00:09 -04:00
Tim Edwards 0b014e6efd Merge branch 'master' into netgen-1.5 2021-03-20 03:00:09 -04:00
Tim Edwards 9ca713dfd9 Merge branch 'master' into netgen-1.5 2021-03-18 03:00:29 -04:00
Tim Edwards 851a1f941e Merge branch 'master' into netgen-1.5 2021-03-06 03:00:09 -05:00
Tim Edwards fb798d6ce7 Merge branch 'master' into netgen-1.5 2021-03-03 03:00:12 -05:00
Tim Edwards a888502038 Merge branch 'master' into netgen-1.5 2021-03-02 03:00:35 -05:00
Tim Edwards c16258d4d1 Merge branch 'master' into netgen-1.5 2021-02-25 03:00:36 -05:00
Tim Edwards 5341d7a5fd Merge branch 'master' into netgen-1.5 2021-02-17 03:00:31 -05:00
Tim Edwards 8395df633c Merge branch 'master' into netgen-1.5 2021-02-10 03:00:16 -05:00
Tim Edwards 6554063df3 Merge branch 'master' into netgen-1.5 2021-01-22 03:00:40 -05:00
Tim Edwards 4416a380b3 Merge branch 'master' into netgen-1.5 2021-01-18 03:00:51 -05:00
Tim Edwards 46394b2000 Merge branch 'master' into netgen-1.5 2021-01-17 03:00:15 -05:00
Tim Edwards 3fe3bc4cfa Merge branch 'master' into netgen-1.5 2021-01-09 03:00:32 -05:00
Tim Edwards 6661910672 Merge branch 'master' into netgen-1.5 2020-12-21 03:00:30 -05:00
Tim Edwards e7a36630f6 Merge branch 'master' into netgen-1.5 2020-12-16 03:00:54 -05:00
Tim Edwards f32b0b34a3 Merge branch 'master' into netgen-1.5 2020-12-06 03:00:10 -05:00
Tim Edwards 6b731ddd7a Merge branch 'master' into netgen-1.5 2020-12-04 03:00:27 -05:00
Tim Edwards 99e35d8b11 Merge branch 'master' into netgen-1.5 2020-10-09 03:00:25 -04:00
Tim Edwards 65b542f0ab Merge branch 'master' into netgen-1.5 2020-10-08 03:00:22 -04:00
Tim Edwards b826870be9 Merge branch 'master' into netgen-1.5 2020-08-09 03:01:40 -04:00
Tim Edwards ed5276d67b Merge branch 'master' into netgen-1.5 2020-08-04 03:00:31 -04:00
Tim Edwards 69c9d85be7 Merge branch 'master' into netgen-1.5 2020-08-01 03:00:23 -04:00
Tim Edwards ad05d059c7 Merge branch 'master' into netgen-1.5 2020-07-31 03:00:27 -04:00
Tim Edwards 1b2cd1497c Merge branch 'master' into netgen-1.5 2020-07-30 03:00:28 -04:00
Tim Edwards d9d5a46c6e Merge branch 'master' into netgen-1.5 2020-07-25 03:00:09 -04:00
Tim Edwards d73b711e3a Merge branch 'master' into netgen-1.5 2020-07-02 03:00:09 -04:00
Tim Edwards 1428580109 Merge branch 'master' into netgen-1.5 2020-06-17 03:00:38 -04:00
Tim Edwards 210dfb25c3 Merge branch 'master' into netgen-1.5 2020-06-04 03:00:24 -04:00
Tim Edwards 27f2ab8b3f Merge branch 'master' into netgen-1.5 2020-03-28 03:00:24 -04:00
Tim Edwards 1be00bbd99 Merge branch 'master' into netgen-1.5 2020-03-27 03:00:21 -04:00
Tim Edwards 03b241a5d4 Merge branch 'master' into netgen-1.5 2020-03-11 03:00:17 -04:00
Tim Edwards 43cebd1ef9 Merge branch 'master' into netgen-1.5 2020-03-06 03:00:39 -05:00
Tim Edwards 0490959b07 Merge branch 'master' into netgen-1.5 2020-03-05 03:00:09 -05:00
Tim Edwards dc841f3293 Merge branch 'master' into netgen-1.5 2020-02-24 17:35:04 -05:00
Tim Edwards 05bcfede69 Merge branch 'master' into netgen-1.5 2020-02-24 16:39:19 -05:00
Tim Edwards 72ed78e55a Update for change in ocd git script 2020-02-24 15:04:59 -05:00
Tim Edwards 59bb8a89c0 "ocd_git_pure automatic update to repo" 2020-02-24 15:04:27 -05:00
Tim Edwards 9bdaee652e "ocd_git_pure automatic update to repo" 2020-02-18 03:00:14 -05:00
Tim Edwards 9879b58f83 Merge branch 'master' into netgen-1.5 2020-02-18 03:00:13 -05:00
Tim Edwards 9e3b705fcc "ocd_git_pure automatic update to repo" 2020-02-11 03:00:09 -05:00
Tim Edwards d2c9129242 Merge branch 'master' into netgen-1.5 2020-02-11 03:00:09 -05:00
Tim Edwards 942f421fa3 "ocd_git_pure automatic update to repo" 2020-01-30 03:01:39 -05:00
Tim Edwards 6bc948d8ba Merge branch 'master' into netgen-1.5 2020-01-30 03:01:38 -05:00
Tim Edwards c1ad37f05a "ocd_git_pure automatic update to repo" 2020-01-14 03:00:47 -05:00
Tim Edwards 9edefe7d59 Merge branch 'master' into netgen-1.5 2020-01-14 03:00:47 -05:00
Tim Edwards f6b9629521 "ocd_git_pure automatic update to repo" 2019-11-20 03:00:33 -05:00
Tim Edwards 7b2e01f2af Merge branch 'master' into netgen-1.5 2019-11-20 03:00:33 -05:00
Tim Edwards 224050f153 "ocd_git_pure automatic update to repo" 2019-10-09 03:00:08 -04:00
Tim Edwards 74e8c3e168 Merge branch 'master' into netgen-1.5 2019-10-09 03:00:08 -04:00
Tim Edwards 95a29fcd8c "ocd_git_pure automatic update to repo" 2019-09-11 03:00:07 -04:00
Tim Edwards 723a950fd3 Merge branch 'master' into netgen-1.5 2019-09-11 03:00:07 -04:00
Tim Edwards e3368cb22a "ocd_git_pure automatic update to repo" 2019-09-10 03:00:08 -04:00
Tim Edwards f06e6548bb Merge branch 'master' into netgen-1.5 2019-09-10 03:00:08 -04:00
Tim Edwards 72ed19ff36 "ocd_git_pure automatic update to repo" 2019-09-09 03:00:10 -04:00
Tim Edwards 39b8e3d14a Merge branch 'master' into netgen-1.5 2019-09-09 03:00:10 -04:00
Tim Edwards b63dfa8638 "ocd_git_pure automatic update to repo" 2019-08-20 03:00:20 -04:00
Tim Edwards f918f33c51 Merge branch 'master' into netgen-1.5 2019-08-20 03:00:20 -04:00
Tim Edwards 63b2e48ea1 "ocd_git_pure automatic update to repo" 2019-08-13 03:00:08 -04:00
Tim Edwards 6e63f49d53 Merge branch 'master' into netgen-1.5 2019-08-13 03:00:07 -04:00
Tim Edwards 419b6de29a "ocd_git_pure automatic update to repo" 2019-08-11 03:00:07 -04:00
Tim Edwards 205cf2aa58 Merge branch 'master' into netgen-1.5 2019-08-11 03:00:07 -04:00
Tim Edwards 52b6766fc8 "ocd_git_pure automatic update to repo" 2019-08-04 03:00:20 -04:00
Tim Edwards 7b0bdd29e8 Merge branch 'master' into netgen-1.5 2019-08-04 03:00:20 -04:00
Tim Edwards 433cbd090a "ocd_git_pure automatic update to repo" 2019-07-25 03:00:16 -04:00
Tim Edwards 3087bd3337 Merge branch 'master' into netgen-1.5 2019-07-25 03:00:16 -04:00
Tim Edwards b79a29d662 "ocd_git_pure automatic update to repo" 2019-07-15 03:00:27 -04:00
Tim Edwards bf9c61e412 Merge branch 'master' into netgen-1.5 2019-07-15 03:00:27 -04:00
Tim Edwards 8d34bd372d "ocd_git_pure automatic update to repo" 2019-07-03 03:00:22 -04:00
Tim Edwards 229c2931a8 Merge branch 'master' into netgen-1.5 2019-07-03 03:00:22 -04:00
Tim Edwards b8da97deb1 "ocd_git_pure automatic update to repo" 2019-06-16 03:00:15 -04:00
Tim Edwards b7187d5899 Merge branch 'master' into netgen-1.5 2019-06-16 03:00:15 -04:00
Tim Edwards d27d441c58 "ocd_git_pure automatic update to repo" 2019-06-13 03:00:05 -04:00
Tim Edwards 48c9e6b292 Merge branch 'master' into netgen-1.5 2019-06-13 03:00:05 -04:00
Tim Edwards ced5846da3 "ocd_git_pure automatic update to repo" 2019-05-18 03:00:05 -04:00
Tim Edwards b99d33064f Merge branch 'master' into netgen-1.5 2019-05-18 03:00:04 -04:00
Tim Edwards 399472e940 "ocd_git_pure automatic update to repo" 2019-05-07 09:13:00 -04:00
24 changed files with 2658 additions and 4550 deletions

View File

@ -1 +1 @@
1.5.323 1.5.255

View File

@ -22,7 +22,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <strings.h>
#include <ctype.h> #include <ctype.h>
#ifdef IBMPC #ifdef IBMPC
#include <stdlib.h> /* for strtol on PC */ #include <stdlib.h> /* for strtol on PC */
@ -91,7 +90,7 @@ char *ActelName(char *Name)
/* strip physical-pin information, if it exists */ /* strip physical-pin information, if it exists */
if ((nm = strrchr(name,PHYSICALPIN[0])) != NULL) *nm = '\0'; if ((nm = strrchr(name,PHYSICALPIN[0])) != NULL) *nm = '\0';
if (strlen(name) > 13) { if (strlen(name) > 13) {
ActelIndex = (ActelIndex + 1) % ACTELNAMESIZE; ActelIndex = (++ActelIndex) % ACTELNAMESIZE;
/* format the value of the hashed value of the string */ /* format the value of the hashed value of the string */
sprintf(ActelNames[ActelIndex], "$%lX", ActelNameHash(name)); sprintf(ActelNames[ActelIndex], "$%lX", ActelNameHash(name));
if (Debug) if (Debug)
@ -102,7 +101,7 @@ Printf("ActelNameHash returns %s on name %s\n",ActelNames[ActelIndex], name);
NeedsQuoting = 0; NeedsQuoting = 0;
if (NULL != strpbrk(name, ".,:; \t\"'\n\r")) NeedsQuoting = 1; if (NULL != strpbrk(name, ".,:; \t\"'\n\r")) NeedsQuoting = 1;
ActelIndex = (ActelIndex + 1) % ACTELNAMESIZE; ActelIndex = (++ActelIndex) % ACTELNAMESIZE;
if (!NeedsQuoting) { if (!NeedsQuoting) {
strcpy(ActelNames[ActelIndex], name); strcpy(ActelNames[ActelIndex], name);
return(ActelNames[ActelIndex]); return(ActelNames[ActelIndex]);

View File

@ -31,8 +31,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "print.h" #include "print.h"
#include "hash.h" #include "hash.h"
static int invlambda = 100; /* Used in sim and prm files */
void extCell(char *name, int filenum) void extCell(char *name, int filenum)
{ {
struct nlist *tp, *tp2; struct nlist *tp, *tp2;
@ -452,8 +450,7 @@ void simCell(char *name, int filenum)
struct nlist *tp, *tp2; struct nlist *tp, *tp2;
struct objlist *ob, *ob2; struct objlist *ob, *ob2;
char FileName[500], simclass; char FileName[500], simclass;
char writeLine[1024], paramString[128]; short i;
short i, p, mult;
double l, w, v; double l, w, v;
tp = LookupCellFile(name, filenum); tp = LookupCellFile(name, filenum);
@ -481,9 +478,9 @@ void simCell(char *name, int filenum)
} }
/* print out header list */ /* print out header list */
/* distance units are multiplied by invlambda */ /* distance units are multiplied by 100 (distances are in um) */
FlushString("| units: %d tech: scmos\n", 100 * invlambda); FlushString("| units: 100 tech: scmos\n");
/* now run through cell's contents, print instances */ /* now run through cell's contents, print instances */
for (ob = tp->cell; ob != NULL; ob = ob->next) { for (ob = tp->cell; ob != NULL; ob = ob->next) {
@ -519,12 +516,8 @@ void simCell(char *name, int filenum)
case CLASS_NPN: case CLASS_NPN:
simclass = 'b'; simclass = 'b';
break; break;
case CLASS_SUBCKT:
case CLASS_MODULE:
simclass = 'x';
break;
default: default:
simclass = '|'; simclass = 'x';
break; break;
} }
@ -597,115 +590,6 @@ void simCell(char *name, int filenum)
FlushString(" %g\n", v); FlushString(" %g\n", v);
break; break;
case CLASS_MODULE:
*writeLine = 'x';
*(writeLine + 1) = '\0';
mult = 1;
/* Important---Need to look up the cell definition; if
* the first pin is "drain" then it is a FET, and pins
* get swapped from D-G-S-B to G-S-D-B. Source and drain
* are treated here as equivalent because the .sim format
* has no concept of an asymmetric source and drain.
*/
ob2 = tp2->cell;
if ((*matchfunc)(ob2->next->name, "gate"))
{
strcat(writeLine, " ");
strcat(writeLine, NodeAlias(tp, ob->next));
strcat(writeLine, " ");
strcat(writeLine, NodeAlias(tp, ob));
ob2 = ob->next->next;
}
else
ob2 = ob;
while (ob2 != NULL) {
strcat(writeLine, " ");
strcat(writeLine, NodeAlias(tp, ob2));
ob2 = ob2->next;
if ((ob2 == NULL) || (ob2->type <= FIRSTPIN)) break;
}
if (ob2 && ob2->type == PROPERTY) {
struct valuelist *vl;
/* Only known parameters are L, W, X, and Y */
for (p = 0;; p++) {
vl = (struct valuelist *)(&(ob2->instance.props[p]));
if (vl->type == PROP_ENDLIST) {
strcat(writeLine, " l=1");
break;
}
else if ((*matchfunc)(vl->key, "L")) {
v = vl->value.dval;
sprintf(paramString, " l=%d", (int)(0.5 + (v * invlambda)));
strcat(writeLine, paramString);
break;
}
}
for (p = 0;; p++) {
vl = (struct valuelist *)(&(ob2->instance.props[p]));
if (vl->type == PROP_ENDLIST) {
strcat(writeLine, " w=1");
break;
}
else if ((*matchfunc)(vl->key, "W")) {
v = vl->value.dval;
sprintf(paramString, " w=%d", (int)(0.5 + (v * invlambda)));
strcat(writeLine, paramString);
break;
}
}
for (p = 0;; p++) {
vl = (struct valuelist *)(&(ob2->instance.props[p]));
if (vl->type == PROP_ENDLIST) {
strcat(writeLine, " x=0");
break;
}
else if ((*matchfunc)(vl->key, "X")) {
i = vl->value.ival;
sprintf(paramString, " x=%d", i);
strcat(writeLine, paramString);
break;
}
}
for (p = 0;; p++) {
vl = (struct valuelist *)(&(ob2->instance.props[p]));
if (vl->type == PROP_ENDLIST) {
strcat(writeLine, " y=0");
break;
}
else if ((*matchfunc)(vl->key, "Y")) {
i = vl->value.ival;
sprintf(paramString, " y=%d", i);
strcat(writeLine, paramString);
}
}
for (p = 0;; p++) {
vl = (struct valuelist *)(&(ob2->instance.props[p]));
if (vl->type == PROP_ENDLIST) {
break;
}
else if ((*matchfunc)(vl->key, "M")) {
if (vl->type == PROP_INTEGER)
mult = vl->value.ival;
else
mult = vl->value.dval;
}
}
}
strcat(writeLine, " ");
strcat(writeLine, tp2->name);
strcat(writeLine, "\n");
/* Multiple instances (M != 1) are written multiple times.
* NF is ignored in favor of having a single device with
* the total width.
*/
for (i = 0; i < mult; i++)
FlushString(writeLine);
break;
default: default:
FlushString("| unhandled component %s\n", tp2->name); FlushString("| unhandled component %s\n", tp2->name);
break; break;
@ -742,181 +626,6 @@ int StrIsInt(char *s)
return (1); return (1);
} }
/*------------------------------------------------------*/
/* Read a .prm format file. This is specifically to */
/* get the "device" lines that indicate how a SPICE */
/* subcircuit model or a .sim "x" record needs to be */
/* translated into a specific component type like a */
/* FET, diode, resistor, etc. */
/*------------------------------------------------------*/
char *ReadPrm(char *fname, int *fnum)
{
int filenum;
struct keyvalue *kvlist = NULL;
struct nlist *tp;
if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
char name[MAX_STR_LEN];
SetExtension(name, fname, PRM_EXTENSION);
if (OpenParseFile(name, *fnum) < 0) {
Printf("Error in prm file read: No file %s\n",name);
*fnum = filenum;
return NULL;
}
}
/* Make sure all .prm file reading is case INsensitive */
/* This is because the only reason to read a PRM file */
/* is to find all the subcircuit device types so that */
/* a SPICE file can be read and a SIM file written. */
matchfunc = matchnocase;
matchintfunc = matchfile;
hashfunc = hashnocase;
CellDef(fname, filenum);
while (!EndParseFile()) {
char devicename[MAX_STR_LEN];
SkipTok(NULL);
if (EndParseFile()) break;
if (nexttok[0] == ';') continue; /* Comment line */
else if (nexttok[0] == '\0') continue; /* Blank line */
else if (match(nexttok, "lambda")) {
SkipTok(NULL);
invlambda = (int)(0.5 + (1.0 / atof(nexttok)));
SkipNewLine(NULL); /* skip any attributes */
}
else if (match(nexttok, "device")) {
SkipTok(NULL);
if (match(nexttok, "nfet")) {
SkipTok(NULL);
strcpy(devicename, nexttok);
/* Create 4-terminal nfet subcircuit device record */
if (LookupCellFile(devicename, filenum) == NULL) {
CellDef(devicename, filenum);
Port("drain");
Port("gate");
Port("source");
Port("bulk");
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
PropertyInteger(devicename, filenum, "nf", 0, 1);
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum);
}
LinkProperties(devicename, kvlist);
SkipNewLine(NULL); /* skip any attributes */
}
else if (match(nexttok, "pfet")) {
SkipTok(NULL);
strcpy(devicename, nexttok);
/* Create 4-terminal pfet subcircuit device record */
if (LookupCellFile(devicename, filenum) == NULL) {
CellDef(devicename, filenum);
Port("drain");
Port("gate");
Port("source");
Port("well");
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
PropertyInteger(devicename, filenum, "nf", 0, 1);
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum);
}
LinkProperties(devicename, kvlist);
SkipNewLine(NULL); /* skip various attributes */
}
else if (match(nexttok, "resistor")) {
SkipTok(NULL);
strcpy(devicename, nexttok);
/* Resistor device has additional record for the value */
/* (Need to do something with this. . . ?) */
SkipTok(NULL);
/* Create resistor subcircuit device record */
if (LookupCellFile(devicename, filenum) == NULL) {
CellDef(devicename, filenum);
Port("end_a");
Port("end_b");
PropertyDouble(devicename, filenum, "value", 0.01, 0.0);
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum);
}
LinkProperties(devicename, kvlist);
SkipNewLine(NULL); /* skip various attributes */
}
else if (match(nexttok, "capacitor")) {
SkipTok(NULL);
strcpy(devicename, nexttok);
/* Capacitor device has additional record for the value */
/* (Need to do something with this. . . ?) */
SkipTok(NULL);
/* Create capacitor subcircuit device record */
if (LookupCellFile(devicename, filenum) == NULL) {
CellDef(devicename, filenum);
Port("top");
Port("bottom");
PropertyDouble(devicename, filenum, "value", 0.01, 0.0);
PropertyDouble(devicename, filenum, "l", 0.01, 0.0);
PropertyDouble(devicename, filenum, "w", 0.01, 0.0);
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum); /* Reopen */
}
LinkProperties(devicename, kvlist);
SkipNewLine(NULL);
}
else if (match(nexttok, "diode")) {
SkipTok(NULL);
strcpy(devicename, nexttok);
/* Create diode subcircuit device record */
if (LookupCellFile(devicename, filenum) == NULL) {
CellDef(devicename, filenum);
Port("anode");
Port("cathode");
PropertyInteger(devicename, filenum, "m", 0, 1);
SetClass(CLASS_MODULE);
EndCell();
ReopenCellDef(fname, filenum); /* Reopen */
}
LinkProperties(devicename, kvlist);
SkipNewLine(NULL);
}
else {
Printf("Unknown device type in .prm: '%s'\n", nexttok);
InputParseError(stderr);
SkipNewLine(NULL);
}
}
else {
/* Could spell out all the keywords used in .prm files */
/* but probably not worth the effort. */
SkipNewLine(NULL);
}
DeleteProperties(&kvlist);
}
EndCell();
CloseParseFile();
tp = LookupCellFile(fname, filenum);
if (tp) tp->flags |= CELL_TOP;
*fnum = filenum;
return fname;
}
/*-------------------------*/ /*-------------------------*/
/* Read a .sim format file */ /* Read a .sim format file */
/*-------------------------*/ /*-------------------------*/
@ -935,7 +644,7 @@ char *ReadSim(char *fname, int *fnum)
SetExtension(name, fname, SIM_EXTENSION); SetExtension(name, fname, SIM_EXTENSION);
if (OpenParseFile(name, *fnum) < 0) { if (OpenParseFile(name, *fnum) < 0) {
Printf("Error in sim file read: No file %s\n",name); Printf("Error in ext file read: No file %s\n",name);
*fnum = filenum; *fnum = filenum;
return NULL; return NULL;
} }
@ -1138,7 +847,7 @@ char *ReadSim(char *fname, int *fnum)
} }
else if (match(nexttok, "r")) { /* 2-port resistors */ else if (match(nexttok, "r")) { /* 2-port resistors */
if (IgnoreRC) { if (IgnoreRC) {
/* ignore all resistances */ /* ignore all capacitances */
SkipNewLine(NULL); SkipNewLine(NULL);
} }
else { else {

View File

@ -136,16 +136,17 @@ void flattenCell(char *name, int file)
ob2 = ob2->next; ob2 = ob2->next;
} }
/* delete all port elements from child */ /* delete all port elements from child */
while (IsPort(ChildObjList)) { while (IsPort(ChildObjList)) {
/* delete all ports at beginning of list */ /* delete all ports at beginning of list */
if (Debug) Printf("deleting leading port from child\n"); if (Debug) Printf("deleting leading port from child\n");
tmp = ChildObjList->next; tmp = ChildObjList->next;
FreeObjectAndHash(ChildObjList, ChildCell); FreeObjectAndHash(ChildObjList, ChildCell);
if ((ChildObjList = tmp) == NULL) break; ChildObjList = tmp;
} }
tmp = ChildObjList; tmp = ChildObjList;
while (tmp && (tmp->next != NULL)) { while (tmp->next != NULL) {
if (IsPort(tmp->next)) { if (IsPort(tmp->next)) {
ob2 = (tmp->next)->next; ob2 = (tmp->next)->next;
if (Debug) Printf("deleting a port from child\n"); if (Debug) Printf("deleting a port from child\n");
@ -300,6 +301,8 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
return 0; return 0;
} }
} }
/* Placeholder cells must not be flattened */
if (ThisCell->flags & CELL_PLACEHOLDER) return 0;
FreeNodeNames(ThisCell); FreeNodeNames(ThisCell);
@ -337,10 +340,6 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
LastObj = ParentParams; LastObj = ParentParams;
continue; continue;
} }
if (ChildCell->flags & CELL_PLACEHOLDER) {
LastObj = ParentParams;
continue; // Placeholder cells must not be flattened
}
if (ChildCell == ThisCell) { if (ChildCell == ThisCell) {
LastObj = ParentParams; LastObj = ParentParams;
continue; // Avoid infinite loop continue; // Avoid infinite loop
@ -602,11 +601,9 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
else break; else break;
/* Put the child cell at the start of ChildObjList */ /* Put the child cell at the start of ChildObjList */
if (ChildEnd) {
ChildEnd->next = ChildObjList; ChildEnd->next = ChildObjList;
ChildObjList = ChildStart; ChildObjList = ChildStart;
} }
}
/* Put the child cell at the start of ChildObjList */ /* Put the child cell at the start of ChildObjList */
if (ChildEnd) { if (ChildEnd) {
@ -1218,6 +1215,7 @@ int UniquePins(char *name, int filenum)
firstport = (struct objlist **)CALLOC(maxnode + 1, sizeof(struct objlist *)); firstport = (struct objlist **)CALLOC(maxnode + 1, sizeof(struct objlist *));
portcount = FIRSTPIN; portcount = FIRSTPIN;
lob = NULL;
for (ob = ThisCell->cell; ob != NULL; ob = ob->next) { for (ob = ThisCell->cell; ob != NULL; ob = ob->next) {
if (ob->type != PORT) break; if (ob->type != PORT) break;
if (ob->node > 0) { if (ob->node > 0) {
@ -1228,16 +1226,16 @@ int UniquePins(char *name, int filenum)
firstport[ob->node]->name, ThisCell->name, ThisCell->file); firstport[ob->node]->name, ThisCell->name, ThisCell->file);
/* Do not count this as a duplicate pin. */ /* Do not count this as a duplicate pin. */
nodecount[ob->node]--; nodecount[ob->node]--;
/* Note: Previously there was code here to move the shorted port /* Move the pin adjacent to the one it is shorted to (if it
* next to the pin it is shorted to. This causes the cell def pins * isn't already); this will make the work of MatchPins() easier.
* to become scrambled with respect to the pin order of its instances.
* Removed the code 9/1/2023. But---Not sure if any code depends
* on shorted pins being adjacent.
*/ */
/* When two pins are shorted, they are by definition permutable */ if (firstport[ob->node]->next != ob) {
PermuteSetup(ThisCell->name, ThisCell->file, ob->name, lob->next = ob->next;
firstport[ob->node]->name); ob->next = firstport[ob->node]->next;
firstport[ob->node]->next = ob;
ob = lob;
}
lob = ob;
continue; continue;
} }
else { else {
@ -1258,6 +1256,7 @@ int UniquePins(char *name, int filenum)
} }
} }
portcount++; portcount++;
lob = ob;
} }
if (needscleanup) if (needscleanup)
@ -1308,14 +1307,6 @@ int UniquePins(char *name, int filenum)
return 1; return 1;
} }
/* Structure used below for keeping track of node numbers
* belonging to removed nodes.
*/
struct LinkedNum {
int node;
struct LinkedNum *next;
};
/*------------------------------------------------------*/ /*------------------------------------------------------*/
/* Callback function for CleanupPins */ /* Callback function for CleanupPins */
/* Note that if the first pin of the instance is a */ /* Note that if the first pin of the instance is a */
@ -1328,7 +1319,6 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
struct nlist *ptr; struct nlist *ptr;
struct objlist *ob, *obt, *lob, *nob, *firstpin, *pob; struct objlist *ob, *obt, *lob, *nob, *firstpin, *pob;
struct nlist *tc = (struct nlist *)clientdata; struct nlist *tc = (struct nlist *)clientdata;
struct LinkedNum *newnodenum, *removedNodes = (struct LinkedNum *)NULL;
int pinnum; int pinnum;
char *saveinst = NULL; char *saveinst = NULL;
@ -1384,15 +1374,6 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
saveinst = ob->instance.name; saveinst = ob->instance.name;
} }
if (ob->model.class != NULL) FREE(ob->model.class); if (ob->model.class != NULL) FREE(ob->model.class);
// Record the net number of the pin being removed, to
// check at the end if the net belonged to a pin that
// got orphaned.
newnodenum = (struct LinkedNum *)MALLOC(sizeof(struct LinkedNum));
newnodenum->node = ob->node;
newnodenum->next = removedNodes;
removedNodes = newnodenum;
FREE(ob); FREE(ob);
} }
else { else {
@ -1436,28 +1417,6 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
} }
} }
while (removedNodes != NULL) {
int nodenum = removedNodes->node;
struct objlist *ob2;
/* Only concerned with nodes that are in the pin list of ptr->cell */
for (ob = ptr->cell; ob != NULL; ob = ob->next) {
if (ob->type != PORT) break;
if (ob->node == nodenum) break;
}
if (ob && (ob->type == PORT)) {
/* Check if this node number exists only in the port record */
for (nob = ob->next; nob != NULL; nob = nob->next)
if (nob->node == nodenum) break;
if (nob == NULL) {
ob->node = -1; /* This pin is now disconnected */
}
}
newnodenum = removedNodes;
removedNodes = removedNodes->next;
FREE(newnodenum);
}
if (saveinst != NULL) FREE(saveinst); if (saveinst != NULL) FREE(saveinst);
return NULL; /* Keep the search going */ return NULL; /* Keep the search going */
} }
@ -1678,8 +1637,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
ECompare *ecomp, *ncomp; ECompare *ecomp, *ncomp;
ECompList *list0X, *listX0; ECompList *list0X, *listX0;
int hascontents1, hascontents2; int hascontents1, hascontents2;
int match, modified1 = 0, modified2 = 0; int match, modified = 0;
int not_top;
if (file1 == -1) if (file1 == -1)
tc1 = LookupCell(name1); tc1 = LookupCell(name1);
@ -1755,26 +1713,16 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)" Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell1->name, " makes a better match\n", ecomp->cell1->name,
name1, file1); name1, file1);
if (flattenInstancesOf(name1, file1, ecomp->cell1->name) > 0) flattenInstancesOf(name1, file1, ecomp->cell1->name);
modified1++; modified++;
}
else if (ecomp->cell1 && (ecomp->num1 > 0)) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" would make a better match but is prohibited.\n",
ecomp->cell1->name, name1, file1);
} }
if (ecomp->cell2 && (ecomp->num2 > 0) && if (ecomp->cell2 && (ecomp->num2 > 0) &&
(!(ecomp->cell2->flags & CELL_PLACEHOLDER))) { (!(ecomp->cell2->flags & CELL_PLACEHOLDER))) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)" Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell2->name, " makes a better match\n", ecomp->cell2->name,
name2, file2); name2, file2);
if (flattenInstancesOf(name2, file2, ecomp->cell2->name) > 0) flattenInstancesOf(name2, file2, ecomp->cell2->name);
modified2++; modified++;
}
else if (ecomp->cell2 && (ecomp->num2 > 0)) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" would make a better match but is prohibited.\n",
ecomp->cell2->name, name2, file2);
} }
} }
@ -1863,13 +1811,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)" Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell2->name, " makes a better match\n", ecomp->cell2->name,
name2, file2); name2, file2);
if (flattenInstancesOf(name2, file2, ecomp->cell2->name) > 0) flattenInstancesOf(name2, file2, ecomp->cell2->name);
modified2++; modified++;
}
else if (ecomp->cell2) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" would make a better match but is prohibited.\n",
ecomp->cell2->name, name2, file2);
} }
} }
} }
@ -1934,13 +1877,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)" Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell1->name, " makes a better match\n", ecomp->cell1->name,
name1, file1); name1, file1);
if (flattenInstancesOf(name1, file1, ecomp->cell1->name) > 0) flattenInstancesOf(name1, file1, ecomp->cell1->name);
modified1++; modified++;
}
else if (ecomp->cell1) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" would make a better match but is prohibited.\n",
ecomp->cell1->name, name1, file1);
} }
} }
} }
@ -1970,8 +1908,6 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
// Remove non-matching zero-value devices. This can // Remove non-matching zero-value devices. This can
// be done on a per-instance basis. // be done on a per-instance basis.
not_top = (PeekCompareQueueTop(NULL, NULL, NULL, NULL) == -1) ? FALSE : TRUE;
ecomp = (ECompare *)HashFirst(&compdict); ecomp = (ECompare *)HashFirst(&compdict);
while (ecomp != NULL) { while (ecomp != NULL) {
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) && if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
@ -2020,44 +1956,6 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
} }
if (found) break; if (found) break;
} }
if (found) {
/* Beware remove shorting devices that */
/* connect two ports. Otherwise the */
/* port lists get screwed up. It is */
/* better in that case to force the */
/* cells to be declared mismatched. */
/* This is ignored for a top-level cell */
/* because it will just show up as a */
/* port mismatch error as it should. */
/* (12/12/2025---disabling this worked; */
/* may need to go back to a failing */
/* example and determine how pin */
/* matching gets scrambled.) */
if ((not_top == TRUE) &&
(ecomp->cell1->class != CLASS_ISOURCE)) {
int found1 = FALSE;
int found2 = FALSE;
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
if (!IsPort(ob2)) break;
else if (ob2->node == node1)
found1 = TRUE;
else if (ob2->node == node2)
found2 = TRUE;
if (found1 && found2) {
Fprintf(stdout, "Warning: "
"zero-valued device connects "
"port %s to another port; pin "
"matching may be affected.\n",
ob2->name);
// found = FALSE;
break;
}
}
}
}
if (found) { if (found) {
Fprintf(stdout, "Removing zero-valued device " Fprintf(stdout, "Removing zero-valued device "
"%s from cell %s (%d) makes a better " "%s from cell %s (%d) makes a better "
@ -2105,7 +2003,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
/* Remove from list */ /* Remove from list */
ecomp->num1--; ecomp->num1--;
modified1++; modified++;
ob1 = lob; ob1 = lob;
} }
@ -2177,27 +2075,6 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
break; break;
} }
} }
/* (See comments above about removing shorts */
/* between two ports.) */
if ((not_top == TRUE) &&
(ecomp->cell2->class != CLASS_ISOURCE)) {
int found1 = FALSE;
int found2 = FALSE;
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
if (!IsPort(ob1)) break;
else if (ob1->node == node1)
found1 = TRUE;
else if (ob1->node == node2)
found2 = TRUE;
if (found1 && found2) {
found = FALSE;
break;
}
}
}
if (found) break; if (found) break;
} }
if (found) { if (found) {
@ -2243,8 +2120,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
} }
/* Remove from list */ /* Remove from list */
ecomp->num2--; ecomp->num1--;
modified2++; modified++;
ob2 = lob; ob2 = lob;
} }
@ -2278,7 +2155,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
// are no other modifications, as this rule is relaxed compared to other // are no other modifications, as this rule is relaxed compared to other
// rules, and the other rules should be exhaustively applied first. // rules, and the other rules should be exhaustively applied first.
if ((listX0 != NULL) && (list0X != NULL) && ((modified1 + modified2) == 0)) { if ((listX0 != NULL) && (list0X != NULL) && (modified == 0)) {
ECompare *ecomp0X, *ecompX0; ECompare *ecomp0X, *ecompX0;
ECompList *elist0X, *elistX0; ECompList *elist0X, *elistX0;
for (elistX0 = listX0; elistX0; elistX0 = elistX0->next) { for (elistX0 = listX0; elistX0; elistX0 = elistX0->next) {
@ -2304,24 +2181,13 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
ecompX0->cell1->file, &compdict); ecompX0->cell1->file, &compdict);
if (dstr) *dstr = '['; if (dstr) *dstr = '[';
if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) { if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) {
if (!(ecompX0->cell1->flags & CELL_PLACEHOLDER)) { Fprintf(stdout, "Flattening instances of %s in cell %s"
Fprintf(stdout, "Flattening instances of %s in cell" "(%d) makes a better match\n",
" %s (%d) makes a better match\n",
ecompX0->cell1->name, name1, file1); ecompX0->cell1->name, name1, file1);
if (flattenInstancesOf(name1, file1, flattenInstancesOf(name1, file1, ecompX0->cell1->name);
ecompX0->cell1->name) > 0) {
ecompX0->num1 = 0; ecompX0->num1 = 0;
ecomp0X->num1 += ecompX0->num1; ecomp0X->num1 += ecompX0->num1;
modified1++; modified++;
}
}
else
{
Fprintf(stdout, "Flattening instances of %s in "
"cell %s (%d) would make a better "
"match but is prohibited.\n",
ecompX0->cell1->name, name1, file1);
}
break; break;
} }
} }
@ -2341,23 +2207,13 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
ecomp0X->cell2->file, &compdict); ecomp0X->cell2->file, &compdict);
if (dstr) *dstr = '['; if (dstr) *dstr = '[';
if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) { if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) {
if (!(ecomp0X->cell2->flags & CELL_PLACEHOLDER)) { Fprintf(stdout, "Flattening instances of %s in cell %s"
Fprintf(stdout, "Flattening instances of %s in cell" " (%d) makes a better match\n",
" %s (%d) makes a better match\n",
ecomp0X->cell2->name, name2, file2); ecomp0X->cell2->name, name2, file2);
if (flattenInstancesOf(name2, file2, flattenInstancesOf(name2, file2, ecomp0X->cell2->name);
ecomp0X->cell2->name) > 0) {
ecomp0X->num2 = 0; ecomp0X->num2 = 0;
ecompX0->num2 += ecomp0X->num2; ecompX0->num2 += ecomp0X->num2;
modified2++; modified++;
}
}
else {
Fprintf(stdout, "Flattening instances of %s in "
"cell %s (%d) would make a better "
"match but is prohibited.\n",
ecompX0->cell2->name, name2, file2);
}
break; break;
} }
} }
@ -2388,17 +2244,5 @@ done:
FREE(list0X); FREE(list0X);
list0X = nextptr; list0X = nextptr;
} }
return modified;
// If either netlist was modified, rebuild its node cache
if (modified1 > 0) {
FreeNodeNames(tc1);
CacheNodeNames(tc1);
}
if (modified2 > 0) {
FreeNodeNames(tc2);
CacheNodeNames(tc2);
}
return modified1 + modified2;
} }

View File

@ -137,39 +137,32 @@ static unsigned char uppercase[] = {
// horrible things can happen, as, for example, names AOI12 and OAI12 // horrible things can happen, as, for example, names AOI12 and OAI12
// have exactly the same hash result. Lousy for binning and even // have exactly the same hash result. Lousy for binning and even
// lousier for generating class magic numbers. // lousier for generating class magic numbers.
//
// Updated again 4/2/2026 to the FNV-1a hash, which is better than
// SDBM for this application, according to ChatGPT.
unsigned long hashnocase(char *s, int hashsize) unsigned long hashnocase(char *s, int hashsize)
{ {
unsigned long hashval = 2166136261ul; unsigned long hashval;
for (; *s != '\0'; s++) {
hashval ^= uppercase[*s]; for (hashval = 0; *s != '\0'; )
hashval *= 16777619ul; hashval = uppercase[*s++]
} + (hashval << 6) + (hashval << 16) - hashval;
return (hashsize == 0) ? hashval : (hashval % hashsize); return (hashsize == 0) ? hashval : (hashval % hashsize);
} }
unsigned long hashcase(char *s, int hashsize) unsigned long hashcase(char *s, int hashsize)
{ {
unsigned long hashval = 2166136261ul; unsigned long hashval;
for (; *s != '\0'; s++) {
hashval ^= (unsigned char)(*s); for (hashval = 0; *s != '\0'; )
hashval *= 16777619ul; hashval = (*s++) + (hashval << 6) + (hashval << 16) - hashval;
}
return (hashsize == 0) ? hashval : (hashval % hashsize); return (hashsize == 0) ? hashval : (hashval % hashsize);
} }
unsigned long genhash(char *s, int c, int hashsize) unsigned long genhash(char *s, int c, int hashsize)
{ {
unsigned long hashval = 2166136261ul; unsigned long hashval;
hashval ^= (unsigned long)c;
hashval *= 16777619ul; for (hashval = (unsigned long)c; *s != '\0'; )
for (; *s != '\0'; s++) { hashval = (*s++) + (hashval << 6) + (hashval << 16) - hashval;
hashval ^= (unsigned char)(*s);
hashval *= 16777619ul;
}
return (hashsize == 0) ? hashval : (hashval % hashsize); return (hashsize == 0) ? hashval : (hashval % hashsize);
} }

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,7 @@ extern void RegroupDataStructures();
extern void FormatIllegalElementClasses(); extern void FormatIllegalElementClasses();
extern void FormatIllegalNodeClasses(); extern void FormatIllegalNodeClasses();
extern int ResolveAutomorphsByProperty(); extern int ResolveAutomorphsByProperty();
extern int ResolveAutomorphsByPin(int match_nets); extern int ResolveAutomorphsByPin();
extern void SummarizeElementClasses(struct ElementClass *EC); extern void SummarizeElementClasses(struct ElementClass *EC);
extern int remove_group_tags(struct objlist *ob); extern int remove_group_tags(struct objlist *ob);
@ -70,8 +70,6 @@ extern int remove_group_tags(struct objlist *ob);
#ifdef TCL_NETGEN #ifdef TCL_NETGEN
extern int EquivalentNode(); extern int EquivalentNode();
extern int EquivalentElement(); extern int EquivalentElement();
extern void DeriveAreaProperty();
extern void DerivePerimeterProperty();
extern void enable_interrupt(); extern void enable_interrupt();
extern void disable_interrupt(); extern void disable_interrupt();

View File

@ -302,7 +302,7 @@ int GetNextLineNoNewline(char *delimiter)
{ {
char *newbuf; char *newbuf;
int testc; int testc;
static int nested = 0; int nested = 0;
int llen; int llen;
if (feof(infile)) return -1; if (feof(infile)) return -1;
@ -329,11 +329,6 @@ int GetNextLineNoNewline(char *delimiter)
llen = strlen(line); llen = strlen(line);
} }
while (llen == linesize - 1) { while (llen == linesize - 1) {
/* Note that in the rare case where a newline is in the last buffer
* position, we're done.
*/
if (*(line + llen - 1) == '\n') break;
newbuf = (char *)MALLOC(linesize + 501); newbuf = (char *)MALLOC(linesize + 501);
strcpy(newbuf, line); strcpy(newbuf, line);
FREE(line); FREE(line);
@ -592,31 +587,19 @@ void SkipTokNoNewline(char *delimiter)
/* */ /* */
/* Modified 3/30/2015 to include the condition where a comment line is */ /* Modified 3/30/2015 to include the condition where a comment line is */
/* in the middle of a series of continuation lines. */ /* in the middle of a series of continuation lines. */
/* */
/* Modified 1/3/2024 to avoid skipping two lines if a line has only the */
/* comment character '*' followed by a newline. It seems that '\n' is */
/* being ignored in WHITESPACE_DELIMITER, but it's easier to write the */
/* code to find the exception rather than track down the problem in */
/* GetNextLine(). */
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
void SpiceTokNoNewline(void) void SpiceTokNoNewline(void)
{ {
int contline; int contline;
if ((nexttok = strdtok0(NULL, WHITESPACE_DELIMITER, NULL, FALSE)) != NULL) return; if ((nexttok = strdtok(NULL, WHITESPACE_DELIMITER, NULL)) != NULL) return;
while (nexttok == NULL) { while (nexttok == NULL) {
contline = getc(infile); contline = getc(infile);
if (contline == '*') { if (contline == '*') {
char testline = ' ';
while ((testline == ' ') || (testline == '\t'))
testline = getc(infile);
if (testline != '\n') {
ungetc(testline, infile);
GetNextLine(WHITESPACE_DELIMITER); GetNextLine(WHITESPACE_DELIMITER);
SkipNewLine(NULL); SkipNewLine(NULL);
}
continue; continue;
} }
else if (contline != '+') { else if (contline != '+') {
@ -628,8 +611,7 @@ void SpiceTokNoNewline(void)
} }
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
/* Skip to the next token, ignoring any C-style comments and verilog */ /* Skip to the next token, ignoring any C-style comments. */
/* "(* ... *)"-style comments. */
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
void SkipTokComments(char *delimiter) void SkipTokComments(char *delimiter)
@ -645,11 +627,6 @@ void SkipTokComments(char *delimiter)
SkipTok(delimiter); SkipTok(delimiter);
if (nexttok) SkipTok(delimiter); if (nexttok) SkipTok(delimiter);
} }
else if (match(nexttok, "(*")) {
while (nexttok && !match(nexttok, "*)"))
SkipTok(delimiter);
if (nexttok) SkipTok(delimiter);
}
else break; else break;
} }
} }
@ -685,7 +662,6 @@ void SpiceSkipNewLine(void)
ungetc(contline, infile); ungetc(contline, infile);
} }
#if 0 /* Commented with "#if 0" due to comment characters in the comment */
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
/* Function similar to strtok() for token parsing. The difference is */ /* Function similar to strtok() for token parsing. The difference is */
/* that it takes two sets of delimiters. The first is whitespace */ /* that it takes two sets of delimiters. The first is whitespace */
@ -706,9 +682,8 @@ void SpiceSkipNewLine(void)
/* the first character of the delimiter string in addition to marking */ /* the first character of the delimiter string in addition to marking */
/* the boundary between two-character and one-character delimiters. */ /* the boundary between two-character and one-character delimiters. */
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
#endif
char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog) char *strdtok(char *pstring, char *delim1, char *delim2)
{ {
static char *stoken = NULL; static char *stoken = NULL;
static char *sstring = NULL; static char *sstring = NULL;
@ -753,10 +728,10 @@ char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog)
/* should know whether it is parsing SPICE or verilog and handle the syntax */ /* should know whether it is parsing SPICE or verilog and handle the syntax */
/* accordingly (needs to be done). */ /* accordingly (needs to be done). */
if (isverilog && (*s == '\\')) { if (*s == '\\') {
s++; s++;
while (*s != '\0') { while (*s != '\0') {
if ((*s == ' ') || ((*s == '\\') && (*(s + 1) == '\0'))) { if ((*s == ' ') || (*s == '\\')) {
s++; s++;
break; break;
} }
@ -824,17 +799,6 @@ char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog)
return sstring; return sstring;
} }
/*----------------------------------------------------------------------*/
/* strdtok() is the original string tokenizer. It calls strdtok0() */
/* with isverilog=TRUE, so that tokens are parsed as (potentially) */
/* verilog names, which includes verilog backslash notation. */
/*----------------------------------------------------------------------*/
char *strdtok(char *pstring, char *delim1, char *delim2)
{
return strdtok0(pstring, delim1, delim2, TRUE);
}
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
void InputParseError(FILE *f) void InputParseError(FILE *f)
@ -916,7 +880,7 @@ char *ReadNetlist(char *fname, int *fnum)
}; };
#ifdef mips #ifdef mips
struct filetype formats[8]; struct filetype formats[7];
formats[0].extension = NTK_EXTENSION; formats[0].extension = NTK_EXTENSION;
formats[0].proc = ReadNtk; formats[0].proc = ReadNtk;
@ -924,16 +888,14 @@ char *ReadNetlist(char *fname, int *fnum)
formats[1].proc = ReadExtHier; formats[1].proc = ReadExtHier;
formats[2].extension = SIM_EXTENSION; formats[2].extension = SIM_EXTENSION;
formats[2].proc = ReadSim; formats[2].proc = ReadSim;
formats[3].extension = PRM_EXTENSION; formats[3].extension = SPICE_EXTENSION;
formats[3].proc = ReadPrm; formats[3].proc = ReadSpice;
formats[4].extension = SPICE_EXTENSION; formats[4].extension = NETGEN_EXTENSION;
formats[4].proc = ReadSpice; formats[4].proc = ReadNetgenFile;
formats[5].extension = NETGEN_EXTENSION; formats[5].extension = VERILOG_EXTENSION;
formats[5].proc = ReadNetgenFile; formats[5].proc = ReadVerilogFile;
formats[6].extension = VERILOG_EXTENSION; formats[6].extension = NULL;
formats[6].proc = ReadVerilogFile; formats[6].proc = NULL;
formats[7].extension = NULL;
formats[7].proc = NULL;
#else /* not mips (i.e. compiler with reasonable initializers) */ #else /* not mips (i.e. compiler with reasonable initializers) */
@ -942,7 +904,6 @@ char *ReadNetlist(char *fname, int *fnum)
{NTK_EXTENSION, ReadNtk}, {NTK_EXTENSION, ReadNtk},
{EXT_EXTENSION, ReadExtHier}, {EXT_EXTENSION, ReadExtHier},
{SIM_EXTENSION, ReadSim}, {SIM_EXTENSION, ReadSim},
{PRM_EXTENSION, ReadPrm},
{SPICE_EXTENSION, ReadSpice}, {SPICE_EXTENSION, ReadSpice},
{SPICE_EXT2, ReadSpice}, {SPICE_EXT2, ReadSpice},
{SPICE_EXT3, ReadSpice}, {SPICE_EXT3, ReadSpice},

View File

@ -7,7 +7,6 @@
#define WOMBAT_EXTENSION ".wom" #define WOMBAT_EXTENSION ".wom"
#define EXT_EXTENSION ".ext" #define EXT_EXTENSION ".ext"
#define SIM_EXTENSION ".sim" #define SIM_EXTENSION ".sim"
#define PRM_EXTENSION ".prm"
#define SPICE_EXTENSION ".spice" #define SPICE_EXTENSION ".spice"
#define SPICE_EXT2 ".spc" #define SPICE_EXT2 ".spc"
#define SPICE_EXT3 ".sp" #define SPICE_EXT3 ".sp"
@ -36,7 +35,6 @@ extern struct hashdict *definitions;
extern char *nexttok; extern char *nexttok;
#define SKIPTO(a) do {SkipTok(NULL);} while (!match(nexttok,a)) #define SKIPTO(a) do {SkipTok(NULL);} while (!match(nexttok,a))
extern char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog);
extern char *strdtok(char *pstring, char *delim1, char *delim2); extern char *strdtok(char *pstring, char *delim1, char *delim2);
extern char *GetLineAtTok(); extern char *GetLineAtTok();
extern void SkipTok(char *delimiter); extern void SkipTok(char *delimiter);

View File

@ -25,8 +25,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> /* for strtof() */ #include <stdlib.h> /* for strtof() */
#include <stdarg.h> #include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <ctype.h> /* toupper() */ #include <ctype.h> /* toupper() */
#ifdef IBMPC #ifdef IBMPC
#include <alloc.h> #include <alloc.h>
@ -302,8 +300,6 @@ int ReduceOneExpression(struct valuelist *kv, struct objlist *parprops,
tstr = sstr - 1; tstr = sstr - 1;
numlast = 1; numlast = 1;
} }
/* But might not be. . . */
if ((dval != 0) || (sstr > estr))
break; break;
} }
/* Not a number, so must be arithmetic */ /* Not a number, so must be arithmetic */
@ -324,8 +320,6 @@ int ReduceOneExpression(struct valuelist *kv, struct objlist *parprops,
tstr = sstr - 1; tstr = sstr - 1;
numlast = 1; numlast = 1;
} }
/* But might not be. . . */
if ((dval != 0) || (sstr > estr))
break; break;
} }
/* Not a number, so must be arithmetic */ /* Not a number, so must be arithmetic */
@ -2250,10 +2244,7 @@ int PromoteProperty(struct property *prop, struct valuelist *vl,
if (prop == NULL || vl == NULL) return -1; if (prop == NULL || vl == NULL) return -1;
if (prop->type == vl->type) return 1; /* Nothing to do */ if (prop->type == vl->type) return 1; /* Nothing to do */
result = 0; result = 0;
/* If vl is an expression but prop is not, then try to reduce if (prop->type == PROP_EXPRESSION) {
* the expression in vl.
*/
if (vl->type == PROP_EXPRESSION) {
ReduceOneExpression(vl, ob, tc, FALSE); ReduceOneExpression(vl, ob, tc, FALSE);
} }
switch (prop->type) { switch (prop->type) {
@ -3099,7 +3090,7 @@ void add_balancing_close(struct objlist *ob1, struct objlist *ob2)
for (nob = ob1->next; nob && nob->type != FIRSTPIN; nob = nob->next) for (nob = ob1->next; nob && nob->type != FIRSTPIN; nob = nob->next)
if (nob->type == PROPERTY) if (nob->type == PROPERTY)
break; break;
if (nob == NULL || nob->type != PROPERTY) return; // shouldn't happen if (nob->type != PROPERTY) return; // shouldn't happen
opentags = 0; opentags = 0;
for (; nob->next && nob->next->type == PROPERTY; nob = nob->next) { for (; nob->next && nob->next->type == PROPERTY; nob = nob->next) {
@ -3649,7 +3640,7 @@ int CombineSeries(char *model, int file)
nob->type = PROPERTY; nob->type = PROPERTY;
nob->name = strsave("properties"); nob->name = strsave("properties");
nob->node = -2; /* Don't report as disconnected node */ nob->node = -2; /* Don't report as disconnected node */
nob->model.class = (obp == NULL || obp->model.class == NULL) ? NULL : nob->model.class = (obp->model.class == NULL) ? NULL :
strsave(obp->model.class); strsave(obp->model.class);
nob->instance.props = NewPropValue(2); nob->instance.props = NewPropValue(2);

View File

@ -191,7 +191,6 @@ extern char *ReadNtk (char *fname, int *fnum);
extern char *ReadExtHier(char *fname, int *fnum); extern char *ReadExtHier(char *fname, int *fnum);
extern char *ReadExtFlat(char *fname, int *fnum); extern char *ReadExtFlat(char *fname, int *fnum);
extern char *ReadSim(char *fname, int *fnum); extern char *ReadSim(char *fname, int *fnum);
extern char *ReadPrm(char *fname, int *fnum);
extern char *ReadSpice(char *fname, int *fnum); extern char *ReadSpice(char *fname, int *fnum);
extern char *ReadSpiceLib(char *fname, int *fnum); extern char *ReadSpiceLib(char *fname, int *fnum);
extern char *ReadNetgenFile (char *fname, int *fnum); extern char *ReadNetgenFile (char *fname, int *fnum);

View File

@ -223,35 +223,12 @@ int matchnocase(char *st1, char *st2)
{ {
char *sp1 = st1; char *sp1 = st1;
char *sp2 = st2; char *sp2 = st2;
char v1 = FALSE, v2 = FALSE;
/* In case of a property that does not exist in one netlist, matchnocase()
* may be passed a null value, so return 0 to indicate a non-match.
* *Both* values null will also be treated as a mismatch (debatable
* behavior).
*/
if (!sp1 || !sp2) return 0;
/* Verilog back-slash escaped names should match an equivalent non-
* back-slashed name. (NOTE: This behavior needs to be added to match().)
*/
if ((*sp1 == '\\') && (*sp2 != '\\')) {
v1 = TRUE;
sp1++;
}
if ((*sp2 == '\\') && (*sp1 != '\\')) {
v2 = TRUE;
sp2++;
}
while (*sp1 != '\0' && *sp2 != '\0') { while (*sp1 != '\0' && *sp2 != '\0') {
if (to_lower[*sp1] != to_lower[*sp2]) break; if (to_lower[*sp1] != to_lower[*sp2]) break;
sp1++; sp1++;
sp2++; sp2++;
} }
if (v1 && (*sp1 == ' ')) sp1++;
if (v2 && (*sp2 == ' ')) sp2++;
if ((*sp1 != '\0') || (*sp2 != '\0')) return 0; if ((*sp1 != '\0') || (*sp2 != '\0')) return 0;
return 1; return 1;
} }
@ -282,33 +259,6 @@ int matchfilenocase(char *st1, char *st2, int f1, int f2)
return 1; return 1;
} }
/* Delimiter matching---Find an opening delimiter in a string. */
/* Return the position of the first opening delimeter in the string, */
/* like strchr(). Place the actual delimeter character in *delim. */
char *get_array_delimiter(char *name, char *delim)
{
char *stest = name;
while (*stest != '\0')
{
if (to_lower[*stest] == '<') {
*delim = *stest;
return stest;
}
stest++;
}
return NULL;
}
/* Delimiter parsing---Check if a character is an opening array delimiter. */
/* Return TRUE if the character is an opening delimiter, FALSE if not. */
int is_delimiter(char testc)
{
return (to_lower[testc] == '<') ? TRUE : FALSE;
}
#ifdef HAVE_MALLINFO #ifdef HAVE_MALLINFO
void PrintMemoryStats(void) void PrintMemoryStats(void)
{ {
@ -476,7 +426,6 @@ int removeshorted(struct hashlist *p, int file)
ob = nob; ob = nob;
} }
} }
return 1;
} }
/* Remove shorted instances of class "class" from the database */ /* Remove shorted instances of class "class" from the database */
@ -567,7 +516,6 @@ int deleteclass(struct hashlist *p, int file)
} }
} }
FREE(checknodes); FREE(checknodes);
return 1;
} }
/* Remove all instances of class "class" from the database */ /* Remove all instances of class "class" from the database */
@ -605,7 +553,6 @@ int renameinstances(struct hashlist *p, int file)
} }
} }
} }
return 1;
} }
void InstanceRename(char *from, char *to, int file) void InstanceRename(char *from, char *to, int file)
@ -628,10 +575,9 @@ int freeprop(struct hashlist *p)
struct property *prop; struct property *prop;
prop = (struct property *)(p->ptr); prop = (struct property *)(p->ptr);
if (prop->type == PROP_STRING) { if (prop->type == PROP_STRING)
if (prop->pdefault.string != NULL) if (prop->pdefault.string != NULL)
FREE(prop->pdefault.string); FREE(prop->pdefault.string);
}
else if (prop->type == PROP_EXPRESSION) { else if (prop->type == PROP_EXPRESSION) {
struct tokstack *stackptr, *nptr; struct tokstack *stackptr, *nptr;
stackptr = prop->pdefault.stack; stackptr = prop->pdefault.stack;
@ -687,7 +633,7 @@ static int PrintCellHashTableElement(struct hashlist *p)
ptr = (struct nlist *)(p->ptr); ptr = (struct nlist *)(p->ptr);
if ((TopFile >= 0) && (ptr->file != TopFile)) return 1; if ((TopFile >= 0) && (ptr->file != TopFile)) return 1;
if ((ptr->class != CLASS_SUBCKT) && (ptr->class != CLASS_MODULE)) { if (ptr->class != CLASS_SUBCKT) {
/* only print primitive cells if Debug is enabled */ /* only print primitive cells if Debug is enabled */
if (Debug == 1) Printf("Cell: %s (instanced %d times); Primitive\n", if (Debug == 1) Printf("Cell: %s (instanced %d times); Primitive\n",
ptr->name, ptr->number); ptr->name, ptr->number);
@ -707,7 +653,7 @@ static int PrintCellHashTableElement(struct hashlist *p)
#endif #endif
} }
else else
Printf("Cell: %s (instanced %d times)\n", ptr->name, ptr->number); Printf("Cell: %s (instanced %d times)\n",ptr->name,ptr->number);
return(1); return(1);
} }

View File

@ -309,8 +309,6 @@ extern int match(char *, char *);
extern int matchnocase(char *, char *); extern int matchnocase(char *, char *);
extern int matchfile(char *, char *, int, int); extern int matchfile(char *, char *, int, int);
extern int matchfilenocase(char *, char *, int, int); extern int matchfilenocase(char *, char *, int, int);
extern int is_delimiter(char);
extern char *get_array_delimiter(char *, char *);
extern void GarbageCollect(void); extern void GarbageCollect(void);
extern void InitGarbageCollection(void); extern void InitGarbageCollection(void);

View File

@ -319,7 +319,7 @@ void Fanout(char *cell, char *node, int filter)
while (ob != NULL) { while (ob != NULL) {
char *obname = ob->name; char *obname = ob->name;
if (*obname == '/') obname++; if (*obname == '/') obname++;
if (ob->node == nodenum) { if (ob->node == nodenum)
if (filter == ALLOBJECTS) { if (filter == ALLOBJECTS) {
Printf(" %s (", obname); Printf(" %s (", obname);
PrintObjectType(ob->type); PrintObjectType(ob->type);
@ -331,7 +331,6 @@ void Fanout(char *cell, char *node, int filter)
else if (ob->type == filter) { else if (ob->type == filter) {
Printf(" %s\n", obname); Printf(" %s\n", obname);
} }
}
ob = ob->next; ob = ob->next;
} }
} }
@ -934,7 +933,7 @@ static int PrintLeavesInCellHash(struct hashlist *p)
struct nlist *ptr; struct nlist *ptr;
ptr = (struct nlist *)(p->ptr); ptr = (struct nlist *)(p->ptr);
if (ptr->class == CLASS_SUBCKT) PrintLeavesInCell(ptr->name, ptr->file); if ((ptr->class == CLASS_SUBCKT)) PrintLeavesInCell(ptr->name, ptr->file);
return(0); return(0);
} }

View File

@ -21,9 +21,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#if 0 #if 0
#include <stdarg.h> /* what about varargs, like in pdutils.c ??? */ #include <stdarg.h> /* what about varargs, like in pdutils.c ??? */
#endif #endif
@ -46,7 +43,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "print.h" #include "print.h"
#include "query.h" #include "query.h"
#include "objlist.h" #include "objlist.h"
#include "netcmp.h"
// Global storage for parameters from .PARAM // Global storage for parameters from .PARAM
struct hashdict spiceparams; struct hashdict spiceparams;
@ -196,7 +192,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
if (ob->type == PROPERTY) { if (ob->type == PROPERTY) {
struct valuelist *vl; struct valuelist *vl;
int i; int i;
for (i = 0;; i++) { for (i == 0;; i++) {
vl = &(ob->instance.props[i]); vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break; if (vl->type == PROP_ENDLIST) break;
else if (vl->type == PROP_VALUE) { else if (vl->type == PROP_VALUE) {
@ -216,7 +212,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
if (ob->type == PROPERTY) { if (ob->type == PROPERTY) {
struct valuelist *vl; struct valuelist *vl;
int i; int i;
for (i = 0;; i++) { for (i == 0;; i++) {
vl = &(ob->instance.props[i]); vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break; if (vl->type == PROP_ENDLIST) break;
else if (vl->type == PROP_VALUE) { else if (vl->type == PROP_VALUE) {
@ -236,7 +232,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
if (ob->type == PROPERTY) { if (ob->type == PROPERTY) {
struct valuelist *vl; struct valuelist *vl;
int i; int i;
for (i = 0;; i++) { for (i == 0;; i++) {
vl = &(ob->instance.props[i]); vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break; if (vl->type == PROP_ENDLIST) break;
else if (vl->type == PROP_VALUE) { else if (vl->type == PROP_VALUE) {
@ -399,7 +395,7 @@ int renamepins(struct hashlist *p, int file)
ptr = (struct nlist *)(p->ptr); ptr = (struct nlist *)(p->ptr);
if (ptr->file != file) if (ptr->file != file)
return 0; return 1;
for (ob = ptr->cell; ob != NULL; ob = ob->next) { for (ob = ptr->cell; ob != NULL; ob = ob->next) {
if (ob->type == FIRSTPIN) { if (ob->type == FIRSTPIN) {
@ -426,7 +422,6 @@ int renamepins(struct hashlist *p, int file)
} }
} }
} }
return 1;
} }
/* If any pins are marked unconnected, see if there are */ /* If any pins are marked unconnected, see if there are */
@ -524,7 +519,7 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
char *eqptr, devtype, in_subckt; char *eqptr, devtype, in_subckt;
struct keyvalue *kvlist = NULL; struct keyvalue *kvlist = NULL;
char inst[MAX_STR_LEN], model[MAX_STR_LEN], instname[MAX_STR_LEN]; char inst[MAX_STR_LEN], model[MAX_STR_LEN], instname[MAX_STR_LEN];
struct nlist *tp, *tpsave; struct nlist *tp;
struct objlist *parent, *sobj, *nobj, *lobj, *pobj; struct objlist *parent, *sobj, *nobj, *lobj, *pobj;
inst[MAX_STR_LEN-1] = '\0'; inst[MAX_STR_LEN-1] = '\0';
@ -536,14 +531,8 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
SkipTok(NULL); /* get the next token */ SkipTok(NULL); /* get the next token */
if ((EndParseFile()) && (nexttok == NULL)) break; if ((EndParseFile()) && (nexttok == NULL)) break;
if (nexttok == NULL) break;
/* Handle comment lines. Note that some variants of CDL format if (nexttok[0] == '*') SkipNewLine(NULL);
* use "*." for information that is transparent to SPICE simulators.
* Handle "*.GLOBAL" entries. All others are ignored.
*/
if ((nexttok[0] == '*') && (!matchnocase(nexttok, "*.GLOBAL")))
SkipNewLine(NULL);
else if (matchnocase(nexttok, ".SUBCKT")) { else if (matchnocase(nexttok, ".SUBCKT")) {
SpiceTokNoNewline(); SpiceTokNoNewline();
@ -568,7 +557,6 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
snprintf(model, MAX_STR_LEN-1, "%s", nexttok); snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
tp = LookupCellFile(nexttok, filenum); tp = LookupCellFile(nexttok, filenum);
tpsave = NULL;
/* Check for name conflict with duplicate cell names */ /* Check for name conflict with duplicate cell names */
/* This may mean that the cell was used before it was */ /* This may mean that the cell was used before it was */
@ -607,47 +595,12 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
tp = LookupCellFile(nexttok, filenum); tp = LookupCellFile(nexttok, filenum);
} }
else if (tp != NULL) { /* Make a new definition for an empty cell */ else if (tp != NULL) { /* Make a new definition for an empty cell */
/* Handle issue with SPICE read after verilog, where a placeholder
* was created from the verilog. (1) If the pin names are "1", "2",
* "3", then this is a SPICE placeholder, and just remove the CellDef
* and re-create it. Otherwise, create new cell "_PLACEHOLDER_".
* (2) After encountering .ends, run MatchPins between the two cells.
* (3) delete the original cell and rename the new cell.
*/
int i = 1;
char pname[10];
for (pobj = tp->cell; pobj && pobj->type == PORT; pobj = pobj->next) {
sprintf(pname, "%d", i);
if (!matchnocase(pobj->name, pname)) break;
i++;
}
if ((pobj == NULL) || (pobj->type != PORT)) {
/* This is a SPICE placeholder created because the cell was instanced
* before it was defined. However, the pins can be assumed to be in
* the correct order, and pin reordering does not need to be done.
*/
FreePorts(nexttok); FreePorts(nexttok);
CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */ CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */
CellDef(model, filenum); CellDef(model, filenum);
tp = LookupCellFile(model, filenum); tp = LookupCellFile(model, filenum);
update = 1; /* Will need to update existing instances */ update = 1; /* Will need to update existing instances */
} }
else {
/* This is (probably) a verilog placeholder created because the
* verilog was read before the (SPICE) definitions. The verilog
* netlist should have named the pins of the parent cell. However,
* there is no guarantee the order of pins is correct. The MatchPins()
* routine from netcmp.c can be used here to match the cell against
* the placeholder, and reorder the pins in all instances to match.
* Note that we cannot just reorder the SPICE pins to match the
* verilog order, because there may be other SPICE netlists which
* instance the cell with the correct SPICE port order.
*/
tpsave = tp;
CellDef("_PLACEHOLDER_", filenum);
tp = LookupCellFile("_PLACEHOLDER_", filenum);
}
}
else if (tp == NULL) { /* Completely new cell, no name conflict */ else if (tp == NULL) { /* Completely new cell, no name conflict */
CellDef(model, filenum); CellDef(model, filenum);
tp = LookupCellFile(model, filenum); tp = LookupCellFile(model, filenum);
@ -738,38 +691,6 @@ skip_ends:
if (*CellStackPtr) PopStack(CellStackPtr); if (*CellStackPtr) PopStack(CellStackPtr);
if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum); if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum);
SkipNewLine(NULL); SkipNewLine(NULL);
if (tpsave != NULL) {
struct nlist *tpplace;
char *savename;
/* Handle a placeholder from a verilog file that has been replaced
* by a netlist with pins in a different order. The pins need to
* be matched, corrected in the original cell and all instances,
* and the new cell deleted.
*/
Printf("Verilog placeholder %s replaced by SPICE definition\n",
tpsave->name);
tpplace = LookupCellFile("_PLACEHOLDER_", filenum);
/* MatchPins is part of netcmp and normally Circuit2 is the
* circuit being matched, so set Circuit2 to the original
* verilog black-box cell, and MatchPins() will force its
* pins to be rearranged to match the SPICE definition just
* read.
*/
Circuit2 = tpsave;
MatchPins(tpplace, tpsave, 0);
savename = strsave(tpsave->name);
/* Now the original verilog black-box cell can be removed */
FreePorts(savename);
CellDelete(savename, filenum);
/* And _PLACEHOLDER_ is renamed to the original name of the cell. */
CellRehash("_PLACEHOLDER_", savename, filenum);
tpsave = NULL;
Circuit2 = NULL;
FREE(savename);
}
} }
else if (matchnocase(nexttok, ".MODEL")) { else if (matchnocase(nexttok, ".MODEL")) {
unsigned char class = CLASS_SUBCKT; unsigned char class = CLASS_SUBCKT;
@ -831,10 +752,7 @@ skip_ends:
// Handle some commonly-used cards // Handle some commonly-used cards
/* .GLOBAL and *.GLOBAL. Note that *.GLOBAL is excepted from comment-line else if (matchnocase(nexttok, ".GLOBAL")) {
* handling, above, so any line starting with '*' is "*.GLOBAL".
*/
else if (matchnocase(nexttok, ".GLOBAL") || (nexttok[0] == '*')) {
while (nexttok != NULL) { while (nexttok != NULL) {
int numnodes = 0; int numnodes = 0;
SpiceTokNoNewline(); SpiceTokNoNewline();
@ -1783,19 +1701,10 @@ skip_ends:
if (scan->next != NULL) scan = scan->next; if (scan->next != NULL) scan = scan->next;
tail->next = NULL; tail->next = NULL;
/* Check for class defined inside itself (self-referential loop) */
if (!strcasecmp(model, scan->name)) {
Fprintf(stderr, "Fatal: Class \"%s\" is instanced inside of itself!\n",
scan->name);
InputParseError(stderr);
return;
}
/* Check for ignored class */ /* Check for ignored class */
if ((itype = IsIgnored(scan->name, filenum)) == IGNORE_CLASS) { if ((itype = IsIgnored(subcktname, filenum)) == IGNORE_CLASS) {
Printf("Class '%s' instanced in input but is being ignored.\n", scan->name); Printf("Class '%s' instanced in input but is being ignored.\n", model);
return; return;
} }
@ -1810,7 +1719,7 @@ skip_ends:
break; break;
} }
if (shorted == (unsigned char)1) { if (shorted == (unsigned char)1) {
Printf("Instance of '%s' is shorted, ignoring.\n", scan->name); Printf("Instance of '%s' is shorted, ignoring.\n", subcktname);
while (head) { while (head) {
p = head->next; p = head->next;
FREE(head); FREE(head);

View File

@ -57,7 +57,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "netfile.h" #include "netfile.h"
#include "print.h" #include "print.h"
#include "hash.h" #include "hash.h"
#include "netcmp.h"
// See netfile.c for explanation of delimiters. 'X' // See netfile.c for explanation of delimiters. 'X'
// separates single-character delimiters from two-character delimiters. // separates single-character delimiters from two-character delimiters.
@ -76,8 +75,7 @@ struct hashdict verilogparams;
// Global storage for verilog definitions // Global storage for verilog definitions
struct hashdict verilogdefs; struct hashdict verilogdefs;
// Record file pointer that is associated with the hash tables // Record file pointer that is associated with the hash tables
int hashfilep = -1; /* for parameters */ int hashfile = -1;
int hashfiled = -1; /* for definitions */
// Global storage for wire buses // Global storage for wire buses
struct hashdict buses; struct hashdict buses;
@ -157,8 +155,7 @@ struct expr_stack {
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Evaluate an expression for an array bound. This is much like // Evaluate an expression for an array bound. This is much like
// ReduceOneExpression() in netgen.c, but only handles basic integer // ReduceOneExpression() in netgen.c, but only handles basic integer
// arithmetic (+,-,*,/), grouping by parentheses, bit shifts, and // arithmetic (+,-,*,/) and grouping by parentheses.
// if-else operators.
// //
// Returns 1 if successful, 0 on error. // Returns 1 if successful, 0 on error.
// Evaluated result is placed in the integer pointed to by "valptr". // Evaluated result is placed in the integer pointed to by "valptr".
@ -222,39 +219,6 @@ int EvalExpr(struct expr_stack **stackptr, int *valptr)
} }
} }
/* Reduce (a << b) and (a >> b) */
for (texp = start; texp; texp = texp->next) {
if ((texp->last != NULL) && (texp->next != NULL) && (texp->oper != '\0')) {
if ((texp->last->oper == '\0') && (texp->next->oper == '\0')) {
if (texp->oper == '<') {
/* Left shift */
texp->last->value <<= texp->next->value;
/* Remove two items from the stack */
tmp = texp;
texp = texp->last;
texp->next = tmp->next->next;
if (tmp->next->next) tmp->next->next->last = texp;
FREE(tmp->next);
FREE(tmp);
modified = TRUE;
}
if (texp->oper == '>') {
/* Right shift */
texp->last->value >>= texp->next->value;
/* Remove two items from the stack */
tmp = texp;
texp = texp->last;
texp->next = tmp->next->next;
if (tmp->next->next) tmp->next->next->last = texp;
FREE(tmp->next);
FREE(tmp);
modified = TRUE;
}
}
}
}
/* Reduce (a * b) and (a / b) */ /* Reduce (a * b) and (a / b) */
for (texp = start; texp; texp = texp->next) { for (texp = start; texp; texp = texp->next) {
@ -330,39 +294,6 @@ int EvalExpr(struct expr_stack **stackptr, int *valptr)
} }
} }
/* Reduce (a ? b : c) */
for (texp = start; texp; texp = texp->next) {
/* There must be at least five objects on the stack */
if ((texp->last != NULL) && (texp->next != NULL) && (texp->oper != '\0')
&& (texp->next->next != NULL)
&& (texp->next->next->next != NULL)) {
if ((texp->last->oper == '\0') && (texp->next->oper == '\0')
&& (texp->next->next->next->oper == '\0')) {
if ((texp->oper == '?') && (texp->next->next->oper == ':')) {
/* If-Else conditional */
if (texp->last->value)
texp->last->value = texp->next->value;
else
texp->last->value = texp->next->next->next->value;
/* Remove four items from the stack */
tmp = texp;
texp = texp->last;
texp->next = tmp->next->next->next->next;
if (tmp->next->next->next->next)
tmp->next->next->next->next->last = texp;
FREE(tmp->next->next->next);
FREE(tmp->next->next);
FREE(tmp->next);
FREE(tmp);
modified = TRUE;
}
}
}
}
/* Reduce (a) */ /* Reduce (a) */
for (texp = start; texp; texp = texp->next) { for (texp = start; texp; texp = texp->next) {
@ -441,15 +372,8 @@ int ParseIntegerExpression(char *expr, int *iptr)
if (match(sptr, "+") || match(sptr, "-") if (match(sptr, "+") || match(sptr, "-")
|| match(sptr, "*") || match(sptr, "/") || match(sptr, "*") || match(sptr, "/")
|| match(sptr, "(") || match(sptr, ")") || match(sptr, "(") || match(sptr, ")")) {
|| match(sptr, "<<") || match(sptr, ">>")
|| match(sptr, "?") || match(sptr, ":")) {
newexp = (struct expr_stack *)MALLOC(sizeof(struct expr_stack)); newexp = (struct expr_stack *)MALLOC(sizeof(struct expr_stack));
/* Note that "oper" is one character and that "<<" and ">>"
* become '<' and '>', respectively. The less-than and greater-
* than operators are not (yet) handled but will need to be
* recast to some other character in "oper".
*/
newexp->oper = *sptr; newexp->oper = *sptr;
newexp->value = 0; newexp->value = 0;
newexp->next = NULL; newexp->next = NULL;
@ -464,7 +388,7 @@ int ParseIntegerExpression(char *expr, int *iptr)
if ((result = sscanf(sptr, "%d", &value)) != 1) { if ((result = sscanf(sptr, "%d", &value)) != 1) {
// Is name in the parameter list? // Is name in the parameter list?
kl = (struct property *)HashLookup(sptr, &verilogparams); kl = (struct property *)HashLookup(nexttok, &verilogparams);
if (kl == NULL) { if (kl == NULL) {
Printf("Value %s in expression is not a number or a parameter.\n", Printf("Value %s in expression is not a number or a parameter.\n",
sptr); sptr);
@ -477,29 +401,27 @@ int ParseIntegerExpression(char *expr, int *iptr)
if (result != 1) { if (result != 1) {
Printf("Parameter %s has value %s that cannot be parsed" Printf("Parameter %s has value %s that cannot be parsed"
" as an integer.\n", " as an integer.\n",
sptr, kl->pdefault.string); nexttok, kl->pdefault.string);
value = 0; value = 0;
break; break;
} }
} }
else if (kl->type == PROP_INTEGER) { else if (kl->type == PROP_INTEGER) {
value = kl->pdefault.ival; value = kl->pdefault.ival;
result = 1; // Assert valid result
} }
else if (kl->type == PROP_DOUBLE) { else if (kl->type == PROP_DOUBLE) {
value = (int)kl->pdefault.dval; value = (int)kl->pdefault.dval;
if ((double)value != kl->pdefault.dval) { if ((double)value != kl->pdefault.dval) {
Printf("Parameter %s has value %g that cannot be parsed" Printf("Parameter %s has value %g that cannot be parsed"
" as an integer.\n", " as an integer.\n",
sptr, kl->pdefault.dval); nexttok, kl->pdefault.dval);
value = 0; value = 0;
break; break;
} }
result = 1; // Assert valid result
} }
else { else {
Printf("Parameter %s has unknown type; don't know how" Printf("Parameter %s has unknown type; don't know how"
" to parse.\n", sptr); " to parse.\n", nexttok);
value = 0; value = 0;
break; break;
} }
@ -593,8 +515,7 @@ int GetBusTok(struct bus *wb)
} }
else if (match(nexttok, "+") || match(nexttok, "-") else if (match(nexttok, "+") || match(nexttok, "-")
|| match(nexttok, "*") || match(nexttok, "/") || match(nexttok, "*") || match(nexttok, "/")
|| match(nexttok, "(") || match(nexttok, ")") || match(nexttok, "(") || match(nexttok, ")")) {
|| match(nexttok, "<<") || match(nexttok, ">>")) {
newexp = (struct expr_stack *)MALLOC(sizeof(struct expr_stack)); newexp = (struct expr_stack *)MALLOC(sizeof(struct expr_stack));
newexp->oper = *nexttok; newexp->oper = *nexttok;
newexp->value = 0; newexp->value = 0;
@ -795,12 +716,10 @@ int GetBus(char *astr, struct bus *wb)
return 0; return 0;
} }
//--------------------------------------------------------------------
// Output a Verilog Module. Note that since Verilog does not describe // Output a Verilog Module. Note that since Verilog does not describe
// low-level devices like transistors, capacitors, etc., then this // low-level devices like transistors, capacitors, etc., then this
// format is limited to black-box subcircuits. Cells containing any // format is limited to black-box subcircuits. Cells containing any
// such low-level devices are ignored. // such low-level devices are ignored.
//--------------------------------------------------------------------
void VerilogModule(struct nlist *tp) void VerilogModule(struct nlist *tp)
{ {
@ -1099,7 +1018,7 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
char *eqptr, *matchptr; char *eqptr, *matchptr;
struct keyvalue *kvlist = NULL; struct keyvalue *kvlist = NULL;
char inst[MAX_STR_LEN], model[MAX_STR_LEN], portname[MAX_STR_LEN], pkey[MAX_STR_LEN]; char inst[MAX_STR_LEN], model[MAX_STR_LEN], portname[MAX_STR_LEN], pkey[MAX_STR_LEN];
struct nlist *tp, *tpsave; struct nlist *tp;
struct objlist *parent, *sobj, *nobj, *lobj, *pobj, *cref; struct objlist *parent, *sobj, *nobj, *lobj, *pobj, *cref;
inst[MAX_STR_LEN-1] = '\0'; inst[MAX_STR_LEN-1] = '\0';
@ -1233,7 +1152,6 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
snprintf(model, MAX_STR_LEN-1, "%s", nexttok); snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
tp = LookupCellFile(nexttok, filenum); tp = LookupCellFile(nexttok, filenum);
tpsave = NULL;
hasports = (char)0; hasports = (char)0;
/* Check for name conflict with duplicate cell names */ /* Check for name conflict with duplicate cell names */
@ -1273,9 +1191,35 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
tp = LookupCellFile(nexttok, filenum); tp = LookupCellFile(nexttok, filenum);
} }
else if (tp != NULL) { /* Cell exists, but as a placeholder */ else if (tp != NULL) { /* Cell exists, but as a placeholder */
tpsave = tp; struct nlist *tptmp = NULL;
CellDef("_PLACEHOLDER_", filenum); char ctemp[8];
tp = LookupCellFile("_PLACEHOLDER_", filenum); int n = 0;
/* This redefines a placeholder module to an unused temporary cell name */
while (1) {
sprintf(ctemp, "%d", n);
tptmp = LookupCellFile(ctemp, filenum);
if (tptmp == NULL) break;
n++;
}
CellRehash(nexttok, ctemp, filenum);
tptmp = LookupCellFile(ctemp, filenum);
/* Create a new module definition */
CellDef(model, filenum);
tp = LookupCellFile(model, filenum);
/* Find an instance of this module in the netlist */
cref = FindInstanceOf(tp);
if ((cref != NULL) && (cref->name != NULL)) {
hasports = (char)1;
/* Copy ports from the original parent cell to the new parent cell */
for (pobj = tptmp->cell; pobj && (pobj->type == PORT); pobj = pobj->next)
Port(pobj->name);
}
/* Remove the original cell definition */
FreePorts(ctemp);
CellDelete(ctemp, filenum); /* This removes any PLACEHOLDER flag */
} }
else if (tp == NULL) { /* Completely new cell, no name conflict */ else if (tp == NULL) { /* Completely new cell, no name conflict */
CellDef(model, filenum); CellDef(model, filenum);
@ -1484,93 +1428,6 @@ skip_endmodule:
if (*CellStackPtr) PopStack(CellStackPtr); if (*CellStackPtr) PopStack(CellStackPtr);
if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum); if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum);
SkipNewLine(VLOG_DELIMITERS); SkipNewLine(VLOG_DELIMITERS);
if (tpsave != NULL) {
struct nlist *tpplace;
char *savename;
int lnum, pnum, ltest;
unsigned char valid;
struct objlist *lobj, *pobj;
/* Handle a placeholder from a verilog file that has been replaced
* by a netlist with pins in a different order. The pins need to
* be matched, corrected in the original cell and all instances,
* and the new cell deleted.
*/
Printf("Verilog placeholder module %s replaced by module definition\n",
tpsave->name);
tpplace = LookupCellFile("_PLACEHOLDER_", filenum);
/* If tpsave was generated from an instance in a SPICE netlist that
* did not have a black-box subcircuit definition, then the pins
* will all be labeled 1, 2, 3, etc. If so, then assume that the
* verilog pins are in order, and rename the placeholder pins.
* If the number of pins does not match, or if the pins are not
* labeled as ascending integers, then leave the cell alone.
* In either case, output a warning message.
*/
/* Get the number of ports in the placeholder */
pnum = 0;
for (pobj = tpplace->cell; pobj; pobj = pobj->next) {
if (pobj->type != PORT) break;
pnum++;
}
/* Get the number of ports in the saved cell and make */
/* sure that it equals the number of ports in the */
/* placeholder, and that all of the ports in the saved */
/* cell are integers in ascending order. */
valid = TRUE;
lnum = 0;
for (lobj = tpsave->cell; lobj; lobj = lobj->next) {
if (lobj->type != PORT) break;
lnum++;
if (sscanf(lobj->name, "%d", &ltest) != 1) break;
if (ltest != lnum) break;
}
if ((lobj != NULL) && (lobj->type == PORT))
valid = FALSE; /* Pins are not integers in ascending order */
if (pnum != lnum) valid = FALSE; /* Different number of pins */
if (valid == TRUE) {
Printf("Replacing pins of placeholder cell %s from cell definition.\n",
tpsave->name);
pobj = tpplace->cell;
for (lobj = tpsave->cell; lobj; lobj = lobj->next) {
if (lobj->type != PORT) break;
if (pobj == NULL) break; /* should not happen */
FREE(lobj->name);
lobj->name = (char *)MALLOC(strlen(pobj->name) + 1);
strcpy(lobj->name, pobj->name);
pobj = pobj->next;
}
}
else {
Printf("Placeholder pins of cell %s are not compatible and"
" will be left unchanged\n", tpsave->name);
}
/* MatchPins is part of netcmp and normally Circuit2 is the
* circuit being matched, so set Circuit2 to the original
* verilog black-box cell, and MatchPins() will force its
* pins to be rearranged to match the module definition just
* read.
*/
Circuit2 = tpsave;
MatchPins(tpplace, tpsave, 0);
savename = strsave(tpsave->name);
/* Now the original verilog black-box cell can be removed */
FreePorts(savename);
CellDelete(savename, filenum);
/* And _PLACEHOLDER_ is renamed to the original name of the cell. */
CellRehash("_PLACEHOLDER_", savename, filenum);
tpsave = NULL;
Circuit2 = NULL;
FREE(savename);
}
} }
else if (match(nexttok, "`include")) { else if (match(nexttok, "`include")) {
@ -1913,41 +1770,8 @@ skip_endmodule:
} }
else { /* "assign" */ else { /* "assign" */
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS); SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
if (GetBusTok(&wb) == 0) {
char *aptr = strvchr(nexttok, '['); char *aptr = strvchr(nexttok, '[');
/* This is a repeat of code to handle reading of pins, and
* makes sure that all input has been read to the closing
* bracket. There needs to be a single routine to do this,
* or (better) rewrite the parser with lex instead of trying
* to enumerate all the syntax cases separately.
*/
if ((aptr != NULL) && (strvchr(nexttok, ']') == NULL))
{
/* If a bus expressions has whitespace, then concatenate
* to the closing ']'.
*/
char *array_expr = (char *)MALLOC(1);
char *new_array_expr = NULL;
*array_expr = '\0';
/* Read to "]" */
while (nexttok) {
new_array_expr = (char *)MALLOC(strlen(array_expr) +
strlen(nexttok) + 1);
/* Roundabout way to do realloc() becase there is no REALLOC() */
strcpy(new_array_expr, array_expr);
strcat(new_array_expr, nexttok);
FREE(array_expr);
array_expr = new_array_expr;
if (strchr(nexttok, ']')) break;
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
}
if (!nexttok) {
Printf("Unterminated array in assignment %s\n", array_expr);
}
}
if (((aptr == NULL) && (GetBusTok(&wb) == 0)) ||
((aptr != NULL) && (GetBus(aptr, &wb) == 0))) {
if (aptr != NULL) { if (aptr != NULL) {
*aptr = '\0'; *aptr = '\0';
/* Find object of first net in bus */ /* Find object of first net in bus */
@ -1965,15 +1789,6 @@ skip_endmodule:
} }
else { else {
lhs = LookupObject(nexttok, CurrentCell); lhs = LookupObject(nexttok, CurrentCell);
/* Handle the case in which an assignment is made
* without first declaring a wire for the signal,
* which is considered valid syntax (patch by
* Sylvain Munaut).
*/
if (lhs == NULL) {
Node(nexttok);
lhs = LookupObject(nexttok, CurrentCell);
}
strcpy(noderoot, nexttok); strcpy(noderoot, nexttok);
} }
SkipTokComments(VLOG_DELIMITERS); SkipTokComments(VLOG_DELIMITERS);
@ -1989,8 +1804,7 @@ skip_endmodule:
// Allowed uses of "assign" for netlists: // Allowed uses of "assign" for netlists:
// "assign a = b" joins two nets. // "assign a = b" joins two nets.
// "assign a = {b, c, ...}" creates a bus from components. // "assign a = {b, c, ...}" creates a bus from components.
// "assign" using if-else constructs or bit shifts. // "assign" using any boolean arithmetic is not structural verilog.
// ("assign" using any other boolean arithmetic is not structural verilog.)
// "assign a = {x{b}}" creates a bus by repeating a component. // "assign a = {x{b}}" creates a bus by repeating a component.
if (nexttok && match(nexttok, "=")) { if (nexttok && match(nexttok, "=")) {
@ -2023,9 +1837,8 @@ skip_endmodule:
break; break;
} }
else { else {
if (GetBusTok(&wb2) == 0) {
char *aptr = strvchr(nexttok, '['); char *aptr = strvchr(nexttok, '[');
if (((aptr == NULL) && (GetBusTok(&wb2) == 0)) ||
((aptr != NULL) && (GetBus(aptr, &wb2) == 0))) {
j = wb2.start; j = wb2.start;
if (aptr != NULL) { if (aptr != NULL) {
*aptr = '\0'; *aptr = '\0';
@ -2085,21 +1898,12 @@ skip_endmodule:
if (i != -1) if (i != -1)
snprintf(nodename, MAX_STR_LEN, "%s[%d]", noderoot, i); snprintf(nodename, MAX_STR_LEN, "%s[%d]", noderoot, i);
else if (lhs != NULL) else
strncpy(nodename, lhs->name, MAX_STR_LEN - 1); strncpy(nodename, lhs->name, MAX_STR_LEN - 1);
else {
Printf("Error: Improper node name \"%s\".\n", noderoot);
goto skip_endmodule;
}
if (j != -1) if (j != -1)
snprintf(assignname, MAX_STR_LEN, "%s[%d]", assignroot, j); snprintf(assignname, MAX_STR_LEN, "%s[%d]", assignroot, j);
else if (rhs != NULL) else
strncpy(assignname, rhs->name, MAX_STR_LEN - 1); strncpy(assignname, rhs->name, MAX_STR_LEN - 1);
else {
Printf("Error: Improper assignment name \"%s\".\n",
assignroot);
goto skip_endmodule;
}
join(nodename, assignname); join(nodename, assignname);
@ -2251,19 +2055,6 @@ nextinst:
} }
SkipTokComments(VLOG_DELIMITERS); SkipTokComments(VLOG_DELIMITERS);
} }
else if (loop.loopvar != NULL) {
/* Instances created within a generate block for loop have an
* implicit array
*/
int loopval;
struct property *klr;
klr = (struct property *)HashLookup(loop.loopvar, &verilogparams);
loopval = klr->pdefault.ival;
arraystart = arrayend = loopval;
sprintf(instancename + strlen(instancename), "[%d]", loopval);
}
if (match(nexttok, "(")) { if (match(nexttok, "(")) {
char savetok = (char)0; char savetok = (char)0;
@ -2326,19 +2117,7 @@ nextinst:
strcat(new_wire_bundle, nexttok); strcat(new_wire_bundle, nexttok);
FREE(wire_bundle); FREE(wire_bundle);
wire_bundle = new_wire_bundle; wire_bundle = new_wire_bundle;
if (!strcmp(nexttok, "}")) if (!strcmp(nexttok, "}")) break;
{
/* If a "bundle" has only one component, then it is
* not really a bundle and should be treated as a
* single wire.
*/
if (strchr(wire_bundle, ',') == NULL) {
int blen = strlen(wire_bundle + 1) - 1;
memmove(wire_bundle, wire_bundle + 1, blen);
*(wire_bundle + blen) = '\0';
}
break;
}
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS); SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
} }
if (!nexttok) { if (!nexttok) {
@ -2714,7 +2493,6 @@ nextinst:
char *brackptr; char *brackptr;
int j; int j;
char locinst[MAX_STR_LEN]; char locinst[MAX_STR_LEN];
int arraypos = (arraystart > arrayend) ? arraymax - i : i;
if (i != -1) if (i != -1)
sprintf(locinst, "%s[%d]", instancename, i); sprintf(locinst, "%s[%d]", instancename, i);
@ -2751,8 +2529,7 @@ nextinst:
if (scan == NULL) { if (scan == NULL) {
char localnet[MAX_STR_LEN]; char localnet[MAX_STR_LEN];
/* Assume an implicit unconnected pin, unless there are no pins */ /* Assume an implicit unconnected pin */
if (strcmp(obpinname, "(no pins)")) {
sprintf(localnet, "_noconnect_%d_", localcount++); sprintf(localnet, "_noconnect_%d_", localcount++);
Node(localnet); Node(localnet);
join(localnet, obptr->name); join(localnet, obptr->name);
@ -2760,17 +2537,9 @@ nextinst:
"Note: Implicit pin %s in instance %s of %s in cell %s\n", "Note: Implicit pin %s in instance %s of %s in cell %s\n",
obpinname, locinst, modulename, CurrentCell->name); obpinname, locinst, modulename, CurrentCell->name);
} }
}
else if (GetBus(scan->net, &wb) == 0) { else if (GetBus(scan->net, &wb) == 0) {
char *bptr2; char *bptr2;
char *scanroot; char *scanroot;
int isbundle = FALSE;
/* Skip over a bundle delimiter */
if (*scan->net == '{') {
scanroot = strsave(scan->net + 1);
isbundle = TRUE;
}
else
scanroot = strsave(scan->net); scanroot = strsave(scan->net);
brackptr = strvchr(scanroot, '['); brackptr = strvchr(scanroot, '[');
if (brackptr) *brackptr = '\0'; if (brackptr) *brackptr = '\0';
@ -2804,7 +2573,6 @@ nextinst:
else { else {
// Instance must be an array // Instance must be an array
char netname[MAX_STR_LEN]; char netname[MAX_STR_LEN];
char *spos = scanroot;
int slice, portlen, siglen; int slice, portlen, siglen;
/* Get the array size of the port for bit slicing */ /* Get the array size of the port for bit slicing */
@ -2816,26 +2584,6 @@ nextinst:
if (siglen < 0) siglen = -siglen; if (siglen < 0) siglen = -siglen;
siglen++; siglen++;
// If this is a bundle, then count out to the current
// slice and read off the index. NOTE: Need to
// handle multiple bits per bundle entry!
if (isbundle) {
int j;
if (brackptr) *brackptr = '[';
for (j = 0; j < arraypos * portlen; j++) {
spos = strvchr(spos, ',');
if (spos == NULL) break;
spos++;
}
if (spos != NULL) {
brackptr = strvchr(spos, '[');
*brackptr = '\0';
sscanf(brackptr + 1, "%d", &slice);
}
else spos = scanroot; /* should emit an error here */
}
else { /* not a bundle */
// If signal array is smaller than the portlength * // If signal array is smaller than the portlength *
// length of instance array, then the signal wraps. // length of instance array, then the signal wraps.
@ -2855,10 +2603,8 @@ nextinst:
slice = wb.start + (arraystart + i) * portlen; slice = wb.start + (arraystart + i) * portlen;
while (slice > wb2.end) slice -= siglen; while (slice > wb2.end) slice -= siglen;
} }
spos = scanroot;
}
sprintf(netname, "%s[%d]", spos, slice); sprintf(netname, "%s[%d]", scanroot, slice);
if (LookupObject(netname, CurrentCell) == NULL) Node(netname); if (LookupObject(netname, CurrentCell) == NULL) Node(netname);
join(netname, obptr->name); join(netname, obptr->name);
} }
@ -3043,25 +2789,18 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
hashfunc = hashcase; hashfunc = hashcase;
} }
if ((hashfilep != -1) && (hashfilep != *fnum)) { if ((hashfile != -1) && (hashfile != *fnum)) {
/* Started a new file, so remove all the parameters */ /* Started a new file, so remove all the parameters and definitions */
RecurseHashTable(&verilogparams, freeprop); RecurseHashTable(&verilogparams, freeprop);
HashKill(&verilogparams); HashKill(&verilogparams);
hashfilep = -1;
}
if ((hashfiled != -1) && (hashfiled != *fnum)) {
/* Started a new file, so remove all the definitions */
RecurseHashTable(&verilogdefs, freeprop); RecurseHashTable(&verilogdefs, freeprop);
HashKill(&verilogdefs); HashKill(&verilogdefs);
hashfiled = -1; hashfile = -1;
} }
if (hashfilep == -1) { if (hashfile == -1) {
InitializeHashTable(&verilogparams, OBJHASHSIZE); InitializeHashTable(&verilogparams, OBJHASHSIZE);
hashfilep = filenum;
}
if (hashfiled == -1) {
InitializeHashTable(&verilogdefs, OBJHASHSIZE); InitializeHashTable(&verilogdefs, OBJHASHSIZE);
hashfiled = filenum; hashfile = *fnum;
} }
definitions = &verilogdefs; definitions = &verilogdefs;

1091
scripts/config.guess vendored

File diff suppressed because it is too large Load Diff

2911
scripts/config.sub vendored

File diff suppressed because it is too large Load Diff

53
scripts/configure vendored
View File

@ -668,6 +668,7 @@ XMKMF
HAVE_PYTHON3 HAVE_PYTHON3
EGREP EGREP
GREP GREP
M4
RANLIB RANLIB
INSTALL_DATA INSTALL_DATA
INSTALL_SCRIPT INSTALL_SCRIPT
@ -3701,6 +3702,56 @@ else
fi fi
for ac_prog in gm4 gnum4 m4
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_M4+:} false; then :
$as_echo_n "(cached) " >&6
else
case $M4 in
[\\/]* | ?:[\\/]*)
ac_cv_path_M4="$M4" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_M4="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
M4=$ac_cv_path_M4
if test -n "$M4"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $M4" >&5
$as_echo "$M4" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$M4" && break
done
test -n "$M4" || M4="no"
if test x$M4 = xno; then
as_fn_error $? "M4 is required" "$LINENO" 5
fi
if test "$CPP" = "$CC -E" ; then if test "$CPP" = "$CC -E" ; then
CPP="$CPP -x c" CPP="$CPP -x c"
@ -6251,7 +6302,7 @@ fi
*darwin*) *darwin*)
SHDLIB_EXT=".dylib" SHDLIB_EXT=".dylib"
LDDL_FLAGS="-dynamiclib -undefined dynamic_lookup" LDDL_FLAGS="-dynamiclib -flat_namespace -undefined suppress -noprebind"
LDFLAGS="${LDFLAGS} ${LIB_SPECS}" LDFLAGS="${LDFLAGS} ${LIB_SPECS}"
CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common" CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common"
;; ;;

View File

@ -26,6 +26,12 @@ AC_ISC_POSIX
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PROG_RANLIB AC_PROG_RANLIB
dnl GNU M4 is preferred due to some of the option switches.
AC_PATH_PROGS([M4], [gm4 gnum4 m4], [no])
if test x$M4 = xno; then
AC_MSG_ERROR([M4 is required])
fi
dnl check size of pointer for correct behavior on 64-bit systems dnl check size of pointer for correct behavior on 64-bit systems
dnl If the C preprocessor is GCC, we need to force the flag to dnl If the C preprocessor is GCC, we need to force the flag to
dnl assert that input files are of type C, or else the preprocessing dnl assert that input files are of type C, or else the preprocessing
@ -1027,7 +1033,7 @@ fi
*darwin*) *darwin*)
SHDLIB_EXT=".dylib" SHDLIB_EXT=".dylib"
LDDL_FLAGS="-dynamiclib -undefined dynamic_lookup" LDDL_FLAGS="-dynamiclib -flat_namespace -undefined suppress -noprebind"
LDFLAGS="${LDFLAGS} ${LIB_SPECS}" LDFLAGS="${LDFLAGS} ${LIB_SPECS}"
CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common" CFLAGS="${CFLAGS} ${X_CFLAGS} ${INC_SPECS} -I/sw/include -fno-common"
;; ;;

View File

@ -68,7 +68,6 @@ LIB_SPECS = @LIB_SPECS@
LIB_SPECS_NOSTUB = @LIB_SPECS_NOSTUB@ LIB_SPECS_NOSTUB = @LIB_SPECS_NOSTUB@
WISH_EXE = @WISH_EXE@ WISH_EXE = @WISH_EXE@
TCL_LIB_DIR = @TCL_LIB_DIR@ TCL_LIB_DIR = @TCL_LIB_DIR@
EXTRA_CFLAGS =
CC = @CC@ CC = @CC@
CPP = @CPP@ CPP = @CPP@
@ -77,7 +76,7 @@ CXX = @CXX@
CPPFLAGS = -I. -I${NETGENDIR} @CPPFLAGS@ CPPFLAGS = -I. -I${NETGENDIR} @CPPFLAGS@
DFLAGS = @extra_defs@ @stub_defs@ @DEFS@ -DSHDLIB_EXT=\"@SHDLIB_EXT@\" -DNDEBUG DFLAGS = @extra_defs@ @stub_defs@ @DEFS@ -DSHDLIB_EXT=\"@SHDLIB_EXT@\" -DNDEBUG
DFLAGS_NOSTUB = @extra_defs@ @DEFS@ -DSHDLIB_EXT=\"@SHDLIB_EXT@\" -DNDEBUG DFLAGS_NOSTUB = @extra_defs@ @DEFS@ -DSHDLIB_EXT=\"@SHDLIB_EXT@\" -DNDEBUG
CFLAGS = @CFLAGS@ @SHLIB_CFLAGS@ @INC_SPECS@ ${EXTRA_CFLAGS} CFLAGS = @CFLAGS@ @SHLIB_CFLAGS@ @INC_SPECS@
DEPEND_FILE = Depend DEPEND_FILE = Depend
DEPEND_FLAG = @DEPEND_FLAG@ DEPEND_FLAG = @DEPEND_FLAG@

View File

@ -429,7 +429,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set file1 $name1 set file1 $name1
set cell1 $name1 set cell1 $name1
} }
puts stdout "Reading netlist file $file1 for $name1" puts stdout "Reading netlist file $file1"
set fnum1 [netgen::readnet $file1] set fnum1 [netgen::readnet $file1]
} else { } else {
set cell1 [lindex $flist1 0] set cell1 [lindex $flist1 0]
@ -446,7 +446,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set file2 $name2 set file2 $name2
set cell2 $name2 set cell2 $name2
} }
puts stdout "Reading netlist file $file2 for $name2" puts stdout "Reading netlist file $file2"
set fnum2 [netgen::readnet $file2] set fnum2 [netgen::readnet $file2]
} else { } else {
set cell2 [lindex $flist2 0] set cell2 [lindex $flist2 0]
@ -461,7 +461,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
} }
set clist1 [cells list $fnum1] set clist1 [cells list $fnum1]
set cidx [lsearch -exact $clist1 $cell1] set cidx [lsearch -regexp $clist1 ^$cell1$]
if {$cidx < 0} { if {$cidx < 0} {
puts stderr "Cannot find cell $cell1 in file $file1" puts stderr "Cannot find cell $cell1 in file $file1"
return return
@ -469,7 +469,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set cell1 [lindex $clist1 $cidx] set cell1 [lindex $clist1 $cidx]
} }
set clist2 [cells list $fnum2] set clist2 [cells list $fnum2]
set cidx [lsearch -exact $clist2 $cell2] set cidx [lsearch -regexp $clist2 ^$cell2$]
if {$cidx < 0} { if {$cidx < 0} {
puts stderr "Cannot find cell $cell2 in file $file2" puts stderr "Cannot find cell $cell2 in file $file2"
return return
@ -477,18 +477,6 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set cell2 [lindex $clist2 $cidx] set cell2 [lindex $clist2 $cidx]
} }
# The "noflat" list is non-file-specific, so run on each file.
foreach cell $noflat {
set cidx [lsearch -regexp $clist1 ^$cell$]
if {$cidx >= 0} {
netgen::flatten prohibit "$fnum1 $cell"
}
set cidx [lsearch -regexp $clist2 ^$cell$]
if {$cidx >= 0} {
netgen::flatten prohibit "$fnum2 $cell"
}
}
netgen::compare assign "$fnum1 $cell1" "$fnum2 $cell2" netgen::compare assign "$fnum1 $cell1" "$fnum2 $cell2"
if {$setupfile == ""} { if {$setupfile == ""} {
@ -516,14 +504,6 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
} }
} }
close $fsetup close $fsetup
if {$command != {}} {
# Incomplete command. Evaluate it to get a meaningful error message
if {[catch {uplevel 1 [list namespace eval netgen $command]} msg]} {
set msg [string trimright $msg "\n"]
puts stderr "Error $setupfile:$sline (ignoring), $msg"
incr perrors
}
}
} else { } else {
puts stdout "Error: Cannot read the setup file $setupfile" puts stdout "Error: Cannot read the setup file $setupfile"
} }
@ -614,9 +594,6 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
lappend properr [lindex $endval 0] lappend properr [lindex $endval 0]
} elseif {$uresult == -2} { ;# unmatched pins } elseif {$uresult == -2} { ;# unmatched pins
set doCheckFlatten 1 set doCheckFlatten 1
} elseif {$uresult == -4} { ;# unmatched pins and properties
lappend properr [lindex $endval 0]
set doCheckFlatten 1
} }
} else { } else {
# not equivalent # not equivalent
@ -678,11 +655,6 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
} }
} elseif {[netgen::print queue] == {} && $result == 0} { } elseif {[netgen::print queue] == {} && $result == 0} {
set pinMismatch 1 set pinMismatch 1
} else {
# This assumes that proxy pins are added correctly. Previously,
# that was not trusted, and so an initial pin mismatch would
# always force subcells to be flattened.
set doFlatten 0
} }
} }
if {$doFlatten} { if {$doFlatten} {
@ -769,19 +741,6 @@ set auto_noexec 1 ;# don't EVER call UNIX commands w/o "shell" in front
# Cross-Application section # Cross-Application section
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# For use with open_pdks, set PDK_ROOT from the environment. If no
# such environment variable exists, check some common locations.
if {[catch {set PDK_ROOT $::env(PDK_ROOT)}]} {
if {[file isdir /usr/local/share/pdk] == 1} {
set PDK_ROOT /usr/local/share/pdk
} elseif {[file isdir /usr/share/pdk] == 1} {
set PDK_ROOT /usr/share/pdk
} elseif {[file isdir /foss/pdk] == 1} {
set PDK_ROOT /foss/pdk
}
}
# Setup IRSIM assuming that the Tcl version is installed. # Setup IRSIM assuming that the Tcl version is installed.
# We do not need to rename procedure irsim to NULL because it is # We do not need to rename procedure irsim to NULL because it is
# redefined in a script, which simply overwrites the original. # redefined in a script, which simply overwrites the original.

View File

@ -21,8 +21,6 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> /* for getenv */ #include <stdlib.h> /* for getenv */
#include <string.h> #include <string.h>
#include <strings.h>
#include <stdarg.h> /* for va_list */
#include <tcl.h> #include <tcl.h>
@ -45,14 +43,14 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define FALSE 0 #define FALSE 0
#endif #endif
#if TCL_MAJOR_VERSION < 9
typedef int Tcl_Size;
#endif
/*-----------------------*/ /*-----------------------*/
/* Tcl 8.4 compatibility */ /* Tcl 8.4 compatibility */
/*-----------------------*/ /*-----------------------*/
#ifndef CONST84
#define CONST84
#endif
Tcl_Interp *netgeninterp; Tcl_Interp *netgeninterp;
Tcl_Interp *consoleinterp; Tcl_Interp *consoleinterp;
int ColumnBase = 0; int ColumnBase = 0;
@ -62,47 +60,47 @@ extern int PropertyErrorDetected;
/* Function prototypes for all Tcl command callbacks */ /* Function prototypes for all Tcl command callbacks */
int _netgen_readnet(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_readnet(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_readlib(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_readlib(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_canonical(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_canonical(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_writenet(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_writenet(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_flatten(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_flatten(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_nodes(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_nodes(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_elements(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_elements(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_debug(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_debug(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_protochip(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_protochip(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_instances(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_instances(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_contents(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_contents(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_describe(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_describe(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_cells(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_cells(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_ports(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_ports(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_model(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_model(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_leaves(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_leaves(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_quit(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_quit(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_reinit(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_reinit(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_log(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_log(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
#ifdef HAVE_MALLINFO #ifdef HAVE_MALLINFO
int _netgen_printmem(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_printmem(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
#endif #endif
int _netgen_help(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netgen_help(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_matching(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_matching(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_compare(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_compare(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_iterate(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_iterate(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_summary(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_summary(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_print(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_print(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_format(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_format(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_run(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_run(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_verify(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_verify(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_automorphs(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_automorphs(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_equate(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_equate(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_ignore(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_ignore(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_permute(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_permute(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_property(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_property(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_exhaustive(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_exhaustive(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_symmetry(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_symmetry(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_restart(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_restart(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_global(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_global(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_convert(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]); int _netcmp_convert(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
typedef struct _Cmd { typedef struct _Cmd {
char *name; char *name;
@ -289,7 +287,7 @@ GetTopCell(int fnum)
int int
CommonGetFilenameOrFile(Tcl_Interp *interp, Tcl_Obj *fobj, int *fnumptr) CommonGetFilenameOrFile(Tcl_Interp *interp, Tcl_Obj *fobj, int *fnumptr)
{ {
int result; int result, llen;
int fnum, ftest; int fnum, ftest;
char *filename; char *filename;
struct nlist *tp; struct nlist *tp;
@ -372,8 +370,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
struct nlist **tpr, int *fnumptr) struct nlist **tpr, int *fnumptr)
{ {
Tcl_Obj *tobj, *fobj; Tcl_Obj *tobj, *fobj;
int result; int result, llen;
Tcl_Size llen;
int fnum, ftest, index; int fnum, ftest, index;
char *filename, *cellname; char *filename, *cellname;
struct nlist *tp, *tp2; struct nlist *tp, *tp2;
@ -402,7 +399,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
Tcl_ResetResult(interp); Tcl_ResetResult(interp);
/* Is 1st argument a special keyword? */ /* Is 1st argument a special keyword? */
if (Tcl_GetIndexFromObj(interp, tobj, (const char **)suboptions, if (Tcl_GetIndexFromObj(interp, tobj, (CONST84 char **)suboptions,
"special", 0, &index) == TCL_OK) { "special", 0, &index) == TCL_OK) {
switch (index) { switch (index) {
case CIRCUIT1_IDX: case CIRCUIT1_IDX:
@ -458,7 +455,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
/* Check if 2nd item is a reserved keyword */ /* Check if 2nd item is a reserved keyword */
if (Tcl_GetIndexFromObj(interp, fobj, if (Tcl_GetIndexFromObj(interp, fobj,
(const char **)suboptions, (CONST84 char **)suboptions,
"special", 0, &index) == TCL_OK) { "special", 0, &index) == TCL_OK) {
switch (index) { switch (index) {
case CIRCUIT1_IDX: case CIRCUIT1_IDX:
@ -583,7 +580,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
} else { } else {
/* Only one name given; check if it matches subOption */ /* Only one name given; check if it matches subOption */
if (Tcl_GetIndexFromObj(interp, objv, (const char **)suboptions, if (Tcl_GetIndexFromObj(interp, objv, (CONST84 char **)suboptions,
"special", 0, &index) == TCL_OK) { "special", 0, &index) == TCL_OK) {
switch (index) { switch (index) {
@ -668,7 +665,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
int int
_netgen_canonical(ClientData clientData, _netgen_canonical(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
int result; int result;
struct nlist *np; struct nlist *np;
@ -707,14 +704,14 @@ _netgen_canonical(ClientData clientData,
int int
_netgen_readnet(ClientData clientData, _netgen_readnet(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *formats[] = { char *formats[] = {
"automatic", "ext", "extflat", "sim", "prm", "ntk", "spice", "automatic", "ext", "extflat", "sim", "ntk", "spice",
"verilog", "netgen", "actel", "xilinx", NULL "verilog", "netgen", "actel", "xilinx", NULL
}; };
enum FormatIdx { enum FormatIdx {
AUTO_IDX, EXT_IDX, EXTFLAT_IDX, SIM_IDX, PRM_IDX, NTK_IDX, AUTO_IDX, EXT_IDX, EXTFLAT_IDX, SIM_IDX, NTK_IDX,
SPICE_IDX, VERILOG_IDX, NETGEN_IDX, ACTEL_IDX, XILINX_IDX SPICE_IDX, VERILOG_IDX, NETGEN_IDX, ACTEL_IDX, XILINX_IDX
}; };
struct nlist *tc; struct nlist *tc;
@ -744,7 +741,7 @@ _netgen_readnet(ClientData clientData,
return TCL_ERROR; return TCL_ERROR;
} }
else if (objc > 1) { else if (objc > 1) {
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)formats, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)formats,
"format", 0, &index) != TCL_OK) { "format", 0, &index) != TCL_OK) {
if (objc == 3) if (objc == 3)
@ -810,9 +807,6 @@ _netgen_readnet(ClientData clientData,
case SIM_IDX: case SIM_IDX:
retstr = ReadSim(savstr, &filenum); retstr = ReadSim(savstr, &filenum);
break; break;
case PRM_IDX:
retstr = ReadPrm(savstr, &filenum);
break;
case NTK_IDX: case NTK_IDX:
retstr = ReadNtk(savstr, &filenum); retstr = ReadNtk(savstr, &filenum);
break; break;
@ -853,7 +847,7 @@ _netgen_readnet(ClientData clientData,
int int
_netgen_readlib(ClientData clientData, _netgen_readlib(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *formats[] = { char *formats[] = {
"actel", "spice", "xilinx", NULL "actel", "spice", "xilinx", NULL
@ -886,7 +880,7 @@ _netgen_readlib(ClientData clientData,
Tcl_WrongNumArgs(interp, 1, objv, "format [file]"); Tcl_WrongNumArgs(interp, 1, objv, "format [file]");
return TCL_ERROR; return TCL_ERROR;
} }
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)formats, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)formats,
"format", 0, &index) != TCL_OK) { "format", 0, &index) != TCL_OK) {
return TCL_ERROR; return TCL_ERROR;
} }
@ -933,7 +927,7 @@ _netgen_readlib(ClientData clientData,
int int
_netgen_writenet(ClientData clientData, _netgen_writenet(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *formats[] = { char *formats[] = {
"ext", "sim", "ntk", "actel", "ext", "sim", "ntk", "actel",
@ -952,7 +946,7 @@ _netgen_writenet(ClientData clientData,
Tcl_WrongNumArgs(interp, 1, objv, "format file"); Tcl_WrongNumArgs(interp, 1, objv, "format file");
return TCL_ERROR; return TCL_ERROR;
} }
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)formats, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)formats,
"format", 0, &index) != TCL_OK) { "format", 0, &index) != TCL_OK) {
return TCL_ERROR; return TCL_ERROR;
} }
@ -1020,11 +1014,11 @@ _netgen_writenet(ClientData clientData,
int int
_netgen_flatten(ClientData clientData, _netgen_flatten(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *repstr, *file; char *repstr, *file;
int result, filenum; int result, llen, filenum;
struct nlist *tp, *tp2, *tptop; struct nlist *tp, *tp2;
if ((objc < 2) || (objc > 4)) { if ((objc < 2) || (objc > 4)) {
Tcl_WrongNumArgs(interp, 1, objv, "?class? valid_cellname"); Tcl_WrongNumArgs(interp, 1, objv, "?class? valid_cellname");
@ -1038,7 +1032,7 @@ _netgen_flatten(ClientData clientData,
if (objc >= 3) { if (objc >= 3) {
char *argv = Tcl_GetString(objv[1]); char *argv = Tcl_GetString(objv[1]);
if (!strcmp(argv, "class")) { if (!strcmp(argv, "class")) {
tptop = GetTopCell(filenum); tp = GetTopCell(filenum);
if (objc == 4) { if (objc == 4) {
int numflat; int numflat;
@ -1049,7 +1043,7 @@ _netgen_flatten(ClientData clientData,
} }
else { else {
Printf("Flattening instances of %s in cell %s within file %s\n", Printf("Flattening instances of %s in cell %s within file %s\n",
repstr, tp2->name, tptop->name); repstr, tp2->name, tp->name);
numflat = flattenInstancesOf(tp2->name, filenum, repstr); numflat = flattenInstancesOf(tp2->name, filenum, repstr);
if (numflat == 0) { if (numflat == 0) {
Tcl_SetResult(interp, "No instances found to flatten.", NULL); Tcl_SetResult(interp, "No instances found to flatten.", NULL);
@ -1058,20 +1052,16 @@ _netgen_flatten(ClientData clientData,
} }
} }
else { else {
Printf("Flattening instances of %s in file %s\n", repstr, tptop->name); Printf("Flattening instances of %s in file %s\n", repstr, tp->name);
FlattenInstancesOf(repstr, filenum); FlattenInstancesOf(repstr, filenum);
} }
} }
else if (!strcmp(argv, "prohibit") || !strcmp(argv, "deny")) { else if (!strcmp(argv, "prohibit") || !strcmp(argv, "deny")) {
tptop = GetTopCell(filenum); tp = GetTopCell(filenum);
if (tp == NULL) Printf("Will not flatten instances of %s in file %s\n", repstr, tp->name);
Printf("Error: Cell %s does not exist.\n", repstr);
else {
Printf("Will not flatten instances of %s in file %s\n", repstr, tptop->name);
/* Mark cell as placeholder so it will not be flattened */ /* Mark cell as placeholder so it will not be flattened */
tp->flags |= CELL_PLACEHOLDER; tp->flags |= CELL_PLACEHOLDER;
} }
}
else { else {
Tcl_WrongNumArgs(interp, 1, objv, "class valid_cellname"); Tcl_WrongNumArgs(interp, 1, objv, "class valid_cellname");
return TCL_ERROR; return TCL_ERROR;
@ -1094,7 +1084,7 @@ _netgen_flatten(ClientData clientData,
int int
_netgen_nodes(ClientData clientData, _netgen_nodes(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *estr = NULL, *istr = NULL, *cstr, *fstr; char *estr = NULL, *istr = NULL, *cstr, *fstr;
char *optstart; char *optstart;
@ -1212,7 +1202,7 @@ _netgen_nodes(ClientData clientData,
int int
_netgen_elements(ClientData clientData, _netgen_elements(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *nstr = NULL, *cstr; char *nstr = NULL, *cstr;
struct objlist * (*ListSave)(); struct objlist * (*ListSave)();
@ -1307,7 +1297,7 @@ _netgen_elements(ClientData clientData,
int int
_netgen_debug(ClientData clientData, _netgen_debug(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *yesno[] = { char *yesno[] = {
"on", "off", NULL "on", "off", NULL
@ -1321,7 +1311,7 @@ _netgen_debug(ClientData clientData,
if (objc == 1) if (objc == 1)
index = YES_IDX; index = YES_IDX;
else { else {
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)yesno, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
"option", 0, &index) != TCL_OK) { "option", 0, &index) != TCL_OK) {
index = CMD_IDX; index = CMD_IDX;
} }
@ -1356,7 +1346,7 @@ _netgen_debug(ClientData clientData,
int int
_netgen_protochip(ClientData clientData, _netgen_protochip(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
if (objc != 1) { if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)"); Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@ -1376,7 +1366,7 @@ _netgen_protochip(ClientData clientData,
int int
_netgen_instances(ClientData clientData, _netgen_instances(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *repstr; char *repstr;
int result; int result;
@ -1406,7 +1396,7 @@ _netgen_instances(ClientData clientData,
int int
_netgen_contents(ClientData clientData, _netgen_contents(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *repstr; char *repstr;
int result; int result;
@ -1435,7 +1425,7 @@ _netgen_contents(ClientData clientData,
int int
_netgen_describe(ClientData clientData, _netgen_describe(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *repstr; char *repstr;
int file = -1; int file = -1;
@ -1465,7 +1455,7 @@ _netgen_describe(ClientData clientData,
int int
_netgen_cells(ClientData clientData, _netgen_cells(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *repstr, *filename = NULL; char *repstr, *filename = NULL;
char *optstart; char *optstart;
@ -1552,7 +1542,7 @@ _netgen_cells(ClientData clientData,
int int
_netgen_model(ClientData clientData, _netgen_model(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
struct nlist *tp, *tp2; struct nlist *tp, *tp2;
char *model, *retclass; char *model, *retclass;
@ -1602,9 +1592,10 @@ _netgen_model(ClientData clientData,
return result; return result;
if (objc == 3) { if (objc == 3) {
nports = NumberOfPorts(tp->name, fnum); model = Tcl_GetString(objv[2]);
nports = NumberOfPorts(model, fnum);
if (Tcl_GetIndexFromObj(interp, objv[2], (const char **)modelclasses, if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)modelclasses,
"class", 0, &index) != TCL_OK) { "class", 0, &index) != TCL_OK) {
return TCL_ERROR; return TCL_ERROR;
} }
@ -1774,7 +1765,7 @@ wrongNumPorts:
int int
_netgen_ports(ClientData clientData, _netgen_ports(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *repstr; char *repstr;
int result; int result;
@ -1804,7 +1795,7 @@ _netgen_ports(ClientData clientData,
int int
_netgen_leaves(ClientData clientData, _netgen_leaves(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *repstr; char *repstr;
int result; int result;
@ -1840,7 +1831,7 @@ _netgen_leaves(ClientData clientData,
int int
_netgen_quit(ClientData clientData, _netgen_quit(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
if (objc != 1) { if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)"); Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@ -1868,7 +1859,7 @@ _netgen_quit(ClientData clientData,
int int
_netgen_reinit(ClientData clientData, _netgen_reinit(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
if (objc != 1) { if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)"); Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@ -1888,7 +1879,7 @@ _netgen_reinit(ClientData clientData,
int int
_netgen_log(ClientData clientData, _netgen_log(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *yesno[] = { char *yesno[] = {
"start", "end", "reset", "suspend", "resume", "file", "echo", "put", NULL "start", "end", "reset", "suspend", "resume", "file", "echo", "put", NULL
@ -1905,7 +1896,7 @@ _netgen_log(ClientData clientData,
index = (LoggingFile) ? RESUME_IDX : START_IDX; index = (LoggingFile) ? RESUME_IDX : START_IDX;
} }
else { else {
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)yesno, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
"option", 0, &index) != TCL_OK) { "option", 0, &index) != TCL_OK) {
return TCL_ERROR; return TCL_ERROR;
} }
@ -2032,7 +2023,7 @@ _netgen_log(ClientData clientData,
int int
_netgen_printmem(ClientData clientData, _netgen_printmem(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
if (objc != 1) { if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)"); Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@ -2054,7 +2045,7 @@ _netgen_printmem(ClientData clientData,
int int
_netcmp_format(ClientData clientData, _netcmp_format(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
int col1_width = 41, col2_width = 41; int col1_width = 41, col2_width = 41;
@ -2115,13 +2106,13 @@ _netcmp_format(ClientData clientData,
int int
_netcmp_compare(ClientData clientData, _netcmp_compare(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *name1, *name2, *file1, *file2, *optstart; char *name1, *name2, *file1, *file2, *optstart;
int fnum1, fnum2, dolist = 0; int fnum1, fnum2, dolist = 0;
int dohierarchy = FALSE; int dohierarchy = FALSE;
int assignonly = FALSE; int assignonly = FALSE;
int argstart = 1, qresult, result; int argstart = 1, qresult, llen, result;
int hascontents1, hascontents2; int hascontents1, hascontents2;
struct Correspond *nextcomp; struct Correspond *nextcomp;
struct nlist *tp1 = NULL, *tp2 = NULL; struct nlist *tp1 = NULL, *tp2 = NULL;
@ -2292,7 +2283,7 @@ _netcmp_compare(ClientData clientData,
int int
_netcmp_iterate(ClientData clientData, _netcmp_iterate(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
if (objc != 1) { if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)"); Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@ -2316,7 +2307,7 @@ _netcmp_iterate(ClientData clientData,
int int
_netcmp_summary(ClientData clientData, _netcmp_summary(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *options[] = { char *options[] = {
"nodes", "elements", NULL "nodes", "elements", NULL
@ -2331,7 +2322,7 @@ _netcmp_summary(ClientData clientData,
return TCL_ERROR; return TCL_ERROR;
} }
if (objc == 2) { if (objc == 2) {
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
"option", 0, &index) != TCL_OK) { "option", 0, &index) != TCL_OK) {
return TCL_ERROR; return TCL_ERROR;
} }
@ -2357,7 +2348,7 @@ _netcmp_summary(ClientData clientData,
int int
_netcmp_print(ClientData clientData, _netcmp_print(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *options[] = { char *options[] = {
"nodes", "elements", "queue", NULL "nodes", "elements", "queue", NULL
@ -2395,16 +2386,16 @@ _netcmp_print(ClientData clientData,
return TCL_ERROR; return TCL_ERROR;
} }
if (objc >= 2) { if (objc >= 2) {
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
"option", 0, &index) != TCL_OK) { "option", 0, &index) != TCL_OK) {
if ((objc == 2) && (Tcl_GetIndexFromObj(interp, objv[1], if ((objc == 2) && (Tcl_GetIndexFromObj(interp, objv[1],
(const char **)classes, "class", 0, &class) != TCL_OK)) { (CONST84 char **)classes, "class", 0, &class) != TCL_OK)) {
return TCL_ERROR; return TCL_ERROR;
} }
} }
} }
if (objc == 3 && index != QUEUE_IDX) { if (objc == 3 && index != QUEUE_IDX) {
if (Tcl_GetIndexFromObj(interp, objv[2], (const char **)classes, if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)classes,
"class", 0, &class) != TCL_OK) { "class", 0, &class) != TCL_OK) {
return TCL_ERROR; return TCL_ERROR;
} }
@ -2448,7 +2439,7 @@ _netcmp_print(ClientData clientData,
int int
_netcmp_run(ClientData clientData, _netcmp_run(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *options[] = { char *options[] = {
"converge", "resolve", NULL "converge", "resolve", NULL
@ -2475,7 +2466,7 @@ _netcmp_run(ClientData clientData,
if (objc == 1) if (objc == 1)
index = RESOLVE_IDX; index = RESOLVE_IDX;
else { else {
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
"option", 0, &index) != TCL_OK) { "option", 0, &index) != TCL_OK) {
return TCL_ERROR; return TCL_ERROR;
} }
@ -2519,13 +2510,7 @@ _netcmp_run(ClientData clientData,
if (automorphisms > 0) { if (automorphisms > 0) {
// Next, attempt to resolve automorphisms uniquely by // Next, attempt to resolve automorphisms uniquely by
// using the pin names // using the pin names
automorphisms = ResolveAutomorphsByPin(FALSE); automorphisms = ResolveAutomorphsByPin();
}
if (automorphisms > 0) {
// Next, attempt to resolve automorphisms uniquely by
// using the net names (should only be done after
// resolving by pin).
automorphisms = ResolveAutomorphsByPin(TRUE);
} }
if (automorphisms > 0) { if (automorphisms > 0) {
// Anything left is truly indistinguishable // Anything left is truly indistinguishable
@ -2535,16 +2520,8 @@ _netcmp_run(ClientData clientData,
if (automorphisms == -1) if (automorphisms == -1)
Fprintf(stdout, "Netlists do not match.\n"); Fprintf(stdout, "Netlists do not match.\n");
else if (automorphisms == -2) { else if (automorphisms == -2)
Fprintf(stdout, "Netlists match uniquely with port"); Fprintf(stdout, "Netlists match uniquely with port errors.\n");
if (PropertyErrorDetected) {
Fprintf(stdout, " and property errors.\n");
PrintPropertyResults(dolist);
}
else {
Fprintf(stdout, " errors.\n");
}
}
else { else {
if (automorphisms == 0) if (automorphisms == 0)
Fprintf(stdout, "Netlists match uniquely"); Fprintf(stdout, "Netlists match uniquely");
@ -2579,7 +2556,6 @@ _netcmp_run(ClientData clientData,
/* 0: not verified */ /* 0: not verified */
/* -1: no elements or nodes */ /* -1: no elements or nodes */
/* -3: verified with property error */ /* -3: verified with property error */
/* -4: verified with property and port errors */
/* equiv option */ /* equiv option */
/* -2: pin mismatch */ /* -2: pin mismatch */
/* */ /* */
@ -2592,7 +2568,7 @@ _netcmp_run(ClientData clientData,
int int
_netcmp_verify(ClientData clientData, _netcmp_verify(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *options[] = { char *options[] = {
"nodes", "elements", "properties", "only", "all", "equivalent", "unique", NULL "nodes", "elements", "properties", "only", "all", "equivalent", "unique", NULL
@ -2624,7 +2600,7 @@ _netcmp_verify(ClientData clientData,
return TCL_ERROR; return TCL_ERROR;
} }
if (objc == 2) { if (objc == 2) {
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
"option", 0, &index) != TCL_OK) { "option", 0, &index) != TCL_OK) {
return TCL_ERROR; return TCL_ERROR;
} }
@ -2673,20 +2649,14 @@ _netcmp_verify(ClientData clientData,
disable_interrupt(); disable_interrupt();
if (index == EQUIV_IDX || index == UNIQUE_IDX) if (index == EQUIV_IDX || index == UNIQUE_IDX)
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
else { else
Fprintf(stdout, "Netlists do not match.\n"); Fprintf(stdout, "Netlists do not match.\n");
Fprintf(stdout, "Port matching may fail to disambiguate symmetries.\n");
}
} }
else if (automorphisms == -2) { else if (automorphisms == -2) {
if (index == EQUIV_IDX) if (index == EQUIV_IDX)
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
else if (index == UNIQUE_IDX) { else if (index == UNIQUE_IDX)
if (PropertyErrorDetected == 0)
Tcl_SetObjResult(interp, Tcl_NewIntObj(-2)); Tcl_SetObjResult(interp, Tcl_NewIntObj(-2));
else
Tcl_SetObjResult(interp, Tcl_NewIntObj(-4));
}
else if (index > 0) else if (index > 0)
Fprintf(stdout, "Circuits match uniquely with port errors.\n"); Fprintf(stdout, "Circuits match uniquely with port errors.\n");
} }
@ -2781,7 +2751,7 @@ _netcmp_verify(ClientData clientData,
int int
_netcmp_automorphs(ClientData clientData, _netcmp_automorphs(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
if (objc != 1) { if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)"); Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@ -2802,7 +2772,7 @@ _netcmp_automorphs(ClientData clientData,
int int
_netcmp_convert(ClientData clientData, _netcmp_convert(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *cellname; char *cellname;
int filenum = -1; int filenum = -1;
@ -2832,10 +2802,10 @@ _netcmp_convert(ClientData clientData,
int int
_netcmp_global(ClientData clientData, _netcmp_global(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *filename, *cellname, *pattern; char *filename, *cellname, *pattern;
int numchanged = 0, p, fnum, result; int numchanged = 0, p, fnum, llen, result;
struct nlist *tp; struct nlist *tp;
if (objc < 2) { if (objc < 2) {
@ -2869,7 +2839,7 @@ _netcmp_global(ClientData clientData,
int int
_netcmp_ignore(ClientData clientData, _netcmp_ignore(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *options[] = { char *options[] = {
"class", "shorted", NULL "class", "shorted", NULL
@ -2883,7 +2853,7 @@ _netcmp_ignore(ClientData clientData,
char *name = NULL, *name2 = NULL; char *name = NULL, *name2 = NULL;
if (objc >= 3) { if (objc >= 3) {
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
"option", 0, &index) == TCL_OK) { "option", 0, &index) == TCL_OK) {
objc--; objc--;
objv++; objv++;
@ -2917,7 +2887,7 @@ _netcmp_ignore(ClientData clientData,
int int
_netcmp_equate(ClientData clientData, _netcmp_equate(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *options[] = { char *options[] = {
"nodes", "elements", "classes", "pins", NULL "nodes", "elements", "classes", "pins", NULL
@ -2932,8 +2902,7 @@ _netcmp_equate(ClientData clientData,
struct ElementClass *saveEclass = NULL; struct ElementClass *saveEclass = NULL;
struct NodeClass *saveNclass = NULL; struct NodeClass *saveNclass = NULL;
int file1, file2; int file1, file2;
int i, dolist = 0, doforce = 0, dounique = 0; int i, l1, l2, ltest, lent, dolist = 0, doforce = 0, dounique = 0;
Tcl_Size l1, l2, lent, ltest;
Tcl_Obj *tobj1, *tobj2, *tobj3; Tcl_Obj *tobj1, *tobj2, *tobj3;
while (objc > 1) { while (objc > 1) {
@ -2963,7 +2932,7 @@ _netcmp_equate(ClientData clientData,
return TCL_ERROR; return TCL_ERROR;
} }
else { else {
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
"option", 0, &index) != TCL_OK) { "option", 0, &index) != TCL_OK) {
return TCL_ERROR; return TCL_ERROR;
} }
@ -3432,31 +3401,22 @@ _netcmp_equate(ClientData clientData,
int int
_netcmp_property(ClientData clientData, _netcmp_property(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
int fnum, i; int fnum, i, llen;
struct nlist *tp; struct nlist *tp;
struct property *kl, *kllast, *klnext; struct property *kl, *kllast, *klnext;
Tcl_Obj *tobj1, *tobj2, *tobj3; Tcl_Obj *tobj1, *tobj2, *tobj3;
Tcl_Size llen;
double dval; double dval;
int ival, argstart; int ival, argstart;
char *topoptions[] = {
"default", "series", "serial", "parallel", "topology", NULL
};
enum TopOptionIdx {
TOP_DEFAULT_IDX, TOP_SERIES_IDX, TOP_SERIAL_IDX, TOP_PARALLEL_IDX,
TOP_TOPOLOGY_IDX
};
char *options[] = { char *options[] = {
"add", "create", "remove", "delete", "tolerance", "merge", "serial", "add", "create", "remove", "delete", "tolerance", "merge", "serial",
"series", "parallel", "associate", "derive", NULL "series", "parallel", "associate", "topology", NULL
}; };
enum OptionIdx { enum OptionIdx {
ADD_IDX, CREATE_IDX, REMOVE_IDX, DELETE_IDX, TOLERANCE_IDX, MERGE_IDX, ADD_IDX, CREATE_IDX, REMOVE_IDX, DELETE_IDX, TOLERANCE_IDX, MERGE_IDX,
SERIAL_IDX, SERIES_IDX, PARALLEL_IDX, ASSOCIATE_IDX, DERIVE_IDX SERIAL_IDX, SERIES_IDX, PARALLEL_IDX, ASSOCIATE_IDX, TOPOLOGY_IDX
}; };
int result, index, idx2; int result, index, idx2;
@ -3491,14 +3451,6 @@ _netcmp_property(ClientData clientData,
COMB_NONE_IDX, COMB_PAR_IDX, COMB_ADD_IDX, COMB_CRITICAL_IDX COMB_NONE_IDX, COMB_PAR_IDX, COMB_ADD_IDX, COMB_CRITICAL_IDX
}; };
char *deriveoptions[] = {
"area", "perimeter", NULL
};
enum DeriveOptionIdx {
AREA_IDX, PERIMETER_IDX
};
char *yesno[] = { char *yesno[] = {
"on", "yes", "true", "enable", "allow", "on", "yes", "true", "enable", "allow",
"off", "no", "false", "disable", "prohibit", NULL "off", "no", "false", "disable", "prohibit", NULL
@ -3513,13 +3465,8 @@ _netcmp_property(ClientData clientData,
"strict", "relaxed", NULL "strict", "relaxed", NULL
}; };
/* Don't need to check return value */
index = -1;
Tcl_GetIndexFromObj(interp, objv[1], (const char **)topoptions,
"option", 0, &index);
/* Check for special command "property default" */ /* Check for special command "property default" */
if ((objc == 2) && (index == TOP_DEFAULT_IDX)) { if ((objc == 2) && (!strcmp(Tcl_GetString(objv[1]), "default"))) {
/* For each FET device, do "merge {w add_critical}" and */ /* For each FET device, do "merge {w add_critical}" and */
/* "remove as ad ps pd". This allows parallel devices */ /* "remove as ad ps pd". This allows parallel devices */
@ -3566,7 +3513,7 @@ _netcmp_property(ClientData clientData,
} }
return TCL_OK; return TCL_OK;
} }
else if ((objc == 3) && (index == TOP_PARALLEL_IDX)) { else if ((objc == 3) && (!strcmp(Tcl_GetString(objv[1]), "parallel"))) {
if (!strcmp(Tcl_GetString(objv[2]), "none")) { if (!strcmp(Tcl_GetString(objv[2]), "none")) {
GlobalParallelNone = TRUE; GlobalParallelNone = TRUE;
SetParallelCombine(FALSE); SetParallelCombine(FALSE);
@ -3588,7 +3535,8 @@ _netcmp_property(ClientData clientData,
} }
return TCL_OK; return TCL_OK;
} }
else if ((objc == 3) && ((index == TOP_SERIES_IDX) || (index == TOP_SERIAL_IDX))) { else if ((objc == 3) && ((!strcmp(Tcl_GetString(objv[1]), "series")) ||
(!strcmp(Tcl_GetString(objv[1]), "serial")))) {
if (!strcmp(Tcl_GetString(objv[2]), "none")) { if (!strcmp(Tcl_GetString(objv[2]), "none")) {
SetSeriesCombine(FALSE); SetSeriesCombine(FALSE);
} }
@ -3602,7 +3550,7 @@ _netcmp_property(ClientData clientData,
} }
return TCL_OK; return TCL_OK;
} }
else if ((objc > 1) && (index == TOP_TOPOLOGY_IDX)) { else if ((objc > 1) && (!strcmp(Tcl_GetString(objv[1]), "topology"))) {
if (objc == 2) { if (objc == 2) {
if (ExactTopology) if (ExactTopology)
Tcl_SetResult(interp, "Strict topology property matching.", Tcl_SetResult(interp, "Strict topology property matching.",
@ -3613,7 +3561,7 @@ _netcmp_property(ClientData clientData,
} }
else if (objc == 3) { else if (objc == 3) {
if (Tcl_GetIndexFromObj(interp, objv[2], if (Tcl_GetIndexFromObj(interp, objv[2],
(const char **)topo, (CONST84 char **)topo,
"topology", 0, &idx2) == TCL_OK) { "topology", 0, &idx2) == TCL_OK) {
if (idx2 == 0) if (idx2 == 0)
ExactTopology = TRUE; ExactTopology = TRUE;
@ -3672,7 +3620,7 @@ _netcmp_property(ClientData clientData,
Tcl_SetObjResult(interp, tobj1); Tcl_SetObjResult(interp, tobj1);
} }
else { else {
if (Tcl_GetIndexFromObj(interp, objv[2], (const char **)options, if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)options,
"option", 0, &index) != TCL_OK) { "option", 0, &index) != TCL_OK) {
index = ADD_IDX; index = ADD_IDX;
argstart = 2; argstart = 2;
@ -3705,7 +3653,7 @@ _netcmp_property(ClientData clientData,
// Each value must be a list of two, or a yes/no answer. // Each value must be a list of two, or a yes/no answer.
if (Tcl_GetIndexFromObj(interp, objv[i], if (Tcl_GetIndexFromObj(interp, objv[i],
(const char **)yesno, (CONST84 char **)yesno,
"combine", 0, &idx2) == TCL_OK) { "combine", 0, &idx2) == TCL_OK) {
if (idx2 <= 4) { /* true, enable, etc. */ if (idx2 <= 4) { /* true, enable, etc. */
if (index == SERIAL_IDX || index == SERIES_IDX) if (index == SERIAL_IDX || index == SERIES_IDX)
@ -3737,7 +3685,7 @@ _netcmp_property(ClientData clientData,
if (result != TCL_OK) return result; if (result != TCL_OK) return result;
result = Tcl_GetIndexFromObj(interp, tobj2, result = Tcl_GetIndexFromObj(interp, tobj2,
(const char **)combineoptions, (CONST84 char **)combineoptions,
"combine_type", 0, &idx2); "combine_type", 0, &idx2);
if (result != TCL_OK) return result; if (result != TCL_OK) return result;
@ -3822,7 +3770,7 @@ _netcmp_property(ClientData clientData,
/* {key, type} or {key, tolerance} duplet */ /* {key, type} or {key, tolerance} duplet */
if (Tcl_GetIndexFromObj(interp, tobj2, if (Tcl_GetIndexFromObj(interp, tobj2,
(const char **)suboptions, (CONST84 char **)suboptions,
"type", 0, &idx2) != TCL_OK) { "type", 0, &idx2) != TCL_OK) {
Tcl_ResetResult(interp); Tcl_ResetResult(interp);
if (Tcl_GetDoubleFromObj(interp, tobj2, &dval) if (Tcl_GetDoubleFromObj(interp, tobj2, &dval)
@ -3866,7 +3814,7 @@ _netcmp_property(ClientData clientData,
/* {key, type, tolerance} triplet */ /* {key, type, tolerance} triplet */
if (Tcl_GetIndexFromObj(interp, tobj2, if (Tcl_GetIndexFromObj(interp, tobj2,
(const char **)suboptions, (CONST84 char **)suboptions,
"type", 0, &idx2) != TCL_OK) "type", 0, &idx2) != TCL_OK)
return TCL_ERROR; return TCL_ERROR;
@ -4009,7 +3957,7 @@ _netcmp_property(ClientData clientData,
if (result != TCL_OK) return result; if (result != TCL_OK) return result;
result = Tcl_GetIndexFromObj(interp, tobj2, result = Tcl_GetIndexFromObj(interp, tobj2,
(const char **)mergeoptions, (CONST84 char **)mergeoptions,
"merge_type", 0, &idx2); "merge_type", 0, &idx2);
if (result != TCL_OK) return result; if (result != TCL_OK) return result;
@ -4048,32 +3996,6 @@ _netcmp_property(ClientData clientData,
} }
break; break;
case DERIVE_IDX:
/* Create a derived property. For now, this just creates
* "area" or "perimeter" properties. There may not (?)
* be enough cause to make other ones. Unlike other
* "property" options, this option causes the whole circuit
* database to be searched for the device in question, and
* the new property is added.
*/
if (objc < 6) {
Tcl_WrongNumArgs(interp, 2, objv, "{area|perimeter width length}");
return TCL_ERROR;
}
result = Tcl_GetIndexFromObj(interp, objv[3],
(const char **)deriveoptions,
"area|perimeter", 0, &idx2);
if (result != TCL_OK) return result;
switch (idx2) {
case AREA_IDX:
DeriveAreaProperty(tp, fnum, Tcl_GetString(objv[4]),
Tcl_GetString(objv[5]));
break;
case PERIMETER_IDX:
DerivePerimeterProperty(tp, fnum, Tcl_GetString(objv[4]),
Tcl_GetString(objv[5]));
break;
}
} }
} }
return TCL_OK; return TCL_OK;
@ -4093,7 +4015,7 @@ _netcmp_property(ClientData clientData,
int int
_netcmp_permute(ClientData clientData, _netcmp_permute(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *model, *pin1, *pin2; char *model, *pin1, *pin2;
char *permuteclass[] = { char *permuteclass[] = {
@ -4114,7 +4036,7 @@ _netcmp_permute(ClientData clientData,
index = DEFLT_IDX; index = DEFLT_IDX;
} }
else { else {
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)permuteclass, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)permuteclass,
"permute class", 0, &index) != TCL_OK) { "permute class", 0, &index) != TCL_OK) {
if (objc != 4) { if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv, "?valid_cellname pin1 pin2?"); Tcl_WrongNumArgs(interp, 1, objv, "?valid_cellname pin1 pin2?");
@ -4234,7 +4156,7 @@ _netcmp_permute(ClientData clientData,
int int
_netcmp_symmetry(ClientData clientData, _netcmp_symmetry(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
Printf("Symmetry breaking method has been deprecated.\n"); Printf("Symmetry breaking method has been deprecated.\n");
return TCL_OK; return TCL_OK;
@ -4250,7 +4172,7 @@ _netcmp_symmetry(ClientData clientData,
int int
_netcmp_exhaustive(ClientData clientData, _netcmp_exhaustive(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *yesno[] = { char *yesno[] = {
"on", "off", NULL "on", "off", NULL
@ -4263,7 +4185,7 @@ _netcmp_exhaustive(ClientData clientData,
if (objc == 1) if (objc == 1)
index = -1; index = -1;
else { else {
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)yesno, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
"option", 0, &index) != TCL_OK) "option", 0, &index) != TCL_OK)
return TCL_ERROR; return TCL_ERROR;
} }
@ -4292,7 +4214,7 @@ _netcmp_exhaustive(ClientData clientData,
int int
_netcmp_restart(ClientData clientData, _netcmp_restart(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
if (objc != 1) { if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)"); Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@ -4312,7 +4234,7 @@ _netcmp_restart(ClientData clientData,
int int
_netgen_help(ClientData clientData, _netgen_help(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
int n; int n;
@ -4343,7 +4265,7 @@ _netgen_help(ClientData clientData,
int int
_netcmp_matching(ClientData clientData, _netcmp_matching(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
char *options[] = { char *options[] = {
"nodes", "elements", NULL "nodes", "elements", NULL
@ -4365,7 +4287,7 @@ _netcmp_matching(ClientData clientData,
name = Tcl_GetString(objv[1]); name = Tcl_GetString(objv[1]);
} }
else { else {
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options, if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
"option", 0, &index) != TCL_OK) { "option", 0, &index) != TCL_OK) {
return TCL_ERROR; return TCL_ERROR;
} }
@ -4494,14 +4416,14 @@ void tcl_vprintf(FILE *f, const char *fmt, va_list args_in)
void tcl_stdflush(FILE *f) void tcl_stdflush(FILE *f)
{ {
Tcl_InterpState state; Tcl_SavedResult state;
static char stdstr[] = "::flush stdxxx"; static char stdstr[] = "::flush stdxxx";
char *stdptr = stdstr + 11; char *stdptr = stdstr + 11;
state = Tcl_SaveInterpState(netgeninterp, TCL_OK); Tcl_SaveResult(netgeninterp, &state);
strcpy(stdptr, (f == stderr) ? "err" : "out"); strcpy(stdptr, (f == stderr) ? "err" : "out");
Tcl_Eval(netgeninterp, stdstr); Tcl_Eval(netgeninterp, stdstr);
Tcl_RestoreInterpState(netgeninterp, state); Tcl_RestoreResult(netgeninterp, &state);
} }
/*------------------------------------------------------*/ /*------------------------------------------------------*/
@ -4531,7 +4453,7 @@ char *Tcl_Strdup(const char *s)
/*------------------------------------------------------*/ /*------------------------------------------------------*/
int _tkcon_interrupt(ClientData clientData, int _tkcon_interrupt(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{ {
InterruptPending = 1; InterruptPending = 1;
return TCL_OK; return TCL_OK;
@ -4570,7 +4492,7 @@ int Tclnetgen_Init(Tcl_Interp *interp)
/* Remember the interpreter */ /* Remember the interpreter */
netgeninterp = interp; netgeninterp = interp;
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) return TCL_ERROR; if (Tcl_InitStubs(interp, "8.5", 0) == NULL) return TCL_ERROR;
for (n = 0; netgen_cmds[n].name != NULL; n++) { for (n = 0; netgen_cmds[n].name != NULL; n++) {
sprintf(keyword, "netgen::%s", netgen_cmds[n].name); sprintf(keyword, "netgen::%s", netgen_cmds[n].name);
@ -4579,8 +4501,7 @@ int Tclnetgen_Init(Tcl_Interp *interp)
} }
for (n = 0; netcmp_cmds[n].name != NULL; n++) { for (n = 0; netcmp_cmds[n].name != NULL; n++) {
sprintf(keyword, "netgen::%s", netcmp_cmds[n].name); sprintf(keyword, "netgen::%s", netcmp_cmds[n].name);
Tcl_CreateObjCommand(interp, keyword, Tcl_CreateObjCommand(interp, keyword, netcmp_cmds[n].handler,
(Tcl_ObjCmdProc *)netcmp_cmds[n].handler,
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
} }

View File

@ -44,8 +44,6 @@ exec ${NETGEN_WISH:=wish} "$0" ${1+"$@"}
if {$tcl_version < 8.0} { if {$tcl_version < 8.0} {
return -code error "tkcon requires at least Tcl/Tk8" return -code error "tkcon requires at least Tcl/Tk8"
} else { } else {
# Prevent breaking on version 8.5.2
# package require -exact Tk $tcl_version
package require Tk $tcl_version package require Tk $tcl_version
} }
@ -61,6 +59,18 @@ foreach pkg [info loaded {}] {
} }
catch {unset pkg file name version} catch {unset pkg file name version}
# Tk 8.4 makes previously exposed stuff private.
# FIX: Update tkcon to not rely on the private Tk code.
#
if {![llength [info globals tkPriv]]} {
::tk::unsupported::ExposePrivateVariable tkPriv
}
foreach cmd {SetCursor UpDownLine Transpose ScrollPages} {
if {![llength [info commands tkText$cmd]]} {
::tk::unsupported::ExposePrivateCommand tkText$cmd
}
}
# Initialize the ::tkcon namespace # Initialize the ::tkcon namespace
# #
namespace eval ::tkcon { namespace eval ::tkcon {
@ -186,7 +196,7 @@ proc ::tkcon::Init {} {
tkcon_puts tkcon_gets observe observe_var unalias which what tkcon_puts tkcon_gets observe observe_var unalias which what
} }
version 2.3 version 2.3
RCS {RCS: @(#) $Id: tkcon.tcl,v 1.2 2008/04/18 16:28:13 tim Exp $} RCS {RCS: @(#) $Id: tkcon.tcl,v 1.2 2008/05/23 00:20:17 tim Exp $}
HEADURL {http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/tkcon/tkcon/tkcon.tcl?rev=HEAD} HEADURL {http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/tkcon/tkcon/tkcon.tcl?rev=HEAD}
docs "http://tkcon.sourceforge.net/" docs "http://tkcon.sourceforge.net/"
email {jeff@hobbs.org} email {jeff@hobbs.org}
@ -735,7 +745,7 @@ proc ::tkcon::EvalCmd {w cmd} {
$w tag bind $tag <Leave> \ $w tag bind $tag <Leave> \
[list $w tag configure $tag -underline 0] [list $w tag configure $tag -underline 0]
$w tag bind $tag <ButtonRelease-1> \ $w tag bind $tag <ButtonRelease-1> \
"if {!\[info exists ::tk::Priv(mouseMoved)\] || !\$::tk::Priv(mouseMoved)} \ "if {!\[info exists tkPriv(mouseMoved)\] || !\$tkPriv(mouseMoved)} \
{[list edit -attach [Attach] -type error -- $PRIV(errorInfo)]}" {[list edit -attach [Attach] -type error -- $PRIV(errorInfo)]}"
} else { } else {
$w insert output $res\n stderr $w insert output $res\n stderr
@ -2464,7 +2474,7 @@ proc ::tkcon::ErrorHighlight w {
$w tag configure $tag -foreground $COLOR(stdout) $w tag configure $tag -foreground $COLOR(stdout)
$w tag bind $tag <Enter> [list $w tag configure $tag -underline 1] $w tag bind $tag <Enter> [list $w tag configure $tag -underline 1]
$w tag bind $tag <Leave> [list $w tag configure $tag -underline 0] $w tag bind $tag <Leave> [list $w tag configure $tag -underline 0]
$w tag bind $tag <ButtonRelease-1> "if {!\$::tk::Priv(mouseMoved)} \ $w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \
{[list edit -attach $app -type proc -find $what -- $cmd]}" {[list edit -attach $app -type proc -find $what -- $cmd]}"
} }
set info [string range $info $c1 end] set info [string range $info $c1 end]
@ -2493,7 +2503,7 @@ proc ::tkcon::ErrorHighlight w {
$w tag configure $tag -foreground $COLOR(proc) $w tag configure $tag -foreground $COLOR(proc)
$w tag bind $tag <Enter> [list $w tag configure $tag -underline 1] $w tag bind $tag <Enter> [list $w tag configure $tag -underline 1]
$w tag bind $tag <Leave> [list $w tag configure $tag -underline 0] $w tag bind $tag <Leave> [list $w tag configure $tag -underline 0]
$w tag bind $tag <ButtonRelease-1> "if {!\$::tk::Priv(mouseMoved)} \ $w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \
{[list edit -attach $app -type proc -- $cmd]}" {[list edit -attach $app -type proc -- $cmd]}"
} }
} }
@ -2542,8 +2552,8 @@ proc tkcon {cmd args} {
## 'congets' a replacement for [gets stdin] ## 'congets' a replacement for [gets stdin]
# Use the 'gets' alias of 'tkcon_gets' command instead of # Use the 'gets' alias of 'tkcon_gets' command instead of
# calling the *get* methods directly for best compatability # calling the *get* methods directly for best compatability
if {[llength $args] > 1} { if {[llength $args]} {
return -code error "wrong # args: must be \"tkcon congets [pfix]\"" return -code error "wrong # args: must be \"tkcon congets\""
} }
tkcon show tkcon show
set old [bind TkConsole <<TkCon_Eval>>] set old [bind TkConsole <<TkCon_Eval>>]
@ -2551,12 +2561,7 @@ proc tkcon {cmd args} {
set w $::tkcon::PRIV(console) set w $::tkcon::PRIV(console)
# Make sure to move the limit to get the right data # Make sure to move the limit to get the right data
$w mark set insert end $w mark set insert end
if {[llength $args]} {
$w mark set limit insert $w mark set limit insert
$w insert end $args
} else {
$w mark set limit insert
}
$w see end $w see end
vwait ::tkcon::PRIV(wait) vwait ::tkcon::PRIV(wait)
set line [::tkcon::CmdGet $w] set line [::tkcon::CmdGet $w]
@ -2793,19 +2798,13 @@ proc tkcon_puts args {
foreach {arg1 arg2 arg3} $args { break } foreach {arg1 arg2 arg3} $args { break }
if {$len == 1} { if {$len == 1} {
set sarg $arg1 tkcon console insert output "$arg1\n" stdout
set nl 1
set farg stdout
} elseif {$len == 2} { } elseif {$len == 2} {
if {![string compare $arg1 -nonewline]} { if {![string compare $arg1 -nonewline]} {
set sarg $arg2 tkcon console insert output $arg2 stdout
set farg stdout
set nl 0
} elseif {![string compare $arg1 stdout] \ } elseif {![string compare $arg1 stdout] \
|| ![string compare $arg1 stderr]} { || ![string compare $arg1 stderr]} {
set sarg $arg2 tkcon console insert output "$arg2\n" $arg1
set farg $arg1
set nl 1
} else { } else {
set len 0 set len 0
} }
@ -2813,15 +2812,11 @@ proc tkcon_puts args {
if {![string compare $arg1 -nonewline] \ if {![string compare $arg1 -nonewline] \
&& (![string compare $arg2 stdout] \ && (![string compare $arg2 stdout] \
|| ![string compare $arg2 stderr])} { || ![string compare $arg2 stderr])} {
set sarg $arg3 tkcon console insert output $arg3 $arg2
set farg $arg2
set nl 0
} elseif {(![string compare $arg1 stdout] \ } elseif {(![string compare $arg1 stdout] \
|| ![string compare $arg1 stderr]) \ || ![string compare $arg1 stderr]) \
&& ![string compare $arg3 nonewline]} { && ![string compare $arg3 nonewline]} {
set sarg $arg2 tkcon console insert output $arg2 $arg1
set farg $arg1
set nl 0
} else { } else {
set len 0 set len 0
} }
@ -2831,42 +2826,7 @@ proc tkcon_puts args {
## $len == 0 means it wasn't handled by tkcon above. ## $len == 0 means it wasn't handled by tkcon above.
## ##
if {$len == 0} {
if {$len != 0} {
## "poor man's" \r substitution---erase everything on the output
## line and print from character after the \r
set rpt [string last \r $sarg]
if {$rpt >= 0} {
tkcon console delete "insert linestart" "insert lineend"
set sarg [string range $sarg [expr {$rpt + 1}] end]
}
set bpt [string first \b $sarg]
if {$bpt >= 0} {
set narg [string range $sarg [expr {$bpt + 1}] end]
set sarg [string range $sarg 0 [expr {$bpt - 1}]]
set nl 0
}
if {$nl == 0} {
tkcon console insert output $sarg $farg
} else {
tkcon console insert output "$sarg\n" $farg
}
if {$bpt >= 0} {
tkcon console delete "insert -1 char" insert
if {$nl == 0} {
tkcon_puts $farg $narg nonewline
} else {
tkcon_puts $farg $narg
}
}
} else {
global errorCode errorInfo global errorCode errorInfo
if {[catch "tkcon_tcl_puts $args" msg]} { if {[catch "tkcon_tcl_puts $args" msg]} {
regsub tkcon_tcl_puts $msg puts msg regsub tkcon_tcl_puts $msg puts msg
@ -4146,7 +4106,7 @@ proc ::tkcon::Bindings {} {
global tcl_platform tk_version global tcl_platform tk_version
#----------------------------------------------------------------------- #-----------------------------------------------------------------------
# Elements of ::tk::Priv that are used in this file: # Elements of tkPriv that are used in this file:
# #
# char - Character position on the line; kept in order # char - Character position on the line; kept in order
# to allow moving up or down past short lines while # to allow moving up or down past short lines while
@ -4174,9 +4134,6 @@ proc ::tkcon::Bindings {} {
foreach ev [bind Text] { bind TkConsole $ev [bind Text $ev] } foreach ev [bind Text] { bind TkConsole $ev [bind Text $ev] }
## We really didn't want the newline insertion ## We really didn't want the newline insertion
bind TkConsole <Control-Key-o> {} bind TkConsole <Control-Key-o> {}
## in 8.6b3, the virtual events <<NextLine>> and <<PrevLine>>
# mess up our history feature
bind TkConsole <<NextLine>> {} bind TkConsole <<NextLine>> {}
bind TkConsole <<PrevLine>> {} bind TkConsole <<PrevLine>> {}
@ -4385,9 +4342,9 @@ proc ::tkcon::Bindings {} {
bind TkConsole <Control-a> { bind TkConsole <Control-a> {
if {[%W compare {limit linestart} == {insert linestart}]} { if {[%W compare {limit linestart} == {insert linestart}]} {
::tk::TextSetCursor %W limit tkTextSetCursor %W limit
} else { } else {
::tk::TextSetCursor %W {insert linestart} tkTextSetCursor %W {insert linestart}
} }
} }
bind TkConsole <Key-Home> [bind TkConsole <Control-a>] bind TkConsole <Key-Home> [bind TkConsole <Control-a>]
@ -4411,14 +4368,14 @@ proc ::tkcon::Bindings {} {
} }
bind TkConsole <<TkCon_Previous>> { bind TkConsole <<TkCon_Previous>> {
if {[%W compare {insert linestart} != {limit linestart}]} { if {[%W compare {insert linestart} != {limit linestart}]} {
::tk::TextSetCursor %W [::tk::TextUpDownLine %W -1] tkTextSetCursor %W [tkTextUpDownLine %W -1]
} else { } else {
::tkcon::Event -1 ::tkcon::Event -1
} }
} }
bind TkConsole <<TkCon_Next>> { bind TkConsole <<TkCon_Next>> {
if {[%W compare {insert linestart} != {end-1c linestart}]} { if {[%W compare {insert linestart} != {end-1c linestart}]} {
::tk::TextSetCursor %W [::tk::TextUpDownLine %W 1] tkTextSetCursor %W [tkTextUpDownLine %W 1]
} else { } else {
::tkcon::Event 1 ::tkcon::Event 1
} }
@ -4433,7 +4390,7 @@ proc ::tkcon::Bindings {} {
} }
bind TkConsole <<TkCon_Transpose>> { bind TkConsole <<TkCon_Transpose>> {
## Transpose current and previous chars ## Transpose current and previous chars
if {[%W compare insert > "limit+1c"]} { ::tk::TextTranspose %W } if {[%W compare insert > "limit+1c"]} { tkTextTranspose %W }
} }
bind TkConsole <<TkCon_ClearLine>> { bind TkConsole <<TkCon_ClearLine>> {
## Clear command line (Unix shell staple) ## Clear command line (Unix shell staple)
@ -4451,10 +4408,10 @@ proc ::tkcon::Bindings {} {
::tkcon::Insert %W $::tkcon::PRIV(tmp) ::tkcon::Insert %W $::tkcon::PRIV(tmp)
%W see end %W see end
} }
catch {bind TkConsole <Key-Page_Up> { ::tk::TextScrollPages %W -1 }} catch {bind TkConsole <Key-Page_Up> { tkTextScrollPages %W -1 }}
catch {bind TkConsole <Key-Prior> { ::tk::TextScrollPages %W -1 }} catch {bind TkConsole <Key-Prior> { tkTextScrollPages %W -1 }}
catch {bind TkConsole <Key-Page_Down> { ::tk::TextScrollPages %W 1 }} catch {bind TkConsole <Key-Page_Down> { tkTextScrollPages %W 1 }}
catch {bind TkConsole <Key-Next> { ::tk::TextScrollPages %W 1 }} catch {bind TkConsole <Key-Next> { tkTextScrollPages %W 1 }}
bind TkConsole <$PRIV(meta)-d> { bind TkConsole <$PRIV(meta)-d> {
if {[%W compare insert >= limit]} { if {[%W compare insert >= limit]} {
%W delete insert {insert wordend} %W delete insert {insert wordend}
@ -4472,7 +4429,7 @@ proc ::tkcon::Bindings {} {
} }
bind TkConsole <ButtonRelease-2> { bind TkConsole <ButtonRelease-2> {
if { if {
(!$::tk::Priv(mouseMoved) || $tk_strictMotif) && (!$tkPriv(mouseMoved) || $tk_strictMotif) &&
![catch {::tkcon::GetSelection %W} ::tkcon::PRIV(tmp)] ![catch {::tkcon::GetSelection %W} ::tkcon::PRIV(tmp)]
} { } {
if {[%W compare @%x,%y < limit]} { if {[%W compare @%x,%y < limit]} {