Compare commits
157 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
bcbc736b51 | |
|
|
f5f1240073 | |
|
|
02d7a1bd01 | |
|
|
7878b3cfbc | |
|
|
7f727e6674 | |
|
|
d111fa0a3b | |
|
|
178b172c06 | |
|
|
7870538ec9 | |
|
|
ee4e1e087f | |
|
|
7a8b5e835b | |
|
|
77f7a773e3 | |
|
|
9a48a59f68 | |
|
|
535b8285e9 | |
|
|
1e1d506697 | |
|
|
4edaf0813d | |
|
|
a4ae5ed989 | |
|
|
d850586a14 | |
|
|
4b5b117100 | |
|
|
935e54abe6 | |
|
|
49ccf1949a | |
|
|
9b84776374 | |
|
|
2af3f2a3f7 | |
|
|
738abbdad9 | |
|
|
8d7569e9a3 | |
|
|
d9425163e1 | |
|
|
9ba1dfe814 | |
|
|
fadd0ae2fc | |
|
|
153ce0e2b3 | |
|
|
bfdacab28c | |
|
|
7e9bd9f2a0 | |
|
|
ee92d880d7 | |
|
|
d3407b3e56 | |
|
|
0a94bec191 | |
|
|
4a7b6bf22a | |
|
|
661c9ee854 | |
|
|
5b21c1be3a | |
|
|
e11dbac384 | |
|
|
0535128421 | |
|
|
afe0e9f758 | |
|
|
e487890641 | |
|
|
bb44d3f827 | |
|
|
c25c4e1160 | |
|
|
8ed4e3cf38 | |
|
|
69838d79e4 | |
|
|
fc7c9371e8 | |
|
|
0d19868145 | |
|
|
6b4eb01ee8 | |
|
|
737b2a73bf | |
|
|
6b8c6d1718 | |
|
|
610eebb758 | |
|
|
97058c5017 | |
|
|
aa120460d0 | |
|
|
ea5cbacf1c | |
|
|
cdd768addc | |
|
|
66cf2b82d9 | |
|
|
bc4192496b | |
|
|
168e5502a1 | |
|
|
8d4b621b7d | |
|
|
ba3e862552 | |
|
|
cf6dd2a638 | |
|
|
b6d896e73f | |
|
|
9251ce2a48 | |
|
|
aa82164c08 | |
|
|
fb7876c7a6 | |
|
|
e31caa3500 | |
|
|
c1355bee45 | |
|
|
4fb8b59a2f | |
|
|
626faf22f9 | |
|
|
550234dce5 | |
|
|
a4c0028706 | |
|
|
e7ae84bbc8 | |
|
|
43c018f3bc | |
|
|
ca119edc0a | |
|
|
84348d2fe1 | |
|
|
813b29cdc4 | |
|
|
ccf4a0a900 | |
|
|
e34166fdb9 | |
|
|
a13491e358 | |
|
|
1d05b8b676 | |
|
|
e97d6f1aeb | |
|
|
fb4759a8cd | |
|
|
45d4004d43 | |
|
|
0b014e6efd | |
|
|
9ca713dfd9 | |
|
|
851a1f941e | |
|
|
fb798d6ce7 | |
|
|
a888502038 | |
|
|
c16258d4d1 | |
|
|
5341d7a5fd | |
|
|
8395df633c | |
|
|
6554063df3 | |
|
|
4416a380b3 | |
|
|
46394b2000 | |
|
|
3fe3bc4cfa | |
|
|
6661910672 | |
|
|
e7a36630f6 | |
|
|
f32b0b34a3 | |
|
|
6b731ddd7a | |
|
|
99e35d8b11 | |
|
|
65b542f0ab | |
|
|
b826870be9 | |
|
|
ed5276d67b | |
|
|
69c9d85be7 | |
|
|
ad05d059c7 | |
|
|
1b2cd1497c | |
|
|
d9d5a46c6e | |
|
|
d73b711e3a | |
|
|
1428580109 | |
|
|
210dfb25c3 | |
|
|
27f2ab8b3f | |
|
|
1be00bbd99 | |
|
|
03b241a5d4 | |
|
|
43cebd1ef9 | |
|
|
0490959b07 | |
|
|
dc841f3293 | |
|
|
05bcfede69 | |
|
|
72ed78e55a | |
|
|
59bb8a89c0 | |
|
|
9bdaee652e | |
|
|
9879b58f83 | |
|
|
9e3b705fcc | |
|
|
d2c9129242 | |
|
|
942f421fa3 | |
|
|
6bc948d8ba | |
|
|
c1ad37f05a | |
|
|
9edefe7d59 | |
|
|
f6b9629521 | |
|
|
7b2e01f2af | |
|
|
224050f153 | |
|
|
74e8c3e168 | |
|
|
95a29fcd8c | |
|
|
723a950fd3 | |
|
|
e3368cb22a | |
|
|
f06e6548bb | |
|
|
72ed19ff36 | |
|
|
39b8e3d14a | |
|
|
b63dfa8638 | |
|
|
f918f33c51 | |
|
|
63b2e48ea1 | |
|
|
6e63f49d53 | |
|
|
419b6de29a | |
|
|
205cf2aa58 | |
|
|
52b6766fc8 | |
|
|
7b0bdd29e8 | |
|
|
433cbd090a | |
|
|
3087bd3337 | |
|
|
b79a29d662 | |
|
|
bf9c61e412 | |
|
|
8d34bd372d | |
|
|
229c2931a8 | |
|
|
b8da97deb1 | |
|
|
b7187d5899 | |
|
|
d27d441c58 | |
|
|
48c9e6b292 | |
|
|
ced5846da3 | |
|
|
b99d33064f | |
|
|
399472e940 |
|
|
@ -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]);
|
||||||
|
|
|
||||||
305
base/ext.c
305
base/ext.c
|
|
@ -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,17 +516,13 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (simclass != 'x')
|
if (simclass != 'x')
|
||||||
FlushString("%c", simclass);
|
FlushString("%c", simclass);
|
||||||
|
|
||||||
switch (tp2->class) {
|
switch (tp2->class) {
|
||||||
case CLASS_NMOS: case CLASS_NMOS4:
|
case CLASS_NMOS: case CLASS_NMOS4:
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
248
base/flatten.c
248
base/flatten.c
|
|
@ -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,10 +601,8 @@ 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 */
|
||||||
|
|
@ -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);
|
flattenInstancesOf(name1, file1, ecompX0->cell1->name);
|
||||||
if (flattenInstancesOf(name1, file1,
|
ecompX0->num1 = 0;
|
||||||
ecompX0->cell1->name) > 0) {
|
ecomp0X->num1 += ecompX0->num1;
|
||||||
ecompX0->num1 = 0;
|
modified++;
|
||||||
ecomp0X->num1 += ecompX0->num1;
|
|
||||||
modified1++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
flattenInstancesOf(name2, file2, ecomp0X->cell2->name);
|
||||||
if (flattenInstancesOf(name2, file2,
|
ecomp0X->num2 = 0;
|
||||||
ecomp0X->cell2->name) > 0) {
|
ecompX0->num2 += ecomp0X->num2;
|
||||||
ecomp0X->num2 = 0;
|
modified++;
|
||||||
ecompX0->num2 += ecomp0X->num2;
|
|
||||||
modified2++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
33
base/hash.c
33
base/hash.c
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
1130
base/netcmp.c
1130
base/netcmp.c
File diff suppressed because it is too large
Load Diff
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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 = ' ';
|
GetNextLine(WHITESPACE_DELIMITER);
|
||||||
while ((testline == ' ') || (testline == '\t'))
|
SkipNewLine(NULL);
|
||||||
testline = getc(infile);
|
|
||||||
if (testline != '\n') {
|
|
||||||
ungetc(testline, infile);
|
|
||||||
GetNextLine(WHITESPACE_DELIMITER);
|
|
||||||
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},
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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,9 +300,7 @@ int ReduceOneExpression(struct valuelist *kv, struct objlist *parprops,
|
||||||
tstr = sstr - 1;
|
tstr = sstr - 1;
|
||||||
numlast = 1;
|
numlast = 1;
|
||||||
}
|
}
|
||||||
/* But might not be. . . */
|
break;
|
||||||
if ((dval != 0) || (sstr > estr))
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
/* Not a number, so must be arithmetic */
|
/* Not a number, so must be arithmetic */
|
||||||
*tstr = '\0';
|
*tstr = '\0';
|
||||||
|
|
@ -324,9 +320,7 @@ int ReduceOneExpression(struct valuelist *kv, struct objlist *parprops,
|
||||||
tstr = sstr - 1;
|
tstr = sstr - 1;
|
||||||
numlast = 1;
|
numlast = 1;
|
||||||
}
|
}
|
||||||
/* But might not be. . . */
|
break;
|
||||||
if ((dval != 0) || (sstr > estr))
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
/* Not a number, so must be arithmetic */
|
/* Not a number, so must be arithmetic */
|
||||||
*tstr = '\0';
|
*tstr = '\0';
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
192
base/objlist.c
192
base/objlist.c
|
|
@ -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;
|
||||||
|
|
@ -650,65 +596,65 @@ int freeprop(struct hashlist *p)
|
||||||
|
|
||||||
void CellDelete(char *name, int fnum)
|
void CellDelete(char *name, int fnum)
|
||||||
{
|
{
|
||||||
/* delete all the contents of cell 'name', and remove 'name' from
|
/* delete all the contents of cell 'name', and remove 'name' from
|
||||||
the cell hash table. NOTE: this procedure does not care or check
|
the cell hash table. NOTE: this procedure does not care or check
|
||||||
if 'name' has been instanced anywhere. It is assumed that if this
|
if 'name' has been instanced anywhere. It is assumed that if this
|
||||||
is the case, the user will (quickly) define a new cell of that name.
|
is the case, the user will (quickly) define a new cell of that name.
|
||||||
*/
|
*/
|
||||||
struct objlist *ob, *obnext;
|
struct objlist *ob, *obnext;
|
||||||
struct nlist *tp;
|
struct nlist *tp;
|
||||||
|
|
||||||
tp = LookupCellFile(name, fnum);
|
tp = LookupCellFile(name, fnum);
|
||||||
if (tp == NULL) {
|
if (tp == NULL) {
|
||||||
Printf ("No cell '%s' found.\n", name);
|
Printf ("No cell '%s' found.\n", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HashIntDelete(name, fnum, &cell_dict);
|
HashIntDelete(name, fnum, &cell_dict);
|
||||||
/* now make sure that we free all the fields of the nlist struct */
|
/* now make sure that we free all the fields of the nlist struct */
|
||||||
if (tp->name != NULL) FREE(tp->name);
|
if (tp->name != NULL) FREE(tp->name);
|
||||||
HashKill(&(tp->objdict));
|
HashKill(&(tp->objdict));
|
||||||
HashKill(&(tp->instdict));
|
HashKill(&(tp->instdict));
|
||||||
RecurseHashTable(&(tp->propdict), freeprop);
|
RecurseHashTable(&(tp->propdict), freeprop);
|
||||||
HashKill(&(tp->propdict));
|
HashKill(&(tp->propdict));
|
||||||
FreeNodeNames(tp);
|
FreeNodeNames(tp);
|
||||||
ob = tp->cell;
|
ob = tp->cell;
|
||||||
while (ob != NULL) {
|
while (ob != NULL) {
|
||||||
obnext = ob->next;
|
obnext = ob->next;
|
||||||
FreeObject (ob);
|
FreeObject (ob);
|
||||||
ob = obnext;
|
ob = obnext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int PrintCellHashTableElement(struct hashlist *p)
|
static int PrintCellHashTableElement(struct hashlist *p)
|
||||||
{
|
{
|
||||||
struct nlist *ptr;
|
struct nlist *ptr;
|
||||||
|
|
||||||
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);
|
||||||
else if (Debug == 3) { /* list */
|
else if (Debug == 3) { /* list */
|
||||||
#ifdef TCL_NETGEN
|
#ifdef TCL_NETGEN
|
||||||
Tcl_AppendElement(netgeninterp, ptr->name);
|
Tcl_AppendElement(netgeninterp, ptr->name);
|
||||||
#else
|
#else
|
||||||
Printf("%s ", ptr->name);
|
Printf("%s ", ptr->name);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((Debug == 2) || (Debug == 3)) { /* list only */
|
else if ((Debug == 2) || (Debug == 3)) { /* list only */
|
||||||
#ifdef TCL_NETGEN
|
#ifdef TCL_NETGEN
|
||||||
Tcl_AppendElement(netgeninterp, ptr->name);
|
Tcl_AppendElement(netgeninterp, ptr->name);
|
||||||
#else
|
#else
|
||||||
Printf("%s ", ptr->name);
|
Printf("%s ", ptr->name);
|
||||||
#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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print the contents of the cell hash table. */
|
/* Print the contents of the cell hash table. */
|
||||||
|
|
@ -717,65 +663,65 @@ static int PrintCellHashTableElement(struct hashlist *p)
|
||||||
|
|
||||||
void PrintCellHashTable(int full, int filenum)
|
void PrintCellHashTable(int full, int filenum)
|
||||||
{
|
{
|
||||||
int total, bins;
|
int total, bins;
|
||||||
int OldDebug;
|
int OldDebug;
|
||||||
|
|
||||||
if ((filenum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
|
if ((filenum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
|
||||||
PrintCellHashTable(full, Circuit1->file);
|
PrintCellHashTable(full, Circuit1->file);
|
||||||
PrintCellHashTable(full, Circuit2->file);
|
PrintCellHashTable(full, Circuit2->file);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TopFile = filenum;
|
TopFile = filenum;
|
||||||
|
|
||||||
bins = RecurseHashTable(&cell_dict, CountHashTableBinsUsed);
|
bins = RecurseHashTable(&cell_dict, CountHashTableBinsUsed);
|
||||||
total = RecurseHashTable(&cell_dict, CountHashTableEntries);
|
total = RecurseHashTable(&cell_dict, CountHashTableEntries);
|
||||||
if (full < 2)
|
if (full < 2)
|
||||||
Printf("Hash table: %d of %d bins used; %d cells total (%.2f per bin)\n",
|
Printf("Hash table: %d of %d bins used; %d cells total (%.2f per bin)\n",
|
||||||
bins, CELLHASHSIZE, total, (bins == 0) ? 0 :
|
bins, CELLHASHSIZE, total, (bins == 0) ? 0 :
|
||||||
(float)((float)total / (float)bins));
|
(float)((float)total / (float)bins));
|
||||||
|
|
||||||
OldDebug = Debug;
|
OldDebug = Debug;
|
||||||
Debug = full;
|
Debug = full;
|
||||||
RecurseHashTable(&cell_dict, PrintCellHashTableElement);
|
RecurseHashTable(&cell_dict, PrintCellHashTableElement);
|
||||||
Debug = OldDebug;
|
Debug = OldDebug;
|
||||||
#ifndef TCL_NETGEN
|
#ifndef TCL_NETGEN
|
||||||
if (full >= 2) Printf("\n");
|
if (full >= 2) Printf("\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
struct nlist *FirstCell(void)
|
struct nlist *FirstCell(void)
|
||||||
{
|
{
|
||||||
return((struct nlist *)HashFirst(&cell_dict));
|
return((struct nlist *)HashFirst(&cell_dict));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct nlist *NextCell(void)
|
struct nlist *NextCell(void)
|
||||||
{
|
{
|
||||||
return((struct nlist *)HashNext(&cell_dict));
|
return((struct nlist *)HashNext(&cell_dict));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ClearDumpedElement(struct hashlist *np)
|
static int ClearDumpedElement(struct hashlist *np)
|
||||||
{
|
{
|
||||||
struct nlist *p;
|
struct nlist *p;
|
||||||
|
|
||||||
p = (struct nlist *)(np->ptr);
|
p = (struct nlist *)(np->ptr);
|
||||||
p->dumped = 0;
|
p->dumped = 0;
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearDumpedList(void)
|
void ClearDumpedList(void)
|
||||||
{
|
{
|
||||||
RecurseHashTable(&cell_dict, ClearDumpedElement);
|
RecurseHashTable(&cell_dict, ClearDumpedElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
int RecurseCellHashTable(int (*foo)(struct hashlist *np))
|
int RecurseCellHashTable(int (*foo)(struct hashlist *np))
|
||||||
{
|
{
|
||||||
return RecurseHashTable(&cell_dict, foo);
|
return RecurseHashTable(&cell_dict, foo);
|
||||||
}
|
}
|
||||||
|
|
||||||
int RecurseCellFileHashTable(int (*foo)(struct hashlist *, int), int value)
|
int RecurseCellFileHashTable(int (*foo)(struct hashlist *, int), int value)
|
||||||
{
|
{
|
||||||
return RecurseHashTableValue(&cell_dict, foo, value);
|
return RecurseHashTableValue(&cell_dict, foo, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Yet another version, passing one parameter that is a pointer */
|
/* Yet another version, passing one parameter that is a pointer */
|
||||||
|
|
@ -783,7 +729,7 @@ int RecurseCellFileHashTable(int (*foo)(struct hashlist *, int), int value)
|
||||||
struct nlist *RecurseCellHashTable2(struct nlist *(*foo)(struct hashlist *,
|
struct nlist *RecurseCellHashTable2(struct nlist *(*foo)(struct hashlist *,
|
||||||
void *), void *pointer)
|
void *), void *pointer)
|
||||||
{
|
{
|
||||||
return RecurseHashTablePointer(&cell_dict, foo, pointer);
|
return RecurseHashTablePointer(&cell_dict, foo, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************** WILD-CARD STUFF *******************************/
|
/************************** WILD-CARD STUFF *******************************/
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
121
base/spice.c
121
base/spice.c
|
|
@ -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,46 +595,11 @@ 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
|
FreePorts(nexttok);
|
||||||
* was created from the verilog. (1) If the pin names are "1", "2",
|
CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */
|
||||||
* "3", then this is a SPICE placeholder, and just remove the CellDef
|
CellDef(model, filenum);
|
||||||
* and re-create it. Otherwise, create new cell "_PLACEHOLDER_".
|
tp = LookupCellFile(model, filenum);
|
||||||
* (2) After encountering .ends, run MatchPins between the two cells.
|
update = 1; /* Will need to update existing instances */
|
||||||
* (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);
|
|
||||||
CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */
|
|
||||||
CellDef(model, filenum);
|
|
||||||
tp = LookupCellFile(model, filenum);
|
|
||||||
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);
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
411
base/verilog.c
411
base/verilog.c
|
|
@ -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", <est) != 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);
|
||||||
char *aptr = strvchr(nexttok, '[');
|
if (GetBusTok(&wb) == 0) {
|
||||||
|
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 {
|
||||||
char *aptr = strvchr(nexttok, '[');
|
if (GetBusTok(&wb2) == 0) {
|
||||||
if (((aptr == NULL) && (GetBusTok(&wb2) == 0)) ||
|
char *aptr = strvchr(nexttok, '[');
|
||||||
((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,27 +2529,18 @@ 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);
|
Fprintf(stdout,
|
||||||
Fprintf(stdout,
|
|
||||||
"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;
|
scanroot = strsave(scan->net);
|
||||||
/* Skip over a bundle delimiter */
|
|
||||||
if (*scan->net == '{') {
|
|
||||||
scanroot = strsave(scan->net + 1);
|
|
||||||
isbundle = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
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,49 +2584,27 @@ nextinst:
|
||||||
if (siglen < 0) siglen = -siglen;
|
if (siglen < 0) siglen = -siglen;
|
||||||
siglen++;
|
siglen++;
|
||||||
|
|
||||||
// If this is a bundle, then count out to the current
|
// If signal array is smaller than the portlength *
|
||||||
// slice and read off the index. NOTE: Need to
|
// length of instance array, then the signal wraps.
|
||||||
// handle multiple bits per bundle entry!
|
|
||||||
if (isbundle) {
|
if (wb2.start >= wb2.end && arraystart >= arrayend) {
|
||||||
int j;
|
slice = wb.start - (arraystart - i) * portlen;
|
||||||
if (brackptr) *brackptr = '[';
|
while (slice < wb2.end) slice += siglen;
|
||||||
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 */
|
else if (wb2.start < wb2.end && arraystart > arrayend) {
|
||||||
|
slice = wb.start + (arraystart - i) * portlen;
|
||||||
// If signal array is smaller than the portlength *
|
while (slice > wb2.end) slice -= siglen;
|
||||||
// length of instance array, then the signal wraps.
|
}
|
||||||
|
else if (wb2.start > wb2.end && arraystart < arrayend) {
|
||||||
if (wb2.start >= wb2.end && arraystart >= arrayend) {
|
slice = wb.start - (arraystart + i) * portlen;
|
||||||
slice = wb.start - (arraystart - i) * portlen;
|
while (slice < wb2.end) slice += siglen;
|
||||||
while (slice < wb2.end) slice += siglen;
|
}
|
||||||
}
|
else { // (wb2.start < wb2.end && arraystart < arrayend)
|
||||||
else if (wb2.start < wb2.end && arraystart > arrayend) {
|
slice = wb.start + (arraystart + i) * portlen;
|
||||||
slice = wb.start + (arraystart - i) * portlen;
|
while (slice > wb2.end) slice -= siglen;
|
||||||
while (slice > wb2.end) slice -= siglen;
|
|
||||||
}
|
|
||||||
else if (wb2.start > wb2.end && arraystart < arrayend) {
|
|
||||||
slice = wb.start - (arraystart + i) * portlen;
|
|
||||||
while (slice < wb2.end) slice += siglen;
|
|
||||||
}
|
|
||||||
else { // (wb2.start < wb2.end && arraystart < arrayend)
|
|
||||||
slice = wb.start + (arraystart + i) * portlen;
|
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
;;
|
;;
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
;;
|
;;
|
||||||
|
|
|
||||||
|
|
@ -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@
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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,19 +1052,15 @@ _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);
|
/* Mark cell as placeholder so it will not be flattened */
|
||||||
else {
|
tp->flags |= CELL_PLACEHOLDER;
|
||||||
Printf("Will not flatten instances of %s in file %s\n", repstr, tptop->name);
|
|
||||||
/* Mark cell as placeholder so it will not be flattened */
|
|
||||||
tp->flags |= CELL_PLACEHOLDER;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Tcl_WrongNumArgs(interp, 1, objv, "class valid_cellname");
|
Tcl_WrongNumArgs(interp, 1, objv, "class valid_cellname");
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
115
tcltk/tkcon.tcl
115
tcltk/tkcon.tcl
|
|
@ -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]} {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue