Compare commits

..
64 Commits
Author SHA1 Message Date
Tim Edwards da3b96ae9e Merge branch 'master' into netgen-1.5 2026-04-28 02:00:02 -04:00
R. Timothy Edwards 8a2bbe0723 Updated version to go along with PR #105 from user jalcim on github. 2026-04-27 09:50:37 -04:00
jalcim a0c49a026a fix(netcmp): correct signal handler type for K&R declaration
netcmp.c:55 declares oldinthandler with empty parameter list:
    void (*oldinthandler)() = SIG_DFL;

In K&R / pre-C23, this means 'function with unspecified parameters'.
GCC 14+ infers void(*)(void), which is incompatible with signal(2)'s
expected void(*)(int) handler. The signal(SIGINT, oldinthandler) calls
at lines 8777 and 8784 then fail with -Wincompatible-pointer-types
(now a default error in GCC 14+).

This 1-line fix matches the actual usage as a SIGINT handler with int
signum parameter, and restores tclnetgen.so build on Fedora 41+ /
Debian 13+ / Ubuntu 24.04+ (any system with GCC 14+).

Tested: tclnetgen.so now builds successfully and 'netgen -batch lvs'
mode works again.
2026-04-26 22:06:07 +02:00
Tim Edwards 1520e276bc Merge branch 'master' into netgen-1.5 2026-04-04 02:00:02 -04:00
R. Timothy Edwards 665203bba1 Corrected genhash() after Mitch Bailey pointed out that the function
was no longer hashing on both values passed to the function, as it
is supposed to.
2026-04-03 08:48:34 -04:00
Tim Edwards f02802dd21 Merge branch 'master' into netgen-1.5 2026-04-03 02:00:04 -04:00
R. Timothy Edwards 0192558d4b Updated version corresponding to the last commit. 2026-04-02 21:30:01 -04:00
R. Timothy Edwards 21d329b22d Modified the hash algorithm used by netgen after a discussion with
ChatGPT about hash implementations.  Switched from SDBM to FNV-1a,
which should be a better/stronger hash algorithm.  Could do
something more sophisticated, but this change can be done in a few
minutes.
2026-04-02 21:29:04 -04:00
Tim Edwards b76c9a1712 Merge branch 'master' into netgen-1.5 2026-02-03 02:00:02 -05:00
R. Timothy Edwards 37b1a2a07d Cleaned up some errors (most minor, some not so minor) in the
code that were surfaced by Stefan Thiede running clang on Mac
OS.  Function prototype warnings have not been fixed yet, as
that is a more involved fix, although it needs to be done.
2026-02-02 20:53:13 -05:00
Tim Edwards 4d44abcca4 Merge branch 'master' into netgen-1.5 2026-01-16 02:00:02 -05:00
R. Timothy Edwards 777f7ef095 Found a counting issue with netcmp output that will overrun the
output string buffer if the size of the copied string is just
the wrong amount, due to the use of strcpy() instead of
strncpy() in at least one place.  Just hacked a solution by
allocating more space for the string, but this should be fixed
properly.  Also:  Discovered that the "zero valued resistor"
routine looks for shorted ports in the wrong place, and if it
finds shorted ports it wrongly decides that the device it's
looking at is a zero-valued resistor whether or not it really
is zero-valued.
2026-01-15 16:39:18 -05:00
Tim Edwards 29ee16644d Merge branch 'master' into netgen-1.5 2025-12-29 02:00:02 -05:00
R. Timothy Edwards 9b4185fe62 Reverted a change from a long time ago regarding removal of zero
valued resistors connecting two ports.  I do not recall exactly
why I put that in but it appears to cause incorrect behavior.
2025-12-28 14:54:07 -05:00
Tim Edwards f5147e5af6 Merge branch 'master' into netgen-1.5 2025-12-12 02:00:03 -05:00
R. Timothy Edwards ddd95c4fe6 Added a few lines to the setup file parser so that if there is a
missing brace in the file (a common error), then the fact that
there is an unevaluated command when the file has finished being
read will trigger an evaluation of the unfinished code and emit
an error.  Previously, the command and anything after the
unterminated brace would just silently get ignored, which was not
helpful for debugging setup syntax errors.
2025-12-11 12:08:31 -05:00
Tim Edwards 23b4e19204 Merge branch 'master' into netgen-1.5 2025-12-09 02:00:02 -05:00
R. Timothy Edwards c0c9993980 Corrected a major error with the verilog parser. The verilog
parser was not assigning the correct file number for the first
input file, which resulted in the effect that if the first
file read sets definitions for the netlist, then those definitions
are wiped out on the following file read.  There has been a workaround
to read from /dev/null on the first file read so that the file number
is set on all subsequent reads.  This fix avoids the need for the
workaround.
2025-12-08 16:45:27 -05:00
R. Timothy Edwards 8a20b90074 Corrected an issue that can cause a segfault in an incorrect run
setup when a cell has no pins.  Didn't really analyze the error
condition, just caught and handled the condition to avoid the
segfault.
2025-12-08 13:09:50 -05:00
Tim Edwards 5bb279a9e4 Merge branch 'master' into netgen-1.5 2025-11-30 02:00:04 -05:00
R. Timothy Edwards 3392159243 Added some extra code to the verilog parser. It now handles some
additional syntax for wire bundles specified as a pin connection
on an array of instances, and a few other things.  These are not
exhaustive but are solving an immediate problem.  I will go back
and clean up the code to make it work for more general cases
later.
2025-11-29 11:55:26 -05:00
Tim Edwards b2662b443f Merge branch 'master' into netgen-1.5 2025-11-25 02:00:02 -05:00
R. Timothy Edwards 24c6eb4cb9 Updated the version to go along with the merge of pull request 2025-11-24 12:26:57 -05:00
Mitch Bailey 9048191486 Allow processing of cellnames with $.
When loading a file, also print cellname on errors

Signed-off-by: Mitch Bailey <[email protected]>
2025-11-24 12:26:30 -05:00
Tim Edwards 1acef6c52c Merge branch 'master' into netgen-1.5 2025-11-22 02:00:02 -05:00
R. Timothy Edwards 72d7d55bbe Corrected an issue with the "-noflatten" switch to "lvs", which is
also a problem with the underlying "flatten prohibit" command
option;  in one place, the cell's subcircuits were being prohibited
from being flattened, causing issues including a potential infinite
loop.
2025-11-21 15:52:14 -05:00
Tim Edwards 7459b6dfe8 Merge branch 'master' into netgen-1.5 2025-11-13 02:00:02 -05:00
R. Timothy Edwards 04163aedcc One hopefully final modification to ensure that Tcl_InitStubs()
uses the Tcl version that the program has been compiled to.  This
should work with both Tcl 8.X and Tcl 9.X.
2025-11-12 11:32:18 -05:00
R. Timothy Edwards f7d35f9cca Accidentally changed a file in the last commit which gets
overwritten by "configure".  Moved the modification to the source
file that doesn't get overwritten.
2025-11-12 09:55:29 -05:00
R. Timothy Edwards 601277e539 Updated the revision number for the last set of changes. 2025-11-12 09:19:52 -05:00
R. Timothy Edwards 73344329f8 Made some updates for Tcl 9 compatibility; also changed the
Makefile to pass EXTRA_CFLAGS for testing with "-std=c99" and
"-std=gnu99".  Made some additional corrections to ensure a
clean compile using -std=gnu99.
2025-11-12 09:17:46 -05:00
Tim Edwards 7f2ab31143 Merge branch 'master' into netgen-1.5 2025-11-12 02:00:02 -05:00
R. Timothy Edwards 08485d28a7 Changed CONST and CONST84 everywhere in tclnetgen.c to "const".
The capitalized version of this got removed from the Tcl headers
as some point and is no longer valid.  Added an include of
"strings.h" to base/actel.c, which was missing it (uses
strcasecmp() in the code, and needs the function declaration).
2025-11-11 09:59:14 -05:00
Tim Edwards 45164bbf98 Merge branch 'master' into netgen-1.5 2025-11-08 02:00:04 -05:00
R. Timothy Edwards 2ee286efb4 Corrected the pin permutation check for pin matching; previously,
this was not doing the correct cross-check, instead looking in the
same netlist for the permutable pin and checking its node number,
which is useless since the node number is the same by definition
for permutable pins.  This error would result in occasional false
negative results during pin matching, showing matching where pins
are actually not matched.
2025-11-07 14:06:22 -05:00
Tim Edwards 46cb8d6637 Merge branch 'master' into netgen-1.5 2025-10-24 02:00:04 -04:00
R. Timothy Edwards dae6919d4f Updating the version to go along with the merge of pull request 2025-10-23 09:54:36 -04:00
D. Mitch Bailey 017bdc6e48 Changed nested to static variable. Otherwise gets reset with each line.
Signed-off-by: D. Mitch Bailey <[email protected]>
2025-10-23 08:30:08 +00:00
Tim Edwards 2825b786b7 Merge branch 'master' into netgen-1.5 2025-10-23 02:00:04 -04:00
R. Timothy Edwards b371af9235 Corrected an error that was assumed to have been fixed three years
ago (and may have been, but only under limited circumstances).  Do
to several errors, using "-noflatten" on the command line and using
"flatten prohibit" in a script would not prevent cells from being
flattened;  the "-noflatten" list needed to be used to call "flatten
prohibit", and "flatten prohibit" needed to be fixed to flag the
specified cell instead of the top level cell where it exists.
2025-10-22 10:43:00 -04:00
Tim Edwards 0af8c7ad49 Merge branch 'master' into netgen-1.5 2025-10-10 02:00:03 -04:00
R. Timothy Edwards b5432d139b Corrected a corner-case where a module with no ports in verilog
was creating an implicit net for the stand-in "(no pins)" port.
2025-10-09 10:36:41 -04:00
Tim Edwards 0aa20dcf62 Merge branch 'master' into netgen-1.5 2025-10-09 02:00:04 -04:00
R. Timothy Edwards 0e958bd45c Corrected an issue in which black-box entries (such as low-level
subcircuit devices) do not output information about mismatched
pins.  This can end up being treated as a non-error but the
mismatch should be noted in the output regardless.
2025-10-08 10:03:35 -04:00
Tim Edwards 7cbf15aab1 Merge branch 'master' into netgen-1.5 2025-10-03 02:00:02 -04:00
R. Timothy Edwards b59196fa81 Modified the SPICE file read routine to accept the CDL syntax
"*.GLOBAL" as equivalent to ".GLOBAL".  Corrected the property
matching to handle property combination when no "critical"
property is given.  Critical properties exist when one property
must remain constant and equal for other properties to combine,
such as transistor length.  But, for example, capacitors can
combine area without any restriction based on another property.
Also, corrected the property matching code to allow more than
one property to be additive (example:  capacitor area and
perimeter).  Corrected the equation for adding properties in
parallel combination.
2025-10-02 12:33:28 -04:00
Tim Edwards 1de6f88f1e Merge branch 'master' into netgen-1.5 2025-09-10 02:00:02 -04:00
R. Timothy Edwards 6e6e9fb73f Added code to catch and print an error in connectivity between a
port and an internal node which can be missed when pin permutations
are present.  Previously, that could produce a situation where
netgen would report a "port error" but otherwise list all ports
as matching.  Because the permutation handling makes this hard to
detect while generating pin correspondence output, the non-matching
pins are listed separately at the end, and only if no mismatch was
detected during output.
2025-09-09 13:45:29 -04:00
Tim Edwards 33fed391fd Merge branch 'master' into netgen-1.5 2025-09-01 02:00:02 -04:00
R. Timothy Edwards e84700a607 Added a NULL check at one point in the SPICE read routine that
prevents a segfault under some condition (not fully investigated)
involving .include files.  Appears to resolve the problem without
any unintended consequences.
2025-08-31 16:52:35 -04:00
Tim Edwards 5f5248b3d0 Merge branch 'master' into netgen-1.5 2025-08-27 02:00:03 -04:00
R. Timothy Edwards 0bee21ccc8 Corrected an issue in which a property error in a subcell would not
be reported at the end if there was a port error.  This is important
because port errors often resolve themselves, but the cell should not
be reported clean if the port errors resolved but it had property
errors.  Also:  Added a method to derive area and/or perimeter
properties from length and width, so that capacitors can be combined
in parallel without regard to which dimension is width and which is
length.  This feature has only been lightly tested.
2025-08-26 17:47:46 -04:00
Tim Edwards 80f9263004 Merge branch 'master' into netgen-1.5 2025-08-26 02:00:02 -04:00
R. Timothy Edwards c269f1de89 Corrected an unexpected corner-case error in which if a newline in
a spice netlist falls exactly on the last non-null position of the
input buffer after the buffer has been expanded to accept more
input data, then the next line gets read in automatically, and
the newline gets treated as whitespace and not a newline.
2025-08-25 10:31:19 -04:00
Tim Edwards edb50746cb Merge branch 'master' into netgen-1.5 2025-08-19 02:00:02 -04:00
R. Timothy Edwards 4443826f9e Corrected a place in netcmp.c where a new instance net connection
is created without setting the cell name or instance name.  That
can cause a crash condition when attempting to locate the instance
from the net record.
2025-08-18 10:37:36 -04:00
Tim Edwards f2368ca223 Merge branch 'master' into netgen-1.5 2025-05-18 02:00:02 -04:00
R. Timothy Edwards a60dac6124 Modified the primary SPICE token reading routine so that the call
to strdtok() can differentiate between reading verilog and reading
SPICE.  Otherwise, SPICE containing the (dubious) syntax of using
backslashes in names will get treated as a verilog name with
verilog backslash notation, with generally undesirable results.
When called from the SPICE reading routine, backslashes are
treated as-is and not as verilog notation.
2025-05-17 20:29:38 -04:00
Tim Edwards ee93d52a26 Merge branch 'master' into netgen-1.5 2025-03-26 02:00:02 -04:00
R. Timothy Edwards bbe645f0ab Corrected an error in which netgen was trying to reduce an
expression in a property that was not necessarily a parameter,
and if it wasn't, then netgen would crash.  Surfaced by an
example using complicated parameters that netgen was apparently
unable to handle (an issue for another day;  the main goal here
was to avoid a segmentation violation).
2025-03-25 17:00:58 -04:00
Tim Edwards ba7004fd5b Merge branch 'master' into netgen-1.5 2025-03-10 02:00:02 -04:00
Tim Edwards 4f315d33d6 Fixed a corner case found by Sylvain Munaut (see github issue
tracker #96) in which a subcircuit with only one port (in this
case, a pad) but which has properties (in this case, "M") will
fail to set the pointer position ahead of the property because
the loop starts after the first pin, so it has already missed
the position that needs to be saved.  Fixed by initializing
the value to the first pin position before starting the loop.
2025-03-09 11:07:58 -04:00
Tim Edwards 704bfbc871 Merge branch 'master' into netgen-1.5 2025-02-10 02:00:03 -05:00
Tim Edwards 4457248ecd Corrected a long-standing issue with permutation, which turned out
to be caused by failing to have a systematic way of determining
which pin's hash value would be used for the hash value of all the
pins.  Because equivalent cells in the two netlists may have pins in
different order, it was possible that they might end up with
different hashes.  This was solved simply by always taking the
larger hash value of the two pins belonging to the permutable pair.
Now permutation works correctly for arbitrary subcircuits.
(Previously it worked for low-level components like MOSFETs because
the pin order is always the same.)
2025-02-09 21:26:54 -05:00
16 changed files with 884 additions and 284 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.291
1.5.319
+3 -2
View File
@@ -22,6 +22,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <stdarg.h>
#include <strings.h>
#include <ctype.h>
#ifdef IBMPC
#include <stdlib.h> /* for strtol on PC */
@@ -90,7 +91,7 @@ char *ActelName(char *Name)
/* strip physical-pin information, if it exists */
if ((nm = strrchr(name,PHYSICALPIN[0])) != NULL) *nm = '\0';
if (strlen(name) > 13) {
ActelIndex = (++ActelIndex) % ACTELNAMESIZE;
ActelIndex = (ActelIndex + 1) % ACTELNAMESIZE;
/* format the value of the hashed value of the string */
sprintf(ActelNames[ActelIndex], "$%lX", ActelNameHash(name));
if (Debug)
@@ -101,7 +102,7 @@ Printf("ActelNameHash returns %s on name %s\n",ActelNames[ActelIndex], name);
NeedsQuoting = 0;
if (NULL != strpbrk(name, ".,:; \t\"'\n\r")) NeedsQuoting = 1;
ActelIndex = (++ActelIndex) % ACTELNAMESIZE;
ActelIndex = (ActelIndex + 1) % ACTELNAMESIZE;
if (!NeedsQuoting) {
strcpy(ActelNames[ActelIndex], name);
return(ActelNames[ActelIndex]);
+82 -28
View File
@@ -300,8 +300,6 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
return 0;
}
}
/* Placeholder cells must not be flattened */
if (ThisCell->flags & CELL_PLACEHOLDER) return 0;
FreeNodeNames(ThisCell);
@@ -339,6 +337,10 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
LastObj = ParentParams;
continue;
}
if (ChildCell->flags & CELL_PLACEHOLDER) {
LastObj = ParentParams;
continue; // Placeholder cells must not be flattened
}
if (ChildCell == ThisCell) {
LastObj = ParentParams;
continue; // Avoid infinite loop
@@ -1753,16 +1755,26 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell1->name,
name1, file1);
flattenInstancesOf(name1, file1, ecomp->cell1->name);
modified1++;
if (flattenInstancesOf(name1, file1, ecomp->cell1->name) > 0)
modified1++;
}
else if (ecomp->cell1 && (ecomp->num1 > 0)) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" would make a better match but is prohibited.\n",
ecomp->cell1->name, name1, file1);
}
if (ecomp->cell2 && (ecomp->num2 > 0) &&
(!(ecomp->cell2->flags & CELL_PLACEHOLDER))) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell2->name,
name2, file2);
flattenInstancesOf(name2, file2, ecomp->cell2->name);
modified2++;
if (flattenInstancesOf(name2, file2, ecomp->cell2->name) > 0)
modified2++;
}
else if (ecomp->cell2 && (ecomp->num2 > 0)) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" would make a better match but is prohibited.\n",
ecomp->cell2->name, name2, file2);
}
}
@@ -1851,8 +1863,13 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell2->name,
name2, file2);
flattenInstancesOf(name2, file2, ecomp->cell2->name);
modified2++;
if (flattenInstancesOf(name2, file2, ecomp->cell2->name) > 0)
modified2++;
}
else if (ecomp->cell2) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" would make a better match but is prohibited.\n",
ecomp->cell2->name, name2, file2);
}
}
}
@@ -1917,8 +1934,13 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" makes a better match\n", ecomp->cell1->name,
name1, file1);
flattenInstancesOf(name1, file1, ecomp->cell1->name);
modified1++;
if (flattenInstancesOf(name1, file1, ecomp->cell1->name) > 0)
modified1++;
}
else if (ecomp->cell1) {
Fprintf(stdout, "Flattening instances of %s in cell %s (%d)"
" would make a better match but is prohibited.\n",
ecomp->cell1->name, name1, file1);
}
}
}
@@ -1996,8 +2018,11 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
break;
}
}
if (found) break;
}
/* Do NOT remove shorting devices that */
if (found) {
/* Beware remove shorting devices that */
/* connect two ports. Otherwise the */
/* port lists get screwed up. It is */
/* better in that case to force the */
@@ -2005,6 +2030,10 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
/* This is ignored for a top-level cell */
/* because it will just show up as a */
/* port mismatch error as it should. */
/* (12/12/2025---disabling this worked; */
/* may need to go back to a failing */
/* example and determine how pin */
/* matching gets scrambled.) */
if ((not_top == TRUE) &&
(ecomp->cell1->class != CLASS_ISOURCE)) {
@@ -2017,14 +2046,18 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
else if (ob2->node == node2)
found2 = TRUE;
if (found1 && found2) {
found = FALSE;
Fprintf(stdout, "Warning: "
"zero-valued device connects "
"port %s to another port; pin "
"matching may be affected.\n",
ob2->name);
// found = FALSE;
break;
}
}
}
if (found) break;
}
if (found) {
Fprintf(stdout, "Removing zero-valued device "
"%s from cell %s (%d) makes a better "
@@ -2271,13 +2304,24 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
ecompX0->cell1->file, &compdict);
if (dstr) *dstr = '[';
if ((ncomp == ecomp0X) && (ecomp0X->num2 <= ecompX0->num1)) {
Fprintf(stdout, "Flattening instances of %s in cell %s"
"(%d) makes a better match\n",
ecompX0->cell1->name, name1, file1);
flattenInstancesOf(name1, file1, ecompX0->cell1->name);
ecompX0->num1 = 0;
ecomp0X->num1 += ecompX0->num1;
modified1++;
if (!(ecompX0->cell1->flags & CELL_PLACEHOLDER)) {
Fprintf(stdout, "Flattening instances of %s in cell"
" %s (%d) makes a better match\n",
ecompX0->cell1->name, name1, file1);
if (flattenInstancesOf(name1, file1,
ecompX0->cell1->name) > 0) {
ecompX0->num1 = 0;
ecomp0X->num1 += ecompX0->num1;
modified1++;
}
}
else
{
Fprintf(stdout, "Flattening instances of %s in "
"cell %s (%d) would make a better "
"match but is prohibited.\n",
ecompX0->cell1->name, name1, file1);
}
break;
}
}
@@ -2297,13 +2341,23 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
ecomp0X->cell2->file, &compdict);
if (dstr) *dstr = '[';
if ((ncomp == ecompX0) && (ecompX0->num1 <= ecomp0X->num2)) {
Fprintf(stdout, "Flattening instances of %s in cell %s"
" (%d) makes a better match\n",
ecomp0X->cell2->name, name2, file2);
flattenInstancesOf(name2, file2, ecomp0X->cell2->name);
ecomp0X->num2 = 0;
ecompX0->num2 += ecomp0X->num2;
modified2++;
if (!(ecomp0X->cell2->flags & CELL_PLACEHOLDER)) {
Fprintf(stdout, "Flattening instances of %s in cell"
" %s (%d) makes a better match\n",
ecomp0X->cell2->name, name2, file2);
if (flattenInstancesOf(name2, file2,
ecomp0X->cell2->name) > 0) {
ecomp0X->num2 = 0;
ecompX0->num2 += ecomp0X->num2;
modified2++;
}
}
else {
Fprintf(stdout, "Flattening instances of %s in "
"cell %s (%d) would make a better "
"match but is prohibited.\n",
ecompX0->cell2->name, name2, file2);
}
break;
}
}
+20 -13
View File
@@ -137,32 +137,39 @@ static unsigned char uppercase[] = {
// horrible things can happen, as, for example, names AOI12 and OAI12
// have exactly the same hash result. Lousy for binning and even
// lousier for generating class magic numbers.
//
// Updated again 4/2/2026 to the FNV-1a hash, which is better than
// SDBM for this application, according to ChatGPT.
unsigned long hashnocase(char *s, int hashsize)
{
unsigned long hashval;
for (hashval = 0; *s != '\0'; )
hashval = uppercase[*s++]
+ (hashval << 6) + (hashval << 16) - hashval;
unsigned long hashval = 2166136261ul;
for (; *s != '\0'; s++) {
hashval ^= uppercase[*s];
hashval *= 16777619ul;
}
return (hashsize == 0) ? hashval : (hashval % hashsize);
}
unsigned long hashcase(char *s, int hashsize)
{
unsigned long hashval;
for (hashval = 0; *s != '\0'; )
hashval = (*s++) + (hashval << 6) + (hashval << 16) - hashval;
unsigned long hashval = 2166136261ul;
for (; *s != '\0'; s++) {
hashval ^= (unsigned char)(*s);
hashval *= 16777619ul;
}
return (hashsize == 0) ? hashval : (hashval % hashsize);
}
unsigned long genhash(char *s, int c, int hashsize)
{
unsigned long hashval;
for (hashval = (unsigned long)c; *s != '\0'; )
hashval = (*s++) + (hashval << 6) + (hashval << 16) - hashval;
unsigned long hashval = 2166136261ul;
hashval ^= (unsigned long)c;
hashval *= 16777619ul;
for (; *s != '\0'; s++) {
hashval ^= (unsigned char)(*s);
hashval *= 16777619ul;
}
return (hashsize == 0) ? hashval : (hashval % hashsize);
}
+319 -43
View File
@@ -24,6 +24,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdarg.h>
#include <setjmp.h>
#include <signal.h>
#include <strings.h> /* for strncasecmp() */
#include <time.h> /* for time() as a seed for random number generator */
#include <limits.h>
#include <math.h> /* for fabs() */
@@ -51,7 +52,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef TCL_NETGEN
int InterruptPending = 0;
void (*oldinthandler)() = SIG_DFL;
void (*oldinthandler)(int) = SIG_DFL;
extern Tcl_Interp *netgeninterp;
extern int check_interrupt();
#endif
@@ -1217,7 +1218,8 @@ SortFanoutLists(nlist1, nlist2)
f2 -= 1;
matched[f1] = -1;
total++;
if (f2 != f1) {
if ((f2 != f1) && (nlist2->flist[f1].permute != 0) &&
(nlist2->flist[f2].permute != 0)) {
temp = nlist2->flist[f2];
nlist2->flist[f2] = nlist2->flist[f1];
nlist2->flist[f1] = temp;
@@ -1251,7 +1253,8 @@ SortFanoutLists(nlist1, nlist2)
f1 -= 1;
matched[f2] = -1;
total++;
if (f1 != f2) {
if ((f1 != f2) && (nlist1->flist[f1].permute != 0) &&
(nlist1->flist[f2].permute != 0)) {
temp = nlist1->flist[f1];
nlist1->flist[f1] = nlist1->flist[f2];
nlist1->flist[f2] = temp;
@@ -1619,8 +1622,8 @@ void FormatIllegalElementClasses()
char *permcount;
int bytesleft;
permname = CALLOC(right_col_end + 2, sizeof(char));
permcount = CALLOC(right_col_end + 2, sizeof(char));
permname = CALLOC(right_col_end + 100, sizeof(char));
permcount = CALLOC(right_col_end + 100, sizeof(char));
ostr = output_string_init();
found = 0;
@@ -3579,7 +3582,7 @@ int FlattenUnmatched(struct nlist *tc, char *parent, int stoplevel, int loclevel
tc->name, parent, tc->file);
changed = flattenInstancesOf(parent, tc->file, tc->name);
Fprintf(stdout, "(%d instance%s)\n", changed, ((changed == 1) ? "" : "s"));
return 1;
return (changed != 0);
}
if (tc->cell == NULL) return 0;
@@ -5216,14 +5219,23 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
if (comb == TRUE) {
double pd;
int hascrit = FALSE;
int mult, cidx = -1;
struct valuelist *avl, *cvl = NULL;
struct valuelist **avl, **cvl;
struct valuelist *cvlp;
critval.type = PROP_ENDLIST;
critval.value.dval = 0.0;
/* Track properties separately so that multiple properties can be
* added together (e.g., area and perimeter)
*/
avl = (struct valuelist **)CALLOC(pcount, sizeof(struct valuelist *));
cvl = (struct valuelist **)CALLOC(pcount, sizeof(struct valuelist *));
for (i = 0; i < run; i++) {
avl = NULL;
// if (vlist[0][i] == NULL) continue;
// mult = vlist[0][i]->value.ival;
for (p = 0; p < pcount; p++) avl[p] = NULL;
if (vlist[0][i] == NULL)
mult = 1;
else
@@ -5240,6 +5252,7 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
/* critical properties never combine, but track them */
if ((series == TRUE) && (ctype & MERGE_S_CRIT)) {
hascrit = TRUE;
pd = 2 * fabs(vl->value.dval - critval.value.dval) /
(vl->value.dval + critval.value.dval);
if ((vl->type != critval.type) || (pd > kl->slop.dval))
@@ -5251,6 +5264,7 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
continue;
}
if ((series == FALSE) && (ctype & MERGE_P_CRIT)) {
hascrit = TRUE;
pd = 2 * fabs(vl->value.dval - critval.value.dval) /
(vl->value.dval + critval.value.dval);
if ((vl->type != critval.type) || (pd > kl->slop.dval))
@@ -5284,19 +5298,30 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
}
}
if (ctype & (MERGE_S_ADD | MERGE_P_ADD | MERGE_S_PAR | MERGE_P_PAR))
avl = vl;
avl[p] = vl;
}
if (cidx == i) cvl = avl;
if (hascrit == FALSE) cidx = 0; /* No critical property */
/* Each time a new critical value is found, set the location */
/* of the property record that will collect the summation or */
/* parallel combination of values. */
if (cidx == i) {
for (p = 1; p < pcount; p++) {
cvl[p] = avl[p];
}
}
/* Sorting should have put all records with the same critical */
/* value together sequentially. So if there are still */
/* multiple property records, then merge them into the first */
/* record with the same critical property value. */
/* record with the same critical property value. If no */
/* critical value exists, then all records can be merged. */
if ((i > 0) && (cidx >= 0) && (cidx < i)) {
for (p = 1; p < pcount; p++) {
vl = vlist[p][i];
ctype = clist[p][i];
cvlp = cvl[p];
if (ctype & (MERGE_S_ADD | MERGE_P_ADD)) {
if (!vlist[0][i]) {
@@ -5305,21 +5330,21 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
sizeof(struct valuelist));
}
vlist[0][i]->value.ival = 0; /* set M to 0 */
if (cvl && (cvl->type == PROP_INTEGER))
if (cvlp && (cvlp->type == PROP_INTEGER))
{
if (vl->type == PROP_INTEGER)
cvl->value.ival += vl->value.ival;
cvlp->value.ival += vl->value.ival;
else {
cvl->type = PROP_DOUBLE;
cvl->value.dval = (double)cvl->value.ival + vl->value.dval;
cvlp->type = PROP_DOUBLE;
cvlp->value.dval = (double)cvlp->value.ival + vl->value.dval;
}
}
else if ((cvl && vl->type == PROP_DOUBLE))
else if ((cvlp && vl->type == PROP_DOUBLE))
{
if (vl->type == PROP_INTEGER)
cvl->value.dval += (double)vl->value.ival;
cvlp->value.dval += (double)vl->value.ival;
else
cvl->value.dval += vl->value.dval;
cvlp->value.dval += vl->value.dval;
}
}
else if (ctype & (MERGE_S_PAR | MERGE_P_PAR)) {
@@ -5329,21 +5354,22 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
sizeof(struct valuelist));
}
vlist[0][i]->value.ival = 0; /* set M to 0 */
/* To do parallel combination, both types need to
/* Parallel value combination: (X * Y) / (X + Y)
* To do parallel combination, both types need to
* be double, so recast them if they are integer.
*/
if (vl->type == PROP_INTEGER) {
vl->type = PROP_DOUBLE;
vl->value.dval = (double)(vl->value.ival);
}
if (cvl && (cvl->type == PROP_INTEGER)) {
cvl->type = PROP_DOUBLE;
cvl->value.dval = (double)cvl->value.ival;
if (cvlp && (cvlp->type == PROP_INTEGER)) {
cvlp->type = PROP_DOUBLE;
cvlp->value.dval = (double)cvlp->value.ival;
}
if ((cvl && (vl->type == PROP_DOUBLE))) {
cvl->value.dval =
sqrt(cvl->value.dval * cvl->value.dval
+ vl->value.dval * vl->value.dval);
if ((cvlp && (vl->type == PROP_DOUBLE))) {
cvlp->value.dval =
(vl->value.dval * cvlp->value.dval) /
(vl->value.dval + cvlp->value.dval);
}
}
}
@@ -5355,6 +5381,9 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series,
Printf("Combined %d parallel devices.\n", changed);
}
}
FREE(avl);
FREE(cvl);
}
// Remove entries with M (S) = 0
@@ -6053,6 +6082,9 @@ PropertyMatch(struct Element *E1, struct Element *E2,
#endif
}
obn1 = ob1->next;
obn2 = ob2->next;
/* Find the first property record of each circuit. obn1, obn2 are */
/* the last device record before the properties for each device. */
for (tp1 = ob1->next; (tp1 != NULL) && tp1->type > FIRSTPIN; tp1 = tp1->next)
@@ -7013,10 +7045,21 @@ int Permute()
return (0);
}
/* update magic numbers */
for (NL = E->nodelist; NL != NULL; NL = NL->next)
if (NL->pin_magic == one)
NL->pin_magic = two;
/* Update magic numbers. To ensure that this works */
/* regardless of the pin order of the pins in each */
/* netlist, always set both pins to the larger of */
/* the two pin_magic values. */
if (one > two) {
for (NL = E->nodelist; NL != NULL; NL = NL->next)
if (NL->pin_magic == two)
NL->pin_magic = one;
}
else {
for (NL = E->nodelist; NL != NULL; NL = NL->next)
if (NL->pin_magic == one)
NL->pin_magic = two;
}
}
}
}
@@ -7501,6 +7544,11 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
}
else {
lob = ob;
if (ob == NULL) {
Fprintf(stdout, "Error: Premature end of pin list on "
"instance %s.\n", firstpin->instance.name);
break;
}
ob->type = i++;
ob = ob->next;
}
@@ -7514,6 +7562,12 @@ struct nlist *addproxies(struct hashlist *p, void *clientdata)
else {
lob = ob;
ob->type = i++;
if (ob->model.class == NULL) {
ob->model.class = strsave(tc->name);
}
if (ob->instance.name == NULL) {
ob->instance.name = strsave(firstpin->instance.name);
}
ob = ob->next;
}
tob = tob->next;
@@ -7579,6 +7633,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
int hasproxy1 = 0, hasproxy2 = 0;
int needclean1 = 0, needclean2 = 0;
int nomatch = 0;
int P1, P2;
int filenum = -1;
int *correspond;
char *ostr;
@@ -7611,6 +7666,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
return 2;
}
correspond = (int *)CALLOC((tc1->nodename_cache_maxnodenum + 1), sizeof(int));
cover = (char *)CALLOC(numnodes, sizeof(char));
numorig = numnodes;
@@ -7829,8 +7885,6 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
ob1 = tc1->cell;
correspond = (int *)CALLOC((tc1->nodename_cache_maxnodenum + 1), sizeof(int));
for (i = 0; i < numorig; i++) {
bangptr1 = strrchr(ob1->name, '!');
if (bangptr1 && (*(bangptr1 + 1) == '\0'))
@@ -7951,7 +8005,7 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
if (bangptr2) *bangptr2 = '!';
break;
}
else {
else if (IsPort(ob1) && IsPort(ob2)) {
struct Permutation *permute1, *permute2;
struct objlist *ob1a = NULL, *ob2a = NULL;
@@ -7961,30 +8015,28 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
*/
for (permute1 = tc1->permutes; permute1; permute1 = permute1->next) {
if ((*matchfunc)(ob1->name, permute1->pin1)) {
ob1a = LookupObject(permute1->pin1, tc1);
ob2a = LookupObject(permute1->pin2, tc2);
break;
}
else if ((*matchfunc)(ob1->name, permute1->pin2)) {
ob1a = LookupObject(permute1->pin2, tc1);
ob2a = LookupObject(permute1->pin1, tc2);
break;
}
}
for (permute2 = tc2->permutes; permute2; permute2 = permute2->next) {
if ((*matchfunc)(ob2->name, permute2->pin1)) {
ob2a = LookupObject(permute2->pin1, tc2);
ob1a = LookupObject(permute2->pin2, tc1);
break;
}
else if ((*matchfunc)(ob2->name, permute2->pin2)) {
ob2a = LookupObject(permute2->pin2, tc2);
ob1a = LookupObject(permute2->pin1, tc1);
break;
}
}
if (ob1a && ob2a) {
if ((ob1->node == ob1a->node) && (ob2->node == ob2a->node)) {
/* This should be enough to prove equivalency */
if ((correspond[ob1->node] == 0) || (correspond[ob1->node] == ob2->node)) {
correspond[ob1->node] = ob2->node; /* remember corresponding node */
if ((correspond[ob1->node] == 0) ||
(correspond[ob1->node] == ob2->node)) {
ob2->model.port = i; /* save order */
*(cover + i) = (char)1;
@@ -8150,6 +8202,14 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
hasproxy1 = 1;
HashPtrInstall(obn->name, obn, &(tc1->objdict));
/* If this is a black-box circuit, then the pin has not been output */
if (NodeClasses == NULL) {
output_string_fill(ostr);
output_string_left(ostr, "%s", "(no matching pin)");
output_string_right(ostr, "%s", ob2->name);
output_string_print(ostr);
}
}
}
@@ -8220,6 +8280,14 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
hasproxy2 = 1;
HashPtrInstall(obn->name, obn, &(tc2->objdict));
/* If this is a black-box circuit, then the pin has not been output */
if (NodeClasses == NULL) {
output_string_fill(ostr);
output_string_left(ostr, "%s", ob1->name);
output_string_right(ostr, "%s", "(no matching pin)");
output_string_print(ostr);
}
}
else if (ob1 != NULL && ob1->type == PORT && ob1->node < 0) {
@@ -8247,6 +8315,38 @@ int MatchPins(struct nlist *tc1, struct nlist *tc2, int dolist)
if (Debug == 0)
output_string_print_divider(ostr, FALSE);
/* Catch errors where disconnected ports get effectively hidden by */
/* pin permutations. */
if (result == 1) {
int found = 0;
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
P1 = P2 = 0;
for (N1 = NC->nodes; N1 != NULL; N1 = N1->next) {
if (N1->graph == Circuit2->file)
if (IsPort(N1->object)) P2++;
if (N1->graph == Circuit1->file)
if (IsPort(N1->object)) P1++;
}
if (P1 != P2) {
if (found == 0)
Fprintf(stdout, "\nPort connection errors found:\n");
found = 1;
for (N1 = NC->nodes; N1 != NULL; N1 = N1->next) {
obn = N1->object;
if (IsPort(obn))
Fprintf(stdout, " %s (%d)\n", obn->name, N1->graph);
else
Fprintf(stdout, " %s (%d) (no port)\n", obn->name, N1->graph);
if (N1->graph == Circuit1->file)
correspond[obn->node] = -1;
}
}
}
if (found == 1) Fprintf(stdout, "\n");
}
/* Run cleanuppins on circuit 1 */
if (needclean1)
CleanupPins(tc1->name, tc1->file);
@@ -8459,6 +8559,182 @@ int EquivalentElement(char *name, struct nlist *circuit, struct objlist **retobj
return retval;
}
/*------------------------------------------------------*/
/* Structure and definitins used by derivedprops() */
/*------------------------------------------------------*/
enum DerivedType {area_type, perimeter_type};
typedef struct _derivedpropdata {
struct nlist *cell;
int fnum;
char *pwidth;
char *plength;
enum DerivedType type;
} DerivedPropData;
/*------------------------------------------------------*/
/* derivedprops --- Callback function for a recursive */
/* search over all cells with a pointer clientdata. */
/* The pointer is a DerivedPropData structure that */
/* contains the information needed to determine how to */
/* generate an "area" or "perimeter" property based on */
/* the device length and width. */
/*------------------------------------------------------*/
struct nlist *derivedprops(struct hashlist *p, void *clientdata)
{
struct nlist *ptr;
struct objlist *ob;
struct valuelist *vl, *newvlist;
struct nlist *tc;
struct property *prop;
int i;
double valuew, valuel, valuea = 0.0, valuep = 0.0;
int haswidth = FALSE, haslength = FALSE;
int hasarea = FALSE, hasperimeter = FALSE;
DerivedPropData *dpd = (DerivedPropData *)clientdata;
tc = dpd->cell;
ptr = (struct nlist *)(p->ptr);
if (ptr->file != tc->file) return NULL;
/* Search all instances in the cell for properties, find those matching
* the cell class to be modified, and create a new derived property for
* area or perimeter for that instance.
*/
for (ob = ptr->cell; ob; ob = ob->next) {
if (ob->type == PROPERTY) {
if ((*matchfunc)(ob->model.class, tc->name)) {
for (i = 0;; i++) {
vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break;
prop = (struct property *)HashLookup(vl->key, &(tc->propdict));
if (prop != NULL) {
if ((*matchfunc)(vl->key, dpd->pwidth)) {
haswidth = TRUE;
if (vl->type == PROP_DOUBLE)
valuew = vl->value.dval;
else if (vl->type == PROP_INTEGER)
valuew = (double)vl->value.ival;
else
haswidth = FALSE;
}
else if ((*matchfunc)(vl->key, dpd->plength)) {
haslength = TRUE;
if (vl->type == PROP_DOUBLE)
valuel = vl->value.dval;
else if (vl->type == PROP_INTEGER)
valuel = (double)vl->value.ival;
else
haslength = FALSE;
}
else if ((dpd->type == area_type)
&& ((*matchfunc)(vl->key, "area"))) {
hasarea = TRUE;
}
else if ((dpd->type == perimeter_type)
&& ((*matchfunc)(vl->key, "perimeter"))) {
hasperimeter = TRUE;
}
}
}
if (haslength && haswidth) {
/* Once the property names for device width and length have
* been found, and the values recorded, add the area or
* perimeter value to the property list for the instance,
* unless the instance already has the property.
*/
newvlist = (struct valuelist *)CALLOC(i + 1, sizeof(struct valuelist));
vl = &newvlist[i];
vl->key = NULL;
vl->type = PROP_ENDLIST;
vl->value.ival = 0;
vl = &newvlist[--i];
if ((dpd->type == area_type) && (!hasarea)) {
valuea = valuew * valuel;
vl->key = strsave("area");
vl->type = PROP_DOUBLE;
vl->value.dval = valuea;
} else if ((dpd->type == perimeter_type) && (!hasperimeter)) {
valuep = 2 * (valuew + valuel);
vl->key = strsave("perimeter");
vl->type = PROP_DOUBLE;
vl->value.dval = valuep;
}
for (--i; i >= 0; i--) {
vl = &newvlist[i];
vl->key = ob->instance.props[i].key;
vl->type = ob->instance.props[i].type;
vl->value = ob->instance.props[i].value;
}
FREE(ob->instance.props);
ob->instance.props = newvlist;
}
}
}
}
}
/*------------------------------------------------------*/
/* Create a new "area" or "perimeter" property in all */
/* instances of a given device, based on the specified */
/* names for the width and length parameters. */
/*------------------------------------------------------*/
void
DeriveProperty(struct nlist *tc, int fnum, char *pwidth, char *plength,
enum DerivedType type)
{
DerivedPropData dpd;
dpd.pwidth = pwidth;
dpd.plength = plength;
dpd.fnum = fnum;
dpd.cell = tc;
dpd.type = type;
/* Create the new derived property in the cell. */
if (type == area_type)
PropertyDouble(tc->name, fnum, "area", 0.01, 0.0);
else if (type == perimeter_type)
PropertyDouble(tc->name, fnum, "perimeter", 0.01, 0.0);
else
return;
/* Find all instances of the cell and add the derived property */
RecurseCellHashTable2(derivedprops, (void *)(&dpd));
}
/*------------------------------------------------------*/
/* Create a new "area" property in all instances of a */
/* given device, based on the specified width and */
/* length parameter names. */
/*------------------------------------------------------*/
void
DeriveAreaProperty(struct nlist *tp, int fnum, char *pwidth, char *plength)
{
DeriveProperty(tp, fnum, pwidth, plength, area_type);
}
/*------------------------------------------------------*/
/* Create a new "perimeter" property in all instances */
/* of a given device, based on the specified width and */
/* length parameter names. */
/*------------------------------------------------------*/
void
DerivePerimeterProperty(struct nlist *tp, int fnum, char *pwidth, char *plength)
{
DeriveProperty(tp, fnum, pwidth, plength, perimeter_type);
}
/*------------------------------------------------------*/
/* Flatten the two cells at the top of the compare */
/* queue. */
+2
View File
@@ -70,6 +70,8 @@ extern int remove_group_tags(struct objlist *ob);
#ifdef TCL_NETGEN
extern int EquivalentNode();
extern int EquivalentElement();
extern void DeriveAreaProperty();
extern void DerivePerimeterProperty();
extern void enable_interrupt();
extern void disable_interrupt();
+22 -4
View File
@@ -302,7 +302,7 @@ int GetNextLineNoNewline(char *delimiter)
{
char *newbuf;
int testc;
int nested = 0;
static int nested = 0;
int llen;
if (feof(infile)) return -1;
@@ -329,6 +329,11 @@ int GetNextLineNoNewline(char *delimiter)
llen = strlen(line);
}
while (llen == linesize - 1) {
/* Note that in the rare case where a newline is in the last buffer
* position, we're done.
*/
if (*(line + llen - 1) == '\n') break;
newbuf = (char *)MALLOC(linesize + 501);
strcpy(newbuf, line);
FREE(line);
@@ -599,7 +604,7 @@ void SpiceTokNoNewline(void)
{
int contline;
if ((nexttok = strdtok(NULL, WHITESPACE_DELIMITER, NULL)) != NULL) return;
if ((nexttok = strdtok0(NULL, WHITESPACE_DELIMITER, NULL, FALSE)) != NULL) return;
while (nexttok == NULL) {
contline = getc(infile);
@@ -680,6 +685,7 @@ void SpiceSkipNewLine(void)
ungetc(contline, infile);
}
#if 0 /* Commented with "#if 0" due to comment characters in the comment */
/*----------------------------------------------------------------------*/
/* Function similar to strtok() for token parsing. The difference is */
/* that it takes two sets of delimiters. The first is whitespace */
@@ -700,8 +706,9 @@ void SpiceSkipNewLine(void)
/* the first character of the delimiter string in addition to marking */
/* the boundary between two-character and one-character delimiters. */
/*----------------------------------------------------------------------*/
#endif
char *strdtok(char *pstring, char *delim1, char *delim2)
char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog)
{
static char *stoken = NULL;
static char *sstring = NULL;
@@ -746,7 +753,7 @@ char *strdtok(char *pstring, char *delim1, char *delim2)
/* should know whether it is parsing SPICE or verilog and handle the syntax */
/* accordingly (needs to be done). */
if (*s == '\\') {
if (isverilog && (*s == '\\')) {
s++;
while (*s != '\0') {
if ((*s == ' ') || ((*s == '\\') && (*(s + 1) == '\0'))) {
@@ -817,6 +824,17 @@ char *strdtok(char *pstring, char *delim1, char *delim2)
return sstring;
}
/*----------------------------------------------------------------------*/
/* strdtok() is the original string tokenizer. It calls strdtok0() */
/* with isverilog=TRUE, so that tokens are parsed as (potentially) */
/* verilog names, which includes verilog backslash notation. */
/*----------------------------------------------------------------------*/
char *strdtok(char *pstring, char *delim1, char *delim2)
{
return strdtok0(pstring, delim1, delim2, TRUE);
}
/*----------------------------------------------------------------------*/
void InputParseError(FILE *f)
+1
View File
@@ -36,6 +36,7 @@ extern struct hashdict *definitions;
extern char *nexttok;
#define SKIPTO(a) do {SkipTok(NULL);} while (!match(nexttok,a))
extern char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog);
extern char *strdtok(char *pstring, char *delim1, char *delim2);
extern char *GetLineAtTok();
extern void SkipTok(char *delimiter);
+6 -1
View File
@@ -25,6 +25,8 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <stdlib.h> /* for strtof() */
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <ctype.h> /* toupper() */
#ifdef IBMPC
#include <alloc.h>
@@ -2248,7 +2250,10 @@ int PromoteProperty(struct property *prop, struct valuelist *vl,
if (prop == NULL || vl == NULL) return -1;
if (prop->type == vl->type) return 1; /* Nothing to do */
result = 0;
if (prop->type == PROP_EXPRESSION) {
/* If vl is an expression but prop is not, then try to reduce
* the expression in vl.
*/
if (vl->type == PROP_EXPRESSION) {
ReduceOneExpression(vl, ob, tc, FALSE);
}
switch (prop->type) {
+5 -1
View File
@@ -449,6 +449,7 @@ int removeshorted(struct hashlist *p, int file)
ob = nob;
}
}
return 1;
}
/* Remove shorted instances of class "class" from the database */
@@ -539,6 +540,7 @@ int deleteclass(struct hashlist *p, int file)
}
}
FREE(checknodes);
return 1;
}
/* Remove all instances of class "class" from the database */
@@ -576,6 +578,7 @@ int renameinstances(struct hashlist *p, int file)
}
}
}
return 1;
}
void InstanceRename(char *from, char *to, int file)
@@ -598,9 +601,10 @@ int freeprop(struct hashlist *p)
struct property *prop;
prop = (struct property *)(p->ptr);
if (prop->type == PROP_STRING)
if (prop->type == PROP_STRING) {
if (prop->pdefault.string != NULL)
FREE(prop->pdefault.string);
}
else if (prop->type == PROP_EXPRESSION) {
struct tokstack *stackptr, *nptr;
stackptr = prop->pdefault.stack;
+3 -2
View File
@@ -319,7 +319,7 @@ void Fanout(char *cell, char *node, int filter)
while (ob != NULL) {
char *obname = ob->name;
if (*obname == '/') obname++;
if (ob->node == nodenum)
if (ob->node == nodenum) {
if (filter == ALLOBJECTS) {
Printf(" %s (", obname);
PrintObjectType(ob->type);
@@ -331,6 +331,7 @@ void Fanout(char *cell, char *node, int filter)
else if (ob->type == filter) {
Printf(" %s\n", obname);
}
}
ob = ob->next;
}
}
@@ -933,7 +934,7 @@ static int PrintLeavesInCellHash(struct hashlist *p)
struct nlist *ptr;
ptr = (struct nlist *)(p->ptr);
if ((ptr->class == CLASS_SUBCKT)) PrintLeavesInCell(ptr->name, ptr->file);
if (ptr->class == CLASS_SUBCKT) PrintLeavesInCell(ptr->name, ptr->file);
return(0);
}
+19 -6
View File
@@ -21,6 +21,9 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#if 0
#include <stdarg.h> /* what about varargs, like in pdutils.c ??? */
#endif
@@ -193,7 +196,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
if (ob->type == PROPERTY) {
struct valuelist *vl;
int i;
for (i == 0;; i++) {
for (i = 0;; i++) {
vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break;
else if (vl->type == PROP_VALUE) {
@@ -213,7 +216,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
if (ob->type == PROPERTY) {
struct valuelist *vl;
int i;
for (i == 0;; i++) {
for (i = 0;; i++) {
vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break;
else if (vl->type == PROP_VALUE) {
@@ -233,7 +236,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
if (ob->type == PROPERTY) {
struct valuelist *vl;
int i;
for (i == 0;; i++) {
for (i = 0;; i++) {
vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break;
else if (vl->type == PROP_VALUE) {
@@ -396,7 +399,7 @@ int renamepins(struct hashlist *p, int file)
ptr = (struct nlist *)(p->ptr);
if (ptr->file != file)
return 1;
return 0;
for (ob = ptr->cell; ob != NULL; ob = ob->next) {
if (ob->type == FIRSTPIN) {
@@ -423,6 +426,7 @@ int renamepins(struct hashlist *p, int file)
}
}
}
return 1;
}
/* If any pins are marked unconnected, see if there are */
@@ -532,8 +536,14 @@ void ReadSpiceFile(char *fname, int filenum, struct cellstack **CellStackPtr,
SkipTok(NULL); /* get the next token */
if ((EndParseFile()) && (nexttok == NULL)) break;
if (nexttok == NULL) break;
if (nexttok[0] == '*') SkipNewLine(NULL);
/* Handle comment lines. Note that some variants of CDL format
* use "*." for information that is transparent to SPICE simulators.
* Handle "*.GLOBAL" entries. All others are ignored.
*/
if ((nexttok[0] == '*') && (!matchnocase(nexttok, "*.GLOBAL")))
SkipNewLine(NULL);
else if (matchnocase(nexttok, ".SUBCKT")) {
SpiceTokNoNewline();
@@ -821,7 +831,10 @@ skip_ends:
// Handle some commonly-used cards
else if (matchnocase(nexttok, ".GLOBAL")) {
/* .GLOBAL and *.GLOBAL. Note that *.GLOBAL is excepted from comment-line
* handling, above, so any line starting with '*' is "*.GLOBAL".
*/
else if (matchnocase(nexttok, ".GLOBAL") || (nexttok[0] == '*')) {
while (nexttok != NULL) {
int numnodes = 0;
SpiceTokNoNewline();
+172 -39
View File
@@ -76,7 +76,8 @@ struct hashdict verilogparams;
// Global storage for verilog definitions
struct hashdict verilogdefs;
// Record file pointer that is associated with the hash tables
int hashfile = -1;
int hashfilep = -1; /* for parameters */
int hashfiled = -1; /* for definitions */
// Global storage for wire buses
struct hashdict buses;
@@ -156,7 +157,8 @@ struct expr_stack {
//-------------------------------------------------------------------------
// Evaluate an expression for an array bound. This is much like
// ReduceOneExpression() in netgen.c, but only handles basic integer
// arithmetic (+,-,*,/) and grouping by parentheses.
// arithmetic (+,-,*,/), grouping by parentheses, bit shifts, and
// if-else operators.
//
// Returns 1 if successful, 0 on error.
// Evaluated result is placed in the integer pointed to by "valptr".
@@ -220,6 +222,39 @@ int EvalExpr(struct expr_stack **stackptr, int *valptr)
}
}
/* Reduce (a << b) and (a >> b) */
for (texp = start; texp; texp = texp->next) {
if ((texp->last != NULL) && (texp->next != NULL) && (texp->oper != '\0')) {
if ((texp->last->oper == '\0') && (texp->next->oper == '\0')) {
if (texp->oper == '<') {
/* Left shift */
texp->last->value <<= texp->next->value;
/* Remove two items from the stack */
tmp = texp;
texp = texp->last;
texp->next = tmp->next->next;
if (tmp->next->next) tmp->next->next->last = texp;
FREE(tmp->next);
FREE(tmp);
modified = TRUE;
}
if (texp->oper == '>') {
/* Right shift */
texp->last->value >>= texp->next->value;
/* Remove two items from the stack */
tmp = texp;
texp = texp->last;
texp->next = tmp->next->next;
if (tmp->next->next) tmp->next->next->last = texp;
FREE(tmp->next);
FREE(tmp);
modified = TRUE;
}
}
}
}
/* Reduce (a * b) and (a / b) */
for (texp = start; texp; texp = texp->next) {
@@ -295,6 +330,39 @@ int EvalExpr(struct expr_stack **stackptr, int *valptr)
}
}
/* Reduce (a ? b : c) */
for (texp = start; texp; texp = texp->next) {
/* There must be at least five objects on the stack */
if ((texp->last != NULL) && (texp->next != NULL) && (texp->oper != '\0')
&& (texp->next->next != NULL)
&& (texp->next->next->next != NULL)) {
if ((texp->last->oper == '\0') && (texp->next->oper == '\0')
&& (texp->next->next->next->oper == '\0')) {
if ((texp->oper == '?') && (texp->next->next->oper == ':')) {
/* If-Else conditional */
if (texp->last->value)
texp->last->value = texp->next->value;
else
texp->last->value = texp->next->next->next->value;
/* Remove four items from the stack */
tmp = texp;
texp = texp->last;
texp->next = tmp->next->next->next->next;
if (tmp->next->next->next->next)
tmp->next->next->next->next->last = texp;
FREE(tmp->next->next->next);
FREE(tmp->next->next);
FREE(tmp->next);
FREE(tmp);
modified = TRUE;
}
}
}
}
/* Reduce (a) */
for (texp = start; texp; texp = texp->next) {
@@ -373,8 +441,15 @@ int ParseIntegerExpression(char *expr, int *iptr)
if (match(sptr, "+") || match(sptr, "-")
|| match(sptr, "*") || match(sptr, "/")
|| match(sptr, "(") || match(sptr, ")")) {
|| match(sptr, "(") || match(sptr, ")")
|| match(sptr, "<<") || match(sptr, ">>")
|| match(sptr, "?") || match(sptr, ":")) {
newexp = (struct expr_stack *)MALLOC(sizeof(struct expr_stack));
/* Note that "oper" is one character and that "<<" and ">>"
* become '<' and '>', respectively. The less-than and greater-
* than operators are not (yet) handled but will need to be
* recast to some other character in "oper".
*/
newexp->oper = *sptr;
newexp->value = 0;
newexp->next = NULL;
@@ -389,7 +464,7 @@ int ParseIntegerExpression(char *expr, int *iptr)
if ((result = sscanf(sptr, "%d", &value)) != 1) {
// Is name in the parameter list?
kl = (struct property *)HashLookup(nexttok, &verilogparams);
kl = (struct property *)HashLookup(sptr, &verilogparams);
if (kl == NULL) {
Printf("Value %s in expression is not a number or a parameter.\n",
sptr);
@@ -402,27 +477,29 @@ int ParseIntegerExpression(char *expr, int *iptr)
if (result != 1) {
Printf("Parameter %s has value %s that cannot be parsed"
" as an integer.\n",
nexttok, kl->pdefault.string);
sptr, kl->pdefault.string);
value = 0;
break;
}
}
else if (kl->type == PROP_INTEGER) {
value = kl->pdefault.ival;
result = 1; // Assert valid result
}
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);
sptr, kl->pdefault.dval);
value = 0;
break;
}
result = 1; // Assert valid result
}
else {
Printf("Parameter %s has unknown type; don't know how"
" to parse.\n", nexttok);
" to parse.\n", sptr);
value = 0;
break;
}
@@ -516,7 +593,8 @@ int GetBusTok(struct bus *wb)
}
else if (match(nexttok, "+") || match(nexttok, "-")
|| match(nexttok, "*") || match(nexttok, "/")
|| match(nexttok, "(") || match(nexttok, ")")) {
|| match(nexttok, "(") || match(nexttok, ")")
|| match(nexttok, "<<") || match(nexttok, ">>")) {
newexp = (struct expr_stack *)MALLOC(sizeof(struct expr_stack));
newexp->oper = *nexttok;
newexp->value = 0;
@@ -1879,7 +1957,8 @@ skip_endmodule:
// Allowed uses of "assign" for netlists:
// "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" using if-else constructs or bit shifts.
// ("assign" using any other boolean arithmetic is not structural verilog.)
// "assign a = {x{b}}" creates a bus by repeating a component.
if (nexttok && match(nexttok, "=")) {
@@ -2140,6 +2219,19 @@ nextinst:
}
SkipTokComments(VLOG_DELIMITERS);
}
else if (loop.loopvar != NULL) {
/* Instances created within a generate block for loop have an
* implicit array
*/
int loopval;
struct property *klr;
klr = (struct property *)HashLookup(loop.loopvar, &verilogparams);
loopval = klr->pdefault.ival;
arraystart = arrayend = loopval;
sprintf(instancename + strlen(instancename), "[%d]", loopval);
}
if (match(nexttok, "(")) {
char savetok = (char)0;
@@ -2202,7 +2294,8 @@ nextinst:
strcat(new_wire_bundle, nexttok);
FREE(wire_bundle);
wire_bundle = new_wire_bundle;
if (!strcmp(nexttok, "}")) break;
if (!strcmp(nexttok, "}"))
break;
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
}
if (!nexttok) {
@@ -2578,6 +2671,7 @@ nextinst:
char *brackptr;
int j;
char locinst[MAX_STR_LEN];
int arraypos = (arraystart > arrayend) ? arraymax - i : i;
if (i != -1)
sprintf(locinst, "%s[%d]", instancename, i);
@@ -2614,18 +2708,27 @@ nextinst:
if (scan == NULL) {
char localnet[MAX_STR_LEN];
/* Assume an implicit unconnected pin */
sprintf(localnet, "_noconnect_%d_", localcount++);
Node(localnet);
join(localnet, obptr->name);
Fprintf(stdout,
/* Assume an implicit unconnected pin, unless there are no pins */
if (strcmp(obpinname, "(no pins)")) {
sprintf(localnet, "_noconnect_%d_", localcount++);
Node(localnet);
join(localnet, obptr->name);
Fprintf(stdout,
"Note: Implicit pin %s in instance %s of %s in cell %s\n",
obpinname, locinst, modulename, CurrentCell->name);
}
}
else if (GetBus(scan->net, &wb) == 0) {
char *bptr2;
char *scanroot;
scanroot = strsave(scan->net);
int isbundle = FALSE;
/* Skip over a bundle delimiter */
if (*scan->net == '{') {
scanroot = strsave(scan->net + 1);
isbundle = TRUE;
}
else
scanroot = strsave(scan->net);
brackptr = strvchr(scanroot, '[');
if (brackptr) *brackptr = '\0';
@@ -2658,6 +2761,7 @@ nextinst:
else {
// Instance must be an array
char netname[MAX_STR_LEN];
char *spos = scanroot;
int slice, portlen, siglen;
/* Get the array size of the port for bit slicing */
@@ -2669,27 +2773,49 @@ nextinst:
if (siglen < 0) siglen = -siglen;
siglen++;
// If signal array is smaller than the portlength *
// length of instance array, then the signal wraps.
// If this is a bundle, then count out to the current
// slice and read off the index. NOTE: Need to
// handle multiple bits per bundle entry!
if (isbundle) {
int j;
if (brackptr) *brackptr = '[';
for (j = 0; j < arraypos * portlen; j++) {
spos = strvchr(spos, ',');
if (spos == NULL) break;
spos++;
}
if (spos != NULL) {
brackptr = strvchr(spos, '[');
*brackptr = '\0';
sscanf(brackptr + 1, "%d", &slice);
}
else spos = scanroot; /* should emit an error here */
}
else { /* not a bundle */
if (wb2.start >= wb2.end && arraystart >= arrayend) {
slice = wb.start - (arraystart - i) * portlen;
while (slice < wb2.end) slice += siglen;
}
else if (wb2.start < wb2.end && arraystart > arrayend) {
slice = wb.start + (arraystart - i) * portlen;
while (slice > wb2.end) slice -= siglen;
}
else if (wb2.start > wb2.end && arraystart < arrayend) {
slice = wb.start - (arraystart + i) * portlen;
while (slice < wb2.end) slice += siglen;
}
else { // (wb2.start < wb2.end && arraystart < arrayend)
slice = wb.start + (arraystart + i) * portlen;
while (slice > wb2.end) slice -= siglen;
// If signal array is smaller than the portlength *
// length of instance array, then the signal wraps.
if (wb2.start >= wb2.end && arraystart >= arrayend) {
slice = wb.start - (arraystart - i) * portlen;
while (slice < wb2.end) slice += siglen;
}
else if (wb2.start < wb2.end && arraystart > arrayend) {
slice = wb.start + (arraystart - i) * portlen;
while (slice > wb2.end) slice -= siglen;
}
else if (wb2.start > wb2.end && arraystart < arrayend) {
slice = wb.start - (arraystart + i) * portlen;
while (slice < wb2.end) slice += siglen;
}
else { // (wb2.start < wb2.end && arraystart < arrayend)
slice = wb.start + (arraystart + i) * portlen;
while (slice > wb2.end) slice -= siglen;
}
spos = scanroot;
}
sprintf(netname, "%s[%d]", scanroot, slice);
sprintf(netname, "%s[%d]", spos, slice);
if (LookupObject(netname, CurrentCell) == NULL) Node(netname);
join(netname, obptr->name);
}
@@ -2874,18 +3000,25 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
hashfunc = hashcase;
}
if ((hashfile != -1) && (hashfile != *fnum)) {
/* Started a new file, so remove all the parameters and definitions */
if ((hashfilep != -1) && (hashfilep != *fnum)) {
/* Started a new file, so remove all the parameters */
RecurseHashTable(&verilogparams, freeprop);
HashKill(&verilogparams);
hashfilep = -1;
}
if ((hashfiled != -1) && (hashfiled != *fnum)) {
/* Started a new file, so remove all the definitions */
RecurseHashTable(&verilogdefs, freeprop);
HashKill(&verilogdefs);
hashfile = -1;
hashfiled = -1;
}
if (hashfile == -1) {
if (hashfilep == -1) {
InitializeHashTable(&verilogparams, OBJHASHSIZE);
hashfilep = filenum;
}
if (hashfiled == -1) {
InitializeHashTable(&verilogdefs, OBJHASHSIZE);
hashfile = *fnum;
hashfiled = filenum;
}
definitions = &verilogdefs;
+2 -1
View File
@@ -68,6 +68,7 @@ LIB_SPECS = @LIB_SPECS@
LIB_SPECS_NOSTUB = @LIB_SPECS_NOSTUB@
WISH_EXE = @WISH_EXE@
TCL_LIB_DIR = @TCL_LIB_DIR@
EXTRA_CFLAGS =
CC = @CC@
CPP = @CPP@
@@ -76,7 +77,7 @@ CXX = @CXX@
CPPFLAGS = -I. -I${NETGENDIR} @CPPFLAGS@
DFLAGS = @extra_defs@ @stub_defs@ @DEFS@ -DSHDLIB_EXT=\"@SHDLIB_EXT@\" -DNDEBUG
DFLAGS_NOSTUB = @extra_defs@ @DEFS@ -DSHDLIB_EXT=\"@SHDLIB_EXT@\" -DNDEBUG
CFLAGS = @CFLAGS@ @SHLIB_CFLAGS@ @INC_SPECS@
CFLAGS = @CFLAGS@ @SHLIB_CFLAGS@ @INC_SPECS@ ${EXTRA_CFLAGS}
DEPEND_FILE = Depend
DEPEND_FLAG = @DEPEND_FLAG@
+27 -4
View File
@@ -429,7 +429,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set file1 $name1
set cell1 $name1
}
puts stdout "Reading netlist file $file1"
puts stdout "Reading netlist file $file1 for $name1"
set fnum1 [netgen::readnet $file1]
} else {
set cell1 [lindex $flist1 0]
@@ -446,7 +446,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set file2 $name2
set cell2 $name2
}
puts stdout "Reading netlist file $file2"
puts stdout "Reading netlist file $file2 for $name2"
set fnum2 [netgen::readnet $file2]
} else {
set cell2 [lindex $flist2 0]
@@ -461,7 +461,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
}
set clist1 [cells list $fnum1]
set cidx [lsearch -regexp $clist1 ^$cell1$]
set cidx [lsearch -exact $clist1 $cell1]
if {$cidx < 0} {
puts stderr "Cannot find cell $cell1 in file $file1"
return
@@ -469,7 +469,7 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set cell1 [lindex $clist1 $cidx]
}
set clist2 [cells list $fnum2]
set cidx [lsearch -regexp $clist2 ^$cell2$]
set cidx [lsearch -exact $clist2 $cell2]
if {$cidx < 0} {
puts stderr "Cannot find cell $cell2 in file $file2"
return
@@ -477,6 +477,18 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set cell2 [lindex $clist2 $cidx]
}
# The "noflat" list is non-file-specific, so run on each file.
foreach cell $noflat {
set cidx [lsearch -regexp $clist1 ^$cell$]
if {$cidx >= 0} {
netgen::flatten prohibit "$fnum1 $cell"
}
set cidx [lsearch -regexp $clist2 ^$cell$]
if {$cidx >= 0} {
netgen::flatten prohibit "$fnum2 $cell"
}
}
netgen::compare assign "$fnum1 $cell1" "$fnum2 $cell2"
if {$setupfile == ""} {
@@ -504,6 +516,14 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
}
}
close $fsetup
if {$command != {}} {
# Incomplete command. Evaluate it to get a meaningful error message
if {[catch {uplevel 1 [list namespace eval netgen $command]} msg]} {
set msg [string trimright $msg "\n"]
puts stderr "Error $setupfile:$sline (ignoring), $msg"
incr perrors
}
}
} else {
puts stdout "Error: Cannot read the setup file $setupfile"
}
@@ -594,6 +614,9 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
lappend properr [lindex $endval 0]
} elseif {$uresult == -2} { ;# unmatched pins
set doCheckFlatten 1
} elseif {$uresult == -4} { ;# unmatched pins and properties
lappend properr [lindex $endval 0]
set doCheckFlatten 1
}
} else {
# not equivalent
+200 -139
View File
@@ -21,6 +21,8 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <stdlib.h> /* for getenv */
#include <string.h>
#include <strings.h>
#include <stdarg.h> /* for va_list */
#include <tcl.h>
@@ -43,14 +45,14 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define FALSE 0
#endif
#if TCL_MAJOR_VERSION < 9
typedef int Tcl_Size;
#endif
/*-----------------------*/
/* Tcl 8.4 compatibility */
/*-----------------------*/
#ifndef CONST84
#define CONST84
#endif
Tcl_Interp *netgeninterp;
Tcl_Interp *consoleinterp;
int ColumnBase = 0;
@@ -60,47 +62,47 @@ extern int PropertyErrorDetected;
/* Function prototypes for all Tcl command callbacks */
int _netgen_readnet(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_readlib(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_canonical(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_writenet(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_flatten(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_nodes(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_elements(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_debug(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_protochip(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_instances(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_contents(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_describe(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_cells(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_ports(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_model(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_leaves(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_quit(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_reinit(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_log(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_readnet(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_readlib(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_canonical(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_writenet(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_flatten(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_nodes(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_elements(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_debug(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_protochip(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_instances(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_contents(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_describe(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_cells(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_ports(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_model(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_leaves(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_quit(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_reinit(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netgen_log(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
#ifdef HAVE_MALLINFO
int _netgen_printmem(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_printmem(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
#endif
int _netgen_help(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_matching(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_compare(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_iterate(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_summary(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_print(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_format(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_run(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_verify(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_automorphs(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_equate(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_ignore(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_permute(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_property(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_exhaustive(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_symmetry(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_restart(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_global(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netcmp_convert(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
int _netgen_help(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_matching(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_compare(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_iterate(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_summary(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_print(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_format(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_run(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_verify(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_automorphs(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_equate(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_ignore(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_permute(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_property(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_exhaustive(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_symmetry(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_restart(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_global(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
int _netcmp_convert(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
typedef struct _Cmd {
char *name;
@@ -287,7 +289,7 @@ GetTopCell(int fnum)
int
CommonGetFilenameOrFile(Tcl_Interp *interp, Tcl_Obj *fobj, int *fnumptr)
{
int result, llen;
int result;
int fnum, ftest;
char *filename;
struct nlist *tp;
@@ -370,7 +372,8 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
struct nlist **tpr, int *fnumptr)
{
Tcl_Obj *tobj, *fobj;
int result, llen;
int result;
Tcl_Size llen;
int fnum, ftest, index;
char *filename, *cellname;
struct nlist *tp, *tp2;
@@ -399,7 +402,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
Tcl_ResetResult(interp);
/* Is 1st argument a special keyword? */
if (Tcl_GetIndexFromObj(interp, tobj, (CONST84 char **)suboptions,
if (Tcl_GetIndexFromObj(interp, tobj, (const char **)suboptions,
"special", 0, &index) == TCL_OK) {
switch (index) {
case CIRCUIT1_IDX:
@@ -455,7 +458,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
/* Check if 2nd item is a reserved keyword */
if (Tcl_GetIndexFromObj(interp, fobj,
(CONST84 char **)suboptions,
(const char **)suboptions,
"special", 0, &index) == TCL_OK) {
switch (index) {
case CIRCUIT1_IDX:
@@ -580,7 +583,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
} else {
/* Only one name given; check if it matches subOption */
if (Tcl_GetIndexFromObj(interp, objv, (CONST84 char **)suboptions,
if (Tcl_GetIndexFromObj(interp, objv, (const char **)suboptions,
"special", 0, &index) == TCL_OK) {
switch (index) {
@@ -665,7 +668,7 @@ CommonParseCell(Tcl_Interp *interp, Tcl_Obj *objv,
int
_netgen_canonical(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
int result;
struct nlist *np;
@@ -704,7 +707,7 @@ _netgen_canonical(ClientData clientData,
int
_netgen_readnet(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *formats[] = {
"automatic", "ext", "extflat", "sim", "prm", "ntk", "spice",
@@ -741,7 +744,7 @@ _netgen_readnet(ClientData clientData,
return TCL_ERROR;
}
else if (objc > 1) {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)formats,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)formats,
"format", 0, &index) != TCL_OK) {
if (objc == 3)
@@ -850,7 +853,7 @@ _netgen_readnet(ClientData clientData,
int
_netgen_readlib(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *formats[] = {
"actel", "spice", "xilinx", NULL
@@ -883,7 +886,7 @@ _netgen_readlib(ClientData clientData,
Tcl_WrongNumArgs(interp, 1, objv, "format [file]");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)formats,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)formats,
"format", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -930,7 +933,7 @@ _netgen_readlib(ClientData clientData,
int
_netgen_writenet(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *formats[] = {
"ext", "sim", "ntk", "actel",
@@ -949,7 +952,7 @@ _netgen_writenet(ClientData clientData,
Tcl_WrongNumArgs(interp, 1, objv, "format file");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)formats,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)formats,
"format", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -1017,11 +1020,11 @@ _netgen_writenet(ClientData clientData,
int
_netgen_flatten(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *repstr, *file;
int result, llen, filenum;
struct nlist *tp, *tp2;
int result, filenum;
struct nlist *tp, *tp2, *tptop;
if ((objc < 2) || (objc > 4)) {
Tcl_WrongNumArgs(interp, 1, objv, "?class? valid_cellname");
@@ -1035,7 +1038,7 @@ _netgen_flatten(ClientData clientData,
if (objc >= 3) {
char *argv = Tcl_GetString(objv[1]);
if (!strcmp(argv, "class")) {
tp = GetTopCell(filenum);
tptop = GetTopCell(filenum);
if (objc == 4) {
int numflat;
@@ -1046,7 +1049,7 @@ _netgen_flatten(ClientData clientData,
}
else {
Printf("Flattening instances of %s in cell %s within file %s\n",
repstr, tp2->name, tp->name);
repstr, tp2->name, tptop->name);
numflat = flattenInstancesOf(tp2->name, filenum, repstr);
if (numflat == 0) {
Tcl_SetResult(interp, "No instances found to flatten.", NULL);
@@ -1055,15 +1058,19 @@ _netgen_flatten(ClientData clientData,
}
}
else {
Printf("Flattening instances of %s in file %s\n", repstr, tp->name);
Printf("Flattening instances of %s in file %s\n", repstr, tptop->name);
FlattenInstancesOf(repstr, filenum);
}
}
else if (!strcmp(argv, "prohibit") || !strcmp(argv, "deny")) {
tp = GetTopCell(filenum);
Printf("Will not flatten instances of %s in file %s\n", repstr, tp->name);
/* Mark cell as placeholder so it will not be flattened */
tp->flags |= CELL_PLACEHOLDER;
tptop = GetTopCell(filenum);
if (tp == NULL)
Printf("Error: Cell %s does not exist.\n", repstr);
else {
Printf("Will not flatten instances of %s in file %s\n", repstr, tptop->name);
/* Mark cell as placeholder so it will not be flattened */
tp->flags |= CELL_PLACEHOLDER;
}
}
else {
Tcl_WrongNumArgs(interp, 1, objv, "class valid_cellname");
@@ -1087,7 +1094,7 @@ _netgen_flatten(ClientData clientData,
int
_netgen_nodes(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *estr = NULL, *istr = NULL, *cstr, *fstr;
char *optstart;
@@ -1205,7 +1212,7 @@ _netgen_nodes(ClientData clientData,
int
_netgen_elements(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *nstr = NULL, *cstr;
struct objlist * (*ListSave)();
@@ -1300,7 +1307,7 @@ _netgen_elements(ClientData clientData,
int
_netgen_debug(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *yesno[] = {
"on", "off", NULL
@@ -1314,7 +1321,7 @@ _netgen_debug(ClientData clientData,
if (objc == 1)
index = YES_IDX;
else {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)yesno,
"option", 0, &index) != TCL_OK) {
index = CMD_IDX;
}
@@ -1349,7 +1356,7 @@ _netgen_debug(ClientData clientData,
int
_netgen_protochip(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@@ -1369,7 +1376,7 @@ _netgen_protochip(ClientData clientData,
int
_netgen_instances(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *repstr;
int result;
@@ -1399,7 +1406,7 @@ _netgen_instances(ClientData clientData,
int
_netgen_contents(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *repstr;
int result;
@@ -1428,7 +1435,7 @@ _netgen_contents(ClientData clientData,
int
_netgen_describe(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *repstr;
int file = -1;
@@ -1458,7 +1465,7 @@ _netgen_describe(ClientData clientData,
int
_netgen_cells(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *repstr, *filename = NULL;
char *optstart;
@@ -1545,7 +1552,7 @@ _netgen_cells(ClientData clientData,
int
_netgen_model(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
struct nlist *tp, *tp2;
char *model, *retclass;
@@ -1597,7 +1604,7 @@ _netgen_model(ClientData clientData,
if (objc == 3) {
nports = NumberOfPorts(tp->name, fnum);
if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)modelclasses,
if (Tcl_GetIndexFromObj(interp, objv[2], (const char **)modelclasses,
"class", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -1767,7 +1774,7 @@ wrongNumPorts:
int
_netgen_ports(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *repstr;
int result;
@@ -1797,7 +1804,7 @@ _netgen_ports(ClientData clientData,
int
_netgen_leaves(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *repstr;
int result;
@@ -1833,7 +1840,7 @@ _netgen_leaves(ClientData clientData,
int
_netgen_quit(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@@ -1861,7 +1868,7 @@ _netgen_quit(ClientData clientData,
int
_netgen_reinit(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@@ -1881,7 +1888,7 @@ _netgen_reinit(ClientData clientData,
int
_netgen_log(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *yesno[] = {
"start", "end", "reset", "suspend", "resume", "file", "echo", "put", NULL
@@ -1898,7 +1905,7 @@ _netgen_log(ClientData clientData,
index = (LoggingFile) ? RESUME_IDX : START_IDX;
}
else {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)yesno,
"option", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -2025,7 +2032,7 @@ _netgen_log(ClientData clientData,
int
_netgen_printmem(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@@ -2047,7 +2054,7 @@ _netgen_printmem(ClientData clientData,
int
_netcmp_format(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
int col1_width = 41, col2_width = 41;
@@ -2108,13 +2115,13 @@ _netcmp_format(ClientData clientData,
int
_netcmp_compare(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *name1, *name2, *file1, *file2, *optstart;
int fnum1, fnum2, dolist = 0;
int dohierarchy = FALSE;
int assignonly = FALSE;
int argstart = 1, qresult, llen, result;
int argstart = 1, qresult, result;
int hascontents1, hascontents2;
struct Correspond *nextcomp;
struct nlist *tp1 = NULL, *tp2 = NULL;
@@ -2285,7 +2292,7 @@ _netcmp_compare(ClientData clientData,
int
_netcmp_iterate(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@@ -2309,7 +2316,7 @@ _netcmp_iterate(ClientData clientData,
int
_netcmp_summary(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *options[] = {
"nodes", "elements", NULL
@@ -2324,7 +2331,7 @@ _netcmp_summary(ClientData clientData,
return TCL_ERROR;
}
if (objc == 2) {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
"option", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -2350,7 +2357,7 @@ _netcmp_summary(ClientData clientData,
int
_netcmp_print(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *options[] = {
"nodes", "elements", "queue", NULL
@@ -2388,16 +2395,16 @@ _netcmp_print(ClientData clientData,
return TCL_ERROR;
}
if (objc >= 2) {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
"option", 0, &index) != TCL_OK) {
if ((objc == 2) && (Tcl_GetIndexFromObj(interp, objv[1],
(CONST84 char **)classes, "class", 0, &class) != TCL_OK)) {
(const char **)classes, "class", 0, &class) != TCL_OK)) {
return TCL_ERROR;
}
}
}
if (objc == 3 && index != QUEUE_IDX) {
if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)classes,
if (Tcl_GetIndexFromObj(interp, objv[2], (const char **)classes,
"class", 0, &class) != TCL_OK) {
return TCL_ERROR;
}
@@ -2441,7 +2448,7 @@ _netcmp_print(ClientData clientData,
int
_netcmp_run(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *options[] = {
"converge", "resolve", NULL
@@ -2468,7 +2475,7 @@ _netcmp_run(ClientData clientData,
if (objc == 1)
index = RESOLVE_IDX;
else {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
"option", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -2572,6 +2579,7 @@ _netcmp_run(ClientData clientData,
/* 0: not verified */
/* -1: no elements or nodes */
/* -3: verified with property error */
/* -4: verified with property and port errors */
/* equiv option */
/* -2: pin mismatch */
/* */
@@ -2584,7 +2592,7 @@ _netcmp_run(ClientData clientData,
int
_netcmp_verify(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *options[] = {
"nodes", "elements", "properties", "only", "all", "equivalent", "unique", NULL
@@ -2616,7 +2624,7 @@ _netcmp_verify(ClientData clientData,
return TCL_ERROR;
}
if (objc == 2) {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
"option", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -2673,8 +2681,12 @@ _netcmp_verify(ClientData clientData,
else if (automorphisms == -2) {
if (index == EQUIV_IDX)
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
else if (index == UNIQUE_IDX)
Tcl_SetObjResult(interp, Tcl_NewIntObj(-2));
else if (index == UNIQUE_IDX) {
if (PropertyErrorDetected == 0)
Tcl_SetObjResult(interp, Tcl_NewIntObj(-2));
else
Tcl_SetObjResult(interp, Tcl_NewIntObj(-4));
}
else if (index > 0)
Fprintf(stdout, "Circuits match uniquely with port errors.\n");
}
@@ -2769,7 +2781,7 @@ _netcmp_verify(ClientData clientData,
int
_netcmp_automorphs(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@@ -2790,7 +2802,7 @@ _netcmp_automorphs(ClientData clientData,
int
_netcmp_convert(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *cellname;
int filenum = -1;
@@ -2820,10 +2832,10 @@ _netcmp_convert(ClientData clientData,
int
_netcmp_global(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *filename, *cellname, *pattern;
int numchanged = 0, p, fnum, llen, result;
int numchanged = 0, p, fnum, result;
struct nlist *tp;
if (objc < 2) {
@@ -2857,7 +2869,7 @@ _netcmp_global(ClientData clientData,
int
_netcmp_ignore(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *options[] = {
"class", "shorted", NULL
@@ -2871,7 +2883,7 @@ _netcmp_ignore(ClientData clientData,
char *name = NULL, *name2 = NULL;
if (objc >= 3) {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
"option", 0, &index) == TCL_OK) {
objc--;
objv++;
@@ -2905,7 +2917,7 @@ _netcmp_ignore(ClientData clientData,
int
_netcmp_equate(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *options[] = {
"nodes", "elements", "classes", "pins", NULL
@@ -2920,7 +2932,8 @@ _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, dounique = 0;
int i, dolist = 0, doforce = 0, dounique = 0;
Tcl_Size l1, l2, lent, ltest;
Tcl_Obj *tobj1, *tobj2, *tobj3;
while (objc > 1) {
@@ -2950,7 +2963,7 @@ _netcmp_equate(ClientData clientData,
return TCL_ERROR;
}
else {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
"option", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -3419,22 +3432,31 @@ _netcmp_equate(ClientData clientData,
int
_netcmp_property(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
int fnum, i, llen;
int fnum, i;
struct nlist *tp;
struct property *kl, *kllast, *klnext;
Tcl_Obj *tobj1, *tobj2, *tobj3;
Tcl_Size llen;
double dval;
int ival, argstart;
char *topoptions[] = {
"default", "series", "serial", "parallel", "topology", NULL
};
enum TopOptionIdx {
TOP_DEFAULT_IDX, TOP_SERIES_IDX, TOP_SERIAL_IDX, TOP_PARALLEL_IDX,
TOP_TOPOLOGY_IDX
};
char *options[] = {
"add", "create", "remove", "delete", "tolerance", "merge", "serial",
"series", "parallel", "associate", "topology", NULL
"series", "parallel", "associate", "derive", NULL
};
enum OptionIdx {
ADD_IDX, CREATE_IDX, REMOVE_IDX, DELETE_IDX, TOLERANCE_IDX, MERGE_IDX,
SERIAL_IDX, SERIES_IDX, PARALLEL_IDX, ASSOCIATE_IDX, TOPOLOGY_IDX
SERIAL_IDX, SERIES_IDX, PARALLEL_IDX, ASSOCIATE_IDX, DERIVE_IDX
};
int result, index, idx2;
@@ -3469,6 +3491,14 @@ _netcmp_property(ClientData clientData,
COMB_NONE_IDX, COMB_PAR_IDX, COMB_ADD_IDX, COMB_CRITICAL_IDX
};
char *deriveoptions[] = {
"area", "perimeter", NULL
};
enum DeriveOptionIdx {
AREA_IDX, PERIMETER_IDX
};
char *yesno[] = {
"on", "yes", "true", "enable", "allow",
"off", "no", "false", "disable", "prohibit", NULL
@@ -3483,8 +3513,13 @@ _netcmp_property(ClientData clientData,
"strict", "relaxed", NULL
};
/* Don't need to check return value */
index = -1;
Tcl_GetIndexFromObj(interp, objv[1], (const char **)topoptions,
"option", 0, &index);
/* Check for special command "property default" */
if ((objc == 2) && (!strcmp(Tcl_GetString(objv[1]), "default"))) {
if ((objc == 2) && (index == TOP_DEFAULT_IDX)) {
/* For each FET device, do "merge {w add_critical}" and */
/* "remove as ad ps pd". This allows parallel devices */
@@ -3531,7 +3566,7 @@ _netcmp_property(ClientData clientData,
}
return TCL_OK;
}
else if ((objc == 3) && (!strcmp(Tcl_GetString(objv[1]), "parallel"))) {
else if ((objc == 3) && (index == TOP_PARALLEL_IDX)) {
if (!strcmp(Tcl_GetString(objv[2]), "none")) {
GlobalParallelNone = TRUE;
SetParallelCombine(FALSE);
@@ -3553,8 +3588,7 @@ _netcmp_property(ClientData clientData,
}
return TCL_OK;
}
else if ((objc == 3) && ((!strcmp(Tcl_GetString(objv[1]), "series")) ||
(!strcmp(Tcl_GetString(objv[1]), "serial")))) {
else if ((objc == 3) && ((index == TOP_SERIES_IDX) || (index == TOP_SERIAL_IDX))) {
if (!strcmp(Tcl_GetString(objv[2]), "none")) {
SetSeriesCombine(FALSE);
}
@@ -3568,7 +3602,7 @@ _netcmp_property(ClientData clientData,
}
return TCL_OK;
}
else if ((objc > 1) && (!strcmp(Tcl_GetString(objv[1]), "topology"))) {
else if ((objc > 1) && (index == TOP_TOPOLOGY_IDX)) {
if (objc == 2) {
if (ExactTopology)
Tcl_SetResult(interp, "Strict topology property matching.",
@@ -3579,7 +3613,7 @@ _netcmp_property(ClientData clientData,
}
else if (objc == 3) {
if (Tcl_GetIndexFromObj(interp, objv[2],
(CONST84 char **)topo,
(const char **)topo,
"topology", 0, &idx2) == TCL_OK) {
if (idx2 == 0)
ExactTopology = TRUE;
@@ -3638,7 +3672,7 @@ _netcmp_property(ClientData clientData,
Tcl_SetObjResult(interp, tobj1);
}
else {
if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)options,
if (Tcl_GetIndexFromObj(interp, objv[2], (const char **)options,
"option", 0, &index) != TCL_OK) {
index = ADD_IDX;
argstart = 2;
@@ -3671,7 +3705,7 @@ _netcmp_property(ClientData clientData,
// Each value must be a list of two, or a yes/no answer.
if (Tcl_GetIndexFromObj(interp, objv[i],
(CONST84 char **)yesno,
(const char **)yesno,
"combine", 0, &idx2) == TCL_OK) {
if (idx2 <= 4) { /* true, enable, etc. */
if (index == SERIAL_IDX || index == SERIES_IDX)
@@ -3703,7 +3737,7 @@ _netcmp_property(ClientData clientData,
if (result != TCL_OK) return result;
result = Tcl_GetIndexFromObj(interp, tobj2,
(CONST84 char **)combineoptions,
(const char **)combineoptions,
"combine_type", 0, &idx2);
if (result != TCL_OK) return result;
@@ -3788,7 +3822,7 @@ _netcmp_property(ClientData clientData,
/* {key, type} or {key, tolerance} duplet */
if (Tcl_GetIndexFromObj(interp, tobj2,
(CONST84 char **)suboptions,
(const char **)suboptions,
"type", 0, &idx2) != TCL_OK) {
Tcl_ResetResult(interp);
if (Tcl_GetDoubleFromObj(interp, tobj2, &dval)
@@ -3832,7 +3866,7 @@ _netcmp_property(ClientData clientData,
/* {key, type, tolerance} triplet */
if (Tcl_GetIndexFromObj(interp, tobj2,
(CONST84 char **)suboptions,
(const char **)suboptions,
"type", 0, &idx2) != TCL_OK)
return TCL_ERROR;
@@ -3975,7 +4009,7 @@ _netcmp_property(ClientData clientData,
if (result != TCL_OK) return result;
result = Tcl_GetIndexFromObj(interp, tobj2,
(CONST84 char **)mergeoptions,
(const char **)mergeoptions,
"merge_type", 0, &idx2);
if (result != TCL_OK) return result;
@@ -4014,6 +4048,32 @@ _netcmp_property(ClientData clientData,
}
break;
case DERIVE_IDX:
/* Create a derived property. For now, this just creates
* "area" or "perimeter" properties. There may not (?)
* be enough cause to make other ones. Unlike other
* "property" options, this option causes the whole circuit
* database to be searched for the device in question, and
* the new property is added.
*/
if (objc < 6) {
Tcl_WrongNumArgs(interp, 2, objv, "{area|perimeter width length}");
return TCL_ERROR;
}
result = Tcl_GetIndexFromObj(interp, objv[3],
(const char **)deriveoptions,
"area|perimeter", 0, &idx2);
if (result != TCL_OK) return result;
switch (idx2) {
case AREA_IDX:
DeriveAreaProperty(tp, fnum, Tcl_GetString(objv[4]),
Tcl_GetString(objv[5]));
break;
case PERIMETER_IDX:
DerivePerimeterProperty(tp, fnum, Tcl_GetString(objv[4]),
Tcl_GetString(objv[5]));
break;
}
}
}
return TCL_OK;
@@ -4033,7 +4093,7 @@ _netcmp_property(ClientData clientData,
int
_netcmp_permute(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *model, *pin1, *pin2;
char *permuteclass[] = {
@@ -4054,7 +4114,7 @@ _netcmp_permute(ClientData clientData,
index = DEFLT_IDX;
}
else {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)permuteclass,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)permuteclass,
"permute class", 0, &index) != TCL_OK) {
if (objc != 4) {
Tcl_WrongNumArgs(interp, 1, objv, "?valid_cellname pin1 pin2?");
@@ -4174,7 +4234,7 @@ _netcmp_permute(ClientData clientData,
int
_netcmp_symmetry(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
Printf("Symmetry breaking method has been deprecated.\n");
return TCL_OK;
@@ -4190,7 +4250,7 @@ _netcmp_symmetry(ClientData clientData,
int
_netcmp_exhaustive(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *yesno[] = {
"on", "off", NULL
@@ -4203,7 +4263,7 @@ _netcmp_exhaustive(ClientData clientData,
if (objc == 1)
index = -1;
else {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)yesno,
"option", 0, &index) != TCL_OK)
return TCL_ERROR;
}
@@ -4232,7 +4292,7 @@ _netcmp_exhaustive(ClientData clientData,
int
_netcmp_restart(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "(no arguments)");
@@ -4252,7 +4312,7 @@ _netcmp_restart(ClientData clientData,
int
_netgen_help(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
int n;
@@ -4283,7 +4343,7 @@ _netgen_help(ClientData clientData,
int
_netcmp_matching(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
char *options[] = {
"nodes", "elements", NULL
@@ -4305,7 +4365,7 @@ _netcmp_matching(ClientData clientData,
name = Tcl_GetString(objv[1]);
}
else {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)options,
if (Tcl_GetIndexFromObj(interp, objv[1], (const char **)options,
"option", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -4434,14 +4494,14 @@ void tcl_vprintf(FILE *f, const char *fmt, va_list args_in)
void tcl_stdflush(FILE *f)
{
Tcl_SavedResult state;
Tcl_InterpState state;
static char stdstr[] = "::flush stdxxx";
char *stdptr = stdstr + 11;
Tcl_SaveResult(netgeninterp, &state);
state = Tcl_SaveInterpState(netgeninterp, TCL_OK);
strcpy(stdptr, (f == stderr) ? "err" : "out");
Tcl_Eval(netgeninterp, stdstr);
Tcl_RestoreResult(netgeninterp, &state);
Tcl_RestoreInterpState(netgeninterp, state);
}
/*------------------------------------------------------*/
@@ -4471,7 +4531,7 @@ char *Tcl_Strdup(const char *s)
/*------------------------------------------------------*/
int _tkcon_interrupt(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
InterruptPending = 1;
return TCL_OK;
@@ -4510,7 +4570,7 @@ int Tclnetgen_Init(Tcl_Interp *interp)
/* Remember the interpreter */
netgeninterp = interp;
if (Tcl_InitStubs(interp, "8.5", 0) == NULL) return TCL_ERROR;
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) return TCL_ERROR;
for (n = 0; netgen_cmds[n].name != NULL; n++) {
sprintf(keyword, "netgen::%s", netgen_cmds[n].name);
@@ -4519,7 +4579,8 @@ int Tclnetgen_Init(Tcl_Interp *interp)
}
for (n = 0; netcmp_cmds[n].name != NULL; n++) {
sprintf(keyword, "netgen::%s", netcmp_cmds[n].name);
Tcl_CreateObjCommand(interp, keyword, netcmp_cmds[n].handler,
Tcl_CreateObjCommand(interp, keyword,
(Tcl_ObjCmdProc *)netcmp_cmds[n].handler,
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
}