Compare commits

...
120 Commits
Author SHA1 Message Date
Tim Edwards 0b014e6efd Merge branch 'master' into netgen-1.5 2021-03-20 03:00:09 -04:00
Tim Edwards 0a2adeb593 Modified the "flatten" command to allow class "module" to be
flattened.  This is marginally useful---since the "module" class
is a black box, it is essentially the same as using the "ignore"
command.
2021-03-19 13:57:11 -04:00
Tim Edwards 330b34139c Slight modification to print the list of cells being forced to
match for both the filename option and immediate list.
2021-03-19 10:51:42 -04:00
Tim Edwards 62d0352149 Modified the "-noflatten" command option to "lvs" so that it can be
given a filename as a value in addition to being passed a list of
cells directly.
2021-03-19 09:41:42 -04:00
Tim Edwards 9ca713dfd9 Merge branch 'master' into netgen-1.5 2021-03-18 03:00:29 -04:00
Tim Edwards b1b04b8e87 Corrected a statement related to proxy pins that can cause a
segfault condition.
2021-03-17 16:31:22 -04:00
Tim Edwards 851a1f941e Merge branch 'master' into netgen-1.5 2021-03-06 03:00:09 -05:00
Tim Edwards 6b9d92de65 Corrected some pointer-to-int and int-to-pointer conversions to
keep the compiler happy.
2021-03-05 20:19:04 -05:00
Tim Edwards d763ad0e60 First and simplest (but most effective) cut at aligning the two
sides of the output when presenting side-by-side results.  This
matches up net or device names within a partition.  Where net or
device names match, the contents are also aligned on either side.
I attempted to also do a "best match" of contents between sides,
but as this involves a lot of analyzing the contents, it is very
computationally expensive, and so the code has been disabled.  It
could be added back in as an option.  There are also various ways
to optimize it for speed.
2021-03-05 17:23:22 -05:00
Tim Edwards fd72e24a86 Corrected an error in the code that handles no-connects as valid
pins for enabling parallel combinations, which could cause a crash.
Added a "-force" option to "equate pins" to allow pins to be matched
even on subcircuits that did not correctly match;  this was done in
conjuction with an extra option to the "lvs" command "-noflatten="
to pass a list of cellname to not be flattened even if they do not
match.  This is generally discouraged, as it prevents netgen from
resolving differences between layout and schematic hierarchy, but it
can be useful for checking that the hierarchy above a certain cell
is correct, given that if a subcell is really unmatched, then its
errors will keep propagating up the top level, making additional
errors hard to diagnose.
2021-03-05 11:32:17 -05:00
Tim Edwards 20077d3d56 Modifed the handling of parallelized no-connects so that the behavior
can be turned on or off from the setup using "property parallel open"
to allow parallelizing devices with no-connect pins vs. "property
parallel connected" to only allow parallelizing of devices with all
pins connected.
2021-03-03 17:31:45 -05:00
Tim Edwards fb798d6ce7 Merge branch 'master' into netgen-1.5 2021-03-03 03:00:12 -05:00
Tim Edwards a21ba820e9 Corrected a missing variable in a print statement in the SPICE read
routine that can cause a segfault.
2021-03-02 21:48:48 -05:00
Tim Edwards 792c5e569a Resolved the case mentioned in a prior commit where the case of N
devices in parallel with unconnected pins would be confused with
N devices in parallel with those pins all tied together.  This is
treated as a property error.
2021-03-02 16:49:03 -05:00
Tim Edwards f92192efd4 Corrected an error from yesterday's commit; the test case for
parallel combinations with disconnected nodes works with the error,
but in general it won't.
2021-03-02 10:58:36 -05:00
Tim Edwards 1f50c7ccc5 Updating VERSION with pull request #18 on github. 2021-03-02 10:16:54 -05:00
Ahmed Ghazy 8282460774 Remove netgen.{sh,tcl} and add them to .gitignore 2021-03-02 10:24:17 +02:00
Tim Edwards a888502038 Merge branch 'master' into netgen-1.5 2021-03-02 03:00:35 -05:00
Tim Edwards ea07642172 Removed the symmetry breaking option from the scripted "lvs"
command.
2021-03-01 16:57:49 -05:00
Tim Edwards e9da037001 Removed the code for fast symmetry breaking, as it has been found
to generate incorrect results on occasion.  The method to parallelize
cells with the same no-connect pins should avoid the worst-case
symmetry breaking that was previously plaguing the LVS of large
standard-cell layouts.
2021-03-01 16:55:07 -05:00
Tim Edwards 7ee50a3f8f Modified the parallel combination code to treat cells as equivalently
parallel if the same pins are no-connects.  These were previously not
treated as parallel because each no-connect has a unique node number,
and cells were only considered as parallel if all pins connected to
the same node numbers.  This avoids issues with long-running symmetry
breaking on standard cell designs due to cells like antenna taps or
any cell that is placed without connecting it up.  To do:  This
makes indistinguishable certain cases, e.g., N cells in circuit 1
with pin X open vs. N cells in circuit 2 with pin X all tied together.
This could be caught during property matching.
2021-03-01 16:33:55 -05:00
Tim Edwards c16258d4d1 Merge branch 'master' into netgen-1.5 2021-02-25 03:00:36 -05:00
Tim Edwards c7848c9c02 Corrected an error that (in a rare circumstance) can cause netgen
to go into an infinite loop and fill memory until it crashes, due
to a complete pin mismatch between devices causing one device to
have its pins removed and replaced with proxy pins.
2021-02-24 16:12:19 -05:00
Tim Edwards 5341d7a5fd Merge branch 'master' into netgen-1.5 2021-02-17 03:00:31 -05:00
Tim Edwards 402e1f0f25 Found a chokepoint in FlattenInstancesOf that was unnecessary as it
was running through the entire object linked list to find the
predecessor of a record that it had already found.  Solved by simply
keeping track of the predecessor record.
2021-02-16 17:12:00 -05:00
Tim Edwards 8395df633c Merge branch 'master' into netgen-1.5 2021-02-10 03:00:16 -05:00
Tim Edwards 19471275df Added handling of control blocks (.CONTROL ... .ENDC) in ngspice-
format files to the SPICE parser, so that netgen can be run
directly on a testbench file and not generate errors due to
statements in the control block.
2021-02-09 09:30:27 -05:00
Tim Edwards e75f5661e2 Added a zero-value current source to the zero-valued devices handled
by the pre-matching method.  The current source is treated like the
others except that it forms an open circuit rather than a short.
2021-02-09 09:12:22 -05:00
Tim Edwards 6554063df3 Merge branch 'master' into netgen-1.5 2021-01-22 03:00:40 -05:00
Tim Edwards a034fc16d6 Updated VERSION. 2021-01-21 13:41:20 -05:00
Tim Edwards 62fbd422e2 Modified netcmp.c "addproxies" routine to not get confused by cells
with no pins marked with a "(no pins)" placeholder.  Otherwise it
goes into an infinite loop and eats up memory until it crashes.
2021-01-21 13:38:44 -05:00
Tim Edwards 4416a380b3 Merge branch 'master' into netgen-1.5 2021-01-18 03:00:51 -05:00
Tim Edwards d0bae6aff4 Updated VERSION with the merge of pull request #15 from Alessandro de
Laurenzis.
2021-01-17 11:38:11 -05:00
Alessandro De Laurenzis 8a7bb7f2ca Fix missing prototype for ReadVerilogFile function
Unbreak OpenBSD port for mips64 arch
2021-01-17 10:21:52 +01:00
Tim Edwards 46394b2000 Merge branch 'master' into netgen-1.5 2021-01-17 03:00:15 -05:00
Tim Edwards 0df6c83df5 Updated VERSION to go along with the merge of pull request #14
from Anton Blanchard.
2021-01-16 12:05:52 -05:00
Anton Blanchard 8996fe03dc Increase OBJHASHSIZE
I have a design that is taking quite a long time for netgen to complete LVS
checking. Profiles show a large chunk of runtime is in the hash functions.

Some of the hashtables are very sparsely populated, but others are
heavily used. One hashtable has chains of over 250. Longer term it would
be worth investigating resizing the hashtables (or perhaps using other
data strutures), but for now I looked at what changing the number of
hash buckets (OBJHASHSIZE) does for performance:

OBJHASHSIZE	time (mm:ss)
997		24:18
10093		 4:42
42073		 3:12
104729		 2:51

I somewhat arbitrarily chose 42073 which gives us a 7.6x improvement in
runtime.
2021-01-15 18:24:34 -07:00
Tim Edwards 3fe3bc4cfa Merge branch 'master' into netgen-1.5 2021-01-09 03:00:32 -05:00
Tim Edwards f3cebd9099 Corrected a potential crash condition while doing series combination. 2021-01-08 09:55:00 -05:00
Tim Edwards 6661910672 Merge branch 'master' into netgen-1.5 2020-12-21 03:00:30 -05:00
Tim Edwards 920c6e6928 Corrected a problem causing a segfault during a property record
copy if the property record does not have a model.class record
(should it always?).
2020-12-20 11:55:20 -05:00
Tim Edwards e7a36630f6 Merge branch 'master' into netgen-1.5 2020-12-16 03:00:54 -05:00
Tim Edwards 69780aa048 Added patch from Mitch Bailey which sorts the objects in a verilog
file input so that pins occur first before nodes, as they do in a
SPICE netlist.  Certain parts of the comparison code depend on pins
being first in the netlist, and reordering them when reading input
is easier than rewriting the rest of the code.
2020-12-15 09:57:49 -05:00
Tim Edwards f32b0b34a3 Merge branch 'master' into netgen-1.5 2020-12-06 03:00:10 -05:00
Tim Edwards 2a0ebfde93 Updated VERSION with the commit. 2020-12-05 15:46:45 -05:00
Tim Edwards 6e9e6abe98 Removed the netgen.sh and netgen.tcl scripts from the repository,
which are generated by ./configure and should not be in the repo.
2020-12-05 15:46:03 -05:00
Tim Edwards 6b731ddd7a Merge branch 'master' into netgen-1.5 2020-12-04 03:00:27 -05:00
Tim Edwards b9769b9f55 Updated version to go along with pull request merge from github. 2020-12-03 20:17:59 -05:00
Tim 'mithro' Ansell 7e42483986 Fix configure script to not clobber CFLAGS.
Signed-off-by: Tim 'mithro' Ansell <[email protected]>
2020-11-29 16:39:28 -08:00
Tim 'mithro' Ansell 97b0d08e4f Rework configure script so exit code works.
The previous script would swallow the exit code of the `./configure`
script and thus it looked like doing a configure always succeeded.

Signed-off-by: Tim 'mithro' Ansell <[email protected]>
2020-11-29 16:35:47 -08:00
Tim Edwards 99e35d8b11 Merge branch 'master' into netgen-1.5 2020-10-09 03:00:25 -04:00
Tim Edwards d2c356f9e2 Added a "-full" switch to the scripted "lvs" command that switches
to the old symmetry breaking method (see previous commit message).
2020-10-08 09:57:01 -04:00
Tim Edwards 5e99fd5ef9 Found a counterexample which shows that the fast symmetry breaking
introduced in revision 150 can result in an incorrect result
reporting a bad match where the match is actually good (as proven
by running the full symmetry breaking on the same netlist).
Because the fast symmetry breaking is orders of magnitude faster
for large circuits, and because the false positive result appears
to be rare, I have introduced a command "symmetry" to switch
methods between fast and full.  So fast symmetry breaking can be
run unless the result fails on symmetry breaking, in which case
the method can be switched to full to see if the problem is a
false positive or not.  This is not an ideal solution, and some
investigation is needed to determine if there is a way to apply
fast symmetry breaking without encountering a false positive
error.
2020-10-08 09:43:25 -04:00
Tim Edwards 65b542f0ab Merge branch 'master' into netgen-1.5 2020-10-08 03:00:22 -04:00
Tim Edwards 04dd4a64d5 Corrected problems with the port count routine not being specified
with the file number, so that it can get confused between libraries.
Also made a fix to coerce one cell class to be forced to be the
same in both circuits under some circumstances.
2020-10-07 21:32:07 -04:00
Tim Edwards b826870be9 Merge branch 'master' into netgen-1.5 2020-08-09 03:01:40 -04:00
Tim Edwards 50b0e9cb65 Found examples where the automated "pin matching" algorithm causes
the top level circuits to be declared matching with no errors even
though the pins do not match.  "proxy pins" are fine for subcells
to detect cases where one subcell has an unused pin and the matching
subcell does not declare it, but that should not be allowed on the
top level, as it cannot be known whether the pin is unused or not.
2020-08-08 13:19:26 -04:00
Tim Edwards ed5276d67b Merge branch 'master' into netgen-1.5 2020-08-04 03:00:31 -04:00
Tim Edwards 82be18ec4b Corrected a bounds check on sub-arrays inside bundles, that prevents
the bundle from being parsed correctly when any sub-array is only one
bit wide.
2020-08-03 22:57:19 -04:00
Tim Edwards 4ee3a1464b Corrected the left-hand side assignment for "assign" statements and
corrected the error statement so that it refers both to the (corrected)
left-hand side and also the portion of the right-hand side that cannot
be parsed as structural verilog.
2020-08-03 11:49:09 -04:00
Tim Edwards 69c9d85be7 Merge branch 'master' into netgen-1.5 2020-08-01 03:00:23 -04:00
Tim Edwards 8e215d3b66 Corrected the PropertyMatch() routine; previously the symmetry
breaking by property was only matching properties between circuits but
not within the same circuit, which is needed for correct symmetry
breaking.  But the PropertyMatch() routine assumed that it is passed
one item from each circuit, leading to a segfault when running the
symmetry breaking within a single circuit.  This has been fixed.
2020-07-31 12:56:20 -04:00
Tim Edwards c45d51e950 Tracked down and fixed problems with implicit pins in verilog (pins
that are not declared in the verilog netlist because they don't
connect to anything, and their presence is not required by verilog
syntax) and the printing of proxy pins created to act as placeholders
for those implicit pins.  Also removed the pinting of the "disconnected
pin" messages for black-box modules (since by definition they have
disconnected pins, because black-box modules have no contents).
2020-07-31 12:22:50 -04:00
Tim Edwards ad05d059c7 Merge branch 'master' into netgen-1.5 2020-07-31 03:00:27 -04:00
Tim Edwards 85eb34c01e Made several corrections to handling of proxy pins when matching
black-box circuits, especially those coming from verilog netlists
where a pin does not need to be declared and is implicitly floating.
This prevents the need to have an explicit black-box entry for any
verilog module that may have an instance that does not declare all
the pin connections.  Also corrected an error which causes mysterious
failures if a verilog netlist is read before a SPICE netlist,
because the former gets hashed case-sensitive and the latter changes
the hashing to case-insensitive.  Modified to force the SPICE
netlist to be treated case-sensitive, which may cause errors, but
is consistent with the reverse order handling, and doesn't cause
unexplained errors.
2020-07-30 22:51:34 -04:00
Tim Edwards 8a24c6c3ca Modified the ResolveAutomorphisms() routine once again, to break
symmetry of all elements in all symmetric partitions, rather than
(as previously done) all elements in each partition, before re-
running iterations to convergence.  This solves the problem of
having a very large number of partitions with a few elements each
taking a long time to run.
2020-07-30 14:48:08 -04:00
Tim Edwards 46cdf48bc4 Updated the version to force the tarball and github mirror. 2020-07-30 08:10:09 -04:00
Tim Edwards 9d542b92b0 Corrected one logical error in netcmp.c from the last commit,
discovered and fixed by Ahmed Ghazy.
2020-07-30 08:06:44 -04:00
Tim Edwards 1b2cd1497c Merge branch 'master' into netgen-1.5 2020-07-30 03:00:28 -04:00
Tim Edwards 71ad228d8d Modified the symmetry breaking routine that arbitrarily resolves
automorphisms so that it arbitrarily assigns all pairs from
circuit1 and circuit2 at once rather than assigning one pair at
a time and rerunning to convergence.  I'm not sure of the validity
of this, other than that I have never seen a circuit fail to match
after resolving automorphisms, leading me to believe that the way
the symmetry breaking is done is irrelevant.
2020-07-29 21:13:45 -04:00
Tim Edwards 339a0d5d4e Updated version to force the new tarball and github mirror. 2020-07-29 13:59:24 -04:00
Tim Edwards 9cebb76787 Corrected a problem in ResolveAutomorphsByProperty() that causes
long run-times even when there are no properties to check.  Corrected
a problem with SPICE and verilog netlist reading which arbitrarily
replaces file extensions even when a file extension is given,
resulting in reading the wrong file.
2020-07-29 13:57:08 -04:00
Tim Edwards d9d5a46c6e Merge branch 'master' into netgen-1.5 2020-07-25 03:00:09 -04:00
Tim Edwards 251622c8bc Corrected the routines DescendCountQueue and DescendCompareQueue
to include type CLASS_MODULE in the list of types to descend into,
since "module" (black-box) types need to be checked for pin
matching even if they have no contents.  This allows two verilog
netlists to be compared against each other.
2020-07-24 20:50:07 -04:00
Tim Edwards d73b711e3a Merge branch 'master' into netgen-1.5 2020-07-02 03:00:09 -04:00
Tim Edwards 18739235a9 Extended the code from the last commit to cover cases in which the
definition covers multiple lines;  this also is a general handler
of the backslash-newline continuation line.
2020-07-01 16:00:54 -04:00
Tim Edwards 07c493c796 Corrected the verilog parser's behavior with respect to string
definitions:  Now correctly parses everything from the definition
name to the end of line as the definition value.  Also:  The
search for definitions in the body of the text does not reject
non-alphanumerics "_" and "$" in the definition name, without
which definition names containing those characters will go
unrecongized.  Have not yet extended this to multi-line definition
values.
2020-07-01 14:28:00 -04:00
Tim Edwards cca0e4b3f3 Corrected an error in bundle assignment that failed to make a copy
of the root name of the LHS net, and so would use the last root
name copied, which might have belonged to something entirely
different, or nothing at all.
2020-07-01 13:11:37 -04:00
Tim Edwards 1428580109 Merge branch 'master' into netgen-1.5 2020-06-17 03:00:38 -04:00
Tim Edwards fb0e1d10b0 Added back a correction that did not get made in this code base
and so didn't make it into the commit.  Handles implicit pins in
verilog.
2020-06-16 17:16:30 -04:00
Tim Edwards 6f81e1d294 Removed a restriction on the "equate pins" command such that pins
are matched on circuits that have no elements.  This condition
does not necessarily indicate an error, and matching pins has no
adverse affect (while refusing to match them certainly can).
2020-06-16 15:56:59 -04:00
Tim Edwards cec6d89474 Corrected an uninitialized variable error in the verilog reading code
that produces a segfault condition.
2020-06-16 12:52:29 -04:00
Tim Edwards 210dfb25c3 Merge branch 'master' into netgen-1.5 2020-06-04 03:00:24 -04:00
Tim Edwards 9bcca3ac21 Corrected the verilog parsing (yet again!) so that it does not
mistakenly flag bus delimiter characters inside backslash-escaped
names when looking for bus delimiters.
2020-06-03 17:00:42 -04:00
Tim Edwards 27f2ab8b3f Merge branch 'master' into netgen-1.5 2020-03-28 03:00:24 -04:00
Tim Edwards 6ae6a246e9 Some additional changes to better identify behavioral verilog
blocks.
2020-03-27 15:09:56 -04:00
Tim Edwards d985ea340e One more bug fix. . . unitialized variable error. 2020-03-27 12:47:24 -04:00
Tim Edwards 5ea7916ff1 Final (I hope) correction to netgen for handling signal wraparound
for buses applied to instance arrayes.
2020-03-27 12:15:57 -04:00
Tim Edwards cf9dedb2f7 Additional corrections; needed to maintain port width in the
scan structure because it is used in two different places and
would have to run a cost-prohibitive search of the cell's
object list.  Also, was missing recording a bus input/output
signal from an "input" or "output" statement (as opposed to
in-line signals in the I/O list).
2020-03-27 11:31:21 -04:00
Tim Edwards da667c3b17 Corrected handling of wire bundles in the verilog parser. 2020-03-27 08:48:48 -04:00
Tim Edwards 1be00bbd99 Merge branch 'master' into netgen-1.5 2020-03-27 03:00:21 -04:00
Tim Edwards 36aa373fb2 Corrected an error in the verilog read to correctly assign signals
to bus pins over an array of instances.  Takes care of the three
situations where the length of the signal bus equals the number of
instances;  where the length of the signal bus is a multiple of
the number of instances;  and where the number of instances is a
multiple of the length of the signal bus.
2020-03-26 11:53:52 -04:00
Tim Edwards 18f230fc46 Changed the default string size for tmpstr in flattenInstancesOf
from 200 to 1024.  Probably this should be dynamically allocated
and expanded as needed, as it is holding names that are of
increasing length as a hierarchy is descended and the instance
prefixes appended to the name.
2020-03-26 09:04:52 -04:00
Tim Edwards 03b241a5d4 Merge branch 'master' into netgen-1.5 2020-03-11 03:00:17 -04:00
Tim Edwards 0f5a618353 Corrected some problems with property matching in netcmp.c.
However, I have identified an issue that has not yet been resolved,
which is that there can be automorphisms that are potentially
broken by property matching.  Currently, the automorphisms are
arbitrarily resolved, then properties are matched---and may fail
accordingly.
2020-03-10 21:39:41 -04:00
Tim Edwards 43cebd1ef9 Merge branch 'master' into netgen-1.5 2020-03-06 03:00:39 -05:00
Tim Edwards 983c654086 Corrected error in property matching that can cause a segfault. 2020-03-05 15:20:46 -05:00
Tim Edwards 515fccc633 Corrected error in printing the name of a file when it is not found
in an "include" statement in either SPICE or verilog.  Modified pin
matching behavior to force cells in both netlists to be marked as
black-box entries if either one is marked as a black-box entry (this
may not be needed, but shouldn't do any harm, either).
2020-03-05 09:41:22 -05:00
Tim Edwards 0490959b07 Merge branch 'master' into netgen-1.5 2020-03-05 03:00:09 -05:00
Tim Edwards 7d94a7d5f6 Updated VERSION for new tarball. 2020-03-04 21:06:21 -05:00
Tim Edwards 39b3bb4d96 Changed behavior of MatchPins so that disconnected pins that are to
be removed because they do not match pins on the other cell being
compared, are marked with a different number (-2) than the usual
(-1).  CleanupPins then only removes those pins that are marked,
rather than all disconnected pins.
2020-03-04 21:01:43 -05:00
Tim Edwards 44673a04b6 Corrected the verilog parser to handle backslash-escape notation
in instance names, and to ignore bus delimiters inside backslash-
escaped names when determining if a net is a bus or not.
2020-03-04 16:55:53 -05:00
Tim Edwards a34f08b20a Corrected problem in flattening code that would attempt to flatten
a cell that mismatched by having zero instances.  Which fails and
repeats indefinitely.
2020-03-04 15:17:42 -05:00
Tim Edwards 240a276431 Changed behavior of "equate pins" to detect placeholder cells as
a different way of treating "black box" cells.  Even when the
"-blackbox" option is specified, any cell that has no definition
will be treated as a black box.  This allows comparison of a
black-box netlist against a non-black-box netlist, such as a
verilog netlist vs. a SPICE netlist, without forcing the black-box
attribute on the SPICE netlist.  Then, if the SPICE netlist
contains cells without elements such as fill/decap/tap cells,
they can be flattened and removed instead of forcing an error or
requiring the use of "ignore".
2020-03-03 10:50:45 -05:00
Tim Edwards dc841f3293 Merge branch 'master' into netgen-1.5 2020-02-24 17:35:04 -05:00
Tim Edwards f7037fc9e6 Updated VERSION manually; checking regeneration of tarball. 2020-02-24 17:34:38 -05:00
Tim Edwards 23fb9356f4 Corrected Makefile to use -include instead of include on defs.mak
so that "make distclean" works.
2020-02-24 17:31:06 -05:00
Tim Edwards 05bcfede69 Merge branch 'master' into netgen-1.5 2020-02-24 16:39:19 -05:00
Tim Edwards 027b4ae468 Test update of VERSION. 2020-02-24 16:38:56 -05:00
Tim Edwards 72ed78e55a Update for change in ocd git script 2020-02-24 15:04:59 -05:00
Tim Edwards 59bb8a89c0 "ocd_git_pure automatic update to repo" 2020-02-24 15:04:27 -05:00
Tim Edwards 08a442fda2 Removed VERSION from .gitignore, and updated VERSION. 2020-02-24 11:50:38 -05:00
Tim Edwards 9bdaee652e "ocd_git_pure automatic update to repo" 2020-02-18 03:00:14 -05:00
Tim Edwards 9879b58f83 Merge branch 'master' into netgen-1.5 2020-02-18 03:00:13 -05:00
Tim Edwards cc0cc512c0 Modified the Makefile per the patch from Charlene at OpenBSD to
add GR_LIBS to the list of options to CC, as this apparently
prevents problems with older binutils, and should not affect
builds otherwise.
2020-02-17 14:04:40 -05:00
Tim Edwards 9e3b705fcc "ocd_git_pure automatic update to repo" 2020-02-11 03:00:09 -05:00
Tim Edwards d2c9129242 Merge branch 'master' into netgen-1.5 2020-02-11 03:00:09 -05:00
Tim Edwards e9c0596dfe One additional change to allow a single value to the "format" command
to apply to both column widths.
2020-02-10 09:17:45 -05:00
Tim Edwards 9a1e295367 Based on code from John Wood, added command "netgen::format <col1_width>
<col2_width>" to set the output format width, to avoid the fixed column
widths of 41 characters which can truncate long strings in the output
such as deep cell hierarchies.  This command can be placed in the setup
script to widen the output columns to accomodate the result (to-do:
provide an "auto" mode to automatically determine the best width).
2020-02-10 09:11:34 -05:00
Tim Edwards 942f421fa3 "ocd_git_pure automatic update to repo" 2020-01-30 03:01:39 -05:00
20 changed files with 1603 additions and 427 deletions
+2
View File
@@ -12,3 +12,5 @@ scripts/config.status
*~
*.log
UPDATE_ME
tcltk/netgen.sh
tcltk/netgen.tcl
+1 -1
View File
@@ -9,7 +9,7 @@ MODULES = base
MAKEFLAGS =
INSTALL_CAD_DIRS = lib doc
include defs.mak
-include defs.mak
all: $(ALL_TARGET)
+1 -1
View File
@@ -1 +1 @@
1.5.135
1.5.173
+125 -53
View File
@@ -193,17 +193,19 @@ void flattenCell(char *name, int file)
if (Debug) Printf("Renaming %s to %s\n", tmp->name, tmpstr);
FreeString(tmp->name);
tmp->name = strsave(tmpstr);
#if OLDPREFIX
sprintf(tmpstr, "%s%s%s", ParentParams->instance.name, SEPARATOR,
tmp->instance.name);
#else
strcpy(tmpstr+prefixlength,tmp->instance.name);
#endif
FreeString(tmp->instance.name);
tmp->instance.name = strsave(tmpstr);
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
if (tmp->type == FIRSTPIN)
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
if ((tmp->type != NODE) && (tmp->instance.name != NULL)) {
#if OLDPREFIX
sprintf(tmpstr, "%s%s%s", ParentParams->instance.name, SEPARATOR,
tmp->instance.name);
#else
strcpy(tmpstr+prefixlength,tmp->instance.name);
#endif
FreeString(tmp->instance.name);
tmp->instance.name = strsave(tmpstr);
if (tmp->type == FIRSTPIN)
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
}
}
/* splice instance out of parent */
@@ -253,13 +255,13 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
{
struct objlist *ParentParams;
struct objlist *ParentProps;
struct objlist *NextObj;
struct objlist *NextObj, *LastObj, *prepp;
struct objlist *ChildObjList;
struct nlist *ThisCell;
struct nlist *ChildCell;
struct objlist *tmp, *ob2, *ob3;
int notdone, rnodenum;
char tmpstr[200];
char tmpstr[1024];
int nextnode, oldmax, numflat = 0;
#if !OLDPREFIX
int prefixlength;
@@ -296,21 +298,35 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
while (notdone) {
notdone = 0;
ParentParams = ThisCell->cell;
LastObj = NULL;
for (ParentParams = ThisCell->cell; ParentParams != NULL;
ParentParams = NextObj) {
ParentParams = NextObj) {
if (Debug) Printf("Parent = %s, type = %d\n",
ParentParams->name, ParentParams->type);
NextObj = ParentParams->next;
if (ParentParams->type != FIRSTPIN) continue;
if (!(*matchfunc)(ParentParams->model.class, instance)) continue;
if (ParentParams->type != FIRSTPIN) {
LastObj = ParentParams;
continue;
}
if (!(*matchfunc)(ParentParams->model.class, instance)) {
LastObj = ParentParams;
continue;
}
ChildCell = LookupCellFile(ParentParams->model.class, ThisCell->file);
if (Debug)
Printf(" Flattening instance: %s, primitive = %s\n",
ParentParams->instance.name, (ChildCell->class ==
CLASS_SUBCKT) ? "no" : "yes");
if (ChildCell->class != CLASS_SUBCKT) continue;
if (ChildCell == ThisCell) continue; // Avoid infinite loop
if ((ChildCell->class != CLASS_SUBCKT) && (ChildCell->class != CLASS_MODULE)) {
LastObj = ParentParams;
continue;
}
if (ChildCell == ThisCell) {
LastObj = ParentParams;
continue; // Avoid infinite loop
}
/* Does the parent cell have properties? If so, save a pointer to them */
for (ParentProps = ParentParams->next; ParentProps &&
@@ -373,10 +389,10 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
}
/* in pathological cases, the lengths of the port lists may
change. This is an error, but that is no reason to allow
the code to core dump. We avoid this by placing a
superfluous check on ob2->type
*/
* change. This is an error, but that is no reason to allow
* the code to core dump. We avoid this by placing a
* superfluous check on ob2->type
*/
if (ob2 != NULL)
ob2 = ob2->next;
@@ -456,17 +472,19 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
if (Debug) Printf("Renaming %s to %s\n", tmp->name, tmpstr);
FreeString(tmp->name);
tmp->name = strsave(tmpstr);
#if OLDPREFIX
sprintf(tmpstr, "%s%s%s", ParentParams->instance.name, SEPARATOR,
tmp->instance.name);
#else
strcpy(tmpstr+prefixlength,tmp->instance.name);
#endif
FreeString(tmp->instance.name);
tmp->instance.name = strsave(tmpstr);
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
if (tmp->type == FIRSTPIN)
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
if ((tmp->type != NODE) && (tmp->instance.name != NULL)) {
#if OLDPREFIX
sprintf(tmpstr, "%s%s%s", ParentParams->instance.name, SEPARATOR,
tmp->instance.name);
#else
strcpy(tmpstr+prefixlength,tmp->instance.name);
#endif
FreeString(tmp->instance.name);
tmp->instance.name = strsave(tmpstr);
if (tmp->type == FIRSTPIN)
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
}
}
/* Do property inheritance */
@@ -497,10 +515,21 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
for (ob2 = ChildObjList; ob2 && ob2->next != NULL; ob2 = ob2->next) ;
}
else {
/* find ParentParams in ThisCell list */
for (ob2 = ThisCell->cell; ob2 && ob2->next != ParentParams; ob2=ob2->next);
/* find ParentParams in ThisCell list. In most cases, LastObj */
/* should be pointing to it. */
if (LastObj && (LastObj->next == ParentParams)) {
ob2 = LastObj;
}
else {
for (ob2 = LastObj; ob2 && ob2->next != ParentParams; ob2=ob2->next);
if (ob2 == NULL) {
/* It should not happen that LastObj is ahead of ParentParams */
/* but just in case, this long loop will find it. */
for (ob2 = ThisCell->cell; ob2 && ob2->next != ParentParams; ob2=ob2->next);
}
}
if (ob2)
for (ob2->next = ChildObjList; ob2->next != NULL; ob2 = ob2->next) ;
for (ob2->next = ChildObjList; ob2->next != NULL; ob2 = ob2->next) ;
}
/* now, ob2 is last element in child list, so skip and reclaim parent */
@@ -1136,9 +1165,10 @@ int UniquePins(char *name, int filenum)
struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
{
struct nlist *ptr;
struct objlist *ob, *obt, *lob, *nob, *firstpin;
struct objlist *ob, *obt, *lob, *nob, *firstpin, *pob;
struct nlist *tc = (struct nlist *)clientdata;
int pinnum;
char *saveinst = NULL;
ptr = (struct nlist *)(p->ptr);
if (tc->file != ptr->file) return NULL;
@@ -1166,7 +1196,7 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
while (ob && obt && (ob->type > FIRSTPIN || ob == firstpin) &&
ob->model.class != NULL) {
nob = ob->next;
if ((obt->type == PORT) && (obt->node == -1)) {
if ((obt->type == PORT) && (obt->node == -2)) {
/* Remove this pin */
@@ -1186,13 +1216,44 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
}
FREE(ob->name);
if (ob->instance.name != NULL) FREE(ob->instance.name);
if (ob->instance.name != NULL) {
/* Keep a copy of the instance name (see below) */
if (saveinst != NULL) FREE(saveinst);
saveinst = ob->instance.name;
}
if (ob->model.class != NULL) FREE(ob->model.class);
FREE(ob);
}
else {
lob = ob;
ob->type = pinnum++; // Renumber pins in order
if ((ob->type == PROPERTY) && (pinnum == 1))
{
/* If this happens, then all the pins got removed,
* and there is probably something very much wrong
* with the setup. However, to keep netgen from
* blowing up, add back a "proxy(no pins)" record
* in front; otherwise we'd have an orphaned
* property record.
*/
pob = GetObject();
pob->name = (char *)MALLOC(15);
sprintf(pob->name, "proxy(no pins)");
pob->model.class = strsave(ob->model.class);
if (saveinst != NULL)
pob->instance.name = strsave(saveinst);
else
/* This should never happen */
pob->instance.name = strsave("error");
pob->type = pinnum++;
pob->node = -1;
pob->next = ob;
lob->next = pob;
lob = ob;
}
else
{
lob = ob;
ob->type = pinnum++; // Renumber pins in order
}
}
ob = nob;
obt = obt->next;
@@ -1203,6 +1264,8 @@ struct nlist *cleanuppins(struct hashlist *p, void *clientdata)
HashPtrInstall(firstpin->instance.name, firstpin, &(ptr->instdict));
}
}
if (saveinst != NULL) FREE(saveinst);
return NULL; /* Keep the search going */
}
@@ -1238,7 +1301,7 @@ int CleanupPins(char *name, int filenum)
for (ob = ThisCell->cell; ob != NULL; ob = ob->next) {
if (ob->type != PORT) break;
if (ob->node == -1) {
if (ob->node == -2) {
needscleanup = 1;
break;
}
@@ -1265,7 +1328,7 @@ int CleanupPins(char *name, int filenum)
}
else if (ob->type != PORT) break;
nob = ob->next;
if (ob->node == -1) {
if (ob->node == -2) {
if (lob == NULL) {
ThisCell->cell = ob->next;
}
@@ -1539,7 +1602,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
/* (it without regard to cell1) improves the matching. */
else if ((ecomp->num1 != ecomp->num2) && (ecomp->cell2 != NULL) &&
(ecomp->cell2->class == CLASS_SUBCKT)) {
(ecomp->num2 != 0) && (ecomp->cell2->class == CLASS_SUBCKT)) {
ecomp->add2 = -ecomp->num2;
match = 1;
for (ob2 = ecomp->cell2->cell; ob2; ob2 = ob2->next) {
@@ -1597,7 +1660,7 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
/* (it without regard to cell1) improves the matching. */
else if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
(ecomp->cell1->class == CLASS_SUBCKT)) {
(ecomp->num1 != 0) && (ecomp->cell1->class == CLASS_SUBCKT)) {
ecomp->add1 = -ecomp->num1;
match = 1;
for (ob2 = ecomp->cell1->cell; ob2; ob2 = ob2->next) {
@@ -1660,7 +1723,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
while (ecomp != NULL) {
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell1 != NULL) &&
((ecomp->cell1->class == CLASS_RES) ||
(ecomp->cell1->class == CLASS_VSOURCE))) {
(ecomp->cell1->class == CLASS_VSOURCE) ||
(ecomp->cell1->class == CLASS_ISOURCE))) {
int node1 = -1, node2 = -1;
lob = NULL;
for (ob1 = tc1->cell; ob1; ) {
@@ -1709,11 +1773,16 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
tsub1->name,
tc1->name);
/* merge node of endpoints */
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
if (ob2->node == node2)
ob2->node = node1;
}
/* A current source is an open, while a */
/* resistor or voltage source is a short. */
if (ecomp->cell1->class != CLASS_ISOURCE) {
/* merge node of endpoints */
for (ob2 = tc1->cell; ob2; ob2 = ob2->next) {
if (ob2->node == node2)
ob2->node = node1;
}
}
/* snip, snip. Excise this device */
if (lob == NULL) {
@@ -1765,7 +1834,8 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
if ((ecomp->num1 != ecomp->num2) && (ecomp->cell2 != NULL) &&
((ecomp->cell2->class == CLASS_RES) ||
(ecomp->cell2->class == CLASS_VSOURCE))) {
(ecomp->cell2->class == CLASS_VSOURCE) ||
(ecomp->cell2->class == CLASS_ISOURCE))) {
int node1 = -1, node2 = -1;
lob = NULL;
for (ob2 = tc2->cell; ob2; ) {
@@ -1815,9 +1885,11 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
tc2->name);
/* merge node of endpoints */
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
if (ob1->node == node2)
ob1->node = node1;
if (ecomp->cell2->class != CLASS_ISOURCE) {
for (ob1 = tc2->cell; ob1; ob1 = ob1->next) {
if (ob1->node == node2)
ob1->node = node1;
}
}
/* snip, snip. Excise this device */
+718 -198
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -8,6 +8,9 @@ extern struct nlist *Circuit2;
extern int ExhaustiveSubdivision;
extern int left_col_end;
extern int right_col_end;
#ifdef TCL_NETGEN
#include <tcl.h>
extern int InterruptPending;
+47 -9
View File
@@ -289,6 +289,7 @@ int GetNextLineNoNewline(char *delimiter)
char *newbuf;
int testc;
int nested = 0;
int llen;
if (feof(infile)) return -1;
@@ -301,20 +302,33 @@ int GetNextLineNoNewline(char *delimiter)
if (linesize == 0) {
/* Allocate memory for line */
linesize = 500;
line = (char *)MALLOC(linesize);
linetok = (char *)MALLOC(linesize);
linesize = 2000;
line = (char *)MALLOC(linesize + 1);
linetok = (char *)MALLOC(linesize + 1);
}
fgets(line, linesize, infile);
while (strlen(line) == linesize - 1) {
newbuf = (char *)MALLOC(linesize + 500);
/* Immediately resolve backslash-EOL */
llen = strlen(line);
while ((llen > 1) && (llen < linesize - 1) && *(line + llen - 2) == '\\') {
*(line + llen - 2) = '\n';
fgets(line + llen - 1, linesize - llen + 1, infile);
llen = strlen(line);
}
while (llen == linesize - 1) {
newbuf = (char *)MALLOC(linesize + 501);
strcpy(newbuf, line);
FREE(line);
line = newbuf;
fgets(line + linesize - 1, 501, infile);
llen = strlen(line);
while ((llen > 1) && (llen < linesize - 1) && *(line + llen - 2) == '\\') {
*(line + llen - 2) = '\n';
fgets(line + llen - 1, linesize - llen + 1, infile);
llen = strlen(line);
}
linesize += 500;
FREE(linetok);
linetok = (char *)MALLOC(linesize);
linetok = (char *)MALLOC(linesize + 1);
}
/* Check for substitutions (verilog only). Make sure linetok is */
@@ -329,7 +343,7 @@ int GetNextLineNoNewline(char *delimiter)
for (s = line; *s != '\0'; s++) {
if (*s == '`') {
w = s + 1;
while (isalnum(*w)) w++;
while (isalnum(*w) || (*w == '_') || (*w == '$')) w++;
e = *w;
*w = '\0';
kl = (struct property *)HashLookup(s + 1, definitions);
@@ -365,7 +379,7 @@ int GetNextLineNoNewline(char *delimiter)
for (s = line; *s != '\0'; s++) {
if (*s == '`') {
w = s + 1;
while (isalnum(*w)) w++;
while (isalnum(*w) || (*w == '_') || (*w == '$')) w++;
e = *w;
*w = '\0';
kl = (struct property *)HashLookup(s + 1, definitions);
@@ -496,6 +510,24 @@ void GetNextLine(char *delimiter)
} while (nexttok == NULL);
}
/*----------------------------------------------------------------------*/
/* Return a pointer to the line at the position of nexttok */
/* This is used only when returning the entire line, untokenized, and */
/* is only called by the verilog read routine when reading the value of */
/* a `define statement. */
/*----------------------------------------------------------------------*/
char *GetLineAtTok()
{
char *lpos;
if (nexttok == NULL) return NULL;
if (line == NULL) return NULL;
lpos = strstr(line, nexttok);
return lpos;
}
/*----------------------------------------------------------------------*/
/* if nexttok is already NULL, force scanner to read new line */
/*----------------------------------------------------------------------*/
@@ -673,6 +705,7 @@ char *strdtok(char *pstring, char *delim1, char *delim2)
/* accordingly (needs to be done). */
if (*s == '\\') {
s++;
while (*s != '\0') {
if ((*s == ' ') || (*s == '\\')) {
s++;
@@ -765,7 +798,7 @@ int OpenParseFile(char *name, int fnum)
FILE *locfile;
struct filestack *newfile;
locfile = fopen(name,"r");
locfile = fopen(name, "r");
linenum = 0;
/* reset the token scanner */
nexttok = NULL;
@@ -850,7 +883,12 @@ char *ReadNetlist(char *fname, int *fnum)
{SPICE_EXTENSION, ReadSpice},
{SPICE_EXT2, ReadSpice},
{SPICE_EXT3, ReadSpice},
{SPICE_EXT4, ReadSpice},
{SPICE_EXT5, ReadSpice},
{SPICE_EXT6, ReadSpice},
{SPICE_EXT7, ReadSpice},
{VERILOG_EXTENSION, ReadVerilog},
{SYS_VERILOG_EXTENSION, ReadVerilog},
{NETGEN_EXTENSION, ReadNetgenFile},
{NULL, NULL}
};
+7 -1
View File
@@ -9,11 +9,16 @@
#define SIM_EXTENSION ".sim"
#define SPICE_EXTENSION ".spice"
#define SPICE_EXT2 ".spc"
#define SPICE_EXT3 ".fspc"
#define SPICE_EXT3 ".sp"
#define SPICE_EXT4 ".spi"
#define SPICE_EXT5 ".fspc"
#define SPICE_EXT6 ".cir"
#define SPICE_EXT7 ".ckt"
#define NETGEN_EXTENSION ".ntg"
#define CCODE_EXTENSION ".c.code"
#define ESACAP_EXTENSION ".esa"
#define VERILOG_EXTENSION ".v"
#define SYS_VERILOG_EXTENSION ".sv"
#define LINELENGTH 80
@@ -31,6 +36,7 @@ extern struct hashdict *definitions;
extern char *nexttok;
#define SKIPTO(a) do {SkipTok(NULL);} while (!match(nexttok,a))
extern char *strdtok(char *pstring, char *delim1, char *delim2);
extern char *GetLineAtTok();
extern void SkipTok(char *delimiter);
extern void SkipTokNoNewline(char *delimiter);
extern void SkipTokComments(char *delimiter);
+52 -9
View File
@@ -50,6 +50,7 @@ int NextNode;
int Composition = NONE;
int QuickSearch = 0;
int GlobalParallelNone = FALSE;
int GlobalParallelOpen = TRUE;
int AddToExistingDefinition = 0; /* default: overwrite cell when reopened */
@@ -1337,7 +1338,7 @@ void Node(char *name)
tp->name = strsave(name);
tp->type = NODE; /* internal node type */
tp->model.class = NULL;
tp->instance.name = NULL;
tp->instance.flags = 0;
tp->node = -1; /* null node */
tp->next = NULL;
AddToCurrentCell (tp);
@@ -2470,7 +2471,8 @@ void CopyProperties(struct objlist *obj_to, struct objlist *obj_from)
kvcur->value.ival = 0;
obj_to->instance.props = kvcopy;
obj_to->model.class = strsave(obj_from->model.class);
if (obj_from->model.class)
obj_to->model.class = strsave(obj_from->model.class);
}
}
@@ -3131,6 +3133,9 @@ int remove_group_tags(struct objlist *ob)
/* If the device has permutable pins, then duplicate hashes are made */
/* for each permutation. */
/* */
/* If the device has isolated (unconnected) pins, then treat them as */
/* all belonging to the same net for the purpose of parallel merging. */
/* */
/* Return the number of devices merged. */
/*----------------------------------------------------------------------*/
@@ -3145,6 +3150,7 @@ int CombineParallel(char *model, int file)
size_t pcnt;
int i, dcnt = 0, hastag;
char *pstr, *p2str, *pptr;
int *nodecount;
struct valuelist *kv;
if ((tp = LookupCellFile(model, file)) == NULL) {
@@ -3154,6 +3160,20 @@ int CombineParallel(char *model, int file)
InitializeHashTable(&devdict, OBJHASHSIZE);
/* Make one pass to count the number of times each node number is */
/* used. This list indicates which pins are no-connects, so they */
/* can be treated as equivalent for the purpose of parallelization. */
nodecount = (int *)CALLOC((tp->nodename_cache_maxnodenum + 1), sizeof(int));
if (GlobalParallelOpen) {
for (ob = tp->cell; ob; ob = ob->next) {
if (ob->node >= 0)
if (ob->type != NODE)
nodecount[ob->node]++;
}
}
lob = NULL;
for (ob = tp->cell; ob; ) {
if (ob->type == FIRSTPIN) {
@@ -3200,7 +3220,14 @@ int CombineParallel(char *model, int file)
pptr += pstr - (char *)2;
for (ob2 = ob; ob2 && (ob2->type > FIRSTPIN || ob2 == ob); ob2 = ob2->next) {
sprintf(pptr, "_%d", ob2->node);
if ((ob2->node >= 0) && (nodecount[ob2->node] == 1))
{
nob = (tp->nodename_cache)[ob2->node];
nob->instance.flags = NO_CONNECT;
strcat(pptr, "_nc");
}
else
sprintf(pptr, "_%d", ob2->node);
pptr += strlen(pptr);
}
@@ -3236,11 +3263,26 @@ int CombineParallel(char *model, int file)
for (ob2 = ob; ob2 && (ob2->type > FIRSTPIN || ob2 == ob);
ob2 = ob2->next) {
if (ob2 == pob1)
sprintf(pptr, "_%d", pob2->node);
{
if ((pob2->node >= 0) && (nodecount[pob2->node] == 1))
strcat(pptr, "_nc");
else
sprintf(pptr, "_%d", pob2->node);
}
else if (ob2 == pob2)
sprintf(pptr, "_%d", pob1->node);
{
if ((pob1->node >= 0) && (nodecount[pob1->node] == 1))
strcat(pptr, "_nc");
else
sprintf(pptr, "_%d", pob1->node);
}
else
sprintf(pptr, "_%d", ob2->node);
{
if ((ob2->node >= 0) && (nodecount[ob2->node] == 1))
strcat(pptr, "_nc");
else
sprintf(pptr, "_%d", ob2->node);
}
pptr += strlen(pptr);
}
HashPtrInstall(p2str, ob, &devdict);
@@ -3256,7 +3298,7 @@ int CombineParallel(char *model, int file)
else {
/* Find parallel device "ob" and append properties of */
/* "sob" to it. If "ob" does not have properties, then */
/* create a property record and set property "M" to 2. */
/* create a property record and set property "M" to 1. */
/* Find last non-property record of sob ( = pob) */
/* Find first property record of sob ( = spropfirst) */
@@ -3364,6 +3406,7 @@ int CombineParallel(char *model, int file)
if (dcnt > 0) {
Fprintf(stdout, "Class %s: Merged %d devices.\n", model, dcnt);
}
FREE(nodecount);
return dcnt;
}
@@ -3583,8 +3626,8 @@ int CombineSeries(char *model, int file)
/* Excise the 2nd instance. instlist[i][1] remains as the */
/* only pointer to it. */
for (obp = instlist[i][0]; obp->next->type > FIRSTPIN ||
obp->next->type == PROPERTY; obp = obp->next);
for (obp = instlist[i][0]; obp->next && (obp->next->type > FIRSTPIN ||
obp->next->type == PROPERTY); obp = obp->next);
for (ob2 = obp; ob2 && ob2->next != instlist[i][1]; ob2 = ob2->next);
/* Device may have been moved by the above code. If so, look for */
+10
View File
@@ -65,6 +65,15 @@ extern void AssignCircuits(char *name1, int file1, char *name2, int file2);
/* flatten.c */
extern int PrematchLists(char *, int, char *, int);
/* verilog.c */
struct cellstack {
char *cellname;
struct cellstack *next;
};
void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr,
int blackbox);
/* Define (enumerate) various device classes, largely based on SPICE */
/* model types, mixed with some ext/sim types. */
@@ -140,6 +149,7 @@ extern int NoOutput; /* set this to 1 to disable stdout output */
extern int Composition; /* direction of composition */
extern int UnixWildcards; /* TRUE if *,?,{},[] only; false if full REGEXP */
extern int GlobalParallelNone; /* If TRUE, don't parallel combine any cells */
extern int GlobalParallelOpen; /* If TRUE, parallel combine cells w/no-connects */
/* magic internal flag to restrict searches to recently placed cells */
extern int QuickSearch;
/* does re"CellDef"ing a cell add to it or overwrite it??? */
+13 -6
View File
@@ -289,7 +289,7 @@ static struct hashdict cell_dict;
void InitCellHashTable(void)
{
hashfunc = hash;
matchfunc = match;
matchfunc = NULL;
matchintfunc = matchfile;
InitializeHashTable(&cell_dict, CELLHASHSIZE);
}
@@ -975,7 +975,10 @@ struct objlist *CopyObjList(struct objlist *oldlist, unsigned char doforall)
newob->model.class = NULL;
else
newob->model.class = strsave(tmp->model.class);
newob->instance.name = (tmp->instance.name) ?
if (newob->type == NODE)
newob->instance.flags = tmp->instance.flags;
else
newob->instance.name = (tmp->instance.name) ?
strsave(tmp->instance.name) : NULL;
}
newob->node = tmp->node;
@@ -1095,8 +1098,8 @@ void FreeObject(struct objlist *ob)
FREE(ob->instance.props);
}
}
else {
/* All other records */
else if (ob->type != NODE) {
/* All other records except NODE, which uses this for flags */
if (ob->instance.name != NULL) FreeString(ob->instance.name);
}
if (ob->model.class != NULL) FreeString(ob->model.class);
@@ -1112,13 +1115,17 @@ void FreeObjectAndHash(struct objlist *ob, struct nlist *ptr)
/*************** GENERAL UTILITIES ****************************/
int NumberOfPorts(char *cellname)
int NumberOfPorts(char *cellname, int file)
{
struct nlist *tp;
struct objlist *ob;
int ports;
tp = LookupCell(cellname);
if (file == -1)
tp = LookupCell(cellname);
else
tp = LookupCellFile(cellname, file);
if (tp == NULL) return(0);
ports = 0;
for (ob = tp->cell; ob != NULL; ob = ob->next)
+5 -3
View File
@@ -28,6 +28,8 @@
#define PROXY (0) /* Used in model.port record of ports */
#define NO_CONNECT 1 /* Use in object list to flag an isolated net */
/* Lists of device properties. Order is defined at the time of */
/* the cell definition; values are sorted at the time instances */
/* are read. */
@@ -160,6 +162,7 @@ struct objlist {
union {
char *name; /* unique name for the instance, or */
/* (string) value of property for properties */
int flags; /* Used by NODE type to flag isolated net */
struct valuelist *props; /* Property record */
} instance;
int node; /* the electrical node number of the port/node/pin */
@@ -192,9 +195,8 @@ struct Permutation {
struct Permutation *next;
};
#define OBJHASHSIZE 997 /* the size of the object and instance hash lists */
#define OBJHASHSIZE 42073 /* the size of the object and instance hash lists */
/* prime numbers are good choices as hash sizes */
/* 101 is a good number for IBMPC */
/* cell definition for hash table */
/* NOTE: "file" must come first for the hash matching by name and file */
@@ -242,7 +244,7 @@ extern void FreeObjectAndHash(struct objlist *ob, struct nlist *ptr);
extern void FreePorts(char *cellname);
extern struct IgnoreList *ClassIgnore;
extern int NumberOfPorts(char *cellname);
extern int NumberOfPorts(char *cellname, int file);
extern struct objlist *InstanceNumber(struct nlist *tp, int inst);
extern struct objlist *List(char *list_template);
+1 -1
View File
@@ -929,7 +929,7 @@ void ToggleDebug(void)
void DescribeCell(char *name, int detail)
{
Printf("Cell: %s contains %d instances, %d nodes and %d ports\n", name,
NumberOfInstances(name), RenumberNodes(name), NumberOfPorts(name));
NumberOfInstances(name), RenumberNodes(name), NumberOfPorts(name, -1));
PrintEmbeddingTree(stdout,name,detail);
}
+13 -6
View File
@@ -801,9 +801,16 @@ void DescribeInstance(char *name, int file)
{
if (ob->node > nodemax) nodemax = ob->node;
else if ((ob->node == -1) && (ob->model.port != PROXY)) {
if (disconnectednodes == 0) Fprintf(stderr, "\n");
disconnectednodes++;
Fprintf(stderr, "Cell %s disconnected node: %s\n", tp->name, ob->name);
/* All black-box modules and placeholders by definition have all */
/* disconnected pins, so don't report those. */
if (!(tp->flags & CELL_PLACEHOLDER) && (tp->class != CLASS_MODULE))
{
if (disconnectednodes == 0) Fprintf(stderr, "\n");
disconnectednodes++;
Fprintf(stderr, "Cell %s disconnected node: %s\n", tp->name, ob->name);
}
}
}
instlist = (unsigned char *) CALLOC((nodemax + 1), sizeof(unsigned char));
@@ -900,7 +907,7 @@ void PrintLeavesInCell(char *cellname, int filenum)
np->dumped = 1;
if (np->class != CLASS_SUBCKT) {
Printf("%s; %d ports; Primitive.\n", cellname, NumberOfPorts(cellname));
Printf("%s; %d ports; Primitive.\n", cellname, NumberOfPorts(cellname, filenum));
return;
}
@@ -913,7 +920,7 @@ void PrintLeavesInCell(char *cellname, int filenum)
am_a_leaf = 0;
}
if (am_a_leaf) Printf("%s; %d ports\n", cellname, NumberOfPorts(cellname));
if (am_a_leaf) Printf("%s; %d ports\n", cellname, NumberOfPorts(cellname, filenum));
return;
}
@@ -1063,7 +1070,7 @@ void Query(void)
ActelLib();
break;
case 'S':
promptstring("Read SPICE (.ckt) file? ", repstr);
promptstring("Read SPICE (.spice) file? ", repstr);
ReadSpice(repstr, &filenum);
break;
case 'V':
+46 -24
View File
@@ -473,15 +473,6 @@ void CleanupSubcell() {
SetClass(CLASS_MODULE);
}
/*------------------------------------------------------*/
/* Structure for stacking nested subcircuit definitions */
/*------------------------------------------------------*/
struct cellstack {
char *cellname;
struct cellstack *next;
};
/*------------------------------------------------------*/
/* Push a subcircuit name onto the stack */
/*------------------------------------------------------*/
@@ -874,6 +865,17 @@ skip_ends:
}
}
/* Ignore anything in a .CONTROL ... .ENDC block */
else if (matchnocase(nexttok, ".CONTROL")) {
while (1) {
SpiceSkipNewLine();
SkipTok(NULL);
if (EndParseFile()) break;
if (matchnocase(nexttok, ".ENDC"))
break;
}
}
// Blackbox (library) mode---parse only subcircuits and models;
// ignore all components.
@@ -1184,7 +1186,7 @@ skip_ends:
else if (CountPorts(model, filenum) != 2) {
/* Modeled device: Make sure it has the right number of ports */
Fprintf(stderr, "Device \"%s\" has wrong number of ports for a "
"resistor.\n");
"resistor.\n", model);
goto baddevice;
}
usemodel = 1;
@@ -1883,20 +1885,36 @@ char *ReadSpiceTop(char *fname, int *fnum, int blackbox)
CurrentCell = NULL;
if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
char name[100];
SetExtension(name, fname, SPICE_EXTENSION);
if ((filenum = OpenParseFile(name, *fnum)) < 0) {
Fprintf(stderr,"Error in SPICE file read: No file %s\n",name);
if (strrchr(fname, '.') == NULL) {
char name[1024];
SetExtension(name, fname, SPICE_EXTENSION);
if ((filenum = OpenParseFile(name, *fnum)) < 0) {
Fprintf(stderr, "Error in SPICE file read: No file %s\n", name);
*fnum = filenum;
return NULL;
}
}
else {
Fprintf(stderr, "Error in SPICE file read: No file %s\n", fname);
*fnum = filenum;
return NULL;
}
}
}
/* Make sure all SPICE file reading is case insensitive */
matchfunc = matchnocase;
matchintfunc = matchfilenocase;
hashfunc = hashnocase;
/* Make sure all SPICE file reading is case insensitive */
/* BUT if a verilog file was read before it, then it will */
/* be forced to be case sensitive, caveat end-user. */
if (matchfunc == match) {
Printf("Warning: A case-sensitive file has been read and so the "
"SPICE netlist must be treated case-sensitive to match.\n");
}
else {
matchfunc = matchnocase;
matchintfunc = matchfilenocase;
hashfunc = hashnocase;
}
InitializeHashTable(&spiceparams, OBJHASHSIZE);
@@ -1980,14 +1998,18 @@ void IncludeSpice(char *fname, int parent, struct cellstack **CellStackPtr,
/* helps, if the file didn't have an extension. But */
/* really, we're getting desperate at this point. */
if (strchr(fname, '.') == NULL) {
if (strrchr(fname, '.') == NULL) {
SetExtension(name, fname, SPICE_EXTENSION);
filenum = OpenParseFile(name, parent);
}
if (filenum < 0) {
Fprintf(stderr,"Error in SPICE file include: No file %s\n",name);
return;
if (filenum < 0) {
Fprintf(stderr, "Error in SPICE file include: No file %s\n", name);
return;
}
}
else {
Fprintf(stderr, "Error in SPICE file include: No file %s\n", fname);
return;
}
}
}
ReadSpiceFile(fname, parent, CellStackPtr, blackbox);
+280 -82
View File
@@ -98,6 +98,31 @@ struct bus *NewBus()
return (wb);
}
//-------------------------------------------------------------------------
// Find a character c in a string, assuming that string may contain
// verilog names, where anything, including char c, may appear in the
// string if it is a backslash-escaped name. Only the position of
// character c outside of a verilog name is reported.
//-------------------------------------------------------------------------
char *strvchr(char *string, char c)
{
char *s;
for (s = string; *s != '\0'; s++) {
if (*s == '\\') {
while (*s != '\0' && *s != ' ') s++;
if (*s == '\0') {
Fprintf(stderr, "Error: Verilog backslash-escaped name"
" does not end with a space.\n");
break;
}
}
if (*s == c) return s;
}
return NULL;
}
//-------------------------------------------------------------------------
// Get bus indexes from the notation name[a:b]. If there is only "name"
// then look up the name in the bus hash list and return the index bounds.
@@ -283,7 +308,7 @@ int GetBusTok(struct bus *wb)
int GetBus(char *astr, struct bus *wb)
{
char *colonptr, *brackstart, *brackend, *sigend, sdelim;
char *colonptr, *brackstart, *brackend, *sigend, sdelim, *aastr;
int result, start, end;
if (wb == NULL) return 0;
@@ -302,8 +327,8 @@ int GetBus(char *astr, struct bus *wb)
astr++;
wb->end = 0;
while((*astr != '\0') && (*astr != '}')) {
sigend = strchr(astr, ',');
if (sigend == NULL) sigend = strchr(astr, '}');
sigend = strvchr(astr, ',');
if (sigend == NULL) sigend = strvchr(astr, '}');
if (sigend == NULL) {
Printf("Badly formed wire bundle \"%s\"\n", astr - 1);
return 1;
@@ -325,15 +350,22 @@ int GetBus(char *astr, struct bus *wb)
return 0;
}
brackstart = strchr(astr, '[');
// Delimiters may appear in backslash-escaped names. . . ignore these.
aastr = astr;
if (*aastr == '\\') {
aastr++;
while (*aastr != ' ' && *aastr != '\\' && *aastr != '\0') aastr++;
}
brackstart = strvchr(aastr, '[');
if (brackstart != NULL) {
brackend = strchr(astr, ']');
brackend = strvchr(aastr, ']');
if (brackend == NULL) {
Printf("Badly formed array notation \"%s\"\n", astr);
return 1;
}
*brackend = '\0';
colonptr = strchr(astr, ':');
colonptr = strvchr(aastr, ':');
if (colonptr) *colonptr = '\0';
result = sscanf(brackstart + 1, "%d", &start);
if (colonptr) *colonptr = ':';
@@ -521,9 +553,43 @@ void CleanupModule() {
int maxnode = 0;
int has_submodules = FALSE;
struct objlist *sobj, *nobj, *lobj, *pobj;
struct objlist *myLastPort, *object_it, *myNextObject;
if (CurrentCell == NULL) return;
myLastPort = NULL;
/* Reorder objects so that all ports come first, before nodes, because
* parts of the code depend on it.
*/
for (object_it = CurrentCell->cell; object_it && object_it->type <= 0;
object_it = myNextObject ) {
myNextObject = object_it->next;
if (!myNextObject) // end of list
continue;
if (myLastPort == NULL) {
if (object_it->type == PORT) {
myLastPort = object_it; // port at begining of list
myNextObject = object_it; // otherwise skips one
}
else if (myNextObject->type == PORT) {
object_it->next = myNextObject->next;
myNextObject->next = CurrentCell->cell;
CurrentCell->cell = myNextObject;
myLastPort = myNextObject;
}
}
else if (myNextObject->type == PORT) {
object_it->next = myNextObject->next;
myNextObject->next = myLastPort->next;
myLastPort->next = myNextObject;
myLastPort = myNextObject;
}
}
for (sobj = CurrentCell->cell; sobj; sobj = sobj->next)
if (sobj->node > maxnode)
maxnode = sobj->node + 1;
@@ -566,11 +632,6 @@ void CleanupModule() {
/* Structure for stacking nested module definitions */
/*------------------------------------------------------*/
struct cellstack {
char *cellname;
struct cellstack *next;
};
/* Forward declarations */
extern void IncludeVerilog(char *, int, struct cellstack **, int);
@@ -912,7 +973,7 @@ skip_endmodule:
}
else if (match(nexttok, "input") || match(nexttok, "output")
|| match(nexttok, "inout")) {
struct bus wb;
struct bus wb, *nb;
// Parsing of ports as statements not in the module pin list.
wb.start = wb.end = -1;
@@ -945,6 +1006,11 @@ skip_endmodule:
Port(portname);
}
}
/* Also register this port as a bus */
nb = NewBus();
nb->start = wb.start;
nb->end = wb.end;
HashPtrInstall(nexttok, nb, &buses);
wb.start = wb.end = -1;
}
else {
@@ -1058,6 +1124,13 @@ skip_endmodule:
kl->pdefault.ival = 1;
kl->slop.ival = 0;
}
else if (nexttok[0] == '(') {
/* For now, the netgen verilog parser doesn't handle `define f(X) ... */
SkipNewLine(VLOG_DELIMITERS);
FREE(kl->key);
FREE(kl);
kl = NULL;
}
else if (ConvertStringToInteger(nexttok, &ival) == 1) {
/* Parameter parses as an integer */
kl->type = PROP_INTEGER;
@@ -1071,12 +1144,19 @@ skip_endmodule:
kl->slop.dval = 0.01; // One percent default
}
else {
/* Treat the parameter as a string */
char *toks;
/* Treat the parameter as a string; BUT pull everything to */
/* EOL, not just the current token. */
toks = GetLineAtTok();
kl->type = PROP_STRING;
kl->pdefault.string = strsave(nexttok);
kl->pdefault.string = strsave(toks);
kl->slop.dval = 0.0;
SkipNewLine(VLOG_DELIMITERS);
}
HashPtrInstall(kl->key, kl, &verilogdefs);
if (kl) HashPtrInstall(kl->key, kl, &verilogdefs);
}
else if (match(nexttok, "`undef")) {
struct property *kl = NULL;
@@ -1165,7 +1245,7 @@ skip_endmodule:
else { /* "assign" */
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
if (GetBus(nexttok, &wb) == 0) {
char *aptr = strchr(nexttok, '[');
char *aptr = strvchr(nexttok, '[');
if (aptr != NULL) {
*aptr = '\0';
/* Find object of first net in bus */
@@ -1174,9 +1254,16 @@ skip_endmodule:
lhs = LookupObject(nodename, CurrentCell);
*aptr = '[';
}
else {
strcpy(noderoot, nexttok);
/* Set LHS to the start of the vector */
sprintf(nodename, "%s[%d]", nexttok, wb.start);
lhs = LookupObject(nodename, CurrentCell);
}
}
else {
lhs = LookupObject(nexttok, CurrentCell);
strcpy(noderoot, nexttok);
}
SkipTokComments(VLOG_DELIMITERS);
if (lhs && ((!nexttok) || (!match(nexttok, "=")))) {
@@ -1219,7 +1306,7 @@ skip_endmodule:
}
else {
if (GetBus(nexttok, &wb2) == 0) {
char *aptr = strchr(nexttok, '[');
char *aptr = strvchr(nexttok, '[');
j = wb2.start;
if (aptr != NULL) {
*aptr = '\0';
@@ -1237,13 +1324,21 @@ skip_endmodule:
if (rhs != NULL) {
Printf("Improper assignment; left-hand side cannot "
"be parsed.\n");
Printf("Right-hand side is \"%s\".\n", rhs->name);
if (j != -1)
Printf("Right-hand side is \"%s\".\n", assignroot);
else
Printf("Right-hand side is \"%s\".\n", rhs->name);
Printf("Improper expression is \"%s\".\n", nexttok);
break;
}
if (lhs != NULL) {
Printf("Improper assignment; right-hand side cannot "
"be parsed.\n");
Printf("Left-hand side is \"%s\".\n", lhs->name);
if (i != -1)
Printf("Left-hand side is \"%s\".\n", noderoot);
else
Printf("Left-hand side is \"%s\".\n", lhs->name);
Printf("Improper expression is \"%s\".\n", nexttok);
/* Not parsable, probably behavioral verilog? */
Printf("Module '%s' is not structural verilog, "
"making black-box.\n", model);
@@ -1308,6 +1403,7 @@ skip_endmodule:
struct portelement {
char *name; // Name of port in subcell
char *net; // Name of net connecting to port in the parent
int width; // Width of port, if port is a bus
struct portelement *next;
};
@@ -1315,6 +1411,22 @@ skip_endmodule:
struct objlist *obptr;
strncpy(modulename, nexttok, 99);
/* If module name is a verilog primitive, then treat the module as a */
/* black box (this is not a complete list. Preferable to use hash */
/* function instead of lots of strcmp() calls). */
if (!strcmp(modulename, "buf") || !strcmp(modulename, "notif1") ||
!strcmp(modulename, "not") || !strcmp(modulename, "and") ||
!strcmp(modulename, "or") || !strcmp(modulename, "bufif0") ||
!strcmp(modulename, "bufif1") || !strcmp(modulename, "notif0")) {
Printf("Module contains verilog primitive '%s'.\n", nexttok);
Printf("Module '%s' is not structural verilog, making black-box.\n", model);
SetClass(CLASS_MODULE);
goto skip_endmodule;
}
if (!(*CellStackPtr)) {
CellDef(fname, filenum);
PushStack(fname, CellStackPtr);
@@ -1417,6 +1529,7 @@ nextinst:
else {
new_port = (struct portelement *)CALLOC(1, sizeof(struct portelement));
new_port->name = strsave(nexttok + 1);
new_port->width = -1;
SkipTokComments(VLOG_DELIMITERS);
if (!match(nexttok, "(")) {
Printf("Badly formed subcircuit pin line at \"%s\"\n", nexttok);
@@ -1438,25 +1551,25 @@ nextinst:
}
else {
if (!strcmp(nexttok, "{")) {
char *in_line_net = (char *)MALLOC(1);
char *new_in_line_net = NULL;
*in_line_net = '\0';
/* In-line array---read to "}" */
char *wire_bundle = (char *)MALLOC(1);
char *new_wire_bundle = NULL;
*wire_bundle = '\0';
/* Wire bundle---read to "}" */
while (nexttok) {
new_in_line_net = (char *)MALLOC(strlen(in_line_net) +
new_wire_bundle = (char *)MALLOC(strlen(wire_bundle) +
strlen(nexttok) + 1);
/* Roundabout way to do realloc() becase there is no REALLOC() */
strcpy(new_in_line_net, in_line_net);
strcat(new_in_line_net, nexttok);
FREE(in_line_net);
in_line_net = new_in_line_net;
strcpy(new_wire_bundle, wire_bundle);
strcat(new_wire_bundle, nexttok);
FREE(wire_bundle);
wire_bundle = new_wire_bundle;
if (!strcmp(nexttok, "}")) break;
SkipTokComments(VLOG_PIN_CHECK_DELIMITERS);
}
if (!nexttok) {
Printf("Unterminated net in pin %s\n", in_line_net);
Printf("Unterminated net in pin %s\n", wire_bundle);
}
new_port->net = in_line_net;
new_port->net = wire_bundle;
}
else
new_port->net = strsave(nexttok);
@@ -1558,19 +1671,40 @@ nextinst:
// Check if net name is a wire bus or portion of a bus
if (GetBus(scan->net, &wb) == 0) {
int range;
// This takes care of three situations:
// (1) The signal bus length matches the number of instances:
// apply one signal per instance.
// (2) The signal bus length is a multiple of the number of instances:
// apply a signal sub-bus to each instance.
// (3) The number of instances is a multiple of the signal bus length:
// apply the same signal to each instance.
if ((arrayend - arraystart) == (wb.end - wb.start)) {
// Net is a bus, but net is split over arrayed instances
Port(scan->name);
}
else if (wb.start > wb.end) {
range = wb.start - wb.end;
if ((arraystart - arrayend) > (wb.start - wb.end))
range = (((arraystart - arrayend) + 1) /
((wb.start - wb.end) + 1)) - 1;
else
range = (((wb.start - wb.end) + 1) /
((arraystart - arrayend) + 1)) - 1;
for (i = range; i >= 0; i--) {
sprintf(defport, "%s[%d]", scan->name, i);
Port(defport);
}
}
else {
range = wb.end - wb.start;
if ((arrayend - arraystart) > (wb.end - wb.start))
range = (((arrayend - arraystart) + 1) /
((wb.end - wb.start) + 1)) - 1;
else
range = (((wb.end - wb.start) + 1) /
((arrayend - arraystart) + 1)) - 1;
for (i = 0; i <= range; i++) {
sprintf(defport, "%s[%d]", scan->name, i);
Port(defport);
@@ -1622,7 +1756,12 @@ nextinst:
int j, result;
struct objlist *bobj;
char *bptr;
int minnet, maxnet, testidx;
int minnet, maxnet, testidx, width;
width = portstart - portend;
if (width < 0) width = -width;
width++;
scan->width = width;
result = GetBus(scan->net, &wb);
if (result == -1) {
@@ -1636,7 +1775,7 @@ nextinst:
for (bobj = CurrentCell->cell; bobj; bobj = bobj->next) {
if (bobj->type == PORT) {
if ((bptr = strchr(bobj->name, '[')) != NULL) {
if ((bptr = strvchr(bobj->name, '[')) != NULL) {
*bptr = '\0';
if (!strcmp(bobj->name, scan->net)) {
*bptr = '[';
@@ -1648,7 +1787,7 @@ nextinst:
}
}
else if (bobj->type == NODE) {
if ((bptr = strchr(bobj->name, '[')) != NULL) {
if ((bptr = strvchr(bobj->name, '[')) != NULL) {
*bptr = '\0';
if (!strcmp(bobj->name, scan->net)) {
if (sscanf(bptr + 1, "%d", &testidx) == 1) {
@@ -1674,17 +1813,31 @@ nextinst:
}
if (result == 0) {
if (((wb.start - wb.end) != (portstart - portend)) &&
((wb.start - wb.end) != (portend - portstart))) {
if (((wb.start - wb.end) != (arraystart - arrayend)) &&
((wb.start - wb.end) != (arrayend - arraystart))) {
Fprintf(stderr, "Error: Net %s bus width does not match "
"port %s bus width.\n", scan->net, scan->name);
}
// Otherwise, net is bit-sliced across array of instances.
int match = 0;
int wblen, arraylen;
arraylen = arraystart - arrayend;
wblen = wb.start - wb.end;
if (arraylen < 0) arraylen = -arraylen;
if (wblen < 0) wblen = -wblen;
arraylen++;
wblen++;
if ((scan->width * arraylen) == wblen) match = 1;
else if (wblen == scan->width) match = 1;
else if (wblen == arraylen) match = 1;
else {
Fprintf(stderr, "Warning: Net %s bus width (%d) does not match "
"port %s bus width (%d) or array width (%d).\n",
scan->net, wblen, scan->name, scan->width, arraylen);
}
else if (wb.start > wb.end) {
char *bptr, *cptr, cchar, *netname;
// Net is bit-sliced across array of instances.
if (wb.start > wb.end) {
char *bptr = NULL, *cptr = NULL, cchar, *netname;
unsigned char is_bundle = 0;
struct bus wbb;
@@ -1695,8 +1848,8 @@ nextinst:
if (*netname == '{') {
is_bundle = 1;
netname++;
cptr = strchr(netname, ',');
if (cptr == NULL) cptr = strchr(netname, '}');
cptr = strvchr(netname, ',');
if (cptr == NULL) cptr = strvchr(netname, '}');
if (cptr == NULL) cptr = netname + strlen(netname) - 1;
cchar = *cptr;
*cptr = '\0';
@@ -1705,14 +1858,12 @@ nextinst:
// Remove indexed part of scan->net
if (GetBus(netname, &wbb) == 0) {
i = wbb.start;
if ((bptr = strchr(netname, '[')) != NULL)
if ((bptr = strvchr(netname, '[')) != NULL)
*bptr = '\0';
}
else
i = -1;
if (is_bundle) *cptr = cchar; /* Restore bundle delimiter */
while (1) {
new_port = (struct portelement *)CALLOC(1,
sizeof(struct portelement));
@@ -1723,6 +1874,7 @@ nextinst:
else
sprintf(vname, "%s[%d]", netname, i);
new_port->net = strsave(vname);
new_port->width = scan->width;
if (last == NULL)
head = new_port;
@@ -1736,34 +1888,36 @@ nextinst:
if (portstart > portend) j--;
else j++;
if (wbb.start > wbb.end) i--;
else i++;
if (i != -1) {
if (wbb.start > wbb.end) i--;
else i++;
}
if (is_bundle &&
((i == -1) ||
((wbb.start > wbb.end) && (i < wbb.end)) ||
((wbb.start < wbb.end) && (i > wbb.end)))) {
((wbb.start <= wbb.end) && (i > wbb.end)))) {
if (bptr) *bptr = '[';
netname = cptr + 1;
cptr = strchr(netname, ',');
if (cptr == NULL) cptr = strchr(netname, '}');
if (cptr) *cptr = cchar; /* Restore previous bundle delimiter */
cptr = strvchr(netname, ',');
if (cptr == NULL) cptr = strvchr(netname, '}');
if (cptr == NULL) cptr = netname + strlen(netname) - 1;
cchar = *cptr;
*cptr = '\0';
if (GetBus(netname, &wbb) == 0) {
i = wbb.start;
if ((bptr = strchr(netname, '[')) != NULL)
if ((bptr = strvchr(netname, '[')) != NULL)
*bptr = '\0';
}
else i = -1;
*cptr = cchar; /* Restore delimiter */
}
}
FREE(scan);
scan = last;
if (cptr) *cptr = cchar; /* Restore bundle delimiter */
}
}
else if (portstart != portend) {
@@ -1793,7 +1947,7 @@ nextinst:
obptr = LookupInstance(locinst, CurrentCell);
if (obptr != NULL) {
do {
struct bus wb;
struct bus wb, wb2;
char *obpinname;
int obpinidx;
@@ -1815,14 +1969,21 @@ nextinst:
scan = scan->next;
}
if (scan == NULL) {
Fprintf(stderr, "Error: No match in call for pin %s\n", obpinname);
break;
}
char localnet[100];
if (GetBus(scan->net, &wb) == 0) {
/* Assume an implicit unconnected pin */
sprintf(localnet, "_noconnect_%d_", localcount++);
Node(localnet);
join(localnet, obptr->name);
Fprintf(stderr,
"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);
brackptr = strchr(scanroot, '[');
brackptr = strvchr(scanroot, '[');
if (brackptr) *brackptr = '\0';
if (arraystart == -1) {
@@ -1854,16 +2015,37 @@ nextinst:
else {
// Instance must be an array
char netname[128];
int slice;
if (wb.start >= wb.end && arraystart >= arrayend)
slice = wb.start - (arraystart - i);
else if (wb.start < wb.end && arraystart > arrayend)
slice = wb.start + (arraystart - i);
else if (wb.start > wb.end && arraystart < arrayend)
slice = wb.start - (arraystart + i);
else // (wb.start < wb.end && arraystart < arrayend)
slice = wb.start + (arraystart + i);
int slice, portlen, siglen;
/* Get the array size of the port for bit slicing */
portlen = (scan->width < 0) ? 1 : scan->width;
/* Get the full array size of the connecting bus */
GetBus(scanroot, &wb2);
siglen = wb2.start - wb2.end;
if (siglen < 0) siglen = -siglen;
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;
}
sprintf(netname, "%s[%d]", scanroot, slice);
if (LookupObject(netname, CurrentCell) == NULL) Node(netname);
join(netname, obptr->name);
@@ -1931,14 +2113,21 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
CurrentCell = NULL;
if ((filenum = OpenParseFile(fname, *fnum)) < 0) {
char name[100];
SetExtension(name, fname, VERILOG_EXTENSION);
if ((filenum = OpenParseFile(name, *fnum)) < 0) {
Fprintf(stderr,"Error in Verilog file read: No file %s\n",name);
*fnum = filenum;
return NULL;
if (strchr(fname, '.') == NULL) {
char name[1024];
SetExtension(name, fname, VERILOG_EXTENSION);
if ((filenum = OpenParseFile(name, *fnum)) < 0) {
Fprintf(stderr, "Error in Verilog file read: No file %s\n", name);
*fnum = filenum;
return NULL;
}
}
else {
Fprintf(stderr, "Error in Verilog file read: No file %s\n", fname);
*fnum = filenum;
return NULL;
}
}
/* All Verilog file reading is case sensitive. However: if */
@@ -1949,6 +2138,11 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox)
Printf("Warning: A case-insensitive file has been read and so the "
"verilog file must be treated case-insensitive to match.\n");
}
else {
matchfunc = match;
matchintfunc = matchfile;
hashfunc = hash;
}
InitializeHashTable(&verilogparams, OBJHASHSIZE);
InitializeHashTable(&verilogdefs, OBJHASHSIZE);
@@ -2036,11 +2230,15 @@ void IncludeVerilog(char *fname, int parent, struct cellstack **CellStackPtr,
if (strchr(fname, '.') == NULL) {
SetExtension(name, fname, VERILOG_EXTENSION);
filenum = OpenParseFile(name, parent);
if (filenum < 0) {
fprintf(stderr,"Error in Verilog file include: No file %s\n", name);
return;
}
}
if (filenum < 0) {
else {
fprintf(stderr,"Error in Verilog file include: No file %s\n", fname);
return;
}
}
}
}
ReadVerilogFile(fname, parent, CellStackPtr, blackbox);
Vendored
+3 -1
View File
@@ -4,4 +4,6 @@
# all of its config scripts in a different directory than the configure
# script itself.
( CFLAGS="-g" ; export CFLAGS ; cd scripts ; ./configure "$@" )
export CFLAGS="$CFLAGS -g"
cd scripts
exec ./configure "$@"
+1 -1
View File
@@ -25,7 +25,7 @@ install-tcl: netgenexec${EXEEXT} $(DESTDIR)${INSTALL_BINDIR}/netgen.sh ${TCL_FIL
netgenexec${EXEEXT}: netgenexec.c
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS_NOSTUB} netgenexec.c \
-o netgenexec${EXEEXT} \
${LDFLAGS} ${LIBS} ${LIB_SPECS_NOSTUB}
${LIB_SPECS_NOSTUB} ${LDFLAGS} ${LIBS} ${GR_LIBS}
netgen.tcl: netgen.tcl.in
sed -e 's%TCL_DIR%${TCLDIR}%g' \
+96 -12
View File
@@ -352,7 +352,7 @@ proc netgen::convert_to_json {filename lvs_final} {
close $fjson
}
#----------------------------------------------------------------
#-----------------------------------------------------------------------
# Define the "lvs" command as a way of calling the netgen options
# for standard compare, essentially the same as the old "netcomp"
# standalone program.
@@ -361,14 +361,20 @@ proc netgen::convert_to_json {filename lvs_final} {
# although if the cells have not been read in yet, then the
# original syntax of filename or {filename cellname} is required.
#
# "args" is passed to verify and may therefore contain only the
# value "-list" or nothing. If "-list", then output is returned
# as a nested list.
#----------------------------------------------------------------
# "args" may be "-list", "-json", or "-blackbox".
# "-list" returns output as a nested list.
# "-json" creates a .json-format output file in addition to stdout.
# "-blackbox" treats empty cells as black-box entries.
# "-noflatten={list}" is a list of cells not to flatten if mismatched.
# i.e., the cells are expected to match and any mismatch cannot be
# expected to be resolved by flattening the contents of the mismatched
# cells.
#-----------------------------------------------------------------------
proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
set dolist 0
set dojson 0
set noflat {}
foreach arg $args {
if {$arg == "-list"} {
puts stdout "Generating list result"
@@ -382,6 +388,30 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
} elseif {$arg == "-blackbox"} {
puts stdout "Treating empty subcircuits as black-box cells"
netgen::model blackbox on
} elseif {[string first "-noflatten=" $arg] == 0} {
set value [string range $arg 11 end]
# If argument is a filename then read the list of cells from it;
# otherwise, argument is the list of files itself in quotes or
# braces.
if {![catch {file exists $value}]} {
if {![catch {open $value r} fnf]} {
while {[gets $fnf line] >= 0} {
if {[lindex $line 0] != "#"} {
foreach cell $line {
lappend noflat $cell
}
}
}
close $fnf
} else {
puts stderr "Cannot open file $value for reading cell list."
}
} else {
set noflat [string trim $value \"\{\}]
}
if {[llength $noflat] > 0} {
puts stdout "Will not flatten these subcells: $noflat"
}
}
}
@@ -501,6 +531,8 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
return
}
set properr {}
set matcherr {}
set pinsgood 0
while {$endval != {}} {
if {$dolist == 1} {
netgen::run -list converge
@@ -528,9 +560,30 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
# Flatten the non-matching subcircuit (but not the top-level cells)
if {[netgen::print queue] != {}} {
netgen::log put " Flattening non-matched subcircuits $endval"
netgen::flatten class "[lindex $endval 0] $fnum1"
netgen::flatten class "[lindex $endval 1] $fnum2"
if {([lsearch $noflat [lindex $endval 0]] == -1) &&
([lsearch $noflat [lindex $endval 1]] == -1)} {
netgen::log put " Flattening non-matched subcircuits $endval"
netgen::flatten class "[lindex $endval 0] $fnum1"
netgen::flatten class "[lindex $endval 1] $fnum2"
} else {
netgen::log put " Continuing with black-boxed subcircuits $endval"
lappend matcherr [lindex $endval 0]
# Match pins
netgen::log echo off
if {$dolist == 1} {
set result [equate -list -force pins "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"]
} else {
set result [equate -force pins "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"]
}
if {$result != 0} {
equate classes "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"
}
set pinsgood $result
netgen::log echo on
}
}
} else {
# Match pins
@@ -546,15 +599,39 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
equate classes "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"
}
set pinsgood $result
netgen::log echo on
}
if {$uresult == 2} {lappend properr [lindex $endval 0]}
} else {
# Flatten the non-matching subcircuit (but not the top-level cells)
if {[netgen::print queue] != {}} {
netgen::log put " Flattening non-matched subcircuits $endval"
netgen::flatten class "[lindex $endval 0] $fnum1"
netgen::flatten class "[lindex $endval 1] $fnum2"
if {([lsearch $noflat [lindex $endval 1]] == -1) &&
([lsearch $noflat [lindex $endval 1]] == -1)} {
netgen::log put " Flattening non-matched subcircuits $endval"
netgen::flatten class "[lindex $endval 0] $fnum1"
netgen::flatten class "[lindex $endval 1] $fnum2"
} else {
netgen::log put " Continuing with black-boxed subcircuits $endval"
lappend matcherr [lindex $endval 0]
netgen::log put " Continuing with black-boxed subcircuits $endval"
lappend matcherr [lindex $endval 0]
# Match pins
netgen::log echo off
if {$dolist == 1} {
set result [equate -list -force pins "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"]
} else {
set result [equate -force pins "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"]
}
if {$result != 0} {
equate classes "$fnum1 [lindex $endval 0]" \
"$fnum2 [lindex $endval 1]"
}
set pinsgood $result
netgen::log echo on
}
}
}
netgen::log echo off
@@ -569,10 +646,17 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
netgen::log echo off
puts stdout "Result: " nonewline
netgen::log echo on
verify only
if {$pinsgood == 0} {
netgen::log put "The top level cell failed pin matching.\n"
} else {
verify only
}
if {$properr != {}} {
netgen::log put "The following cells had property errors: $properr\n"
}
if {$matcherr != {}} {
netgen::log put "The following subcells failed to match: $matcherr\n"
}
if {$dolog} {
netgen::log end
}
+179 -19
View File
@@ -85,6 +85,7 @@ 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[]);
@@ -93,6 +94,7 @@ 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[]);
@@ -199,6 +201,9 @@ Command netcmp_cmds[] = {
{"print", _netcmp_print,
"\n "
"print netcomp internal data structure"},
{"format", _netcmp_format,
"<col1_width> <col2_width>\n "
"set width of formatted output"},
{"run", _netcmp_run,
"[converge|resolve]\n "
"converge: run netcomp to completion (convergence)\n "
@@ -240,6 +245,8 @@ Command netcmp_cmds[] = {
{"exhaustive", _netcmp_exhaustive,
"\n "
"toggle exhaustive subdivision"},
{"symmetry", _netcmp_symmetry,
"(deprecated)"},
{"restart", _netcmp_restart,
"\n "
"start over (reset data structures)"},
@@ -1528,23 +1535,24 @@ int
_netgen_model(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
struct nlist *tp;
struct nlist *tp, *tp2;
char *model, *retclass;
unsigned char class;
int fnum = -1;
int result, index, nports;
int result, index, nports, nports2;
char *modelclasses[] = {
"undefined", "nmos", "pmos", "pnp", "npn",
"resistor", "capacitor", "diode",
"inductor", "module", "blackbox", "xline",
"moscap", "mosfet", "bjt", "subcircuit", NULL
"moscap", "mosfet", "bjt", "subcircuit", "copy",
NULL
};
enum OptionIdx {
UNDEF_IDX, NMOS_IDX, PMOS_IDX, PNP_IDX, NPN_IDX,
RES_IDX, CAP_IDX, DIODE_IDX, INDUCT_IDX,
MODULE_IDX, BLACKBOX_IDX, XLINE_IDX, MOSCAP_IDX,
MOSFET_IDX, BJT_IDX, SUBCKT_IDX
MOSFET_IDX, BJT_IDX, SUBCKT_IDX, COPY_IDX
};
if (objc != 3 && objc != 2) {
@@ -1576,7 +1584,7 @@ _netgen_model(ClientData clientData,
if (objc == 3) {
model = Tcl_GetString(objv[2]);
nports = NumberOfPorts(model);
nports = NumberOfPorts(model, fnum);
if (Tcl_GetIndexFromObj(interp, objv[2], (CONST84 char **)modelclasses,
"class", 0, &index) != TCL_OK) {
@@ -1640,6 +1648,40 @@ _netgen_model(ClientData clientData,
break;
case SUBCKT_IDX:
class = CLASS_SUBCKT;
break;
case COPY_IDX:
/* "copy" is not a class, but indicates that the cell, */
/* if undefined or a module, should have its class */
/* taken from the other circuit, if that circuit has a */
/* cell of the same name. */
if (Circuit1 == NULL || Circuit2 == NULL) {
Tcl_SetResult(interp, "Circuits have not been queued for comparison.",
NULL);
return TCL_ERROR;
}
if (tp == Circuit1) {
tp2 = LookupCellFile(tp->name, Circuit2->file);
nports2 = NumberOfPorts(tp2->name, Circuit2->file);
}
else if (tp == Circuit2) {
tp2 = LookupCellFile(tp->name, Circuit1->file);
nports2 = NumberOfPorts(tp2->name, Circuit1->file);
}
else {
Tcl_SetResult(interp, "The referenced netlist is not being compared.",
NULL);
return TCL_ERROR;
}
/* Should a non-matching number of ports be considered a fatal error? */
// if (nports2 != nports) {
// Tcl_SetResult(interp, "The number of ports for this cell does not "
// "match between netlists.", NULL);
// return TCL_ERROR;
// }
class = tp2->class;
/* To do (maybe): Rename tp ports to match tp2? */
break;
}
tp->class = class;
@@ -1971,6 +2013,61 @@ _netgen_printmem(ClientData clientData,
}
#endif
/*------------------------------------------------------*/
/* Function name: _netcmp_format */
/* Syntax: */
/* netgen::format [col1_width [col2_width]] */
/* Formerly: (none) */
/* Results: */
/* Side Effects: */
/*------------------------------------------------------*/
int
_netcmp_format(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
int col1_width = 41, col2_width = 41;
if (objc > 1) {
if (Tcl_GetIntFromObj(interp, objv[1], &col1_width) != TCL_OK)
return TCL_ERROR;
if (objc > 2) {
if (Tcl_GetIntFromObj(interp, objv[2], &col2_width) != TCL_OK)
return TCL_ERROR;
} else {
/* If only one argument is given, then apply it to both columns */
col2_width = col1_width;
}
if (col1_width <= 0 || col2_width <= 0) {
Tcl_SetResult(interp, "Column width cannot be zero or less\n", NULL);
}
// Default values for left and right columns are 43 and 87
left_col_end = col1_width + 2;
right_col_end = left_col_end + col2_width + 3;
}
else if (objc == 1) {
Tcl_Obj *lobj, *tobj;
col1_width = left_col_end - 2;
col2_width = right_col_end - col1_width - 5;
lobj = Tcl_NewListObj(0, NULL);
tobj = Tcl_NewIntObj(col1_width);
Tcl_ListObjAppendElement(interp, lobj, Tcl_NewIntObj(col1_width));
Tcl_ListObjAppendElement(interp, lobj, Tcl_NewIntObj(col2_width));
Tcl_SetObjResult(interp, lobj);
return TCL_OK;
}
else {
Tcl_WrongNumArgs(interp, 1, objv, "[col1_width [col2_width]]");
return TCL_ERROR;
}
}
/*------------------------------------------------------*/
/* The following code breaks up the NETCOMP() command */
/* from netcmp.c into individual functions w/arguments */
@@ -2730,11 +2827,13 @@ _netcmp_equate(ClientData clientData,
char *name1 = NULL, *name2 = NULL, *optstart;
struct nlist *tp1, *tp2, *SaveC1, *SaveC2;
struct objlist *ob1, *ob2;
struct ElementClass *saveEclass = NULL;
struct NodeClass *saveNclass = NULL;
int file1, file2;
int i, l1, l2, ltest, lent, dolist = 0;
int i, l1, l2, ltest, lent, dolist = 0, doforce = 0;
Tcl_Obj *tobj1, *tobj2, *tobj3;
if (objc > 1) {
while (objc > 1) {
optstart = Tcl_GetString(objv[1]);
if (*optstart == '-') optstart++;
if (!strcmp(optstart, "list")) {
@@ -2742,6 +2841,13 @@ _netcmp_equate(ClientData clientData,
objv++;
objc--;
}
else if (!strcmp(optstart, "force")) {
doforce = 1;
objv++;
objc--;
}
else
break;
}
if ((objc != 2) && (objc != 4) && (objc != 6)) {
@@ -2899,16 +3005,41 @@ _netcmp_equate(ClientData clientData,
break;
case PINS_IDX:
if ((ElementClasses == NULL) && (auto_blackbox == FALSE)) {
if (CurrentCell == NULL)
Fprintf(stderr, "Equate elements: no current cell.\n");
Fprintf(stderr, "Equate pins: cell %s and/or %s has no elements.\n",
name1, name2);
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
return TCL_OK;
if ((ElementClasses != NULL) && (doforce == TRUE)) {
saveEclass = ElementClasses;
saveNclass = NodeClasses;
ElementClasses = NULL;
NodeClasses = NULL;
}
else if (ElementClasses == NULL) {
/* This has been called outside of a netlist compare, */
if ((ElementClasses == NULL) && (auto_blackbox == FALSE)) {
if (CurrentCell == NULL) {
Fprintf(stderr, "Equate elements: no current cell.\n");
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
return TCL_OK;
}
else if ((tp1->flags & CELL_PLACEHOLDER) ||
(tp2->flags & CELL_PLACEHOLDER)) {
if (tp1->flags & CELL_PLACEHOLDER) {
Fprintf(stdout, "Warning: Equate pins: cell %s "
"has no definition, treated as a black box.\n", name1);
}
if (tp2->flags & CELL_PLACEHOLDER) {
Fprintf(stdout, "Warning: Equate pins: cell %s "
"has no definition, treated as a black box.\n", name2);
}
// If a cell in either circuit is marked as a black box, then
// the cells in both circuits should be marked as a black box.
tp1->flags |= CELL_PLACEHOLDER;
tp2->flags |= CELL_PLACEHOLDER;
}
else {
Fprintf(stdout, "Equate pins: cell %s and/or %s "
"has no elements.\n", name1, name2);
/* This is not necessarily an error, so go ahead and match pins. */
}
}
if (ElementClasses == NULL) {
/* This may have been called outside of a netlist compare, */
/* probably to force name matching of pins on black-box */
/* devices. But MatchPins only works if tp1 == Circuit1 */
/* and tp2 == Circuit2, so preserve these values and */
@@ -2942,6 +3073,12 @@ _netcmp_equate(ClientData clientData,
/* Recover temporarily set global variables (see above) */
Circuit1 = SaveC1;
Circuit2 = SaveC2;
/* Recover ElementClasses if forcing pins on mismatched circuits */
if (doforce == TRUE) {
ElementClasses = saveEclass;
NodeClasses = saveNclass;
}
}
break;
@@ -3301,9 +3438,15 @@ _netcmp_property(ClientData clientData,
GlobalParallelNone = FALSE;
SetParallelCombine(TRUE);
}
else if (!strcmp(Tcl_GetString(objv[2]), "connected")) {
GlobalParallelOpen = FALSE;
}
else if (!strcmp(Tcl_GetString(objv[2]), "open")) {
GlobalParallelOpen = TRUE;
}
else {
Tcl_SetResult(interp, "Bad option, should be property parallel none|all",
NULL);
Tcl_SetResult(interp, "Bad option, should be property parallel "
"none|all|connected", NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -3859,6 +4002,23 @@ _netcmp_permute(ClientData clientData,
return TCL_OK;
}
/*------------------------------------------------------*/
/* Function name: _netcmp_symmetry */
/* Syntax: netgen::symmetry [fast|full] */
/* Formerly: x */
/* Results: */
/* Side Effects: */
/* Notes: Deprecated, retained for compatibility. */
/*------------------------------------------------------*/
int
_netcmp_symmetry(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
Printf("Symmetry breaking method has been deprecated.\n");
return TCL_OK;
}
/*------------------------------------------------------*/
/* Function name: _netcmp_exhaustive */
/* Syntax: netgen::exhaustive [on|off] */
@@ -3880,7 +4040,7 @@ _netcmp_exhaustive(ClientData clientData,
int result, index;
if (objc == 1)
index = YES_IDX;
index = -1;
else {
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
"option", 0, &index) != TCL_OK)