Compare commits

...
57 Commits
Author SHA1 Message Date
Tim Edwards bcbc736b51 Merge branch 'master' into netgen-1.5 2023-08-28 02:00:03 -04:00
Tim Edwards 615c55cbe2 Updated the config.guess and config.sub files; the newer ones
support, among other things, RISC-V.
2023-08-27 11:53:16 -04:00
Tim Edwards f5f1240073 Merge branch 'master' into netgen-1.5 2023-07-12 02:00:03 -04:00
Tim Edwards 87d8759a69 Corrected part of the MatchPins() routine so that the JSON output
tracks the output printed to stdout when matching pins.  One section
of this subroutine used the wrong pointers when writing to the Tcl
list (for eventual JSON output) which was the fundamental error.
Beyond that, the "debug" case (if used) would fail to run some of
the matching code, and the "no matching pin" case needed to be
handled for the Tcl list output.  Now the terminal output, terminal
debug output, and Tcl list output should all be in agreement on the
pin lists.
2023-07-11 15:40:00 -04:00
Tim Edwards 02d7a1bd01 Merge branch 'master' into netgen-1.5 2023-06-13 02:00:02 -04:00
Tim Edwards 1efa054ac1 Corrected an issue with shorted ports. When shorted ports are
connected only to ports and not to any devices, then they do not
show up in NodeClasses() and so pass through most of the checks
in MatchPins().  A separate correspondence check is needed to make
sure that the same shorted ports appear in both netlists.
2023-06-12 17:16:49 -04:00
Tim Edwards 7878b3cfbc Merge branch 'master' into netgen-1.5 2023-04-15 02:00:01 -04:00
Tim Edwards 609d1de250 Corrected a problem in the flattening routine, which was a missing
method for flattening a subcircuit with property M != 1.
2023-04-14 20:09:36 -04:00
Tim Edwards 7f727e6674 Merge branch 'master' into netgen-1.5 2023-04-14 02:00:01 -04:00
Tim Edwards 47c3b34612 Corrected the node merging around zero-volt voltage sources and
zero-ohm resistors so that if one of the nodes being merged is a
port, it is preferred over the other.
2023-04-13 15:41:12 -04:00
Tim Edwards d111fa0a3b Merge branch 'master' into netgen-1.5 2023-03-30 02:00:02 -04:00
Tim Edwards 66317c9848 Corrected an error in order-of-precedence of arithmetic operators,
ensuring that, e.g., in (a)*b+c, (a)*b gets evaluated before b+c.
2023-03-29 19:45:39 -04:00
Tim Edwards eeb3c0e5c6 Added support for simple forms of for() loops in generate blocks.
This is done by treating the loop variable as a temporary parameter
that is valid only inside the loop, and changing the parameter
value on each loop iteration.  The file stream position is used
to iterate the loop with calls to fseek() and ftell(), so that the
input tokenizer continues to work within loops.
2023-03-29 16:17:37 -04:00
Tim Edwards 490f9f7dbc Added a missing check for using a verilog macro definition as an
array delimeter for an instance array in verilog.
2023-03-29 09:54:45 -04:00
Tim Edwards 178b172c06 Merge branch 'master' into netgen-1.5 2023-03-08 02:00:03 -05:00
Tim Edwards 40cf82c2cb Slightly modified the fix from the last commit to allow an empty
string for the setup file to be the "trivial default" previously
used in case of the setup file not being found.  Put a newline
around the setup file messages so that they stand out from the
rest of the initial output information.
2023-03-07 09:00:39 -05:00
Tim Edwards 1ac2b592fb Changed what was a not-very-well thought out behavior: On being
passed an invalid setup file, the netgen "lvs" script uses a
trivial default setup and issues no error or warning.  Replaced
this behavior with an error message and a hard stop.
2023-03-07 08:53:06 -05:00
Tim Edwards 7870538ec9 Merge branch 'master' into netgen-1.5 2023-03-07 02:00:02 -05:00
Tim Edwards e12883037c Modified code from EquivalenceClasses() that forces the two cells
to have unique class hashes.  This has the problem that it prevents
comparing N-to-1 cells because declaring X->X1 as equivalent breaks
the original name equivalence of X->X.  The new implementation adds
the switch "-unique" to preserve the original behavior.  Otherwise,
the class hashes are made the same as the 2nd cell passed to the
command, and it is the responsibility of the person running LVS to
ensure that this is done in the correct direction.
2023-03-06 09:36:35 -05:00
Tim Edwards ee4e1e087f Merge branch 'master' into netgen-1.5 2023-03-05 02:00:01 -05:00
Tim Edwards 2d63fd63c1 Corrected the wrong order of arguments in an strncpy() command
that was introduced in a recent pull request, as pointed out by
Mitch Bailey in github issue #72.
2023-03-04 10:05:57 -05:00
Tim Edwards 7a8b5e835b Merge branch 'master' into netgen-1.5 2023-03-01 02:00:03 -05:00
Tim Edwards e557e61a02 Updated version and fixed a redundant include statement after
merging pull request #71 from Donn.
2023-02-28 09:04:45 -05:00
Donn 67da250615 Patches for Clang 2023-02-28 09:02:41 -05:00
Tim Edwards 77f7a773e3 Merge branch 'master' into netgen-1.5 2023-02-28 02:00:03 -05:00
Tim Edwards cd013621a7 Relaxed the prohibition on ((S != 1) && (M != 1)) in device
network parallel/series networks.  Instead, added a global option
with command "property tolerance strict|relaxed" to reinstate the
original (strict) behavior on demand, while relaxing it by default.
This allows certain series/parallel networks to match numerically
even though the schematic netlist may have combined individual
devices.
2023-02-27 15:26:18 -05:00
Tim Edwards 9a48a59f68 Merge branch 'master' into netgen-1.5 2023-02-25 02:00:03 -05:00
Tim Edwards 45712a04f1 Removed X11 definitions from the configuration when compiling
with Tcl, since Tk is launched independently through the console
script and nothing inside of netgen itself involves graphics.
This prevents netgenexec from linking to Tk and X11 libraries.
2023-02-24 10:42:59 -05:00
Tim Edwards 535b8285e9 Merge branch 'master' into netgen-1.5 2022-12-20 02:00:03 -05:00
Tim Edwards 28a2950439 Modified netgen output to not print information about combining
individual components in parallel and series as it reduces the
networks.  This information is available in total in the cell
summary.
2022-12-19 14:37:11 -05:00
Tim Edwards 1e1d506697 Merge branch 'master' into netgen-1.5 2022-12-16 02:00:03 -05:00
Tim Edwards 013fff9f37 (1) Fixed the series sorting, which needed to be modified to match
the parallel sorting routine.  This fixes occasional property
errors with series-connected devices such as resistors.  (2) Added
a method to associate properties with specific pins when pins are
permutable.  This allows netgen to properly check a value like
source/drain area when the definition of source and drain has
changed due to permutation of the device.  (3) Added a "property"
command extension "associate" to associate a property with a pin,
for use with the method described in (2).
2022-12-15 21:34:56 -05:00
Tim Edwards 4edaf0813d Merge branch 'master' into netgen-1.5 2022-11-17 02:00:01 -05:00
Tim Edwards 2292ab813b Corrected a badly implemented routine that can cause very long
run-times on large projects where a lot of cells need to be
deleted.
2022-11-16 12:37:05 -05:00
Tim Edwards a4ae5ed989 Merge branch 'master' into netgen-1.5 2022-11-05 02:00:01 -04:00
Tim Edwards 7e8508db53 Additional correction to the property match subroutine to better
check instances with permutable pins when checking parallelized
instances with disconnected pins vs. mutually connected pins.
2022-11-04 20:40:37 -04:00
Tim Edwards c9f7b24e0f Found an error in property matching causing weird errors in the
LVS result.  The property matching was failing to match (M=1) to
(M!=1) if M was not registered as a property name (which it often
isn't).  This would allow devices with different numbers of
instances in parallel to be put in the same matching group,
which then could later identify as a mismatch if the instances
were checked in a different order.
2022-11-04 12:07:21 -04:00
Tim Edwards d850586a14 Merge branch 'master' into netgen-1.5 2022-11-03 02:00:03 -04:00
Tim Edwards 95605ebbd4 Prevented checks from automatically treating two empty cells as
black boxes.  The check was supposed to check that both empty
cells really are black box entries.
2022-11-02 09:48:39 -04:00
Tim Edwards 4b5b117100 Merge branch 'master' into netgen-1.5 2022-11-02 02:00:02 -04:00
Tim Edwards 98e6a4bd8f Implemented the change from pull request #65 from Mitch Bailey
(slightly altered to put the inexpensive flag checks before the
more expensive string match).
2022-11-01 13:21:35 -04:00
Tim Edwards c73d9ec4ff Updated version to go along with pull request #67 from Mitch
Bailey.
2022-11-01 11:44:36 -04:00
D. Mitch Bailey a5375177c5 parameterized string length and increased to 256
Rebasing over latest commit.
2022-11-01 11:43:43 -04:00
Tim Edwards 935e54abe6 Merge branch 'master' into netgen-1.5 2022-11-01 02:00:02 -04:00
Tim Edwards 27b095754e Fixed an error that prints bogus property mismatch errors when
netgen is supposed to be checking properties for symmetry sorting,
but not reporting anything.  This causes mysterious property
mismatch errors that don't actually exist to show up in the
output.
2022-10-31 17:32:15 -04:00
Tim Edwards 49ccf1949a Merge branch 'master' into netgen-1.5 2022-10-30 02:00:03 -04:00
Tim Edwards db457c562b Corrected a problem that is very similar to the last issue, which
is that when the "class ignore" command is used, then ports of a
parent cell need to be checked for being disconnected if they
connect only to ports of an ignored/deleted child cell.
2022-10-29 11:43:01 -04:00
Tim Edwards 9b84776374 Merge branch 'master' into netgen-1.5 2022-10-26 02:00:01 -04:00
Tim Edwards 06386bee1b Corrected an issue with "flatten": If a cell has disconnected ports,
then flattening instances of that cell can cause a port of the parent
cell connected to the disconnected port of the child cell to itself
become disconnected.  If the parent port is not changed to show the
disconnected state, then pin mismatch can occur if the netlist being
matched didn't have the same flattened subcell.  This condition is
now detected and handled correctly.
2022-10-25 20:14:44 -04:00
Tim Edwards 2af3f2a3f7 Merge branch 'master' into netgen-1.5 2022-10-25 02:00:01 -04:00
Tim Edwards 7cd8d82964 Fix for an error causing a segfault. This does not fix the
underlying issue (which needs to be investigated), but it does
prevent netgen from crashing when it encounters it (netgen will
generate an erro message instead).
2022-10-24 21:45:14 -04:00
Tim Edwards 738abbdad9 Merge branch 'master' into netgen-1.5 2022-10-01 02:00:01 -04:00
Tim Edwards 3aeea9d164 Re-applied the modifications of revisions 231 and 232, and updated
the version to revision 234.
2022-09-30 11:47:36 -04:00
Tim Edwards 12e1ff295f Revert "Part 2 of folding in Mitch Bailey's code. This part is a"
This reverts commit 4fa4d046c8.

Reverting back to before the major change to MatchPins(), which is
breaking existing LVS scripts.
2022-09-30 11:36:09 -04:00
Tim Edwards 8d7569e9a3 Merge branch 'master' into netgen-1.5 2022-09-24 02:00:02 -04:00
Tim Edwards 2f9e898ec6 Version updated along with the merge of pull request #62 from
Mitch Bailey.
2022-09-23 16:04:49 -04:00
D. Mitch Bailey 9663579dd0 Restore matching circuits if one is empty (but only if pins match). 2022-09-21 08:05:39 -07:00
34 changed files with 5220 additions and 2419 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.232
1.5.256
+1 -1
View File
@@ -131,7 +131,7 @@ if format = 1, use the actel .pin file format
struct nlist *tp;
struct objlist *ob, *ob2;
char *ptr;
char physicalpin[200];
char physicalpin[MAX_STR_LEN];
tp = LookupCell(name);
if (tp == NULL) return;
+2
View File
@@ -176,4 +176,6 @@ extern int open(char *path, int oflag, ...); /* HPUX has it in <sys/fcntl.h> */
#define FALSE 0
#endif
#define MAX_STR_LEN 256
#endif /* _CONFIG_H */
+3 -3
View File
@@ -629,7 +629,7 @@ struct embed *FlattenEmbeddingTree(struct embed *E)
int LenEmbed(char *prefix, struct nlist *np, struct embed *E, int flatten)
/* return the number of characters required to print element E */
{
char longstr[200];
char longstr[MAX_STR_LEN];
if (E == NULL) return(0);
if (E->left == NULL && E->right == NULL) {
@@ -668,7 +668,7 @@ void PrintEmb(FILE *outfile, char *prefix, struct nlist *np,
struct objlist *ob;
char *instancename;
struct nlist *np2;
char name[200];
char name[MAX_STR_LEN];
ob = InstanceNumber(np,E->instancenumber);
instancename = ob->instance.name;
@@ -706,7 +706,7 @@ void PrintEmbed(FILE *outfile, char *prefix, struct nlist *np,
struct objlist *ob;
char *instancename;
struct nlist *np2;
char name[200];
char name[MAX_STR_LEN];
ob = InstanceNumber(np,E->instancenumber);
instancename = ob->instance.name;
+23 -23
View File
@@ -167,7 +167,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
int filenum;
if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
char name[100];
char name[MAX_STR_LEN];
SetExtension(name, fname, EXT_EXTENSION);
if ((filenum = OpenParseFile(name, *fnum)) < 0) {
@@ -208,7 +208,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
else if (match(nexttok, "style")) SkipNewLine(NULL);
else if (match(nexttok, "resistclasses")) SkipNewLine(NULL);
else if (match(nexttok, "node")) {
char name[200];
char name[MAX_STR_LEN];
/* No cell is generated until at least one valid "node" or "use" */
/* has been read in the file. */
@@ -223,8 +223,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
SkipNewLine(NULL);
}
else if (match(nexttok, "equiv")) {
char name[200];
char name2[200];
char name[MAX_STR_LEN];
char name2[MAX_STR_LEN];
SkipTok(NULL);
GetExtName(name, nexttok);
if (LookupObject(name,CurrentCell) == NULL) Node(name);
@@ -235,8 +235,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
SkipNewLine(NULL);
}
else if (match(nexttok, "device")) {
char dev_name[100], dev_class[100];
char gate[200], drain[200], source[200], subs[200];
char dev_name[MAX_STR_LEN], dev_class[MAX_STR_LEN];
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN], subs[MAX_STR_LEN];
char inststr[64];
SkipTok(NULL);
strcpy(dev_class, nexttok);
@@ -306,8 +306,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
SkipNewLine(NULL);
}
else if (match(nexttok, "fet")) { /* old-style FET record */
char fet_class[100];
char gate[200], drain[200], source[200], subs[200];
char fet_class[MAX_STR_LEN];
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN], subs[MAX_STR_LEN];
char inststr[64];
SkipTok(NULL);
strcpy(fet_class, nexttok);
@@ -365,7 +365,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
SkipNewLine(NULL);
}
else {
char ctop[200], cbot[200], cdummy[200];
char ctop[MAX_STR_LEN], cbot[MAX_STR_LEN], cdummy[MAX_STR_LEN];
SkipTok(NULL);
GetExtName(ctop, nexttok);
SkipTok(NULL);
@@ -375,8 +375,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
}
}
else if (match(nexttok, "use")) {
char name[200];
char instancename[200];
char name[MAX_STR_LEN];
char instancename[MAX_STR_LEN];
char *basename;
/* No cell is generated until at least one valid "node" or "use" */
@@ -390,7 +390,7 @@ char *ReadExt(char *fname, int doflat, int *fnum)
SkipTok(NULL);
GetExtName(name, nexttok);
if ((basename = strrchr(name,'/')) != NULL) {
char tmp[200];
char tmp[MAX_STR_LEN];
strcpy(tmp, basename+1);
strcpy(name, tmp);
}
@@ -405,8 +405,8 @@ char *ReadExt(char *fname, int doflat, int *fnum)
SkipNewLine(NULL);
}
else if (match(nexttok, "merge")) {
char name[200];
char name2[200];
char name[MAX_STR_LEN];
char name2[MAX_STR_LEN];
SkipTok(NULL);
GetExtName(name, nexttok);
SkipTok(NULL);
@@ -640,7 +640,7 @@ char *ReadSim(char *fname, int *fnum)
double simscale = 1.0;
if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
char name[100];
char name[MAX_STR_LEN];
SetExtension(name, fname, SIM_EXTENSION);
if (OpenParseFile(name, *fnum) < 0) {
@@ -670,7 +670,7 @@ char *ReadSim(char *fname, int *fnum)
SkipNewLine(NULL);
}
else if (match(nexttok, "n")) {
char gate[200], drain[200], source[200];
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN];
char inststr[25], *instptr = NULL;
SkipTok(NULL);
@@ -714,7 +714,7 @@ char *ReadSim(char *fname, int *fnum)
LinkProperties("n", kvlist);
}
else if (match(nexttok, "p")) {
char gate[200], drain[200], source[200];
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN];
char inststr[25], *instptr = NULL;
SkipTok(NULL);
GetExtName(gate, nexttok);
@@ -754,7 +754,7 @@ char *ReadSim(char *fname, int *fnum)
LinkProperties("p", kvlist);
}
else if (match(nexttok, "e")) { /* 3-port capacitors (poly/poly2) */
char gate[200], drain[200], source[200];
char gate[MAX_STR_LEN], drain[MAX_STR_LEN], source[MAX_STR_LEN];
char inststr[25], *instptr = NULL;
SkipTok(NULL);
GetExtName(gate, nexttok);
@@ -788,7 +788,7 @@ char *ReadSim(char *fname, int *fnum)
E(fname, instptr, gate, drain, source);
}
else if (match(nexttok, "b")) { /* bipolars added by Tim 7/16/96 */
char base[200], emitter[200], collector[200];
char base[MAX_STR_LEN], emitter[MAX_STR_LEN], collector[MAX_STR_LEN];
char inststr[25], *instptr = NULL;
SkipTok(NULL);
GetExtName(base, nexttok);
@@ -826,7 +826,7 @@ char *ReadSim(char *fname, int *fnum)
SkipNewLine(NULL);
}
else {
char ctop[200], cbot[200], cdummy[200];
char ctop[MAX_STR_LEN], cbot[MAX_STR_LEN], cdummy[MAX_STR_LEN];
SkipTok(NULL);
GetExtName(ctop, nexttok);
if (LookupObject(ctop, CurrentCell) == NULL)
@@ -851,7 +851,7 @@ char *ReadSim(char *fname, int *fnum)
SkipNewLine(NULL);
}
else {
char rtop[200], rbot[200];
char rtop[MAX_STR_LEN], rbot[MAX_STR_LEN];
SkipTok(NULL);
GetExtName(rtop, nexttok);
if (LookupObject(rtop, CurrentCell) == NULL)
@@ -875,7 +875,7 @@ char *ReadSim(char *fname, int *fnum)
SkipNewLine(NULL);
}
else {
char rtop[200], rbot[200], rdummy[200];
char rtop[MAX_STR_LEN], rbot[MAX_STR_LEN], rdummy[MAX_STR_LEN];
char inststr[25], *instptr = NULL;
SkipTok(NULL);
GetExtName(rdummy, nexttok);
@@ -917,7 +917,7 @@ char *ReadSim(char *fname, int *fnum)
SkipNewLine(NULL);
}
else if (match(nexttok, "=")) {
char node1[200], node2[200];
char node1[MAX_STR_LEN], node2[MAX_STR_LEN];
SkipTok(NULL);
GetExtName(node1, nexttok);
SkipTok(NULL);
+106 -7
View File
@@ -53,7 +53,7 @@ void flattenCell(char *name, int file)
struct nlist *ChildCell;
struct objlist *tmp, *ob2, *ob3;
int notdone, rnodenum;
char tmpstr[200];
char tmpstr[MAX_STR_LEN];
int nextnode, oldmax;
#if !OLDPREFIX
int prefixlength;
@@ -243,6 +243,13 @@ void flattenCell(char *name, int file)
ThisCell->dumped = 1; /* indicate cell has been flattened */
}
/* Structure used to keep track of nodes needing checking */
struct linkednode {
int node;
struct linkednode *next;
};
/*--------------------------------------------------------------*/
/* flattenInstancesOf -- */
/* */
@@ -265,6 +272,7 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
struct nlist *ThisCell;
struct nlist *ChildCell;
struct objlist *tmp, *ob2, *ob3;
struct linkednode *checknodes = NULL, *newlnode, *chknode;
int notdone, rnodenum;
char tmpstr[1024];
int nextnode, oldmax, numflat = 0;
@@ -416,6 +424,16 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
}
UpdateNodeNumbers(ChildStart, tmp->node, ob2->node);
}
else if (tmp->node == -1) {
/* Opposite case: If child port is an unconnected node, then */
/* removing the instance may make the parent node become */
/* unconnected. For now, just record the node number. At the */
/* end we'll check if these nodes are actually disconnected. */
newlnode = (struct linkednode *)MALLOC(sizeof(struct linkednode));
newlnode->node = ob2->node;
newlnode->next = checknodes;
checknodes = newlnode;
}
/* in pathological cases, the lengths of the port lists may
* change. This is an error, but that is no reason to allow
@@ -518,11 +536,10 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
/* Do property inheritance */
/* NOTE: Need to do: Check properties for M > 1 and decrement
* and repeat without moving CurrentProp
*/
if (CurrentProp) {
int i, mval;
struct valuelist *kv;
for (ob2 = ChildStart; ob2 != NULL; ob2=ob2->next) {
/* If the parent cell has properties to declare, then */
@@ -530,10 +547,49 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
/* spiceparams dictionary is active (during file */
/* reading only). */
if (ob2->type == PROPERTY)
if (ob2->type == PROPERTY) {
ReduceExpressions(ob2, CurrentProp, ChildCell,
(spiceparams.hashtab == NULL) ? 0 : 1);
}
}
}
/* Check for property M. If it exists and is greater than */
/* one, reduce it and repeat; i.e., generate multiple */
/* child instances to match the M value. Probably this */
/* could be done quicker by just creating a new property */
/* M for a single child. */
mval = 0;
for (i = 0; ; i++) {
kv = &(CurrentProp->instance.props[i]);
if (kv->type == PROP_ENDLIST) break;
if ((*matchfunc)(kv->key, "M")) {
if (kv->type == PROP_INTEGER) {
mval = kv->value.ival;
kv->value.ival = mval - 1;
break;
}
else if (kv->type == PROP_DOUBLE) {
mval = (int)kv->value.dval;
kv->value.dval = (double)mval - 1;
break;
}
}
}
if (mval > 1) {
/* Put the child cell at the start of ChildObjList */
if (ChildEnd) {
ChildEnd->next = ChildObjList;
ChildObjList = ChildStart;
/* Continue without moving CurrentProp */
/* Note that if ChildEnd is NULL then the child cell
* is optimized out and there is no need to do it
* M times.
*/
continue;
}
}
/* Repeat for each property record, as each property represents a
* unique instance that must be flattened individually.
@@ -598,6 +654,29 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
NextObj = ParentParams;
} /* repeat until no more instances found */
}
/* Check nodes that may have become disconnected after child flattening */
while (checknodes != NULL) {
struct objlist *portnode = NULL;
chknode = checknodes;
checknodes = checknodes->next;
for (ob3 = ThisCell->cell; ob3; ob3 = ob3->next) {
if ((ob3->type != PORT) && (portnode == NULL))
break;
else if ((ob3->type == PORT) && (ob3->node == chknode->node))
portnode = ob3;
else if ((ob3->type >= FIRSTPIN) && (ob3->node == chknode->node))
break;
}
if ((ob3 == NULL) && (portnode != NULL)) {
/* Port became disconnected when child was flattened */
portnode->node = -1;
}
FREE(chknode);
}
CacheNodeNames(ThisCell);
ThisCell->dumped = 1; /* indicate cell has been flattened */
return numflat;
@@ -1888,6 +1967,16 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if (ecomp->cell1->class != CLASS_ISOURCE) {
/* merge node of endpoints */
/* Prefer a port node over a non-port node */
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
if (!IsPort(ob2)) break;
else if (ob2->node == node1) break;
else if (ob2->node == node2) {
int ntemp = node1;
node1 = node2;
node2 = ntemp;
}
}
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
if (ob2->node == node2)
ob2->node = node1;
@@ -1996,6 +2085,16 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
/* merge node of endpoints */
if (ecomp->cell2->class != CLASS_ISOURCE) {
/* Prefer a port node over a non-port node */
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
if (!IsPort(ob1)) break;
else if (ob1->node == node1) break;
else if (ob1->node == node2) {
int ntemp = node1;
node1 = node2;
node2 = ntemp;
}
}
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
if (ob1->node == node2)
ob1->node = node1;
+2 -1
View File
@@ -17,6 +17,7 @@ along with this program; see the file copying. If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* inetcomp.c -- a simple wrapper to the NETCOMP() function */
#include "config.h"
#include <stdio.h>
#include "netgen.h"
@@ -33,7 +34,7 @@ void STRCPY(char *dest, char *source)
int main(int argc, char *argv[])
{
char cell1[200], cell2[200];
char cell1[MAX_STR_LEN], cell2[MAX_STR_LEN];
Debug = 0;
if (argc != 1) {
+674 -302
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -7,6 +7,7 @@ extern struct nlist *Circuit1;
extern struct nlist *Circuit2;
extern int ExhaustiveSubdivision;
extern int ExactTopology;
extern int left_col_end;
extern int right_col_end;
@@ -37,7 +38,8 @@ extern int PermuteSetup(char *model, int filenum, char *pin1, char *pin2);
extern int PermuteForget(char *model, int filenum, char *pin1, char *pin2);
extern int EquivalenceElements(char *name1, int file1, char *name2, int file2);
extern int EquivalenceNodes(char *name1, int file1, char *name2, int file2);
extern int EquivalenceClasses(char *name1, int file1, char *name2, int file2);
extern int EquivalenceClasses(char *name1, int file1, char *name2, int file2,
int dounique);
extern int IgnoreClass(char *name, int file, unsigned char type);
extern int MatchPins(struct nlist *tp1, struct nlist *tp2, int dolist);
extern int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run,
+18 -4
View File
@@ -183,7 +183,6 @@ void CloseFile(char *filename)
fclose(outfile);
}
/* STUFF TO READ INPUT FILES */
static char *line = NULL; /* actual line read in */
@@ -207,6 +206,21 @@ struct hashdict *definitions = (struct hashdict *)NULL;
#define WHITESPACE_DELIMITER " \t\n\r"
/*----------------------------------------------------------------------*/
/* Seek and Tell on infile stream, for use with handling generate */
/* loops in verilog. */
/*----------------------------------------------------------------------*/
void SeekFile(long offset)
{
fseek(infile, offset, SEEK_SET);
}
long TellFile()
{
return ftell(infile);
}
/*----------------------------------------------------------------------*/
/* TrimQuoted() --- */
/* Remove spaces from inside single- or double-quoted strings. */
@@ -914,7 +928,7 @@ char *ReadNetlist(char *fname, int *fnum)
}
/* try appending extensions in sequence, and testing for file existance */
for (index = 0; formats[index].extension != NULL; index++) {
char testname[200];
char testname[MAX_STR_LEN];
strcpy(testname, fname);
strcat(testname, formats[index].extension);
if (OpenParseFile(testname, *fnum) >= 0) {
@@ -1019,7 +1033,7 @@ void WriteNetgenFile(char *name, char *filename)
char *ReadNetgenFile (char *fname, int *fnum)
{
char name[100];
char name[MAX_STR_LEN];
char *LastCellRead = NULL;
int filenum;
@@ -1255,7 +1269,7 @@ int READ(void *buf, int bytes)
char *ReadNetgenFile (char *fname, int *fnum)
{
char name[100];
char name[MAX_STR_LEN];
int len, chars;
char *LastCellRead = NULL;
+2
View File
@@ -47,5 +47,7 @@ extern void InputParseError(FILE *f);
extern int OpenParseFile(char *name, int fnum);
extern int EndParseFile(void);
extern int CloseParseFile(void);
extern void SeekFile(long offset); /* handles verilog 'for' loops */
extern long TellFile(); /* handles verilog 'for' loops */
#endif /* _NETFILE_H */
+46 -1
View File
@@ -57,7 +57,7 @@ int AddToExistingDefinition = 0; /* default: overwrite cell when reopened */
extern int errno; /* Defined in stdlib.h */
#define MAX_STATIC_STRINGS 5
static char staticstrings[MAX_STATIC_STRINGS][200];
static char staticstrings[MAX_STATIC_STRINGS][MAX_STR_LEN];
static int laststring;
extern struct hashdict spiceparams; /* From spice.c */
@@ -984,6 +984,51 @@ PropertyDelete(char *name, int fnum, char *key)
return 0;
}
/*----------------------------------------------------------------------*/
/* Associate a property with a specific pin */
/*----------------------------------------------------------------------*/
int
PropertyAssociatePin(char *name, int fnum, char *key, char *pin)
{
struct property *kl = NULL;
struct nlist *tc;
struct objlist *ob;
int result;
if ((fnum == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
result = PropertyAssociatePin(name, Circuit1->file, key, pin);
result = PropertyAssociatePin(name, Circuit2->file, key, pin);
return result;
}
tc = LookupCellFile(name, fnum);
if (tc == NULL) {
Printf("No device %s found for PropertyAssociatePin()\n", name);
return -1;
}
kl = (struct property *)HashLookup(key, &(tc->propdict));
if (kl == NULL) {
Printf("No property %s found for device %s\n", key, name);
return -1;
}
else {
for (ob = tc->cell; ob != NULL; ob = ob->next) {
if (ob->type != PORT) break;
else if ((*matchfunc)(ob->name, pin)) {
kl->pin = ob->name;
break;
}
}
if (ob == NULL) {
Printf("No pin %s found for device %s\n", pin, name);
return -1;
}
}
return 0;
}
/*----------------------------------------------------------------------*/
/* Set the tolerance of a property in the master cell record. */
/*----------------------------------------------------------------------*/
+1
View File
@@ -39,6 +39,7 @@ extern void SetParallelCombine(int value);
extern void SetSeriesCombine(int value);
extern int PropertyTolerance(char *name, int fnum, char *key, int ival,
double dval);
extern int PropertyAssociatePin(char *name, int fnum, char *key, char *pin);
extern int PropertyMerge(char *name, int fnum, char *key, int merge_type,
int merge_mask);
extern void ResolveProperties(char *name1, int file1, char *name2, int file2);
+2 -2
View File
@@ -181,7 +181,7 @@ void Ntk(char *name, char *filename)
char *ReadNtk (char *fname, int *fnum)
{
char model[100], instancename[100], name[100];
char model[MAX_STR_LEN], instancename[MAX_STR_LEN], name[MAX_STR_LEN];
struct objlist *ob;
int CellDefInProgress = 0;
int filenum;
@@ -218,7 +218,7 @@ char *ReadNtk (char *fname, int *fnum)
}
}
else if (match(nexttok, "s")) {
char last[100];
char last[MAX_STR_LEN];
*last = '\0';
if (!CellDefInProgress) {
/* fake cell declaration for top-level call */
+42 -3
View File
@@ -130,6 +130,7 @@ struct property *NewProperty(void)
kl = (struct property *)CALLOC(1,sizeof(struct property));
if (kl == NULL) Fprintf(stderr,"NewProperty: Core allocation error\n");
kl->pin = (char *)NULL;
return (kl);
}
@@ -440,15 +441,32 @@ void RemoveShorted(char *class, int file)
RecurseCellFileHashTable(removeshorted, file);
}
/* Remove instances of a deleted class from the database. */
/* NOTE: This treats deleted classes as not existing, so it */
/* needs to take care of disconnected ports in the same manner */
/* as flattenInstancesOf() in disconnecting the port of a */
/* parent cell if it connected to nothing other than the */
/* deleted instance. */
int deleteclass(struct hashlist *p, int file)
{
struct nlist *ptr;
struct objlist *ob, *lob, *nob;
struct objlist *ob, *lob, *nob, *portnode;
unsigned char *checknodes;
int i;
ptr = (struct nlist *)(p->ptr);
if ((file != -1) && (ptr->file != file)) return 0;
/* Note: This could be made faster by enumerating all times each
* node is used during the full pass, then subtracting each time
* the node is deleted in a child, then disconnecting all nodes
* that ended up with a zero count.
*/
checknodes = (unsigned char *)CALLOC(ptr->nodename_cache_maxnodenum + 1,
sizeof(unsigned char));
lob = NULL;
for (ob = ptr->cell; ob != NULL;) {
nob = ob->next;
@@ -456,6 +474,8 @@ int deleteclass(struct hashlist *p, int file)
if ((*matchfunc)(ob->model.class, OldCell->name)) {
HashDelete(ob->instance.name, &(ptr->instdict));
while (1) {
if (ob->type >= FIRSTPIN)
checknodes[ob->node] = (unsigned char)1;
FreeObjectAndHash(ob, ptr);
ob = nob;
if (ob == NULL) break;
@@ -477,6 +497,25 @@ int deleteclass(struct hashlist *p, int file)
ob = nob;
}
}
for (i = 0; i <= ptr->nodename_cache_maxnodenum; i++) {
if (checknodes[i] != 0) {
portnode = NULL;
for (ob = ptr->cell; ob != NULL; ob = ob->next) {
if ((ob->type != PORT) && (portnode == NULL))
break;
else if ((ob->type == PORT) && (ob->node == i))
portnode = ob;
else if ((ob->type >= FIRSTPIN) && (ob->node == i))
break;
}
if ((ob == NULL) && (portnode != NULL)) {
/* Port became disconnected when child was deleted */
portnode->node = -1;
}
}
}
FREE(checknodes);
}
/* Remove all instances of class "class" from the database */
@@ -697,7 +736,7 @@ struct nlist *RecurseCellHashTable2(struct nlist *(*foo)(struct hashlist *,
char *FixTemplate(char *t)
{
char buffer[200];
char buffer[MAX_STR_LEN];
char *rstr;
int i,j;
int InsideBrace;
@@ -1208,7 +1247,7 @@ static char *OldNodeName(struct nlist *tp, int node)
struct objlist *firstuniqueglobal;
struct objlist *firstglobal;
struct objlist *firstpin;
static char StrBuffer[100];
static char StrBuffer[MAX_STR_LEN];
#if 0
/* make second pass, looking for ports */
+11 -9
View File
@@ -135,6 +135,7 @@ struct property {
unsigned char idx; /* index into valuelist */
unsigned char type; /* string, integer, double, value, expression */
unsigned char merge; /* how property changes when devices are merged */
char *pin; /* associated pin (or NULL if not associated) */
union {
char *string;
double dval;
@@ -206,7 +207,7 @@ struct nlist {
char *name;
int number; /* number of instances defined */
int dumped; /* instance count, and general-purpose marker */
unsigned char flags;
unsigned short flags;
unsigned char class;
unsigned long classhash; /* randomized hash value for cell class */
struct Permutation *permutes; /* list of permuting pins */
@@ -222,17 +223,18 @@ struct nlist {
/* Defined nlist structure flags */
#define CELL_MATCHED 0x01 /* cell matched to another */
#define CELL_NOCASE 0x02 /* cell is case-insensitive (e.g., SPICE) */
#define CELL_TOP 0x04 /* cell is a top-level cell */
#define CELL_PLACEHOLDER 0x08 /* cell is a placeholder cell */
#define CELL_PROPSMATCHED 0x10 /* properties matched to matching cell */
#define CELL_DUPLICATE 0x20 /* cell has a duplicate */
#define CELL_MATCHED 0x001 /* cell matched to another */
#define CELL_NOCASE 0x002 /* cell is case-insensitive (e.g., SPICE) */
#define CELL_TOP 0x004 /* cell is a top-level cell */
#define CELL_PLACEHOLDER 0x008 /* cell is a placeholder cell */
#define CELL_PROPSMATCHED 0x010 /* properties matched to matching cell */
#define CELL_DUPLICATE 0x020 /* cell has a duplicate */
#define CELL_VERILOG 0x040 /* cell is verilog module */
/* Flags for combination allowances and prohibitions */
#define COMB_SERIES 0x40
#define COMB_NO_PARALLEL 0x80
#define COMB_SERIES 0x100
#define COMB_NO_PARALLEL 0x200
extern struct nlist *CurrentCell;
extern struct objlist *CurrentTail;
+9 -9
View File
@@ -511,8 +511,8 @@ int OpenEmbeddingFile(char *cellname, char *filename)
/* returns 1 if OK */
{
struct nlist *tp;
char outfilename[200];
char logfilename[200];
char outfilename[MAX_STR_LEN];
char logfilename[MAX_STR_LEN];
tp = LookupCell(cellname);
if (tp == NULL) {
@@ -783,7 +783,7 @@ void SetupArray(char *prompt1, char *prompt2, char *prompt3, int *data,
void (*proc)(void))
{
int i, oldfanout;
char name[100];
char name[MAX_STR_LEN];
Printf(prompt1);
for (i = 1; i <= MAX_TREE_DEPTH; i++)
@@ -792,7 +792,7 @@ void SetupArray(char *prompt1, char *prompt2, char *prompt3, int *data,
oldfanout = 1;
for (i = 1; i <= MAX_TREE_DEPTH; i++) {
char prompt[100];
char prompt[MAX_STR_LEN];
int newfanout;
sprintf(prompt, prompt2, i);
promptstring(prompt, name);
@@ -822,7 +822,7 @@ void SetupArrayFromString(char *prompt1, char *prompt3, int *data,
void (*proc)(void), char *text)
{
int i, oldfanout, newfanout;
char string[100];
char string[MAX_STR_LEN];
char *ch;
char *endch;
@@ -962,7 +962,7 @@ void ProtoPrintParameters(void)
void PROTOCHIP(void)
/* a simple command interpreter to manage embedding/routing */
{
char name[100];
char name[MAX_STR_LEN];
char ch;
InitializeFanout();
@@ -1136,7 +1136,7 @@ void PROTOCHIP(void)
oldfanout = 1;
for (i = 1; i <= MAX_TREE_DEPTH; i++) {
char prompt[100];
char prompt[MAX_STR_LEN];
int newfanout;
sprintf(prompt,"Fanout for level %d (0 to quit): ",i);
promptstring(prompt, name);
@@ -1168,7 +1168,7 @@ void PROTOCHIP(void)
oldfanout = 1;
for (i = 1; i <= MAX_TREE_DEPTH; i++) {
char prompt[100];
char prompt[MAX_STR_LEN];
int newfanout;
sprintf(prompt,"Common nodes for level %d (0 to quit): ",i);
promptstring(prompt, name);
@@ -1200,7 +1200,7 @@ void PROTOCHIP(void)
oldfanout = 1;
for (i = 1; i <= MAX_TREE_DEPTH; i++) {
char prompt[100];
char prompt[MAX_STR_LEN];
int newfanout;
sprintf(prompt,"Used leaves for level %d (0 to quit): ",i);
promptstring(prompt, name);
+3 -3
View File
@@ -37,7 +37,7 @@ extern int ColumnBase;
struct filestr {
FILE *f;
char buffer[200];
char buffer[MAX_STR_LEN];
int wrap; /* column to wrap around in, or 0 if no wrap */
} file_buffers[MAXFILES];
@@ -107,7 +107,7 @@ void Fprintf(FILE *f, char *format, ...)
{
va_list ap;
int FileIndex;
char tmpstr[200];
char tmpstr[MAX_STR_LEN];
int bufferlongenough;
int linewrapexceeded;
@@ -203,7 +203,7 @@ void Printf(char *format, ...)
void Printf(char *format, ...)
{
va_list ap;
char tmpstr[200];
char tmpstr[MAX_STR_LEN];
va_start(ap, format);
vsprintf(tmpstr, format, ap);
+4 -4
View File
@@ -52,7 +52,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/*************************************************************************/
static int SuppressPrompts = 0;
static char InputLine[200];
static char InputLine[MAX_STR_LEN];
void typeahead(char *str)
{
@@ -73,7 +73,7 @@ but reads from 'promptstring_infile' if nec. */
/* If interactive, puts out 'prompt' */
{
char *nexttok;
char tmpstr[200];
char tmpstr[MAX_STR_LEN];
int echo;
if (promptstring_infile == NULL)
@@ -959,8 +959,8 @@ void Query(void)
{
/* little interactive debugger */
char reply;
char repstr[100];
char repstr2[100];
char repstr[MAX_STR_LEN];
char repstr2[MAX_STR_LEN];
float StartTime; /* for elapsed CPU times */
int Timing; /* if true, print times of each command */
int filenum = -1;
+117 -105
View File
@@ -518,13 +518,13 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
int warnings = 0, update = 0, hasports = 0;
char *eqptr, devtype, in_subckt;
struct keyvalue *kvlist = NULL;
char inst[256], model[256], instname[256];
char inst[MAX_STR_LEN], model[MAX_STR_LEN], instname[MAX_STR_LEN];
struct nlist *tp;
struct objlist *parent, *sobj, *nobj, *lobj, *pobj;
inst[255] = '\0';
model[255] = '\0';
instname[255] = '\0';
inst[MAX_STR_LEN-1] = '\0';
model[MAX_STR_LEN-1] = '\0';
instname[MAX_STR_LEN-1] = '\0';
in_subckt = (char)0;
while (!EndParseFile()) {
@@ -555,7 +555,7 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
/* Check for existence of the cell. We may need to rename it. */
snprintf(model, 99, "%s", nexttok);
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
tp = LookupCellFile(nexttok, filenum);
/* Check for name conflict with duplicate cell names */
@@ -703,7 +703,7 @@ skip_ends:
SpiceTokNoNewline();
if (nexttok == NULL) continue; /* Ignore if no model name */
snprintf(model, 99, "%s", nexttok);
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
@@ -887,29 +887,29 @@ skip_ends:
}
else if (toupper(nexttok[0]) == 'Q') {
char emitter[100], base[100], collector[100];
emitter[99] = '\0';
base[99] = '\0';
collector[99] = '\0';
char emitter[MAX_STR_LEN], base[MAX_STR_LEN], collector[MAX_STR_LEN];
emitter[MAX_STR_LEN-1] = '\0';
base[MAX_STR_LEN-1] = '\0';
collector[MAX_STR_LEN-1] = '\0';
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
}
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(collector, nexttok, 99); SpiceTokNoNewline();
strncpy(collector, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(base, nexttok, 99); SpiceTokNoNewline();
strncpy(base, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(emitter, nexttok, 99); SpiceTokNoNewline();
strncpy(emitter, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
/* make sure all the nodes exist */
if (LookupObject(collector, CurrentCell) == NULL) Node(collector);
if (LookupObject(base, CurrentCell) == NULL) Node(base);
if (LookupObject(emitter, CurrentCell) == NULL) Node(emitter);
/* Read the device model */
snprintf(model, 99, "%s", nexttok);
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
while (nexttok != NULL)
{
@@ -940,30 +940,30 @@ skip_ends:
goto baddevice;
}
snprintf(instname, 255, "%s:%s", model, inst);
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
Cell(instname, model, collector, base, emitter);
pobj = LinkProperties(model, kvlist);
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
DeleteProperties(&kvlist);
}
else if (toupper(nexttok[0]) == 'M') {
char drain[100], gate[100], source[100], bulk[100];
drain[99] = '\0';
gate[99] = '\0';
source[99] = '\0';
bulk[99] = '\0';
char drain[MAX_STR_LEN], gate[MAX_STR_LEN], source[MAX_STR_LEN], bulk[MAX_STR_LEN];
drain[MAX_STR_LEN-1] = '\0';
gate[MAX_STR_LEN-1] = '\0';
source[MAX_STR_LEN-1] = '\0';
bulk[MAX_STR_LEN-1] = '\0';
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
}
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(drain, nexttok, 99); SpiceTokNoNewline();
strncpy(drain, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(gate, nexttok, 99); SpiceTokNoNewline();
strncpy(gate, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(source, nexttok, 99); SpiceTokNoNewline();
strncpy(source, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
/* make sure all the nodes exist */
if (LookupObject(drain, CurrentCell) == NULL) Node(drain);
@@ -971,11 +971,11 @@ skip_ends:
if (LookupObject(source, CurrentCell) == NULL) Node(source);
/* handle the substrate node */
strncpy(bulk, nexttok, 99); SpiceTokNoNewline();
strncpy(bulk, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (LookupObject(bulk, CurrentCell) == NULL) Node(bulk);
/* Read the device model */
snprintf(model, 99, "%s", nexttok);
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
while (nexttok != NULL)
{
@@ -1013,7 +1013,7 @@ skip_ends:
goto baddevice;
}
snprintf(instname, 255, "%s:%s", model, inst);
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
Cell(instname, model, drain, gate, source, bulk);
pobj = LinkProperties(model, kvlist);
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
@@ -1027,19 +1027,19 @@ skip_ends:
SpiceSkipNewLine();
}
else {
char ctop[100], cbot[100];
ctop[99] = '\0';
cbot[99] = '\0';
char ctop[MAX_STR_LEN], cbot[MAX_STR_LEN];
ctop[MAX_STR_LEN-1] = '\0';
cbot[MAX_STR_LEN-1] = '\0';
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
}
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(ctop, nexttok, 99); SpiceTokNoNewline();
strncpy(ctop, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(cbot, nexttok, 99); SpiceTokNoNewline();
strncpy(cbot, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
/* make sure all the nodes exist */
if (LookupObject(ctop, CurrentCell) == NULL) Node(ctop);
@@ -1058,7 +1058,7 @@ skip_ends:
model[0] = '\0';
if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL))
snprintf(model, 99, "%s", nexttok);
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
/* Any other device properties? */
while (nexttok != NULL)
@@ -1071,7 +1071,7 @@ skip_ends:
}
else if (!strncmp(nexttok, "$[", 2)) {
// Support for CDL modeled capacitor format
snprintf(model, 99, "%s", nexttok + 2);
snprintf(model, MAX_STR_LEN-1, "%s", nexttok + 2);
if ((eqptr = strchr(model, ']')) != NULL)
*eqptr = '\0';
}
@@ -1104,7 +1104,7 @@ skip_ends:
usemodel = 1;
}
snprintf(instname, 255, "%s:%s", model, inst);
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
if (usemodel)
Cell(instname, model, ctop, cbot);
else
@@ -1121,19 +1121,19 @@ skip_ends:
SpiceSkipNewLine();
}
else {
char rtop[100], rbot[100];
rtop[99] = '\0';
rbot[99] = '\0';
char rtop[MAX_STR_LEN], rbot[MAX_STR_LEN];
rtop[MAX_STR_LEN-1] = '\0';
rbot[MAX_STR_LEN-1] = '\0';
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
}
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(rtop, nexttok, 99); SpiceTokNoNewline();
strncpy(rtop, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(rbot, nexttok, 99); SpiceTokNoNewline();
strncpy(rbot, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
/* make sure all the nodes exist */
if (LookupObject(rtop, CurrentCell) == NULL) Node(rtop);
if (LookupObject(rbot, CurrentCell) == NULL) Node(rbot);
@@ -1152,7 +1152,7 @@ skip_ends:
model[0] = '\0';
if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL))
snprintf(model, 99, "%s", nexttok);
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
/* Any other device properties? */
while (nexttok != NULL) {
@@ -1164,7 +1164,7 @@ skip_ends:
}
else if (!strncmp(nexttok, "$[", 2)) {
// Support for CDL modeled resistor format
snprintf(model, 99, "%s", nexttok + 2);
snprintf(model, MAX_STR_LEN-1, "%s", nexttok + 2);
if ((eqptr = strchr(model, ']')) != NULL)
*eqptr = '\0';
}
@@ -1197,7 +1197,7 @@ skip_ends:
else
strcpy(model, "r"); /* Use default resistor model */
snprintf(instname, 255, "%s:%s", model, inst);
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
if (usemodel)
Cell(instname, model, rtop, rbot);
else
@@ -1208,25 +1208,25 @@ skip_ends:
}
}
else if (toupper(nexttok[0]) == 'D') { /* diode */
char cathode[100], anode[100];
cathode[99] = '\0';
anode[99] = '\0';
char cathode[MAX_STR_LEN], anode[MAX_STR_LEN];
cathode[MAX_STR_LEN-1] = '\0';
anode[MAX_STR_LEN-1] = '\0';
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
}
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(anode, nexttok, 99); SpiceTokNoNewline();
strncpy(anode, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(cathode, nexttok, 99); SpiceTokNoNewline();
strncpy(cathode, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
/* make sure all the nodes exist */
if (LookupObject(anode, CurrentCell) == NULL) Node(anode);
if (LookupObject(cathode, CurrentCell) == NULL) Node(cathode);
/* Read the device model */
snprintf(model, 99, "%s", nexttok);
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
while (nexttok != NULL)
{
@@ -1255,7 +1255,7 @@ skip_ends:
Fprintf(stderr, "Device \"%s\" has wrong number of ports for a diode.\n");
goto baddevice;
}
snprintf(instname, 255, "%s:%s", model, inst);
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
Cell(instname, model, anode, cathode);
pobj = LinkProperties(model, kvlist);
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
@@ -1268,25 +1268,25 @@ skip_ends:
SpiceSkipNewLine();
}
else {
char node1[100], node2[100], node3[100], node4[100];
node1[99] = '\0';
node2[99] = '\0';
node3[99] = '\0';
node4[99] = '\0';
char node1[MAX_STR_LEN], node2[MAX_STR_LEN], node3[MAX_STR_LEN], node4[MAX_STR_LEN];
node1[MAX_STR_LEN-1] = '\0';
node2[MAX_STR_LEN-1] = '\0';
node3[MAX_STR_LEN-1] = '\0';
node4[MAX_STR_LEN-1] = '\0';
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
}
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(node1, nexttok, 99); SpiceTokNoNewline();
strncpy(node1, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(node2, nexttok, 99); SpiceTokNoNewline();
strncpy(node2, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(node3, nexttok, 99); SpiceTokNoNewline();
strncpy(node3, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(node4, nexttok, 99); SpiceTokNoNewline();
strncpy(node4, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
/* make sure all the nodes exist */
if (LookupObject(node1, CurrentCell) == NULL) Node(node1);
if (LookupObject(node2, CurrentCell) == NULL) Node(node2);
@@ -1298,7 +1298,7 @@ skip_ends:
model[0] = '\0';
if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL))
snprintf(model, 99, "%s", nexttok);
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
/* Any other device properties? */
while (nexttok != NULL) {
@@ -1334,7 +1334,7 @@ skip_ends:
else
strcpy(model, "t"); /* Use default xline model */
snprintf(instname, 255, "%s:%s", model, inst);
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
if (usemodel)
Cell(instname, model, node1, node2, node3, node4);
@@ -1347,20 +1347,20 @@ skip_ends:
}
}
else if (toupper(nexttok[0]) == 'L') { /* inductor */
char end_a[100], end_b[100];
char end_a[MAX_STR_LEN], end_b[MAX_STR_LEN];
int usemodel = 0;
end_a[99] = '\0';
end_b[99] = '\0';
end_a[MAX_STR_LEN-1] = '\0';
end_b[MAX_STR_LEN-1] = '\0';
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
}
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(end_a, nexttok, 99); SpiceTokNoNewline();
strncpy(end_a, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(end_b, nexttok, 99); SpiceTokNoNewline();
strncpy(end_b, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
/* make sure all the nodes exist */
if (LookupObject(end_a, CurrentCell) == NULL) Node(end_a);
if (LookupObject(end_b, CurrentCell) == NULL) Node(end_b);
@@ -1379,7 +1379,7 @@ skip_ends:
model[0] = '\0';
if ((nexttok != NULL) && ((eqptr = strchr(nexttok, '=')) == NULL))
snprintf(model, 99, "%s", nexttok);
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
/* Any other device properties? */
while (nexttok != NULL)
@@ -1417,7 +1417,7 @@ skip_ends:
else
strcpy(model, "l"); /* Use default inductor model */
snprintf(instname, 255, "%s:%s", model, inst);
snprintf(instname, MAX_STR_LEN-1, "%s:%s", model, inst);
if (usemodel)
Cell(instname, model, end_a, end_b);
else
@@ -1431,19 +1431,19 @@ skip_ends:
/* black-box subcircuits (class MODULE): V, I, E */
else if (toupper(nexttok[0]) == 'V') { /* voltage source */
char pos[100], neg[100];
pos[99] = '\0';
neg[99] = '\0';
char pos[MAX_STR_LEN], neg[MAX_STR_LEN];
pos[MAX_STR_LEN-1] = '\0';
neg[MAX_STR_LEN-1] = '\0';
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
}
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(pos, nexttok, 99); SpiceTokNoNewline();
strncpy(pos, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(neg, nexttok, 99); SpiceTokNoNewline();
strncpy(neg, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
/* make sure all the nodes exist */
if (LookupObject(pos, CurrentCell) == NULL) Node(pos);
@@ -1499,19 +1499,19 @@ skip_ends:
DeleteProperties(&kvlist);
}
else if (toupper(nexttok[0]) == 'I') { /* current source */
char pos[100], neg[100];
pos[99] = '\0';
neg[99] = '\0';
char pos[MAX_STR_LEN], neg[MAX_STR_LEN];
pos[MAX_STR_LEN-1] = '\0';
neg[MAX_STR_LEN-1] = '\0';
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
}
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(pos, nexttok, 99); SpiceTokNoNewline();
strncpy(pos, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(neg, nexttok, 99); SpiceTokNoNewline();
strncpy(neg, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
/* make sure all the nodes exist */
if (LookupObject(pos, CurrentCell) == NULL) Node(pos);
if (LookupObject(neg, CurrentCell) == NULL) Node(neg);
@@ -1553,25 +1553,25 @@ skip_ends:
DeleteProperties(&kvlist);
}
else if (toupper(nexttok[0]) == 'E') { /* controlled voltage source */
char pos[100], neg[100], ctrlp[100], ctrln[100];
pos[99] = '\0';
neg[99] = '\0';
ctrlp[99] = '\0';
ctrln[99] = '\0';
char pos[MAX_STR_LEN], neg[MAX_STR_LEN], ctrlp[MAX_STR_LEN], ctrln[MAX_STR_LEN];
pos[MAX_STR_LEN-1] = '\0';
neg[MAX_STR_LEN-1] = '\0';
ctrlp[MAX_STR_LEN-1] = '\0';
ctrln[MAX_STR_LEN-1] = '\0';
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
}
strncpy(inst, nexttok + 1, 99); SpiceTokNoNewline();
strncpy(inst, nexttok + 1, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(pos, nexttok, 99); SpiceTokNoNewline();
strncpy(pos, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(neg, nexttok, 99); SpiceTokNoNewline();
strncpy(neg, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(ctrlp, nexttok, 99); SpiceTokNoNewline();
strncpy(ctrlp, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
if (nexttok == NULL) goto baddevice;
strncpy(ctrln, nexttok, 99); SpiceTokNoNewline();
strncpy(ctrln, nexttok, MAX_STR_LEN-1); SpiceTokNoNewline();
/* make sure all the nodes exist */
if (LookupObject(pos, CurrentCell) == NULL) Node(pos);
@@ -1619,11 +1619,11 @@ skip_ends:
}
else if (toupper(nexttok[0]) == 'X') { /* subcircuit instances */
char instancename[100], subcktname[100];
char instancename[MAX_STR_LEN], subcktname[MAX_STR_LEN];
int itype, in_props;
instancename[99] = '\0';
subcktname[99] = '\0';
instancename[MAX_STR_LEN-1] = '\0';
subcktname[MAX_STR_LEN-1] = '\0';
struct portelement {
char *name;
@@ -1633,8 +1633,8 @@ skip_ends:
struct portelement *head, *tail, *scan, *scannext;
struct objlist *obptr;
snprintf(instancename, 99, "%s", nexttok + 1);
strncpy(instancename, nexttok + 1, 99);
snprintf(instancename, MAX_STR_LEN-1, "%s", nexttok + 1);
strncpy(instancename, nexttok + 1, MAX_STR_LEN-1);
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
@@ -1742,14 +1742,14 @@ skip_ends:
/* names. */
if (strncmp(instancename, scan->name, strlen(scan->name))) {
snprintf(subcktname, 99, "%s:%s", scan->name, instancename);
snprintf(subcktname, MAX_STR_LEN-1, "%s:%s", scan->name, instancename);
strcpy(instancename, subcktname);
}
else {
snprintf(subcktname, 99, "/%s", instancename);
snprintf(subcktname, MAX_STR_LEN-1, "/%s", instancename);
strcpy(instancename, subcktname);
}
snprintf(subcktname, 99, "%s", scan->name);
snprintf(subcktname, MAX_STR_LEN-1, "%s", scan->name);
if (scan == head) {
head = NULL;
@@ -1783,6 +1783,18 @@ skip_ends:
ReopenCellDef((*CellStackPtr)->cellname, filenum); /* Reopen */
update = 1;
}
else if (tp->flags & CELL_VERILOG) {
if (tp->flags & CELL_PLACEHOLDER) {
/* Flag this as an error. To do: Rearrange the verilog instance pins to */
/* match the SPICE subcircuit pin order. */
Fprintf(stderr, "Error: SPICE subcircuit %s should be read before verilog "
"module using it, or pins may not match!\n", subcktname);
}
else {
Fprintf(stderr, "Error: SPICE subcircuit %s redefines a verilog module!\n",
subcktname);
}
}
/* nexttok is now NULL, scan->name points to class */
@@ -1985,7 +1997,7 @@ void IncludeSpice(char *fname, int parent, struct cellstack **CellStackPtr,
int blackbox)
{
int filenum = -1;
char name[256];
char name[MAX_STR_LEN];
/* If fname does not begin with "/", then assume that it is */
/* in the same relative path as its parent. */
+2
View File
@@ -34,6 +34,8 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "print.h"
#endif
extern void Finsert(FILE *f);
void test_entry(void)
{
+471 -53
View File
@@ -42,6 +42,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <stdlib.h> /* for calloc(), free(), getenv() */
#include <ctype.h> /* for isalnum() */
#ifndef IBMPC
#include <sys/types.h> /* for getpwnam() tilde expansion */
#include <pwd.h>
@@ -63,6 +64,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define VLOG_EQUATION_DELIMITERS "X///**/#((**)X,;:(){}[]=+-*/"
#define VLOG_PIN_NAME_DELIMITERS "X///**/(**)X()"
#define VLOG_PIN_CHECK_DELIMITERS "X///**/(**)X,;(){}"
#define VLOG_INTEGER_DELIMITERS "X///**/X;[]"
// Used by portelement structure "flags" record.
#define PORT_NOT_FOUND 0
@@ -83,6 +85,16 @@ struct bus {
int end;
};
// Global storage for a 'for' loop
struct _loop {
char *loopvar;
int start;
int end;
long filepos;
};
struct _loop loop;
// Free a bus structure in the hash table during cleanup
int freebus (struct hashlist *p)
@@ -244,7 +256,16 @@ int EvalExpr(struct expr_stack **stackptr, int *valptr)
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')) {
/* Watch for (a)*b+c or a+b*(c); multiplies must be solved first */
if ((texp->last->last != NULL) && ((texp->last->last->oper == '*')
|| (texp->last->last->oper == '/'))) {
/* Do nothing */
}
else if ((texp->next->next != NULL) && ((texp->next->next->oper == '*')
|| (texp->next->next->oper == '/'))) {
/* Do nothing */
}
else if ((texp->last->oper == '\0') && (texp->next->oper == '\0')) {
if (texp->oper == '-') {
/* Subtract */
texp->last->value -= texp->next->value;
@@ -290,6 +311,7 @@ int EvalExpr(struct expr_stack **stackptr, int *valptr)
}
}
}
}
/* If only one numerical item remains, then place it in valptr and return 1 */
@@ -311,6 +333,134 @@ int EvalExpr(struct expr_stack **stackptr, int *valptr)
return 0;
}
//-------------------------------------------------------------------------
// Parse an expression which must resolve to a single integer.
// If it does, return "1" and put the integer in the return
// pointer "iptr". If not, return "0" and iptr is undefined.
// The expression may use parameters, standard arithmetic,
// and parenthetic grouping. This routine does not tokenize input
// but assumes that the entire expression is in the string "expr".
//-------------------------------------------------------------------------
int ParseIntegerExpression(char *expr, int *iptr)
{
int result, value;
char *sptr, *cptr, savec;
struct property *kl = NULL;
struct expr_stack *stack, *newexp;
stack = NULL;
savec = '\0';
sptr = expr;
result = 1;
while (sptr && (*sptr != '\0')) {
// Move sptr to first non-space character
while (isspace(*sptr)) sptr++;
// Tokenize. Look ahead to next delimeter and truncate string there.
cptr = sptr + 1;
if (isalnum(*sptr) || (*sptr == '_') || (*sptr == '$')) {
while (*cptr != '\0') {
if (isalnum(*cptr)) cptr++;
else if ((*cptr == '_') || (*cptr == '$')) cptr++;
else break;
}
}
savec = *cptr;
*cptr = '\0';
if (match(sptr, "+") || match(sptr, "-")
|| match(sptr, "*") || match(sptr, "/")
|| match(sptr, "(") || match(sptr, ")")) {
newexp = (struct expr_stack *)MALLOC(sizeof(struct expr_stack));
newexp->oper = *sptr;
newexp->value = 0;
newexp->next = NULL;
newexp->last = stack;
if (stack) stack->next = newexp;
stack = newexp;
sptr = cptr;
*cptr = savec;
continue;
}
if ((result = sscanf(sptr, "%d", &value)) != 1) {
// Is name in the parameter list?
kl = (struct property *)HashLookup(nexttok, &verilogparams);
if (kl == NULL) {
Printf("Value %s in expression is not a number or a parameter.\n",
sptr);
value = 0;
break;
}
else {
if (kl->type == PROP_STRING) {
result = sscanf(kl->pdefault.string, "%d", &value);
if (result != 1) {
Printf("Parameter %s has value %s that cannot be parsed"
" as an integer.\n",
nexttok, kl->pdefault.string);
value = 0;
break;
}
}
else if (kl->type == PROP_INTEGER) {
value = kl->pdefault.ival;
}
else if (kl->type == PROP_DOUBLE) {
value = (int)kl->pdefault.dval;
if ((double)value != kl->pdefault.dval) {
Printf("Parameter %s has value %g that cannot be parsed"
" as an integer.\n",
nexttok, kl->pdefault.dval);
value = 0;
break;
}
}
else {
Printf("Parameter %s has unknown type; don't know how"
" to parse.\n", nexttok);
value = 0;
break;
}
}
}
newexp = (struct expr_stack *)MALLOC(sizeof(struct expr_stack));
newexp->oper = '\0';
newexp->value = value;
newexp->next = NULL;
newexp->last = stack;
if (stack) stack->next = newexp;
stack = newexp;
/* Move to next token */
sptr = cptr;
*cptr = savec;
}
if (result != 0) {
if (stack == NULL) {
Printf("Empty array found.\n");
result = 0;
}
else if (EvalExpr(&stack, iptr) != 1) {
Printf("Bad expression found in array.\n");
result = 0;
}
}
/* In case of error, stack may need cleaning up */
while (stack != NULL) {
newexp = stack;
stack = stack->last;
FREE(newexp);
}
return result;
}
//-------------------------------------------------------------------------
// Get bus indexes from the notation name[a:b]. If there is only "name"
// then look up the name in the bus hash list and return the index bounds.
@@ -323,7 +473,6 @@ int EvalExpr(struct expr_stack **stackptr, int *valptr)
int GetBusTok(struct bus *wb)
{
int result, start, end, value;
char oper;
struct property *kl = NULL;
struct expr_stack *stack, *newexp;
@@ -338,7 +487,6 @@ int GetBusTok(struct bus *wb)
if (match(nexttok, "[")) {
start = end = -1;
oper = '\0';
while (nexttok) {
SkipTokComments(VLOG_EQUATION_DELIMITERS);
if (match(nexttok, "]")) {
@@ -467,13 +615,16 @@ int GetBusTok(struct bus *wb)
//--------------------------------------------------------------------
// GetBus() is similar to GetBusTok() (see above), but it parses from
// a string instead of the input tokenizer.
// a string instead of the input tokenizer, and expressions are not
// allowed.
//--------------------------------------------------------------------
int GetBus(char *astr, struct bus *wb)
{
char *colonptr, *brackstart, *brackend, *sigend, sdelim, *aastr;
int result, start, end;
struct property *kl = NULL;
struct expr_stack *stack, *newexp;
if (wb == NULL) return 0;
else {
@@ -531,7 +682,7 @@ int GetBus(char *astr, struct bus *wb)
*brackend = '\0';
colonptr = strvchr(aastr, ':');
if (colonptr) *colonptr = '\0';
result = sscanf(brackstart + 1, "%d", &start);
result = ParseIntegerExpression(brackstart + 1, &start);
if (colonptr) *colonptr = ':';
if (result != 1) {
Printf("Badly formed array notation \"%s\"\n", astr);
@@ -539,7 +690,7 @@ int GetBus(char *astr, struct bus *wb)
return 1;
}
if (colonptr)
result = sscanf(colonptr + 1, "%d", &end);
result = ParseIntegerExpression(colonptr + 1, &end);
else {
result = 1;
end = start; // Single bit
@@ -803,6 +954,56 @@ extern void IncludeVerilog(char *, int, struct cellstack **, int);
extern void PushStack(char *cellname, struct cellstack **top);
extern void PopStack(struct cellstack **top);
/*------------------------------------------------------*/
/* Callback routine for FindInstanceOf() */
/* NOTE: This casts a (struct objlist) pointer to a */
/* (struct nlist) pointer for the purpose of using */
/* RecurseCellHashTable2(). FindInstanceOf() casts it */
/* back into a (struct objlist) pointer. */
/*------------------------------------------------------*/
struct nlist *findInstance(struct hashlist *p, void *clientdata)
{
struct nlist *ptr;
struct objlist *ob;
struct nlist *tref = (struct nlist *)clientdata;
ptr = (struct nlist *)(p->ptr);
if (ptr->file != tref->file) return NULL;
ob = LookupInstance(tref->name, ptr);
return (struct nlist *)ob;
}
/*------------------------------------------------------*/
/* Routine to find the first instance of a cell */
/*------------------------------------------------------*/
struct objlist *FindInstanceOf(struct nlist *tc)
{
return (struct objlist *)RecurseCellHashTable2(findInstance, (void *)tc);
}
/*------------------------------------------------------*/
/* Given a reference cell pointer tref and a port name */
/* portname, check if portname is a port of tref. If */
/* not, then call Port() to add one. If tref is NULL, */
/* then always add the port. */
/*------------------------------------------------------*/
void CheckPort(struct objlist *tref, char *portname)
{
struct objlist *ob;
if (tref != NULL) {
for (ob = CurrentCell->cell; ob && (ob->type == PORT); ob = ob->next) {
if ((*matchfunc)(ob->name, portname))
return;
}
}
Port(portname);
}
/*------------------------------------------------------*/
/* Read a verilog structural netlist */
/*------------------------------------------------------*/
@@ -816,16 +1017,17 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
char devtype, in_module, in_param;
char *eqptr, *matchptr;
struct keyvalue *kvlist = NULL;
char inst[256], model[256], instname[256], portname[256], pkey[256];
char inst[MAX_STR_LEN], model[MAX_STR_LEN], portname[MAX_STR_LEN], pkey[MAX_STR_LEN];
struct nlist *tp;
struct objlist *parent, *sobj, *nobj, *lobj, *pobj;
struct objlist *parent, *sobj, *nobj, *lobj, *pobj, *cref;
inst[255] = '\0';
model[255] = '\0';
instname[255] = '\0';
inst[MAX_STR_LEN-1] = '\0';
model[MAX_STR_LEN-1] = '\0';
in_module = (char)0;
in_param = (char)0;
loop.loopvar = NULL;
while (!EndParseFile()) {
SkipTokComments(VLOG_DELIMITERS); /* get the next token */
@@ -938,6 +1140,7 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
InputParseError(stderr);
}
in_module = (char)1;
cref = NULL;
/* Save pointer to current cell */
if (CurrentCell != NULL)
@@ -947,8 +1150,9 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
/* Check for existence of the cell. We may need to rename it. */
snprintf(model, 99, "%s", nexttok);
snprintf(model, MAX_STR_LEN-1, "%s", nexttok);
tp = LookupCellFile(nexttok, filenum);
hasports = (char)0;
/* Check for name conflict with duplicate cell names */
/* This may mean that the cell was used before it was */
@@ -986,23 +1190,48 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
CellDef(nexttok, filenum);
tp = LookupCellFile(nexttok, filenum);
}
else if (tp != NULL) { /* Make a new definition for an empty cell */
FreePorts(nexttok);
CellDelete(nexttok, filenum); /* This removes any PLACEHOLDER flag */
else if (tp != NULL) { /* Cell exists, but as a placeholder */
struct nlist *tptmp = NULL;
char ctemp[8];
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 */
CellDef(model, filenum);
tp = LookupCellFile(model, filenum);
}
hasports = (char)0;
inlined_decls = (char)0;
if (tp != NULL) {
struct bus wb, *nb;
tp->flags |= CELL_VERILOG;
PushStack(tp->name, CellStackPtr);
/* Need to support both types of I/O lists: Those */
@@ -1071,7 +1300,7 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
if (GetBusTok(&wb) != 0) {
// Didn't parse as a bus, so wing it
wb.start = wb.end = -1;
Port(nexttok);
CheckPort(cref, nexttok);
}
}
else {
@@ -1079,13 +1308,13 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
if (wb.start > wb.end) {
for (i = wb.start; i >= wb.end; i--) {
sprintf(portname, "%s[%d]", nexttok, i);
Port(portname);
CheckPort(cref, portname);
}
}
else {
for (i = wb.start; i <= wb.end; i++) {
sprintf(portname, "%s[%d]", nexttok, i);
Port(portname);
CheckPort(cref, portname);
}
}
/* Also register this port as a bus */
@@ -1097,7 +1326,7 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
wb.start = wb.end = -1;
}
else {
Port(nexttok);
CheckPort(cref, nexttok);
}
}
hasports = 1;
@@ -1153,7 +1382,7 @@ skip_endmodule:
if (GetBusTok(&wb) != 0) {
// Didn't parse as a bus, so wing it
wb.start = wb.end = -1;
Port(nexttok);
CheckPort(cref, nexttok);
}
}
else if (!match(nexttok, ",")) {
@@ -1161,13 +1390,13 @@ skip_endmodule:
if (wb.start > wb.end) {
for (i = wb.start; i >= wb.end; i--) {
sprintf(portname, "%s[%d]", nexttok, i);
Port(portname);
CheckPort(cref, portname);
}
}
else {
for (i = wb.start; i <= wb.end; i++) {
sprintf(portname, "%s[%d]", nexttok, i);
Port(portname);
CheckPort(cref, portname);
}
}
/* Also register this port as a bus */
@@ -1178,7 +1407,7 @@ skip_endmodule:
wb.start = wb.end = -1;
}
else {
Port(nexttok);
CheckPort(cref, nexttok);
}
}
hasports = 1;
@@ -1194,6 +1423,7 @@ skip_endmodule:
InputParseError(stderr);
}
in_module = (char)0;
cref = NULL;
if (*CellStackPtr) PopStack(CellStackPtr);
if (*CellStackPtr) ReopenCellDef((*CellStackPtr)->cellname, filenum);
@@ -1338,9 +1568,148 @@ skip_endmodule:
while (!match(nexttok, ";")) SkipTok("X///**/X,;");
continue;
}
else if (match(nexttok, "end")) {
/* Handle a 'for' loop */
if (loop.loopvar != NULL) {
int loopval;
struct property *klr;
klr = (struct property *)HashLookup(loop.loopvar, &verilogparams);
loopval = klr->pdefault.ival;
if (loopval < loop.end) loopval++;
else if (loopval > loop.end) loopval--;
SeekFile(loop.filepos);
if (loopval == loop.end)
{
HashDelete(loop.loopvar, &verilogparams);
FREE(klr);
FREE(loop.loopvar);
loop.loopvar = NULL;
}
else
klr->pdefault.ival = loopval;
}
continue;
}
else if (match(nexttok, "begin") || match(nexttok, "generate")) {
/* 'generate' section or 'for' loop start is ignored */
continue;
}
else if (match(nexttok, "generate") || match(nexttok, "endgenerate")) {
/* 'generate' section is ignored */
continue;
}
else if (match(nexttok, "genvar")) {
while (!match(nexttok, ";")) SkipTok("X///**/X,;");
continue;
}
else if (match(nexttok, "for")) {
char limittype = '\0';
char *paramkey = NULL;
struct property *kl = NULL, *klr;
/* Parse out the loop variable and count. Set the loop
* variable as a parameter. Find the beginning of the
* loop block and record the file position so that the
* block can be re-parsed for each loop iteration.
*/
SkipTokNoNewline(VLOG_DELIMITERS);
if ((nexttok == NULL) || !match(nexttok, "(")) {
Printf("Badly formed 'for' loop.\n");
FREE(paramkey);
break;
}
SkipTokNoNewline(VLOG_DELIMITERS);
/* Next token must be the loop variable */
if (nexttok == NULL) break;
paramkey = strsave(nexttok);
SkipTokNoNewline(VLOG_DELIMITERS);
if (!match(nexttok, "=")) {
Printf("Badly formed 'for' loop.\n");
FREE(paramkey);
break;
}
SkipTokNoNewline(VLOG_INTEGER_DELIMITERS);
if (ParseIntegerExpression(nexttok, &ival) == 0) {
FREE(paramkey);
break;
}
kl = NewProperty();
kl->type = PROP_INTEGER;
kl->slop.ival = 0;
kl->pdefault.ival = ival;
kl->key = paramkey;
kl->idx = 0;
kl->merge = MERGE_NONE;
SkipTokNoNewline(VLOG_DELIMITERS);
if (!match(nexttok, ";")) {
Printf("Badly formed 'for' loop.\n");
FREE(paramkey);
FREE(kl);
break;
}
/* Assuming a standard 'for' loop here */
SkipTokNoNewline(VLOG_DELIMITERS);
if (!match(nexttok, paramkey)) {
Printf("Don't know how to parse this 'for' loop!\n");
FREE(paramkey);
FREE(kl);
break;
}
SkipTokNoNewline(VLOG_DELIMITERS);
if (strlen(nexttok) == 1) limittype = *nexttok;
SkipTokNoNewline(VLOG_INTEGER_DELIMITERS);
if (ParseIntegerExpression(nexttok, &ival) == 0) {
FREE(kl);
FREE(paramkey);
break;
}
/* Loops will stop after the last value, so if value is > or <,
* then adjust the end value accordingly.
*/
if (limittype == '<')
ival--;
else if (limittype == '>')
ival++;
SkipTokNoNewline(VLOG_DELIMITERS);
if (!match(nexttok, ";")) {
Printf("Badly formed 'for' loop.\n");
FREE(paramkey);
FREE(kl);
break;
}
/* Assume a standard 'for' loop and skip to the block begin */
/* To do: Parse out the loop increment value. */
while (1) {
SkipTokNoNewline(VLOG_DELIMITERS);
if (EndParseFile()) break;
else if (match(nexttok, "begin")) break;
}
if (EndParseFile()) {
Printf("Badly formed 'for' loop: No begin/end block.\n");
FREE(paramkey);
FREE(kl);
break;
}
/* Save the loop variable, ending value, and file position */
loop.loopvar = paramkey;
loop.start = kl->pdefault.ival;
loop.end = ival;
loop.filepos = TellFile();
/* 'for' loop has been completely parsed, so save the loop variable */
HashPtrInstall(paramkey, kl, &verilogparams);
}
else if (match(nexttok, "wire") || match(nexttok, "assign")) { /* wire = node */
struct bus wb, wb2, *nb;
char nodename[128], noderoot[100];
char nodename[MAX_STR_LEN], noderoot[MAX_STR_LEN];
int is_wire = match(nexttok, "wire");
int j;
struct objlist *lhs, *rhs;
@@ -1401,7 +1770,7 @@ skip_endmodule:
}
else { /* "assign" */
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
if (GetBus(nexttok, &wb) == 0) {
if (GetBusTok(&wb) == 0) {
char *aptr = strvchr(nexttok, '[');
if (aptr != NULL) {
*aptr = '\0';
@@ -1436,9 +1805,11 @@ skip_endmodule:
// "assign a = b" joins two nets.
// "assign a = {b, c, ...}" creates a bus from components.
// "assign" using any boolean arithmetic is not structural verilog.
// "assign a = {x{b}}" creates a bus by repeating a component.
if (nexttok && match(nexttok, "=")) {
char assignname[128], assignroot[100];
char assignname[MAX_STR_LEN], assignroot[MAX_STR_LEN];
int multiplier = 1;
i = wb.start;
while (1) {
@@ -1447,6 +1818,10 @@ skip_endmodule:
if (match(nexttok, "{")) {
/* RHS is a bundle */
/* Make provisional multiplier active. NOTE: */
/* this is not going to properly handle complex */
/* multipliers like {2{a,b}}. Needs rework. */
if (multiplier < 0) multiplier = -multiplier;
continue;
}
else if (match(nexttok, "}")) {
@@ -1462,7 +1837,7 @@ skip_endmodule:
break;
}
else {
if (GetBus(nexttok, &wb2) == 0) {
if (GetBusTok(&wb2) == 0) {
char *aptr = strvchr(nexttok, '[');
j = wb2.start;
if (aptr != NULL) {
@@ -1478,6 +1853,18 @@ skip_endmodule:
else {
j = -1;
rhs = LookupObject(nexttok, CurrentCell);
/* Check if rhs starts with a signal multiplier */
if (rhs == NULL) {
if (ConvertStringToInteger(nexttok, &multiplier) == 1) {
/* Set multiplier to a negative value to
* indicate that it is provisional, waiting on
* signal specification to follow.
*/
multiplier = -multiplier;
continue;
}
}
}
if ((lhs == NULL) || (rhs == NULL)) {
if (rhs != NULL) {
@@ -1490,7 +1877,7 @@ skip_endmodule:
Printf("Improper expression is \"%s\".\n", nexttok);
break;
}
if (lhs != NULL) {
if ((lhs != NULL) || (multiplier < 0)) {
Printf("Improper assignment; right-hand side cannot "
"be parsed.\n");
if (i != -1)
@@ -1510,21 +1897,27 @@ skip_endmodule:
/* until bits in signal are exhausted or LHS is full. */
if (i != -1)
sprintf(nodename, "%s[%d]", noderoot, i);
snprintf(nodename, MAX_STR_LEN, "%s[%d]", noderoot, i);
else
sprintf(nodename, lhs->name);
strncpy(nodename, lhs->name, MAX_STR_LEN - 1);
if (j != -1)
sprintf(assignname, "%s[%d]", assignroot, j);
snprintf(assignname, MAX_STR_LEN, "%s[%d]", assignroot, j);
else
sprintf(assignname, rhs->name);
strncpy(assignname, rhs->name, MAX_STR_LEN - 1);
join(nodename, assignname);
if (i == wb.end) break;
i += (wb.end > wb.start) ? 1 : -1;
if (j == wb2.end) break;
j += (wb2.end > wb2.start) ? 1 : -1;
if (j == wb2.end) {
if (multiplier <= 1)
break;
else
multiplier--;
}
else
j += (wb2.end > wb2.start) ? 1 : -1;
}
}
}
@@ -1552,12 +1945,12 @@ skip_endmodule:
goto skip_endmodule;
}
else { /* module instances */
char instancename[100], modulename[100];
char instancename[MAX_STR_LEN], modulename[MAX_STR_LEN];
int itype, arraystart, arrayend, arraymax, arraymin;
char ignore;
instancename[99] = '\0';
modulename[99] = '\0';
instancename[MAX_STR_LEN-1] = '\0';
modulename[MAX_STR_LEN-1] = '\0';
struct portelement {
char *name; // Name of port in subcell
@@ -1570,7 +1963,7 @@ skip_endmodule:
struct portelement *head, *tail, *scan, *last, *scannext;
struct objlist *obptr;
strncpy(modulename, nexttok, 99);
strncpy(modulename, nexttok, MAX_STR_LEN-1);
/* If module name is a verilog primitive, then treat the module as a */
/* black box (this is not a complete list. Preferable to use hash */
@@ -1648,7 +2041,7 @@ nextinst:
}
}
strncpy(instancename, nexttok, 99);
strncpy(instancename, nexttok, MAX_STR_LEN-1);
/* Printf("Diagnostic: new instance is %s\n", instancename); */
SkipTokComments(VLOG_DELIMITERS);
@@ -1698,7 +2091,7 @@ nextinst:
}
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
if (match(nexttok, ")")) {
char localnet[100];
char localnet[MAX_STR_LEN];
// Empty parens, so create a new local node
savetok = (char)1;
if (arraystart != -1) {
@@ -1732,6 +2125,31 @@ nextinst:
}
new_port->net = wire_bundle;
}
else if ((strchr(nexttok, '[') != NULL) &&
(strchr(nexttok, ']') == NULL)) {
/* If a bus expressions has whitespace, then treat it like
* a bundle, above, concatenating 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 net in pin %s\n", array_expr);
}
new_port->net = array_expr;
}
else if (nexttok[0] == '~' || nexttok[0] == '!' || nexttok[0] == '-') {
/* All of these imply that the signal is logically manipulated */
/* in turn implying behavioral code. */
@@ -1830,7 +2248,7 @@ nextinst:
tp = LookupCellFile(modulename, filenum);
if (tp == NULL) {
struct bus wb, pb;
char defport[128];
char defport[MAX_STR_LEN];
Fprintf(stdout, "Creating placeholder cell definition for "
"module %s.\n", modulename);
@@ -1921,7 +2339,7 @@ nextinst:
if (portstart != -1) {
struct bus wb;
struct portelement *new_port;
char vname[256];
char vname[MAX_STR_LEN];
int j, result;
struct objlist *bobj;
char *bptr;
@@ -2074,7 +2492,7 @@ nextinst:
for (i = arraymin; i <= arraymax; i++) {
char *brackptr;
int j;
char locinst[128];
char locinst[MAX_STR_LEN];
if (i != -1)
sprintf(locinst, "%s[%d]", instancename, i);
@@ -2109,13 +2527,13 @@ nextinst:
scan = scan->next;
}
if (scan == NULL) {
char localnet[100];
char localnet[MAX_STR_LEN];
/* Assume an implicit unconnected pin */
sprintf(localnet, "_noconnect_%d_", localcount++);
Node(localnet);
join(localnet, obptr->name);
Fprintf(stderr,
Fprintf(stdout,
"Note: Implicit pin %s in instance %s of %s in cell %s\n",
obpinname, locinst, modulename, CurrentCell->name);
}
@@ -2129,7 +2547,7 @@ nextinst:
if (arraystart == -1) {
// Port may be an array
int range;
char pinname[128];
char pinname[MAX_STR_LEN];
// Check if port is an array
if (obpinidx == -1) {
@@ -2154,7 +2572,7 @@ nextinst:
}
else {
// Instance must be an array
char netname[128];
char netname[MAX_STR_LEN];
int slice, portlen, siglen;
/* Get the array size of the port for bit slicing */
@@ -2204,11 +2622,11 @@ nextinst:
for (scan = head; scan; scan = scan->next) {
if (!(scan->flags & PORT_FOUND)) {
if (tp->flags & CELL_PLACEHOLDER) {
char tempname[128];
char tempname[MAX_STR_LEN];
int maxnode;
/* This pin was probably implicit in the first call */
/* and so it needs to be added to the definition. */
/* This pin was probably implicit in the first call */
/* and so it needs to be added to the definition. */
ReopenCellDef(modulename, filenum);
Port(scan->name);
@@ -2265,7 +2683,7 @@ nextinst:
sprintf(tempname, "_noconnect_%d_", localcount++);
Node(tempname);
join(tempname, nobj->name);
Fprintf(stderr, "Note: Implicit pin %s in instance "
Fprintf(stdout, "Note: Implicit pin %s in instance "
"%s of %s in cell %s\n",
scan->name, sobj->instance.name,
modulename, CurrentCell->name);
@@ -2432,7 +2850,7 @@ void IncludeVerilog(char *fname, int parent, struct cellstack **CellStackPtr,
int blackbox)
{
int filenum = -1;
char name[256];
char name[MAX_STR_LEN];
/* If fname does not begin with "/", then assume that it is */
/* in the same relative path as its parent. */
+5 -5
View File
@@ -65,10 +65,10 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
Widget toplevel = NULL;
char GlobalFileName[100],
GlobalCellName[100],
GlobalOtherName[100],
GlobalDataName[100];
char GlobalFileName[MAX_STR_LEN],
GlobalCellName[MAX_STR_LEN],
GlobalOtherName[MAX_STR_LEN],
GlobalDataName[MAX_STR_LEN];
/*********************************************************
* Menu structure: attaches label string to a function,
@@ -1708,7 +1708,7 @@ void X_main_loop(int argc, char *argv[])
XmStringCharSet cs = "ISOLatin1";
static char prompt_response[100];
static char prompt_response[MAX_STR_LEN];
int prompt_done;
int calling_editor; /* which string are we trying to get ? */
#define FILE_NAME 1
+2 -1
View File
@@ -17,6 +17,7 @@ along with this program; see the file copying. If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* inetcomp.c -- a simple wrapper to the NETCOMP() function */
#include "config.h"
#include <stdio.h>
#include "netgen.h"
@@ -33,7 +34,7 @@ void STRCPY(char *dest, char *source)
int main(int argc, char *argv[])
{
char cell1[200], cell2[200];
char cell1[MAX_STR_LEN], cell2[MAX_STR_LEN];
Debug = 0;
if (argc != 1) {
+3 -2
View File
@@ -17,6 +17,7 @@ along with this program; see the file copying. If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* netcomp.c -- a simple wrapper to provide netlist comparison functionality */
#include "config.h"
#include <stdio.h>
#include "netgen.h"
@@ -51,7 +52,7 @@ void STRCPY(char *dest, char *source)
int main(int argc, char *argv[])
{
#ifndef HAVE_GETOPT
char cell1[200], cell2[200];
char cell1[MAX_STR_LEN], cell2[MAX_STR_LEN];
int filenum = -1;
Debug = 0;
@@ -67,7 +68,7 @@ int main(int argc, char *argv[])
STRCPY(cell2, ReadNetlist(argv[2], &filenum));
if (argc == 5) STRCPY(cell2, argv[4]); /* if explicit cell name specified */
#else
char cell1[200], cell2[200];
char cell1[MAX_STR_LEN], cell2[MAX_STR_LEN];
int usage = 0;
int args;
int c;
+1
View File
@@ -23,6 +23,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdlib.h> /* for getenv */
#endif
#include "netgen.h"
#include "print.h"
int main(int argc, char **argv)
{
+3 -1
View File
@@ -20,9 +20,11 @@ along with this program; see the file copying. If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ntk2xnf.c -- a simple wrapper to translate .ntk to Xilinx XNF format */
#include "config.h"
#include <stdio.h>
#include "netgen.h"
#include "xilinx.h"
#ifdef HAVE_X11
/* the following two X procedures are to permit linking
@@ -47,7 +49,7 @@ void STRCPY(char *dest, char *source)
int main(int argc, char *argv[])
{
char cellname[200];
char cellname[MAX_STR_LEN];
int filenum = -1;
Debug = 0;
+699 -418
View File
File diff suppressed because it is too large Load Diff
+1487 -1430
View File
File diff suppressed because it is too large Load Diff
+20 -3
View File
@@ -712,6 +712,7 @@ infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
@@ -794,6 +795,7 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1046,6 +1048,15 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1183,7 +1194,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir
libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@@ -1336,6 +1347,7 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@@ -6065,7 +6077,6 @@ fi
if test $usingTcl ; then
usingX11=1
cadinstall="$cadinstall tcltk"
modules="$modules tcltk"
programs="$programs tcltk"
@@ -6075,7 +6086,11 @@ if test $usingTcl ; then
extra_libs="$extra_libs \${NETGENDIR}/tcltk/libtcltk.o"
extra_defs="$extra_defs -DTCL_DIR=\\\"\${TCLDIR}\\\""
stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS"
if test $usingX11 ; then
stub_defs="$stub_defs -DUSE_TCL_STUBS"
else
stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS"
fi
else
programs="$programs netgen"
unused="$unused tcltk"
@@ -6160,6 +6175,7 @@ if test $usingTcl ; then
# Tk libraries and header files
#
# -----------------------------------------------------------------------
if test $usingX11 ; then
if test "${TK_INC_DIR}" != "/usr/include" ; then
INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}"
fi
@@ -6176,6 +6192,7 @@ if test $usingTcl ; then
loader_run_path="${TK_LIB_DIR}:${loader_run_path}"
fi
fi
fi
# -----------------------------------------------------------------------
#
+7 -2
View File
@@ -807,7 +807,6 @@ dnl "make" instead of requiring "make tcl"
dnl ----------------------------------------------------------------
if test $usingTcl ; then
usingX11=1
cadinstall="$cadinstall tcltk"
modules="$modules tcltk"
programs="$programs tcltk"
@@ -816,7 +815,11 @@ if test $usingTcl ; then
AC_DEFINE(TCL_NETGEN)
extra_libs="$extra_libs \${NETGENDIR}/tcltk/libtcltk.o"
extra_defs="$extra_defs -DTCL_DIR=\\\"\${TCLDIR}\\\""
stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS"
if test $usingX11 ; then
stub_defs="$stub_defs -DUSE_TCL_STUBS"
else
stub_defs="$stub_defs -DUSE_TCL_STUBS -DUSE_TK_STUBS"
fi
else
programs="$programs netgen"
unused="$unused tcltk"
@@ -903,6 +906,7 @@ if test $usingTcl ; then
# Tk libraries and header files
#
# -----------------------------------------------------------------------
if test $usingX11 ; then
if test "${TK_INC_DIR}" != "/usr/include" ; then
INC_SPECS="${INC_SPECS} -I${TK_INC_DIR}"
fi
@@ -919,6 +923,7 @@ if test $usingTcl ; then
loader_run_path="${TK_LIB_DIR}:${loader_run_path}"
fi
fi
fi
# -----------------------------------------------------------------------
#
File diff suppressed because it is too large Load Diff
+12 -6
View File
@@ -62,7 +62,7 @@ proc netgen::convert_to_json {filename lvs_final} {
puts $fjson " \["
set cktval [lindex $value 0]
foreach pin [lrange $cktval 0 end-1] {
set pinstr [string map {"\\" "\\\\"} $pin]
set pinstr [string map {"\\" "\\\\"} $pin]
puts $fjson " \"$pinstr\","
}
set pin [string map {"\\" "\\\\"} [lindex $cktval end]]
@@ -70,7 +70,7 @@ proc netgen::convert_to_json {filename lvs_final} {
puts $fjson " \], \["
set cktval [lindex $value 1]
foreach pin [lrange $cktval 0 end-1] {
set pinstr [string map {"\\" "\\\\"} $pin]
set pinstr [string map {"\\" "\\\\"} $pin]
puts $fjson " \"$pinstr\","
}
set pin [string map {"\\" "\\\\"} [lindex $cktval end]]
@@ -479,8 +479,12 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
netgen::compare assign "$fnum1 $cell1" "$fnum2 $cell2"
if {[file exists $setupfile]} {
puts stdout "Reading setup file $setupfile"
if {$setupfile == ""} {
puts stdout "\nNo setup file specified. Using trivial default setup.\n"
netgen::permute default ;# transistors and resistors
netgen::property default
} elseif {[file exists $setupfile]} {
puts stdout "\nReading setup file $setupfile\n"
# Instead of sourcing the setup file, run each line so we can
# catch individual errors and not let them halt the LVS process
set perrors 0
@@ -508,8 +512,10 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
puts stdout "Warning: There were errors reading the setup file"
}
} elseif {[string first nosetup $setupfile] < 0} {
netgen::permute default ;# transistors and resistors
netgen::property default
puts stderr "\nError: Setup file $setupfile does not exist.\n"
return
} else {
puts stderr "\nNo setup file specified. Continuing without a setup.\n"
}
if {[string first nolog $logfile] < 0} {
+76 -19
View File
@@ -2228,7 +2228,13 @@ _netcmp_compare(ClientData clientData,
Fprintf(stdout, "\nCircuit 1 cell %s is a black box; will not flatten "
"Circuit 2\n", name1);
}
else if (hascontents1 || hascontents2) {
else if (!hascontents1 && !hascontents2 && (tp1->flags & CELL_PLACEHOLDER)
&& (tp2->flags & CELL_PLACEHOLDER)) {
/* Two empty subcircuits, don't flatten anything */
Fprintf(stdout, "\nCircuit 1 cell %s and Circuit 2 cell %s are black"
" boxes.\n", name1, name2);
}
else {
FlattenUnmatched(tp1, name1, 1, 0);
FlattenUnmatched(tp2, name2, 1, 0);
DescribeContents(name1, fnum1, name2, fnum2);
@@ -2241,10 +2247,6 @@ _netcmp_compare(ClientData clientData,
DescribeContents(name1, fnum1, name2, fnum2);
}
}
else { /* Two empty subcircuits */
Fprintf(stdout, "\nCircuit 1 cell %s and Circuit 2 cell %s are black"
" boxes.\n", name1, name2);
}
CreateTwoLists(name1, fnum1, name2, fnum2, dolist);
// Return the names of the two cells being compared, if doing "compare
@@ -2900,7 +2902,7 @@ _netcmp_equate(ClientData clientData,
struct ElementClass *saveEclass = NULL;
struct NodeClass *saveNclass = NULL;
int file1, file2;
int i, l1, l2, ltest, lent, dolist = 0, doforce = 0;
int i, l1, l2, ltest, lent, dolist = 0, doforce = 0, dounique = 0;
Tcl_Obj *tobj1, *tobj2, *tobj3;
while (objc > 1) {
@@ -2916,6 +2918,11 @@ _netcmp_equate(ClientData clientData,
objv++;
objc--;
}
else if (!strcmp(optstart, "unique")) {
dounique = 1;
objv++;
objc--;
}
else
break;
}
@@ -3340,19 +3347,9 @@ _netcmp_equate(ClientData clientData,
return TCL_ERROR;
}
}
/* Now that all pins are assigned by name, reorder */
/* the pin lists of the 2nd cell to match the */
/* order of the 1st. */
/* Reorder the pin lists of instances of the 2nd */
/* cell to match the order of the 1st. */
// pindata.cell2 = tp2;
// RecurseCellHashTable2(pinorder, (void *)(&pindata));
}
if (EquivalenceClasses(tp1->name, file1, tp2->name, file2)) {
if (EquivalenceClasses(tp1->name, file1, tp2->name, file2, dounique)) {
Fprintf(stdout, "Device classes %s and %s are equivalent.\n",
tp1->name, tp2->name);
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
@@ -3375,6 +3372,8 @@ _netcmp_equate(ClientData clientData,
/* add --- add new property */
/* remove --- delete existing property */
/* tolerance --- set property tolerance */
/* associate --- associate property with a pin */
/* topology --- set exact/relaxed matching */
/* merge --- (deprecated) */
/* or */
/* netgen::property default */
@@ -3413,11 +3412,11 @@ _netcmp_property(ClientData clientData,
char *options[] = {
"add", "create", "remove", "delete", "tolerance", "merge", "serial",
"series", "parallel", NULL
"series", "parallel", "associate", "topology", NULL
};
enum OptionIdx {
ADD_IDX, CREATE_IDX, REMOVE_IDX, DELETE_IDX, TOLERANCE_IDX, MERGE_IDX,
SERIAL_IDX, SERIES_IDX, PARALLEL_IDX
SERIAL_IDX, SERIES_IDX, PARALLEL_IDX, ASSOCIATE_IDX, TOPOLOGY_IDX
};
int result, index, idx2;
@@ -3462,6 +3461,10 @@ _netcmp_property(ClientData clientData,
return TCL_ERROR;
}
char *topo[] = {
"strict", "relaxed", NULL
};
/* Check for special command "property default" */
if ((objc == 2) && (!strcmp(Tcl_GetString(objv[1]), "default"))) {
@@ -3547,6 +3550,36 @@ _netcmp_property(ClientData clientData,
}
return TCL_OK;
}
else if ((objc > 1) && (!strcmp(Tcl_GetString(objv[1]), "topology"))) {
if (objc == 2) {
if (ExactTopology)
Tcl_SetResult(interp, "Strict topology property matching.",
NULL);
else
Tcl_SetResult(interp, "Relaxed topology property matching.",
NULL);
}
else if (objc == 3) {
if (Tcl_GetIndexFromObj(interp, objv[2],
(CONST84 char **)topo,
"topology", 0, &idx2) == TCL_OK) {
if (idx2 == 0)
ExactTopology = TRUE;
else if (idx2 == 1)
ExactTopology = FALSE;
else {
Tcl_SetResult(interp, "Topology matching type must be "
"'strict' or 'relaxed'.", NULL);
return TCL_ERROR;
}
}
}
else {
Tcl_WrongNumArgs(interp, 1, objv, "strict|relaxed");
return TCL_ERROR;
}
return TCL_OK;
}
result = CommonParseCell(interp, objv[1], &tp, &fnum);
if (result != TCL_OK) return result;
@@ -3840,6 +3873,29 @@ _netcmp_property(ClientData clientData,
}
break;
case ASSOCIATE_IDX:
if (objc == 3) {
Tcl_WrongNumArgs(interp, 1, objv, "{property_key pin_name} ...");
return TCL_ERROR;
}
for (i = 3; i < objc; i++) {
// Each value must be a duplet
result = Tcl_ListObjLength(interp, objv[i], &llen);
if ((result != TCL_OK) || (llen != 2)) {
Tcl_SetResult(interp, "Not a {key pin} pair list.",
NULL);
}
else {
result = Tcl_ListObjIndex(interp, objv[i], 0, &tobj1);
if (result != TCL_OK) return result;
result = Tcl_ListObjIndex(interp, objv[i], 1, &tobj2);
if (result != TCL_OK) return result;
PropertyAssociatePin(tp->name, fnum, Tcl_GetString(tobj1),
Tcl_GetString(tobj2));
}
}
break;
case TOLERANCE_IDX:
if (objc == 3) {
Tcl_WrongNumArgs(interp, 1, objv, "{property_key tolerance} ...");
@@ -3939,6 +3995,7 @@ _netcmp_property(ClientData clientData,
}
}
break;
}
}
return TCL_OK;